迁移了大部分数据配置
This commit is contained in:
38
MainGame.gd
38
MainGame.gd
@@ -2206,6 +2206,9 @@ func _handle_global_broadcast_message(data: Dictionary):
|
||||
# 将消息传递给大喇叭面板处理
|
||||
global_server_broadcast_panel.receive_broadcast_message(data)
|
||||
|
||||
# 立即更新主界面大喇叭显示
|
||||
update_broadcast_display_from_message(data)
|
||||
|
||||
# 处理全服大喇叭发送响应
|
||||
func _handle_global_broadcast_response(data: Dictionary):
|
||||
var success = data.get("success", false)
|
||||
@@ -2224,9 +2227,25 @@ func _handle_broadcast_history_response(data: Dictionary):
|
||||
global_server_broadcast_panel.receive_history_messages(data)
|
||||
|
||||
# 更新主界面大喇叭显示为最新消息
|
||||
update_broadcast_display_from_panel()
|
||||
|
||||
# 从消息数据直接更新大喇叭显示
|
||||
func update_broadcast_display_from_message(data: Dictionary):
|
||||
if global_server_broadcast:
|
||||
var username = data.get("username", "匿名")
|
||||
var player_name = data.get("玩家昵称", "")
|
||||
var content = data.get("content", "")
|
||||
|
||||
# 优先显示玩家昵称
|
||||
var display_name = player_name if player_name != "" else username
|
||||
global_server_broadcast.text = display_name + ": " + content
|
||||
print("主界面大喇叭已更新为: ", global_server_broadcast.text)
|
||||
|
||||
# 从面板获取最新消息更新大喇叭显示
|
||||
func update_broadcast_display_from_panel():
|
||||
if global_server_broadcast and global_server_broadcast_panel:
|
||||
var latest_message = global_server_broadcast_panel.get_latest_message()
|
||||
if latest_message != "全服大喇叭":
|
||||
if latest_message != "暂无消息" and latest_message != "全服大喇叭":
|
||||
global_server_broadcast.text = latest_message
|
||||
print("主界面大喇叭已更新为: ", latest_message)
|
||||
else:
|
||||
@@ -2236,13 +2255,11 @@ func _handle_broadcast_history_response(data: Dictionary):
|
||||
# 初始化大喇叭显示
|
||||
func _init_broadcast_display():
|
||||
if global_server_broadcast and global_server_broadcast_panel:
|
||||
# 先设置为空
|
||||
global_server_broadcast.text = ""
|
||||
# 设置默认文本
|
||||
global_server_broadcast.text = "全服大喇叭"
|
||||
|
||||
# 直接从本地文件加载历史消息
|
||||
# 先从本地加载,然后请求服务器最新消息
|
||||
_load_broadcast_from_local()
|
||||
|
||||
# 无论是否有本地消息,都请求服务器获取最新消息
|
||||
_request_latest_broadcast_message()
|
||||
|
||||
# 从本地文件加载大喇叭消息
|
||||
@@ -2269,20 +2286,21 @@ func _load_broadcast_from_local():
|
||||
var content = latest.get("content", "")
|
||||
global_server_broadcast.text = display_name + ": " + content
|
||||
|
||||
|
||||
|
||||
# 请求服务器获取最新的一条大喇叭消息
|
||||
func _request_latest_broadcast_message():
|
||||
# 请求最近1天的消息,只获取最新的一条
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.is_connected_to_server():
|
||||
# 请求最近1天的消息
|
||||
var success = tcp_network_manager_panel.send_message({
|
||||
"type": "request_broadcast_history",
|
||||
"days": 1,
|
||||
"limit": 1, # 只要最新的一条
|
||||
"limit": 10, # 获取最近10条,客户端取最新的
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
|
||||
if not success:
|
||||
print("请求最新大喇叭消息失败")
|
||||
else:
|
||||
print("未连接到服务器,无法请求最新大喇叭消息")
|
||||
|
||||
# 请求服务器历史消息用于刷新显示
|
||||
func _request_server_history_for_refresh():
|
||||
|
||||
@@ -270,7 +270,9 @@ glow_intensity = 1.0
|
||||
glow_strength = 0.75
|
||||
glow_bloom = 1.0
|
||||
glow_blend_mode = 1
|
||||
fog_enabled = true
|
||||
fog_mode = 1
|
||||
fog_sun_scatter = 1.0
|
||||
fog_density = 1.0
|
||||
|
||||
[node name="main" type="Node"]
|
||||
script = ExtResource("1_v3yaj")
|
||||
@@ -877,7 +879,7 @@ theme_override_constants/shadow_offset_y = 4
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 50
|
||||
text = "宠物背包2"
|
||||
text = "宠物背包"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="QuitButton" type="Button" parent="UI/BigPanel/PetBagPanel"]
|
||||
|
||||
@@ -456,7 +456,7 @@ func _on_data_received(data):
|
||||
# 添加商品到小卖部响应
|
||||
elif action_type == "add_product_to_store":
|
||||
if success:
|
||||
main_game.login_data["玩家小卖部"] = updated_data["玩家小卖部"]
|
||||
main_game.login_data["小卖部配置"] = updated_data["小卖部配置"]
|
||||
main_game.crop_warehouse = updated_data["作物仓库"]
|
||||
|
||||
# 更新UI
|
||||
@@ -472,7 +472,7 @@ func _on_data_received(data):
|
||||
# 下架小卖部商品响应
|
||||
elif action_type == "remove_store_product":
|
||||
if success:
|
||||
main_game.login_data["玩家小卖部"] = updated_data["玩家小卖部"]
|
||||
main_game.login_data["小卖部配置"] = updated_data["小卖部配置"]
|
||||
main_game.crop_warehouse = updated_data["作物仓库"]
|
||||
|
||||
# 更新UI
|
||||
@@ -510,7 +510,7 @@ func _on_data_received(data):
|
||||
elif action_type == "buy_store_booth":
|
||||
if success:
|
||||
main_game.money = updated_data["钱币"]
|
||||
main_game.login_data["小卖部格子数"] = updated_data["小卖部格子数"]
|
||||
main_game.login_data["小卖部配置"] = updated_data["小卖部配置"]
|
||||
|
||||
# 更新UI
|
||||
main_game._update_ui()
|
||||
|
||||
@@ -415,7 +415,7 @@ func _display_version_info():
|
||||
func _handle_login_success(user_data: Dictionary):
|
||||
# 保存登录数据到主游戏
|
||||
main_game.login_data = user_data.duplicate()
|
||||
main_game.remaining_likes = user_data.get("今日剩余点赞次数", 10)
|
||||
main_game.remaining_likes = user_data.get("点赞系统", {}).get("今日剩余点赞次数", 10)
|
||||
|
||||
# 更新主游戏数据
|
||||
main_game.experience = user_data.get("经验值", 0)
|
||||
|
||||
@@ -50,13 +50,15 @@ func update_player_store_ui():
|
||||
# 获取小卖部数据
|
||||
if main_game.is_visiting_mode:
|
||||
# 访问模式:显示被访问玩家的小卖部
|
||||
player_store_data = main_game.visited_player_data.get("玩家小卖部", [])
|
||||
max_store_slots = main_game.visited_player_data.get("小卖部格子数", 10)
|
||||
var store_config = main_game.visited_player_data.get("小卖部配置", {"商品列表": [], "格子数": 10})
|
||||
player_store_data = store_config.get("商品列表", [])
|
||||
max_store_slots = store_config.get("格子数", 10)
|
||||
buy_product_booth_button.hide() # 访问模式下隐藏购买格子按钮
|
||||
else:
|
||||
# 正常模式:显示自己的小卖部
|
||||
player_store_data = main_game.login_data.get("玩家小卖部", [])
|
||||
max_store_slots = main_game.login_data.get("小卖部格子数", 10)
|
||||
var store_config = main_game.login_data.get("小卖部配置", {"商品列表": [], "格子数": 10})
|
||||
player_store_data = store_config.get("商品列表", [])
|
||||
max_store_slots = store_config.get("格子数", 10)
|
||||
buy_product_booth_button.show() # 正常模式下显示购买格子按钮
|
||||
|
||||
# 创建商品按钮
|
||||
@@ -187,7 +189,7 @@ func _on_product_buy_selected(product_data: Dictionary, slot_index: int):
|
||||
batch_buy_popup.show_buy_popup(
|
||||
product_name,
|
||||
product_price,
|
||||
"玩家小卖部商品",
|
||||
"小卖部商品",
|
||||
"store_product", # 特殊类型标识
|
||||
_on_confirm_buy_store_product,
|
||||
_on_cancel_buy_store_product
|
||||
|
||||
@@ -85,8 +85,8 @@ func send_broadcast_message():
|
||||
else:
|
||||
Toast.show("消息发送失败", Color.RED, 2.0, 1.0)
|
||||
|
||||
# 接收全服大喇叭消息
|
||||
func receive_broadcast_message(data: Dictionary):
|
||||
# 统一的消息处理函数
|
||||
func _add_message_to_history(data: Dictionary):
|
||||
var username = data.get("username", "匿名")
|
||||
var player_name = data.get("玩家昵称", "")
|
||||
var content = data.get("content", "")
|
||||
@@ -109,18 +109,13 @@ func receive_broadcast_message(data: Dictionary):
|
||||
"display_name": display_name
|
||||
}
|
||||
|
||||
# 按时间戳插入到正确位置(保持时间顺序)
|
||||
var inserted = false
|
||||
for i in range(message_history.size()):
|
||||
if message_history[i].get("timestamp", 0) > timestamp:
|
||||
message_history.insert(i, message_record)
|
||||
inserted = true
|
||||
break
|
||||
|
||||
# 如果没有找到插入位置,说明是最新消息,添加到末尾
|
||||
if not inserted:
|
||||
message_history.append(message_record)
|
||||
|
||||
# 接收全服大喇叭消息
|
||||
func receive_broadcast_message(data: Dictionary):
|
||||
# 使用统一的处理函数
|
||||
_add_message_to_history(data)
|
||||
|
||||
# 保持消息历史记录在限制范围内
|
||||
if message_history.size() > max_message_history:
|
||||
message_history.pop_front()
|
||||
@@ -129,10 +124,6 @@ func receive_broadcast_message(data: Dictionary):
|
||||
if visible:
|
||||
update_message_display()
|
||||
|
||||
# 更新主界面的大喇叭显示
|
||||
if main_game and main_game.has_method("update_broadcast_display"):
|
||||
main_game.update_broadcast_display(display_name + ": " + content)
|
||||
|
||||
# 保存到本地
|
||||
save_chat_history()
|
||||
|
||||
@@ -229,25 +220,19 @@ func receive_history_messages(data: Dictionary):
|
||||
print("大喇叭面板收到历史消息: ", messages.size(), " 条")
|
||||
|
||||
if messages.size() > 0:
|
||||
# 清空当前消息历史
|
||||
# 清空当前历史记录,重新加载
|
||||
message_history.clear()
|
||||
|
||||
# 添加服务器返回的历史消息
|
||||
# 处理每条消息
|
||||
for msg in messages:
|
||||
var message_record = {
|
||||
"username": msg.get("username", "匿名"),
|
||||
"玩家昵称": msg.get("玩家昵称", ""),
|
||||
"content": msg.get("content", ""),
|
||||
"timestamp": msg.get("timestamp", 0),
|
||||
"time_str": msg.get("time_str", ""),
|
||||
"display_name": msg.get("display_name", msg.get("username", "匿名"))
|
||||
}
|
||||
message_history.append(message_record)
|
||||
print("添加消息: ", message_record.display_name, ": ", message_record.content)
|
||||
_add_message_to_history(msg)
|
||||
|
||||
# 按时间戳排序消息历史(从旧到新)
|
||||
# 按时间戳排序
|
||||
message_history.sort_custom(func(a, b): return a.get("timestamp", 0) < b.get("timestamp", 0))
|
||||
print("排序后消息历史大小: ", message_history.size())
|
||||
|
||||
# 保持消息历史记录在限制范围内
|
||||
if message_history.size() > max_message_history:
|
||||
message_history = message_history.slice(-max_message_history)
|
||||
|
||||
# 更新显示
|
||||
update_message_display()
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
# 萌芽农场 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文件的备选方案,为后续的全面迁移奠定了坚实的基础。
|
||||
@@ -195,7 +195,7 @@ class EmailVerification:
|
||||
@staticmethod
|
||||
def save_verification_code(qq_number, verification_code, expiry_time=300, code_type="register"):
|
||||
"""
|
||||
保存验证码到缓存文件
|
||||
保存验证码到MongoDB(优先)或缓存文件(备用)
|
||||
|
||||
参数:
|
||||
qq_number (str): QQ号
|
||||
@@ -208,6 +208,21 @@ class EmailVerification:
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
mongo_api = SMYMongoDBAPI("test")
|
||||
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)
|
||||
|
||||
@@ -239,7 +254,7 @@ class EmailVerification:
|
||||
with open(VERIFICATION_CACHE_FILE, 'w', encoding='utf-8') as file:
|
||||
json.dump(verification_data, file, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"[验证码系统] 为QQ {qq_number} 保存{code_type}验证码: {verification_code}, 过期时间: {expire_at}")
|
||||
print(f"[验证码系统-JSON] 为QQ {qq_number} 保存{code_type}验证码: {verification_code}, 过期时间: {expire_at}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"保存验证码失败: {str(e)}")
|
||||
@@ -248,7 +263,7 @@ class EmailVerification:
|
||||
@staticmethod
|
||||
def verify_code(qq_number, input_code, code_type="register"):
|
||||
"""
|
||||
验证用户输入的验证码
|
||||
验证用户输入的验证码(优先使用MongoDB)
|
||||
|
||||
参数:
|
||||
qq_number (str): QQ号
|
||||
@@ -261,9 +276,21 @@ class EmailVerification:
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
mongo_api = SMYMongoDBAPI("test")
|
||||
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"[验证码系统] QQ {qq_number} 验证失败: 缓存文件不存在")
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 缓存文件不存在")
|
||||
return False, "验证码不存在或已过期"
|
||||
|
||||
# 读取验证码数据
|
||||
@@ -271,12 +298,12 @@ class EmailVerification:
|
||||
with open(VERIFICATION_CACHE_FILE, 'r', encoding='utf-8') as file:
|
||||
verification_data = json.load(file)
|
||||
except Exception as e:
|
||||
print(f"[验证码系统] 读取验证码文件失败: {str(e)}")
|
||||
print(f"[验证码系统-JSON] 读取验证码文件失败: {str(e)}")
|
||||
return False, "验证码数据损坏"
|
||||
|
||||
# 检查该QQ号是否有验证码
|
||||
if qq_number not in verification_data:
|
||||
print(f"[验证码系统] QQ {qq_number} 验证失败: 没有找到验证码记录")
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 没有找到验证码记录")
|
||||
return False, "验证码不存在,请重新获取"
|
||||
|
||||
# 获取存储的验证码信息
|
||||
@@ -287,16 +314,16 @@ class EmailVerification:
|
||||
is_used = code_info.get("used", False)
|
||||
created_at = code_info.get("created_at", 0)
|
||||
|
||||
print(f"[验证码系统] QQ {qq_number} 验证码详情: 存储码={stored_code}, 输入码={input_code}, 类型={stored_code_type}, 已使用={is_used}, 创建时间={created_at}")
|
||||
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"[验证码系统] QQ {qq_number} 验证失败: 验证码类型不匹配,存储类型={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"[验证码系统] QQ {qq_number} 验证失败: 验证码已被使用")
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码已被使用")
|
||||
return False, "验证码已被使用,请重新获取"
|
||||
|
||||
# 检查验证码是否过期
|
||||
@@ -306,7 +333,7 @@ class EmailVerification:
|
||||
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"[验证码系统] QQ {qq_number} 验证失败: 验证码已过期")
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码已过期")
|
||||
return False, "验证码已过期,请重新获取"
|
||||
|
||||
# 验证码比较(不区分大小写)
|
||||
@@ -318,22 +345,34 @@ class EmailVerification:
|
||||
try:
|
||||
with open(VERIFICATION_CACHE_FILE, 'w', encoding='utf-8') as file:
|
||||
json.dump(verification_data, file, indent=2, ensure_ascii=False)
|
||||
print(f"[验证码系统] QQ {qq_number} 验证成功: 验证码已标记为已使用")
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证成功: 验证码已标记为已使用")
|
||||
return True, "验证码正确"
|
||||
except Exception as e:
|
||||
print(f"[验证码系统] 标记验证码已使用时失败: {str(e)}")
|
||||
print(f"[验证码系统-JSON] 标记验证码已使用时失败: {str(e)}")
|
||||
return True, "验证码正确" # 即使标记失败,验证还是成功的
|
||||
else:
|
||||
print(f"[验证码系统] QQ {qq_number} 验证失败: 验证码不匹配")
|
||||
print(f"[验证码系统-JSON] QQ {qq_number} 验证失败: 验证码不匹配")
|
||||
return False, "验证码错误"
|
||||
|
||||
@staticmethod
|
||||
def clean_expired_codes():
|
||||
"""
|
||||
清理过期的验证码和已使用的验证码
|
||||
清理过期的验证码和已使用的验证码(优先使用MongoDB)
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
mongo_api = SMYMongoDBAPI("test")
|
||||
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
|
||||
|
||||
@@ -355,12 +394,12 @@ class EmailVerification:
|
||||
# 过期的验证码
|
||||
if current_time > expire_at:
|
||||
should_remove = True
|
||||
print(f"[验证码清理] 移除过期验证码: QQ {qq_number}")
|
||||
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"[验证码清理] 移除已使用的验证码: QQ {qq_number}")
|
||||
print(f"[验证码清理-JSON] 移除已使用的验证码: QQ {qq_number}")
|
||||
|
||||
if should_remove:
|
||||
removed_keys.append(qq_number)
|
||||
@@ -373,7 +412,7 @@ class EmailVerification:
|
||||
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"[验证码清理] 共清理了 {len(removed_keys)} 个验证码")
|
||||
print(f"[验证码清理-JSON] 共清理了 {len(removed_keys)} 个验证码")
|
||||
|
||||
except Exception as e:
|
||||
print(f"清理验证码失败: {str(e)}")
|
||||
@@ -381,7 +420,7 @@ class EmailVerification:
|
||||
@staticmethod
|
||||
def get_verification_status(qq_number):
|
||||
"""
|
||||
获取验证码状态(用于调试)
|
||||
获取验证码状态(优先使用MongoDB)
|
||||
|
||||
参数:
|
||||
qq_number (str): QQ号
|
||||
@@ -391,6 +430,33 @@ class EmailVerification:
|
||||
"""
|
||||
import time
|
||||
|
||||
# 优先尝试使用MongoDB
|
||||
try:
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
mongo_api = SMYMongoDBAPI("test")
|
||||
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"}
|
||||
|
||||
@@ -412,7 +478,8 @@ class EmailVerification:
|
||||
"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)
|
||||
"used_at": code_info.get("used_at", 0),
|
||||
"source": "json"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
from TCPServer import TCPServer
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
|
||||
import time
|
||||
import json
|
||||
import os
|
||||
@@ -8,6 +8,9 @@ import threading
|
||||
import datetime
|
||||
import re
|
||||
import random
|
||||
#导入服务器外置插件模块
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI #导入MongoDB数据库模块
|
||||
from QQEmailSendAPI import EmailVerification#导入QQ邮箱发送模块
|
||||
|
||||
"""
|
||||
萌芽农场TCP游戏服务器 - 代码结构说明
|
||||
@@ -30,14 +33,6 @@ import random
|
||||
- 批量数据保存:定时批量写入,提升性能
|
||||
- 智能缓存管理:LRU策略,自动清理过期数据
|
||||
|
||||
🎮 游戏功能模块:
|
||||
- 用户系统:注册、登录、邮箱验证
|
||||
- 农场系统:种植、收获、浇水、施肥
|
||||
- 升级系统:经验获取、等级提升
|
||||
- 社交系统:访问农场、点赞互动
|
||||
- 奖励系统:每日签到、幸运抽奖
|
||||
- 排行系统:玩家排行榜展示
|
||||
|
||||
📊 数据存储:
|
||||
- 玩家数据:JSON格式存储在game_saves目录
|
||||
- 配置文件:作物数据、初始模板等
|
||||
@@ -205,7 +200,7 @@ class TCPGameServer(TCPServer):
|
||||
def start_verification_code_cleanup_timer(self):
|
||||
"""启动验证码清理定时器"""
|
||||
try:
|
||||
from QQEmailSend import EmailVerification
|
||||
|
||||
EmailVerification.clean_expired_codes()
|
||||
self.log('INFO', "验证码清理完成", 'SERVER')
|
||||
except Exception as e:
|
||||
@@ -433,7 +428,7 @@ class TCPGameServer(TCPServer):
|
||||
|
||||
#加载作物配置数据(优化版本)
|
||||
def _load_crop_data(self):
|
||||
"""加载作物配置数据(带缓存优化)"""
|
||||
"""加载作物配置数据(优先MongoDB,带缓存优化)"""
|
||||
current_time = time.time()
|
||||
|
||||
# 检查缓存是否有效
|
||||
@@ -442,10 +437,26 @@ class TCPGameServer(TCPServer):
|
||||
return self.crop_data_cache
|
||||
|
||||
# 缓存过期或不存在,重新加载
|
||||
# 优先尝试从MongoDB加载
|
||||
if self.use_mongodb and self.mongo_api:
|
||||
try:
|
||||
crop_data = self.mongo_api.get_crop_data_config()
|
||||
if crop_data:
|
||||
self.crop_data_cache = crop_data
|
||||
self.crop_data_cache_time = current_time
|
||||
self.log('INFO', "成功从MongoDB加载作物数据配置", 'SERVER')
|
||||
return self.crop_data_cache
|
||||
else:
|
||||
self.log('WARNING', "MongoDB中未找到作物数据配置,尝试JSON文件", 'SERVER')
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"从MongoDB加载作物数据失败: {str(e)},尝试JSON文件", 'SERVER')
|
||||
|
||||
# MongoDB失败或不可用,尝试从JSON文件加载
|
||||
try:
|
||||
with open("config/crop_data.json", 'r', encoding='utf-8') as file:
|
||||
self.crop_data_cache = json.load(file)
|
||||
self.crop_data_cache_time = current_time
|
||||
self.log('INFO', "成功从JSON文件加载作物数据配置", 'SERVER')
|
||||
return self.crop_data_cache
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"无法加载作物数据: {str(e)}", 'SERVER')
|
||||
@@ -1059,7 +1070,7 @@ class TCPGameServer(TCPServer):
|
||||
|
||||
# 验证验证码
|
||||
if verification_code:
|
||||
from QQEmailSend import EmailVerification
|
||||
|
||||
success, verify_message = EmailVerification.verify_code(username, verification_code, "register")
|
||||
if not success:
|
||||
self.log('WARNING', f"QQ号 {username} 注册验证码验证失败: {verify_message}", 'SERVER')
|
||||
@@ -1092,54 +1103,47 @@ class TCPGameServer(TCPServer):
|
||||
|
||||
#辅助函数-创建新用户
|
||||
def _create_new_user(self, client_id, username, password, farm_name, player_name):
|
||||
"""创建新用户"""
|
||||
"""创建新用户(优先从MongoDB加载模板)"""
|
||||
try:
|
||||
# 从模板加载初始玩家数据
|
||||
# 优先从MongoDB加载初始玩家数据模板
|
||||
player_data = None
|
||||
if self.use_mongodb and self.mongo_api:
|
||||
try:
|
||||
player_data = self.mongo_api.get_initial_player_data_template()
|
||||
if player_data:
|
||||
self.log('INFO', "成功从MongoDB加载初始玩家数据模板", 'SERVER')
|
||||
else:
|
||||
self.log('WARNING', "MongoDB中未找到初始玩家数据模板,尝试从JSON文件加载", 'SERVER')
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"从MongoDB加载初始玩家数据模板失败: {str(e)},尝试从JSON文件加载", 'SERVER')
|
||||
|
||||
# MongoDB加载失败或不可用,从JSON文件加载
|
||||
if not player_data:
|
||||
template_path = os.path.join("config", "initial_player_data_template.json")
|
||||
if not os.path.exists(template_path):
|
||||
return self._send_register_error(client_id, "服务器配置错误,无法注册新用户")
|
||||
|
||||
with open(template_path, 'r', encoding='utf-8') as file:
|
||||
player_data = json.load(file)
|
||||
self.log('INFO', "成功从JSON文件加载初始玩家数据模板", 'SERVER')
|
||||
|
||||
# 更新玩家基本信息
|
||||
current_time = datetime.datetime.now()
|
||||
time_str = current_time.strftime("%Y年%m月%d日%H时%M分%S秒")
|
||||
|
||||
# 更新玩家数据
|
||||
player_data.update({
|
||||
"玩家账号": username,
|
||||
"玩家密码": password,
|
||||
"农场名称": farm_name or "我的农场",
|
||||
"玩家昵称": player_name or username,
|
||||
"个人简介": "", # 新增个人简介字段,默认为空
|
||||
"经验值": player_data.get("经验值", 0),
|
||||
"等级": player_data.get("等级", 1),
|
||||
"钱币": player_data.get("钱币", 1000)
|
||||
"个人简介": "",
|
||||
"最后登录时间": time_str,
|
||||
"注册时间": time_str,
|
||||
"总游玩时间": player_data.get("总游玩时间", "0时0分0秒")
|
||||
})
|
||||
|
||||
# 确保农场地块存在
|
||||
if "农场土地" not in player_data:
|
||||
player_data["农场土地"] = []
|
||||
for i in range(40):
|
||||
player_data["农场土地"].append({
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"is_dead": False,
|
||||
"is_diged": i < 5, # 默认开垦前5块地
|
||||
"is_planted": False,
|
||||
"max_grow_time": 5 if i >= 5 else 3
|
||||
})
|
||||
|
||||
if "种子仓库" not in player_data:
|
||||
player_data["种子仓库"] = []
|
||||
|
||||
# 更新注册时间和登录时间
|
||||
current_time = datetime.datetime.now()
|
||||
time_str = current_time.strftime("%Y年%m月%d日%H时%M分%S秒")
|
||||
player_data["最后登录时间"] = time_str
|
||||
|
||||
# 设置新玩家的注册时间(不同于模板中的默认时间)
|
||||
player_data["注册时间"] = time_str
|
||||
|
||||
if "总游玩时间" not in player_data:
|
||||
player_data["总游玩时间"] = "0时0分0秒"
|
||||
# 确保必要字段存在
|
||||
self._ensure_player_data_fields(player_data)
|
||||
|
||||
# 保存新用户数据
|
||||
file_path = os.path.join("game_saves", f"{username}.json")
|
||||
@@ -1148,7 +1152,6 @@ class TCPGameServer(TCPServer):
|
||||
|
||||
self.log('INFO', f"用户 {username} 注册成功,注册时间: {time_str},享受3天新玩家10倍生长速度奖励", 'SERVER')
|
||||
|
||||
# 返回成功响应
|
||||
return self.send_data(client_id, {
|
||||
"type": "register_response",
|
||||
"status": "success",
|
||||
@@ -1159,6 +1162,29 @@ class TCPGameServer(TCPServer):
|
||||
self.log('ERROR', f"注册用户 {username} 时出错: {str(e)}", 'SERVER')
|
||||
return self._send_register_error(client_id, f"注册过程中出现错误: {str(e)}")
|
||||
|
||||
def _ensure_player_data_fields(self, player_data):
|
||||
"""确保玩家数据包含所有必要字段"""
|
||||
# 确保农场地块存在
|
||||
if "农场土地" not in player_data:
|
||||
player_data["农场土地"] = []
|
||||
for i in range(40):
|
||||
player_data["农场土地"].append({
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"is_dead": False,
|
||||
"is_diged": i < 20, # 默认开垦前20块地
|
||||
"is_planted": False,
|
||||
"max_grow_time": 5 if i >= 20 else 3,
|
||||
"已浇水": False,
|
||||
"已施肥": False,
|
||||
"土地等级": 0
|
||||
})
|
||||
|
||||
# 确保基本仓库存在
|
||||
for field in ["种子仓库", "作物仓库", "道具背包", "宠物背包", "巡逻宠物", "出战宠物"]:
|
||||
if field not in player_data:
|
||||
player_data[field] = []
|
||||
|
||||
#辅助函数-客户端版本检查
|
||||
def _check_client_version(self, client_version, action_name="操作"):
|
||||
"""检查客户端版本是否与服务端匹配"""
|
||||
@@ -1176,7 +1202,6 @@ class TCPGameServer(TCPServer):
|
||||
#处理验证码请求
|
||||
def _handle_verification_code_request(self, client_id, message):
|
||||
"""处理验证码请求"""
|
||||
from QQEmailSend import EmailVerification
|
||||
|
||||
qq_number = message.get("qq_number", "")
|
||||
|
||||
@@ -1215,7 +1240,6 @@ class TCPGameServer(TCPServer):
|
||||
#处理验证码验证
|
||||
def _handle_verify_code(self, client_id, message):
|
||||
"""处理验证码验证"""
|
||||
from QQEmailSend import EmailVerification
|
||||
|
||||
qq_number = message.get("qq_number", "")
|
||||
input_code = message.get("code", "")
|
||||
@@ -1250,7 +1274,6 @@ class TCPGameServer(TCPServer):
|
||||
#处理忘记密码验证码请求
|
||||
def _handle_forget_password_verification_code_request(self, client_id, message):
|
||||
"""处理忘记密码验证码请求"""
|
||||
from QQEmailSend import EmailVerification
|
||||
|
||||
qq_number = message.get("qq_number", "")
|
||||
|
||||
@@ -1298,7 +1321,6 @@ class TCPGameServer(TCPServer):
|
||||
#处理重置密码请求
|
||||
def _handle_reset_password_request(self, client_id, message):
|
||||
"""处理重置密码请求"""
|
||||
from QQEmailSend import EmailVerification
|
||||
|
||||
username = message.get("username", "")
|
||||
new_password = message.get("new_password", "")
|
||||
@@ -5329,20 +5351,28 @@ class TCPGameServer(TCPServer):
|
||||
# 扣除点赞次数
|
||||
player_data["点赞系统"]["今日剩余点赞次数"] = remaining_likes - 1
|
||||
|
||||
# 初始化目标玩家的点赞系统(如果不存在)
|
||||
if "点赞系统" not in target_player_data:
|
||||
target_player_data["点赞系统"] = {
|
||||
"今日剩余点赞次数": 10,
|
||||
"点赞上次刷新时间": datetime.datetime.now().strftime("%Y-%m-%d"),
|
||||
"总点赞数": 0
|
||||
}
|
||||
|
||||
# 更新目标玩家的点赞数量
|
||||
target_player_data["点赞数"] = target_player_data.get("点赞数", 0) + 1
|
||||
target_player_data["点赞系统"]["总点赞数"] = target_player_data["点赞系统"].get("总点赞数", 0) + 1
|
||||
|
||||
# 保存两个玩家的数据
|
||||
self.save_player_data(username, player_data)
|
||||
self.save_player_data(target_username, target_player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 点赞了玩家 {target_username},目标玩家点赞数:{target_player_data['点赞数']},剩余点赞次数:{player_data['点赞系统']['今日剩余点赞次数']}", 'SERVER')
|
||||
self.log('INFO', f"玩家 {username} 点赞了玩家 {target_username},目标玩家点赞数:{target_player_data['点赞系统']['总点赞数']},剩余点赞次数:{player_data['点赞系统']['今日剩余点赞次数']}", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "like_player_response",
|
||||
"success": True,
|
||||
"message": f"成功点赞玩家 {target_username}!剩余点赞次数:{player_data['点赞系统']['今日剩余点赞次数']}",
|
||||
"target_likes": target_player_data["点赞数"],
|
||||
"target_likes": target_player_data["点赞系统"]["总点赞数"],
|
||||
"remaining_likes": player_data["点赞系统"]["今日剩余点赞次数"]
|
||||
})
|
||||
#检查并更新每日点赞次数
|
||||
@@ -5356,7 +5386,8 @@ class TCPGameServer(TCPServer):
|
||||
if "点赞系统" not in player_data:
|
||||
player_data["点赞系统"] = {
|
||||
"今日剩余点赞次数": 10,
|
||||
"点赞上次刷新时间": current_date
|
||||
"点赞上次刷新时间": current_date,
|
||||
"总点赞数": 0
|
||||
}
|
||||
return True # 发生了初始化
|
||||
|
||||
@@ -5367,6 +5398,8 @@ class TCPGameServer(TCPServer):
|
||||
like_system["今日剩余点赞次数"] = 10
|
||||
if "点赞上次刷新时间" not in like_system:
|
||||
like_system["点赞上次刷新时间"] = current_date
|
||||
if "总点赞数" not in like_system:
|
||||
like_system["总点赞数"] = 0
|
||||
|
||||
# 检查是否需要每日重置
|
||||
last_refresh_date = like_system.get("点赞上次刷新时间", "")
|
||||
@@ -5961,7 +5994,7 @@ class TCPGameServer(TCPServer):
|
||||
"last_login_timestamp": last_login_timestamp,
|
||||
"总游玩时间": total_time_str,
|
||||
"total_time_seconds": total_time_seconds,
|
||||
"like_num": player_data.get("点赞数", 0),
|
||||
"like_num": player_data.get("点赞系统", {}).get("总点赞数", 0),
|
||||
"is_online": is_online
|
||||
}
|
||||
|
||||
@@ -6123,9 +6156,8 @@ class TCPGameServer(TCPServer):
|
||||
"出战宠物": self._convert_battle_pets_to_full_data(target_player_data),
|
||||
"稻草人配置": target_player_data.get("稻草人配置", {}),
|
||||
"智慧树配置": target_player_data.get("智慧树配置", {}),
|
||||
"玩家小卖部": target_player_data.get("玩家小卖部", []), # 添加小卖部数据
|
||||
"小卖部格子数": target_player_data.get("小卖部格子数", 10), # 添加小卖部格子数
|
||||
"点赞数": target_player_data.get("点赞数", 0), # 添加点赞数
|
||||
"小卖部配置": target_player_data.get("小卖部配置", {"商品列表": [], "格子数": 10}), # 添加小卖部配置
|
||||
"点赞数": target_player_data.get("点赞系统", {}).get("总点赞数", 0), # 添加点赞数
|
||||
"最后登录时间": target_player_data.get("最后登录时间", "未知"),
|
||||
"总游玩时间": target_player_data.get("总游玩时间", "0时0分0秒"),
|
||||
"total_likes": target_player_data.get("total_likes", 0)
|
||||
@@ -6540,19 +6572,30 @@ class TCPGameServer(TCPServer):
|
||||
if player_data:
|
||||
player_name = player_data.get("玩家昵称", "")
|
||||
|
||||
# 获取当前时间戳
|
||||
current_timestamp = time.time()
|
||||
|
||||
# 创建广播消息
|
||||
broadcast_message = {
|
||||
"type": "global_broadcast_message",
|
||||
"username": username,
|
||||
"玩家昵称": player_name,
|
||||
"content": content,
|
||||
"timestamp": time.time()
|
||||
"timestamp": current_timestamp
|
||||
}
|
||||
|
||||
# 广播给所有在线用户
|
||||
self.broadcast(broadcast_message)
|
||||
|
||||
# 保存消息到日志文件
|
||||
# 保存消息到MongoDB
|
||||
if self.mongo_api and self.mongo_api.is_connected():
|
||||
success = self.mongo_api.save_chat_message(username, player_name, content, current_timestamp)
|
||||
if not success:
|
||||
self.log('WARNING', f"保存聊天消息到MongoDB失败,尝试保存到本地文件", 'BROADCAST')
|
||||
self._save_broadcast_message_to_log(username, player_name, content)
|
||||
else:
|
||||
# 如果MongoDB不可用,保存到本地文件作为备份
|
||||
self.log('WARNING', f"MongoDB不可用,保存聊天消息到本地文件", 'BROADCAST')
|
||||
self._save_broadcast_message_to_log(username, player_name, content)
|
||||
|
||||
# 发送成功响应给发送者
|
||||
@@ -6603,9 +6646,27 @@ class TCPGameServer(TCPServer):
|
||||
|
||||
try:
|
||||
days = message.get("days", 3) # 默认加载3天
|
||||
limit = message.get("limit", 500) # 默认限制500条
|
||||
if days > 30: # 限制最多30天
|
||||
days = 30
|
||||
|
||||
# 优先从MongoDB获取历史消息
|
||||
messages = []
|
||||
if self.mongo_api and self.mongo_api.is_connected():
|
||||
try:
|
||||
messages = self.mongo_api.get_chat_history(days, limit)
|
||||
# 转换数据格式以兼容客户端
|
||||
for msg in messages:
|
||||
msg["玩家昵称"] = msg.get("player_name", "")
|
||||
msg["display_name"] = msg.get("player_name", "") if msg.get("player_name") else msg.get("username", "匿名")
|
||||
self.log('INFO', f"从MongoDB获取了 {len(messages)} 条历史消息", 'SERVER')
|
||||
except Exception as e:
|
||||
self.log('ERROR', f"从MongoDB获取历史消息失败: {str(e)}", 'SERVER')
|
||||
messages = []
|
||||
|
||||
# 如果MongoDB获取失败或没有数据,尝试从本地文件获取
|
||||
if not messages:
|
||||
self.log('INFO', f"尝试从本地文件获取历史消息", 'SERVER')
|
||||
messages = self._load_broadcast_history(days)
|
||||
|
||||
# 发送历史消息响应
|
||||
@@ -6733,7 +6794,7 @@ class TCPGameServer(TCPServer):
|
||||
self.log('ERROR', f"解析日志消息失败: {line}, 错误: {str(e)}", 'SERVER')
|
||||
return None
|
||||
|
||||
#==========================全服大喇叭消息处理==========================
|
||||
#==========================全服大喇叭消息处理==========================
|
||||
|
||||
|
||||
|
||||
@@ -9223,13 +9284,15 @@ class TCPGameServer(TCPServer):
|
||||
return self._send_action_error(client_id, "add_product_to_store", "商品价格必须大于0")
|
||||
|
||||
# 初始化小卖部数据
|
||||
if "玩家小卖部" not in player_data:
|
||||
player_data["玩家小卖部"] = []
|
||||
if "小卖部格子数" not in player_data:
|
||||
player_data["小卖部格子数"] = 10
|
||||
if "小卖部配置" not in player_data:
|
||||
player_data["小卖部配置"] = {
|
||||
"商品列表": [],
|
||||
"格子数": 10
|
||||
}
|
||||
|
||||
player_store = player_data["玩家小卖部"]
|
||||
max_slots = player_data["小卖部格子数"]
|
||||
store_config = player_data["小卖部配置"]
|
||||
player_store = store_config["商品列表"]
|
||||
max_slots = store_config["格子数"]
|
||||
|
||||
# 检查小卖部格子是否已满
|
||||
if len(player_store) >= max_slots:
|
||||
@@ -9280,7 +9343,7 @@ class TCPGameServer(TCPServer):
|
||||
"success": True,
|
||||
"message": f"成功添加 {product_count} 个 {product_name} 到小卖部",
|
||||
"updated_data": {
|
||||
"玩家小卖部": player_data["玩家小卖部"],
|
||||
"小卖部配置": player_data["小卖部配置"],
|
||||
"作物仓库": player_data.get("作物仓库", [])
|
||||
}
|
||||
})
|
||||
@@ -9304,7 +9367,8 @@ class TCPGameServer(TCPServer):
|
||||
return self._send_action_error(client_id, "remove_store_product", "无效的商品槽位")
|
||||
|
||||
# 检查小卖部数据
|
||||
player_store = player_data.get("玩家小卖部", [])
|
||||
store_config = player_data.get("小卖部配置", {"商品列表": [], "格子数": 10})
|
||||
player_store = store_config.get("商品列表", [])
|
||||
if slot_index >= len(player_store):
|
||||
return self._send_action_error(client_id, "remove_store_product", "商品槽位不存在")
|
||||
|
||||
@@ -9356,7 +9420,7 @@ class TCPGameServer(TCPServer):
|
||||
"success": True,
|
||||
"message": f"成功下架 {product_count} 个 {product_name},已返回仓库",
|
||||
"updated_data": {
|
||||
"玩家小卖部": player_data["玩家小卖部"],
|
||||
"小卖部配置": player_data["小卖部配置"],
|
||||
"作物仓库": player_data.get("作物仓库", [])
|
||||
}
|
||||
})
|
||||
@@ -9399,7 +9463,8 @@ class TCPGameServer(TCPServer):
|
||||
return self._send_action_error(client_id, "buy_store_product", f"卖家 {seller_username} 不存在")
|
||||
|
||||
# 检查卖家小卖部
|
||||
seller_store = seller_data.get("玩家小卖部", [])
|
||||
seller_store_config = seller_data.get("小卖部配置", {"商品列表": [], "格子数": 10})
|
||||
seller_store = seller_store_config.get("商品列表", [])
|
||||
if slot_index >= len(seller_store):
|
||||
return self._send_action_error(client_id, "buy_store_product", "商品不存在")
|
||||
|
||||
@@ -9498,10 +9563,14 @@ class TCPGameServer(TCPServer):
|
||||
return self._send_action_error(client_id, "buy_store_booth", "无效的购买费用")
|
||||
|
||||
# 初始化小卖部数据
|
||||
if "小卖部格子数" not in player_data:
|
||||
player_data["小卖部格子数"] = 10
|
||||
if "小卖部配置" not in player_data:
|
||||
player_data["小卖部配置"] = {
|
||||
"商品列表": [],
|
||||
"格子数": 10
|
||||
}
|
||||
|
||||
current_slots = player_data["小卖部格子数"]
|
||||
store_config = player_data["小卖部配置"]
|
||||
current_slots = store_config["格子数"]
|
||||
|
||||
# 检查是否已达上限
|
||||
if current_slots >= 40:
|
||||
@@ -9518,21 +9587,21 @@ class TCPGameServer(TCPServer):
|
||||
|
||||
# 执行购买
|
||||
player_data["钱币"] -= cost
|
||||
player_data["小卖部格子数"] += 1
|
||||
store_config["格子数"] += 1
|
||||
|
||||
# 保存玩家数据
|
||||
self.save_player_data(username, player_data)
|
||||
|
||||
self.log('INFO', f"玩家 {username} 购买小卖部格子,花费 {cost} 元,格子数:{current_slots} -> {player_data['小卖部格子数']}", 'SERVER')
|
||||
self.log('INFO', f"玩家 {username} 购买小卖部格子,花费 {cost} 元,格子数:{current_slots} -> {store_config['格子数']}", 'SERVER')
|
||||
|
||||
return self.send_data(client_id, {
|
||||
"type": "action_response",
|
||||
"action_type": "buy_store_booth",
|
||||
"success": True,
|
||||
"message": f"成功购买格子,花费 {cost} 元,当前格子数:{player_data['小卖部格子数']}",
|
||||
"message": f"成功购买格子,花费 {cost} 元,当前格子数:{store_config['格子数']}",
|
||||
"updated_data": {
|
||||
"钱币": player_data["钱币"],
|
||||
"小卖部格子数": player_data["小卖部格子数"]
|
||||
"小卖部配置": player_data["小卖部配置"]
|
||||
}
|
||||
})
|
||||
#==========================小卖部管理处理==========================
|
||||
@@ -9803,10 +9872,24 @@ class ConsoleCommands:
|
||||
print(f"❌ 玩家 {qq_number} 不存在")
|
||||
return
|
||||
|
||||
# 加载初始化模板
|
||||
# 加载初始化模板(优先从MongoDB)
|
||||
template_data = None
|
||||
if self.server.use_mongodb and self.server.mongo_api:
|
||||
try:
|
||||
template_data = self.server.mongo_api.get_initial_player_data_template()
|
||||
if template_data:
|
||||
print("✅ 成功从MongoDB加载初始玩家数据模板")
|
||||
else:
|
||||
print("⚠️ MongoDB中未找到初始玩家数据模板,尝试从JSON文件加载")
|
||||
except Exception as e:
|
||||
print(f"⚠️ 从MongoDB加载初始玩家数据模板失败: {str(e)},尝试从JSON文件加载")
|
||||
|
||||
# MongoDB加载失败或不可用,从JSON文件加载
|
||||
if not template_data:
|
||||
try:
|
||||
with open("config/initial_player_data_template.json", 'r', encoding='utf-8') as f:
|
||||
template_data = json.load(f)
|
||||
print("✅ 成功从JSON文件加载初始玩家数据模板")
|
||||
except Exception as e:
|
||||
print(f"❌ 无法加载初始化模板: {str(e)}")
|
||||
return
|
||||
|
||||
Binary file not shown.
BIN
Server/__pycache__/QQEmailSendAPI.cpython-313.pyc
Normal file
BIN
Server/__pycache__/QQEmailSendAPI.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
# 这个文件确保 chat 文件夹被包含在版本控制中
|
||||
# 全服大喇叭消息日志将储存在这个文件夹中
|
||||
@@ -1,8 +0,0 @@
|
||||
[2025年07月06日 23:45:03] 树萌芽(3205788256): 1
|
||||
[2025年07月06日 23:45:05] 树萌芽(3205788256): 2
|
||||
[2025年07月06日 23:45:07] 树萌芽(3205788256): 3
|
||||
[2025年07月06日 23:45:09] 树萌芽(3205788256): 4
|
||||
[2025年07月06日 23:45:18] 树萌芽(3205788256): 5
|
||||
[2025年07月06日 23:51:18] 树萌芽(3205788256): 我知道你在玩,柚大青!
|
||||
[2025年07月06日 23:51:52] 柚大青(2143323382): (≧▽≦)
|
||||
[2025年07月06日 23:52:22] 柚大青(2143323382): 被你发现了哈哈哈ꉂꉂ(ᵔᗜᵔ*)
|
||||
@@ -1 +0,0 @@
|
||||
[2025年07月09日 09:19:45] 柚大青(2143323382): 12321312312
|
||||
@@ -1,5 +0,0 @@
|
||||
[2025年07月21日 10:20:26] 树萌芽(3205788256): 你好啊
|
||||
[2025年07月21日 10:22:05] 树萌芽(3205788256): 哈哈哈
|
||||
[2025年07月21日 10:23:53] 树萌芽(3205788256): 测试聊天
|
||||
[2025年07月21日 10:26:42] 3205788256(3205788256): 123213
|
||||
[2025年07月21日 10:37:22] 树萌芽(3205788256): 你好
|
||||
@@ -1,86 +0,0 @@
|
||||
{
|
||||
"测试作物": {"作物名称":"0号作物","成熟物名称":"0号作物","花费":1,"生长时间":5,"收益":10000,"品质":"普通","描述":"仅供测试使用的特殊作物","耐候性":10,"等级":1,"经验":999,"能否购买":false},
|
||||
"野草1": {"作物名称":"野草1","成熟物名称":null,"花费":0,"生长时间":5,"收益":-110,"品质":"普通","描述":"野草","耐候性":99,"等级":1,"经验":0,"能否购买":true,"是否杂草":true},
|
||||
"野草2": {"作物名称":"野草2","成熟物名称":null,"花费":0,"生长时间":5,"收益":-200,"品质":"普通","描述":"野草","耐候性":99,"等级":1,"经验":0,"能否购买":true,"是否杂草":true},
|
||||
"杂草1": {"作物名称":"杂草1","成熟物名称":null,"花费":0,"生长时间":5,"收益":-150,"品质":"普通","描述":"杂草","耐候性":99,"等级":1,"经验":0,"能否购买":true,"是否杂草":true},
|
||||
"杂草2": {"作物名称":"杂草2","成熟物名称":null,"花费":0,"生长时间":5,"收益":-90,"品质":"普通","描述":"野草","耐候性":99,"等级":1,"经验":0,"能否购买":true,"是否杂草":true},
|
||||
"小麦": {"作物名称":"小麦","成熟物名称":"小麦","花费":50,"生长时间":300,"收益":75,"品质":"普通","描述":"最基础的粮食作物,生长快速,适合新手练习","耐候性":8,"等级":1,"经验":8,"能否购买":true},
|
||||
"胡萝卜": {"作物名称":"胡萝卜","成熟物名称":"胡萝卜","花费":40,"生长时间":240,"收益":65,"品质":"普通","描述":"营养丰富的根茎类蔬菜,容易种植","耐候性":9,"等级":1,"经验":7,"能否购买":true,"喂养效果":{"移动速度":5,"闪避率":2}},
|
||||
"土豆": {"作物名称":"土豆","成熟物名称":"马铃薯","花费":60,"生长时间":480,"收益":95,"品质":"普通","描述":"耐寒的块茎作物,产量稳定","耐候性":12,"等级":1,"经验":10,"能否购买":true},
|
||||
"稻谷": {"作物名称":"稻谷","成熟物名称":"稻谷","花费":70,"生长时间":600,"收益":110,"品质":"普通","描述":"重要的主粮作物,需要充足水分","耐候性":7,"等级":1,"经验":12,"能否购买":true},
|
||||
"大蒜": {"作物名称":"大蒜","成熟物名称":"大蒜","花费":50,"生长时间":550,"收益":100,"品质":"普通","描述":"常用调味作物,具有抗菌功效,种植门槛低","耐候性":10,"等级":1,"经验":8,"能否购买":true},
|
||||
"生菜": {"作物名称":"生菜","成熟物名称":"生菜","花费":45,"生长时间":650,"收益":120,"品质":"普通","描述":"速生叶菜,适合沙拉生食,需保持土壤湿润","耐候性":17,"等级":1,"经验":9,"能否购买":true},
|
||||
"石榴": {"作物名称":"石榴","成熟物名称":"石榴","花费":45,"生长时间":650,"收益":120,"品质":"普通","描述":"速生叶菜,适合沙拉生食,需保持土壤湿润","耐候性":17,"等级":1,"经验":9,"能否购买":true},
|
||||
"辣椒": {"作物名称":"辣椒","成熟物名称":"辣椒","花费":45,"生长时间":650,"收益":120,"品质":"普通","描述":"速生叶菜,适合沙拉生食,需保持土壤湿润","耐候性":17,"等级":1,"经验":9,"能否购买":true},
|
||||
"番茄": {"作物名称":"番茄","成熟物名称":"番茄","花费":90,"生长时间":720,"收益":140,"品质":"普通","描述":"多汁的果实,市场需求大","耐候性":8,"等级":2,"经验":16,"能否购买":true},
|
||||
"洋葱": {"作物名称":"洋葱","成熟物名称":"洋葱","花费":75,"生长时间":840,"收益":125,"品质":"普通","描述":"调味蔬菜,储存时间长","耐候性":11,"等级":2,"经验":14,"能否购买":true},
|
||||
"大豆": {"作物名称":"大豆","成熟物名称":"大豆","花费":85,"生长时间":1080,"收益":145,"品质":"普通","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"豌豆": {"作物名称":"豌豆","成熟物名称":"豌豆","花费":65,"生长时间":720,"收益":110,"品质":"普通","描述":"嫩绿的豆荚蔬菜","耐候性":10,"等级":2,"经验":15,"能否购买":true},
|
||||
"黄瓜": {"作物名称":"黄瓜","成熟物名称":"黄瓜","花费":85,"生长时间":1200,"收益":150,"品质":"普通","描述":"清脆爽口的瓜类","耐候性":8,"等级":2,"经验":18,"能否购买":true},
|
||||
"大白菜": {"作物名称":"大白菜","成熟物名称":"大白菜","花费":70,"生长时间":900,"收益":120,"品质":"普通","描述":"北方冬季的主要蔬菜","耐候性":15,"等级":2,"经验":16,"能否购买":true},
|
||||
"葡萄": {"作物名称":"葡萄","成熟物名称":"葡萄","花费":200,"生长时间":2700,"收益":340,"品质":"普通","描述":"用于酿酒的珍贵果实","耐候性":9,"等级":4,"经验":35,"能否购买":true},
|
||||
"南瓜": {"作物名称":"南瓜","成熟物名称":"南瓜","花费":180,"生长时间":3600,"收益":320,"品质":"普通","描述":"大型瓜果,节庆装饰的首选","耐候性":12,"等级":4,"经验":38,"能否购买":true},
|
||||
"茄子": {"作物名称":"茄子","成熟物名称":"茄子","花费":190,"生长时间":2400,"收益":310,"品质":"普通","描述":"紫色的营养蔬菜","耐候性":10,"等级":4,"经验":32,"能否购买":true},
|
||||
|
||||
"玉米": {"作物名称":"玉米","成熟物名称":"玉米","花费":80,"生长时间":900,"收益":130,"品质":"优良","描述":"高产的谷物作物,营养价值高","耐候性":10,"等级":2,"经验":15,"能否购买":true},
|
||||
"葫芦": {"作物名称":"葫芦","成熟物名称":"葫芦","花费":85,"生长时间":1080,"收益":145,"品质":"优良","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"柠檬": {"作物名称":"柠檬树","成熟物名称":"柠檬","花费":85,"生长时间":1080,"收益":145,"品质":"优良","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"枇杷": {"作物名称":"枇杷树","成熟物名称":"枇杷","花费":85,"生长时间":1080,"收益":145,"品质":"优良","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"山楂": {"作物名称":"山楂树","成熟物名称":"山楂","花费":85,"生长时间":1080,"收益":145,"品质":"优良","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"仙人掌":{"作物名称":"仙人掌","成熟物名称":"仙人掌","花费":85,"生长时间":1080,"收益":145,"品质":"优良","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"椰子": {"作物名称":"椰子树","成熟物名称":"椰子","花费":85,"生长时间":1080,"收益":145,"品质":"优良","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"西瓜": {"作物名称":"西瓜","成熟物名称":"西瓜","花费":250,"生长时间":4800,"收益":450,"品质":"优良","描述":"夏日消暑的大型水果","耐候性":6,"等级":5,"经验":50,"能否购买":true},
|
||||
"甘蔗": {"作物名称":"甘蔗","成熟物名称":"甘蔗","花费":280,"生长时间":5400,"收益":500,"品质":"优良","描述":"制糖的重要原料","耐候性":5,"等级":5,"经验":55,"能否购买":true},
|
||||
"甜菜": {"作物名称":"甜菜","成熟物名称":"甜菜","花费":240,"生长时间":4200,"收益":420,"品质":"优良","描述":"制糖的另一种选择","耐候性":11,"等级":5,"经验":45,"能否购买":true},
|
||||
"郁金香": {"作物名称":"郁金香","成熟物名称":"郁金香","花费":280,"生长时间":5100,"收益":510,"品质":"优良","描述":"美丽的观赏植物","耐候性":10,"等级":5,"经验":50,"能否购买":true},
|
||||
"花椰菜": {"作物名称":"花椰菜","成熟物名称":"花椰菜","花费":110,"生长时间":1320,"收益":185,"品质":"优良","描述":"营养丰富的十字花科蔬菜","耐候性":8,"等级":3,"经验":20,"能否购买":true},
|
||||
"柿子": {"作物名称":"柿子树","成熟物名称":"柿子","花费":140,"生长时间":1800,"收益":230,"品质":"优良","描述":"秋季成熟的甜美果实","耐候性":10,"等级":3,"经验":25,"能否购买":true},
|
||||
"梨子": {"作物名称":"梨树","成熟物名称":"梨子","花费":210,"生长时间":2820,"收益":350,"品质":"优良","描述":"春季开花的落叶果树","耐候性":10,"等级":3,"经验":25,"能否购买":true},
|
||||
"桃子": {"作物名称":"桃树","成熟物名称":"桃子","花费":220,"生长时间":2940,"收益":360,"品质":"优良","描述":"粉色花海中的果实树种","耐候性":9,"等级":3,"经验":25,"能否购买":true,"作物ID":"作物35","喂养效果":{"经验":10,"生命值":3,"攻击力":2,"移动速度":1,"亲密度":5}},
|
||||
"荔枝": {"作物名称":"荔枝树","成熟物名称":"荔枝","花费":230,"生长时间":3060,"收益":380,"品质":"优良","描述":"亚热带珍稀水果,果肉如凝脂","耐候性":8,"等级":3,"经验":26,"能否购买":true},
|
||||
"树莓": {"作物名称":"树莓","成熟物名称":"树莓","花费":140,"生长时间":2700,"收益":240,"品质":"优良","描述":"小巧精致的浆果","耐候性":9,"等级":3,"经验":30,"能否购买":true},
|
||||
"鱼腥草": {"作物名称":"鱼腥草","成熟物名称":"鱼腥草","花费":300,"生长时间":7200,"收益":600,"品质":"优良","描述":"具有特殊药用价值的野菜","耐候性":18,"等级":6,"经验":90,"能否购买":true},
|
||||
"芦笋": {"作物名称":"芦笋","成熟物名称":"芦笋","花费":220,"生长时间":3000,"收益":370,"品质":"优良","描述":"高档蔬菜,营养价值极高","耐候性":8,"等级":4,"经验":40,"能否购买":true},
|
||||
"苹果": {"作物名称":"苹果树","成熟物名称":"苹果","花费":450,"生长时间":9600,"收益":820,"品质":"优良","描述":"结果丰富的果树","耐候性":14,"等级":7,"经验":110,"能否购买":true,"喂养效果":{"生命值":5,"护甲值":2}},
|
||||
"橘子": {"作物名称":"橘子树","成熟物名称":"橘子","花费":480,"生长时间":10200,"收益":850,"品质":"优良","描述":"维生素C丰富的果树","耐候性":12,"等级":7,"经验":115,"能否购买":true},
|
||||
"香蕉": {"作物名称":"香蕉树","成熟物名称":"香蕉","花费":420,"生长时间":8400,"收益":780,"品质":"优良","描述":"热带水果之王","耐候性":5,"等级":7,"经验":100,"能否购买":true},
|
||||
|
||||
"牵牛花": {"作物名称":"牵牛花","成熟物名称":"牵牛花","花费":85,"生长时间":1080,"收益":145,"品质":"稀有","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"百合花": {"作物名称":"百合花","成熟物名称":"百合花","花费":260,"生长时间":4800,"收益":480,"品质":"稀有","描述":"美丽的观赏植物","耐候性":10,"等级":5,"经验":50,"能否购买":true},
|
||||
"山葵": {"作物名称":"山葵","成熟物名称":"山葵","花费":500,"生长时间":10800,"收益":1000,"品质":"稀有","描述":"日式料理的珍贵调料","耐候性":22,"等级":7,"经验":150,"能否购买":true},
|
||||
"草莓": {"作物名称":"草莓","成熟物名称":"草莓","花费":120,"生长时间":1440,"收益":200,"品质":"稀有","描述":"甜美的浆果,深受喜爱","耐候性":6,"等级":3,"经验":22,"能否购买":true,"喂养效果":{"经验":8,"暴击率":3,"亲密度":10}},
|
||||
"蓝莓": {"作物名称":"蓝莓","成熟物名称":"蓝莓","花费":160,"生长时间":2100,"收益":260,"品质":"稀有","描述":"抗氧化的超级食物","耐候性":7,"等级":3,"经验":28,"能否购买":true},
|
||||
"栀子花": {"作物名称":"栀子花","成熟物名称":"栀子花","花费":180,"生长时间":2400,"收益":300,"品质":"稀有","描述":"美丽的观赏植物","耐候性":10,"等级":3,"经验":25,"能否购买":true},
|
||||
"玫瑰花": {"作物名称":"玫瑰花","成熟物名称":"玫瑰花","花费":190,"生长时间":2520,"收益":310,"品质":"稀有","描述":"美丽的观赏植物","耐候性":10,"等级":3,"经验":25,"能否购买":true},
|
||||
"菠萝": {"作物名称":"菠萝","成熟物名称":"菠萝","花费":200,"生长时间":2700,"收益":340,"品质":"稀有","描述":"热带水果之王","耐候性":10,"等级":3,"经验":25,"能否购买":true},
|
||||
"芒果": {"作物名称":"芒果树","成熟物名称":"芒果","花费":240,"生长时间":3180,"收益":400,"品质":"稀有","描述":"热带阳光孕育的香甜果实","耐候性":10,"等级":3,"经验":27,"能否购买":true},
|
||||
"咖啡豆": {"作物名称":"咖啡豆","成熟物名称":"咖啡豆","花费":200,"生长时间":2500,"收益":340,"品质":"稀有","描述":"热带经济作物,果实经烘焙后可制成饮品,需温暖气候","耐候性":8,"等级":4,"经验":35,"能否购买":true},
|
||||
"可可豆": {"作物名称":"可可树","成熟物名称":"可可果","花费":200,"生长时间":2500,"收益":340,"品质":"稀有","描述":"制作巧克力的原料,需高温高湿环境,经济价值较高","耐候性":10,"等级":4,"经验":36,"能否购买":true},
|
||||
"向日葵": {"作物名称":"向日葵","成熟物名称":"向日葵","花费":160,"生长时间":3600,"收益":280,"品质":"稀有","描述":"向阳而生的美丽花朵","耐候性":13,"等级":4,"经验":35,"能否购买":true},
|
||||
"哈密瓜": {"作物名称":"哈密瓜","成熟物名称":"哈密瓜","花费":380,"生长时间":7800,"收益":700,"品质":"稀有","描述":"甘甜的高级水果","耐候性":8,"等级":6,"经验":85,"能否购买":true},
|
||||
"藏红花": {"作物名称":"藏红花","成熟物名称":"藏红花","花费":400,"生长时间":7000,"收益":710,"品质":"稀有","描述":"世界上最昂贵的香料之一,需精心照料,花朵可提取柱头","耐候性":9,"等级":6,"经验":80,"能否购买":true},
|
||||
"龙果": {"作物名称":"火龙果","成熟物名称":"火龙果","花费":800,"生长时间":14400,"收益":1500,"品质":"稀有","描述":"传说中的神秘果实,蕴含强大能量","耐候性":25,"等级":8,"经验":200,"能否购买":true},
|
||||
|
||||
"杨桃": {"作物名称":"杨桃","成熟物名称":"杨桃","花费":85,"生长时间":1080,"收益":145,"品质":"史诗","描述":"富含蛋白质的豆类作物","耐候性":9,"等级":2,"经验":18,"能否购买":true},
|
||||
"香草": {"作物名称":"香草","成熟物名称":"香草","花费":300,"生长时间":6000,"收益":550,"品质":"史诗","描述":"珍贵的调料植物","耐候性":7,"等级":5,"经验":60,"能否购买":true},
|
||||
"康乃馨": {"作物名称":"康乃馨","成熟物名称":"康乃馨","花费":270,"生长时间":5100,"收益":510,"品质":"史诗","描述":"美丽的观赏植物","耐候性":10,"等级":5,"经验":50,"能否购买":true},
|
||||
"藏羚羊草": {"作物名称":"藏羚羊草","成熟物名称":"藏羚羊草","花费":80,"生长时间":200,"收益":200,"品质":"史诗","描述":"高原珍稀草种,用于生态修复,对土壤要求苛刻但市场需求大","耐候性":15,"等级":5,"经验":20,"能否购买":true},
|
||||
"迷迭香": {"作物名称":"迷迭香","成熟物名称":"迷迭香","花费":100,"生长时间":1680,"收益":210,"品质":"史诗","描述":"芳香型草本植物,可用于烹饪和精油提取,耐旱易存活","耐候性":12,"等级":3,"经验":22,"能否购买":true},
|
||||
"蕨菜": {"作物名称":"蕨菜","成熟物名称":"蕨菜","花费":180,"生长时间":2400,"收益":300,"品质":"史诗","描述":"野生山菜,口感独特","耐候性":16,"等级":4,"经验":35,"能否购买":true},
|
||||
"人参": {"作物名称":"人参","成熟物名称":"人参","花费":400,"生长时间":7200,"收益":720,"品质":"史诗","描述":"珍贵的药用植物,需要耐心培养","耐候性":15,"等级":6,"经验":80,"能否购买":true},
|
||||
"富贵竹": {"作物名称":"富贵竹","成熟物名称":"富贵竹","花费":350,"生长时间":6600,"收益":650,"品质":"史诗","描述":"寓意吉祥的观赏植物","耐候性":12,"等级":6,"经验":75,"能否购买":true},
|
||||
"芦荟": {"作物名称":"芦荟","成熟物名称":"芦荟","花费":320,"生长时间":6000,"收益":600,"品质":"史诗","描述":"具有药用价值的多肉植物","耐候性":18,"等级":6,"经验":70,"能否购买":true},
|
||||
"金橘": {"作物名称":"金橘子树","成熟物名称":"金橘","花费":500,"生长时间":10800,"收益":900,"品质":"史诗","描述":"金黄色的珍贵柑橘","耐候性":10,"等级":7,"经验":120,"能否购买":true},
|
||||
"松露": {"作物名称":"松露","成熟物名称":"松露","花费":1000,"生长时间":18000,"收益":2000,"品质":"史诗","描述":"地下的黑金,顶级料理的灵魂","耐候性":20,"等级":8,"经验":250,"能否购买":true},
|
||||
"冬虫夏草": {"作物名称":"冬虫夏草","成熟物名称":"冬虫夏草","花费":600,"生长时间":12000,"收益":1200,"品质":"史诗","描述":"稀世珍宝,药王之称","耐候性":30,"等级":7,"经验":180,"能否购买":true},
|
||||
|
||||
"糖果树": {"作物名称":"糖果树","成熟物名称":null,"花费":250,"生长时间":3300,"收益":420,"品质":"传奇","描述":"传说中结出彩色糖果的魔法树","耐候性":7,"等级":3,"经验":25,"能否购买":true},
|
||||
"面包树": {"作物名称":"面包树","成熟物名称":null,"花费":260,"生长时间":3420,"收益":440,"品质":"传奇","描述":"热带地区的淀粉质主食树种","耐候性":9,"等级":3,"经验":25,"能否购买":true},
|
||||
"幸运草": {"作物名称":"幸运草","成熟物名称":null,"花费":150,"生长时间":1560,"收益":220,"品质":"传奇","描述":"四片叶子的幸运象征植物","耐候性":6,"等级":3,"经验":20,"能否购买":true},
|
||||
"幸运花": {"作物名称":"幸运花","成熟物名称":null,"花费":170,"生长时间":1680,"收益":240,"品质":"传奇","描述":"绽放时带来好运的神秘花卉","耐候性":7,"等级":3,"经验":22,"能否购买":true},
|
||||
"摇钱树": {"作物名称":"摇钱树","成熟物名称":null,"花费":300,"生长时间":3600,"收益":500,"品质":"传奇","描述":"传说中能结出金币的神树","耐候性":10,"等级":3,"经验":30,"能否购买":true},
|
||||
"月光草": {"作物名称":"月光草","成熟物名称":"月光草","花费":700,"生长时间":14500,"收益":1500,"品质":"传奇","描述":"夜间开花的神秘植物,花瓣在月光下散发荧光,传说具有许愿功效","耐候性":20,"等级":8,"经验":200,"能否购买":true},
|
||||
"凤凰木": {"作物名称":"凤凰树","成熟物名称":"凤凰木","花费":650,"生长时间":12600,"收益":1400,"品质":"传奇","描述":"传说中凤凰栖息的神树,开花时如火焰般绚烂,木材可驱邪避灾","耐候性":25,"等级":8,"经验":210,"能否购买":true},
|
||||
"杂交树1": {"作物名称":"0号杂交树","成熟物名称":null,"花费":1200,"生长时间":21600,"收益":2500,"品质":"传奇","描述":"初中生物书最后的幻想","耐候性":35,"等级":9,"经验":300,"能否购买":true},
|
||||
"杂交树2": {"作物名称":"1号杂交树","成熟物名称":null,"花费":1500,"生长时间":25200,"收益":3000,"品质":"传奇","描述":"初中生物书最后的想象","耐候性":40,"等级":10,"经验":400,"能否购买":true}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
{
|
||||
"基础奖励": {
|
||||
"金币": {
|
||||
"最小值": 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,
|
||||
"描述": "满月连击奖励"
|
||||
}
|
||||
},
|
||||
"连击倍率": {
|
||||
"启用": true,
|
||||
"基础倍率": 1.0,
|
||||
"每日递增": 0.1,
|
||||
"最大倍率": 3.0,
|
||||
"说明": "连续签到可提升奖励倍率"
|
||||
},
|
||||
"历史记录": {
|
||||
"保存天数": 30,
|
||||
"清理规则": "超过30天的记录自动清理",
|
||||
"格式": "年月日时分秒: 奖励描述"
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
{
|
||||
"经验值": 0,
|
||||
"等级": 1,
|
||||
"钱币": 5000,
|
||||
"农场名称": "农场名称",
|
||||
"玩家昵称": "玩家名称",
|
||||
"玩家账号": "用户名",
|
||||
"玩家密码": "密码",
|
||||
"最后登录时间": "2025年07月20日17时19分16秒",
|
||||
"总游玩时间": "0时0分0秒",
|
||||
"农场土地": [],
|
||||
"种子仓库": [],
|
||||
"作物仓库": [],
|
||||
"宠物背包": [],
|
||||
"巡逻宠物": [],
|
||||
"出战宠物": [],
|
||||
"注册时间": "2025年05月21日15时00分00秒",
|
||||
"个人简介": "个人简介",
|
||||
"稻草人配置": {
|
||||
"已拥有稻草人类型": [
|
||||
"稻草人1"
|
||||
],
|
||||
"稻草人展示类型": "",
|
||||
"稻草人昵称": "稻草人",
|
||||
"稻草人说的话": {
|
||||
"第一句话": {
|
||||
"内容": "第一句话",
|
||||
"颜色": "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
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"精准采集-镰刀": {"花费":100,"描述":"可以在收获作物时必定掉落该作物的种子","类型":"作物道具","道具图片":"res://assets/道具图片/紫水晶镰刀.webp"},
|
||||
"时运-镰刀": {"花费":100,"描述":"可以在收获作物时掉落更多的作物的收获物","类型":"作物道具","道具图片":"res://assets/道具图片/红宝石镰刀.webp"},
|
||||
"农家肥": {"花费":100,"描述":"(施肥道具)可以在30分钟内2倍速作物生长","类型":"作物道具","道具图片":"res://assets/道具图片/农家肥.webp"},
|
||||
"金坷垃": {"花费":100,"描述":"(施肥道具)可以在5分钟内5倍速作物的生长","类型":"作物道具","道具图片":"res://assets/道具图片/金坷垃2.webp"},
|
||||
"水壶": {"花费":100,"描述":"(浇水道具)直接让作物生长进度+1%","类型":"作物道具","道具图片":"res://assets/道具图片/铁质洒水壶.webp"},
|
||||
"水桶": {"花费":100,"描述":"(浇水道具)让作物生长进度+2%","类型":"作物道具","道具图片":"res://assets/道具图片/木质水桶2.webp"},
|
||||
"杀虫剂": {"花费":100,"描述":"杀虫,暂时没什么用","类型":"作物道具","道具图片":"res://assets/道具图片/杀虫剂.webp"},
|
||||
"除草剂": {"花费":100,"描述":"除草","类型":"作物道具","道具图片":"res://assets/道具图片/除草剂.webp"},
|
||||
"生长素": {"花费":100,"描述":"时运可以10分钟内3倍速作物生长,而且作物生长速度+3%","类型":"作物道具","道具图片":"res://assets/道具图片/生长素.webp"},
|
||||
"铲子": {"花费":100,"描述":"铲除作物","类型":"作物道具","道具图片":"res://assets/道具图片/附魔铁铲.webp"},
|
||||
|
||||
"不死图腾": {"花费":100,"描述":"让宠物死亡复活一次","类型":"宠物道具","道具图片":"res://assets/道具图片/不死图腾.webp"},
|
||||
"荆棘护甲": {"花费":100,"描述":"宠物收到伤害时反弹伤害给敌人","类型":"宠物道具","道具图片":"res://assets/道具图片/荆棘护甲.webp"},
|
||||
"狂暴药水": {"花费":100,"描述":"宠物血量低于某个值,进入狂暴模式","类型":"宠物道具","道具图片":"res://assets/道具图片/狂暴药水.webp"},
|
||||
"援军令牌": {"花费":100,"描述":"血量低于某个值,召唤一堆宠物仆从帮助你战斗","类型":"宠物道具","道具图片":"res://assets/道具图片/援军令牌.webp"},
|
||||
"金刚图腾": {"花费":100,"描述":"更改宠物元素为金元素","类型":"宠物道具","道具图片":"res://assets/道具图片/金元素图腾.webp"},
|
||||
"灵木图腾": {"花费":100,"描述":"更改宠物元素为木元素","类型":"宠物道具","道具图片":"res://assets/道具图片/木元素图腾.webp"},
|
||||
"潮汐图腾": {"花费":100,"描述":"更改宠物元素为水元素","类型":"宠物道具","道具图片":"res://assets/道具图片/水元素图腾.webp"},
|
||||
"烈焰图腾": {"花费":100,"描述":"更改宠物元素为火元素","类型":"宠物道具","道具图片":"res://assets/道具图片/火元素图腾.webp"},
|
||||
"敦岩图腾": {"花费":100,"描述":"更改宠物元素为土元素","类型":"宠物道具","道具图片":"res://assets/道具图片/土元素图腾.webp"},
|
||||
|
||||
"小额经验卡": {"花费":100,"描述":"让宠物获得500经验值","类型":"农场道具","道具图片":"res://assets/道具图片/小额经验卡.webp"},
|
||||
"小额金币卡": {"花费":100,"描述":"让宠物获得500金币","类型":"农场道具","道具图片":"res://assets/道具图片/小额金币卡.webp"}
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
{
|
||||
"抽奖费用": {
|
||||
"单抽": 800,
|
||||
"五连抽": 3600,
|
||||
"十连抽": 6400
|
||||
},
|
||||
"概率配置": {
|
||||
"普通": {
|
||||
"概率": 0.45,
|
||||
"金币范围": [100, 300],
|
||||
"经验范围": [50, 150],
|
||||
"种子数量": [2, 4]
|
||||
},
|
||||
"优良": {
|
||||
"概率": 0.25,
|
||||
"金币范围": [300, 600],
|
||||
"经验范围": [150, 300],
|
||||
"种子数量": [1, 3]
|
||||
},
|
||||
"稀有": {
|
||||
"概率": 0.12,
|
||||
"金币范围": [600, 1000],
|
||||
"经验范围": [300, 500],
|
||||
"种子数量": [1, 2]
|
||||
},
|
||||
"史诗": {
|
||||
"概率": 0.025,
|
||||
"金币范围": [1000, 1500],
|
||||
"经验范围": [500, 800],
|
||||
"种子数量": [1, 1]
|
||||
},
|
||||
"传奇": {
|
||||
"概率": 0.005,
|
||||
"金币范围": [1500, 2500],
|
||||
"经验范围": [800, 1200],
|
||||
"种子数量": [1, 1]
|
||||
},
|
||||
"空奖": {
|
||||
"概率": 0.15,
|
||||
"提示语": ["谢谢惠顾", "下次再来", "再试一次", "继续努力"]
|
||||
}
|
||||
},
|
||||
"礼包配置": {
|
||||
"成长套餐": {
|
||||
"稀有度": "优良",
|
||||
"内容": {
|
||||
"金币": [200, 400],
|
||||
"经验": [100, 200],
|
||||
"种子数量": [2, 3]
|
||||
}
|
||||
},
|
||||
"稀有礼包": {
|
||||
"稀有度": "稀有",
|
||||
"内容": {
|
||||
"金币": [400, 700],
|
||||
"经验": [200, 350],
|
||||
"种子数量": [2, 3]
|
||||
}
|
||||
},
|
||||
"史诗礼包": {
|
||||
"稀有度": "史诗",
|
||||
"内容": {
|
||||
"金币": [700, 1200],
|
||||
"经验": [350, 600],
|
||||
"种子数量": [1, 2]
|
||||
}
|
||||
},
|
||||
"传奇大礼包": {
|
||||
"稀有度": "传奇",
|
||||
"内容": {
|
||||
"金币": [1000, 2000],
|
||||
"经验": [600, 1000],
|
||||
"史诗种子数量": [1, 1],
|
||||
"稀有种子数量": [2, 3]
|
||||
}
|
||||
}
|
||||
},
|
||||
"保底机制": {
|
||||
"十连抽保底": true,
|
||||
"保底最低稀有度": "稀有"
|
||||
},
|
||||
"奖励类型权重": {
|
||||
"普通": {
|
||||
"金币": 0.4,
|
||||
"经验": 0.3,
|
||||
"种子": 0.3
|
||||
},
|
||||
"优良": {
|
||||
"金币": 0.3,
|
||||
"经验": 0.2,
|
||||
"种子": 0.3,
|
||||
"礼包": 0.2
|
||||
},
|
||||
"稀有": {
|
||||
"金币": 0.2,
|
||||
"经验": 0.2,
|
||||
"种子": 0.4,
|
||||
"礼包": 0.2
|
||||
},
|
||||
"史诗": {
|
||||
"金币": 0.2,
|
||||
"经验": 0.2,
|
||||
"种子": 0.4,
|
||||
"礼包": 0.2
|
||||
},
|
||||
"传奇": {
|
||||
"金币": 0.1,
|
||||
"经验": 0.1,
|
||||
"种子": 0.5,
|
||||
"礼包": 0.3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"新手礼包配置": {
|
||||
"礼包说明": "每个账号仅可领取一次的新手大礼包",
|
||||
"奖励内容": {
|
||||
"金币": 6000,
|
||||
"经验": 1000,
|
||||
"种子": [
|
||||
{
|
||||
"名称": "龙果",
|
||||
"品质": "传奇",
|
||||
"数量": 1
|
||||
},
|
||||
{
|
||||
"名称": "杂交树1",
|
||||
"品质": "传奇",
|
||||
"数量": 1
|
||||
},
|
||||
{
|
||||
"名称": "杂交树2",
|
||||
"品质": "传奇",
|
||||
"数量": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"提示消息": {
|
||||
"成功": "新手大礼包领取成功!获得6000金币、1000经验和3个传奇种子",
|
||||
"已领取": "新手大礼包已经领取过了"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
{
|
||||
"在线礼包配置": {
|
||||
"1分钟": {
|
||||
"时长秒数": 60,
|
||||
"奖励": {
|
||||
"金币": 100,
|
||||
"经验": 50,
|
||||
"种子": [
|
||||
{"名称": "小麦", "数量": 5},
|
||||
{"名称": "胡萝卜", "数量": 3}
|
||||
]
|
||||
}
|
||||
},
|
||||
"3分钟": {
|
||||
"时长秒数": 180,
|
||||
"奖励": {
|
||||
"金币": 250,
|
||||
"经验": 150,
|
||||
"种子": [
|
||||
{"名称": "胡萝卜", "数量": 5},
|
||||
{"名称": "玉米", "数量": 3}
|
||||
]
|
||||
}
|
||||
},
|
||||
"5分钟": {
|
||||
"时长秒数": 300,
|
||||
"奖励": {
|
||||
"金币": 500,
|
||||
"经验": 250,
|
||||
"种子": [
|
||||
{"名称": "玉米", "数量": 3},
|
||||
{"名称": "番茄", "数量": 2}
|
||||
]
|
||||
}
|
||||
},
|
||||
"10分钟": {
|
||||
"时长秒数": 600,
|
||||
"奖励": {
|
||||
"金币": 800,
|
||||
"经验": 400,
|
||||
"种子": [
|
||||
{"名称": "番茄", "数量": 3},
|
||||
{"名称": "辣椒", "数量": 2}
|
||||
]
|
||||
}
|
||||
},
|
||||
"30分钟": {
|
||||
"时长秒数": 1800,
|
||||
"奖励": {
|
||||
"金币": 1500,
|
||||
"经验": 750,
|
||||
"种子": [
|
||||
{"名称": "草莓", "数量": 2},
|
||||
{"名称": "花椰菜", "数量": 2}
|
||||
]
|
||||
}
|
||||
},
|
||||
"1小时": {
|
||||
"时长秒数": 3600,
|
||||
"奖励": {
|
||||
"金币": 3000,
|
||||
"经验": 1500,
|
||||
"种子": [
|
||||
{"名称": "葡萄", "数量": 2},
|
||||
{"名称": "南瓜", "数量": 1},
|
||||
{"名称": "咖啡豆", "数量": 1}
|
||||
]
|
||||
}
|
||||
},
|
||||
"3小时": {
|
||||
"时长秒数": 10800,
|
||||
"奖励": {
|
||||
"金币": 8000,
|
||||
"经验": 4000,
|
||||
"种子": [
|
||||
{"名称": "人参", "数量": 1},
|
||||
{"名称": "藏红花", "数量": 1}
|
||||
]
|
||||
}
|
||||
},
|
||||
"5小时": {
|
||||
"时长秒数": 18000,
|
||||
"奖励": {
|
||||
"金币": 15000,
|
||||
"经验": 7500,
|
||||
"种子": [
|
||||
{"名称": "龙果", "数量": 1},
|
||||
{"名称": "松露", "数量": 1},
|
||||
{"名称": "月光草", "数量": 1}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"每日重置": true,
|
||||
"在线时长记录保留天数": 1
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"稻草人类型": {
|
||||
"稻草人1": {"图片": "res://assets/道具图片/稻草人1.webp", "价格": 1000},
|
||||
"稻草人2": {"图片": "res://assets/道具图片/稻草人2.webp", "价格": 1000},
|
||||
"稻草人3": {"图片": "res://assets/道具图片/稻草人3.webp", "价格": 1000}
|
||||
},
|
||||
"修改稻草人配置花费": 300
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"体力系统配置": {
|
||||
"最大体力值": 20,
|
||||
"每小时恢复体力": 1,
|
||||
"恢复间隔秒数": 3600,
|
||||
"新玩家初始体力": 20,
|
||||
"体力消耗": {
|
||||
"浇水": 1,
|
||||
"施肥": 1,
|
||||
"挖地": 2,
|
||||
"收获": 1,
|
||||
"种植": 1,
|
||||
"除草": 1,
|
||||
"偷菜": 2
|
||||
},
|
||||
"提示消息": {
|
||||
"体力不足": "体力值不足!当前体力:{current_stamina},需要:{required_stamina}",
|
||||
"体力恢复": "体力已恢复到:{current_stamina}",
|
||||
"体力重置": "新的一天,体力已重置为:{current_stamina}",
|
||||
"体力消耗": "消耗 {amount} 点体力,剩余体力:{remaining_stamina}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"timestamp": "2024-01-01 12:00:00",
|
||||
"sender": "system",
|
||||
"content": "欢迎来到智慧树!这里是一个匿名的心愿许愿池,分享你的心声吧~",
|
||||
"id": "default_message_001"
|
||||
},
|
||||
{
|
||||
"timestamp": "2024-01-01 12:30:00",
|
||||
"sender": "system",
|
||||
"content": "记得定期给智慧树浇水施肥哦,它会越长越高~",
|
||||
"id": "default_message_002"
|
||||
},
|
||||
{
|
||||
"timestamp": "2024-01-01 13:00:00",
|
||||
"sender": "system",
|
||||
"content": "智慧树需要你的呵护,除草杀虫让它更健康!",
|
||||
"id": "default_message_003"
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-07-09 10:52:31",
|
||||
"sender": "2143323382",
|
||||
"content": "陌生人你好呀",
|
||||
"id": "e62d7c3e-4965-4110-b7f2-a5f5a3806d86"
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-07-09 15:46:18",
|
||||
"sender": "2143323382",
|
||||
"content": "你好",
|
||||
"id": "13c3e296-b23b-4ad4-a68e-93d28769614a"
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-07-09 16:53:16",
|
||||
"sender": "2143323382",
|
||||
"content": "我喜欢柚小青",
|
||||
"id": "5bf10c6b-fc73-4a5f-a246-99a474148175"
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-07-09 16:54:31",
|
||||
"sender": "2143323382",
|
||||
"content": "柚小青最可爱",
|
||||
"id": "f1af2d77-c860-4f1a-8d2b-f5dd0dc5a672"
|
||||
}
|
||||
],
|
||||
"total_messages": 7,
|
||||
"last_update": "2025-07-09 16:54:31"
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"经验值": 455,
|
||||
"等级": 36,
|
||||
"钱币": 200797815,
|
||||
"钱币": 200796649,
|
||||
"农场名称": "柚大青の小农场",
|
||||
"玩家昵称": "柚大青",
|
||||
"玩家账号": "2143323382",
|
||||
"玩家密码": "tyh@19900420",
|
||||
"最后登录时间": "2025年07月21日10时06分20秒",
|
||||
"总游玩时间": "6时47分13秒",
|
||||
"最后登录时间": "2025年07月21日13时43分17秒",
|
||||
"总游玩时间": "6时50分12秒",
|
||||
"农场土地": [
|
||||
{
|
||||
"crop_type": "",
|
||||
@@ -715,7 +715,7 @@
|
||||
{
|
||||
"name": "土豆",
|
||||
"quality": "普通",
|
||||
"count": 18
|
||||
"count": 19
|
||||
},
|
||||
{
|
||||
"name": "咖啡豆",
|
||||
@@ -745,7 +745,7 @@
|
||||
{
|
||||
"name": "仙人掌",
|
||||
"quality": "优良",
|
||||
"count": 4
|
||||
"count": 5
|
||||
},
|
||||
{
|
||||
"name": "大豆",
|
||||
@@ -993,7 +993,8 @@
|
||||
},
|
||||
"点赞系统": {
|
||||
"今日剩余点赞次数": 10,
|
||||
"点赞上次刷新时间": "2025-07-21"
|
||||
"点赞上次刷新时间": "2025-07-21",
|
||||
"总点赞数": 0
|
||||
},
|
||||
"新手礼包": {
|
||||
"已领取": true,
|
||||
@@ -1047,8 +1048,10 @@
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"玩家小卖部": [],
|
||||
"小卖部格子数": 10,
|
||||
"小卖部配置": {
|
||||
"商品列表": [],
|
||||
"格子数": 50
|
||||
},
|
||||
"游戏设置": {
|
||||
"背景音乐音量": 1.0,
|
||||
"天气显示": true
|
||||
@@ -1092,6 +1095,5 @@
|
||||
}
|
||||
},
|
||||
"稻草人昵称颜色": "b38282ff"
|
||||
},
|
||||
"点赞数": 10
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
155
Server/test_initial_player_template_migration.py
Normal file
155
Server/test_initial_player_template_migration.py
Normal file
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
初始玩家数据模板MongoDB迁移测试脚本
|
||||
作者: AI Assistant
|
||||
功能: 测试初始玩家数据模板从JSON到MongoDB的迁移功能
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
|
||||
def load_template_from_json():
|
||||
"""从JSON文件加载初始玩家数据模板"""
|
||||
try:
|
||||
with open("config/initial_player_data_template.json", 'r', encoding='utf-8') as file:
|
||||
return json.load(file)
|
||||
except Exception as e:
|
||||
print(f"❌ 加载JSON文件失败: {e}")
|
||||
return None
|
||||
|
||||
def test_initial_player_template_migration():
|
||||
"""测试初始玩家数据模板迁移"""
|
||||
print("=== 初始玩家数据模板MongoDB迁移测试 ===")
|
||||
|
||||
# 1. 连接MongoDB
|
||||
print("\n1. 连接MongoDB...")
|
||||
try:
|
||||
api = SMYMongoDBAPI("test")
|
||||
if not api.is_connected():
|
||||
print("❌ MongoDB连接失败")
|
||||
return False
|
||||
print("✅ MongoDB连接成功")
|
||||
except Exception as e:
|
||||
print(f"❌ MongoDB连接异常: {e}")
|
||||
return False
|
||||
|
||||
# 2. 从JSON文件加载模板数据
|
||||
print("\n2. 从JSON文件加载初始玩家数据模板...")
|
||||
json_data = load_template_from_json()
|
||||
if not json_data:
|
||||
print("❌ JSON数据加载失败")
|
||||
return False
|
||||
print(f"✅ JSON数据加载成功,包含字段: {len(json_data)} 个")
|
||||
print(f" 主要字段: {list(json_data.keys())[:8]}...")
|
||||
|
||||
# 3. 测试从MongoDB获取模板数据
|
||||
print("\n3. 从MongoDB获取初始玩家数据模板...")
|
||||
try:
|
||||
mongo_data = api.get_initial_player_data_template()
|
||||
if mongo_data:
|
||||
print(f"✅ MongoDB数据获取成功,包含字段: {len(mongo_data)} 个")
|
||||
|
||||
# 4. 比较数据一致性
|
||||
print("\n4. 比较数据一致性...")
|
||||
if len(json_data) == len(mongo_data):
|
||||
print("✅ 字段数量一致")
|
||||
else:
|
||||
print(f"⚠️ 字段数量不一致: JSON({len(json_data)}) vs MongoDB({len(mongo_data)})")
|
||||
|
||||
# 检查关键字段
|
||||
key_fields = ["经验值", "等级", "钱币", "农场土地", "种子仓库", "作物仓库", "道具背包"]
|
||||
for field in key_fields:
|
||||
if field in json_data and field in mongo_data:
|
||||
json_value = json_data[field]
|
||||
mongo_value = mongo_data[field]
|
||||
if json_value == mongo_value:
|
||||
print(f"✅ {field}: 数据一致")
|
||||
else:
|
||||
print(f"⚠️ {field}: 数据不一致")
|
||||
if field in ["经验值", "等级", "钱币"]:
|
||||
print(f" JSON: {json_value}, MongoDB: {mongo_value}")
|
||||
elif field == "农场土地":
|
||||
print(f" JSON: {len(json_value)}块地, MongoDB: {len(mongo_value)}块地")
|
||||
else:
|
||||
print(f"❌ {field}: 字段缺失")
|
||||
else:
|
||||
print("❌ MongoDB中未找到初始玩家数据模板")
|
||||
|
||||
# 5. 如果MongoDB中没有数据,尝试更新
|
||||
print("\n5. 尝试更新MongoDB中的初始玩家数据模板...")
|
||||
try:
|
||||
success = api.update_initial_player_data_template(json_data)
|
||||
if success:
|
||||
print("✅ 初始玩家数据模板更新到MongoDB成功")
|
||||
|
||||
# 再次验证
|
||||
print("\n6. 验证更新后的数据...")
|
||||
updated_data = api.get_initial_player_data_template()
|
||||
if updated_data and len(updated_data) == len(json_data):
|
||||
print("✅ 数据更新验证成功")
|
||||
|
||||
# 验证关键字段
|
||||
for field in ["经验值", "等级", "钱币"]:
|
||||
if field in updated_data and updated_data[field] == json_data[field]:
|
||||
print(f"✅ {field}: {updated_data[field]}")
|
||||
else:
|
||||
print("❌ 数据更新验证失败")
|
||||
else:
|
||||
print("❌ 初始玩家数据模板更新到MongoDB失败")
|
||||
except Exception as e:
|
||||
print(f"❌ 更新MongoDB数据时异常: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 从MongoDB获取数据时异常: {e}")
|
||||
return False
|
||||
|
||||
# 7. 测试服务器创建新用户逻辑
|
||||
print("\n7. 测试服务器创建新用户逻辑...")
|
||||
try:
|
||||
# 模拟服务器的创建用户逻辑
|
||||
from TCPGameServer import TCPGameServer
|
||||
|
||||
# 创建服务器实例(不启动网络服务)
|
||||
server = TCPGameServer()
|
||||
|
||||
# 测试模板加载(通过_ensure_player_data_fields方法间接测试)
|
||||
test_data = {"测试": "数据"}
|
||||
server._ensure_player_data_fields(test_data)
|
||||
|
||||
if "农场土地" in test_data and len(test_data["农场土地"]) == 40:
|
||||
print(f"✅ 服务器成功生成农场土地,共 {len(test_data['农场土地'])} 块")
|
||||
|
||||
# 检查前20块地是否已开垦
|
||||
digged_count = sum(1 for land in test_data["农场土地"] if land.get("is_diged", False))
|
||||
print(f"✅ 已开垦土地: {digged_count} 块")
|
||||
else:
|
||||
print("❌ 服务器农场土地生成失败")
|
||||
|
||||
# 检查基本仓库
|
||||
required_fields = ["种子仓库", "作物仓库", "道具背包", "宠物背包", "巡逻宠物", "出战宠物"]
|
||||
missing_fields = [field for field in required_fields if field not in test_data]
|
||||
if not missing_fields:
|
||||
print(f"✅ 所有必要仓库字段已创建: {required_fields}")
|
||||
else:
|
||||
print(f"❌ 缺少仓库字段: {missing_fields}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 测试服务器逻辑时异常: {e}")
|
||||
|
||||
print("\n=== 测试完成 ===")
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
try:
|
||||
test_initial_player_template_migration()
|
||||
except KeyboardInterrupt:
|
||||
print("\n测试被用户中断")
|
||||
except Exception as e:
|
||||
print(f"测试过程中发生异常: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
139
Server/test_optimized_config_api.py
Normal file
139
Server/test_optimized_config_api.py
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
测试优化后的配置API
|
||||
验证所有配置方法是否正常工作
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from SMYMongoDBAPI import SMYMongoDBAPI
|
||||
|
||||
def test_all_config_methods():
|
||||
"""测试所有配置方法"""
|
||||
print("=== 测试优化后的配置API ===")
|
||||
|
||||
try:
|
||||
# 创建API实例(测试环境)
|
||||
api = SMYMongoDBAPI("test")
|
||||
|
||||
if not api.is_connected():
|
||||
print("❌ 数据库连接失败,请检查MongoDB服务")
|
||||
return False
|
||||
|
||||
print("✅ 数据库连接成功")
|
||||
|
||||
# 测试所有配置方法
|
||||
config_tests = [
|
||||
("每日签到配置", api.get_daily_checkin_config),
|
||||
("幸运抽奖配置", api.get_lucky_draw_config),
|
||||
("新手大礼包配置", api.get_new_player_config),
|
||||
("智慧树配置", api.get_wisdom_tree_config),
|
||||
("稻草人配置", api.get_scare_crow_config),
|
||||
("在线礼包配置", api.get_online_gift_config),
|
||||
("道具配置", api.get_item_config),
|
||||
("宠物配置", api.get_pet_config),
|
||||
("体力系统配置", api.get_stamina_config),
|
||||
("作物数据配置", api.get_crop_data_config),
|
||||
("初始玩家数据模板", api.get_initial_player_data_template)
|
||||
]
|
||||
|
||||
success_count = 0
|
||||
total_count = len(config_tests)
|
||||
|
||||
for config_name, get_method in config_tests:
|
||||
try:
|
||||
config = get_method()
|
||||
if config:
|
||||
print(f"✅ {config_name}: 获取成功 ({len(config)} 个字段)")
|
||||
success_count += 1
|
||||
else:
|
||||
print(f"❌ {config_name}: 获取失败 (返回None)")
|
||||
except Exception as e:
|
||||
print(f"❌ {config_name}: 获取异常 - {e}")
|
||||
|
||||
print(f"\n=== 测试结果 ===")
|
||||
print(f"成功: {success_count}/{total_count}")
|
||||
print(f"成功率: {success_count/total_count*100:.1f}%")
|
||||
|
||||
# 测试CONFIG_IDS字典
|
||||
print(f"\n=== CONFIG_IDS字典验证 ===")
|
||||
print(f"配置ID数量: {len(api.CONFIG_IDS)}")
|
||||
for key, value in api.CONFIG_IDS.items():
|
||||
print(f" {key}: {value}")
|
||||
|
||||
# 断开连接
|
||||
api.disconnect()
|
||||
print("\n✅ 测试完成,数据库连接已断开")
|
||||
|
||||
return success_count == total_count
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 测试过程中出现异常: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def test_code_optimization():
|
||||
"""测试代码优化效果"""
|
||||
print("\n=== 代码优化验证 ===")
|
||||
|
||||
# 读取SMYMongoDBAPI.py文件
|
||||
try:
|
||||
with open('SMYMongoDBAPI.py', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 统计代码行数
|
||||
lines = content.split('\n')
|
||||
total_lines = len(lines)
|
||||
|
||||
# 统计方法数量
|
||||
method_count = content.count('def ')
|
||||
|
||||
# 统计通用方法使用次数
|
||||
generic_get_usage = content.count('_get_config_by_id')
|
||||
generic_update_usage = content.count('_update_config_by_id')
|
||||
|
||||
print(f"✅ 代码文件总行数: {total_lines}")
|
||||
print(f"✅ 方法总数: {method_count}")
|
||||
print(f"✅ 通用获取方法使用次数: {generic_get_usage}")
|
||||
print(f"✅ 通用更新方法使用次数: {generic_update_usage}")
|
||||
|
||||
# 检查是否还有重复代码
|
||||
duplicate_patterns = [
|
||||
'collection.find_one({"_id": object_id})',
|
||||
'collection.replace_one({"_id": object_id}, update_data)',
|
||||
'if "_id" in result:',
|
||||
'del result["_id"]'
|
||||
]
|
||||
|
||||
print(f"\n=== 重复代码检查 ===")
|
||||
for pattern in duplicate_patterns:
|
||||
count = content.count(pattern)
|
||||
if count > 2: # 允许在通用方法中出现
|
||||
print(f"⚠️ 发现重复代码: '{pattern}' 出现 {count} 次")
|
||||
else:
|
||||
print(f"✅ 代码模式 '{pattern}' 已优化")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 代码优化验证失败: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("开始测试优化后的配置API...\n")
|
||||
|
||||
# 测试所有配置方法
|
||||
api_test_success = test_all_config_methods()
|
||||
|
||||
# 测试代码优化效果
|
||||
optimization_test_success = test_code_optimization()
|
||||
|
||||
print(f"\n=== 最终结果 ===")
|
||||
if api_test_success and optimization_test_success:
|
||||
print("🎉 所有测试通过!代码优化成功!")
|
||||
else:
|
||||
print("❌ 部分测试失败,请检查相关问题")
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 19020,
|
||||
"grow_time": 25230,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树1",
|
||||
"grow_time": 19060,
|
||||
"grow_time": 21670,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 4438,
|
||||
"grow_time": 25200,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 13308,
|
||||
"grow_time": 25254,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -101,7 +101,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 2218,
|
||||
"grow_time": 12749,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -178,7 +178,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 2216,
|
||||
"grow_time": 12747,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -189,7 +189,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 2216,
|
||||
"grow_time": 12747,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -200,7 +200,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 2216,
|
||||
"grow_time": 12747,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -277,7 +277,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 2214,
|
||||
"grow_time": 12745,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -321,7 +321,7 @@
|
||||
},
|
||||
{
|
||||
"crop_type": "杂交树2",
|
||||
"grow_time": 2213,
|
||||
"grow_time": 12744,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
@@ -822,9 +822,9 @@
|
||||
"农场名称": "树萌芽の狗窝",
|
||||
"玩家昵称": "树萌芽",
|
||||
"等级": 66,
|
||||
"钱币": 615196901889,
|
||||
"最后登录时间": "2025年07月21日10时54分03秒",
|
||||
"总游玩时间": "162时57分23秒",
|
||||
"钱币": 615196902055,
|
||||
"最后登录时间": "2025年07月21日13时20分46秒",
|
||||
"总游玩时间": "162时58分35秒",
|
||||
"玩家账号": "3205788256",
|
||||
"玩家密码": "123456",
|
||||
"个人简介": "人生啊,就这样吧",
|
||||
@@ -923,7 +923,7 @@
|
||||
{
|
||||
"name": "仙人掌",
|
||||
"quality": "优良",
|
||||
"count": 3
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"name": "胡萝卜",
|
||||
@@ -933,7 +933,7 @@
|
||||
{
|
||||
"name": "土豆",
|
||||
"quality": "普通",
|
||||
"count": 3
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"name": "马铃薯",
|
||||
@@ -1361,27 +1361,10 @@
|
||||
],
|
||||
"登录时间": 1753061433.2417476
|
||||
},
|
||||
"玩家小卖部": [
|
||||
{
|
||||
"商品类型": "作物",
|
||||
"商品名称": "番茄",
|
||||
"商品价格": 999,
|
||||
"商品数量": 1
|
||||
"小卖部配置": {
|
||||
"商品列表": [],
|
||||
"格子数": 11
|
||||
},
|
||||
{
|
||||
"商品类型": "作物",
|
||||
"商品名称": "番茄",
|
||||
"商品价格": 888,
|
||||
"商品数量": 81
|
||||
},
|
||||
{
|
||||
"商品类型": "作物",
|
||||
"商品名称": "荔枝",
|
||||
"商品价格": 99999999999999999,
|
||||
"商品数量": 1
|
||||
}
|
||||
],
|
||||
"小卖部格子数": 10,
|
||||
"游戏设置": {
|
||||
"背景音乐音量": 0.0,
|
||||
"天气显示": true
|
||||
|
||||
Reference in New Issue
Block a user