Merge pull request #11 from Mualamx/Beta
✨ 添加数据库字段(是否为点券作物,点券作物单价);实现点券购买种子;我的种子查询页面添加点券单价。
This commit is contained in:
commit
ac495ad6e9
@ -58,6 +58,12 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
help="金币兑换农场币的倍数 默认值为: 2倍",
|
help="金币兑换农场币的倍数 默认值为: 2倍",
|
||||||
default_value="2",
|
default_value="2",
|
||||||
),
|
),
|
||||||
|
RegisterConfig(
|
||||||
|
key="点券兑换倍数",
|
||||||
|
value="2000",
|
||||||
|
help="农场币兑换点券的倍数 比例为2000:1",
|
||||||
|
default_value="2000",
|
||||||
|
),
|
||||||
RegisterConfig(
|
RegisterConfig(
|
||||||
key="手续费",
|
key="手续费",
|
||||||
value="0.2",
|
value="0.2",
|
||||||
|
|||||||
129
command.py
129
command.py
@ -85,6 +85,8 @@ diuse_farm = on_alconna(
|
|||||||
Subcommand("harvest", help_text="收获"),
|
Subcommand("harvest", help_text="收获"),
|
||||||
Subcommand("eradicate", help_text="铲除"),
|
Subcommand("eradicate", help_text="铲除"),
|
||||||
Subcommand("my-plant", help_text="我的作物"),
|
Subcommand("my-plant", help_text="我的作物"),
|
||||||
|
Subcommand("lock-plant", Args["name?", str], help_text="作物加锁"),
|
||||||
|
Subcommand("unlock-plant", Args["name?", str], help_text="作物解锁"),
|
||||||
Subcommand("sell-plant", Args["name?", str]["num?", int], help_text="出售作物"),
|
Subcommand("sell-plant", Args["name?", str]["num?", int], help_text="出售作物"),
|
||||||
Subcommand("stealing", Args["target?", At], help_text="偷菜"),
|
Subcommand("stealing", Args["target?", At], help_text="偷菜"),
|
||||||
Subcommand("buy-point", Args["num?", int], help_text="购买农场币"),
|
Subcommand("buy-point", Args["num?", int], help_text="购买农场币"),
|
||||||
@ -92,6 +94,8 @@ diuse_farm = on_alconna(
|
|||||||
Subcommand("change-name", Args["name?", str], help_text="更改农场名"),
|
Subcommand("change-name", Args["name?", str], help_text="更改农场名"),
|
||||||
Subcommand("sign-in", help_text="农场签到"),
|
Subcommand("sign-in", help_text="农场签到"),
|
||||||
Subcommand("admin-up", Args["num?", int], help_text="农场下阶段"),
|
Subcommand("admin-up", Args["num?", int], help_text="农场下阶段"),
|
||||||
|
Subcommand("point-to-vipPoint", Args["num?", int], help_text="点券兑换"),
|
||||||
|
Subcommand("my-vipPoint", help_text="我的点券"),
|
||||||
),
|
),
|
||||||
priority=5,
|
priority=5,
|
||||||
block=True,
|
block=True,
|
||||||
@ -328,6 +332,65 @@ async def _(session: Uninfo):
|
|||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
|
diuse_farm.shortcut(
|
||||||
|
"作物加锁(?P<name>)",
|
||||||
|
command="我的农场",
|
||||||
|
arguments=["lock-plant", "{name}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@diuse_farm.assign("lock-plant")
|
||||||
|
async def _(session: Uninfo, name: Match[str]):
|
||||||
|
uid = str(session.user.id)
|
||||||
|
|
||||||
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
|
return
|
||||||
|
|
||||||
|
result = await g_pFarmManager.lockUserPlantByUid(uid, name.result, 1)
|
||||||
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
|
diuse_farm.shortcut(
|
||||||
|
"作物解锁(?P<name>)",
|
||||||
|
command="我的农场",
|
||||||
|
arguments=["unlock-plant", "{name}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@diuse_farm.assign("unlock-plant")
|
||||||
|
async def _(session: Uninfo, name: Match[str]):
|
||||||
|
uid = str(session.user.id)
|
||||||
|
|
||||||
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
|
return
|
||||||
|
|
||||||
|
result = await g_pFarmManager.lockUserPlantByUid(uid, name.result, 0)
|
||||||
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
|
diuse_farm.shortcut(
|
||||||
|
"出售作物(?P<name>.*?)",
|
||||||
|
command="我的农场",
|
||||||
|
arguments=["sell-plant", "{name}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@diuse_farm.assign("sell-plant")
|
||||||
|
async def _(
|
||||||
|
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)
|
||||||
|
):
|
||||||
|
uid = str(session.user.id)
|
||||||
|
|
||||||
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
|
return
|
||||||
|
|
||||||
|
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
|
||||||
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
reclamation = on_alconna(
|
reclamation = on_alconna(
|
||||||
Alconna("开垦"),
|
Alconna("开垦"),
|
||||||
priority=5,
|
priority=5,
|
||||||
@ -364,27 +427,6 @@ async def _(session: Uninfo):
|
|||||||
await MessageUtils.build_message(res).send(reply_to=True)
|
await MessageUtils.build_message(res).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
|
||||||
"出售作物(?P<name>.*?)",
|
|
||||||
command="我的农场",
|
|
||||||
arguments=["sell-plant", "{name}"],
|
|
||||||
prefix=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("sell-plant")
|
|
||||||
async def _(
|
|
||||||
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)
|
|
||||||
):
|
|
||||||
uid = str(session.user.id)
|
|
||||||
|
|
||||||
if not await g_pToolManager.isRegisteredByUid(uid):
|
|
||||||
return
|
|
||||||
|
|
||||||
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
|
|
||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"偷菜",
|
"偷菜",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -606,3 +648,48 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
|||||||
return
|
return
|
||||||
|
|
||||||
await g_pDBService.userSoil.nextPhase(uid, num.result)
|
await g_pDBService.userSoil.nextPhase(uid, num.result)
|
||||||
|
|
||||||
|
|
||||||
|
diuse_farm.shortcut(
|
||||||
|
"点券兑换(.*?)",
|
||||||
|
command="我的农场",
|
||||||
|
arguments=["point-to-vipPoint"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@diuse_farm.assign("point-to-vipPoint")
|
||||||
|
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
||||||
|
if num.result <= 0:
|
||||||
|
await MessageUtils.build_message("请在指令后跟需要购买点券的数量").finish(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
|
|
||||||
|
uid = str(session.user.id)
|
||||||
|
|
||||||
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
|
return
|
||||||
|
|
||||||
|
result = await g_pFarmManager.pointToVipPointByUid(uid, num.result)
|
||||||
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
|
diuse_farm.shortcut(
|
||||||
|
"我的点券",
|
||||||
|
command="我的农场",
|
||||||
|
arguments=["my-vipPoint"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@diuse_farm.assign("my-vipPoint")
|
||||||
|
async def _(session: Uninfo):
|
||||||
|
uid = str(session.user.id)
|
||||||
|
vipPoint = await g_pDBService.user.getUserVipPointByUid(uid)
|
||||||
|
|
||||||
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
|
return
|
||||||
|
|
||||||
|
await MessageUtils.build_message(
|
||||||
|
g_sTranslation["basic"]["vipPoint"].format(vipPoint=vipPoint)
|
||||||
|
).send(reply_to=True)
|
||||||
|
|||||||
@ -34,6 +34,7 @@ g_sTranslation = {
|
|||||||
"basic": {
|
"basic": {
|
||||||
"notFarm": "尚未开通农场,快at我发送 开通农场 开通吧 🌱🚜",
|
"notFarm": "尚未开通农场,快at我发送 开通农场 开通吧 🌱🚜",
|
||||||
"point": "你的当前农场币为: {point} 🌾💰",
|
"point": "你的当前农场币为: {point} 🌾💰",
|
||||||
|
"vipPoint": "你的当前点券为: {vipPoint} 🌾💰",
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"success": "✅ 农场开通成功!\n💼 初始资金:{point}农场币 🥳🎉",
|
"success": "✅ 农场开通成功!\n💼 初始资金:{point}农场币 🥳🎉",
|
||||||
@ -45,7 +46,9 @@ g_sTranslation = {
|
|||||||
"notNum": "❗️ 请输入购买数量!",
|
"notNum": "❗️ 请输入购买数量!",
|
||||||
"noLevel": "🔒 你的等级不够哦,努努力吧 💪",
|
"noLevel": "🔒 你的等级不够哦,努努力吧 💪",
|
||||||
"noPoint": "💰 你的农场币不够哦~ 快速速氪金吧!💸",
|
"noPoint": "💰 你的农场币不够哦~ 快速速氪金吧!💸",
|
||||||
|
"noVipPoint": "💰 你的点券不够哦~ 快速速氪金吧!💸",
|
||||||
"success": "✅ 成功购买{name},花费{total}农场币,剩余{point}农场币 🌾",
|
"success": "✅ 成功购买{name},花费{total}农场币,剩余{point}农场币 🌾",
|
||||||
|
"vipSuccess": "✅ 成功购买{name},花费{total}点券,剩余{point}点券 🌾",
|
||||||
"errorSql": "❌ 购买失败,执行数据库错误!🛑",
|
"errorSql": "❌ 购买失败,执行数据库错误!🛑",
|
||||||
"error": "❌ 购买出错!请检查需购买的种子名称!🔍",
|
"error": "❌ 购买出错!请检查需购买的种子名称!🔍",
|
||||||
},
|
},
|
||||||
@ -121,4 +124,10 @@ g_sTranslation = {
|
|||||||
"aquamarine": "增产+32% 经验+32% 时间-28% 幸运+1%",
|
"aquamarine": "增产+32% 经验+32% 时间-28% 幸运+1%",
|
||||||
"blackcrystal": "增产+32% 经验+40% 时间-28% 幸运+2%",
|
"blackcrystal": "增产+32% 经验+40% 时间-28% 幸运+2%",
|
||||||
},
|
},
|
||||||
|
"lockPlant": {
|
||||||
|
"noPlant": "很抱歉,你的作物仓库中没有该作物",
|
||||||
|
"lockPlant": "加锁成功,现在{name}不会被一键售卖了",
|
||||||
|
"unlockPlant": "解锁成功,现在{name}会被一键售卖了",
|
||||||
|
"error": "未知错误",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ class CUserPlantDB(CSqlManager):
|
|||||||
"uid": "TEXT NOT NULL", # 用户Uid
|
"uid": "TEXT NOT NULL", # 用户Uid
|
||||||
"plant": "TEXT NOT NULL", # 作物名称
|
"plant": "TEXT NOT NULL", # 作物名称
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0", # 数量
|
"count": "INTEGER NOT NULL DEFAULT 0", # 数量
|
||||||
|
"isLock": "INTEGER NOT NULL DEFAULT 0", # 是否上锁 0=没有,非0=有
|
||||||
"PRIMARY KEY": "(uid, plant)",
|
"PRIMARY KEY": "(uid, plant)",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +92,27 @@ class CUserPlantDB(CSqlManager):
|
|||||||
logger.warning("getUserPlantByName 查询失败!", e=e)
|
logger.warning("getUserPlantByName 查询失败!", e=e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def checkUserPlantByName(cls, uid: str, plant: str) -> bool:
|
||||||
|
"""根据作物名称判断用户作物仓库是否存在该作物
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否存在
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT * FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return True if row else False
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("checkUserPlantByName 查询失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def updateUserPlantByName(cls, uid: str, plant: str, count: int) -> bool:
|
async def updateUserPlantByName(cls, uid: str, plant: str, count: int) -> bool:
|
||||||
"""更新 userPlant 表中某个作物的数量
|
"""更新 userPlant 表中某个作物的数量
|
||||||
@ -114,7 +136,51 @@ class CUserPlantDB(CSqlManager):
|
|||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("updateUserPlantByName失败!", e=e)
|
logger.warning("updateUserPlantByName 失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def lockUserPlantByName(cls, uid: str, plant: str, lock: int) -> bool:
|
||||||
|
"""给作物加锁,防止一键售卖
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
lock (int): 0为解锁,非0均为加锁
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否加锁成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userPlant SET isLock = ? WHERE uid = ? AND plant = ?",
|
||||||
|
(lock, uid, plant),
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("lockUserPlantByName 失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def checkPlantLockByName(cls, uid: str, plant: str) -> bool:
|
||||||
|
"""根据作物名称判断是否加锁
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否加锁
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT isLock FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] > 0 if row else False
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("checkUserPlantByName 查询失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@ -165,7 +165,6 @@ class CUserSignDB(CSqlManager):
|
|||||||
if row["currentMonth"] == currentMonth
|
if row["currentMonth"] == currentMonth
|
||||||
else 1
|
else 1
|
||||||
)
|
)
|
||||||
totalSignDays = row["totalSignDays"]
|
|
||||||
lastDate = row["lastSignDate"]
|
lastDate = row["lastSignDate"]
|
||||||
prevDate = (
|
prevDate = (
|
||||||
g_pToolManager.dateTime().strptime(signDate, "%Y-%m-%d")
|
g_pToolManager.dateTime().strptime(signDate, "%Y-%m-%d")
|
||||||
@ -200,7 +199,7 @@ class CUserSignDB(CSqlManager):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
totalSignDays = 1
|
monthSignDays = 1
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO userSignSummary
|
INSERT INTO userSignSummary
|
||||||
@ -211,7 +210,7 @@ class CUserSignDB(CSqlManager):
|
|||||||
uid,
|
uid,
|
||||||
1,
|
1,
|
||||||
currentMonth,
|
currentMonth,
|
||||||
1,
|
monthSignDays,
|
||||||
signDate,
|
signDate,
|
||||||
1,
|
1,
|
||||||
1 if isSupplement else 0,
|
1 if isSupplement else 0,
|
||||||
@ -219,15 +218,13 @@ class CUserSignDB(CSqlManager):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 计算累签奖励
|
# 计算累签奖励
|
||||||
reward = g_pJsonManager.m_pSign["continuou"].get(f"{totalSignDays}", None)
|
reward = g_pJsonManager.m_pSign["continuou"].get(f"{monthSignDays}", None)
|
||||||
|
|
||||||
if reward:
|
if reward:
|
||||||
point += reward.get("point", 0)
|
point += reward.get("point", 0)
|
||||||
exp += reward.get("exp", 0)
|
exp += reward.get("exp", 0)
|
||||||
vipPoint = reward.get("vipPoint", 0)
|
vipPoint = reward.get("vipPoint", 0)
|
||||||
|
|
||||||
plant = reward.get("plant", {})
|
plant = reward.get("plant", {})
|
||||||
|
|
||||||
if plant:
|
if plant:
|
||||||
for key, value in plant.items():
|
for key, value in plant.items():
|
||||||
await g_pDBService.userSeed.addUserSeedByUid(uid, key, value)
|
await g_pDBService.userSeed.addUserSeedByUid(uid, key, value)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class CUserSoilDB(CSqlManager):
|
|||||||
"weedStatus": "INTEGER DEFAULT 0", # 杂草状态 0=无杂草,1=有杂草
|
"weedStatus": "INTEGER DEFAULT 0", # 杂草状态 0=无杂草,1=有杂草
|
||||||
"waterStatus": "INTEGER DEFAULT 0", # 缺水状态 0=不缺水,1=缺水
|
"waterStatus": "INTEGER DEFAULT 0", # 缺水状态 0=不缺水,1=缺水
|
||||||
"harvestCount": "INTEGER DEFAULT 0", # 收获次数
|
"harvestCount": "INTEGER DEFAULT 0", # 收获次数
|
||||||
"isSoilPlanted": "INTEGER DEFAULT NULL", # 是否种植作物
|
"isSoilPlanted": "INTEGER DEFAULT NULL", # 是否种植作物 0=没有,1=有
|
||||||
"PRIMARY KEY": "(uid, soilIndex)",
|
"PRIMARY KEY": "(uid, soilIndex)",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
95
farm/farm.py
95
farm/farm.py
@ -159,6 +159,7 @@ class CFarmManager:
|
|||||||
if image:
|
if image:
|
||||||
avatar = BuildImage(background=image)
|
avatar = BuildImage(background=image)
|
||||||
|
|
||||||
|
await avatar.resize(0, 140, 150)
|
||||||
await img.paste(avatar, (125, 85))
|
await img.paste(avatar, (125, 85))
|
||||||
|
|
||||||
# 头像框
|
# 头像框
|
||||||
@ -732,7 +733,15 @@ class CFarmManager:
|
|||||||
bytes: 返回图片
|
bytes: 返回图片
|
||||||
"""
|
"""
|
||||||
data_list = []
|
data_list = []
|
||||||
column_name = ["-", "作物名称", "数量", "单价", "总价", "是否可以上架交易行"]
|
column_name = [
|
||||||
|
"-",
|
||||||
|
"作物名称",
|
||||||
|
"数量",
|
||||||
|
"单价",
|
||||||
|
"总价",
|
||||||
|
"是否上锁",
|
||||||
|
"是否可以上架交易行",
|
||||||
|
]
|
||||||
|
|
||||||
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
||||||
|
|
||||||
@ -763,7 +772,15 @@ class CFarmManager:
|
|||||||
|
|
||||||
number = int(count) * plantInfo["price"]
|
number = int(count) * plantInfo["price"]
|
||||||
|
|
||||||
data_list.append([icon, name, count, plantInfo["price"], number, sell])
|
isLock = await g_pDBService.userPlant.checkPlantLockByName(uid, name)
|
||||||
|
if isLock:
|
||||||
|
lock = "上锁"
|
||||||
|
else:
|
||||||
|
lock = "未上锁"
|
||||||
|
|
||||||
|
data_list.append(
|
||||||
|
[icon, name, count, plantInfo["price"], number, lock, sell]
|
||||||
|
)
|
||||||
|
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
"作物仓库",
|
"作物仓库",
|
||||||
@ -774,6 +791,31 @@ class CFarmManager:
|
|||||||
|
|
||||||
return result.pic2bytes()
|
return result.pic2bytes()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def lockUserPlantByUid(cls, uid: str, name: str, lock: int) -> str:
|
||||||
|
"""加/解 锁用户作物
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
name (str): 作物名称
|
||||||
|
lock (int): 0=解锁 非0=加锁
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 返回
|
||||||
|
"""
|
||||||
|
# 先判断该用户仓库是否有该作物
|
||||||
|
if not await g_pDBService.userPlant.checkUserPlantByName(uid, name):
|
||||||
|
return g_sTranslation["lockPlant"]["noPlant"]
|
||||||
|
|
||||||
|
# 更改加锁状态
|
||||||
|
if await g_pDBService.userPlant.lockUserPlantByName(uid, name, lock):
|
||||||
|
if lock == 0:
|
||||||
|
return g_sTranslation["lockPlant"]["unlockPlant"].format(name=name)
|
||||||
|
else:
|
||||||
|
return g_sTranslation["lockPlant"]["lockPlant"].format(name=name)
|
||||||
|
else:
|
||||||
|
return g_sTranslation["lockPlant"]["error"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def stealing(cls, uid: str, target: str) -> str:
|
async def stealing(cls, uid: str, target: str) -> str:
|
||||||
"""偷菜
|
"""偷菜
|
||||||
@ -1106,5 +1148,54 @@ class CFarmManager:
|
|||||||
text=g_sTranslation["soilInfo"][soilLevelText],
|
text=g_sTranslation["soilInfo"][soilLevelText],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def pointToVipPointByUid(cls, uid: str, num: int) -> str:
|
||||||
|
"""点券兑换
|
||||||
|
num:用户传参,即将兑换的点券
|
||||||
|
pro:兑换倍数;兑换倍数乘以num即为需要消耗的农场币
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
num (int): 兑换点券数量
|
||||||
|
Returns:
|
||||||
|
str: 返回结果
|
||||||
|
兑换比例在配置文件中配置
|
||||||
|
目前配置文件中默认是20倍
|
||||||
|
100点券需要20000农场币
|
||||||
|
赠送点券规则:
|
||||||
|
小于2000点券:0
|
||||||
|
2000-5000点券:100
|
||||||
|
5000-50000点券:280
|
||||||
|
大于50000点券:3000
|
||||||
|
"""
|
||||||
|
if num < 100:
|
||||||
|
return "点券兑换数量必须大于等于100"
|
||||||
|
|
||||||
|
pro = int(Config.get_config("zhenxun_plugin_farm", "点券兑换倍数"))
|
||||||
|
pro *= num
|
||||||
|
|
||||||
|
point = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
|
if point < pro:
|
||||||
|
return f"你的农场币不足,当前农场币为{point},兑换还需要{pro - point}农场币"
|
||||||
|
|
||||||
|
p = await g_pDBService.user.getUserVipPointByUid(uid)
|
||||||
|
|
||||||
|
giftPoints: int
|
||||||
|
if num < 2000:
|
||||||
|
giftPoints = 0
|
||||||
|
elif num < 5000:
|
||||||
|
giftPoints = 100
|
||||||
|
elif num < 50000:
|
||||||
|
giftPoints = 280
|
||||||
|
else:
|
||||||
|
giftPoints = 3000
|
||||||
|
|
||||||
|
number = num + p + giftPoints
|
||||||
|
await g_pDBService.user.updateUserVipPointByUid(uid, int(number))
|
||||||
|
|
||||||
|
point -= pro
|
||||||
|
await g_pDBService.user.updateUserPointByUid(uid, int(point))
|
||||||
|
|
||||||
|
return f"兑换{num}点券成功,当前点券:{number},赠送点券:{giftPoints},当前农场币:{point}"
|
||||||
|
|
||||||
|
|
||||||
g_pFarmManager = CFarmManager()
|
g_pFarmManager = CFarmManager()
|
||||||
|
|||||||
117
farm/help.py
Normal file
117
farm/help.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from jinja2 import Template
|
||||||
|
from playwright.async_api import async_playwright
|
||||||
|
|
||||||
|
from zhenxun.configs.path_config import DATA_PATH
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
from ..config import g_sResourcePath
|
||||||
|
|
||||||
|
|
||||||
|
def rendeerHtmlToFile(path: Path | str, context: dict, output: Path | str) -> None:
|
||||||
|
"""
|
||||||
|
使用 Jinja2 渲染 HTML 模板并保存到指定文件,会自动创建父目录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): 模板 HTML 路径
|
||||||
|
context (dict): 用于渲染的上下文字典
|
||||||
|
output (str): 输出 HTML 文件路径
|
||||||
|
"""
|
||||||
|
templatePath = str(path)
|
||||||
|
outputPath = str(output)
|
||||||
|
|
||||||
|
templateStr = Path(templatePath).read_text(encoding="utf-8")
|
||||||
|
template = Template(templateStr)
|
||||||
|
rendered = template.render(**context)
|
||||||
|
|
||||||
|
# 自动创建目录
|
||||||
|
Path(outputPath).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
Path(outputPath).write_text(rendered, encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
async def screenshotHtmlToBytes(path: str) -> bytes:
|
||||||
|
"""
|
||||||
|
使用 Playwright 截图本地 HTML 文件并返回 PNG 图片字节数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): 本地 HTML 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bytes: PNG 图片的原始字节内容
|
||||||
|
"""
|
||||||
|
async with async_playwright() as p:
|
||||||
|
browser = await p.chromium.launch()
|
||||||
|
page = await browser.new_page()
|
||||||
|
file_url = Path(path).resolve().as_uri()
|
||||||
|
await page.goto(file_url)
|
||||||
|
image_bytes = await page.screenshot(full_page=True)
|
||||||
|
await browser.close()
|
||||||
|
|
||||||
|
return image_bytes
|
||||||
|
|
||||||
|
|
||||||
|
async def screenshotSave(path: str, save: str) -> None:
|
||||||
|
"""
|
||||||
|
使用 Playwright 渲染本地 HTML 并将截图保存到指定路径
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): HTML 文件路径
|
||||||
|
save (str): PNG 保存路径(如 output/image.png)
|
||||||
|
"""
|
||||||
|
async with async_playwright() as p:
|
||||||
|
browser = await p.chromium.launch()
|
||||||
|
page = await browser.new_page()
|
||||||
|
|
||||||
|
file_url = Path(path).resolve().as_uri()
|
||||||
|
await page.goto(file_url)
|
||||||
|
|
||||||
|
# 确保保存目录存在
|
||||||
|
Path(save).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# 截图并保存到本地文件
|
||||||
|
await page.screenshot(path=save, full_page=True)
|
||||||
|
await browser.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def createHelpImage() -> bool:
|
||||||
|
templatePath = g_sResourcePath / "html/help.html"
|
||||||
|
outputPath = DATA_PATH / "farm_res/html/help.html"
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "功能指令总览",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"command": "开通农场",
|
||||||
|
"description": "首次进入游戏开通农场",
|
||||||
|
"tip": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "购买种子",
|
||||||
|
"description": "从商店中购买可用种子",
|
||||||
|
"tip": "",
|
||||||
|
},
|
||||||
|
{"command": "播种", "description": "将种子种入土地中", "tip": "先开垦土地"},
|
||||||
|
{
|
||||||
|
"command": "收获",
|
||||||
|
"description": "收获成熟作物获得收益",
|
||||||
|
"tip": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "偷菜",
|
||||||
|
"description": "从好友农场中偷取成熟作物",
|
||||||
|
"tip": "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
rendeerHtmlToFile(templatePath, context, outputPath)
|
||||||
|
|
||||||
|
image_bytes = await screenshot_html_to_bytes(html_output_path)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("绘制农场帮助菜单失败", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
41
farm/shop.py
41
farm/shop.py
@ -1,6 +1,5 @@
|
|||||||
import math
|
import math
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
from zhenxun.utils.image_utils import ImageTemplate
|
from zhenxun.utils.image_utils import ImageTemplate
|
||||||
|
|
||||||
from ..config import g_sResourcePath, g_sTranslation
|
from ..config import g_sResourcePath, g_sTranslation
|
||||||
@ -33,7 +32,8 @@ class CShopManager:
|
|||||||
columnName = [
|
columnName = [
|
||||||
"-",
|
"-",
|
||||||
"种子名称",
|
"种子名称",
|
||||||
"种子单价",
|
"农场币",
|
||||||
|
"点券",
|
||||||
"解锁等级",
|
"解锁等级",
|
||||||
"果实单价",
|
"果实单价",
|
||||||
"收获经验",
|
"收获经验",
|
||||||
@ -77,7 +77,8 @@ class CShopManager:
|
|||||||
[
|
[
|
||||||
icon,
|
icon,
|
||||||
plant["name"], # 种子名称
|
plant["name"], # 种子名称
|
||||||
plant["buy"], # 种子单价
|
plant["buy"], # 农场币种子单价
|
||||||
|
plant["vipBuy"], # 点券种子单价
|
||||||
plant["level"], # 解锁等级
|
plant["level"], # 解锁等级
|
||||||
plant["price"], # 果实单价
|
plant["price"], # 果实单价
|
||||||
plant["experience"], # 收获经验
|
plant["experience"], # 收获经验
|
||||||
@ -125,21 +126,32 @@ class CShopManager:
|
|||||||
if level[0] < int(plantInfo["level"]):
|
if level[0] < int(plantInfo["level"]):
|
||||||
return g_sTranslation["buySeed"]["noLevel"]
|
return g_sTranslation["buySeed"]["noLevel"]
|
||||||
|
|
||||||
point = await g_pDBService.user.getUserPointByUid(uid)
|
"""
|
||||||
total = int(plantInfo["buy"]) * num
|
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}"
|
f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}"
|
||||||
)
|
)
|
||||||
|
"""
|
||||||
if point < total:
|
if plantInfo["isVip"] == 1:
|
||||||
return g_sTranslation["buySeed"]["noPoint"]
|
vipPoint = await g_pDBService.user.getUserVipPointByUid(uid)
|
||||||
|
total = int(plantInfo["vipBuy"]) * num
|
||||||
|
if vipPoint < total:
|
||||||
|
return g_sTranslation["buySeed"]["noVipPoint"]
|
||||||
|
await g_pDBService.user.updateUserVipPointByUid(uid, vipPoint - total)
|
||||||
else:
|
else:
|
||||||
|
point = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
|
total = int(plantInfo["buy"]) * num
|
||||||
|
if point < total:
|
||||||
|
return g_sTranslation["buySeed"]["noPoint"]
|
||||||
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
||||||
|
|
||||||
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
|
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
|
||||||
return g_sTranslation["buySeed"]["errorSql"]
|
return g_sTranslation["buySeed"]["errorSql"]
|
||||||
|
|
||||||
|
if plantInfo["isVip"] == 1:
|
||||||
|
return g_sTranslation["buySeed"]["vipSuccess"].format(
|
||||||
|
name=name, total=total, point=vipPoint - total
|
||||||
|
)
|
||||||
|
else:
|
||||||
return g_sTranslation["buySeed"]["success"].format(
|
return g_sTranslation["buySeed"]["success"].format(
|
||||||
name=name, total=total, point=point - total
|
name=name, total=total, point=point - total
|
||||||
)
|
)
|
||||||
@ -167,6 +179,13 @@ class CShopManager:
|
|||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
for plantName, count in plant.items():
|
for plantName, count in plant.items():
|
||||||
|
isLock = await g_pDBService.userPlant.checkPlantLockByName(
|
||||||
|
uid, plantName
|
||||||
|
)
|
||||||
|
|
||||||
|
if isLock:
|
||||||
|
continue
|
||||||
|
|
||||||
plantInfo = await g_pDBService.plant.getPlantByName(plantName)
|
plantInfo = await g_pDBService.plant.getPlantByName(plantName)
|
||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Binary file not shown.
75
resource/html/help.html
Normal file
75
resource/html/help.html
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #ffe4e9;
|
||||||
|
font-family: "Microsoft YaHei", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
}
|
||||||
|
.content-box {
|
||||||
|
background-color: #fff0f5;
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
|
||||||
|
width: 900px;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #ffb6c1;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
tr:not(:last-child) {
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="content-box">
|
||||||
|
<div class="title">{{ title }}</div>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>指令</th>
|
||||||
|
<th>描述</th>
|
||||||
|
<th>Tip</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for entry in data %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ entry.command }}</td>
|
||||||
|
<td>{{ entry.description }}</td>
|
||||||
|
<td>{{ entry.tip }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue
Block a user