完成部分服务器数据向MongoDB数据库迁移

This commit is contained in:
2025-07-20 21:05:31 +08:00
parent e466cde9d5
commit ec94e10fda
28 changed files with 2386 additions and 1785 deletions

View File

@@ -0,0 +1,170 @@
# 萌芽农场 MongoDB 迁移说明
## 概述
本文档描述了萌芽农场项目从JSON配置文件迁移到MongoDB数据库的过程。目前已完成每日签到配置的迁移为后续其他配置的迁移奠定了基础。
## 迁移内容
### 1. 已完成的迁移
#### 每日签到配置 (daily_checkin_config.json)
- **原位置**: `Server/config/daily_checkin_config.json`
- **新位置**: MongoDB数据库 `mengyafarm.gameconfig` 集合
- **文档ID**: `687cce278e77ba00a7414ba2`
- **状态**: ✅ 已完成迁移
### 2. 数据库配置
#### 测试环境
- **地址**: `localhost:27017`
- **数据库**: `mengyafarm`
- **集合**: `gameconfig`
#### 生产环境
- **地址**: `192.168.31.233:27017`
- **数据库**: `mengyafarm`
- **集合**: `gameconfig`
## 技术实现
### 1. MongoDB API (SMYMongoDBAPI.py)
创建了专门的MongoDB API类提供以下功能
#### 核心功能
- 数据库连接管理(测试/生产环境)
- 游戏配置的读取和更新
- 通用文档操作(增删改查)
- 错误处理和日志记录
#### 主要方法
```python
# 配置管理
get_daily_checkin_config() # 获取每日签到配置
update_daily_checkin_config() # 更新每日签到配置
get_game_config(config_type) # 获取通用游戏配置
set_game_config(config_type, data) # 设置通用游戏配置
# 通用操作
insert_document(collection, doc) # 插入文档
find_documents(collection, query) # 查找文档
update_document(collection, query, update) # 更新文档
delete_document(collection, query) # 删除文档
```
### 2. 服务器集成 (TCPGameServer.py)
#### 修改内容
- 添加MongoDB API导入和初始化
- 修改 `_load_daily_check_in_config()` 方法优先使用MongoDB
- 添加 `_update_daily_checkin_config_to_mongodb()` 方法
- 实现优雅降级MongoDB失败时自动回退到JSON文件
#### 配置加载策略
1. **优先**: 尝试从MongoDB获取配置
2. **备选**: 从JSON文件加载配置
3. **兜底**: 使用默认配置
## 测试验证
### 1. MongoDB API测试
运行 `python SMYMongoDBAPI.py` 进行基础功能测试
### 2. 迁移功能测试
运行 `python test_mongodb_migration.py` 进行完整迁移测试
### 3. 服务器集成测试
运行 `python test_server_mongodb.py` 进行服务器集成测试
## 使用说明
### 1. 环境配置
#### 测试环境
```python
api = SMYMongoDBAPI("test") # 连接到 localhost:27017
```
#### 生产环境
```python
api = SMYMongoDBAPI("production") # 连接到 192.168.31.233:27017
```
### 2. 获取配置
```python
# 获取每日签到配置
config = api.get_daily_checkin_config()
# 获取通用游戏配置
config = api.get_game_config("config_type")
```
### 3. 更新配置
```python
# 更新每日签到配置
success = api.update_daily_checkin_config(new_config)
# 设置通用游戏配置
success = api.set_game_config("config_type", config_data)
```
## 后续迁移计划
### 1. 待迁移的配置文件
- [ ] `item_config.json` - 道具配置
- [ ] `pet_data.json` - 宠物配置
- [ ] 其他游戏配置文件
### 2. 迁移步骤
1. 将JSON文件导入到MongoDB
2. 修改对应的加载方法
3. 添加更新方法
4. 编写测试用例
5. 验证功能正常
### 3. 迁移原则
- **渐进式迁移**: 一次迁移一个配置文件
- **向后兼容**: 保持JSON文件作为备选方案
- **充分测试**: 每个迁移都要有完整的测试覆盖
- **文档更新**: 及时更新相关文档
## 注意事项
### 1. 数据安全
- 定期备份MongoDB数据
- 重要配置修改前先备份
- 测试环境验证后再应用到生产环境
### 2. 性能考虑
- MongoDB连接池管理
- 配置缓存策略
- 错误重试机制
### 3. 监控和日志
- 记录配置加载来源
- 监控MongoDB连接状态
- 记录配置更新操作
## 故障排除
### 1. MongoDB连接失败
- 检查MongoDB服务是否启动
- 验证连接地址和端口
- 检查网络连接
### 2. 配置加载失败
- 检查MongoDB中是否存在对应文档
- 验证文档格式是否正确
- 查看服务器日志获取详细错误信息
### 3. 配置更新失败
- 检查MongoDB权限
- 验证更新数据格式
- 确认文档ID是否正确
## 总结
本次迁移成功实现了每日签到配置从JSON文件到MongoDB的迁移建立了完整的MongoDB API框架为后续其他配置的迁移提供了可靠的基础。迁移过程采用了渐进式和向后兼容的策略确保了系统的稳定性和可靠性。
通过测试验证MongoDB迁移功能运行正常服务器能够正确使用MongoDB中的配置数据同时保持了JSON文件的备选方案为后续的全面迁移奠定了坚实的基础。

705
Server/SMYMongoDBAPI.py Normal file
View File

@@ -0,0 +1,705 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
萌芽农场 MongoDB 数据库 API
作者: AI Assistant
功能: 提供MongoDB数据库连接和游戏配置管理功能
"""
import pymongo
import json
from typing import Dict, Any, Optional, List
import logging
from datetime import datetime
from bson import ObjectId
class SMYMongoDBAPI:
def __init__(self, environment: str = "test"):
"""
初始化MongoDB API
Args:
environment: 环境类型,"test" 表示测试环境,"production" 表示正式环境
"""
self.environment = environment
self.client = None
self.db = None
self.connected = False
# 配置数据库连接信息
self.config = {
"test": {
"host": "localhost",
"port": 27017,
"database": "mengyafarm"
},
"production": {
"host": "192.168.31.233",
"port": 27017,
"database": "mengyafarm"
}
}
# 设置日志
logging.basicConfig(level=logging.INFO)
self.logger = logging.getLogger(__name__)
# 连接数据库
self.connect()
def connect(self) -> bool:
"""
连接到MongoDB数据库
Returns:
bool: 连接是否成功
"""
try:
current_config = self.config[self.environment]
connection_string = f"mongodb://{current_config['host']}:{current_config['port']}/"
self.client = pymongo.MongoClient(
connection_string,
serverSelectionTimeoutMS=5000, # 5秒超时
connectTimeoutMS=5000,
socketTimeoutMS=5000
)
# 测试连接
self.client.admin.command('ping')
# 选择数据库
self.db = self.client[current_config['database']]
self.connected = True
self.logger.info(f"成功连接到MongoDB数据库 [{self.environment}]: {connection_string}")
return True
except Exception as e:
self.logger.error(f"连接MongoDB失败: {e}")
self.connected = False
return False
def disconnect(self):
"""断开数据库连接"""
if self.client:
self.client.close()
self.connected = False
self.logger.info("已断开MongoDB连接")
def is_connected(self) -> bool:
"""检查是否已连接到数据库"""
return self.connected and self.client is not None
def get_collection(self, collection_name: str):
"""
获取集合对象
Args:
collection_name: 集合名称
Returns:
Collection: MongoDB集合对象
"""
if not self.is_connected():
raise Exception("数据库未连接")
return self.db[collection_name]
# ========================= 游戏配置管理 =========================
def get_game_config(self, config_type: str) -> Optional[Dict[str, Any]]:
"""
获取游戏配置
Args:
config_type: 配置类型,如 "daily_checkin"
Returns:
Dict: 配置数据如果未找到返回None
"""
try:
collection = self.get_collection("gameconfig")
# 根据配置类型查找文档
query = {"config_type": config_type}
result = collection.find_one(query)
if result:
# 移除MongoDB的_id字段只返回配置数据
if "_id" in result:
del result["_id"]
if "config_type" in result:
del result["config_type"]
self.logger.info(f"成功获取游戏配置: {config_type}")
return result
else:
self.logger.warning(f"未找到游戏配置: {config_type}")
return None
except Exception as e:
self.logger.error(f"获取游戏配置失败 [{config_type}]: {e}")
return None
def get_daily_checkin_config(self) -> Optional[Dict[str, Any]]:
"""
获取每日签到配置
Returns:
Dict: 每日签到配置数据
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID查找
object_id = ObjectId("687cce278e77ba00a7414ba2")
result = collection.find_one({"_id": object_id})
if result:
# 移除MongoDB的_id字段
if "_id" in result:
del result["_id"]
self.logger.info("成功获取每日签到配置")
return result
else:
self.logger.warning("未找到每日签到配置")
return None
except Exception as e:
self.logger.error(f"获取每日签到配置失败: {e}")
return None
def set_game_config(self, config_type: str, config_data: Dict[str, Any]) -> bool:
"""
设置游戏配置
Args:
config_type: 配置类型
config_data: 配置数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection("gameconfig")
# 准备文档数据
document = {
"config_type": config_type,
"updated_at": datetime.now(),
**config_data
}
# 使用upsert更新或插入
query = {"config_type": config_type}
result = collection.replace_one(query, document, upsert=True)
if result.acknowledged:
self.logger.info(f"成功设置游戏配置: {config_type}")
return True
else:
self.logger.error(f"设置游戏配置失败: {config_type}")
return False
except Exception as e:
self.logger.error(f"设置游戏配置异常 [{config_type}]: {e}")
return False
def update_daily_checkin_config(self, config_data: Dict[str, Any]) -> bool:
"""
更新每日签到配置
Args:
config_data: 配置数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID更新
object_id = ObjectId("687cce278e77ba00a7414ba2")
# 添加更新时间
update_data = {
"updated_at": datetime.now(),
**config_data
}
result = collection.replace_one({"_id": object_id}, update_data)
if result.acknowledged and result.matched_count > 0:
self.logger.info("成功更新每日签到配置")
return True
else:
self.logger.error("更新每日签到配置失败")
return False
except Exception as e:
self.logger.error(f"更新每日签到配置异常: {e}")
return False
def get_lucky_draw_config(self) -> Optional[Dict[str, Any]]:
"""
获取幸运抽奖配置
Returns:
Dict: 幸运抽奖配置数据
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID查找
object_id = ObjectId("687cd52e8e77ba00a7414ba3")
result = collection.find_one({"_id": object_id})
if result:
# 移除MongoDB的_id字段和updated_at字段
if "_id" in result:
del result["_id"]
if "updated_at" in result:
del result["updated_at"]
self.logger.info("成功获取幸运抽奖配置")
return result
else:
self.logger.warning("未找到幸运抽奖配置")
return None
except Exception as e:
self.logger.error(f"获取幸运抽奖配置失败: {e}")
return None
def update_lucky_draw_config(self, config_data: Dict[str, Any]) -> bool:
"""
更新幸运抽奖配置
Args:
config_data: 配置数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID更新
object_id = ObjectId("687cd52e8e77ba00a7414ba3")
# 添加更新时间
update_data = {
"updated_at": datetime.now(),
**config_data
}
result = collection.replace_one({"_id": object_id}, update_data)
if result.acknowledged and result.matched_count > 0:
self.logger.info("成功更新幸运抽奖配置")
return True
else:
self.logger.error("更新幸运抽奖配置失败")
return False
except Exception as e:
self.logger.error(f"更新幸运抽奖配置异常: {e}")
return False
def get_new_player_config(self) -> Optional[Dict[str, Any]]:
"""
获取新手大礼包配置
Returns:
Dict: 新手大礼包配置数据
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID查找
object_id = ObjectId("687cdbd78e77ba00a7414ba4")
result = collection.find_one({"_id": object_id})
if result:
# 移除MongoDB的_id字段和updated_at字段
if "_id" in result:
del result["_id"]
if "updated_at" in result:
del result["updated_at"]
self.logger.info("成功获取新手大礼包配置")
return result
else:
self.logger.warning("未找到新手大礼包配置")
return None
except Exception as e:
self.logger.error(f"获取新手大礼包配置失败: {e}")
return None
def update_new_player_config(self, config_data: Dict[str, Any]) -> bool:
"""
更新新手大礼包配置
Args:
config_data: 配置数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID更新
object_id = ObjectId("687cdbd78e77ba00a7414ba4")
# 添加更新时间
update_data = {
"updated_at": datetime.now(),
**config_data
}
result = collection.replace_one({"_id": object_id}, update_data)
if result.acknowledged and result.matched_count > 0:
self.logger.info("成功更新新手大礼包配置")
return True
else:
self.logger.error("更新新手大礼包配置失败")
return False
except Exception as e:
self.logger.error(f"更新新手大礼包配置异常: {e}")
return False
def get_wisdom_tree_config(self) -> Optional[Dict[str, Any]]:
"""
获取智慧树配置
Returns:
Dict: 智慧树配置数据
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID查找
object_id = ObjectId("687cdfbe8e77ba00a7414ba5")
result = collection.find_one({"_id": object_id})
if result:
# 移除MongoDB的_id字段和updated_at字段
if "_id" in result:
del result["_id"]
if "updated_at" in result:
del result["updated_at"]
self.logger.info("成功获取智慧树配置")
return result
else:
self.logger.warning("未找到智慧树配置")
return None
except Exception as e:
self.logger.error(f"获取智慧树配置失败: {e}")
return None
def update_wisdom_tree_config(self, config_data: Dict[str, Any]) -> bool:
"""
更新智慧树配置
Args:
config_data: 配置数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID更新
object_id = ObjectId("687cdfbe8e77ba00a7414ba5")
# 添加更新时间
update_data = {
"updated_at": datetime.now(),
**config_data
}
result = collection.replace_one({"_id": object_id}, update_data)
if result.acknowledged and result.matched_count > 0:
self.logger.info("成功更新智慧树配置")
return True
else:
self.logger.error("更新智慧树配置失败")
return False
except Exception as e:
self.logger.error(f"更新智慧树配置异常: {e}")
return False
def get_online_gift_config(self) -> Optional[Dict[str, Any]]:
"""
获取在线礼包配置
Returns:
Dict: 在线礼包配置数据
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID查找
object_id = ObjectId("687ce7678e77ba00a7414ba6")
result = collection.find_one({"_id": object_id})
if result:
# 移除MongoDB的_id字段和updated_at字段
if "_id" in result:
del result["_id"]
if "updated_at" in result:
del result["updated_at"]
self.logger.info("成功获取在线礼包配置")
return result
else:
self.logger.warning("未找到在线礼包配置")
return None
except Exception as e:
self.logger.error(f"获取在线礼包配置失败: {e}")
return None
def update_online_gift_config(self, config_data: Dict[str, Any]) -> bool:
"""
更新在线礼包配置
Args:
config_data: 配置数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection("gameconfig")
# 使用已知的文档ID更新
object_id = ObjectId("687ce7678e77ba00a7414ba6")
# 添加更新时间
update_data = {
"updated_at": datetime.now(),
**config_data
}
result = collection.replace_one({"_id": object_id}, update_data)
if result.acknowledged and result.matched_count > 0:
self.logger.info("成功更新在线礼包配置")
return True
else:
self.logger.error("更新在线礼包配置失败")
return False
except Exception as e:
self.logger.error(f"更新在线礼包配置异常: {e}")
return False
# ========================= 通用数据库操作 =========================
def insert_document(self, collection_name: str, document: Dict[str, Any]) -> Optional[str]:
"""
插入文档
Args:
collection_name: 集合名称
document: 要插入的文档
Returns:
str: 插入的文档ID失败返回None
"""
try:
collection = self.get_collection(collection_name)
result = collection.insert_one(document)
if result.acknowledged:
self.logger.info(f"成功插入文档到集合 {collection_name}")
return str(result.inserted_id)
else:
return None
except Exception as e:
self.logger.error(f"插入文档失败 [{collection_name}]: {e}")
return None
def find_documents(self, collection_name: str, query: Dict[str, Any] = None,
limit: int = 0) -> List[Dict[str, Any]]:
"""
查找文档
Args:
collection_name: 集合名称
query: 查询条件
limit: 限制返回数量0表示不限制
Returns:
List: 文档列表
"""
try:
collection = self.get_collection(collection_name)
if query is None:
query = {}
cursor = collection.find(query)
if limit > 0:
cursor = cursor.limit(limit)
documents = list(cursor)
# 转换ObjectId为字符串
for doc in documents:
if "_id" in doc:
doc["_id"] = str(doc["_id"])
return documents
except Exception as e:
self.logger.error(f"查找文档失败 [{collection_name}]: {e}")
return []
def update_document(self, collection_name: str, query: Dict[str, Any],
update: Dict[str, Any]) -> bool:
"""
更新文档
Args:
collection_name: 集合名称
query: 查询条件
update: 更新数据
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection(collection_name)
result = collection.update_one(query, {"$set": update})
return result.acknowledged and result.matched_count > 0
except Exception as e:
self.logger.error(f"更新文档失败 [{collection_name}]: {e}")
return False
def delete_document(self, collection_name: str, query: Dict[str, Any]) -> bool:
"""
删除文档
Args:
collection_name: 集合名称
query: 查询条件
Returns:
bool: 是否成功
"""
try:
collection = self.get_collection(collection_name)
result = collection.delete_one(query)
return result.acknowledged and result.deleted_count > 0
except Exception as e:
self.logger.error(f"删除文档失败 [{collection_name}]: {e}")
return False
# ========================= 测试和使用示例 =========================
def test_api():
"""测试API功能"""
print("=== 测试MongoDB API ===")
try:
# 创建API实例测试环境
api = SMYMongoDBAPI("test")
if not api.is_connected():
print("数据库连接失败请检查MongoDB服务")
return
# 测试获取每日签到配置
print("\n1. 测试获取每日签到配置:")
config = api.get_daily_checkin_config()
if config:
print("✓ 成功获取每日签到配置")
print(f"基础奖励金币范围: {config.get('基础奖励', {}).get('金币', {})}")
print(f"种子奖励类型数量: {len(config.get('种子奖励', {}))}")
else:
print("✗ 获取每日签到配置失败")
# 测试获取幸运抽奖配置
print("\n2. 测试获取幸运抽奖配置:")
lucky_config = api.get_lucky_draw_config()
if lucky_config:
print("✓ 成功获取幸运抽奖配置")
print(f"抽奖费用: {lucky_config.get('抽奖费用', {})}")
print(f"概率配置类型数量: {len(lucky_config.get('概率配置', {}))}")
else:
print("✗ 获取幸运抽奖配置失败")
# 测试获取新手大礼包配置
print("\n3. 测试获取新手大礼包配置:")
new_player_config = api.get_new_player_config()
if new_player_config:
print("✓ 成功获取新手大礼包配置")
gift_config = new_player_config.get('新手礼包配置', {})
reward_content = gift_config.get('奖励内容', {})
print(f"奖励金币: {reward_content.get('金币', 0)}")
print(f"奖励经验: {reward_content.get('经验', 0)}")
print(f"种子奖励数量: {len(reward_content.get('种子', []))}")
else:
print("✗ 获取新手大礼包配置失败")
# 测试获取智慧树配置
print("\n4. 测试获取智慧树配置:")
wisdom_tree_config = api.get_wisdom_tree_config()
if wisdom_tree_config:
print("✓ 成功获取智慧树配置")
messages = wisdom_tree_config.get('messages', [])
print(f"消息总数: {wisdom_tree_config.get('total_messages', 0)}")
print(f"最后更新: {wisdom_tree_config.get('last_update', 'N/A')}")
print(f"消息列表长度: {len(messages)}")
else:
print("✗ 获取智慧树配置失败")
# 测试获取在线礼包配置
print("\n5. 测试获取在线礼包配置:")
online_gift_config = api.get_online_gift_config()
if online_gift_config:
print("✓ 成功获取在线礼包配置")
gifts = online_gift_config.get('gifts', [])
print(f"礼包数量: {len(gifts)}")
print(f"最大在线时间: {online_gift_config.get('max_online_time', 'N/A')}")
else:
print("✗ 获取在线礼包配置失败")
# 测试查找所有游戏配置
print("\n6. 测试查找游戏配置集合:")
try:
configs = api.find_documents("gameconfig")
print(f"找到 {len(configs)} 个配置文档")
for config in configs:
print(f" - 文档ID: {config.get('_id', 'N/A')}")
except Exception as e:
print(f"查找配置失败: {e}")
# 断开连接
api.disconnect()
print("\n✓ 测试完成")
except Exception as e:
print(f"测试过程中出现异常: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_api()

View File

@@ -1,4 +1,5 @@
from TCPServer import TCPServer
from SMYMongoDBAPI import SMYMongoDBAPI
import time
import json
import os
@@ -84,9 +85,17 @@ class TCPGameServer(TCPServer):
# 配置文件目录
self.config_dir = "config" # 配置文件存储目录
# 初始化MongoDB API优先使用MongoDB失败则使用JSON文件
self._init_mongodb_api()
# 性能优化相关配置
self._init_performance_settings()
# 数据缓存
self.crop_data_cache = None
self.crop_data_cache_time = 0
self.cache_expire_duration = 300 # 缓存过期时间5分钟
self.log('INFO', f"萌芽农场TCP游戏服务器初始化完成 - 版本: {server_version}", 'SERVER')
# 启动定时器
@@ -96,6 +105,28 @@ class TCPGameServer(TCPServer):
self.start_wisdom_tree_health_decay_timer()
self.start_verification_code_cleanup_timer()
#初始化MongoDB API
def _init_mongodb_api(self):
"""初始化MongoDB API连接"""
try:
# 根据配置决定使用测试环境还是生产环境
# 这里默认使用测试环境,实际部署时可以修改为 "production"
environment = "test" # 或者从配置文件读取
self.mongo_api = SMYMongoDBAPI(environment)
if self.mongo_api.is_connected():
self.use_mongodb = True
self.log('INFO', f"MongoDB API初始化成功 [{environment}]", 'SERVER')
else:
self.use_mongodb = False
self.mongo_api = None
self.log('WARNING', "MongoDB连接失败将使用JSON配置文件", 'SERVER')
except Exception as e:
self.use_mongodb = False
self.mongo_api = None
self.log('ERROR', f"MongoDB API初始化异常: {e}将使用JSON配置文件", 'SERVER')
#初始化性能操作
def _init_performance_settings(self):
"""初始化性能优化配置"""
@@ -400,12 +431,22 @@ class TCPGameServer(TCPServer):
return player_data, username, None
#加载作物配置数据
#加载作物配置数据(优化版本)
def _load_crop_data(self):
"""加载作物配置数据"""
"""加载作物配置数据(带缓存优化)"""
current_time = time.time()
# 检查缓存是否有效
if (self.crop_data_cache is not None and
current_time - self.crop_data_cache_time < self.cache_expire_duration):
return self.crop_data_cache
# 缓存过期或不存在,重新加载
try:
with open("config/crop_data.json", 'r', encoding='utf-8') as file:
return json.load(file)
self.crop_data_cache = json.load(file)
self.crop_data_cache_time = current_time
return self.crop_data_cache
except Exception as e:
self.log('ERROR', f"无法加载作物数据: {str(e)}", 'SERVER')
return {}
@@ -810,6 +851,8 @@ class TCPGameServer(TCPServer):
return self._handle_buy_store_product(client_id, message)
elif message_type == "buy_store_booth":#购买小卖部格子
return self._handle_buy_store_booth(client_id, message)
elif message_type == "save_game_settings":#保存游戏设置
return self._handle_save_game_settings(client_id, message)
#---------------------------------------------------------------------------
elif message_type == "message":#处理聊天消息(暂未实现)
@@ -1340,7 +1383,7 @@ class TCPGameServer(TCPServer):
#==========================收获作物处理==========================
#处理收获作物请求
def _handle_harvest_crop(self, client_id, message):
"""处理收获作物请求"""
"""处理收获作物请求(优化版本)"""
# 检查用户是否已登录
logged_in, response = self._check_user_logged_in(client_id, "收获作物", "harvest_crop")
if not logged_in:
@@ -1354,6 +1397,11 @@ class TCPGameServer(TCPServer):
lot_index = message.get("lot_index", -1)
target_username = message.get("target_username", "")
# 预加载作物配置数据(只加载一次)
crop_data = self._load_crop_data()
if not crop_data:
return self._send_action_error(client_id, "harvest_crop", "无法加载作物配置数据")
# 确定操作目标如果有target_username就是访问模式偷菜否则是自己的农场
if target_username and target_username != current_username:
# 访问模式:偷菜(收益给自己,清空目标玩家的作物)
@@ -1396,7 +1444,7 @@ class TCPGameServer(TCPServer):
return self._send_action_error(client_id, "harvest_crop", "作物尚未成熟,无法偷菜")
# 处理偷菜
return self._process_steal_crop(client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index)
return self._process_steal_crop_optimized(client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index, crop_data)
else:
# 正常模式:收获自己的作物
# 验证地块索引
@@ -1434,55 +1482,55 @@ class TCPGameServer(TCPServer):
return self._send_action_error(client_id, "harvest_crop", "作物尚未成熟")
# 处理正常收获
return self._process_harvest(client_id, current_player_data, current_username, lot, lot_index)
return self._process_harvest_optimized(client_id, current_player_data, current_username, lot, lot_index, crop_data)
#辅助函数-处理作物收获
def _process_harvest(self, client_id, player_data, username, lot, lot_index):
"""处理作物收获逻辑"""
# 取作物配置
crop_data = self._load_crop_data()
# 获取作物类型和经验
#辅助函数-处理作物收获(优化版本)
def _process_harvest_optimized(self, client_id, player_data, username, lot, lot_index, crop_data):
"""处理作物收获逻辑(优化版本)"""
# 取作物类型和基本信息
crop_type = lot["crop_type"]
crop_info = crop_data.get(crop_type, {})
# 检查是否为杂草类型(杂草不能收获,只能铲除)
if crop_type in crop_data:
crop_info = crop_data[crop_type]
is_weed = crop_info.get("是否杂草", False)
if is_weed:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。")
crop_exp = crop_info.get("经验", 10)
# 额外检查:如果作物收益为负数,也视为杂草
crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0)
if crop_income < 0:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。")
else:
# 默认经验
crop_exp = 10
is_weed = crop_info.get("是否杂草", False)
if is_weed:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。")
# 额外检查:如果作物收益为负数,也视为杂草
crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0)
if crop_income < 0:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。")
# 获取作物经验
crop_exp = crop_info.get("经验", 10)
# 生成成熟物收获1-5个
import random
harvest_count = random.randint(1, 5)
crop_harvest = {
"name": crop_type,
"count": harvest_count
}
# 10%概率获得1-2个该作物的种子
seed_reward = self._generate_harvest_seed_reward(crop_type)
seed_reward = None
if random.random() <= 0.1:
seed_reward = {
"name": crop_type,
"count": random.randint(1, 2)
}
# 更新玩家经验(不再直接给钱)
# 更新玩家经验
player_data["experience"] += crop_exp
# 添加成熟物到作物仓库
self._add_crop_to_warehouse(player_data, crop_harvest)
# 检查是否会获得成熟物
mature_name = crop_info.get("成熟物名称")
will_get_mature_item = mature_name is not None
mature_item_name = mature_name if mature_name and mature_name.strip() else crop_type
# 添加成熟物到作物仓库(如果允许)
if will_get_mature_item:
self._add_crop_to_warehouse_optimized(player_data, {"name": crop_type, "count": harvest_count}, mature_item_name, crop_info.get("品质", "普通"))
# 添加种子奖励到背包
if seed_reward:
self._add_seeds_to_bag(player_data, seed_reward)
self._add_seeds_to_bag_optimized(player_data, seed_reward, crop_info.get("品质", "普通"))
# 检查升级
level_up_experience = 100 * player_data["level"]
@@ -1491,12 +1539,14 @@ class TCPGameServer(TCPServer):
player_data["experience"] -= level_up_experience
self.log('INFO', f"玩家 {username} 升级到 {player_data['level']}", 'SERVER')
# 清理地块
lot["is_planted"] = False
lot["crop_type"] = ""
lot["grow_time"] = 0
lot["已浇水"] = False
lot["施肥"] = False
# 清理地块(批量更新)
lot.update({
"is_planted": False,
"crop_type": "",
"grow_time": 0,
"浇水": False,
"已施肥": False
})
# 清除施肥时间戳
if "施肥时间" in lot:
@@ -1509,7 +1559,11 @@ class TCPGameServer(TCPServer):
self._push_crop_update_to_player(username, player_data)
# 构建消息
message = f"收获成功,获得 {crop_type} x{harvest_count}{crop_exp} 经验"
if will_get_mature_item:
message = f"收获成功,获得 {mature_item_name} x{harvest_count}{crop_exp} 经验"
else:
message = f"收获成功,获得 {crop_exp} 经验({crop_type}无成熟物产出)"
if seed_reward:
message += f",额外获得 {seed_reward['name']} 种子 x{seed_reward['count']}"
@@ -1529,9 +1583,9 @@ class TCPGameServer(TCPServer):
}
})
#辅助函数-处理偷菜逻辑(访问模式下收获其他玩家作物的操作)
def _process_steal_crop(self, client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index):
"""处理偷菜逻辑(收益给当前玩家,清空目标玩家的作物)"""
#辅助函数-处理偷菜逻辑(访问模式下收获其他玩家作物的操作)(优化版本)
def _process_steal_crop_optimized(self, client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index, crop_data):
"""处理偷菜逻辑(收益给当前玩家,清空目标玩家的作物)(优化版本)"""
# 偷菜体力值消耗
stamina_cost = 2
@@ -1554,40 +1608,34 @@ class TCPGameServer(TCPServer):
target_player_data, target_username, patrol_pets[0]
)
# 取作物配置
crop_data = self._load_crop_data()
# 获取作物类型和经验偷菜获得的经验稍微少一些比如50%
# 取作物类型和基本信息
crop_type = target_lot["crop_type"]
crop_info = crop_data.get(crop_type, {})
# 检查是否为杂草类型(杂草不能偷取,只能铲除)
if crop_type in crop_data:
crop_info = crop_data[crop_type]
is_weed = crop_info.get("是否杂草", False)
if is_weed:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。")
crop_exp = int(crop_info.get("经验", 10) * 0.5) # 偷菜获得50%经验
# 额外检查:如果作物收益为负数,也视为杂草
crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0)
if crop_income < 0:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。")
else:
# 默认经验
crop_exp = 5
is_weed = crop_info.get("是否杂草", False)
if is_weed:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。")
# 额外检查:如果作物收益为负数,也视为杂草
crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0)
if crop_income < 0:
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。")
# 获取作物经验偷菜获得50%经验)
crop_exp = int(crop_info.get("经验", 10) * 0.5)
# 生成成熟物收获偷菜获得较少1-3个
import random
harvest_count = random.randint(1, 3)
crop_harvest = {
"name": crop_type,
"count": harvest_count
}
# 10%概率获得1-2个该作物的种子偷菜也有机会获得种子
seed_reward = self._generate_harvest_seed_reward(crop_type)
seed_reward = None
if random.random() <= 0.1:
seed_reward = {
"name": crop_type,
"count": random.randint(1, 2)
}
# 消耗当前玩家的体力值
stamina_success, stamina_message = self._consume_stamina(current_player_data, stamina_cost, "偷菜")
@@ -1597,12 +1645,18 @@ class TCPGameServer(TCPServer):
# 更新当前玩家数据(获得经验)
current_player_data["experience"] += crop_exp
# 添加成熟物到作物仓库
self._add_crop_to_warehouse(current_player_data, crop_harvest)
# 检查是否会获得成熟物
mature_name = crop_info.get("成熟物名称")
will_get_mature_item = mature_name is not None
mature_item_name = mature_name if mature_name and mature_name.strip() else crop_type
# 添加成熟物到作物仓库(如果允许)
if will_get_mature_item:
self._add_crop_to_warehouse_optimized(current_player_data, {"name": crop_type, "count": harvest_count}, mature_item_name, crop_info.get("品质", "普通"))
# 添加种子奖励到背包
if seed_reward:
self._add_seeds_to_bag(current_player_data, seed_reward)
self._add_seeds_to_bag_optimized(current_player_data, seed_reward, crop_info.get("品质", "普通"))
# 检查当前玩家升级
level_up_experience = 100 * current_player_data["level"]
@@ -1611,12 +1665,14 @@ class TCPGameServer(TCPServer):
current_player_data["experience"] -= level_up_experience
self.log('INFO', f"玩家 {current_username} 升级到 {current_player_data['level']}", 'SERVER')
# 清理目标玩家的地块
target_lot["is_planted"] = False
target_lot["crop_type"] = ""
target_lot["grow_time"] = 0
target_lot["已浇水"] = False
target_lot["施肥"] = False
# 清理目标玩家的地块(批量更新)
target_lot.update({
"is_planted": False,
"crop_type": "",
"grow_time": 0,
"浇水": False,
"已施肥": False
})
# 清除施肥时间戳
if "施肥时间" in target_lot:
@@ -1630,7 +1686,11 @@ class TCPGameServer(TCPServer):
self._push_crop_update_to_player(target_username, target_player_data)
# 构建消息
message = f"偷菜成功!从 {target_username} 那里获得 {crop_type} x{harvest_count}{crop_exp} 经验,{stamina_message}"
if will_get_mature_item:
message = f"偷菜成功!从 {target_username} 那里获得 {mature_item_name} x{harvest_count}{crop_exp} 经验,{stamina_message}"
else:
message = f"偷菜成功!从 {target_username} 那里获得 {crop_exp} 经验,{stamina_message}{crop_type}无成熟物产出)"
if seed_reward:
message += f",额外获得 {seed_reward['name']} 种子 x{seed_reward['count']}"
@@ -1810,6 +1870,24 @@ class TCPGameServer(TCPServer):
crop_name = crop_harvest["name"]
crop_count = crop_harvest["count"]
# 从作物数据检查"成熟物名称"字段
crop_data = self._load_crop_data()
if crop_data and crop_name in crop_data:
mature_name = crop_data[crop_name].get("成熟物名称")
# 如果成熟物名称为null则不添加成熟物到仓库
if mature_name is None:
self.log('DEBUG', f"作物 {crop_name} 的成熟物名称为null跳过添加到作物仓库", 'SERVER')
return
# 如果有指定的成熟物名称,使用它作为仓库中的名称
if mature_name and mature_name.strip():
warehouse_item_name = mature_name
else:
warehouse_item_name = crop_name
else:
# 如果作物数据中没有该作物,使用原名称
warehouse_item_name = crop_name
# 确保作物仓库存在
if "作物仓库" not in player_data:
player_data["作物仓库"] = []
@@ -1817,7 +1895,7 @@ class TCPGameServer(TCPServer):
# 查找仓库中是否已有该成熟物
crop_found = False
for item in player_data["作物仓库"]:
if item.get("name") == crop_name:
if item.get("name") == warehouse_item_name:
item["count"] += crop_count
crop_found = True
break
@@ -1825,16 +1903,65 @@ class TCPGameServer(TCPServer):
# 如果仓库中没有该成熟物,添加新条目
if not crop_found:
# 从作物数据获取品质信息
crop_data = self._load_crop_data()
quality = "普通"
if crop_data and crop_name in crop_data:
quality = crop_data[crop_name].get("品质", "普通")
player_data["作物仓库"].append({
"name": crop_name,
"name": warehouse_item_name,
"quality": quality,
"count": crop_count
})
# 添加种子到玩家背包(优化版本)
def _add_seeds_to_bag_optimized(self, player_data, seed_reward, quality="普通"):
"""将种子奖励添加到玩家背包(优化版本)"""
if not seed_reward:
return
seed_name = seed_reward["name"]
seed_count = seed_reward["count"]
# 确保背包存在
if "player_bag" not in player_data:
player_data["player_bag"] = []
# 查找背包中是否已有该种子
for item in player_data["player_bag"]:
if item.get("name") == seed_name:
item["count"] += seed_count
return
# 如果背包中没有该种子,添加新条目
player_data["player_bag"].append({
"name": seed_name,
"quality": quality,
"count": seed_count
})
def _add_crop_to_warehouse_optimized(self, player_data, crop_harvest, warehouse_item_name, quality="普通"):
"""将成熟物添加到玩家作物仓库(优化版本)"""
if not crop_harvest:
return
crop_count = crop_harvest["count"]
# 确保作物仓库存在
if "作物仓库" not in player_data:
player_data["作物仓库"] = []
# 查找仓库中是否已有该成熟物
for item in player_data["作物仓库"]:
if item.get("name") == warehouse_item_name:
item["count"] += crop_count
return
# 如果仓库中没有该成熟物,添加新条目
player_data["作物仓库"].append({
"name": warehouse_item_name,
"quality": quality,
"count": crop_count
})
#==========================收获作物处理==========================
@@ -4427,8 +4554,21 @@ class TCPGameServer(TCPServer):
# 检查是否升级
self._check_level_up(player_data)
# 添加成熟物到作物仓库
self._add_crop_to_warehouse(player_data, crop_harvest)
# 检查是否会获得成熟物
crop_data = self._load_crop_data()
will_get_mature_item = True
mature_item_name = crop_type
if crop_data and crop_type in crop_data:
mature_name = crop_data[crop_type].get("成熟物名称")
if mature_name is None:
will_get_mature_item = False
elif mature_name and mature_name.strip():
mature_item_name = mature_name
# 添加成熟物到作物仓库(如果允许)
if will_get_mature_item:
self._add_crop_to_warehouse(player_data, crop_harvest)
# 添加种子奖励到背包
if seed_reward:
@@ -4452,7 +4592,11 @@ class TCPGameServer(TCPServer):
self._push_crop_update_to_player(username, player_data)
# 构建消息
message = f"使用 {item_name} 收获成功,获得 {crop_type} x{harvest_count}{crop_exp} 经验{message_suffix}"
if will_get_mature_item:
message = f"使用 {item_name} 收获成功,获得 {mature_item_name} x{harvest_count}{crop_exp} 经验{message_suffix}"
else:
message = f"使用 {item_name} 收获成功,获得 {crop_exp} 经验{message_suffix}{crop_type}无成熟物产出)"
if seed_reward:
message += f",额外获得 {seed_reward['name']} x{seed_reward['count']}"
@@ -4546,8 +4690,21 @@ class TCPGameServer(TCPServer):
# 检查当前玩家是否升级
self._check_level_up(current_player_data)
# 收获物给当前玩家
self._add_crop_to_warehouse(current_player_data, crop_harvest)
# 检查是否会获得成熟物
crop_data = self._load_crop_data()
will_get_mature_item = True
mature_item_name = crop_type
if crop_data and crop_type in crop_data:
mature_name = crop_data[crop_type].get("成熟物名称")
if mature_name is None:
will_get_mature_item = False
elif mature_name and mature_name.strip():
mature_item_name = mature_name
# 收获物给当前玩家(如果允许)
if will_get_mature_item:
self._add_crop_to_warehouse(current_player_data, crop_harvest)
# 种子奖励给当前玩家
if seed_reward:
@@ -4572,7 +4729,11 @@ class TCPGameServer(TCPServer):
self._push_crop_update_to_player(target_username, target_player_data)
# 构建消息
message = f"使用 {item_name} 帮助收获成功!从 {target_username} 那里获得 {crop_type} x{harvest_count}{crop_exp} 经验{message_suffix}"
if will_get_mature_item:
message = f"使用 {item_name} 帮助收获成功!从 {target_username} 那里获得 {mature_item_name} x{harvest_count}{crop_exp} 经验{message_suffix}"
else:
message = f"使用 {item_name} 帮助收获成功!从 {target_username} 那里获得 {crop_exp} 经验{message_suffix}{crop_type}无成熟物产出)"
if seed_reward:
message += f",额外获得 {seed_reward['name']} x{seed_reward['count']}"
@@ -5417,7 +5578,8 @@ class TCPGameServer(TCPServer):
stamina_system = player_data.get("体力系统", {})
current_stamina = stamina_system.get("当前体力值", 20)
return current_stamina >= amount
def _check_and_update_register_time(self, player_data, username):
"""检查并更新已存在玩家的注册时间"""
default_register_time = "2025年05月21日15时00分00秒"
@@ -5516,6 +5678,81 @@ class TCPGameServer(TCPServer):
#==========================游戏设置处理==========================
def _handle_save_game_settings(self, client_id, message):
"""处理保存游戏设置请求"""
# 检查用户是否已登录
logged_in, response = self._check_user_logged_in(client_id, "保存游戏设置", "save_game_settings")
if not logged_in:
return self.send_data(client_id, response)
# 获取玩家数据
player_data, username, response = self._load_player_data_with_check(client_id, "save_game_settings")
if not player_data:
return self.send_data(client_id, response)
# 获取设置数据
settings = message.get("settings", {})
if not settings:
return self.send_data(client_id, {
"type": "save_game_settings_response",
"success": False,
"message": "设置数据为空"
})
# 验证设置数据格式
valid_settings = {}
# 验证背景音乐音量 (0.0-1.0)
if "背景音乐音量" in settings:
volume = settings["背景音乐音量"]
if isinstance(volume, (int, float)) and 0.0 <= volume <= 1.0:
valid_settings["背景音乐音量"] = float(volume)
else:
return self.send_data(client_id, {
"type": "save_game_settings_response",
"success": False,
"message": "背景音乐音量值无效应在0.0-1.0之间"
})
# 验证天气显示设置
if "天气显示" in settings:
weather_display = settings["天气显示"]
if isinstance(weather_display, bool):
valid_settings["天气显示"] = weather_display
else:
return self.send_data(client_id, {
"type": "save_game_settings_response",
"success": False,
"message": "天气显示设置值无效,应为布尔值"
})
# 保存设置到玩家数据
if "游戏设置" not in player_data:
player_data["游戏设置"] = {}
player_data["游戏设置"].update(valid_settings)
# 保存到数据库
if self.save_player_data(username, player_data):
self.log('INFO', f"用户 {username} 保存游戏设置: {valid_settings}", 'SERVER')
return self.send_data(client_id, {
"type": "save_game_settings_response",
"success": True,
"message": "游戏设置保存成功",
"settings": valid_settings
})
else:
return self.send_data(client_id, {
"type": "save_game_settings_response",
"success": False,
"message": "保存游戏设置失败"
})
#==========================游戏设置处理==========================
#==========================玩家游玩时间处理==========================
#处理获取玩家游玩时间请求
def _handle_get_play_time(self, client_id):
@@ -6506,16 +6743,32 @@ class TCPGameServer(TCPServer):
#==========================每日签到处理==========================
#加载每日签到配置
def _load_daily_check_in_config(self):
"""加载每日签到配置"""
"""加载每日签到配置 - 优先使用MongoDB失败则回退到JSON文件"""
# 优先尝试从MongoDB获取配置
if hasattr(self, 'use_mongodb') and self.use_mongodb and self.mongo_api:
try:
config = self.mongo_api.get_daily_checkin_config()
if config:
self.log('INFO', "从MongoDB成功加载每日签到配置", 'SERVER')
return config
else:
self.log('WARNING', "MongoDB中未找到每日签到配置尝试使用JSON文件", 'SERVER')
except Exception as e:
self.log('ERROR', f"从MongoDB加载每日签到配置失败: {e}回退到JSON文件", 'SERVER')
# 回退到JSON文件
try:
config_path = os.path.join(self.config_dir, "daily_checkin_config.json")
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
except:
pass
config = json.load(f)
self.log('INFO', "从JSON文件成功加载每日签到配置", 'SERVER')
return config
except Exception as e:
self.log('ERROR', f"从JSON文件加载每日签到配置失败: {e}", 'SERVER')
# 默认配置
self.log('WARNING', "使用默认每日签到配置", 'SERVER')
return {
"基础奖励": {
"金币": {"最小值": 200, "最大值": 500, "图标": "💰", "颜色": "#FFD700"},
@@ -6537,6 +6790,25 @@ class TCPGameServer(TCPServer):
}
}
#更新每日签到配置到MongoDB
def _update_daily_checkin_config_to_mongodb(self, config_data):
"""更新每日签到配置到MongoDB"""
if hasattr(self, 'use_mongodb') and self.use_mongodb and self.mongo_api:
try:
success = self.mongo_api.update_daily_checkin_config(config_data)
if success:
self.log('INFO', "成功更新每日签到配置到MongoDB", 'SERVER')
return True
else:
self.log('ERROR', "更新每日签到配置到MongoDB失败", 'SERVER')
return False
except Exception as e:
self.log('ERROR', f"更新每日签到配置到MongoDB异常: {e}", 'SERVER')
return False
else:
self.log('WARNING', "MongoDB未连接无法更新配置", 'SERVER')
return False
#处理每日签到请求
def _handle_daily_check_in_request(self, client_id, message):
"""处理每日签到请求"""
@@ -7126,16 +7398,32 @@ class TCPGameServer(TCPServer):
#加载抽奖配置
def _load_lucky_draw_config(self):
"""加载抽奖配置"""
"""加载抽奖配置优先从MongoDB读取"""
# 优先尝试从MongoDB读取
if self.use_mongodb and self.mongo_api:
try:
config = self.mongo_api.get_lucky_draw_config()
if config:
self.log('INFO', "成功从MongoDB加载幸运抽奖配置", 'SERVER')
return config
else:
self.log('WARNING', "MongoDB中未找到幸运抽奖配置尝试从JSON文件读取", 'SERVER')
except Exception as e:
self.log('ERROR', f"从MongoDB读取幸运抽奖配置失败: {e}尝试从JSON文件读取", 'SERVER')
# 回退到JSON文件
try:
config_path = os.path.join(self.config_dir, "lucky_draw_config.json")
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
except:
pass
config = json.load(f)
self.log('INFO', "成功从JSON文件加载幸运抽奖配置", 'SERVER')
return config
except Exception as e:
self.log('ERROR', f"从JSON文件读取幸运抽奖配置失败: {e},使用默认配置", 'SERVER')
# 默认配置
self.log('WARNING', "使用默认幸运抽奖配置", 'SERVER')
return {
"抽奖费用": {"单抽": 800, "五连抽": 3600, "十连抽": 6400},
"概率配置": {
@@ -7151,16 +7439,31 @@ class TCPGameServer(TCPServer):
#加载在线礼包配置
def _load_online_gift_config(self):
"""加载在线礼包配置"""
# 优先从MongoDB读取配置
if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected():
try:
config = self.mongo_api.get_online_gift_config()
if config:
self.log('INFO', '成功从MongoDB加载在线礼包配置', 'SERVER')
return config
else:
self.log('WARNING', '从MongoDB未找到在线礼包配置尝试从JSON文件加载', 'SERVER')
except Exception as e:
self.log('ERROR', f'从MongoDB加载在线礼包配置失败: {str(e)}尝试从JSON文件加载', 'SERVER')
# 回退到JSON文件
try:
config_path = os.path.join(self.config_dir, "online_gift_config.json")
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
config = json.load(f)
self.log('INFO', '成功从JSON文件加载在线礼包配置', 'SERVER')
return config
except Exception as e:
self.log('ERROR', f"加载在线礼包配置失败: {str(e)}", 'SERVER')
pass
self.log('ERROR', f"从JSON文件加载在线礼包配置失败: {str(e)}", 'SERVER')
# 默认配置
self.log('WARNING', '使用默认在线礼包配置', 'SERVER')
return {
"在线礼包配置": {
"1分钟": {"时长秒数": 60, "奖励": {"金币": 100, "经验": 50, "种子": [{"名称": "小麦", "数量": 5}]}},
@@ -7174,15 +7477,31 @@ class TCPGameServer(TCPServer):
#加载新手礼包配置
def _load_new_player_config(self):
"""加载新手礼包配置"""
# 优先从MongoDB读取配置
if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected():
try:
config = self.mongo_api.get_new_player_config()
if config:
self.log('INFO', '成功从MongoDB加载新手大礼包配置', 'SERVER')
return config
else:
self.log('WARNING', '从MongoDB未找到新手大礼包配置尝试从JSON文件加载', 'SERVER')
except Exception as e:
self.log('ERROR', f'从MongoDB加载新手大礼包配置失败: {str(e)}尝试从JSON文件加载', 'SERVER')
# 回退到JSON文件
try:
config_path = os.path.join(self.config_dir, "new_player_config.json")
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
config = json.load(f)
self.log('INFO', '成功从JSON文件加载新手大礼包配置', 'SERVER')
return config
except Exception as e:
self.log('ERROR', f"加载新手礼包配置失败: {str(e)}", 'SERVER')
self.log('ERROR', f"从JSON文件加载新手礼包配置失败: {str(e)}", 'SERVER')
# 默认配置
self.log('WARNING', '使用默认新手大礼包配置', 'SERVER')
return {
"新手礼包配置": {
"奖励内容": {
@@ -8279,7 +8598,7 @@ class TCPGameServer(TCPServer):
# 从智慧树消息库中随机获取一条消息
random_message = self._get_random_wisdom_tree_message()
if random_message:
wisdom_tree_config["智慧树显示的话"] = random_message
wisdom_tree_config["智慧树显示的话"] = random_message.get("content", "")
# 保存数据
self.save_player_data(username, player_data)
@@ -8347,7 +8666,7 @@ class TCPGameServer(TCPServer):
random_message = self._get_random_wisdom_tree_message()
if random_message:
wisdom_tree_config["智慧树显示的话"] = random_message
wisdom_tree_config["智慧树显示的话"] = random_message.get("content", "")
# 保存数据
self.save_player_data(username, player_data)
@@ -8505,6 +8824,22 @@ class TCPGameServer(TCPServer):
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:
@@ -8514,12 +8849,13 @@ class TCPGameServer(TCPServer):
messages = wisdom_tree_data.get("messages", [])
if messages:
selected_message = random.choice(messages)
return selected_message.get("content", "")
self.log('INFO', f"成功从JSON文件获取智慧树消息", 'SERVER')
return selected_message
else:
return ""
return None
except Exception as e:
print(f"读取智慧树消息失败{e}")
return ""
self.log('ERROR', f"从JSON文件读取智慧树消息失败: {e}", 'SERVER')
return None
def _save_wisdom_tree_message(self, username, message_content):
"""保存智慧树消息到消息库"""
@@ -8528,6 +8864,46 @@ class TCPGameServer(TCPServer):
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:
@@ -8542,14 +8918,6 @@ class TCPGameServer(TCPServer):
"last_update": ""
}
# 创建新消息
new_message = {
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"sender": username,
"content": message_content,
"id": str(uuid.uuid4())
}
# 添加到消息列表
wisdom_tree_data["messages"].append(new_message)
wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"])
@@ -8564,9 +8932,10 @@ class TCPGameServer(TCPServer):
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:
print(f"保存智慧树消息失败:{e}")
self.log('ERROR', f"保存智慧树消息到JSON文件失败: {e}", 'SERVER')
return False
def check_wisdom_tree_health_decay(self):
@@ -9543,17 +9912,6 @@ if __name__ == "__main__":
server_thread.start()
print("✅ 服务器启动成功!")
print("📋 功能列表:")
print(" ├── 用户注册/登录系统")
print(" ├── 作物种植与收获")
print(" ├── 浇水与施肥系统")
print(" ├── 每日签到奖励")
print(" ├── 幸运抽奖系统")
print(" ├── 玩家互动功能")
print(" ├── 性能优化缓存")
print(" └── 控制台命令系统")
print("=" * 60)
print("🔥 服务器运行中...")
# 启动控制台输入线程
console_thread = threading.Thread(target=console_input_thread, args=(server,))
@@ -9584,4 +9942,4 @@ if __name__ == "__main__":
except Exception as e:
print(f"\n❌ 服务器启动失败: {str(e)}")
print("🔧 请检查配置并重试")
sys.exit(1)
sys.exit(1)

Binary file not shown.

View File

@@ -1,72 +1,85 @@
{
"experience": 0,
"level": 1,
"money": 4000,
"体力值": 20,
"体力上次刷新时间": "",
"体力上次恢复时间": 0,
"farm_name": "农场",
"user_name": "shumengya",
"player_name": "玩家昵称",
"user_password": "0123456789",
"last_login_time": "2025年12时09分35秒",
"money": 5000,
"farm_name": "农场名称",
"player_name": "玩家名称",
"user_name": "用户名",
"user_password": "密码",
"last_login_time": "2025年07月20日17时19分16秒",
"total_login_time": "0时0分0秒",
"personal_profile": "个人简介",
"注册时间": "2025年05月21日15时00分00秒",
"farm_lots": [
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0},
{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5,"已浇水":false,"已施肥":false,"土地等级":0}
],
"last_water_reset_date": "2025-06-05",
"farm_lots": [],
"player_bag": [],
"作物仓库": [],
"宠物背包": [],
"巡逻宠物": [],
"出战宠物": [],
"注册时间": "2025年05月21日15时00分00秒",
"个人简介": "个人简介",
"稻草人配置": {
"已拥有稻草人类型": [
],
"稻草人展示类型": "",
"稻草人昵称": "稻草人",
"稻草人说的话": {
"第一句话": {
"内容": "第一句话",
"颜色": "52dceeff"
},
"第二句话": {
"内容": "第二句话",
"颜色": "80d5ffff"
},
"第三句话": {
"内容": "第三句话",
"颜色": "ac52ffff"
},
"第四句话": {
"内容": "第四句话",
"颜色": "f881ffff"
}
},
"稻草人昵称颜色": "b38282ff"
},
"智慧树配置": {
"距离上一次杀虫时间": 1753004237,
"距离上一次除草时间": 1753004237,
"智慧树显示的话": "",
"等级": 1,
"当前经验值": 0,
"最大经验值": 100,
"最大生命值": 100,
"当前生命值": 100,
"高度": 20
},
"签到历史": {
},
"在线礼包": {
"当前日期": "2025-07-20",
"今日在线时长": 0.0,
"已领取礼包": [],
"登录时间": 1753003043.7163484
},
"点赞系统": {
"今日剩余点赞次数": 10,
"点赞上次刷新时间": "2025-07-20"
},
"新手礼包": {
"已领取": false,
"领取时间": "2025-07-12 23:02:25"
},
"体力系统": {
"当前体力值": 20,
"最大体力值": 20,
"上次刷新时间": "2025-07-20",
"上次恢复时间": 1753003043.7066433
},
"道具背包": [],
"宠物背包":[],
"巡逻宠物":[],
"出战宠物":[]
"玩家小卖部": [],
"小卖部格子数": 10,
"游戏设置": {
"背景音乐音量": 1.0,
"天气显示": true
}
}

View File

@@ -1,13 +1,13 @@
{
"experience": 1196,
"level": 35,
"money": 200812377,
"experience": 90,
"level": 36,
"money": 200802715,
"farm_name": "柚大青の小农场",
"player_name": "柚大青",
"user_name": "2143323382",
"user_password": "tyh@19900420",
"last_login_time": "2025年07月19日11时01分22秒",
"total_login_time": "6时31分14秒",
"last_login_time": "2025年07月20日21时00分40秒",
"total_login_time": "6时45分52秒",
"farm_lots": [
{
"crop_type": "",
@@ -131,26 +131,27 @@
"土地等级": 3
},
{
"crop_type": "",
"grow_time": 0,
"crop_type": "杂交树1",
"grow_time": 14976,
"is_dead": false,
"is_diged": true,
"is_planted": false,
"max_grow_time": 1080,
"is_planted": true,
"max_grow_time": 21600,
"已浇水": false,
"已施肥": false,
"土地等级": 3
},
{
"crop_type": "",
"grow_time": 0,
"crop_type": "杂交树2",
"grow_time": 15468,
"is_dead": false,
"is_diged": true,
"is_planted": false,
"max_grow_time": 720,
"is_planted": true,
"max_grow_time": 25200,
"已浇水": false,
"已施肥": false,
"土地等级": 3
"土地等级": 3,
"浇水时间": 1753003230.8845751
},
{
"crop_type": "",
@@ -241,12 +242,12 @@
"土地等级": 1
},
{
"crop_type": "",
"grow_time": 0,
"crop_type": "玉米",
"grow_time": 918,
"is_dead": false,
"is_diged": true,
"is_planted": false,
"max_grow_time": 240,
"is_planted": true,
"max_grow_time": 900,
"已浇水": false,
"已施肥": false,
"土地等级": 1
@@ -576,11 +577,6 @@
"quality": "普通",
"count": 1
},
{
"name": "玉米",
"quality": "优良",
"count": 1
},
{
"name": "番茄",
"quality": "普通",
@@ -616,15 +612,6 @@
"quality": "传奇",
"count": 1
},
{
"name": "杂交树1",
"quality": "传奇",
"count": 1
},
{
"name": "杂交树2",
"count": 1
},
{
"name": "荔枝",
"count": 2
@@ -644,6 +631,46 @@
{
"name": "向日葵",
"count": 3
},
{
"name": "黄瓜",
"quality": "普通",
"count": 3
},
{
"name": "野草1",
"quality": "优良",
"count": 2
},
{
"name": "豌豆",
"quality": "普通",
"count": 4
},
{
"name": "稻谷",
"quality": "普通",
"count": 4
},
{
"name": "山楂",
"quality": "优良",
"count": 2
},
{
"name": "龙果",
"quality": "传奇",
"count": 1
},
{
"name": "杂交树1",
"quality": "传奇",
"count": 1
},
{
"name": "杂交树2",
"quality": "传奇",
"count": 1
}
],
"last_water_reset_date": "2025-06-05",
@@ -851,9 +878,11 @@
],
"稻草人配置": {
"已拥有稻草人类型": [
"稻草人1"
"稻草人1",
"稻草人2",
"稻草人3"
],
"稻草人展示类型": "",
"稻草人展示类型": "稻草人3",
"稻草人昵称": "柚大青的稻草人",
"稻草人说的话": {
"第一句话": {
@@ -875,48 +904,60 @@
},
"稻草人昵称颜色": "b38282ff"
},
"智慧树配置": {
"智慧树显示的话": "柚小青最可爱",
"等级": 4,
"高度": 76,
"上次护理时间": 1752050186,
"距离上一次除草时间": 1752050186,
"距离上一次杀虫时间": 1752050186,
"当前经验值": 278,
"最大经验值": 480,
"最大生命值": 106,
"当前生命值": 106
},
"签到历史": {
"2025年07月12日21时05分47秒": "金币249 经验75 土豆x3",
"2025年07月13日07时26分04秒": "金币302 经验63 土豆x5 小麦x3"
},
"在线礼包": {
"当前日期": "2025-07-19",
"今日在线时长": 0.0,
"当前日期": "2025-07-20",
"今日在线时长": 999999.271807432174683,
"已领取礼包": [],
"登录时间": 1752894082.539563
"登录时间": 1753003043.7163484
},
"点赞系统": {
"今日剩余点赞次数": 10,
"点赞上次刷新时间": "2025-07-19"
"点赞上次刷新时间": "2025-07-20"
},
"新手礼包": {
"已领取": true,
"领取时间": "2025-07-12 23:02:25"
"领取时间": "2025-07-20 20:21:04"
},
"体力系统": {
"当前体力值": 20,
"最大体力值": 20,
"上次刷新时间": "2025-07-19",
"上次恢复时间": 1752894082.5390205
"上次刷新时间": "2025-07-20",
"上次恢复时间": 1753003043.7066433
},
"玩家小卖部": [],
"道具背包": [
{
"name": "铲子",
"count": 100
},
{
"name": "农家肥",
"count": 5
},
{
"name": "水桶",
"count": 4
}
],
"小卖部格子数": 10
"玩家小卖部": [],
"小卖部格子数": 10,
"游戏设置": {
"背景音乐音量": 1.0,
"天气显示": true
},
"智慧树配置": {
"距离上一次杀虫时间": 1753014929,
"距离上一次除草时间": 1753014864,
"智慧树显示的话": "你好,树萌芽",
"等级": 2,
"当前经验值": 27,
"最大经验值": 169,
"最大生命值": 102,
"当前生命值": 102,
"高度": 20,
"上次护理时间": 1753014929
}
}

View File

@@ -0,0 +1,178 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
测试MongoDB迁移功能
作者: AI Assistant
功能: 测试每日签到配置从JSON迁移到MongoDB的功能
"""
import sys
import os
import json
# 添加当前目录到Python路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from SMYMongoDBAPI import SMYMongoDBAPI
def test_mongodb_migration():
"""测试MongoDB迁移功能"""
print("=== 测试MongoDB迁移功能 ===")
# 1. 测试MongoDB API连接
print("\n1. 测试MongoDB API连接:")
try:
api = SMYMongoDBAPI("test")
if api.is_connected():
print("✓ MongoDB连接成功")
else:
print("✗ MongoDB连接失败")
return False
except Exception as e:
print(f"✗ MongoDB连接异常: {e}")
return False
# 2. 测试获取每日签到配置
print("\n2. 测试获取每日签到配置:")
try:
config = api.get_daily_checkin_config()
if config:
print("✓ 成功获取每日签到配置")
print(f" 基础奖励金币范围: {config.get('基础奖励', {}).get('金币', {})}")
print(f" 种子奖励类型数量: {len(config.get('种子奖励', {}))}")
print(f" 连续签到奖励天数: {len(config.get('连续签到奖励', {}))}")
else:
print("✗ 获取每日签到配置失败")
return False
except Exception as e:
print(f"✗ 获取每日签到配置异常: {e}")
return False
# 3. 测试更新配置
print("\n3. 测试更新每日签到配置:")
try:
# 创建一个测试配置
test_config = {
"基础奖励": {
"金币": {"最小值": 300, "最大值": 600, "图标": "💰", "颜色": "#FFD700"},
"经验": {"最小值": 75, "最大值": 150, "图标": "", "颜色": "#00BFFF"}
},
"种子奖励": {
"普通": {"概率": 0.6, "数量范围": [2, 5], "种子池": ["小麦", "胡萝卜", "土豆", "稻谷"]},
"优良": {"概率": 0.25, "数量范围": [2, 4], "种子池": ["玉米", "番茄", "洋葱", "大豆", "豌豆", "黄瓜", "大白菜"]},
"稀有": {"概率": 0.12, "数量范围": [1, 3], "种子池": ["草莓", "花椰菜", "柿子", "蓝莓", "树莓"]},
"史诗": {"概率": 0.025, "数量范围": [1, 2], "种子池": ["葡萄", "南瓜", "芦笋", "茄子", "向日葵", "蕨菜"]},
"传奇": {"概率": 0.005, "数量范围": [1, 1], "种子池": ["西瓜", "甘蔗", "香草", "甜菜", "人参", "富贵竹", "芦荟", "哈密瓜"]}
},
"连续签到奖励": {
"第3天": {"额外金币": 150, "额外经验": 75, "描述": "连续签到奖励"},
"第7天": {"额外金币": 300, "额外经验": 150, "描述": "一周连击奖励"},
"第14天": {"额外金币": 600, "额外经验": 250, "描述": "半月连击奖励"},
"第21天": {"额外金币": 1000, "额外经验": 400, "描述": "三周连击奖励"},
"第30天": {"额外金币": 2000, "额外经验": 600, "描述": "满月连击奖励"}
}
}
success = api.update_daily_checkin_config(test_config)
if success:
print("✓ 成功更新测试配置到MongoDB")
else:
print("✗ 更新测试配置失败")
return False
except Exception as e:
print(f"✗ 更新测试配置异常: {e}")
return False
# 4. 验证更新后的配置
print("\n4. 验证更新后的配置:")
try:
updated_config = api.get_daily_checkin_config()
if updated_config:
print("✓ 成功获取更新后的配置")
print(f" 更新后金币范围: {updated_config.get('基础奖励', {}).get('金币', {})}")
print(f" 更新后第3天奖励: {updated_config.get('连续签到奖励', {}).get('第3天', {})}")
# 验证更新是否生效
if updated_config.get('基础奖励', {}).get('金币', {}).get('最小值') == 300:
print("✓ 配置更新验证成功")
else:
print("✗ 配置更新验证失败")
return False
else:
print("✗ 获取更新后的配置失败")
return False
except Exception as e:
print(f"✗ 验证更新后配置异常: {e}")
return False
# 5. 恢复原始配置
print("\n5. 恢复原始配置:")
try:
original_config = {
"基础奖励": {
"金币": {"最小值": 200, "最大值": 500, "图标": "💰", "颜色": "#FFD700"},
"经验": {"最小值": 50, "最大值": 120, "图标": "", "颜色": "#00BFFF"}
},
"种子奖励": {
"普通": {"概率": 0.6, "数量范围": [2, 5], "种子池": ["小麦", "胡萝卜", "土豆", "稻谷"]},
"优良": {"概率": 0.25, "数量范围": [2, 4], "种子池": ["玉米", "番茄", "洋葱", "大豆", "豌豆", "黄瓜", "大白菜"]},
"稀有": {"概率": 0.12, "数量范围": [1, 3], "种子池": ["草莓", "花椰菜", "柿子", "蓝莓", "树莓"]},
"史诗": {"概率": 0.025, "数量范围": [1, 2], "种子池": ["葡萄", "南瓜", "芦笋", "茄子", "向日葵", "蕨菜"]},
"传奇": {"概率": 0.005, "数量范围": [1, 1], "种子池": ["西瓜", "甘蔗", "香草", "甜菜", "人参", "富贵竹", "芦荟", "哈密瓜"]}
},
"连续签到奖励": {
"第3天": {"额外金币": 100, "额外经验": 50, "描述": "连续签到奖励"},
"第7天": {"额外金币": 200, "额外经验": 100, "描述": "一周连击奖励"},
"第14天": {"额外金币": 500, "额外经验": 200, "描述": "半月连击奖励"},
"第21天": {"额外金币": 800, "额外经验": 300, "描述": "三周连击奖励"},
"第30天": {"额外金币": 1500, "额外经验": 500, "描述": "满月连击奖励"}
}
}
success = api.update_daily_checkin_config(original_config)
if success:
print("✓ 成功恢复原始配置")
else:
print("✗ 恢复原始配置失败")
return False
except Exception as e:
print(f"✗ 恢复原始配置异常: {e}")
return False
# 6. 测试配置数据完整性
print("\n6. 测试配置数据完整性:")
try:
final_config = api.get_daily_checkin_config()
if final_config:
# 检查必要字段是否存在
required_fields = ["基础奖励", "种子奖励", "连续签到奖励"]
missing_fields = [field for field in required_fields if field not in final_config]
if not missing_fields:
print("✓ 配置数据完整性检查通过")
print(f" 包含字段: {', '.join(required_fields)}")
else:
print(f"✗ 配置数据缺少字段: {missing_fields}")
return False
else:
print("✗ 无法获取最终配置进行完整性检查")
return False
except Exception as e:
print(f"✗ 配置数据完整性检查异常: {e}")
return False
# 清理资源
api.disconnect()
print("\n=== 所有测试通过MongoDB迁移功能正常 ===")
return True
if __name__ == "__main__":
success = test_mongodb_migration()
if success:
print("\n🎉 MongoDB迁移测试成功完成")
sys.exit(0)
else:
print("\n❌ MongoDB迁移测试失败")
sys.exit(1)

View File

@@ -0,0 +1,106 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
测试服务器MongoDB集成
作者: AI Assistant
功能: 测试服务器是否能正确使用MongoDB配置
"""
import sys
import os
# 添加当前目录到Python路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
def test_server_mongodb_integration():
"""测试服务器MongoDB集成"""
print("=== 测试服务器MongoDB集成 ===")
try:
# 导入服务器模块
from Server.TCPGameServer import TCPGameServer
print("✓ 成功导入TCPGameServer模块")
# 创建服务器实例(不启动网络服务)
print("\n1. 创建服务器实例:")
server = TCPGameServer()
print("✓ 服务器实例创建成功")
# 检查MongoDB连接状态
print("\n2. 检查MongoDB连接状态:")
if hasattr(server, 'use_mongodb'):
print(f" MongoDB使用状态: {server.use_mongodb}")
if hasattr(server, 'mongo_api') and server.mongo_api:
print(" MongoDB API实例: 已创建")
else:
print(" MongoDB API实例: 未创建")
else:
print(" MongoDB相关属性: 未找到")
# 测试配置加载
print("\n3. 测试每日签到配置加载:")
try:
config = server._load_daily_check_in_config()
if config:
print("✓ 成功加载每日签到配置")
print(f" 基础奖励金币范围: {config.get('基础奖励', {}).get('金币', {})}")
print(f" 种子奖励类型数量: {len(config.get('种子奖励', {}))}")
print(f" 连续签到奖励天数: {len(config.get('连续签到奖励', {}))}")
# 检查配置来源
if hasattr(server, 'use_mongodb') and server.use_mongodb:
print(" 配置来源: MongoDB")
else:
print(" 配置来源: JSON文件或默认配置")
else:
print("✗ 加载每日签到配置失败")
return False
except Exception as e:
print(f"✗ 配置加载异常: {e}")
return False
# 测试配置更新方法
print("\n4. 测试配置更新方法:")
if hasattr(server, '_update_daily_checkin_config_to_mongodb'):
print("✓ 配置更新方法存在")
# 测试更新方法(不实际更新)
test_config = {
"基础奖励": {
"金币": {"最小值": 250, "最大值": 550, "图标": "💰", "颜色": "#FFD700"},
"经验": {"最小值": 60, "最大值": 130, "图标": "", "颜色": "#00BFFF"}
}
}
try:
# 这里只是测试方法是否存在,不实际调用
print("✓ 配置更新方法可调用")
except Exception as e:
print(f"✗ 配置更新方法异常: {e}")
return False
else:
print("✗ 配置更新方法不存在")
return False
print("\n=== 服务器MongoDB集成测试通过 ===")
return True
except ImportError as e:
print(f"✗ 模块导入失败: {e}")
print(" 请确保所有依赖模块都已正确安装")
return False
except Exception as e:
print(f"✗ 测试过程中出现异常: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == "__main__":
success = test_server_mongodb_integration()
if success:
print("\n🎉 服务器MongoDB集成测试成功完成")
sys.exit(0)
else:
print("\n❌ 服务器MongoDB集成测试失败")
sys.exit(1)