📝 加入开垦条件

 新增偷菜功能
🐛 修复购买种子时没有判断等级的BUG
This commit is contained in:
Art_Sakura 2025-03-21 18:14:50 +08:00
parent f50b5f582d
commit 98ae76560b
6 changed files with 343 additions and 117 deletions

View File

@ -27,7 +27,8 @@ __plugin_meta__ = PluginMetadata(
铲除
我的作物
出售作物 [作物/种子名称] [数量]
购买农场币 [数量]
偷菜 at
购买农场币 [数量] 金币转换农场币比率是 1 : 2
""".strip(),
extra=PluginExtraData(
author="Art_Sakura",

View File

@ -1,6 +1,7 @@
from nonebot.rule import to_me
from nonebot_plugin_alconna import (Alconna, AlconnaQuery, Args, Match, Option,
Query, Subcommand, on_alconna, store_true)
from nonebot_plugin_alconna import (Alconna, AlconnaQuery, Args, At, Match,
MultiVar, Option, Query, Subcommand,
on_alconna, store_true)
from nonebot_plugin_uninfo import Uninfo
from zhenxun.services.log import logger
@ -43,10 +44,11 @@ diuse_farm = on_alconna(
Subcommand("eradicate", help_text="铲除"),
Subcommand("my-plant", help_text="我的作物"),
Subcommand("sell-plant", Args["name?", str]["num?", int], help_text="出售作物"),
Subcommand("buy-point", Args["num?", int], help_text="购买农场币")
Subcommand("stealing", Args["target?", At], help_text="偷菜"),
Subcommand("buy-point", Args["num?", int], help_text="购买农场币"),
#Subcommand("sell-point", Args["num?", int], help_text="转换金币")
),
priority=5,
rule=to_me(),
block=True,
)
@ -246,7 +248,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n
await MessageUtils.build_message("尚未开通农场").send()
return None
result = await g_pFarmManager.sellPlantByUid(uid, name.result, num.result)
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
diuse_farm.shortcut(
@ -256,7 +258,7 @@ diuse_farm.shortcut(
prefix=True,
)
@diuse_farm.assign("sell-plant")
@diuse_farm.assign("buy-point")
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
if num.result <= 0:
await MessageUtils.build_message(
@ -273,5 +275,31 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
result = await g_pFarmManager.buyPointByUid(uid, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
diuse_farm.shortcut(
"偷菜",
command="我的农场",
arguments=["stealing"],
prefix=True,
)
@diuse_farm.assign("stealing")
async def _(session: Uninfo, target: Match[At]):
uid = str(session.user.id)
point = await g_pSqlManager.getUserPointByUid(uid)
if point < 0:
await MessageUtils.build_message("尚未开通农场").send()
return None
if not target.available:
await MessageUtils.build_message("请在指令后跟需要at的人").finish(reply_to=True)
tar = target.result
point = await g_pSqlManager.getUserPointByUid(tar.target)
if point < 0:
await MessageUtils.build_message("尚未开通农场").send()
return None
result = await g_pFarmManager.stealing(uid, tar.target)
await MessageUtils.build_message(result).send(reply_to=True)

View File

@ -19,7 +19,87 @@
},
"soil":[1, 1, 1, 2, 3, 5, 7, 9, 12, 15,
18, 21, 25, 29, 33, 38, 43, 48, 54, 60,
66, 72, 78, 85, 92, 99, 106, 114, 120, 130],
"point":[0, 2000, 5000, 10000, 30000, 50000]
66, 72, 78, 85, 92, 99, 106, 114, 120, 130
],
"reclamation":
{
"4":
{
"level": 3,
"point": 800,
"item": ""
},
"5":
{
"level": 5,
"point": 1300,
"item": ""
},
"6":
{
"level": 7,
"point": 3200,
"item": ""
},
"7":
{
"level": 9,
"point": 5500,
"item": ""
},
"8":
{
"level": 12,
"point": 12000,
"item": ""
},
"9":
{
"level": 15,
"point": 19800,
"item": ""
},
"10":
{
"level":3,
"point": 3000,
"item": ""
},
"11":
{
"level":3,
"point": 3000,
"item": ""
},
"12":
{
"level":3,
"point": 3000,
"item": ""
},
"13":
{
"level":3,
"point": 3000,
"item": ""
},
"14":
{
"level":3,
"point": 3000,
"item": ""
},
"15":
{
"level":3,
"point": 3000,
"item": ""
},
"16":
{
"level":3,
"point": 3000,
"item": ""
}
}
}

View File

@ -1,5 +1,5 @@
import os
from datetime import datetime, timedelta
from datetime import date, datetime, timedelta
from io import StringIO
from math import e
from typing import Any, List, Optional
@ -47,7 +47,9 @@ class CSqlManager:
uid INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
exp INTEGER DEFAULT 0,
point INTEGER DEFAULT 0
point INTEGER DEFAULT 0,
soil INTEGER DEFAULT 3,
stealing TEXT DEFAULT NULL
);
"""
@ -120,7 +122,7 @@ class CSqlManager:
#用户信息
userInfo = f"""
INSERT INTO user (uid, name, exp, point) VALUES ({uid}, '{name}', {str(exp)}, {str(point)})
INSERT INTO user (uid, name, exp, point, soil, stealing) VALUES ({uid}, '{name}', {exp}, {point}, 3, '{date.today()}|5')
"""
#用户仓库
@ -145,7 +147,7 @@ class CSqlManager:
return True
@classmethod
async def getUserInfoByUid(cls, uid: str) -> list[dict]:
async def getUserInfoByUid(cls, uid: str) -> dict:
"""根据用户Uid获取用户信息
Args:
@ -155,27 +157,27 @@ class CSqlManager:
list[dict]: 用户信息
"""
if len(uid) <= 0:
return []
return {}
try:
async with cls.m_pDB.execute(
"SELECT * FROM user WHERE uid = ?", (uid,)
) as cursor:
results = []
async for row in cursor:
user_dict = {
userDict = {
"uid": row[0],
"name": row[1],
"exp": row[2],
"point": row[3],
"soil": row[4],
"stealing": row[5]
}
results.append(user_dict)
return results
return userDict
return {}
except Exception as e:
logger.warning(f"getUserInfoByUid查询失败: {e}")
return []
return {}
@classmethod
async def getUserPointByUid(cls, uid: str) -> int:
@ -318,18 +320,16 @@ class CSqlManager:
int: 解锁几块地
"""
if len(uid) <= 0:
return -1
return 0
level = await cls.getUserLevelByUid(uid)
soilNumber = 0
soil_list = g_pJsonManager.m_pLevel['soil'] # type: ignore
async with cls.m_pDB.execute(f"SELECT soil FROM user WHERE uid = '{uid}'") as cursor:
async for row in cursor:
if row[0] == None or len(row[0]) <= 0:
return 0
else:
return int(row[0])
#获取解锁地块
for soil in soil_list:
if level >= soil:
soilNumber += 1
return soilNumber
return 0
@classmethod
async def getUserSoilStatusBySoilID(cls, uid: str, soil: str) -> tuple[bool, str]:
@ -355,7 +355,9 @@ class CSqlManager:
return False, ""
@classmethod
async def updateUserSoilStatusByPlantName(cls, uid: str, soil: str, plant: str = "", status: int = 0) -> bool:
async def updateUserSoilStatusByPlantName(cls, uid: str, soil: str,
plant: str = "",
status: int = 0) -> bool:
"""根据种子名称使用户播种
Args:
@ -371,7 +373,7 @@ class CSqlManager:
return False
if len(plant) <= 0 and status == 4:
s = f",,,{status}"
s = f",,,{status},"
elif len(plant) <= 0 and status != 4:
s = ""
else:
@ -381,8 +383,8 @@ class CSqlManager:
currentTime = datetime.now()
newTime = currentTime + timedelta(minutes=int(plantInfo['time']))
#种子名称种下时间预计成熟时间地状态0无 1长草 2生虫 3缺水 4枯萎状态
s = f"{plant},{int(currentTime.timestamp())},{int(newTime.timestamp())},{status}"
#种子名称种下时间预计成熟时间地状态0无 1长草 2生虫 3缺水 4枯萎,是否被偷 示例QQ号-偷取数量|QQ号-偷取数量
s = f"{plant},{int(currentTime.timestamp())},{int(newTime.timestamp())},{status},"
sql = f"UPDATE soil SET {soil} = '{s}' WHERE uid = '{uid}'"

View File

@ -1,9 +1,10 @@
import asyncio
from datetime import datetime
import random
from datetime import date, datetime
from io import StringIO
from math import exp
from typing import Dict, List, Tuple
from Python311.Lib.PIL.ImImagePlugin import number
from zhenxun.models.user_console import UserConsole
from zhenxun.services.log import logger
from zhenxun.utils._build_image import BuildImage
@ -31,10 +32,9 @@ class CFarmManager:
p = await g_pSqlManager.getUserPointByUid(uid)
await g_pSqlManager.updateUserPointByUid(uid, point + p)
return f"充值{num}农场币成功,当前农场币:{point + p}"
await g_pSqlManager.updateUserPointByUid(uid, num + p)
return f"充值{num}农场币成功,当前农场币:{num + p}"
@classmethod
async def drawFarmByUid(cls, uid: str) -> bytes:
@ -60,19 +60,19 @@ class CFarmManager:
await grass.resize(0, soilSize[0], soilSize[1])
soilPos = g_pJsonManager.m_pSoil['soil'] # type: ignore
soilUnlock = g_pJsonManager.m_pLevel['soil'] # type: ignore
soilUnlock = await g_pSqlManager.getUserSoilByUid(uid)
x = 0
y = 0
isFirstExpansion = True #首次添加扩建图片
isFirstRipe = True
plant = None
for index, level in enumerate(soilUnlock):
for index in range(0, 30):
x = soilPos[str(index + 1)]['x']
y = soilPos[str(index + 1)]['y']
#如果土地已经到达对应等级
if soilNumber >= int(level):
if index > soilUnlock:
await img.paste(soil, (x, y))
isPlant, plant, isRipe= await cls.drawSoilPlant(uid, f"soil{str(index + 1)}")
@ -285,7 +285,7 @@ class CFarmManager:
)
if num > 0:
return f"播种数量超出解锁土地数量,已将可播种土地成功播种{name}!仓库还剩下{plantDict[name]}个种子"
return f"播种数量超出开垦土地数量,已将可播种土地成功播种{name}!仓库还剩下{plantDict[name]}个种子"
else:
return f"播种{name}成功!仓库还剩下{plantDict[name]}个种子"
@ -300,19 +300,18 @@ class CFarmManager:
str: 返回
"""
soilNumber = await g_pSqlManager.getUserLevelByUid(uid)
soilUnlock = g_pJsonManager.m_pLevel['soil'] # type: ignore
soilUnlock = await g_pSqlManager.getUserSoilByUid(uid)
plant = {}
soilNames = [f"soil{i + 1}" for i, level in enumerate(soilUnlock) if soilNumber >= level]
soilNames = [f"soil{i}" for i in range(soilUnlock)]
soilStatuses = await asyncio.gather(*[
g_pSqlManager.getUserSoilStatusBySoilID(uid, name)
for name in soilNames
])
plant: Dict[str, int] = {}
harvest_records: List[str] = []
harvestRecords: List[str] = []
experience = 0
for (soil_name, (status, info)) in zip(soilNames, soilStatuses):
@ -325,15 +324,24 @@ class CFarmManager:
matureTime = datetime.fromtimestamp(int(soilInfo[2]))
if currentTime >= matureTime:
plant[plantId] = plant.get(plantId, 0) + plantInfo['harvest']
experience += plantInfo['experience']
harvest_records.append(f"收获作物:{plantId},数量为:{plantInfo['harvest']},经验为:{plantInfo['experience']}")
number = plantInfo['harvest']
# 批量更新数据库操作
#判断该土地作物是否被透过
if len(soilInfo[4]) > 0:
stealingStatus = soilInfo[4].split('|')
for isUser in stealingStatus:
user = isUser.split('-')
number -= user[1]
plant[plantId] = plant.get(plantId, 0) + number
experience += plantInfo['experience']
harvestRecords.append(f"收获作物:{plantId},数量为:{number},经验为:{plantInfo['experience']}")
#批量更新数据库操作
await g_pSqlManager.updateUserSoilStatusByPlantName(uid, soil_name, "", 4)
if experience > 0:
harvest_records.append(f"\t累计获得经验:{experience}")
harvestRecords.append(f"\t累计获得经验:{experience}")
exp = await g_pSqlManager.getUserExpByUid(uid)
await g_pSqlManager.UpdateUserExpByUid(uid, exp + experience)
@ -346,7 +354,7 @@ class CFarmManager:
','.join([f"{k}|{v}" for k, v in plant.items()])
)
return "\n".join(harvest_records)
return "\n".join(harvestRecords)
@classmethod
async def eradicate(cls, uid: str) -> str:
@ -359,10 +367,9 @@ class CFarmManager:
str: 返回
"""
soilNumber = await g_pSqlManager.getUserLevelByUid(uid)
soilUnlock = g_pJsonManager.m_pLevel['soil'] # type: ignore
soilUnlock = await g_pSqlManager.getUserSoilByUid(uid)
soilNames = [f"soil{i + 1}" for i, level in enumerate(soilUnlock) if soilNumber >= level]
soilNames = [f"soil{i}" for i in range(soilUnlock)]
soilStatuses = await asyncio.gather(*[
g_pSqlManager.getUserSoilStatusBySoilID(uid, name)
for name in soilNames
@ -436,13 +443,15 @@ class CFarmManager:
else:
sell = "不可以"
number = count * int(plantInfo['price'])
data_list.append(
[
icon,
plantName,
count,
plantInfo['price'],
count * int(plantInfo['price']),
number,
sell
]
)
@ -460,82 +469,106 @@ class CFarmManager:
return result.pic2bytes()
@classmethod
async def sellPlantByUid(cls, uid: str, name: str = "", num: int = 1) -> str:
"""出售作物
async def stealing(cls, uid: str, target: str) -> str:
"""偷菜
Args:
uid (str): 用户Uid
target (str): 被偷用户Uid
Returns:
str:
str: 返回
"""
plant = await g_pSqlManager.getUserPlantByUid(uid)
#用户信息
userInfo = await g_pSqlManager.getUserInfoByUid(uid)
#用户可偷次数
userStealing = userInfo["stealing"].split('|')
if plant == None:
return "你仓库没有可以出售的作物"
if date.fromisoformat(userStealing[0]) != date.today():
userStealing[0] = date.today()
userStealing[1] = 5
point = 0
totalSold = 0
remainingItems = []
if int(userStealing[1]) <= 0:
return "你今天可偷次数到达上限啦,手下留情吧"
items = plant.split(',')
if len(name) <= 0:
#出售全部
for item in items:
if '|' in item:
plant_name, count_str = item.split('|', 1)
try:
count = int(count_str)
plant_info = g_pJsonManager.m_pPlant['plant'][plant_name] # type: ignore
point += plant_info['price'] * count
except Exception:
#获取用户
soilUnlock = int(userInfo["soil"])
plant = {}
#根据解锁土地,获取每块土地状态信息
soilNames = [f"soil{i}" for i in range(soilUnlock)]
soilStatuses = await asyncio.gather(*[
g_pSqlManager.getUserSoilStatusBySoilID(target, name)
for name in soilNames
])
plant: Dict[str, int] = {}
harvestRecords: List[str] = []
isStealing = False
for(soilName, (status, info)) in zip(soilNames, soilStatuses):
isStealing = False
if not status:
soilInfo = info.split(',')
plantId = soilInfo[0]
plantInfo = g_pJsonManager.m_pPlant['plant'][plantId] # type: ignore
currentTime = datetime.now()
matureTime = datetime.fromtimestamp(int(soilInfo[2]))
stealingNumber = 0
if currentTime >= matureTime:
#先获取用户是否偷过该土地
stealingStatus = soilInfo[4].split('|')
for isUser in stealingStatus:
user = isUser.split('-')
if user[0] == uid:
isStealing = True
break
stealingNumber += int(user[1])
#如果偷过,则跳过该土地
if isStealing:
continue
await g_pSqlManager.updateUserPlantByUid(uid, "") # 清空仓库
stealingNumber -= plantInfo['harvest']
randomNumber = random.choice([1, 2])
randomNumber = min(randomNumber, stealingNumber)
if randomNumber > 0:
plant[plantId] = plant.get(plantId, 0) + randomNumber
harvestRecords.append(f"成功偷到作物:{plantId},数量为:{randomNumber}")
stealingStatus += f"|{uid}-{randomNumber}"
#如果将作物偷完,就直接更新状态 并记录用户偷取过
if plantInfo['harvest'] - randomNumber + stealingNumber == 0:
sql = f"UPDATE soil SET {soilName} = ',,,4,{stealingStatus}' WHERE uid = '{target}'"
else:
sql = f"UPDATE soil SET {soilName} = '{soilInfo[0]},{soilInfo[1]},{soilInfo[2]},{soilInfo[3]},{stealingStatus}' WHERE uid = '{target}'"
await g_pSqlManager.executeDB(sql)
if not plant:
return "目标没有作物可以被偷"
else:
for item in items:
if '|' in item:
plantName, countStr = item.split('|', 1)
try:
count = int(countStr)
if plantName == name:
sellAmount = min(num, count)
totalSold += sellAmount
remaining = count - sellAmount
# 批量更新用户作物仓库数据
await g_pSqlManager.updateUserPlantByUid(target, ','.join([f"{k}|{v}" for k, v in plant.items()]))
if remaining > 0:
remainingItems.append(f"{plantName}|{remaining}")
userStealing[1] = int(userStealing[1]) - 1
num -= sellAmount
if num == 0:
break
except (ValueError, TypeError):
continue
sql = f"UPDATE user SET stealing = {'|'.join(userStealing)} WHERE uid = {uid}"
if num > 0:
return f"出售作物{name}出错:数量不足"
#计算收益
try:
plantInfo = g_pJsonManager.m_pPlant['plant'][name] # type: ignore
totalPoint = plantInfo['price'] * totalSold
except KeyError:
return f"出售作物{name}出错:作物不存在"
#更新剩余作物
remainingPlant = ','.join(remainingItems) if remainingItems else ""
await g_pSqlManager.updateUserPlantByUid(uid, remainingPlant)
#更新农场币
p = await g_pSqlManager.getUserPointByUid(uid)
await g_pSqlManager.updateUserPointByUid(uid, p + totalPoint)
if name:
return f"成功出售{name},获得农场币:{totalPoint}"
else:
return f"成功出售所有作物,获得农场币:{totalPoint}"
#更新用户每日偷取次数
await g_pSqlManager.executeDB(sql)
return "\n".join(harvestRecords)
g_pFarmManager = CFarmManager()

View File

@ -92,6 +92,12 @@ class CShopManager:
except Exception as e:
return "购买出错!请检查需购买的种子名称!"
level = g_pSqlManager.getUserLevelByUid(uid)
if level < plantInfo['level']:
return "你的等级不够哦,努努力吧"
userPlants = {}
point = await g_pSqlManager.getUserPointByUid(uid)
@ -122,5 +128,81 @@ class CShopManager:
return f"成功购买{name},当前仓库数量为:{userPlants[name]},花费{total}农场币, 剩余{point - total}农场币"
@classmethod
async def sellPlantByUid(cls, uid: str, name: str = "", num: int = 1) -> str:
"""出售作物
Args:
uid (str): 用户Uid
Returns:
str:
"""
plant = await g_pSqlManager.getUserPlantByUid(uid)
if plant == None:
return "你仓库没有可以出售的作物"
point = 0
totalSold = 0
remainingItems = []
items = plant.split(',')
if len(name) <= 0:
#出售全部
for item in items:
if '|' in item:
plant_name, count_str = item.split('|', 1)
try:
count = int(count_str)
plant_info = g_pJsonManager.m_pPlant['plant'][plant_name] # type: ignore
point += plant_info['price'] * count
except Exception:
continue
await g_pSqlManager.updateUserPlantByUid(uid, "") # 清空仓库
else:
for item in items:
if '|' in item:
plantName, countStr = item.split('|', 1)
try:
count = int(countStr)
if plantName == name:
sellAmount = min(num, count)
totalSold += sellAmount
remaining = count - sellAmount
if remaining > 0:
remainingItems.append(f"{plantName}|{remaining}")
num -= sellAmount
if num == 0:
break
except (ValueError, TypeError):
continue
if num > 0:
return f"出售作物{name}出错:数量不足"
#计算收益
try:
plantInfo = g_pJsonManager.m_pPlant['plant'][name] # type: ignore
totalPoint = plantInfo['price'] * totalSold
except KeyError:
return f"出售作物{name}出错:作物不存在"
#更新剩余作物
remainingPlant = ','.join(remainingItems) if remainingItems else ""
await g_pSqlManager.updateUserPlantByUid(uid, remainingPlant)
#更新农场币
p = await g_pSqlManager.getUserPointByUid(uid)
await g_pSqlManager.updateUserPointByUid(uid, p + totalPoint)
if name:
return f"成功出售{name},获得农场币:{totalPoint}"
else:
return f"成功出售所有作物,获得农场币:{totalPoint}"
g_pShopManager = CShopManager()