继续更新UI
This commit is contained in:
1065
SproutFarm-Backend/module/ConsoleCommandsAPI.py
Normal file
1065
SproutFarm-Backend/module/ConsoleCommandsAPI.py
Normal file
File diff suppressed because it is too large
Load Diff
183
SproutFarm-Backend/module/NetworkCore.py
Normal file
183
SproutFarm-Backend/module/NetworkCore.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""
|
||||
网络通信核心模块
|
||||
====================================================================
|
||||
- 负责处理客户端与服务端之间的消息路由
|
||||
- 将消息类型映射到对应的处理函数
|
||||
- 提供统一的消息处理接口
|
||||
====================================================================
|
||||
"""
|
||||
|
||||
class MessageHandler:
|
||||
"""
|
||||
消息处理器类
|
||||
负责将客户端消息路由到对应的处理函数
|
||||
"""
|
||||
|
||||
def __init__(self, server_instance):
|
||||
"""
|
||||
初始化消息处理器
|
||||
|
||||
Args:
|
||||
server_instance: 服务器实例,用于调用具体的处理方法
|
||||
"""
|
||||
self.server = server_instance
|
||||
|
||||
def handle_message(self, client_id, message):
|
||||
"""
|
||||
接收客户端消息并路由到对应处理函数
|
||||
这是服务端与客户端通信的核心中的核心
|
||||
|
||||
Args:
|
||||
client_id: 客户端ID
|
||||
message: 消息内容(字典格式)
|
||||
|
||||
Returns:
|
||||
处理结果
|
||||
"""
|
||||
message_type = message.get("type", "")
|
||||
|
||||
# 用户认证相关
|
||||
if message_type == "greeting": # 默认欢迎
|
||||
return self.server._handle_greeting(client_id, message)
|
||||
elif message_type == "login": # 玩家登录
|
||||
return self.server._handle_login(client_id, message)
|
||||
elif message_type == "register": # 玩家注册
|
||||
return self.server._handle_register(client_id, message)
|
||||
elif message_type == "request_verification_code": # 验证码请求
|
||||
return self.server._handle_verification_code_request(client_id, message)
|
||||
elif message_type == "request_forget_password_verification_code": # 忘记密码验证码请求
|
||||
return self.server._handle_forget_password_verification_code_request(client_id, message)
|
||||
elif message_type == "reset_password": # 重置密码
|
||||
return self.server._handle_reset_password_request(client_id, message)
|
||||
elif message_type == "verify_code": # 验证码
|
||||
return self.server._handle_verify_code(client_id, message)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 游戏操作相关
|
||||
elif message_type == "harvest_crop": # 收获作物
|
||||
return self.server._handle_harvest_crop(client_id, message)
|
||||
elif message_type == "plant_crop": # 种植作物
|
||||
return self.server._handle_plant_crop(client_id, message)
|
||||
elif message_type == "buy_seed": # 购买种子
|
||||
return self.server._handle_buy_seed(client_id, message)
|
||||
elif message_type == "buy_item": # 购买道具
|
||||
return self.server._handle_buy_item(client_id, message)
|
||||
elif message_type == "buy_pet": # 购买宠物
|
||||
return self.server._handle_buy_pet(client_id, message)
|
||||
elif message_type == "rename_pet": # 重命名宠物
|
||||
return self.server._handle_rename_pet(client_id, message)
|
||||
elif message_type == "set_patrol_pet": # 设置巡逻宠物
|
||||
return self.server._handle_set_patrol_pet(client_id, message)
|
||||
elif message_type == "set_battle_pet": # 设置出战宠物
|
||||
return self.server._handle_set_battle_pet(client_id, message)
|
||||
elif message_type == "update_battle_pet_data": # 更新宠物对战数据
|
||||
return self.server._handle_update_battle_pet_data(client_id, message)
|
||||
elif message_type == "feed_pet": # 喂食宠物
|
||||
return self.server._handle_feed_pet(client_id, message)
|
||||
elif message_type == "dig_ground": # 开垦土地
|
||||
return self.server._handle_dig_ground(client_id, message)
|
||||
elif message_type == "remove_crop": # 铲除作物
|
||||
return self.server._handle_remove_crop(client_id, message)
|
||||
elif message_type == "water_crop": # 浇水
|
||||
return self.server._handle_water_crop(client_id, message)
|
||||
elif message_type == "fertilize_crop": # 施肥
|
||||
return self.server._handle_fertilize_crop(client_id, message)
|
||||
elif message_type == "use_item": # 使用道具
|
||||
return self.server._handle_use_item(client_id, message)
|
||||
elif message_type == "upgrade_land": # 升级土地
|
||||
return self.server._handle_upgrade_land(client_id, message)
|
||||
elif message_type == "buy_new_ground": # 添加新的土地
|
||||
return self.server._handle_buy_new_ground(client_id, message)
|
||||
elif message_type == "like_player": # 点赞玩家
|
||||
return self.server._handle_like_player(client_id, message)
|
||||
elif message_type == "request_online_players": # 请求在线玩家
|
||||
return self.server._handle_online_players_request(client_id, message)
|
||||
elif message_type == "get_play_time": # 获取游玩时间
|
||||
return self.server._handle_get_play_time(client_id)
|
||||
elif message_type == "update_play_time": # 更新游玩时间
|
||||
return self.server._handle_update_play_time(client_id)
|
||||
elif message_type == "request_player_rankings": # 请求玩家排行榜
|
||||
return self.server._handle_player_rankings_request(client_id, message)
|
||||
elif message_type == "request_crop_data": # 请求作物数据
|
||||
return self.server._handle_crop_data_request(client_id)
|
||||
elif message_type == "request_item_config": # 请求道具配置数据
|
||||
return self.server._handle_item_config_request(client_id)
|
||||
elif message_type == "request_pet_config": # 请求宠物配置数据
|
||||
return self.server._handle_pet_config_request(client_id)
|
||||
elif message_type == "request_game_tips_config": # 请求游戏小提示配置数据
|
||||
return self.server._handle_game_tips_config_request(client_id)
|
||||
elif message_type == "visit_player": # 拜访其他玩家农场
|
||||
return self.server._handle_visit_player_request(client_id, message)
|
||||
elif message_type == "return_my_farm": # 返回我的农场
|
||||
return self.server._handle_return_my_farm_request(client_id, message)
|
||||
elif message_type == "daily_check_in": # 每日签到
|
||||
return self.server._handle_daily_check_in_request(client_id, message)
|
||||
elif message_type == "get_check_in_data": # 获取签到数据
|
||||
return self.server._handle_get_check_in_data_request(client_id, message)
|
||||
elif message_type == "lucky_draw": # 幸运抽奖
|
||||
return self.server._handle_lucky_draw_request(client_id, message)
|
||||
elif message_type == "claim_new_player_gift": # 领取新手大礼包
|
||||
return self.server._handle_new_player_gift_request(client_id, message)
|
||||
elif message_type == "get_online_gift_data": # 获取在线礼包数据
|
||||
return self.server._handle_get_online_gift_data_request(client_id, message)
|
||||
elif message_type == "claim_online_gift": # 领取在线礼包
|
||||
return self.server._handle_claim_online_gift_request(client_id, message)
|
||||
elif message_type == "ping": # 客户端ping请求
|
||||
return self.server._handle_ping_request(client_id, message)
|
||||
elif message_type == "modify_account_info": # 修改账号信息
|
||||
return self.server._handle_modify_account_info_request(client_id, message)
|
||||
elif message_type == "delete_account": # 删除账号
|
||||
return self.server._handle_delete_account_request(client_id, message)
|
||||
elif message_type == "refresh_player_info": # 刷新玩家信息
|
||||
return self.server._handle_refresh_player_info_request(client_id, message)
|
||||
elif message_type == "global_broadcast": # 全服大喇叭消息
|
||||
return self.server._handle_global_broadcast_message(client_id, message)
|
||||
elif message_type == "request_broadcast_history": # 请求全服大喇叭历史消息
|
||||
return self.server._handle_request_broadcast_history(client_id, message)
|
||||
elif message_type == "use_pet_item": # 宠物使用道具
|
||||
return self.server._handle_use_pet_item(client_id, message)
|
||||
elif message_type == "use_farm_item": # 农场道具使用
|
||||
return self.server._handle_use_farm_item(client_id, message)
|
||||
elif message_type == "buy_scare_crow": # 购买稻草人
|
||||
return self.server._handle_buy_scare_crow(client_id, message)
|
||||
elif message_type == "modify_scare_crow_config": # 修改稻草人配置
|
||||
return self.server._handle_modify_scare_crow_config(client_id, message)
|
||||
elif message_type == "get_scare_crow_config": # 获取稻草人配置
|
||||
return self.server._handle_get_scare_crow_config(client_id, message)
|
||||
elif message_type == "wisdom_tree_operation": # 智慧树操作
|
||||
return self.server._handle_wisdom_tree_operation(client_id, message)
|
||||
elif message_type == "wisdom_tree_message": # 智慧树消息
|
||||
return self.server._handle_wisdom_tree_message(client_id, message)
|
||||
elif message_type == "get_wisdom_tree_config": # 获取智慧树配置
|
||||
return self.server._handle_get_wisdom_tree_config(client_id, message)
|
||||
elif message_type == "sell_crop": # 出售作物
|
||||
return self.server._handle_sell_crop(client_id, message)
|
||||
elif message_type == "add_product_to_store": # 添加商品到小卖部
|
||||
return self.server._handle_add_product_to_store(client_id, message)
|
||||
elif message_type == "remove_store_product": # 下架小卖部商品
|
||||
return self.server._handle_remove_store_product(client_id, message)
|
||||
elif message_type == "buy_store_product": # 购买小卖部商品
|
||||
return self.server._handle_buy_store_product(client_id, message)
|
||||
elif message_type == "buy_store_booth": # 购买小卖部格子
|
||||
return self.server._handle_buy_store_booth(client_id, message)
|
||||
elif message_type == "save_game_settings": # 保存游戏设置
|
||||
return self.server._handle_save_game_settings(client_id, message)
|
||||
elif message_type == "pet_battle_result": # 宠物对战结果
|
||||
return self.server._handle_pet_battle_result(client_id, message)
|
||||
elif message_type == "today_divination": # 今日占卜
|
||||
return self.server._handle_today_divination(client_id, message)
|
||||
elif message_type == "give_money": # 送金币
|
||||
return self.server._handle_give_money_request(client_id, message)
|
||||
elif message_type == "sync_bag_data": # 同步背包数据
|
||||
return self.server._handle_sync_bag_data(client_id, message)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 管理员操作相关
|
||||
elif message_type == "kick_player": # 踢出玩家
|
||||
return self.server._handle_kick_player(client_id, message)
|
||||
|
||||
# elif message_type == "message": # 处理聊天消息(暂未实现)
|
||||
# return self.server._handle_chat_message(client_id, message)
|
||||
else:
|
||||
# 调用父类的默认处理方法
|
||||
return super(type(self.server), self.server)._handle_message(client_id, message)
|
||||
0
SproutFarm-Backend/module/PetSystem.py
Normal file
0
SproutFarm-Backend/module/PetSystem.py
Normal file
543
SproutFarm-Backend/module/QQEmailSendAPI.py
Normal file
543
SproutFarm-Backend/module/QQEmailSendAPI.py
Normal file
@@ -0,0 +1,543 @@
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.application import MIMEApplication
|
||||
from email.header import Header
|
||||
import random
|
||||
import string
|
||||
import json
|
||||
import os
|
||||
|
||||
# 邮件发送配置
|
||||
SENDER_EMAIL = '3205788256@qq.com' # 发件人邮箱
|
||||
SENDER_AUTH_CODE = 'szcaxvbftusqddhi' # 授权码
|
||||
SMTP_SERVER = 'smtp.qq.com' # QQ邮箱SMTP服务器
|
||||
SMTP_PORT = 465 # QQ邮箱SSL端口
|
||||
|
||||
# 验证码缓存文件
|
||||
VERIFICATION_CACHE_FILE = os.path.join("config", "verification_codes.json")
|
||||
|
||||
class QQMailAPI:
|
||||
"""QQ邮箱发送邮件API类"""
|
||||
|
||||
def __init__(self, sender_email, authorization_code):
|
||||
"""
|
||||
初始化邮箱配置
|
||||
:param sender_email: 发送方QQ邮箱地址
|
||||
:param authorization_code: QQ邮箱授权码
|
||||
"""
|
||||
self.sender_email = sender_email
|
||||
self.authorization_code = authorization_code
|
||||
self.smtp_server = 'smtp.qq.com'
|
||||
self.smtp_port = 465 # SSL端口
|
||||
|
||||
# 发送纯文本邮件
|
||||
def send_text_email(self, receiver_email, subject, content, cc_emails=None):
|
||||
"""
|
||||
发送纯文本邮件
|
||||
:param receiver_email: 接收方邮箱地址(单个)
|
||||
:param subject: 邮件主题
|
||||
:param content: 邮件正文内容
|
||||
:param cc_emails: 抄送邮箱列表
|
||||
:return: 发送成功返回True,失败返回False
|
||||
"""
|
||||
try:
|
||||
# 创建邮件对象
|
||||
message = MIMEText(content, 'plain', 'utf-8')
|
||||
message['From'] = Header(self.sender_email, 'utf-8')
|
||||
message['To'] = Header(receiver_email, 'utf-8')
|
||||
message['Subject'] = Header(subject, 'utf-8')
|
||||
|
||||
# 添加抄送
|
||||
if cc_emails:
|
||||
message['Cc'] = Header(",".join(cc_emails), 'utf-8')
|
||||
all_receivers = [receiver_email] + cc_emails
|
||||
else:
|
||||
all_receivers = [receiver_email]
|
||||
|
||||
# 连接SMTP服务器并发送邮件
|
||||
with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server:
|
||||
server.login(self.sender_email, self.authorization_code)
|
||||
server.sendmail(self.sender_email, all_receivers, message.as_string())
|
||||
|
||||
print(f"邮件发送成功:主题='{subject}', 收件人='{receiver_email}'")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"邮件发送失败:{str(e)}")
|
||||
return False
|
||||
|
||||
# 发送HTML格式邮件,可带附件
|
||||
def send_html_email(self, receiver_email, subject, html_content, cc_emails=None, attachments=None):
|
||||
"""
|
||||
发送HTML格式邮件,可带附件
|
||||
:param receiver_email: 接收方邮箱地址(单个)
|
||||
:param subject: 邮件主题
|
||||
:param html_content: HTML格式的邮件正文
|
||||
:param cc_emails: 抄送邮箱列表
|
||||
:param attachments: 附件文件路径列表
|
||||
:return: 发送成功返回True,失败返回False
|
||||
"""
|
||||
try:
|
||||
# 创建带附件的邮件对象
|
||||
message = MIMEMultipart()
|
||||
message['From'] = Header(self.sender_email, 'utf-8')
|
||||
message['To'] = Header(receiver_email, 'utf-8')
|
||||
message['Subject'] = Header(subject, 'utf-8')
|
||||
|
||||
# 添加抄送
|
||||
if cc_emails:
|
||||
message['Cc'] = Header(",".join(cc_emails), 'utf-8')
|
||||
all_receivers = [receiver_email] + cc_emails
|
||||
else:
|
||||
all_receivers = [receiver_email]
|
||||
|
||||
# 添加HTML正文
|
||||
message.attach(MIMEText(html_content, 'html', 'utf-8'))
|
||||
|
||||
# 添加附件
|
||||
if attachments:
|
||||
for file_path in attachments:
|
||||
try:
|
||||
with open(file_path, 'rb') as file:
|
||||
attachment = MIMEApplication(file.read(), _subtype="octet-stream")
|
||||
attachment.add_header('Content-Disposition', 'attachment', filename=file_path.split("/")[-1])
|
||||
message.attach(attachment)
|
||||
except Exception as e:
|
||||
print(f"添加附件失败 {file_path}: {str(e)}")
|
||||
|
||||
# 连接SMTP服务器并发送邮件
|
||||
with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server:
|
||||
server.login(self.sender_email, self.authorization_code)
|
||||
server.sendmail(self.sender_email, all_receivers, message.as_string())
|
||||
|
||||
print(f"HTML邮件发送成功:主题='{subject}', 收件人='{receiver_email}'")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"HTML邮件发送失败:{str(e)}")
|
||||
return False
|
||||
|
||||
class EmailVerification:
|
||||
|
||||
#生成指定长度的随机验证码
|
||||
@staticmethod
|
||||
def generate_verification_code(length=6):
|
||||
"""
|
||||
生成指定长度的随机验证码
|
||||
|
||||
参数:
|
||||
length (int): 验证码长度,默认6位
|
||||
|
||||
返回:
|
||||
str: 生成的验证码
|
||||
"""
|
||||
# 生成包含大写字母和数字的验证码
|
||||
chars = string.ascii_uppercase + string.digits
|
||||
return ''.join(random.choice(chars) for _ in range(length))
|
||||
|
||||
#发送验证码邮件到QQ邮箱
|
||||
@staticmethod
|
||||
def send_verification_email(qq_number, verification_code, email_type="register"):
|
||||
"""
|
||||
发送验证码邮件到QQ邮箱
|
||||
|
||||
参数:
|
||||
qq_number (str): 接收者QQ号
|
||||
verification_code (str): 验证码
|
||||
email_type (str): 邮件类型,"register" 或 "reset_password"
|
||||
|
||||
返回:
|
||||
bool: 发送成功返回True,否则返回False
|
||||
str: 成功或错误信息
|
||||
"""
|
||||
receiver_email = f"{qq_number}@qq.com"
|
||||
|
||||
# 根据邮件类型设置不同的内容
|
||||
if email_type == "reset_password":
|
||||
email_title = "【萌芽农场】密码重置验证码"
|
||||
email_purpose = "重置萌芽农场游戏账号密码"
|
||||
email_color = "#FF6B35" # 橙红色,表示警告性操作
|
||||
else:
|
||||
email_title = "【萌芽农场】注册验证码"
|
||||
email_purpose = "注册萌芽农场游戏账号"
|
||||
email_color = "#4CAF50" # 绿色,表示正常操作
|
||||
|
||||
# 创建邮件内容
|
||||
message = MIMEText(f'''
|
||||
<html>
|
||||
<body>
|
||||
<div style="font-family: Arial, sans-serif; color: #333;">
|
||||
<h2 style="color: {email_color};">萌芽农场 - 邮箱验证码</h2>
|
||||
<p>亲爱的玩家,您好!</p>
|
||||
<p>您正在{email_purpose},您的验证码是:</p>
|
||||
<div style="background-color: #f2f2f2; padding: 10px; font-size: 24px; font-weight: bold; color: {email_color}; text-align: center; margin: 20px 0;">
|
||||
{verification_code}
|
||||
</div>
|
||||
<p>该验证码有效期为5分钟,请勿泄露给他人。</p>
|
||||
<p>如果这不是您本人的操作,请忽略此邮件。</p>
|
||||
<p style="margin-top: 30px; font-size: 12px; color: #999;">
|
||||
本邮件由系统自动发送,请勿直接回复。
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
''', 'html', 'utf-8')
|
||||
|
||||
# 修正From头格式,符合QQ邮箱的要求
|
||||
message['From'] = SENDER_EMAIL
|
||||
message['To'] = receiver_email
|
||||
message['Subject'] = Header(email_title, 'utf-8')
|
||||
|
||||
try:
|
||||
# 使用SSL/TLS连接而不是STARTTLS
|
||||
smtp_obj = smtplib.SMTP_SSL(SMTP_SERVER, 465)
|
||||
smtp_obj.login(SENDER_EMAIL, SENDER_AUTH_CODE)
|
||||
smtp_obj.sendmail(SENDER_EMAIL, [receiver_email], message.as_string())
|
||||
smtp_obj.quit()
|
||||
return True, "验证码发送成功"
|
||||
except Exception as e:
|
||||
return False, f"发送验证码失败: {str(e)}"
|
||||
|
||||
#保存验证码到MongoDB(优先)或缓存文件(备用)
|
||||
@staticmethod
|
||||
def save_verification_code(qq_number, verification_code, expiry_time=300, code_type="register"):
|
||||
"""
|
||||
保存验证码到MongoDB(优先)或缓存文件(备用)
|
||||
|
||||
参数:
|
||||
qq_number (str): QQ号
|
||||
verification_code (str): 验证码
|
||||
expiry_time (int): 过期时间(秒),默认5分钟
|
||||
code_type (str): 验证码类型,"register" 或 "reset_password"
|
||||
|
||||
返回:
|
||||
bool: 保存成功返回True,否则返回False
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from .SMYMongoDBAPI import SMYMongoDBAPI
|
||||
import os
|
||||
# 根据环境动态选择MongoDB配置
|
||||
if os.path.exists('/.dockerenv') or os.environ.get('PRODUCTION', '').lower() == 'true':
|
||||
environment = "production"
|
||||
else:
|
||||
environment = "test"
|
||||
mongo_api = SMYMongoDBAPI(environment)
|
||||
if mongo_api.is_connected():
|
||||
success = mongo_api.save_verification_code(qq_number, verification_code, expiry_time, code_type)
|
||||
if success:
|
||||
print(f"[验证码系统-MongoDB] 为QQ {qq_number} 保存{code_type}验证码: {verification_code}")
|
||||
return True
|
||||
else:
|
||||
print(f"[验证码系统-MongoDB] 保存失败,尝试使用JSON文件")
|
||||
except Exception as e:
|
||||
print(f"[验证码系统-MongoDB] MongoDB保存失败: {str(e)},尝试使用JSON文件")
|
||||
|
||||
# MongoDB失败,使用JSON文件备用
|
||||
# 创建目录(如果不存在)
|
||||
os.makedirs(os.path.dirname(VERIFICATION_CACHE_FILE), exist_ok=True)
|
||||
|
||||
# 读取现有的验证码数据
|
||||
verification_data = {}
|
||||
if os.path.exists(VERIFICATION_CACHE_FILE):
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'r', encoding='utf-8') as file:
|
||||
verification_data = json.load(file)
|
||||
except Exception as e:
|
||||
print(f"读取验证码文件失败: {str(e)}")
|
||||
verification_data = {}
|
||||
|
||||
# 添加新的验证码
|
||||
expire_at = time.time() + expiry_time
|
||||
current_time = time.time()
|
||||
|
||||
# 创建验证码记录,包含更多信息用于调试
|
||||
verification_data[qq_number] = {
|
||||
"code": verification_code,
|
||||
"expire_at": expire_at,
|
||||
"code_type": code_type,
|
||||
"created_at": current_time,
|
||||
"used": False # 新增:标记验证码是否已使用
|
||||
}
|
||||
|
||||
# 保存到文件
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'w', encoding='utf-8') as file:
|
||||
json.dump(verification_data, file, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"[验证码系统-JSON] 为QQ {qq_number} 保存{code_type}验证码: {verification_code}, 过期时间: {expire_at}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"保存验证码失败: {str(e)}")
|
||||
return False
|
||||
|
||||
#验证用户输入的验证码(优先使用MongoDB)
|
||||
@staticmethod
|
||||
def verify_code(qq_number, input_code, code_type="register"):
|
||||
"""
|
||||
验证用户输入的验证码(优先使用MongoDB)
|
||||
|
||||
参数:
|
||||
qq_number (str): QQ号
|
||||
input_code (str): 用户输入的验证码
|
||||
code_type (str): 验证码类型,"register" 或 "reset_password"
|
||||
|
||||
返回:
|
||||
bool: 验证成功返回True,否则返回False
|
||||
str: 成功或错误信息
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from .SMYMongoDBAPI import SMYMongoDBAPI
|
||||
import os
|
||||
# 根据环境动态选择MongoDB配置
|
||||
if os.path.exists('/.dockerenv') or os.environ.get('PRODUCTION', '').lower() == 'true':
|
||||
environment = "production"
|
||||
else:
|
||||
environment = "test"
|
||||
mongo_api = SMYMongoDBAPI(environment)
|
||||
if mongo_api.is_connected():
|
||||
success, message = mongo_api.verify_verification_code(qq_number, input_code, code_type)
|
||||
print(f"[验证码系统-MongoDB] QQ {qq_number} 验证结果: {success}, 消息: {message}")
|
||||
return success, message
|
||||
except Exception as e:
|
||||
print(f"[验证码系统-MongoDB] MongoDB验证失败: {str(e)},尝试使用JSON文件")
|
||||
|
||||
# MongoDB失败,使用JSON文件备用
|
||||
# 检查缓存文件是否存在
|
||||
if not os.path.exists(VERIFICATION_CACHE_FILE):
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 缓存文件不存在")
|
||||
return False, "验证码不存在或已过期"
|
||||
|
||||
# 读取验证码数据
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'r', encoding='utf-8') as file:
|
||||
verification_data = json.load(file)
|
||||
except Exception as e:
|
||||
print(f"[验证码系统-JSON] 读取验证码文件失败: {str(e)}")
|
||||
return False, "验证码数据损坏"
|
||||
|
||||
# 检查该QQ号是否有验证码
|
||||
if qq_number not in verification_data:
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 没有找到验证码记录")
|
||||
return False, "验证码不存在,请重新获取"
|
||||
|
||||
# 获取存储的验证码信息
|
||||
code_info = verification_data[qq_number]
|
||||
stored_code = code_info.get("code", "")
|
||||
expire_at = code_info.get("expire_at", 0)
|
||||
stored_code_type = code_info.get("code_type", "register")
|
||||
is_used = code_info.get("used", False)
|
||||
created_at = code_info.get("created_at", 0)
|
||||
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证码详情: 存储码={stored_code}, 输入码={input_code}, 类型={stored_code_type}, 已使用={is_used}, 创建时间={created_at}")
|
||||
|
||||
# 检查验证码类型是否匹配
|
||||
if stored_code_type != code_type:
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码类型不匹配,存储类型={stored_code_type}, 请求类型={code_type}")
|
||||
return False, f"验证码类型不匹配,请重新获取{code_type}验证码"
|
||||
|
||||
# 检查验证码是否已被使用
|
||||
if is_used:
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码已被使用")
|
||||
return False, "验证码已被使用,请重新获取"
|
||||
|
||||
# 检查验证码是否过期
|
||||
current_time = time.time()
|
||||
if current_time > expire_at:
|
||||
# 移除过期的验证码
|
||||
del verification_data[qq_number]
|
||||
with open(VERIFICATION_CACHE_FILE, 'w', encoding='utf-8') as file:
|
||||
json.dump(verification_data, file, indent=2, ensure_ascii=False)
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码已过期")
|
||||
return False, "验证码已过期,请重新获取"
|
||||
|
||||
# 验证码比较(不区分大小写)
|
||||
if input_code.upper() == stored_code.upper():
|
||||
# 验证成功,标记为已使用而不是删除
|
||||
verification_data[qq_number]["used"] = True
|
||||
verification_data[qq_number]["used_at"] = current_time
|
||||
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'w', encoding='utf-8') as file:
|
||||
json.dump(verification_data, file, indent=2, ensure_ascii=False)
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证成功: 验证码已标记为已使用")
|
||||
return True, "验证码正确"
|
||||
except Exception as e:
|
||||
print(f"[验证码系统-JSON] 标记验证码已使用时失败: {str(e)}")
|
||||
return True, "验证码正确" # 即使标记失败,验证还是成功的
|
||||
else:
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码不匹配")
|
||||
return False, "验证码错误"
|
||||
|
||||
#清理过期的验证码和已使用的验证码(优先使用MongoDB)
|
||||
@staticmethod
|
||||
def clean_expired_codes():
|
||||
"""
|
||||
清理过期的验证码和已使用的验证码(优先使用MongoDB)
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from .SMYMongoDBAPI import SMYMongoDBAPI
|
||||
import os
|
||||
# 根据环境动态选择MongoDB配置
|
||||
if os.path.exists('/.dockerenv') or os.environ.get('PRODUCTION', '').lower() == 'true':
|
||||
environment = "production"
|
||||
else:
|
||||
environment = "test"
|
||||
mongo_api = SMYMongoDBAPI(environment)
|
||||
if mongo_api.is_connected():
|
||||
expired_count = mongo_api.clean_expired_verification_codes()
|
||||
print(f"[验证码系统-MongoDB] 清理完成,删除了 {expired_count} 个过期验证码")
|
||||
return expired_count
|
||||
except Exception as e:
|
||||
print(f"[验证码系统-MongoDB] MongoDB清理失败: {str(e)},尝试使用JSON文件")
|
||||
|
||||
# MongoDB失败,使用JSON文件备用
|
||||
if not os.path.exists(VERIFICATION_CACHE_FILE):
|
||||
return
|
||||
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'r', encoding='utf-8') as file:
|
||||
verification_data = json.load(file)
|
||||
|
||||
current_time = time.time()
|
||||
removed_keys = []
|
||||
|
||||
# 找出过期的验证码和已使用的验证码(超过1小时)
|
||||
for qq_number, code_info in verification_data.items():
|
||||
expire_at = code_info.get("expire_at", 0)
|
||||
is_used = code_info.get("used", False)
|
||||
used_at = code_info.get("used_at", 0)
|
||||
|
||||
should_remove = False
|
||||
|
||||
# 过期的验证码
|
||||
if current_time > expire_at:
|
||||
should_remove = True
|
||||
print(f"[验证码清理-JSON] 移除过期验证码: QQ {qq_number}")
|
||||
|
||||
# 已使用超过1小时的验证码
|
||||
elif is_used and used_at > 0 and (current_time - used_at) > 3600:
|
||||
should_remove = True
|
||||
print(f"[验证码清理-JSON] 移除已使用的验证码: QQ {qq_number}")
|
||||
|
||||
if should_remove:
|
||||
removed_keys.append(qq_number)
|
||||
|
||||
# 移除标记的验证码
|
||||
for key in removed_keys:
|
||||
del verification_data[key]
|
||||
|
||||
# 保存更新后的数据
|
||||
if removed_keys:
|
||||
with open(VERIFICATION_CACHE_FILE, 'w', encoding='utf-8') as file:
|
||||
json.dump(verification_data, file, indent=2, ensure_ascii=False)
|
||||
print(f"[验证码清理-JSON] 共清理了 {len(removed_keys)} 个验证码")
|
||||
|
||||
except Exception as e:
|
||||
print(f"清理验证码失败: {str(e)}")
|
||||
|
||||
#获取验证码状态(优先使用MongoDB)
|
||||
@staticmethod
|
||||
def get_verification_status(qq_number):
|
||||
"""
|
||||
获取验证码状态(优先使用MongoDB)
|
||||
|
||||
参数:
|
||||
qq_number (str): QQ号
|
||||
|
||||
返回:
|
||||
dict: 验证码状态信息
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from .SMYMongoDBAPI import SMYMongoDBAPI
|
||||
import os
|
||||
# 根据环境动态选择MongoDB配置
|
||||
if os.path.exists('/.dockerenv') or os.environ.get('PRODUCTION', '').lower() == 'true':
|
||||
environment = "production"
|
||||
else:
|
||||
environment = "test"
|
||||
mongo_api = SMYMongoDBAPI(environment)
|
||||
if mongo_api.is_connected():
|
||||
verification_codes = mongo_api.get_verification_codes()
|
||||
if verification_codes and qq_number in verification_codes:
|
||||
code_info = verification_codes[qq_number]
|
||||
current_time = time.time()
|
||||
|
||||
return {
|
||||
"status": "found",
|
||||
"code": code_info.get("code", ""),
|
||||
"code_type": code_info.get("code_type", "unknown"),
|
||||
"used": code_info.get("used", False),
|
||||
"expired": current_time > code_info.get("expire_at", 0),
|
||||
"created_at": code_info.get("created_at", 0),
|
||||
"expire_at": code_info.get("expire_at", 0),
|
||||
"used_at": code_info.get("used_at", 0),
|
||||
"source": "mongodb"
|
||||
}
|
||||
else:
|
||||
return {"status": "no_code", "source": "mongodb"}
|
||||
except Exception as e:
|
||||
print(f"[验证码系统-MongoDB] MongoDB状态查询失败: {str(e)},尝试使用JSON文件")
|
||||
|
||||
# MongoDB失败,使用JSON文件备用
|
||||
if not os.path.exists(VERIFICATION_CACHE_FILE):
|
||||
return {"status": "no_cache_file"}
|
||||
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'r', encoding='utf-8') as file:
|
||||
verification_data = json.load(file)
|
||||
|
||||
if qq_number not in verification_data:
|
||||
return {"status": "no_code"}
|
||||
|
||||
code_info = verification_data[qq_number]
|
||||
current_time = time.time()
|
||||
|
||||
return {
|
||||
"status": "found",
|
||||
"code": code_info.get("code", ""),
|
||||
"code_type": code_info.get("code_type", "unknown"),
|
||||
"used": code_info.get("used", False),
|
||||
"expired": current_time > code_info.get("expire_at", 0),
|
||||
"created_at": code_info.get("created_at", 0),
|
||||
"expire_at": code_info.get("expire_at", 0),
|
||||
"used_at": code_info.get("used_at", 0),
|
||||
"source": "json"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
# 测试邮件发送
|
||||
if __name__ == "__main__":
|
||||
# 清理过期验证码
|
||||
EmailVerification.clean_expired_codes()
|
||||
|
||||
# 生成验证码
|
||||
test_qq = input("请输入测试QQ号: ")
|
||||
verification_code = EmailVerification.generate_verification_code()
|
||||
print(f"生成的验证码: {verification_code}")
|
||||
|
||||
# 发送测试邮件
|
||||
success, message = EmailVerification.send_verification_email(test_qq, verification_code)
|
||||
print(f"发送结果: {success}, 消息: {message}")
|
||||
|
||||
if success:
|
||||
# 保存验证码
|
||||
EmailVerification.save_verification_code(test_qq, verification_code)
|
||||
|
||||
# 测试验证
|
||||
test_input = input("请输入收到的验证码: ")
|
||||
verify_success, verify_message = EmailVerification.verify_code(test_qq, test_input)
|
||||
print(f"验证结果: {verify_success}, 消息: {verify_message}")
|
||||
1518
SproutFarm-Backend/module/SMYMongoDBAPI.py
Normal file
1518
SproutFarm-Backend/module/SMYMongoDBAPI.py
Normal file
File diff suppressed because it is too large
Load Diff
508
SproutFarm-Backend/module/SpecialFarm.py
Normal file
508
SproutFarm-Backend/module/SpecialFarm.py
Normal file
@@ -0,0 +1,508 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
特殊农场管理系统
|
||||
作者: AI Assistant
|
||||
功能: 管理特殊农场的自动种植和维护
|
||||
"""
|
||||
|
||||
import time
|
||||
import random
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from bson import ObjectId
|
||||
#自定义包
|
||||
from .SMYMongoDBAPI import SMYMongoDBAPI
|
||||
|
||||
#杂交农场666-种植杂交树1,杂交树2-每天0点种植
|
||||
#花卉农场520-随机种植各种花卉-星期一,星期三,星期五,星期日零点种植
|
||||
#瓜果农场333-随机种植各种瓜果-星期二,星期四,星期六零点种植
|
||||
#小麦谷222-全屏种植小麦-每天0点种植
|
||||
#稻香111-全屏种植稻谷-每天0点种植
|
||||
#幸运农场888-随机种植1-80个幸运草和幸运花-星期一零点种植
|
||||
|
||||
|
||||
|
||||
class SpecialFarmManager:
|
||||
#初始化特殊农场管理器
|
||||
def __init__(self, environment=None):
|
||||
"""
|
||||
初始化特殊农场管理器
|
||||
|
||||
Args:
|
||||
environment: 环境类型,"test" 或 "production",如果为None则自动检测
|
||||
"""
|
||||
# 如果没有指定环境,使用与TCPGameServer相同的环境检测逻辑
|
||||
if environment is None:
|
||||
import os
|
||||
if os.path.exists('/.dockerenv') or os.environ.get('PRODUCTION', '').lower() == 'true':
|
||||
environment = "production"
|
||||
else:
|
||||
environment = "test"
|
||||
|
||||
self.environment = environment
|
||||
self.mongo_api = SMYMongoDBAPI(environment)
|
||||
|
||||
# 设置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.FileHandler('special_farm.log', encoding='utf-8'),
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
# 特殊农场配置
|
||||
self.special_farms = {
|
||||
"杂交农场": {
|
||||
"object_id": "689b4b9286cf953f2f4e56ee",
|
||||
"crops": ["杂交树1", "杂交树2"],
|
||||
"description": "专门种植杂交树的特殊农场"
|
||||
},
|
||||
"花卉农场": {
|
||||
"object_id": "689bec6286cf953f2f4e56f1",
|
||||
"crops": ["郁金香", "牵牛花", "百合花", "栀子花", "玫瑰花", "向日葵", "藏红花", "幸运花"],
|
||||
"description": "盛产各种美丽花卉的特殊农场",
|
||||
"plant_type": "random_flowers" # 标记为随机花卉种植类型
|
||||
},
|
||||
"瓜果农场": {
|
||||
"object_id": "689bf73886cf953f2f4e56fa",
|
||||
"crops": ["西瓜", "南瓜", "哈密瓜", "葫芦", "黄瓜", "龙果", "菠萝", "芒果"],
|
||||
"description": "盛产各种瓜果的农场",
|
||||
"plant_type": "random_fruits" # 标记为随机瓜果种植类型
|
||||
},
|
||||
"小麦谷": {
|
||||
"object_id": "689bf9a886cf953f2f4e56fd",
|
||||
"crops": ["小麦"],
|
||||
"description": "盛产小麦的农场",
|
||||
"plant_type": "single_wheat" # 标记为单一小麦种植类型
|
||||
},
|
||||
"稻香": {
|
||||
"object_id": "689bf9ac86cf953f2f4e56fe",
|
||||
"crops": ["稻谷"],
|
||||
"description": "盛产稻谷的农场",
|
||||
"plant_type": "single_rice" # 标记为单一稻谷种植类型
|
||||
},
|
||||
"幸运农场": {
|
||||
"object_id": "689c027886cf953f2f4e56ff",
|
||||
"crops": ["幸运草", "幸运花"],
|
||||
"description": "盛产幸运草和幸运花的农场",
|
||||
"plant_type": "random_lucky" # 标记为随机幸运植物种植类型
|
||||
}
|
||||
}
|
||||
|
||||
self.logger.info(f"特殊农场管理器初始化完成 - 环境: {environment}")
|
||||
|
||||
#获取作物系统数据
|
||||
def get_crop_data(self):
|
||||
"""
|
||||
获取作物配置数据
|
||||
|
||||
Returns:
|
||||
dict: 作物配置数据
|
||||
"""
|
||||
try:
|
||||
crop_config = self.mongo_api.get_crop_data_config()
|
||||
if crop_config:
|
||||
# 移除MongoDB相关字段
|
||||
if "_id" in crop_config:
|
||||
del crop_config["_id"]
|
||||
if "config_type" in crop_config:
|
||||
del crop_config["config_type"]
|
||||
if "updated_at" in crop_config:
|
||||
del crop_config["updated_at"]
|
||||
return crop_config
|
||||
else:
|
||||
self.logger.error("无法获取作物配置数据")
|
||||
return {}
|
||||
except Exception as e:
|
||||
self.logger.error(f"获取作物配置数据时出错: {str(e)}")
|
||||
return {}
|
||||
|
||||
#通过文档ID获取农场数据
|
||||
def get_player_data_by_object_id(self, object_id):
|
||||
"""
|
||||
通过ObjectId获取玩家数据
|
||||
|
||||
Args:
|
||||
object_id: MongoDB文档ID
|
||||
|
||||
Returns:
|
||||
dict: 玩家数据,如果未找到返回None
|
||||
"""
|
||||
try:
|
||||
collection = self.mongo_api.get_collection("playerdata")
|
||||
oid = ObjectId(object_id)
|
||||
player_data = collection.find_one({"_id": oid})
|
||||
|
||||
if player_data:
|
||||
self.logger.info(f"成功获取玩家数据: {player_data.get('玩家昵称', 'Unknown')}")
|
||||
return player_data
|
||||
else:
|
||||
self.logger.warning(f"未找到ObjectId为 {object_id} 的玩家数据")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"获取玩家数据时出错: {str(e)}")
|
||||
return None
|
||||
|
||||
#通过文档ID保存农场数据
|
||||
def save_player_data_by_object_id(self, object_id, player_data):
|
||||
"""
|
||||
通过ObjectId保存玩家数据
|
||||
|
||||
Args:
|
||||
object_id: MongoDB文档ID
|
||||
player_data: 玩家数据
|
||||
|
||||
Returns:
|
||||
bool: 是否保存成功
|
||||
"""
|
||||
try:
|
||||
collection = self.mongo_api.get_collection("playerdata")
|
||||
oid = ObjectId(object_id)
|
||||
|
||||
# 更新最后登录时间
|
||||
player_data["最后登录时间"] = datetime.now().strftime("%Y年%m月%d日%H时%M分%S秒")
|
||||
|
||||
result = collection.replace_one({"_id": oid}, player_data)
|
||||
|
||||
if result.acknowledged and result.matched_count > 0:
|
||||
self.logger.info(f"成功保存玩家数据: {player_data.get('玩家昵称', 'Unknown')}")
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"保存玩家数据失败: ObjectId {object_id}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"保存玩家数据时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
#在指定农场种植作物
|
||||
def plant_crops_in_farm(self, farm_name):
|
||||
"""
|
||||
为指定特殊农场种植作物
|
||||
|
||||
Args:
|
||||
farm_name: 农场名称
|
||||
|
||||
Returns:
|
||||
bool: 是否种植成功
|
||||
"""
|
||||
if farm_name not in self.special_farms:
|
||||
self.logger.error(f"未知的特殊农场: {farm_name}")
|
||||
return False
|
||||
|
||||
farm_config = self.special_farms[farm_name]
|
||||
object_id = farm_config["object_id"]
|
||||
available_crops = farm_config["crops"]
|
||||
|
||||
# 获取玩家数据
|
||||
player_data = self.get_player_data_by_object_id(object_id)
|
||||
if not player_data:
|
||||
return False
|
||||
|
||||
# 获取作物配置
|
||||
crop_data = self.get_crop_data()
|
||||
if not crop_data:
|
||||
self.logger.error("无法获取作物配置,跳过种植")
|
||||
return False
|
||||
|
||||
# 检查作物是否存在
|
||||
for crop_name in available_crops:
|
||||
if crop_name not in crop_data:
|
||||
self.logger.error(f"作物 {crop_name} 不存在于作物配置中")
|
||||
return False
|
||||
|
||||
# 获取农场土地
|
||||
farm_lands = player_data.get("农场土地", [])
|
||||
if not farm_lands:
|
||||
self.logger.error(f"农场 {farm_name} 没有土地数据")
|
||||
return False
|
||||
|
||||
planted_count = 0
|
||||
plant_type = farm_config.get("plant_type", "normal")
|
||||
|
||||
# 遍历所有土地,先开垦再种植作物
|
||||
for i, land in enumerate(farm_lands):
|
||||
# 根据农场类型选择作物
|
||||
if plant_type == "random_flowers":
|
||||
# 花卉农场:随机种植各种花卉,种满所有土地
|
||||
crop_name = random.choice(available_crops)
|
||||
should_plant = True # 100%种植率,种满所有土地
|
||||
elif plant_type == "random_fruits":
|
||||
# 瓜果农场:随机种植各种瓜果,种满所有土地
|
||||
crop_name = random.choice(available_crops)
|
||||
should_plant = True # 100%种植率,种满所有土地
|
||||
elif plant_type == "single_wheat":
|
||||
# 小麦谷:全屏种植小麦,种满所有土地
|
||||
crop_name = "小麦"
|
||||
should_plant = True # 100%种植率,种满所有土地
|
||||
elif plant_type == "single_rice":
|
||||
# 稻香:全屏种植稻谷,种满所有土地
|
||||
crop_name = "稻谷"
|
||||
should_plant = True # 100%种植率,种满所有土地
|
||||
elif plant_type == "random_lucky":
|
||||
# 幸运农场:随机种植1-80个幸运草和幸运花
|
||||
crop_name = random.choice(available_crops)
|
||||
# 随机决定是否种植,确保总数在1-80之间
|
||||
target_plants = random.randint(1, min(80, len(farm_lands)))
|
||||
should_plant = planted_count < target_plants
|
||||
else:
|
||||
# 普通农场:按原逻辑随机选择
|
||||
crop_name = random.choice(available_crops)
|
||||
should_plant = True
|
||||
|
||||
if should_plant:
|
||||
crop_info = crop_data[crop_name]
|
||||
|
||||
# 更新土地数据(先开垦,再种植)
|
||||
land.update({
|
||||
"is_diged": True, # 确保土地已开垦
|
||||
"is_planted": True,
|
||||
"crop_type": crop_name,
|
||||
"grow_time": 0, # 立即成熟
|
||||
"max_grow_time": crop_info.get("生长时间", 21600),
|
||||
"is_dead": False,
|
||||
"已浇水": True,
|
||||
"已施肥": True,
|
||||
"土地等级": 0
|
||||
})
|
||||
|
||||
# 清除施肥时间戳
|
||||
if "施肥时间" in land:
|
||||
del land["施肥时间"]
|
||||
|
||||
planted_count += 1
|
||||
else:
|
||||
# 留空的土地:只开垦不种植
|
||||
land.update({
|
||||
"is_diged": True,
|
||||
"is_planted": False,
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"max_grow_time": 3,
|
||||
"is_dead": False,
|
||||
"已浇水": False,
|
||||
"已施肥": False,
|
||||
"土地等级": 0
|
||||
})
|
||||
|
||||
# 清除施肥时间戳
|
||||
if "施肥时间" in land:
|
||||
del land["施肥时间"]
|
||||
|
||||
# 保存玩家数据
|
||||
if self.save_player_data_by_object_id(object_id, player_data):
|
||||
self.logger.info(f"成功为 {farm_name} 种植了 {planted_count} 块土地的作物")
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"保存 {farm_name} 数据失败")
|
||||
return False
|
||||
|
||||
#每日维护任务
|
||||
def daily_maintenance(self):
|
||||
"""
|
||||
每日维护任务
|
||||
"""
|
||||
from datetime import datetime
|
||||
|
||||
self.logger.info("开始执行特殊农场维护任务...")
|
||||
|
||||
success_count = 0
|
||||
total_farms = 0
|
||||
current_time = datetime.now()
|
||||
current_weekday = current_time.weekday() # 0=Monday, 1=Tuesday, ..., 6=Sunday
|
||||
current_time_str = current_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
for farm_name in self.special_farms.keys():
|
||||
# 检查农场是否需要在今天维护
|
||||
should_maintain = True
|
||||
|
||||
if farm_name == "瓜果农场":
|
||||
# 瓜果农场只在星期二(1)、四(3)、六(5)维护
|
||||
if current_weekday not in [1, 3, 5]:
|
||||
should_maintain = False
|
||||
self.logger.info(f"瓜果农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护")
|
||||
elif farm_name == "幸运农场":
|
||||
# 幸运农场只在星期一(0)维护
|
||||
if current_weekday != 0:
|
||||
should_maintain = False
|
||||
self.logger.info(f"幸运农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护")
|
||||
|
||||
if should_maintain:
|
||||
total_farms += 1
|
||||
try:
|
||||
if self.plant_crops_in_farm(farm_name):
|
||||
success_count += 1
|
||||
self.logger.info(f"农场 {farm_name} 维护完成")
|
||||
|
||||
# 更新维护时间记录
|
||||
try:
|
||||
farm_config = self.special_farms[farm_name]
|
||||
object_id = farm_config["object_id"]
|
||||
player_data = self.get_player_data_by_object_id(object_id)
|
||||
if player_data:
|
||||
player_data["特殊农场最后维护时间"] = current_time_str
|
||||
self.save_player_data_by_object_id(object_id, player_data)
|
||||
except Exception as record_error:
|
||||
self.logger.error(f"更新 {farm_name} 维护时间记录失败: {str(record_error)}")
|
||||
else:
|
||||
self.logger.error(f"农场 {farm_name} 维护失败")
|
||||
except Exception as e:
|
||||
self.logger.error(f"维护农场 {farm_name} 时出错: {str(e)}")
|
||||
|
||||
self.logger.info(f"维护任务完成: {success_count}/{total_farms} 个农场维护成功")
|
||||
|
||||
#启动定时任务调度器(后台线程模式)
|
||||
def start_scheduler(self):
|
||||
"""
|
||||
启动定时任务调度器(后台线程模式)
|
||||
"""
|
||||
import threading
|
||||
|
||||
self.logger.info("特殊农场定时任务调度器已启动")
|
||||
self.logger.info("维护任务将在每天凌晨0点执行")
|
||||
|
||||
# 检查是否需要立即执行维护任务
|
||||
self._check_and_run_initial_maintenance()
|
||||
|
||||
# 在后台线程中运行调度循环
|
||||
def scheduler_loop():
|
||||
last_maintenance_date = None
|
||||
|
||||
while True:
|
||||
try:
|
||||
now = datetime.now()
|
||||
current_date = now.strftime("%Y-%m-%d")
|
||||
|
||||
# 检查是否到了零点且今天还没有执行过维护
|
||||
if (now.hour == 0 and now.minute == 0 and
|
||||
last_maintenance_date != current_date):
|
||||
self.logger.info("零点维护时间到,开始执行维护任务...")
|
||||
self.daily_maintenance()
|
||||
last_maintenance_date = current_date
|
||||
|
||||
time.sleep(60) # 每分钟检查一次
|
||||
except Exception as e:
|
||||
self.logger.error(f"调度器运行时出错: {str(e)}")
|
||||
time.sleep(60)
|
||||
|
||||
# 启动后台线程
|
||||
scheduler_thread = threading.Thread(target=scheduler_loop, daemon=True)
|
||||
scheduler_thread.start()
|
||||
self.logger.info("特殊农场调度器已在后台线程启动")
|
||||
|
||||
#检查是否需要执行初始维护任务
|
||||
def _check_and_run_initial_maintenance(self):
|
||||
"""
|
||||
检查是否需要执行初始维护任务
|
||||
避免服务器重启时重复执行
|
||||
"""
|
||||
try:
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# 检查今天是否已经执行过维护任务
|
||||
current_time = datetime.now()
|
||||
today = current_time.strftime("%Y-%m-%d")
|
||||
current_weekday = current_time.weekday() # 0=Monday, 1=Tuesday, ..., 6=Sunday
|
||||
|
||||
# 获取特殊农场数据,检查最后维护时间
|
||||
for farm_name, farm_config in self.special_farms.items():
|
||||
object_id = farm_config["object_id"]
|
||||
player_data = self.get_player_data_by_object_id(object_id)
|
||||
|
||||
# 检查农场是否需要在今天维护
|
||||
should_maintain = True
|
||||
if farm_name == "瓜果农场":
|
||||
# 瓜果农场只在星期二(1)、四(3)、六(5)维护
|
||||
if current_weekday not in [1, 3, 5]:
|
||||
should_maintain = False
|
||||
self.logger.info(f"瓜果农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护")
|
||||
elif farm_name == "幸运农场":
|
||||
# 幸运农场只在星期一(0)维护
|
||||
if current_weekday != 0:
|
||||
should_maintain = False
|
||||
self.logger.info(f"幸运农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护")
|
||||
|
||||
if should_maintain and player_data:
|
||||
last_maintenance = player_data.get("特殊农场最后维护时间", "")
|
||||
|
||||
# 如果今天还没有维护过,则执行维护
|
||||
if not last_maintenance or not last_maintenance.startswith(today):
|
||||
self.logger.info(f"检测到 {farm_name} 今日尚未维护,执行维护任务...")
|
||||
if self.plant_crops_in_farm(farm_name):
|
||||
# 更新维护时间记录
|
||||
player_data["特殊农场最后维护时间"] = current_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
self.save_player_data_by_object_id(object_id, player_data)
|
||||
else:
|
||||
self.logger.info(f"{farm_name} 今日已维护过,跳过初始维护")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"检查初始维护任务时出错: {str(e)}")
|
||||
# 如果检查失败,执行一次维护作为备用
|
||||
self.logger.info("执行备用维护任务...")
|
||||
self.daily_maintenance()
|
||||
|
||||
#停止定时任务调度器
|
||||
def stop_scheduler(self):
|
||||
"""
|
||||
停止定时任务调度器
|
||||
"""
|
||||
try:
|
||||
# 设置停止标志(如果需要的话)
|
||||
self.logger.info("特殊农场定时任务调度器已停止")
|
||||
except Exception as e:
|
||||
self.logger.error(f"停止定时任务调度器时出错: {str(e)}")
|
||||
|
||||
#手动执行维护任务
|
||||
def manual_maintenance(self, farm_name=None):
|
||||
"""
|
||||
手动执行维护任务
|
||||
|
||||
Args:
|
||||
farm_name: 指定农场名称,如果为None则维护所有农场
|
||||
"""
|
||||
if farm_name:
|
||||
if farm_name in self.special_farms:
|
||||
self.logger.info(f"手动维护农场: {farm_name}")
|
||||
return self.plant_crops_in_farm(farm_name)
|
||||
else:
|
||||
self.logger.error(f"未知的农场名称: {farm_name}")
|
||||
return False
|
||||
else:
|
||||
self.logger.info("手动维护所有特殊农场")
|
||||
self.daily_maintenance()
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""
|
||||
主函数
|
||||
"""
|
||||
import sys
|
||||
|
||||
# 检查命令行参数
|
||||
environment = "production"
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1] in ["test", "production"]:
|
||||
environment = sys.argv[1]
|
||||
else:
|
||||
print("使用方法: python SpecialFarm.py [test|production]")
|
||||
sys.exit(1)
|
||||
|
||||
# 创建特殊农场管理器
|
||||
manager = SpecialFarmManager(environment)
|
||||
|
||||
# 检查是否为手动模式
|
||||
if len(sys.argv) > 2 and sys.argv[2] == "manual":
|
||||
# 手动执行维护
|
||||
farm_name = sys.argv[3] if len(sys.argv) > 3 else None
|
||||
manager.manual_maintenance(farm_name)
|
||||
else:
|
||||
# 启动定时任务
|
||||
manager.start_scheduler()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
255
SproutFarm-Backend/module/WSRemoteCmdApi.py
Normal file
255
SproutFarm-Backend/module/WSRemoteCmdApi.py
Normal file
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
WebSocket协议的服务器远程命令API
|
||||
作者: AI Assistant
|
||||
功能: 提供基于WebSocket的远程控制台命令执行功能
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import websockets
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
from typing import Dict, Any, Optional
|
||||
#自定义包
|
||||
from .ConsoleCommandsAPI import ConsoleCommandsAPI
|
||||
|
||||
class WSRemoteCmdApi:
|
||||
"""WebSocket远程命令API服务器"""
|
||||
|
||||
def __init__(self, game_server, host="0.0.0.0", port=7071, auth_key="mengya2024"):
|
||||
"""
|
||||
初始化WebSocket远程命令API服务器
|
||||
|
||||
Args:
|
||||
game_server: 游戏服务器实例
|
||||
host: WebSocket服务器监听地址
|
||||
port: WebSocket服务器监听端口
|
||||
auth_key: 认证密钥
|
||||
"""
|
||||
self.game_server = game_server
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.auth_key = auth_key
|
||||
self.server = None
|
||||
self.clients = {} # 存储已连接的客户端
|
||||
self.console_api = ConsoleCommandsAPI(game_server)
|
||||
self.running = False
|
||||
|
||||
async def register_client(self, websocket, path=None):
|
||||
"""注册新的客户端连接"""
|
||||
client_id = f"{websocket.remote_address[0]}:{websocket.remote_address[1]}_{int(time.time())}"
|
||||
self.clients[client_id] = {
|
||||
"websocket": websocket,
|
||||
"authenticated": False,
|
||||
"connect_time": time.time()
|
||||
}
|
||||
|
||||
try:
|
||||
# 发送欢迎消息
|
||||
await self.send_message(websocket, {
|
||||
"type": "welcome",
|
||||
"message": "欢迎连接到萌芽农场远程控制台",
|
||||
"server_version": getattr(self.game_server, 'server_version', '2.2.0'),
|
||||
"require_auth": True
|
||||
})
|
||||
|
||||
# 处理客户端消息
|
||||
async for message in websocket:
|
||||
await self.handle_message(client_id, message)
|
||||
|
||||
except websockets.exceptions.ConnectionClosed:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"❌ 客户端 {client_id} 连接处理出错: {str(e)}")
|
||||
finally:
|
||||
# 清理客户端连接
|
||||
if client_id in self.clients:
|
||||
del self.clients[client_id]
|
||||
print(f"🔌 客户端 {client_id} 已断开连接")
|
||||
|
||||
async def handle_message(self, client_id: str, message: str):
|
||||
"""处理客户端消息"""
|
||||
try:
|
||||
data = json.loads(message)
|
||||
message_type = data.get("type", "")
|
||||
|
||||
if message_type == "auth":
|
||||
await self.handle_auth(client_id, data)
|
||||
elif message_type == "command":
|
||||
await self.handle_command(client_id, data)
|
||||
elif message_type == "ping":
|
||||
await self.handle_ping(client_id, data)
|
||||
else:
|
||||
await self.send_error(client_id, f"未知消息类型: {message_type}")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
await self.send_error(client_id, "无效的JSON格式")
|
||||
except Exception as e:
|
||||
await self.send_error(client_id, f"处理消息时出错: {str(e)}")
|
||||
|
||||
async def handle_auth(self, client_id: str, data: Dict[str, Any]):
|
||||
"""处理客户端认证"""
|
||||
if client_id not in self.clients:
|
||||
return
|
||||
|
||||
provided_key = data.get("auth_key", "")
|
||||
|
||||
if provided_key == self.auth_key:
|
||||
self.clients[client_id]["authenticated"] = True
|
||||
await self.send_message(self.clients[client_id]["websocket"], {
|
||||
"type": "auth_result",
|
||||
"success": True,
|
||||
"message": "认证成功,欢迎使用远程控制台"
|
||||
})
|
||||
print(f"✅ 客户端 {client_id} 认证成功")
|
||||
else:
|
||||
await self.send_message(self.clients[client_id]["websocket"], {
|
||||
"type": "auth_result",
|
||||
"success": False,
|
||||
"message": "认证失败,密钥错误"
|
||||
})
|
||||
print(f"❌ 客户端 {client_id} 认证失败")
|
||||
|
||||
async def handle_command(self, client_id: str, data: Dict[str, Any]):
|
||||
"""处理控制台命令"""
|
||||
if client_id not in self.clients:
|
||||
return
|
||||
|
||||
# 检查是否已认证
|
||||
if not self.clients[client_id]["authenticated"]:
|
||||
await self.send_error(client_id, "请先进行认证")
|
||||
return
|
||||
|
||||
command = data.get("command", "").strip()
|
||||
if not command:
|
||||
await self.send_error(client_id, "命令不能为空")
|
||||
return
|
||||
|
||||
# 执行命令并捕获输出
|
||||
try:
|
||||
# 重定向标准输出来捕获命令执行结果
|
||||
import io
|
||||
import sys
|
||||
|
||||
old_stdout = sys.stdout
|
||||
sys.stdout = captured_output = io.StringIO()
|
||||
|
||||
# 执行命令
|
||||
success = self.console_api.process_command(command)
|
||||
|
||||
# 恢复标准输出
|
||||
sys.stdout = old_stdout
|
||||
output = captured_output.getvalue()
|
||||
|
||||
# 发送执行结果
|
||||
await self.send_message(self.clients[client_id]["websocket"], {
|
||||
"type": "command_result",
|
||||
"command": command,
|
||||
"success": success,
|
||||
"output": output if output else ("命令执行成功" if success else "命令执行失败")
|
||||
})
|
||||
|
||||
print(f"📝 客户端 {client_id} 执行命令: {command} - {'成功' if success else '失败'}")
|
||||
|
||||
except Exception as e:
|
||||
await self.send_error(client_id, f"执行命令时出错: {str(e)}")
|
||||
|
||||
async def handle_ping(self, client_id: str, data: Dict[str, Any]):
|
||||
"""处理ping请求"""
|
||||
if client_id not in self.clients:
|
||||
return
|
||||
|
||||
await self.send_message(self.clients[client_id]["websocket"], {
|
||||
"type": "pong",
|
||||
"timestamp": time.time()
|
||||
})
|
||||
|
||||
async def send_message(self, websocket, data: Dict[str, Any]):
|
||||
"""发送消息到客户端"""
|
||||
try:
|
||||
message = json.dumps(data, ensure_ascii=False)
|
||||
await websocket.send(message)
|
||||
except Exception as e:
|
||||
print(f"❌ 发送消息失败: {str(e)}")
|
||||
|
||||
async def send_error(self, client_id: str, error_message: str):
|
||||
"""发送错误消息到客户端"""
|
||||
if client_id in self.clients:
|
||||
await self.send_message(self.clients[client_id]["websocket"], {
|
||||
"type": "error",
|
||||
"message": error_message
|
||||
})
|
||||
|
||||
def start_server(self):
|
||||
"""启动WebSocket服务器"""
|
||||
if self.running:
|
||||
return
|
||||
|
||||
async def run_server_async():
|
||||
try:
|
||||
self.server = await websockets.serve(
|
||||
self.register_client,
|
||||
self.host,
|
||||
self.port
|
||||
)
|
||||
|
||||
self.running = True
|
||||
print(f"🌐 WebSocket远程控制台服务器已启动: ws://{self.host}:{self.port}")
|
||||
print(f"🔑 认证密钥: {self.auth_key}")
|
||||
|
||||
# 保持服务器运行
|
||||
await self.server.wait_closed()
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ WebSocket服务器启动失败: {str(e)}")
|
||||
self.running = False
|
||||
|
||||
def run_server():
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
try:
|
||||
loop.run_until_complete(run_server_async())
|
||||
except Exception as e:
|
||||
print(f"❌ WebSocket服务器线程异常: {str(e)}")
|
||||
self.running = False
|
||||
|
||||
# 在新线程中运行WebSocket服务器
|
||||
server_thread = threading.Thread(target=run_server, daemon=True)
|
||||
server_thread.start()
|
||||
|
||||
def stop_server(self):
|
||||
"""停止WebSocket服务器"""
|
||||
if not self.running:
|
||||
return
|
||||
|
||||
self.running = False
|
||||
|
||||
# 关闭所有客户端连接
|
||||
for client_id, client_info in list(self.clients.items()):
|
||||
try:
|
||||
asyncio.create_task(client_info["websocket"].close())
|
||||
except:
|
||||
pass
|
||||
|
||||
self.clients.clear()
|
||||
|
||||
if self.server:
|
||||
try:
|
||||
self.server.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
print("🌐 WebSocket远程控制台服务器已停止")
|
||||
|
||||
def get_status(self) -> Dict[str, Any]:
|
||||
"""获取服务器状态"""
|
||||
return {
|
||||
"running": self.running,
|
||||
"host": self.host,
|
||||
"port": self.port,
|
||||
"connected_clients": len(self.clients),
|
||||
"authenticated_clients": len([c for c in self.clients.values() if c["authenticated"]])
|
||||
}
|
||||
708
SproutFarm-Backend/module/WisdomTreeSystem.py
Normal file
708
SproutFarm-Backend/module/WisdomTreeSystem.py
Normal file
@@ -0,0 +1,708 @@
|
||||
"""智慧树系统相关逻辑模块。"""
|
||||
import time
|
||||
|
||||
|
||||
class WisdomTreeMixin:
|
||||
"""智慧树系统逻辑混入类。"""
|
||||
def _handle_wisdom_tree_operation(self, client_id, message):
|
||||
"""处理智慧树操作请求"""
|
||||
# 检查用户是否已登录
|
||||
logged_in, response = self._check_user_logged_in(client_id, "智慧树操作", "wisdom_tree_operation")
|
||||
if not logged_in:
|
||||
return self.send_data(client_id, response)
|
||||
|
||||
# 获取玩家数据
|
||||
player_data, username, response = self._load_player_data_with_check(client_id, "wisdom_tree_operation")
|
||||
if not player_data:
|
||||
return self.send_data(client_id, response)
|
||||
|
||||
operation_type = message.get("operation_type", "")
|
||||
|
||||
# 检查并修复智慧树配置格式
|
||||
self._check_and_fix_wisdom_tree_config(player_data, username)
|
||||
|
||||
# 获取修复后的智慧树配置
|
||||
wisdom_tree_config = player_data["智慧树配置"]
|
||||
|
||||
# 处理不同的操作类型
|
||||
if operation_type == "water":
|
||||
return self._process_wisdom_tree_water(client_id, player_data, username, wisdom_tree_config)
|
||||
elif operation_type == "fertilize":
|
||||
return self._process_wisdom_tree_fertilize(client_id, player_data, username, wisdom_tree_config)
|
||||
elif operation_type == "kill_grass":
|
||||
return self._process_wisdom_tree_kill_grass(client_id, player_data, username, wisdom_tree_config)
|
||||
elif operation_type == "kill_bug":
|
||||
return self._process_wisdom_tree_kill_bug(client_id, player_data, username, wisdom_tree_config)
|
||||
elif operation_type == "play_music":
|
||||
return self._process_wisdom_tree_play_music(client_id, player_data, username, wisdom_tree_config)
|
||||
elif operation_type == "revive":
|
||||
return self._process_wisdom_tree_revive(client_id, player_data, username, wisdom_tree_config)
|
||||
elif operation_type == "get_random_message":
|
||||
return self._process_wisdom_tree_get_random_message(client_id, player_data, username, wisdom_tree_config)
|
||||
else:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "未知的智慧树操作类型",
|
||||
"operation_type": operation_type
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_water(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理智慧树浇水"""
|
||||
# 检查智慧树是否死亡
|
||||
if wisdom_tree_config["当前生命值"] <= 0:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "智慧树已死亡,请先复活!",
|
||||
"operation_type": "water"
|
||||
})
|
||||
|
||||
# 浇水费用
|
||||
water_cost = 100
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < water_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,浇水需要 {water_cost} 金币",
|
||||
"operation_type": "water"
|
||||
})
|
||||
|
||||
# 执行浇水
|
||||
player_data["钱币"] -= water_cost
|
||||
|
||||
# 浇水经验:50-150随机
|
||||
import random
|
||||
exp_gained = random.randint(50, 150)
|
||||
wisdom_tree_config["当前经验值"] += exp_gained
|
||||
|
||||
# 浇水高度:40%概率增加1-2高度
|
||||
height_gained = 0
|
||||
if random.random() < 0.4: # 40%概率
|
||||
height_gained = random.randint(1, 2)
|
||||
wisdom_tree_config["高度"] = min(100, wisdom_tree_config["高度"] + height_gained)
|
||||
|
||||
# 检查等级提升
|
||||
level_up_occurred = self._check_wisdom_tree_level_up(wisdom_tree_config)
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
height_msg = f",高度+{height_gained}" if height_gained > 0 else ""
|
||||
self.log('INFO', f"玩家 {username} 给智慧树浇水,花费 {water_cost} 金币,经验+{exp_gained}{height_msg}", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": f"浇水成功!经验+{exp_gained}{height_msg}",
|
||||
"operation_type": "water",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_fertilize(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理智慧树施肥"""
|
||||
# 检查智慧树是否死亡
|
||||
if wisdom_tree_config["当前生命值"] <= 0:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "智慧树已死亡,请先复活!",
|
||||
"operation_type": "fertilize"
|
||||
})
|
||||
|
||||
# 施肥费用
|
||||
fertilize_cost = 200
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < fertilize_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,施肥需要 {fertilize_cost} 金币",
|
||||
"operation_type": "fertilize"
|
||||
})
|
||||
|
||||
# 执行施肥
|
||||
player_data["钱币"] -= fertilize_cost
|
||||
|
||||
# 施肥经验:10-40随机
|
||||
import random
|
||||
exp_gained = random.randint(10, 40)
|
||||
wisdom_tree_config["当前经验值"] += exp_gained
|
||||
|
||||
# 施肥高度:80%概率增加1-7高度
|
||||
height_gained = 0
|
||||
if random.random() < 0.8: # 80%概率
|
||||
height_gained = random.randint(1, 7)
|
||||
wisdom_tree_config["高度"] = min(100, wisdom_tree_config["高度"] + height_gained)
|
||||
|
||||
# 检查等级提升
|
||||
level_up_occurred = self._check_wisdom_tree_level_up(wisdom_tree_config)
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
height_msg = f",高度+{height_gained}" if height_gained > 0 else ""
|
||||
self.log('INFO', f"玩家 {username} 给智慧树施肥,花费 {fertilize_cost} 金币,经验+{exp_gained}{height_msg}", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": f"施肥成功!经验+{exp_gained}{height_msg}",
|
||||
"operation_type": "fertilize",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_kill_grass(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理智慧树除草"""
|
||||
# 检查智慧树是否死亡
|
||||
if wisdom_tree_config["当前生命值"] <= 0:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "智慧树已死亡,请先复活!",
|
||||
"operation_type": "kill_grass"
|
||||
})
|
||||
|
||||
# 除草费用
|
||||
kill_grass_cost = 150
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < kill_grass_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,除草需要 {kill_grass_cost} 金币",
|
||||
"operation_type": "kill_grass"
|
||||
})
|
||||
|
||||
# 执行除草
|
||||
import time
|
||||
player_data["钱币"] -= kill_grass_cost
|
||||
max_health = wisdom_tree_config["最大生命值"]
|
||||
wisdom_tree_config["当前生命值"] = min(max_health, wisdom_tree_config["当前生命值"] + 10)
|
||||
wisdom_tree_config["距离上一次除草时间"] = int(time.time())
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 给智慧树除草,花费 {kill_grass_cost} 金币,生命值+10", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": "除草成功!生命值+10",
|
||||
"operation_type": "kill_grass",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_kill_bug(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理智慧树杀虫"""
|
||||
# 检查智慧树是否死亡
|
||||
if wisdom_tree_config["当前生命值"] <= 0:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "智慧树已死亡,请先复活!",
|
||||
"operation_type": "kill_bug"
|
||||
})
|
||||
|
||||
# 杀虫费用
|
||||
kill_bug_cost = 150
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < kill_bug_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,杀虫需要 {kill_bug_cost} 金币",
|
||||
"operation_type": "kill_bug"
|
||||
})
|
||||
|
||||
# 执行杀虫
|
||||
player_data["钱币"] -= kill_bug_cost
|
||||
max_health = wisdom_tree_config["最大生命值"]
|
||||
wisdom_tree_config["当前生命值"] = min(max_health, wisdom_tree_config["当前生命值"] + 15)
|
||||
wisdom_tree_config["距离上一次杀虫时间"] = int(time.time())
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 给智慧树杀虫,花费 {kill_bug_cost} 金币,生命值+15", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": "杀虫成功!生命值+15",
|
||||
"operation_type": "kill_bug",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_play_music(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理智慧树放音乐"""
|
||||
# 检查智慧树是否死亡
|
||||
if wisdom_tree_config["当前生命值"] <= 0:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "智慧树已死亡,请先复活!",
|
||||
"operation_type": "play_music"
|
||||
})
|
||||
|
||||
# 放音乐费用
|
||||
play_music_cost = 100
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < play_music_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,放音乐需要 {play_music_cost} 金币",
|
||||
"operation_type": "play_music"
|
||||
})
|
||||
|
||||
# 执行放音乐
|
||||
player_data["钱币"] -= play_music_cost
|
||||
|
||||
# 从智慧树消息库中随机获取一条消息
|
||||
random_message = self._get_random_wisdom_tree_message()
|
||||
if random_message:
|
||||
wisdom_tree_config["智慧树显示的话"] = random_message.get("content", "")
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 给智慧树放音乐,花费 {play_music_cost} 金币,获得随机消息", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": "放音乐成功!获得了一条神秘消息",
|
||||
"operation_type": "play_music",
|
||||
"random_message": random_message,
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_revive(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理智慧树复活"""
|
||||
# 检查智慧树是否真的死亡
|
||||
if wisdom_tree_config["当前生命值"] > 0:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "智慧树还活着,不需要复活!",
|
||||
"operation_type": "revive"
|
||||
})
|
||||
|
||||
# 复活费用
|
||||
revive_cost = 1000
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < revive_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,复活智慧树需要 {revive_cost} 金币",
|
||||
"operation_type": "revive"
|
||||
})
|
||||
|
||||
# 执行复活
|
||||
player_data["钱币"] -= revive_cost
|
||||
wisdom_tree_config["当前生命值"] = wisdom_tree_config["最大生命值"]
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 复活了智慧树,花费 {revive_cost} 金币", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": "智慧树复活成功!",
|
||||
"operation_type": "revive",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
|
||||
def _process_wisdom_tree_get_random_message(self, client_id, player_data, username, wisdom_tree_config):
|
||||
"""处理获取随机智慧树消息"""
|
||||
# 从智慧树消息库中随机获取一条消息
|
||||
random_message = self._get_random_wisdom_tree_message()
|
||||
|
||||
if random_message:
|
||||
wisdom_tree_config["智慧树显示的话"] = random_message.get("content", "")
|
||||
|
||||
# 保存数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": True,
|
||||
"message": "获得了一条神秘消息",
|
||||
"operation_type": "get_random_message",
|
||||
"random_message": random_message,
|
||||
"updated_data": {
|
||||
"智慧树配置": wisdom_tree_config
|
||||
}
|
||||
})
|
||||
else:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_operation_response",
|
||||
"success": False,
|
||||
"message": "暂时没有新消息",
|
||||
"operation_type": "get_random_message"
|
||||
})
|
||||
|
||||
def _handle_wisdom_tree_message(self, client_id, message):
|
||||
"""处理智慧树消息发送请求"""
|
||||
# 检查用户是否已登录
|
||||
logged_in, response = self._check_user_logged_in(client_id, "发送智慧树消息", "wisdom_tree_message")
|
||||
if not logged_in:
|
||||
return self.send_data(client_id, response)
|
||||
|
||||
# 获取玩家数据
|
||||
player_data, username, response = self._load_player_data_with_check(client_id, "wisdom_tree_message")
|
||||
if not player_data:
|
||||
return self.send_data(client_id, response)
|
||||
|
||||
message_content = message.get("message", "").strip()
|
||||
|
||||
# 验证消息内容
|
||||
if not message_content:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_message_response",
|
||||
"success": False,
|
||||
"message": "消息内容不能为空"
|
||||
})
|
||||
|
||||
if len(message_content) > 100:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_message_response",
|
||||
"success": False,
|
||||
"message": "消息长度不能超过100个字符"
|
||||
})
|
||||
|
||||
# 发送消息费用
|
||||
send_cost = 50
|
||||
|
||||
# 检查金钱是否足够
|
||||
if player_data["钱币"] < send_cost:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_message_response",
|
||||
"success": False,
|
||||
"message": f"金钱不足,发送消息需要 {send_cost} 金币"
|
||||
})
|
||||
|
||||
# 扣除费用
|
||||
player_data["钱币"] -= send_cost
|
||||
|
||||
# 保存消息到智慧树消息库
|
||||
success = self._save_wisdom_tree_message(username, message_content)
|
||||
|
||||
if success:
|
||||
# 保存玩家数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 发送智慧树消息,花费 {send_cost} 金币:{message_content}", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_message_response",
|
||||
"success": True,
|
||||
"message": "消息发送成功!",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"]
|
||||
}
|
||||
})
|
||||
else:
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_message_response",
|
||||
"success": False,
|
||||
"message": "消息发送失败,请重试"
|
||||
})
|
||||
|
||||
def _handle_get_wisdom_tree_config(self, client_id, message):
|
||||
"""处理获取智慧树配置请求"""
|
||||
# 检查用户是否已登录
|
||||
logged_in, response = self._check_user_logged_in(client_id, "获取智慧树配置", "get_wisdom_tree_config")
|
||||
if not logged_in:
|
||||
return self.send_data(client_id, response)
|
||||
|
||||
# 获取玩家数据
|
||||
player_data, username, response = self._load_player_data_with_check(client_id, "get_wisdom_tree_config")
|
||||
if not player_data:
|
||||
return self.send_data(client_id, response)
|
||||
|
||||
# 检查并修复智慧树配置
|
||||
self._check_and_fix_wisdom_tree_config(player_data, username)
|
||||
|
||||
# 保存修复后的数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
# 返回智慧树配置
|
||||
wisdom_tree_config = player_data.get("智慧树配置", {})
|
||||
|
||||
self.log('INFO', f"玩家 {username} 请求智慧树配置", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "wisdom_tree_config_response",
|
||||
"success": True,
|
||||
"config": wisdom_tree_config
|
||||
})
|
||||
|
||||
def _check_wisdom_tree_level_up(self, wisdom_tree_config):
|
||||
"""检查智慧树等级提升"""
|
||||
current_level = wisdom_tree_config["等级"]
|
||||
current_experience = wisdom_tree_config["当前经验值"]
|
||||
max_experience = wisdom_tree_config["最大经验值"]
|
||||
level_ups = 0
|
||||
|
||||
# 检查是否可以升级(最高等级20)
|
||||
while current_level < 20 and current_experience >= max_experience:
|
||||
# 升级
|
||||
current_level += 1
|
||||
current_experience -= max_experience # 扣除升级所需经验
|
||||
level_ups += 1
|
||||
|
||||
# 计算新等级的最大经验值
|
||||
max_experience = self._calculate_wisdom_tree_max_exp(current_level)
|
||||
|
||||
self.log('INFO', f"智慧树等级提升到 {current_level} 级,新的最大经验值: {max_experience}", 'SERVER')
|
||||
|
||||
# 每升一级,最大生命值+2,当前生命值也+2
|
||||
if level_ups > 0:
|
||||
health_bonus = level_ups * 2
|
||||
wisdom_tree_config["最大生命值"] = min(200, wisdom_tree_config["最大生命值"] + health_bonus)
|
||||
wisdom_tree_config["当前生命值"] = min(wisdom_tree_config["最大生命值"], wisdom_tree_config["当前生命值"] + health_bonus)
|
||||
self.log('INFO', f"智慧树升级 {level_ups} 级,最大生命值+{health_bonus}", 'SERVER')
|
||||
|
||||
# 更新配置
|
||||
wisdom_tree_config["等级"] = current_level
|
||||
wisdom_tree_config["当前经验值"] = current_experience
|
||||
wisdom_tree_config["最大经验值"] = max_experience
|
||||
|
||||
return level_ups > 0
|
||||
|
||||
def _get_random_wisdom_tree_message(self):
|
||||
"""从智慧树消息库中随机获取一条消息"""
|
||||
import os
|
||||
import json
|
||||
import random
|
||||
|
||||
# 优先从MongoDB读取
|
||||
if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected():
|
||||
try:
|
||||
wisdom_tree_data = self.mongo_api.get_wisdom_tree_config()
|
||||
if wisdom_tree_data:
|
||||
messages = wisdom_tree_data.get("messages", [])
|
||||
if messages:
|
||||
selected_message = random.choice(messages)
|
||||
self.log('INFO', f"成功从MongoDB获取智慧树消息", 'SERVER')
|
||||
return selected_message
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"从MongoDB读取智慧树消息失败: {e}", 'SERVER')
|
||||
|
||||
# 回退到JSON文件
|
||||
wisdom_tree_data_path = os.path.join(os.path.dirname(__file__), "config", "wisdom_tree_data.json")
|
||||
|
||||
try:
|
||||
with open(wisdom_tree_data_path, 'r', encoding='utf-8') as f:
|
||||
wisdom_tree_data = json.load(f)
|
||||
|
||||
messages = wisdom_tree_data.get("messages", [])
|
||||
if messages:
|
||||
selected_message = random.choice(messages)
|
||||
self.log('INFO', f"成功从JSON文件获取智慧树消息", 'SERVER')
|
||||
return selected_message
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"从JSON文件读取智慧树消息失败: {e}", 'SERVER')
|
||||
return None
|
||||
|
||||
def _save_wisdom_tree_message(self, username, message_content):
|
||||
"""保存智慧树消息到消息库"""
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
|
||||
# 创建新消息
|
||||
new_message = {
|
||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||||
"sender": username,
|
||||
"content": message_content,
|
||||
"id": str(uuid.uuid4())
|
||||
}
|
||||
|
||||
# 优先保存到MongoDB
|
||||
if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected():
|
||||
try:
|
||||
# 获取现有数据
|
||||
wisdom_tree_data = self.mongo_api.get_wisdom_tree_config()
|
||||
if not wisdom_tree_data:
|
||||
wisdom_tree_data = {
|
||||
"messages": [],
|
||||
"total_messages": 0,
|
||||
"last_update": ""
|
||||
}
|
||||
|
||||
# 添加新消息
|
||||
wisdom_tree_data["messages"].append(new_message)
|
||||
wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"])
|
||||
wisdom_tree_data["last_update"] = new_message["timestamp"]
|
||||
|
||||
# 保持最多1000条消息
|
||||
if len(wisdom_tree_data["messages"]) > 1000:
|
||||
wisdom_tree_data["messages"] = wisdom_tree_data["messages"][-1000:]
|
||||
wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"])
|
||||
|
||||
# 保存到MongoDB
|
||||
if self.mongo_api.update_wisdom_tree_config(wisdom_tree_data):
|
||||
self.log('INFO', f"成功保存智慧树消息到MongoDB: {username}", 'SERVER')
|
||||
return True
|
||||
else:
|
||||
self.log('ERROR', f"保存智慧树消息到MongoDB失败: {username}", 'SERVER')
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"MongoDB保存智慧树消息异常: {e}", 'SERVER')
|
||||
|
||||
# 回退到JSON文件
|
||||
wisdom_tree_data_path = os.path.join(os.path.dirname(__file__), "config", "wisdom_tree_data.json")
|
||||
|
||||
try:
|
||||
# 读取现有数据
|
||||
if os.path.exists(wisdom_tree_data_path):
|
||||
with open(wisdom_tree_data_path, 'r', encoding='utf-8') as f:
|
||||
wisdom_tree_data = json.load(f)
|
||||
else:
|
||||
wisdom_tree_data = {
|
||||
"messages": [],
|
||||
"total_messages": 0,
|
||||
"last_update": ""
|
||||
}
|
||||
|
||||
# 添加到消息列表
|
||||
wisdom_tree_data["messages"].append(new_message)
|
||||
wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"])
|
||||
wisdom_tree_data["last_update"] = new_message["timestamp"]
|
||||
|
||||
# 保持最多1000条消息
|
||||
if len(wisdom_tree_data["messages"]) > 1000:
|
||||
wisdom_tree_data["messages"] = wisdom_tree_data["messages"][-1000:]
|
||||
wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"])
|
||||
|
||||
# 保存数据
|
||||
with open(wisdom_tree_data_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(wisdom_tree_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
self.log('INFO', f"成功保存智慧树消息到JSON文件: {username}", 'SERVER')
|
||||
return True
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"保存智慧树消息到JSON文件失败: {e}", 'SERVER')
|
||||
return False
|
||||
|
||||
def check_wisdom_tree_health_decay(self):
|
||||
"""检查智慧树生命值衰减"""
|
||||
import time
|
||||
|
||||
current_time = int(time.time())
|
||||
processed_count = 0
|
||||
|
||||
# 检查所有在线玩家
|
||||
for client_id in self.user_data:
|
||||
if self.user_data[client_id].get("logged_in", False):
|
||||
username = self.user_data[client_id]["username"]
|
||||
player_data = self.load_player_data(username)
|
||||
if player_data and "智慧树配置" in player_data:
|
||||
self._process_wisdom_tree_decay(player_data["智慧树配置"], username)
|
||||
self.save_player_data(username, player_data)
|
||||
processed_count += 1
|
||||
|
||||
# 注释:缓存机制已移除,只处理在线玩家的智慧树衰减
|
||||
|
||||
if processed_count > 0:
|
||||
self.log('INFO', f"已处理 {processed_count} 个玩家的智慧树生命值衰减", 'SERVER')
|
||||
|
||||
def _process_wisdom_tree_decay(self, wisdom_tree_config, username):
|
||||
"""处理单个玩家的智慧树生命值衰减"""
|
||||
import time
|
||||
import random
|
||||
|
||||
current_time = int(time.time())
|
||||
|
||||
# 获取上次除草和杀虫时间,处理空字符串和无效值
|
||||
last_grass_time_raw = wisdom_tree_config.get("距离上一次除草时间", current_time)
|
||||
last_bug_time_raw = wisdom_tree_config.get("距离上一次杀虫时间", current_time)
|
||||
|
||||
# 处理空字符串和无效时间戳
|
||||
try:
|
||||
last_grass_time = int(last_grass_time_raw) if last_grass_time_raw and str(last_grass_time_raw).strip() else current_time
|
||||
except (ValueError, TypeError):
|
||||
last_grass_time = current_time
|
||||
|
||||
try:
|
||||
last_bug_time = int(last_bug_time_raw) if last_bug_time_raw and str(last_bug_time_raw).strip() else current_time
|
||||
except (ValueError, TypeError):
|
||||
last_bug_time = current_time
|
||||
|
||||
# 如果时间戳无效(为0或负数),设置为当前时间
|
||||
if last_grass_time <= 0:
|
||||
last_grass_time = current_time
|
||||
if last_bug_time <= 0:
|
||||
last_bug_time = current_time
|
||||
|
||||
# 检查是否3天没有除草
|
||||
days_since_grass = (current_time - last_grass_time) / 86400 # 转换为天数
|
||||
if days_since_grass >= 3:
|
||||
# 计算应该衰减的天数
|
||||
decay_days = int(days_since_grass)
|
||||
if decay_days > 0:
|
||||
# 每天减少1-3血量
|
||||
total_decay = 0
|
||||
for _ in range(decay_days):
|
||||
daily_decay = random.randint(1, 3)
|
||||
total_decay += daily_decay
|
||||
|
||||
wisdom_tree_config["当前生命值"] = max(0, wisdom_tree_config["当前生命值"] - total_decay)
|
||||
self.log('INFO', f"玩家 {username} 的智慧树因{decay_days}天未除草,生命值减少{total_decay}", 'SERVER')
|
||||
|
||||
# 更新除草时间为当前时间,避免重复扣血
|
||||
wisdom_tree_config["距离上一次除草时间"] = current_time
|
||||
|
||||
# 检查是否3天没有杀虫
|
||||
days_since_bug = (current_time - last_bug_time) / 86400 # 转换为天数
|
||||
if days_since_bug >= 3:
|
||||
# 计算应该衰减的天数
|
||||
decay_days = int(days_since_bug)
|
||||
if decay_days > 0:
|
||||
# 每天减少1-3血量
|
||||
total_decay = 0
|
||||
for _ in range(decay_days):
|
||||
daily_decay = random.randint(1, 3)
|
||||
total_decay += daily_decay
|
||||
|
||||
wisdom_tree_config["当前生命值"] = max(0, wisdom_tree_config["当前生命值"] - total_decay)
|
||||
self.log('INFO', f"玩家 {username} 的智慧树因{decay_days}天未杀虫,生命值减少{total_decay}", 'SERVER')
|
||||
|
||||
# 更新杀虫时间为当前时间,避免重复扣血
|
||||
wisdom_tree_config["距离上一次杀虫时间"] = current_time
|
||||
25
SproutFarm-Backend/module/__init__.py
Normal file
25
SproutFarm-Backend/module/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
萌芽农场服务器模块包
|
||||
包含所有服务器外置插件模块
|
||||
"""
|
||||
|
||||
# 导入所有模块类
|
||||
from .SMYMongoDBAPI import SMYMongoDBAPI
|
||||
from .QQEmailSendAPI import QQMailAPI, EmailVerification
|
||||
from .ConsoleCommandsAPI import ConsoleCommandsAPI # 明确导入类名,避免循环导入
|
||||
from .SpecialFarm import SpecialFarmManager # 导入特殊农场管理器
|
||||
from .WSRemoteCmdApi import WSRemoteCmdApi
|
||||
from .NetworkCore import MessageHandler
|
||||
|
||||
|
||||
# 定义模块导出列表
|
||||
__all__ = [
|
||||
'SMYMongoDBAPI',
|
||||
'QQMailAPI',
|
||||
'EmailVerification',
|
||||
'ConsoleCommandsAPI',
|
||||
'SpecialFarmManager',
|
||||
'WSRemoteCmdApi'
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
BIN
SproutFarm-Backend/module/__pycache__/PetSystem.cpython-313.pyc
Normal file
BIN
SproutFarm-Backend/module/__pycache__/PetSystem.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
SproutFarm-Backend/module/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
SproutFarm-Backend/module/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
Reference in New Issue
Block a user