完成对数据库的翻新

This commit is contained in:
Art_Sakura 2025-04-27 17:00:58 +08:00
parent 72baa5d095
commit b5334dfc01
16 changed files with 358 additions and 92 deletions

View File

@ -6,7 +6,7 @@
## 如何安装 ## 如何安装
方法一(推荐):在小真寻后台的插件商店下载即可 方法一(推荐):在小真寻后台的插件商店下载即可<br>
方法二:下载源码放在小真寻`plugin`目录下 方法二:下载源码放在小真寻`plugin`目录下
## 使用指令 ## 使用指令
@ -22,22 +22,32 @@
| 收获 | 收获成熟作物 | | | 收获 | 收获成熟作物 | |
| 铲除 | 铲除荒废作物 | | | 铲除 | 铲除荒废作物 | |
| 我的作物 | | | | 我的作物 | | |
| 出售作物 [作物名称] [数量] | 从仓库里向系统售卖作物 | 作物不填默认清空仓库 数量不填默认全部 | | 出售作物 [作物名称] [数量] | 从仓库里向系统售卖作物 | 不填写作物名将售卖仓库种全部作物 填作物名不填数量将指定作物全部出售 |
| @美波理 偷菜 | 偷别人的菜 | 每人每天只能偷5次 | | @美波理 偷菜 | 偷别人的菜 | 每人每天只能偷5次 |
| 购买农场币 | 将真寻金币兑换成农场币 | 兑换比例默认为1:2 手续费默认20% | | 购买农场币 | 将真寻金币兑换成农场币 | 兑换比例默认为1:2 手续费默认20% |
--- ---
## 更新日志[详细](./log/log.md)
- 感谢[quanquan1014](https://github.com/quanquan1014)对农场名称中包含特殊字符的处理。
- 更正数据库写法但是会导致V1.0用户的作物和种子丢失
- 完善我的农场图片资源,现在会在左上角显示经验、等级、金币等详细信息了
- 完善出售作物逻辑,现在可以空置作物名称来一键出售全部作物了,也可以选择空置数量来一键出售仓库种指定作物
- 完善播种逻辑,现在可以空置数量来一键播种指定作物了
- 新增更改农场名指令
- 改进对土地开垦条件判断
---
## 待办事宜 `Todo` 列表 ## 待办事宜 `Todo` 列表
- [x] 完善我的农场图片,例如左上角显示用户数据 - [x] 完善我的农场图片,例如左上角显示用户数据
- [x] 完善升级数据、作物数据、作物图片 - [ ] 完善升级数据、作物数据、作物图片
- [x] 签到功能 - [ ] 签到功能
- [x] 添加渔场功能 - [ ] 添加渔场功能
- [x] 增加活动、交易行功能 - [ ] 增加活动、交易行功能
- [x] 增加交易行总行功能 - [ ] 增加交易行总行功能
- [x] 添加其他游戏种子素材 - [ ] 添加其他游戏种子素材
- [x] 想不到了,想到再说 - [ ] 想不到了,想到再说
--- ---

View File

@ -24,18 +24,19 @@ __plugin_meta__ = PluginMetadata(
种子商店 [页数] 种子商店 [页数]
购买种子 [作物/种子名称] [数量] 购买种子 [作物/种子名称] [数量]
我的种子 我的种子
播种 [作物/种子名称] [数量] 播种 [作物/种子名称] [数量] (数量不填默认将最大可能播种
收获 收获
铲除 铲除
我的作物 我的作物
出售作物 [作物/种子名称] [数量] (不填写作物 出售作物 [作物/种子名称] [数量] (不填写作物名将售卖仓库种全部作物 填作物名不填数量将指定作物全部出售
偷菜 at 偷菜 at (每人每天只能偷5次
开垦 开垦
购买农场币 [数量] 数量为消耗金币的数量 购买农场币 [数量] 数量为消耗金币的数量
更改农场名 [新农场名]
""".strip(), """.strip(),
extra=PluginExtraData( extra=PluginExtraData(
author="Art_Sakura", author="Art_Sakura",
version="1.0", version="1.1",
commands=[Command(command="我的农场")], commands=[Command(command="我的农场")],
menu_type="群内小游戏", menu_type="群内小游戏",
configs=[ configs=[

View File

@ -1,9 +1,9 @@
from nonebot.adapters import Event, MessageTemplate from nonebot.adapters import Event, MessageTemplate
from nonebot.rule import to_me from nonebot.rule import to_me
from nonebot.typing import T_State from nonebot.typing import T_State
from nonebot_plugin_alconna import (Alconna, AlconnaQuery, Args, Arparma, At, from nonebot_plugin_alconna import (Alconna, AlconnaMatch, AlconnaQuery, Args,
Match, MultiVar, Option, Query, Subcommand, Arparma, At, Match, MultiVar, Option,
on_alconna, store_true) Query, Subcommand, on_alconna, store_true)
from nonebot_plugin_uninfo import Uninfo from nonebot_plugin_uninfo import Uninfo
from nonebot_plugin_waiter import waiter from nonebot_plugin_waiter import waiter
@ -46,18 +46,18 @@ async def handle_register(session: Uninfo):
# 获取原始用户名并安全处理 # 获取原始用户名并安全处理
raw_name = str(session.user.name) raw_name = str(session.user.name)
safe_name = sanitize_username(raw_name) safe_name = sanitize_username(raw_name)
# 初始化用户信息 # 初始化用户信息
success = await g_pSqlManager.initUserInfoByUid( success = await g_pSqlManager.initUserInfoByUid(
uid=uid, uid=uid,
name=safe_name, name=safe_name,
exp=0, exp=0,
point=100 point=500
) )
msg = ( msg = (
"✅ 农场开通成功!\n💼 初始资金:100农场币" "✅ 农场开通成功!\n💼 初始资金:500农场币"
if success if success
else "⚠️ 开通失败,请稍后再试" else "⚠️ 开通失败,请稍后再试"
) )
logger.info(f"用户注册 {'成功' if success else '失败'}{uid}") logger.info(f"用户注册 {'成功' if success else '失败'}{uid}")
@ -65,9 +65,9 @@ async def handle_register(session: Uninfo):
except Exception as e: except Exception as e:
msg = "⚠️ 系统繁忙,请稍后再试" msg = "⚠️ 系统繁忙,请稍后再试"
logger.error(f"注册异常 | UID:{uid} | 错误:{str(e)}") logger.error(f"注册异常 | UID:{uid} | 错误:{str(e)}")
await MessageUtils.build_message(msg).send(reply_to=True) await MessageUtils.build_message(msg).send(reply_to=True)
def sanitize_username(username: str, max_length: int = 15) -> str: def sanitize_username(username: str, max_length: int = 15) -> str:
""" """
安全处理用户名 安全处理用户名
@ -81,14 +81,14 @@ def sanitize_username(username: str, max_length: int = 15) -> str:
# 处理空值 # 处理空值
if not username: if not username:
return "神秘农夫" return "神秘农夫"
# 基础清洗 # 基础清洗
cleaned = username.strip() cleaned = username.strip()
# 允许的字符白名单(可自定义扩展) # 允许的字符白名单(可自定义扩展)
safe_chars = { safe_chars = {
'_', '-', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '-', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
'+', '=', '.', ',', '~', '·', ' ', '+', '=', '.', ',', '~', '·', ' ',
'a','b','c','d','e','f','g','h','i','j','k','l','m', 'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z', 'n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M', 'A','B','C','D','E','F','G','H','I','J','K','L','M',
@ -97,24 +97,24 @@ def sanitize_username(username: str, max_length: int = 15) -> str:
} }
# 添加常用中文字符Unicode范围 # 添加常用中文字符Unicode范围
safe_chars.update(chr(c) for c in range(0x4E00, 0x9FFF+1)) safe_chars.update(chr(c) for c in range(0x4E00, 0x9FFF+1))
# 过滤危险字符 # 过滤危险字符
filtered = [ filtered = [
c if c in safe_chars or 0x4E00 <= ord(c) <= 0x9FFF c if c in safe_chars or 0x4E00 <= ord(c) <= 0x9FFF
else '' else ''
for c in cleaned for c in cleaned
] ]
# 合并处理结果 # 合并处理结果
safe_str = ''.join(filtered) safe_str = ''.join(filtered)
# 转义单引号(双重保障) # 转义单引号(双重保障)
escaped = safe_str.replace("'", "''") escaped = safe_str.replace("'", "''")
# 处理空结果 # 处理空结果
if not escaped: if not escaped:
return "神秘农夫" return "神秘农夫"
# 长度限制 # 长度限制
return escaped[:max_length] return escaped[:max_length]
@ -130,24 +130,24 @@ 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("reclamation", Args["isBool?", 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="购买农场币"),
#Subcommand("sell-point", Args["num?", int], help_text="转换金币") #Subcommand("sell-point", Args["num?", int], help_text="转换金币")
Subcommand("change-name", Args["name?", str], help_text="更改农场名")
), ),
priority=5, priority=5,
block=True, block=True,
) )
@diuse_farm.assign("$main") @diuse_farm.assign("$main")
async def _(session: Uninfo, nickname: str = UserName()): async def _(session: Uninfo):
uid = str(session.user.id) uid = str(session.user.id)
if await isRegisteredByUid(uid) == False: if await isRegisteredByUid(uid) == False:
return return
image = await g_pFarmManager.drawFarmByUid(uid, nickname) image = await g_pFarmManager.drawFarmByUid(uid)
await MessageUtils.build_message(image).send(reply_to=True) await MessageUtils.build_message(image).send(reply_to=True)
diuse_farm.shortcut( diuse_farm.shortcut(
@ -339,12 +339,7 @@ diuse_farm.shortcut(
) )
@diuse_farm.assign("sell-plant") @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),):
if not name.available:
await MessageUtils.build_message(
"请在指令后跟需要出售的作物名称"
).finish(reply_to=True)
uid = str(session.user.id) uid = str(session.user.id)
if await isRegisteredByUid(uid) == False: if await isRegisteredByUid(uid) == False:
@ -401,3 +396,32 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
result = await g_pFarmManager.buyPointByUid(uid, num.result) result = await g_pFarmManager.buyPointByUid(uid, num.result)
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=["change-name", "{name}"],
prefix=True,
)
@diuse_farm.assign("change-name")
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:
return
safeName = sanitize_username(name.result)
result = await g_pSqlManager.updateUserNameByUid(uid, safeName)
if result == True:
await MessageUtils.build_message("更新用户名成功!").send(reply_to=True)
else:
await MessageUtils.build_message("更新用户名失败!").send(reply_to=True)

View File

@ -213,6 +213,21 @@
"sell": false "sell": false
}, },
"番茄": "番茄":
{
"level": 6,
"buy": 251,
"limit": 0,
"experience": 22,
"harvest": 21,
"price": 26,
"time": 17,
"crop": 1,
"again": 0,
"phase": 6,
"general": true,
"sell": false
},
"ATTomato":
{ {
"level": 6, "level": 6,
"buy": 99999, "buy": 99999,

4
config/sign_in.json Normal file
View File

@ -0,0 +1,4 @@
{
"date": "202505",
""
}

View File

@ -143,12 +143,20 @@ class CSqlManager:
"count": "INTEGER NOT NULL DEFAULT 0", "count": "INTEGER NOT NULL DEFAULT 0",
"PRIMARY KEY": "(uid, seed)" "PRIMARY KEY": "(uid, seed)"
} }
# 5. 用户道具明细表
userItem = {
"uid": "INTEGER NOT NULL",
"item": "TEXT NOT NULL",
"count": "INTEGER NOT NULL DEFAULT 0",
"PRIMARY KEY": "(uid, item)"
}
#建表(或增列) #建表(或增列)
await cls.ensureTableSchema("user", userInfo) await cls.ensureTableSchema("user", userInfo)
await cls.ensureTableSchema("soil", userSoilInfo) await cls.ensureTableSchema("soil", userSoilInfo)
await cls.ensureTableSchema("userPlant", userPlant) await cls.ensureTableSchema("userPlant", userPlant)
await cls.ensureTableSchema("userSeed", userSeed) await cls.ensureTableSchema("userSeed", userSeed)
await cls.ensureTableSchema("userItem", userItem)
return True return True
@ -175,7 +183,7 @@ class CSqlManager:
return False return False
@classmethod @classmethod
async def initUserInfoByUid(cls, uid: str, name: str = "", exp: int = 0, point: int = 100): async def initUserInfoByUid(cls, uid: str, name: str = "", exp: int = 0, point: int = 500):
"""初始化用户信息 """初始化用户信息
Args: Args:
@ -190,11 +198,6 @@ class CSqlManager:
INSERT INTO user (uid, name, exp, point, soil, stealing) VALUES ({uid}, '{name}', {exp}, {point}, 3, '{date.today()}|5') INSERT INTO user (uid, name, exp, point, soil, stealing) VALUES ({uid}, '{name}', {exp}, {point}, 3, '{date.today()}|5')
""" """
#用户仓库
userStorehouse = f"""
INSERT INTO storehouse (uid) VALUES ({uid});
"""
#用户土地 #用户土地
userSoilInfo = f""" userSoilInfo = f"""
INSERT INTO soil (uid) VALUES ({uid}); INSERT INTO soil (uid) VALUES ({uid});
@ -203,9 +206,6 @@ class CSqlManager:
if not await cls.executeDB(userInfo): if not await cls.executeDB(userInfo):
return False return False
if not await cls.executeDB(userStorehouse):
return False
if not await cls.executeDB(userSoilInfo): if not await cls.executeDB(userSoilInfo):
return False return False
@ -244,6 +244,55 @@ class CSqlManager:
logger.warning(f"getUserInfoByUid查询失败: {e}") logger.warning(f"getUserInfoByUid查询失败: {e}")
return {} return {}
@classmethod
async def getUserNameByUid(cls, uid: str) -> str:
"""根据用户uid查询用户名
Args:
uid (str): 用户uid
Returns:
str: 用户名如果失败返回空字符串
"""
if not uid:
return ""
try:
async with cls.m_pDB.execute(
"SELECT name FROM user WHERE uid = ?",
(uid,)
) as cursor:
row = await cursor.fetchone()
return row["name"] if row else ""
except Exception as e:
logger.warning(f"真寻农场getUserNameByUid查询失败: {e}")
return ""
@classmethod
async def updateUserNameByUid(cls, uid: str, name: str) -> bool:
"""根据用户uid修改用户名
Args:
uid (str): 用户uid
name (str): 新用户名
Returns:
bool: 是否更新成功
"""
if not uid or not name:
return False
try:
async with cls._transaction():
await cls.m_pDB.execute(
"UPDATE user SET name = ? WHERE uid = ?",
(name, uid)
)
return True
except Exception as e:
logger.warning(f"真寻农场updateUserNameByUid失败: {e}")
return False
@classmethod @classmethod
async def getUserPointByUid(cls, uid: str) -> int: async def getUserPointByUid(cls, uid: str) -> int:
"""根据用户Uid获取用户农场币 """根据用户Uid获取用户农场币
@ -709,4 +758,152 @@ class CSqlManager:
logger.warning(f"真寻农场deleteUserPlantByName 失败: {e}") logger.warning(f"真寻农场deleteUserPlantByName 失败: {e}")
return False return False
@classmethod
async def getUserItemByName(cls, uid: str, item: str) -> Optional[int]:
"""根据道具名称查询某一项数量
Args:
uid (str): 用户uid
item (str): 道具名称
Returns:
Optional[int]: 数量不存在返回None
"""
if not uid or not item:
return None
try:
async with cls.m_pDB.execute(
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
(uid, item)
) as cursor:
row = await cursor.fetchone()
return row[0] if row else None
except Exception as e:
logger.warning(f"真寻农场getUserItemByName查询失败: {e}")
return None
@classmethod
async def getUserItemByUid(cls, uid: str) -> dict:
"""根据用户Uid获取全部道具信息
Args:
uid (str): 用户uid
Returns:
dict: {itemName: count, ...}
"""
if not uid:
return {}
try:
cursor = await cls.m_pDB.execute(
"SELECT item, count FROM userItem WHERE uid = ?",
(uid,)
)
rows = await cursor.fetchall()
return {row["item"]: row["count"] for row in rows}
except Exception as e:
logger.warning(f"真寻农场getUserItemByUid查询失败: {e}")
return {}
@classmethod
async def deleteUserItemByName(cls, uid: str, item: str) -> bool:
"""根据道具名删除道具
Args:
uid (str): 用户uid
item (str): 道具名称
Returns:
bool: 是否删除成功
"""
if not uid or not item:
return False
try:
async with cls._transaction():
await cls.m_pDB.execute(
"DELETE FROM userItem WHERE uid = ? AND item = ?",
(uid, item)
)
return True
except Exception as e:
logger.warning(f"真寻农场deleteUserItemByName失败: {e}")
return False
@classmethod
async def updateUserItemByName(cls, uid: str, item: str, count: int) -> bool:
"""根据道具名直接更新道具数量
Args:
uid (str): 用户uid
item (str): 道具名称
count (int): 要更新的新数量
Returns:
bool: 是否更新成功
"""
if not uid or not item:
return False
try:
async with cls._transaction():
if count <= 0:
await cls.m_pDB.execute(
"DELETE FROM userItem WHERE uid = ? AND item = ?",
(uid, item)
)
else:
await cls.m_pDB.execute(
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
(count, uid, item)
)
return True
except Exception as e:
logger.warning(f"真寻农场updateUserItemByName失败: {e}")
return False
@classmethod
async def addUserItemByUid(cls, uid: str, item: str, count: int = 1) -> bool:
"""根据用户uid添加道具信息
Args:
uid (str): 用户uid
item (str): 道具名称
count (int, optional): 数量.Defaults to 1.
Returns:
bool: 是否添加成功
"""
if not uid or not item:
return False
try:
async with cls._transaction():
async with cls.m_pDB.execute(
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
(uid, item)
) as cursor:
row = await cursor.fetchone()
if row:
newCount = row[0] + count
if newCount <= 0:
await cls.m_pDB.execute(
"DELETE FROM userItem WHERE uid = ? AND item = ?",
(uid, item)
)
else:
await cls.m_pDB.execute(
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
(newCount, uid, item)
)
else:
if count > 0:
await cls.m_pDB.execute(
"INSERT INTO userItem (uid, item, count) VALUES (?, ?, ?)",
(uid, item, count)
)
return True
except Exception as e:
logger.warning(f"真寻农场addUserItemByUid失败: {e}")
return False
g_pSqlManager = CSqlManager() g_pSqlManager = CSqlManager()

View File

@ -51,7 +51,7 @@ class CFarmManager:
return f"充值{point}农场币成功,手续费{tax}金币,当前农场币:{number}" return f"充值{point}农场币成功,手续费{tax}金币,当前农场币:{number}"
@classmethod @classmethod
async def drawFarmByUid(cls, uid: str, name: str) -> bytes: async def drawFarmByUid(cls, uid: str) -> bytes:
"""绘制用户农场 """绘制用户农场
Args: Args:
@ -72,7 +72,9 @@ class CFarmManager:
await grass.resize(0, soilSize[0], soilSize[1]) await grass.resize(0, soilSize[0], soilSize[1])
soilPos = g_pJsonManager.m_pSoil['soil'] soilPos = g_pJsonManager.m_pSoil['soil']
soilUnlock = await g_pSqlManager.getUserSoilByUid(uid)
userInfo = await g_pSqlManager.getUserInfoByUid(uid)
soilUnlock = int(userInfo['soil'])
x = 0 x = 0
y = 0 y = 0
@ -128,7 +130,7 @@ class CFarmManager:
await img.paste(frame, (75, 44)) await img.paste(frame, (75, 44))
#用户名 #用户名
nameImg = await BuildImage.build_text_image(name, size = 24, font_color = (77, 35, 4)) nameImg = await BuildImage.build_text_image(userInfo['name'], size = 24, font_color = (77, 35, 4))
await img.paste(nameImg, (300, 92)) await img.paste(nameImg, (300, 92))
#经验值 #经验值
@ -148,12 +150,10 @@ class CFarmManager:
await img.paste(levelImg, (660, 187)) await img.paste(levelImg, (660, 187))
#金币 #金币
point = await g_pSqlManager.getUserPointByUid(uid) pointImg = await BuildImage.build_text_image(str(userInfo['point']), size = 24, font_color = (253, 253, 253))
pointImg = await BuildImage.build_text_image(str(point), size = 24, font_color = (253, 253, 253))
await img.paste(pointImg, (330, 255)) await img.paste(pointImg, (330, 255))
#点券 #点券 TODO
bonds = await g_pSqlManager.getUserPointByUid(uid)
bondsImg = await BuildImage.build_text_image("0", size = 24, font_color = (253, 253, 253)) bondsImg = await BuildImage.build_text_image("0", size = 24, font_color = (253, 253, 253))
await img.paste(bondsImg, (570, 255)) await img.paste(bondsImg, (570, 255))
@ -473,14 +473,14 @@ class CFarmManager:
if plant is None: if plant is None:
result = await ImageTemplate.table_page( result = await ImageTemplate.table_page(
"作物仓库", "作物仓库",
"播种示例:@小真寻 出售作物 大白菜 [数量]", "出售示例:@小真寻 出售作物 大白菜 [数量]",
column_name, column_name,
data_list, data_list,
) )
return result.pic2bytes() return result.pic2bytes()
sell = "" sell = ""
for name, count in plant.items(): # 使用 .items() 来遍历字典 for name, count in plant.items():
plantInfo = g_pJsonManager.m_pPlant['plant'][name] plantInfo = g_pJsonManager.m_pPlant['plant'][name]
icon = "" icon = ""
icon_path = g_sResourcePath / f"plant/{name}/icon.png" icon_path = g_sResourcePath / f"plant/{name}/icon.png"
@ -507,7 +507,7 @@ class CFarmManager:
result = await ImageTemplate.table_page( result = await ImageTemplate.table_page(
"作物仓库", "作物仓库",
"播种示例:@小真寻 出售作物 大白菜 [数量]", "出售示例:@小真寻 出售作物 大白菜 [数量]",
column_name, column_name,
data_list, data_list,
) )

View File

@ -23,7 +23,7 @@ class CShopManager:
column_name = [ column_name = [
"-", "-",
"种子名称", "种子名称",
"种子单价" "种子单价",
"解锁等级", "解锁等级",
"果实单价", "果实单价",
"收获经验", "收获经验",
@ -132,39 +132,39 @@ class CShopManager:
Returns: Returns:
str: str:
""" """
plantDict = await g_pSqlManager.getUserPlantByUid(uid) if not isinstance(name, str) or name.strip() == "":
if not plantDict: name = ""
plant = await g_pSqlManager.getUserPlantByUid(uid)
if not plant:
return "你仓库没有可以出售的作物" return "你仓库没有可以出售的作物"
totalPoint = 0 point = 0
totalSold = 0
isAll = (num == -1)
if not name: if name == "":
for plantName, count in plantDict.items(): for plantName, count in plant.items():
plantInfo = g_pJsonManager.m_pPlant['plant'][plantName] plantInfo = g_pJsonManager.m_pPlant['plant'][plantName]
totalPoint += plantInfo['price'] * count point += plantInfo['price'] * count
await g_pSqlManager.deleteUserPlantByName(uid, plantName) await g_pSqlManager.updateUserPlantByName(uid, plantName, 0)
else: else:
currentCount = plantDict.get(name) if name not in plant:
if currentCount is None: return f"出售作物{name}出错:仓库中不存在该作物"
return f"出售作物{name}出错:你没有这种作物" available = plant[name]
sellAmount = available if isAll else min(available, num)
if sellAmount <= 0:
return f"出售作物{name}出错:数量不足"
await g_pSqlManager.updateUserPlantByName(uid, name, available - sellAmount)
totalSold = sellAmount
if num == -1: totalPoint = point if name == "" else totalSold * g_pJsonManager.m_pPlant['plant'][name]['price']
sellCount = currentCount currentPoint = await g_pSqlManager.getUserPointByUid(uid)
else: await g_pSqlManager.updateUserPointByUid(uid, currentPoint + totalPoint)
if num > currentCount:
return f"出售作物{name}出错:数量不足"
sellCount = num
plantInfo = g_pJsonManager.m_pPlant['plant'][name] if name == "":
totalPoint = plantInfo['price'] * sellCount return f"成功出售所有作物,获得农场币:{totalPoint},当前农场币:{currentPoint + totalPoint}"
await g_pSqlManager.addUserPlantByUid(uid, name, -sellCount)
point = await g_pSqlManager.getUserPointByUid(uid)
await g_pSqlManager.updateUserPointByUid(uid, point + totalPoint)
if not name:
return f"成功出售所有作物,获得农场币:{totalPoint},当前农场币:{point + totalPoint}"
else: else:
return f"成功出售{name},获得农场币:{totalPoint},当前农场币:{point + totalPoint}" return f"成功出售{name},获得农场币:{totalPoint},当前农场币:{currentPoint + totalPoint}"
g_pShopManager = CShopManager() g_pShopManager = CShopManager()

15
log/log.md Normal file
View File

@ -0,0 +1,15 @@
# 真寻农场更新日志
## V1.1
- 感谢[quanquan1014](https://github.com/quanquan1014)对农场名称中包含特殊字符的处理。
- 更正数据库写法但是会导致V1.0用户的作物和种子丢失
- 完善我的农场图片资源,现在会在左上角显示经验、等级、金币等详细信息了
- 完善出售作物逻辑,现在可以空置作物名称来一键出售全部作物了,也可以选择空置数量来一键出售仓库种指定作物
- 完善播种逻辑,现在可以空置数量来一键播种指定作物了
- 新增更改农场名指令
- 改进对土地开垦条件判断
## V1.0
世界的起源。

View File

@ -1,5 +1,4 @@
from email.mime import base import os
from unittest import result
import httpx import httpx
@ -11,11 +10,11 @@ class CRequestManager:
@classmethod @classmethod
async def download(cls, url: str, savePath: str, fileName: str) -> bool: async def download(cls, url: str, savePath: str, fileName: str) -> bool:
"""下载文件到指定路径 """下载文件到指定路径并覆盖已存在的文件
Args: Args:
url (str): 文件的下载链接 url (str): 文件的下载链接
savePath (str): 保存文件的文件夹路径 savePath (str): 保存文件夹路径
fileName (str): 保存后的文件名 fileName (str): 保存后的文件名
Returns: Returns:
@ -25,7 +24,8 @@ class CRequestManager:
async with httpx.AsyncClient(timeout=10.0) as client: async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(url) response = await client.get(url)
if response.status_code == 200: if response.status_code == 200:
fullPath = savePath.rstrip("/") + "/" + fileName fullPath = os.path.join(savePath, fileName)
os.makedirs(os.path.dirname(fullPath), exist_ok=True)
with open(fullPath, "wb") as f: with open(fullPath, "wb") as f:
f.write(response.content) f.write(response.content)
return True return True

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB