✨ 种子商店新增筛选功能
This commit is contained in:
parent
afa2259ad8
commit
7dc55bccf1
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,3 @@
|
||||
__pycache__
|
||||
__pycache__
|
||||
|
||||
./config/sign_in.json
|
||||
|
||||
45
README.md
45
README.md
@ -5,12 +5,42 @@
|
||||
<a href="./LICENSE">
|
||||
<img src="https://img.shields.io/badge/license-GPL3.0-FE7D37" alt="license">
|
||||
</a>
|
||||
<a href="https://www.python.org">
|
||||
<img src="https://img.shields.io/badge/Python-3.10%2B-blue" alt="Python">
|
||||
</a>
|
||||
<a href="https://nonebot.dev/">
|
||||
<img src="https://img.shields.io/badge/Nonebot-2.0.0%2B-black" alt="Nonebot">
|
||||
</a>
|
||||
<a href="https://github.com/zhenxun-org/zhenxun_bot">
|
||||
<img src="https://img.shields.io/badge/zhenxun-0.2.4%2B-%23ECD9D3" alt="Python">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
[](https://qm.qq.com/q/7hsOD4rOw2)
|
||||
|
||||
</p>
|
||||
|
||||
你是说可以种地对吧🤔?
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
## 目录
|
||||
- [真寻农场(zhenxun\_plugin\_farm)](#真寻农场zhenxun_plugin_farm)
|
||||
- [目录](#目录)
|
||||
- [如何安装](#如何安装)
|
||||
- [使用指令](#使用指令)
|
||||
- [更新日志(详细):](#更新日志详细)
|
||||
- [用户方面](#用户方面)
|
||||
- [代码方面](#代码方面)
|
||||
- [待办事宜 `Todo` 列表](#待办事宜-todo-列表)
|
||||
- [关于](#关于)
|
||||
- [致谢](#致谢)
|
||||
- [许可证](#许可证)
|
||||
|
||||
---
|
||||
|
||||
## 如何安装
|
||||
@ -26,7 +56,7 @@
|
||||
| --- | --- | --- |
|
||||
| @小真寻 开通农场 | 首次开通农场 | |
|
||||
| 我的农场币 | 查询农场币 | |
|
||||
| 种子商店 [页数] | 查看种子商店 | 数量不填默认为1 |
|
||||
| 种子商店 [筛选关键字] [页数] or [页数] | 查看种子商店 | 当第一个参数为非整数时,会默认进入筛选状态。页数不填默认为1 |
|
||||
| 购买种子 [种子名称] [数量] | 购买种子 | 数量不填默认为1 |
|
||||
| 我的种子 | 查询仓库种子 | |
|
||||
| 播种 [种子名称] [数量] | 播种种子 | 数量不填默认将最大可能播种 |
|
||||
@ -37,20 +67,23 @@
|
||||
| @美波理 偷菜 | 偷别人的菜 | 每人每天只能偷5次 |
|
||||
| 购买农场币 | 将真寻金币兑换成农场币 | 兑换比例默认为1:2 手续费默认20% |
|
||||
| 更改农场名 [新的农场名] | 改名 |
|
||||
| 农场签到 | 签到 | 需要注意,该项会从服务器拉取签到数据 |
|
||||
|
||||
---
|
||||
|
||||
## 更新日志[(详细)](./log/log.md):
|
||||
用户方面
|
||||
---
|
||||
- 修复重大BUG,该BUG会导致用户经验等级计算异常
|
||||
- 修正种子价格,现在不会以单价的形式购买种子了,而是新增的种子价格
|
||||
- 新增种子商店筛选功能(如果没有BUG的话后续我的种子、我的作物等也会加入筛选功能
|
||||
- 新增签到功能(测试
|
||||
- 新增农场详述功能,能通过该功能更加详细的观看农场数据
|
||||
- 修复了迁移旧数据库无法正常迁移的BUG
|
||||
|
||||
代码方面
|
||||
---
|
||||
- 彻底重构数据库,但是不会像V1.1一样导致用户数据丢失
|
||||
- 迁移部分代码结构,使文件名和代码功能更加匹配
|
||||
- 加入事件机制,采用类似Qt信号槽机制
|
||||
- 修正了多阶段作物成长素材计算逻辑
|
||||
- 修正了作物数据库字段错乱的问题
|
||||
- 作物新增offset字段,用于以后偏移坐标(尚未加入代码 TODO
|
||||
---
|
||||
|
||||
## 待办事宜 `Todo` 列表
|
||||
|
||||
@ -22,7 +22,7 @@ __plugin_meta__ = PluginMetadata(
|
||||
at 开通农场
|
||||
我的农场
|
||||
我的农场币
|
||||
种子商店 [页数]
|
||||
种子商店 [筛选关键字] [页数] or [页数]
|
||||
购买种子 [作物/种子名称] [数量]
|
||||
我的种子
|
||||
播种 [作物/种子名称] [数量] (数量不填默认将最大可能播种
|
||||
@ -34,6 +34,7 @@ __plugin_meta__ = PluginMetadata(
|
||||
开垦
|
||||
购买农场币 [数量] 数量为消耗金币的数量
|
||||
更改农场名 [新农场名]
|
||||
农场签到
|
||||
""".strip(),
|
||||
extra=PluginExtraData(
|
||||
author="Art_Sakura",
|
||||
|
||||
75
command.py
75
command.py
@ -1,3 +1,5 @@
|
||||
import inspect
|
||||
|
||||
from nonebot.adapters import Event, MessageTemplate
|
||||
from nonebot.rule import to_me
|
||||
from nonebot_plugin_alconna import (Alconna, AlconnaMatch, AlconnaQuery, Args,
|
||||
@ -125,7 +127,7 @@ diuse_farm = on_alconna(
|
||||
Option("--all", action=store_true),
|
||||
Subcommand("detail", help_text="农场详述"),
|
||||
Subcommand("my-point", help_text="我的农场币"),
|
||||
Subcommand("seed-shop", Args["num?", int], help_text="种子商店"),
|
||||
Subcommand("seed-shop", Args["res?", MultiVar(str)], help_text="种子商店"),
|
||||
Subcommand("buy-seed", Args["name?", str]["num?", int], help_text="购买种子"),
|
||||
Subcommand("my-seed", help_text="我的种子"),
|
||||
Subcommand("sowing", Args["name?", str]["num?", int], help_text="播种"),
|
||||
@ -147,7 +149,7 @@ diuse_farm = on_alconna(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
image = await g_pFarmManager.drawFarmByUid(uid)
|
||||
@ -164,7 +166,7 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
info = await g_pFarmManager.drawDetailFarmByUid(uid)
|
||||
@ -197,13 +199,35 @@ diuse_farm.shortcut(
|
||||
)
|
||||
|
||||
@diuse_farm.assign("seed-shop")
|
||||
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 1)):
|
||||
async def _(session: Uninfo, res: Match[tuple[str, ...]]):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
image = await g_pShopManager.getSeedShopImage(num.result)
|
||||
if res.result is inspect._empty:
|
||||
raw = []
|
||||
else:
|
||||
raw = res.result
|
||||
|
||||
filterKey: str | int | None = None
|
||||
page: int = 1
|
||||
|
||||
if len(raw) >= 1 and raw[0] is not None:
|
||||
first = raw[0]
|
||||
if isinstance(first, str) and first.isdigit():
|
||||
page = int(first)
|
||||
else:
|
||||
filterKey = first
|
||||
|
||||
if len(raw) >= 2 and raw[1] is not None and isinstance(raw[1], str) and raw[1].isdigit():
|
||||
page = int(raw[1])
|
||||
|
||||
if filterKey is None:
|
||||
image = await g_pShopManager.getSeedShopImage(page)
|
||||
else:
|
||||
image = await g_pShopManager.getSeedShopImage(filterKey, page)
|
||||
|
||||
await MessageUtils.build_message(image).send()
|
||||
|
||||
diuse_farm.shortcut(
|
||||
@ -214,7 +238,7 @@ diuse_farm.shortcut(
|
||||
)
|
||||
|
||||
@diuse_farm.assign("buy-seed")
|
||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1),):
|
||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1)):
|
||||
if not name.available:
|
||||
await MessageUtils.build_message(
|
||||
"请在指令后跟需要购买的种子名称"
|
||||
@ -222,7 +246,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n
|
||||
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pShopManager.buySeed(uid, name.result, num.result)
|
||||
@ -239,7 +263,7 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pFarmManager.getUserSeedByUid(uid)
|
||||
@ -253,7 +277,7 @@ diuse_farm.shortcut(
|
||||
)
|
||||
|
||||
@diuse_farm.assign("sowing")
|
||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1),):
|
||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)):
|
||||
if not name.available:
|
||||
await MessageUtils.build_message(
|
||||
"请在指令后跟需要播种的种子名称"
|
||||
@ -261,7 +285,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n
|
||||
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pFarmManager.sowing(uid, name.result, num.result)
|
||||
@ -279,7 +303,7 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pFarmManager.harvest(uid)
|
||||
@ -296,7 +320,7 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pFarmManager.eradicate(uid)
|
||||
@ -314,7 +338,7 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pFarmManager.getUserPlantByUid(uid)
|
||||
@ -331,7 +355,7 @@ reclamation = on_alconna(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
condition = await g_pFarmManager.reclamationCondition(uid)
|
||||
@ -360,10 +384,10 @@ diuse_farm.shortcut(
|
||||
)
|
||||
|
||||
@diuse_farm.assign("sell-plant")
|
||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1),):
|
||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
|
||||
@ -380,7 +404,7 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo, target: Match[At]):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
if not target.available:
|
||||
@ -412,7 +436,7 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
||||
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
result = await g_pFarmManager.buyPointByUid(uid, num.result)
|
||||
@ -430,12 +454,12 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo, name: Match[str]):
|
||||
if not name.available:
|
||||
await MessageUtils.build_message(
|
||||
"请在指令后跟需要更改的用户名"
|
||||
"请在指令后跟需要更改的农场名"
|
||||
).finish(reply_to=True)
|
||||
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
safeName = sanitize_username(name.result)
|
||||
@ -443,9 +467,9 @@ async def _(session: Uninfo, name: Match[str]):
|
||||
result = await g_pDBService.user.updateUserNameByUid(uid, safeName)
|
||||
|
||||
if result == True:
|
||||
await MessageUtils.build_message("更新用户名成功!").send(reply_to=True)
|
||||
await MessageUtils.build_message("更新农场名成功!").send(reply_to=True)
|
||||
else:
|
||||
await MessageUtils.build_message("更新用户名失败!").send(reply_to=True)
|
||||
await MessageUtils.build_message("更新农场名失败!").send(reply_to=True)
|
||||
|
||||
diuse_farm.shortcut(
|
||||
"农场签到",
|
||||
@ -458,11 +482,11 @@ diuse_farm.shortcut(
|
||||
async def _(session: Uninfo):
|
||||
uid = str(session.user.id)
|
||||
|
||||
if await isRegisteredByUid(uid) == False:
|
||||
if not await isRegisteredByUid(uid):
|
||||
return
|
||||
|
||||
#判断签到是否正常加载
|
||||
if g_bSignStatus == False:
|
||||
if not g_bSignStatus:
|
||||
await MessageUtils.build_message("签到功能异常!").send()
|
||||
|
||||
return
|
||||
@ -475,7 +499,6 @@ async def _(session: Uninfo):
|
||||
if status == 1 or status == 2:
|
||||
#获取签到总天数
|
||||
signDay = await g_pDBService.userSign.getUserSignCountByDate(uid, toDay.strftime("%Y-%m"))
|
||||
|
||||
exp, point = await g_pDBService.userSign.getUserSignRewardByDate(uid, toDay.strftime("%Y-%m-%d"))
|
||||
|
||||
message += f"签到成功!累计签到天数:{signDay}\n获得经验{exp},获得金币{point}"
|
||||
|
||||
78
config/sign_in.json
Normal file
78
config/sign_in.json
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"date": "202505",
|
||||
"exp_max": 50,
|
||||
"exp_min": 5,
|
||||
"point_max": 2000,
|
||||
"point_min": 200,
|
||||
"continuou":
|
||||
{
|
||||
"1":
|
||||
{
|
||||
"point": 3000,
|
||||
"exp": 20
|
||||
},
|
||||
"3":
|
||||
{
|
||||
"point": 5000,
|
||||
"exp": 25,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
},
|
||||
"5":
|
||||
{
|
||||
"point": 7000,
|
||||
"exp": 50,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
},
|
||||
"7":
|
||||
{
|
||||
"point": 7000,
|
||||
"exp": 50,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
},
|
||||
"10":
|
||||
{
|
||||
"point": 7000,
|
||||
"exp": 50,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
},
|
||||
"15":
|
||||
{
|
||||
"point": 7000,
|
||||
"exp": 50,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
},
|
||||
"20":
|
||||
{
|
||||
"point": 7000,
|
||||
"exp": 50,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
},
|
||||
"25":
|
||||
{
|
||||
"point": 7000,
|
||||
"exp": 50,
|
||||
"plant":
|
||||
{
|
||||
"胡萝卜": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
import ast
|
||||
import os
|
||||
import re
|
||||
from contextlib import asynccontextmanager
|
||||
from unittest import result
|
||||
|
||||
import aiosqlite
|
||||
|
||||
@ -87,6 +89,102 @@ class CPlantManager:
|
||||
logger.warning(f"查询作物失败: {name}", e=e)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def getPlantPhaseByName(cls, name: str) -> list:
|
||||
"""根据作物名称获取作物各个阶段
|
||||
|
||||
Args:
|
||||
name (str): 作物名称
|
||||
|
||||
Returns:
|
||||
list: 阶段数组
|
||||
"""
|
||||
try:
|
||||
async with cls.m_pDB.execute(
|
||||
"SELECT phase FROM plant WHERE name = ?", (name,)
|
||||
) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
return []
|
||||
|
||||
phase = row[0].split(',')
|
||||
|
||||
seen = set()
|
||||
result = []
|
||||
for x in phase:
|
||||
if x not in seen:
|
||||
seen.add(x)
|
||||
result.append(x)
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.warning(f"查询作物阶段失败: {name}", e=e)
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
async def getPlantPhaseNumberByName(cls, name: str) -> int:
|
||||
"""根据作物名称获取作物总阶段数
|
||||
|
||||
Args:
|
||||
name (str): 作物名称
|
||||
|
||||
Returns:
|
||||
int: 总阶段数
|
||||
"""
|
||||
try:
|
||||
async with cls.m_pDB.execute(
|
||||
"SELECT phase FROM plant WHERE name = ?", (name,)
|
||||
) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
return -1
|
||||
|
||||
phase = row[0].split(',')
|
||||
|
||||
#去重
|
||||
seen = set()
|
||||
result = []
|
||||
for x in phase:
|
||||
if x not in seen:
|
||||
seen.add(x)
|
||||
result.append(x)
|
||||
|
||||
return len(result)
|
||||
except Exception as e:
|
||||
logger.warning(f"查询作物阶段失败: {name}", e=e)
|
||||
return -1
|
||||
|
||||
@classmethod
|
||||
async def getPlantAgainByName(cls, name: str) -> int:
|
||||
"""根据作物名称获取作物再次成熟时间
|
||||
|
||||
Args:
|
||||
name (str): 作物名称
|
||||
|
||||
Returns:
|
||||
int: 再次成熟时间 单位:h
|
||||
"""
|
||||
|
||||
try:
|
||||
async with cls.m_pDB.execute(
|
||||
"SELECT phase FROM plant WHERE name = ?", (name,)
|
||||
) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
return -1
|
||||
|
||||
phase = row[0].split(',')
|
||||
again = phase[-1] - phase[3] / 60 / 60
|
||||
|
||||
return again
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"查询作物阶段失败: {name}", e=e)
|
||||
return -1
|
||||
|
||||
@classmethod
|
||||
async def existsPlant(cls, name: str) -> bool:
|
||||
"""判断作物是否存在
|
||||
|
||||
@ -8,8 +8,8 @@ from zhenxun.utils._build_image import BuildImage
|
||||
|
||||
from ..dbService import g_pDBService
|
||||
from ..json import g_pJsonManager
|
||||
from .database import CSqlManager
|
||||
from ..tool import g_pToolManager
|
||||
from .database import CSqlManager
|
||||
|
||||
|
||||
class CUserSignDB(CSqlManager):
|
||||
@ -22,7 +22,7 @@ class CUserSignDB(CSqlManager):
|
||||
"isSupplement": "TINYINT NOT NULL DEFAULT 0", #是否补签
|
||||
"exp": "INT NOT NULL DEFAULT 0", #当天签到经验
|
||||
"point": "INT NOT NULL DEFAULT 0", #当天签到金币
|
||||
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')",#创建时间
|
||||
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))",#创建时间
|
||||
"PRIMARY KEY": "(uid, signDate)"
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ class CUserSignDB(CSqlManager):
|
||||
"lastSignDate": "DATE DEFAULT NULL", #上次签到日期
|
||||
"continuousDays": "INT NOT NULL DEFAULT 0", #连续签到天数
|
||||
"supplementCount": "INT NOT NULL DEFAULT 0", #补签次数
|
||||
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')"#更新时间
|
||||
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))"#更新时间
|
||||
}
|
||||
|
||||
await cls.ensureTableSchema("userSignLog", userSignLog)
|
||||
@ -188,7 +188,7 @@ class CUserSignDB(CSqlManager):
|
||||
)
|
||||
|
||||
#计算累签奖励
|
||||
reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays + 1}", None)
|
||||
reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays}", None)
|
||||
|
||||
if reward:
|
||||
point += reward.get('point', 0)
|
||||
|
||||
@ -4,8 +4,8 @@ from zhenxun.services.log import logger
|
||||
|
||||
from ..dbService import g_pDBService
|
||||
from ..json import g_pJsonManager
|
||||
from .database import CSqlManager
|
||||
from ..tool import g_pToolManager
|
||||
from .database import CSqlManager
|
||||
|
||||
|
||||
class CUserSoilDB(CSqlManager):
|
||||
@ -241,6 +241,45 @@ class CUserSoilDB(CSqlManager):
|
||||
(value, uid, soilIndex),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def updateUserSoilFields(cls, uid: str, soilIndex: int, updates: dict) -> bool:
|
||||
"""批量更新指定用户土地的多个字段
|
||||
|
||||
Args:
|
||||
uid (str): 用户ID
|
||||
soilIndex (int): 土地索引
|
||||
updates (dict): 字段-新值的字典
|
||||
|
||||
Returns:
|
||||
bool: 如果无可更新字段则返回 False,否则更新成功返回 True
|
||||
"""
|
||||
#允许更新的列白名单
|
||||
allowedFields = {
|
||||
"plantName", "plantTime", "matureTime", "soilLevel",
|
||||
"wiltStatus", "fertilizerStatus", "bugStatus",
|
||||
"weedStatus", "waterStatus", "harvestCount"
|
||||
}
|
||||
setClauses = []
|
||||
values = []
|
||||
for field, value in updates.items():
|
||||
if field not in allowedFields:
|
||||
continue
|
||||
setClauses.append(f'"{field}" = ?')
|
||||
values.append(value)
|
||||
if not setClauses:
|
||||
return False
|
||||
|
||||
values.extend([uid, soilIndex])
|
||||
sql = f'UPDATE userSoil SET {", ".join(setClauses)} WHERE uid = ? AND soilIndex = ?'
|
||||
|
||||
try:
|
||||
async with cls._transaction():
|
||||
await cls.m_pDB.execute(sql, tuple(values))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"批量更新土地字段失败: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def deleteUserSoil(cls, uid: str, soilIndex: int):
|
||||
"""删除指定用户的土地记录
|
||||
|
||||
51
farm/farm.py
51
farm/farm.py
@ -289,18 +289,19 @@ class CFarmManager:
|
||||
currentTime = g_pToolManager.dateTime().now()
|
||||
matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime']))
|
||||
|
||||
phase = await g_pDBService.plant.getPlantPhaseNumberByName(soilInfo['plantName'])
|
||||
|
||||
#如果当前时间大于成熟时间 说明作物成熟
|
||||
if currentTime >= matureTime:
|
||||
phase = int(plantInfo['phase'])
|
||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase - 1}.png")
|
||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase}.png")
|
||||
|
||||
return True, plant, True
|
||||
else:
|
||||
#如果是多阶段作物 且没有成熟
|
||||
if soilInfo['harvestCount'] >= 1:
|
||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 2}.png")
|
||||
#如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片
|
||||
# if soilInfo['harvestCount'] >= 1:
|
||||
# plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1s}.png")
|
||||
|
||||
return True, plant, False
|
||||
# return True, plant, False
|
||||
|
||||
#如果没有成熟 则根据当前阶段进行绘制
|
||||
plantedTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['plantTime']))
|
||||
@ -308,7 +309,7 @@ class CFarmManager:
|
||||
elapsedTime = currentTime - plantedTime
|
||||
elapsedHour = elapsedTime.total_seconds() / 3600
|
||||
|
||||
currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1)))
|
||||
currentStage = int(elapsedHour / (plantInfo['time'] / phase))
|
||||
|
||||
if currentStage <= 0:
|
||||
if plantInfo['general'] == False:
|
||||
@ -334,7 +335,6 @@ class CFarmManager:
|
||||
"收获数量",
|
||||
"成熟时间(小时)",
|
||||
"收获次数",
|
||||
"再次成熟时间(小时)",
|
||||
"是否可以上架交易行"
|
||||
]
|
||||
|
||||
@ -358,7 +358,7 @@ class CFarmManager:
|
||||
|
||||
iconPath = g_sResourcePath / f"plant/{seedName}/icon.png"
|
||||
icon = (iconPath, 33, 33) if iconPath.exists() else ""
|
||||
sellable = "可以" if plantInfo['again'] else "不可以"
|
||||
sellable = "可以" if plantInfo['sell'] else "不可以"
|
||||
|
||||
dataList.append([
|
||||
icon,
|
||||
@ -368,7 +368,6 @@ class CFarmManager:
|
||||
plantInfo['harvest'],
|
||||
plantInfo['time'],
|
||||
plantInfo['crop'],
|
||||
plantInfo['again'],
|
||||
sellable
|
||||
])
|
||||
except KeyError:
|
||||
@ -509,11 +508,18 @@ class CFarmManager:
|
||||
if soilInfo['harvestCount'] + 1 >= plantInfo['crop']:
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "wiltStatus", 1)
|
||||
else:
|
||||
matureTs = int(currentTime.timestamp()) + int(plantInfo.get("again", 0)) * 3600
|
||||
phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
|
||||
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "harvestCount", soilInfo['harvestCount'] + 1)
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "lastResetTime", int(currentTime.timestamp()))
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "matureTime", matureTs)
|
||||
ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1
|
||||
p1, p2, *rest = phase
|
||||
|
||||
await g_pDBService.userSoil.updateUserSoilFields(uid, i,
|
||||
{
|
||||
"harvestCount": hc,
|
||||
"plantTime": ts - p1 - p2,
|
||||
"matureTime": ts + p2 + sum(rest),
|
||||
}
|
||||
)
|
||||
|
||||
await g_pEventManager.m_afterHarvest.emit(uid=uid, name=soilInfo['plantName'], num=number, soilIndex=i)
|
||||
|
||||
@ -619,7 +625,7 @@ class CFarmManager:
|
||||
if icon_path.exists():
|
||||
icon = (icon_path, 33, 33)
|
||||
|
||||
if plantInfo['again'] == True:
|
||||
if plantInfo['sell'] == True:
|
||||
sell = "可以"
|
||||
else:
|
||||
sell = "不可以"
|
||||
@ -722,11 +728,18 @@ class CFarmManager:
|
||||
if soilInfo['harvestCount'] + 1 >= plantInfo['crop']:
|
||||
await g_pDBService.userSoil.updateUserSoil(target, i, "wiltStatus", 1)
|
||||
else:
|
||||
matureTs = int(currentTime.timestamp()) + int(plantInfo.get("again", 0)) * 3600
|
||||
phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
|
||||
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "harvestCount", soilInfo['harvestCount'] + 1)
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "lastResetTime", int(currentTime.timestamp()))
|
||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "matureTime", matureTs)
|
||||
ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1
|
||||
p1, p2, *rest = phase
|
||||
|
||||
await g_pDBService.userSoil.updateUserSoilFields(uid, i,
|
||||
{
|
||||
"harvestCount": hc,
|
||||
"plantTime": ts - p1 - p2,
|
||||
"matureTime": ts + p2 + sum(rest),
|
||||
}
|
||||
)
|
||||
|
||||
await g_pDBService.userSteal.addStealRecord(target, i, uid, randomNumber, int(g_pToolManager.dateTime().now().timestamp()))
|
||||
|
||||
|
||||
86
farm/shop.py
86
farm/shop.py
@ -12,16 +12,28 @@ from ..json import g_pJsonManager
|
||||
|
||||
|
||||
class CShopManager:
|
||||
|
||||
@classmethod
|
||||
async def getSeedShopImage(cls, num: int = 1) -> bytes:
|
||||
async def getSeedShopImage(cls, filterKey: str|int = 1, num: int = 1) -> bytes:
|
||||
"""获取商店页面
|
||||
|
||||
Args:
|
||||
filterKey (str|int):
|
||||
- 字符串: 根据关键字筛选种子名称
|
||||
- 整数: 翻至对应页(无筛选)
|
||||
num (int, optional): 当 filterKey 为字符串时,用于指定页码。Defaults to 1.
|
||||
|
||||
Returns:
|
||||
bytes: 返回商店图片bytes
|
||||
"""
|
||||
# 解析参数:区分筛选关键字和页码
|
||||
filterStr = None
|
||||
if isinstance(filterKey, int):
|
||||
page = filterKey
|
||||
else:
|
||||
filterStr = filterKey
|
||||
page = num
|
||||
|
||||
dataList = []
|
||||
# 表头定义
|
||||
columnName = [
|
||||
"-",
|
||||
"种子名称",
|
||||
@ -32,59 +44,65 @@ class CShopManager:
|
||||
"收获数量",
|
||||
"成熟时间(小时)",
|
||||
"收获次数",
|
||||
"再次成熟时间(小时)",
|
||||
"是否可以上架交易行"
|
||||
]
|
||||
|
||||
sell = ""
|
||||
# 查询所有可购买作物,并根据筛选关键字过滤
|
||||
plants = await g_pDBService.plant.listPlants()
|
||||
plantSize = await g_pDBService.plant.countPlants(True)
|
||||
|
||||
start = (num - 1) * 15
|
||||
items = islice(plants, start, start + 15)
|
||||
|
||||
for plant in items:
|
||||
filteredPlants = []
|
||||
for plant in plants:
|
||||
# 跳过未解锁购买的种子
|
||||
if plant['isBuy'] == 0:
|
||||
continue
|
||||
# 字符串筛选
|
||||
if filterStr and filterStr not in plant['name']:
|
||||
continue
|
||||
filteredPlants.append(plant)
|
||||
|
||||
# 计算分页
|
||||
totalCount = len(filteredPlants)
|
||||
pageCount = math.ceil(totalCount / 15) if totalCount else 1
|
||||
startIndex = (page - 1) * 15
|
||||
pageItems = filteredPlants[startIndex: startIndex + 15]
|
||||
|
||||
# 构建数据行
|
||||
dataList = []
|
||||
for plant in pageItems:
|
||||
# 图标处理
|
||||
icon = ""
|
||||
iconPath = g_sResourcePath / f"plant/{plant['name']}/icon.png"
|
||||
if iconPath.exists():
|
||||
icon = (iconPath, 33, 33)
|
||||
|
||||
if plant['again'] == True:
|
||||
sell = "可以"
|
||||
else:
|
||||
sell = "不可以"
|
||||
# 交易行标记
|
||||
sell = "可以" if plant['sell'] else "不可以"
|
||||
|
||||
dataList.append(
|
||||
[
|
||||
icon,
|
||||
plant['name'],
|
||||
plant['buy'],
|
||||
plant['level'],
|
||||
plant['price'],
|
||||
plant['experience'],
|
||||
plant['harvest'],
|
||||
plant['time'],
|
||||
plant['crop'],
|
||||
plant['again'],
|
||||
sell
|
||||
]
|
||||
)
|
||||
dataList.append([
|
||||
icon,
|
||||
plant['name'], # 种子名称
|
||||
plant['buy'], # 种子单价
|
||||
plant['level'], # 解锁等级
|
||||
plant['price'], # 果实单价
|
||||
plant['experience'], # 收获经验
|
||||
plant['harvest'], # 收获数量
|
||||
plant['time'], # 成熟时间(小时)
|
||||
plant['crop'], # 收获次数
|
||||
sell # 是否可上架交易行
|
||||
])
|
||||
|
||||
count = math.ceil(plantSize / 15)
|
||||
title = f"种子商店 页数: {num}/{count}"
|
||||
# 页码标题
|
||||
title = f"种子商店 页数: {page}/{pageCount}"
|
||||
|
||||
# 渲染表格并返回图片bytes
|
||||
result = await ImageTemplate.table_page(
|
||||
title,
|
||||
"购买示例:@小真寻 购买种子 大白菜 5",
|
||||
columnName,
|
||||
dataList,
|
||||
)
|
||||
|
||||
return result.pic2bytes()
|
||||
|
||||
|
||||
@classmethod
|
||||
async def buySeed(cls, uid: str, name: str, num: int = 1) -> str:
|
||||
"""购买种子
|
||||
@ -120,7 +138,7 @@ class CShopManager:
|
||||
else:
|
||||
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
||||
|
||||
if await g_pDBService.userSeed.addUserSeedByUid(uid, name, num) == False:
|
||||
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
|
||||
return "购买失败,执行数据库错误!"
|
||||
|
||||
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"
|
||||
|
||||
14
log/log.md
14
log/log.md
@ -1,5 +1,19 @@
|
||||
# 真寻农场更新日志
|
||||
|
||||
## V1.4
|
||||
用户方面
|
||||
---
|
||||
- 新增种子商店筛选功能(如果没有BUG的话后续我的种子、我的作物等也会加入筛选功能
|
||||
- 新增签到功能(测试
|
||||
- 新增农场详述功能,能通过该功能更加详细的观看农场数据
|
||||
- 修复了迁移旧数据库无法正常迁移的BUG
|
||||
|
||||
代码方面
|
||||
---
|
||||
- 修正了多阶段作物成长素材计算逻辑
|
||||
- 修正了作物数据库字段错乱的问题
|
||||
- 作物新增offset字段,用于以后偏移坐标(尚未加入代码 TODO
|
||||
|
||||
## V1.3
|
||||
用户方面
|
||||
---
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user