diff --git a/__init__.py b/__init__.py index 76914e2..ff68aba 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,6 @@ from nonebot import get_driver from nonebot.plugin import PluginMetadata +from nonebot_plugin_apscheduler import scheduler from zhenxun.configs.utils import Command, PluginExtraData, RegisterConfig from zhenxun.services.log import logger @@ -89,3 +90,12 @@ async def shutdown(): await g_pSqlManager.cleanup() await g_pDBService.cleanup() + + +@scheduler.add_job( + trigger="cron", + hour=0, + minute=30, +) +async def _(): + await g_pJsonManager.initSignInFile() diff --git a/command.py b/command.py index 5ed1044..a024076 100644 --- a/command.py +++ b/command.py @@ -140,6 +140,7 @@ diuse_farm = on_alconna( #Subcommand("sell-point", Args["num?", int], help_text="转换金币") Subcommand("change-name", Args["name?", str], help_text="更改农场名"), Subcommand("sign-in", help_text="农场签到"), + Subcommand("admin-up", Args["num?", int], help_text="农场下阶段"), ), priority=5, block=True, @@ -513,6 +514,11 @@ async def _(session: Uninfo): message += f"\n\n成功领取累计签到奖励:\n额外获得经验{extraExp},额外获得金币{extraPoint}" + vipPoint = reward.get('vipPoint', 0) + + if vipPoint > 0: + message += f",额外获得点券{vipPoint}" + if plant: for key, value in plant.items(): message += f"\n获得{key}种子 * {value}" @@ -522,3 +528,19 @@ async def _(session: Uninfo): await MessageUtils.build_message(message).send() # await MessageUtils.alc_forward_msg([info], session.self_id, BotConfig.self_nickname).send(reply_to=True) + +diuse_farm.shortcut( + "农场下阶段(.*?)", + command="我的农场", + arguments=["admin-up"], + prefix=True, +) + +@diuse_farm.assign("admin-up") +async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)): + uid = str(session.user.id) + + if not await isRegisteredByUid(uid): + return + + await g_pDBService.userSoil.nextPhase(uid, num.result) diff --git a/config.py b/config.py index 7a7a2bc..5de0f55 100644 --- a/config.py +++ b/config.py @@ -2,6 +2,8 @@ from pathlib import Path from zhenxun.configs.path_config import DATA_PATH +g_bIsDebug = True + g_sDBPath = DATA_PATH / "farm_db" g_sDBFilePath = DATA_PATH / "farm_db/farm.db" diff --git a/database/plant.py b/database/plant.py index 216dc35..b562f9c 100644 --- a/database/plant.py +++ b/database/plant.py @@ -8,7 +8,7 @@ import aiosqlite from zhenxun.services.log import logger -from ..config import g_sPlantPath +from ..config import g_bIsDebug, g_sPlantPath class CPlantManager: @@ -27,7 +27,12 @@ class CPlantManager: async def init(cls) -> bool: try: _ = os.path.exists(g_sPlantPath) - cls.m_pDB = await aiosqlite.connect(str(g_sPlantPath)) + + if g_bIsDebug: + cls.m_pDB = await aiosqlite.connect(str(g_sPlantPath.parent / "plant-test.db")) + else: + cls.m_pDB = await aiosqlite.connect(str(g_sPlantPath)) + cls.m_pDB.row_factory = aiosqlite.Row return True except Exception as e: diff --git a/database/user.py b/database/user.py index efd12a0..ea201d5 100644 --- a/database/user.py +++ b/database/user.py @@ -3,8 +3,8 @@ from typing import List, Union from zhenxun.services.log import logger -from .database import CSqlManager from ..tool import g_pToolManager +from .database import CSqlManager class CUserDB(CSqlManager): @@ -16,6 +16,7 @@ class CUserDB(CSqlManager): "name": "TEXT NOT NULL", #农场名称 "exp": "INTEGER DEFAULT 0", #经验值 "point": "INTEGER DEFAULT 0", #金币 + "vipPoint": "INTEGER DEFAULT 0", #点券 "soil": "INTEGER DEFAULT 3", #解锁土地数量 "stealTime": "TEXT DEFAULT NULL", #偷菜时间字符串 "stealCount": "INTEGER DEFAULT 0" #剩余偷菜次数 @@ -203,6 +204,52 @@ class CUserDB(CSqlManager): logger.error("updateUserPointByUid 事务执行失败!", e=e) return False + @classmethod + async def getUserVipPointByUid(cls, uid: str) -> int: + """获取指定用户点券 + + Args: + uid (str): 用户Uid + + Returns: + int: 点券数量,失败返回 -1 + """ + if not uid: + return -1 + try: + async with cls.m_pDB.execute( + "SELECT vipPoint FROM user WHERE uid = ?", (uid,) + ) as cursor: + row = await cursor.fetchone() + return int(row[0]) if row and row[0] is not None else -1 + except Exception as e: + logger.warning("getUservipPointByUid 查询失败!", e=e) + return -1 + + @classmethod + async def updateUserVipPointByUid(cls, uid: str, vipPoint: int) -> bool: + """根据用户Uid更新农场币数量 + + Args: + uid (str): 用户Uid + vipPoint (int): 新农场币数量 + + Returns: + bool: 是否更新成功 + """ + if not uid or vipPoint < 0: + logger.warning("updateUservipPointByUid 参数校验失败!") + return False + try: + async with cls._transaction(): + await cls.m_pDB.execute( + "UPDATE user SET vipPoint = ? WHERE uid = ?", (vipPoint, uid) + ) + return True + except Exception as e: + logger.error("updateUservipPointByUid 事务执行失败!", e=e) + return False + @classmethod async def getUserExpByUid(cls, uid: str) -> int: """获取指定用户经验值 diff --git a/database/userSign.py b/database/userSign.py index dea9c8e..c50fe32 100644 --- a/database/userSign.py +++ b/database/userSign.py @@ -6,6 +6,7 @@ from typing import Optional from zhenxun.services.log import logger from zhenxun.utils._build_image import BuildImage +from ..config import g_bIsDebug from ..dbService import g_pDBService from ..json import g_pJsonManager from ..tool import g_pToolManager @@ -145,6 +146,7 @@ class CUserSignDB(CSqlManager): exp = random.randint(expMin, expMax) point = random.randint(pointMin, pointMax) + vipPoint = 0 async with cls._transaction(): await cls.m_pDB.execute( @@ -193,6 +195,7 @@ class CUserSignDB(CSqlManager): if reward: point += reward.get('point', 0) exp += reward.get('exp', 0) + vipPoint = reward.get('vipPoint', 0) plant = reward.get('plant', {}) @@ -200,6 +203,9 @@ class CUserSignDB(CSqlManager): for key, value in plant.items(): await g_pDBService.userSeed.addUserSeedByUid(uid, key, value) + if g_bIsDebug: + exp += 9999 + #向数据库更新 currentExp = await g_pDBService.user.getUserExpByUid(uid) await g_pDBService.user.updateUserExpByUid(uid, currentExp + exp) @@ -207,6 +213,10 @@ class CUserSignDB(CSqlManager): currentPoint = await g_pDBService.user.getUserPointByUid(uid) await g_pDBService.user.updateUserPointByUid(uid, currentPoint + point) + if vipPoint > 0: + currentVipPoint = await g_pDBService.user.getUserVipPointByUid(uid) + await g_pDBService.user.updateUserVipPointByUid(uid, currentVipPoint + vipPoint) + return 1 except Exception as e: logger.warning("执行签到失败", e=e) diff --git a/database/userSoil.py b/database/userSoil.py index 9702930..3330b71 100644 --- a/database/userSoil.py +++ b/database/userSoil.py @@ -2,6 +2,7 @@ from typing import Optional from zhenxun.services.log import logger +from ..config import g_bIsDebug from ..dbService import g_pDBService from ..json import g_pJsonManager from ..tool import g_pToolManager @@ -29,6 +30,46 @@ class CUserSoilDB(CSqlManager): await cls.ensureTableSchema("userSoil", userSoil) + @classmethod + async def nextPhase(cls, uid: str, soilIndex: int): + """将指定地块的作物进入下个阶段 + + Args: + soilIndex (int): 地块索引 从1开始 + """ + if not g_bIsDebug: + return + + soilInfo = await cls.getUserSoil(uid, soilIndex) + + if not soilInfo: + return + + plantInfo = await g_pDBService.plant.getPlantByName(soilInfo['plantName']) + + if not plantInfo: + return + + currentTime = g_pToolManager.dateTime().now() + matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime'])) + + phase = await g_pDBService.plant.getPlantPhaseNumberByName(soilInfo['plantName']) + phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName']) + + if currentTime >= matureTime: + return + + plantedTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['plantTime'])) + + elapsedTime = currentTime - plantedTime + elapsedHour = elapsedTime.total_seconds() / 3600 + + currentStage = int(elapsedHour / (plantInfo['time'] / phase)) + + t = int(soilInfo['plantTime']) - phaseList[currentStage] + + await cls.updateUserSoil(uid, soilIndex, "plantTime", t) + @classmethod async def getUserFarmByUid(cls, uid: str) -> dict: """获取指定用户的旧农场数据 diff --git a/farm/farm.py b/farm/farm.py index fac1c10..d773344 100644 --- a/farm/farm.py +++ b/farm/farm.py @@ -11,7 +11,7 @@ from zhenxun.utils.enum import GoldHandle from zhenxun.utils.image_utils import ImageTemplate from zhenxun.utils.platform import PlatformUtils -from ..config import g_sResourcePath +from ..config import g_bIsDebug, g_sResourcePath from ..dbService import g_pDBService from ..event.event import g_pEventManager from ..json import g_pJsonManager @@ -88,11 +88,11 @@ class CFarmManager: if index < soilUnlock: await img.paste(soil, (x, y)) - isPlant, plant, isRipe= await cls.drawSoilPlant(uid, index + 1) + isPlant, plant, isRipe, offsetX, offsetY = await cls.drawSoilPlant(uid, index + 1) if isPlant: - await img.paste(plant, (x + soilSize[0] // 2 - plant.width // 2, - y + soilSize[1] // 2 - plant.height // 2)) + await img.paste(plant, (x + soilSize[0] // 2 - plant.width // 2 + offsetX, + y + soilSize[1] // 2 - plant.height // 2 + offsetY)) #1700 275 #首次添加可收获图片 @@ -258,7 +258,7 @@ class CFarmManager: return info @classmethod - async def drawSoilPlant(cls, uid: str, soilIndex: int) -> tuple[bool, BuildImage, bool]: + async def drawSoilPlant(cls, uid: str, soilIndex: int) -> tuple[bool, BuildImage, bool, int, int]: """绘制植物资源 Args: @@ -279,13 +279,18 @@ class CFarmManager: if int(soilInfo.get("wiltStatus", 0)) == 1: plant = BuildImage(background = g_sResourcePath / f"plant/basic/9.png") await plant.resize(0, 150, 212) - return True, plant, False + return True, plant, False, 0, 0 #获取作物详细信息 plantInfo = await g_pDBService.plant.getPlantByName(soilInfo['plantName']) if not plantInfo: logger.error(f"绘制植物资源失败: {soilInfo['plantName']}") - return False, None, False #type: ignore + return False, None, False, 0, 0 #type: ignore + + offsetX = plantInfo.get('officX', 0) + offsetY = plantInfo.get('officY', 0) + offsetW = plantInfo.get('officW', 0) + offsetH = plantInfo.get('officH', 0) currentTime = g_pToolManager.dateTime().now() matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime'])) @@ -296,13 +301,13 @@ class CFarmManager: if currentTime >= matureTime: plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase}.png") - return True, plant, True + return True, plant, True, offsetX, offsetY else: #如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片 # 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, offsetX, offsetY #如果没有成熟 则根据当前阶段进行绘制 plantedTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['plantTime'])) @@ -318,11 +323,11 @@ class CFarmManager: else: plant = BuildImage(background = g_sResourcePath / f"plant/basic/0.png") - await plant.resize(0, 35, 58) + await plant.resize(0, 35 + offsetW, 58 + offsetH) else: plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{currentStage}.png") - return True, plant, False + return True, plant, False, offsetX, offsetY @classmethod async def getUserSeedByUid(cls, uid: str) -> bytes: @@ -568,6 +573,9 @@ class CFarmManager: experience += 3 + if g_bIsDebug: + experience += 999 + #批量更新数据库操作 await g_pDBService.userSoil.deleteUserSoil(uid, i) @@ -775,13 +783,13 @@ class CFarmManager: str = "" if len(item) == 0: - str = f"下次升级所需条件:等级:{level},农场币:{point}" + str = f"下次开垦所需条件:等级:{level},农场币:{point}" else: - str = f"下次升级所需条件:等级:{level},农场币:{point},物品:{item}" + str = f"下次开垦所需条件:等级:{level},农场币:{point},物品:{item}" return str except Exception as e: - return "获取升级土地条件失败!" + return "获取开垦土地条件失败!" @classmethod async def reclamation(cls, uid: str) -> str: diff --git a/json.py b/json.py index 15ecf7e..ad68b1e 100644 --- a/json.py +++ b/json.py @@ -24,12 +24,7 @@ class CJsonManager: if not await self.initSoil(): return False - if not await g_pRequestManager.initSignInFile(): - config.g_bSignStatus = False - - return False - else: - return await self.initSign() + return await self.initSignInFile() async def initItem(self) -> bool: try: @@ -79,6 +74,14 @@ class CJsonManager: logger.warning(f"soil.json JSON格式错误: {e}") return False + async def initSignInFile(self) -> bool: + if not await g_pRequestManager.initSignInFile(): + config.g_bSignStatus = False + + return False + else: + return await self.initSign() + async def initSign(self) -> bool: try: with open( diff --git a/log/log.md b/log/log.md index b0243c3..27560ff 100644 --- a/log/log.md +++ b/log/log.md @@ -12,7 +12,7 @@ --- - 修正了多阶段作物成长素材计算逻辑 - 修正了作物数据库字段错乱的问题 -- 作物新增offset字段,用于以后偏移坐标(尚未加入代码 TODO +- 作物新增offset字段,用于以后偏移坐标 ## V1.3 用户方面 diff --git a/resource/db/plant-test.db b/resource/db/plant-test.db new file mode 100644 index 0000000..1e3d4d1 Binary files /dev/null and b/resource/db/plant-test.db differ diff --git a/resource/db/plant.db b/resource/db/plant.db index a861423..87d6986 100644 Binary files a/resource/db/plant.db and b/resource/db/plant.db differ diff --git a/resource/plant/园艺世/1.png b/resource/plant/园艺世/1.png new file mode 100644 index 0000000..9b88efa Binary files /dev/null and b/resource/plant/园艺世/1.png differ diff --git a/resource/plant/园艺世/2.png b/resource/plant/园艺世/2.png new file mode 100644 index 0000000..9770149 Binary files /dev/null and b/resource/plant/园艺世/2.png differ diff --git a/resource/plant/园艺世/3.png b/resource/plant/园艺世/3.png new file mode 100644 index 0000000..af474c3 Binary files /dev/null and b/resource/plant/园艺世/3.png differ diff --git a/resource/plant/园艺世/4.png b/resource/plant/园艺世/4.png new file mode 100644 index 0000000..cc1943e Binary files /dev/null and b/resource/plant/园艺世/4.png differ diff --git a/resource/plant/园艺世/5.png b/resource/plant/园艺世/5.png new file mode 100644 index 0000000..b6fa942 Binary files /dev/null and b/resource/plant/园艺世/5.png differ diff --git a/resource/plant/园艺世/icon.png b/resource/plant/园艺世/icon.png new file mode 100644 index 0000000..e7990d8 Binary files /dev/null and b/resource/plant/园艺世/icon.png differ diff --git a/resource/plant/蜜思桃/1.png b/resource/plant/蜜思桃/1.png new file mode 100644 index 0000000..55fb940 Binary files /dev/null and b/resource/plant/蜜思桃/1.png differ diff --git a/resource/plant/蜜思桃/2.png b/resource/plant/蜜思桃/2.png new file mode 100644 index 0000000..00fdd1e Binary files /dev/null and b/resource/plant/蜜思桃/2.png differ diff --git a/resource/plant/蜜思桃/3.png b/resource/plant/蜜思桃/3.png new file mode 100644 index 0000000..d06c7ec Binary files /dev/null and b/resource/plant/蜜思桃/3.png differ diff --git a/resource/plant/蜜思桃/4.png b/resource/plant/蜜思桃/4.png new file mode 100644 index 0000000..412f9c8 Binary files /dev/null and b/resource/plant/蜜思桃/4.png differ diff --git a/resource/plant/蜜思桃/5.png b/resource/plant/蜜思桃/5.png new file mode 100644 index 0000000..1c7ea90 Binary files /dev/null and b/resource/plant/蜜思桃/5.png differ diff --git a/resource/plant/蜜思桃/icon.png b/resource/plant/蜜思桃/icon.png new file mode 100644 index 0000000..fff083d Binary files /dev/null and b/resource/plant/蜜思桃/icon.png differ diff --git a/resource/plant/香粽龙舟/0.png b/resource/plant/香粽龙舟/0.png new file mode 100644 index 0000000..2feafb4 Binary files /dev/null and b/resource/plant/香粽龙舟/0.png differ diff --git a/resource/plant/香粽龙舟/1.png b/resource/plant/香粽龙舟/1.png index 2feafb4..64b9a2a 100644 Binary files a/resource/plant/香粽龙舟/1.png and b/resource/plant/香粽龙舟/1.png differ diff --git a/resource/plant/香粽龙舟/2.png b/resource/plant/香粽龙舟/2.png index 64b9a2a..e090a79 100644 Binary files a/resource/plant/香粽龙舟/2.png and b/resource/plant/香粽龙舟/2.png differ diff --git a/resource/plant/香粽龙舟/3.png b/resource/plant/香粽龙舟/3.png index e090a79..8619dec 100644 Binary files a/resource/plant/香粽龙舟/3.png and b/resource/plant/香粽龙舟/3.png differ diff --git a/resource/plant/香粽龙舟/4.png b/resource/plant/香粽龙舟/4.png index 8619dec..f857a33 100644 Binary files a/resource/plant/香粽龙舟/4.png and b/resource/plant/香粽龙舟/4.png differ diff --git a/resource/plant/香粽龙舟/5.png b/resource/plant/香粽龙舟/5.png deleted file mode 100644 index f857a33..0000000 Binary files a/resource/plant/香粽龙舟/5.png and /dev/null differ diff --git a/resource/plant/香粽龙舟/icon.png b/resource/plant/香粽龙舟/icon.png new file mode 100644 index 0000000..4328b05 Binary files /dev/null and b/resource/plant/香粽龙舟/icon.png differ