完成部分服务器数据向MongoDB数据库迁移
This commit is contained in:
@@ -23,12 +23,21 @@ var music_files: Array[String] = []
|
||||
var current_index: int = 0
|
||||
var played_indices: Array[int] = [] # 随机模式已播放的索引
|
||||
|
||||
# 音量控制相关
|
||||
var current_volume: float = 1.0 # 当前音量 (0.0-1.0)
|
||||
var is_muted: bool = false # 是否静音
|
||||
var volume_before_mute: float = 1.0 # 静音前的音量
|
||||
|
||||
func _ready():
|
||||
# 创建音频播放器
|
||||
audio_player = AudioStreamPlayer.new()
|
||||
add_child(audio_player)
|
||||
audio_player.finished.connect(_on_music_finished)
|
||||
|
||||
# 从全局变量读取初始音量设置
|
||||
current_volume = GlobalVariables.BackgroundMusicVolume
|
||||
audio_player.volume_db = linear_to_db(current_volume)
|
||||
|
||||
# 加载音乐文件
|
||||
_load_music_files()
|
||||
|
||||
@@ -164,3 +173,70 @@ func add_music_file(file_path: String) -> bool:
|
||||
else:
|
||||
print("音乐文件不存在: ", file_path)
|
||||
return false
|
||||
|
||||
# ============================= 音量控制功能 =====================================
|
||||
|
||||
func set_volume(volume: float):
|
||||
"""设置音量 (0.0-1.0)"""
|
||||
current_volume = clamp(volume, 0.0, 1.0)
|
||||
if not is_muted:
|
||||
audio_player.volume_db = linear_to_db(current_volume)
|
||||
print("背景音乐音量设置为: ", current_volume)
|
||||
|
||||
func get_volume() -> float:
|
||||
"""获取当前音量"""
|
||||
return current_volume
|
||||
|
||||
func set_mute(muted: bool):
|
||||
"""设置静音状态"""
|
||||
if muted and not is_muted:
|
||||
# 静音
|
||||
volume_before_mute = current_volume
|
||||
audio_player.volume_db = -80.0 # 设置为最小音量
|
||||
is_muted = true
|
||||
print("背景音乐已静音")
|
||||
elif not muted and is_muted:
|
||||
# 取消静音
|
||||
audio_player.volume_db = linear_to_db(current_volume)
|
||||
is_muted = false
|
||||
print("背景音乐取消静音")
|
||||
|
||||
func toggle_mute():
|
||||
"""切换静音状态"""
|
||||
set_mute(not is_muted)
|
||||
|
||||
func is_music_muted() -> bool:
|
||||
"""获取静音状态"""
|
||||
return is_muted
|
||||
|
||||
func pause():
|
||||
"""暂停音乐"""
|
||||
if audio_player.playing:
|
||||
audio_player.stream_paused = true
|
||||
print("背景音乐已暂停")
|
||||
|
||||
func resume():
|
||||
"""恢复音乐"""
|
||||
if audio_player.stream_paused:
|
||||
audio_player.stream_paused = false
|
||||
print("背景音乐已恢复")
|
||||
|
||||
func stop():
|
||||
"""停止音乐"""
|
||||
if audio_player.playing:
|
||||
audio_player.stop()
|
||||
print("背景音乐已停止")
|
||||
|
||||
func is_playing() -> bool:
|
||||
"""检查是否正在播放"""
|
||||
return audio_player.playing and not audio_player.stream_paused
|
||||
|
||||
func get_current_position() -> float:
|
||||
"""获取当前播放位置(秒)"""
|
||||
return audio_player.get_playback_position()
|
||||
|
||||
func get_current_length() -> float:
|
||||
"""获取当前音乐总长度(秒)"""
|
||||
if audio_player.stream:
|
||||
return audio_player.stream.get_length()
|
||||
return 0.0
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
extends Node
|
||||
|
||||
## 简单背景音乐播放器
|
||||
## 自动加载指定文件夹的音乐文件,支持顺序和随机循环播放
|
||||
|
||||
# 播放模式
|
||||
enum PlayMode {
|
||||
SEQUENTIAL, # 顺序循环
|
||||
RANDOM # 随机循环
|
||||
}
|
||||
|
||||
# 配置
|
||||
@export var music_folder: String = "res://assets/音乐/" # 音乐文件夹路径
|
||||
@export var play_mode: PlayMode = PlayMode.SEQUENTIAL # 播放模式
|
||||
@export var auto_start: bool = true # 自动开始播放
|
||||
|
||||
# 内部变量
|
||||
var audio_player: AudioStreamPlayer
|
||||
var music_files: Array[String] = []
|
||||
var current_index: int = 0
|
||||
var played_indices: Array[int] = [] # 随机模式已播放的索引
|
||||
|
||||
func _ready():
|
||||
# 创建音频播放器
|
||||
audio_player = AudioStreamPlayer.new()
|
||||
add_child(audio_player)
|
||||
audio_player.finished.connect(_on_music_finished)
|
||||
|
||||
# 加载音乐文件
|
||||
_load_music_files()
|
||||
|
||||
# 自动开始播放
|
||||
if auto_start and music_files.size() > 0:
|
||||
play_next()
|
||||
|
||||
func _load_music_files():
|
||||
"""加载指定文件夹下的音乐文件"""
|
||||
music_files.clear()
|
||||
|
||||
var dir = DirAccess.open(music_folder)
|
||||
if dir:
|
||||
dir.list_dir_begin()
|
||||
var file_name = dir.get_next()
|
||||
|
||||
while file_name != "":
|
||||
if not dir.current_is_dir():
|
||||
var extension = file_name.get_extension().to_lower()
|
||||
# 支持常见音频格式
|
||||
if extension in ["mp3", "ogg", "wav"]:
|
||||
music_files.append(music_folder + file_name)
|
||||
print("加载音乐: ", file_name)
|
||||
file_name = dir.get_next()
|
||||
|
||||
print("总共加载了 ", music_files.size(), " 首音乐")
|
||||
else:
|
||||
print("无法打开音乐文件夹: ", music_folder)
|
||||
|
||||
func play_next():
|
||||
"""播放下一首音乐"""
|
||||
if music_files.size() == 0:
|
||||
print("没有音乐文件可播放")
|
||||
return
|
||||
|
||||
# 根据播放模式获取下一首音乐的索引
|
||||
match play_mode:
|
||||
PlayMode.SEQUENTIAL:
|
||||
current_index = (current_index + 1) % music_files.size()
|
||||
PlayMode.RANDOM:
|
||||
current_index = _get_random_index()
|
||||
|
||||
# 播放音乐
|
||||
_play_music(current_index)
|
||||
|
||||
func _get_random_index() -> int:
|
||||
"""获取随机音乐索引(避免重复直到所有歌曲都播放过)"""
|
||||
# 如果所有歌曲都播放过了,重置列表
|
||||
if played_indices.size() >= music_files.size():
|
||||
played_indices.clear()
|
||||
|
||||
# 获取未播放的歌曲索引
|
||||
var available_indices: Array[int] = []
|
||||
for i in range(music_files.size()):
|
||||
if i not in played_indices:
|
||||
available_indices.append(i)
|
||||
|
||||
# 随机选择一个
|
||||
if available_indices.size() > 0:
|
||||
var random_choice = available_indices[randi() % available_indices.size()]
|
||||
played_indices.append(random_choice)
|
||||
return random_choice
|
||||
|
||||
return 0
|
||||
|
||||
func _play_music(index: int):
|
||||
"""播放指定索引的音乐"""
|
||||
if index < 0 or index >= music_files.size():
|
||||
return
|
||||
|
||||
var music_path = music_files[index]
|
||||
var audio_stream = load(music_path)
|
||||
|
||||
if audio_stream:
|
||||
audio_player.stream = audio_stream
|
||||
audio_player.play()
|
||||
print("正在播放: ", music_path.get_file())
|
||||
else:
|
||||
print("加载音乐失败: ", music_path)
|
||||
|
||||
func _on_music_finished():
|
||||
"""音乐播放完成时自动播放下一首"""
|
||||
play_next()
|
||||
|
||||
# 公共接口方法
|
||||
func set_play_mode(mode: PlayMode):
|
||||
"""设置播放模式"""
|
||||
play_mode = mode
|
||||
played_indices.clear() # 重置随机播放历史
|
||||
print("播放模式设置为: ", "顺序循环" if mode == PlayMode.SEQUENTIAL else "随机循环")
|
||||
|
||||
func toggle_play_mode():
|
||||
"""切换播放模式"""
|
||||
if play_mode == PlayMode.SEQUENTIAL:
|
||||
set_play_mode(PlayMode.RANDOM)
|
||||
else:
|
||||
set_play_mode(PlayMode.SEQUENTIAL)
|
||||
|
||||
func get_current_music_name() -> String:
|
||||
"""获取当前播放的音乐名称"""
|
||||
if current_index >= 0 and current_index < music_files.size():
|
||||
return music_files[current_index].get_file()
|
||||
return ""
|
||||
@@ -1 +0,0 @@
|
||||
uid://cq0ug1c7nibf1
|
||||
@@ -39,7 +39,6 @@ offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
[node name="ground_sprite" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.8, 0.8, 0.8, 1)
|
||||
material = SubResource("ShaderMaterial_v46ok")
|
||||
position = Vector2(50, 63)
|
||||
scale = Vector2(0.135, 0.135)
|
||||
@@ -50,11 +49,6 @@ material = SubResource("ShaderMaterial_s5pb0")
|
||||
position = Vector2(51, 45)
|
||||
scale = Vector2(0.339844, 0.363281)
|
||||
|
||||
[node name="old_crop_sprite" type="Sprite2D" parent="."]
|
||||
material = SubResource("ShaderMaterial_s5pb0")
|
||||
position = Vector2(51, 39)
|
||||
scale = Vector2(0.06, 0.06)
|
||||
|
||||
[node name="ProgressBar" type="ProgressBar" parent="."]
|
||||
visible = false
|
||||
material = SubResource("ShaderMaterial_cyybs")
|
||||
|
||||
@@ -1,9 +1,203 @@
|
||||
extends Panel
|
||||
#游戏设置面板
|
||||
|
||||
# UI组件引用
|
||||
@onready var background_music_h_slider: HSlider = $Scroll/Panel/BackgroundMusicHSlider
|
||||
@onready var weather_system_check: CheckButton = $Scroll/Panel/WeatherSystemCheck
|
||||
@onready var quit_button: Button = $QuitButton
|
||||
@onready var sure_button: Button = $SureButton
|
||||
@onready var refresh_button: Button = $RefreshButton
|
||||
|
||||
# 引用主游戏和其他组件
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var tcp_network_manager_panel: Panel = get_node("/root/main/UI/BigPanel/TCPNetworkManagerPanel")
|
||||
|
||||
# 游戏设置数据
|
||||
var game_settings: Dictionary = {
|
||||
"背景音乐音量": 1.0,
|
||||
"天气显示": true
|
||||
}
|
||||
|
||||
# 临时设置数据(用户修改但未确认的设置)
|
||||
var temp_settings: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
self.hide()
|
||||
pass
|
||||
|
||||
# 连接信号
|
||||
quit_button.pressed.connect(_on_quit_button_pressed)
|
||||
sure_button.pressed.connect(_on_sure_button_pressed)
|
||||
refresh_button.pressed.connect(_on_refresh_button_pressed)
|
||||
|
||||
# 设置音量滑块范围为0-1
|
||||
background_music_h_slider.min_value = 0.0
|
||||
background_music_h_slider.max_value = 1.0
|
||||
background_music_h_slider.step = 0.01
|
||||
background_music_h_slider.value_changed.connect(_on_background_music_h_slider_value_changed)
|
||||
weather_system_check.toggled.connect(_on_weather_system_check_toggled)
|
||||
|
||||
# 初始化设置值
|
||||
_load_settings_from_global()
|
||||
|
||||
# 当面板可见性改变时
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
func _on_visibility_changed():
|
||||
"""面板可见性改变时的处理"""
|
||||
if visible:
|
||||
# 面板显示时,刷新设置值
|
||||
_load_settings_from_global()
|
||||
_update_ui_from_settings()
|
||||
|
||||
# 禁用缩放功能
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
else:
|
||||
# 面板隐藏时,恢复缩放功能
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
|
||||
func _load_settings_from_global():
|
||||
"""从全局变量和玩家数据加载设置"""
|
||||
# 从GlobalVariables加载默认设置
|
||||
game_settings["背景音乐音量"] = GlobalVariables.BackgroundMusicVolume
|
||||
game_settings["天气显示"] = not GlobalVariables.DisableWeatherDisplay
|
||||
|
||||
# 如果主游戏已登录,尝试从玩家数据加载设置
|
||||
if main_game and main_game.login_data and main_game.login_data.has("游戏设置"):
|
||||
var player_settings = main_game.login_data["游戏设置"]
|
||||
if player_settings.has("背景音乐音量"):
|
||||
game_settings["背景音乐音量"] = player_settings["背景音乐音量"]
|
||||
if player_settings.has("天气显示"):
|
||||
game_settings["天气显示"] = player_settings["天气显示"]
|
||||
|
||||
# 初始化临时设置
|
||||
temp_settings = game_settings.duplicate()
|
||||
|
||||
func _update_ui_from_settings():
|
||||
"""根据设置数据更新UI"""
|
||||
# 更新音量滑块
|
||||
background_music_h_slider.value = temp_settings["背景音乐音量"]
|
||||
|
||||
# 更新天气显示复选框(注意:复选框表示"关闭天气显示")
|
||||
weather_system_check.button_pressed = not temp_settings["天气显示"]
|
||||
|
||||
func _apply_settings_immediately():
|
||||
"""立即应用设置(不保存到服务端)"""
|
||||
# 应用背景音乐音量设置
|
||||
_apply_music_volume_setting()
|
||||
|
||||
# 应用天气显示设置
|
||||
_apply_weather_display_setting()
|
||||
|
||||
func _save_settings_to_server():
|
||||
"""保存设置到服务端"""
|
||||
# 更新正式设置
|
||||
game_settings = temp_settings.duplicate()
|
||||
|
||||
# 应用设置
|
||||
_apply_settings_immediately()
|
||||
|
||||
# 如果已登录,保存到玩家数据并同步到服务端
|
||||
if main_game and main_game.login_data:
|
||||
main_game.login_data["游戏设置"] = game_settings.duplicate()
|
||||
|
||||
# 发送设置到服务端保存
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("is_connected_to_server") and tcp_network_manager_panel.is_connected_to_server():
|
||||
_send_settings_to_server()
|
||||
|
||||
func _apply_music_volume_setting():
|
||||
"""应用背景音乐音量设置"""
|
||||
var bgm_player = main_game.get_node_or_null("GameBGMPlayer")
|
||||
if bgm_player and bgm_player.has_method("set_volume"):
|
||||
bgm_player.set_volume(temp_settings["背景音乐音量"])
|
||||
|
||||
func _apply_weather_display_setting():
|
||||
"""应用天气显示设置"""
|
||||
var weather_system = main_game.get_node_or_null("WeatherSystem")
|
||||
if weather_system and weather_system.has_method("set_weather_display_enabled"):
|
||||
weather_system.set_weather_display_enabled(temp_settings["天气显示"])
|
||||
|
||||
func _send_settings_to_server():
|
||||
"""发送设置到服务端保存"""
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("send_message"):
|
||||
var message = {
|
||||
"type": "save_game_settings",
|
||||
"settings": game_settings,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
}
|
||||
|
||||
if tcp_network_manager_panel.send_message(message):
|
||||
print("游戏设置已发送到服务端保存")
|
||||
else:
|
||||
print("发送游戏设置到服务端失败")
|
||||
|
||||
func _on_quit_button_pressed() -> void:
|
||||
"""关闭设置面板"""
|
||||
self.hide()
|
||||
pass
|
||||
|
||||
func _on_background_music_h_slider_value_changed(value: float) -> void:
|
||||
"""背景音乐音量滑块值改变"""
|
||||
temp_settings["背景音乐音量"] = value
|
||||
# 立即应用音量设置(不保存到服务端)
|
||||
_apply_music_volume_setting()
|
||||
|
||||
# 显示当前音量百分比
|
||||
var volume_percent = int(value * 100)
|
||||
|
||||
func _on_weather_system_check_toggled(toggled_on: bool) -> void:
|
||||
"""天气系统复选框切换"""
|
||||
# 复选框表示"关闭天气显示",所以需要取反
|
||||
temp_settings["天气显示"] = not toggled_on
|
||||
# 立即应用天气设置(不保存到服务端)
|
||||
_apply_weather_display_setting()
|
||||
|
||||
# 显示提示
|
||||
var status_text = "已开启" if temp_settings["天气显示"] else "已关闭"
|
||||
Toast.show("天气显示" + status_text, Color.YELLOW)
|
||||
|
||||
#确认修改设置按钮,点击这个才会发送数据到服务端
|
||||
func _on_sure_button_pressed() -> void:
|
||||
"""确认修改设置"""
|
||||
_save_settings_to_server()
|
||||
Toast.show("设置已保存!", Color.GREEN)
|
||||
|
||||
#刷新设置面板,从服务端加载游戏设置数据
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
"""刷新设置"""
|
||||
_load_settings_from_global()
|
||||
_update_ui_from_settings()
|
||||
_apply_settings_immediately()
|
||||
Toast.show("设置已刷新!", Color.CYAN)
|
||||
|
||||
# 移除原来的自动保存方法,避免循环调用
|
||||
func _on_background_music_h_slider_drag_ended(value_changed: bool) -> void:
|
||||
"""背景音乐音量滑块拖拽结束(保留以兼容场景连接)"""
|
||||
# 不再自动保存,只显示提示
|
||||
if value_changed:
|
||||
var volume_percent = int(background_music_h_slider.value * 100)
|
||||
|
||||
# 公共方法,供外部调用
|
||||
func refresh_settings():
|
||||
"""刷新设置(从服务端或本地重新加载)"""
|
||||
_load_settings_from_global()
|
||||
_update_ui_from_settings()
|
||||
_apply_settings_immediately()
|
||||
|
||||
func get_current_settings() -> Dictionary:
|
||||
"""获取当前设置"""
|
||||
return game_settings.duplicate()
|
||||
|
||||
func apply_settings_from_server(server_settings: Dictionary):
|
||||
"""应用从服务端接收到的设置(避免循环调用)"""
|
||||
if server_settings.has("背景音乐音量"):
|
||||
game_settings["背景音乐音量"] = server_settings["背景音乐音量"]
|
||||
temp_settings["背景音乐音量"] = server_settings["背景音乐音量"]
|
||||
if server_settings.has("天气显示"):
|
||||
game_settings["天气显示"] = server_settings["天气显示"]
|
||||
temp_settings["天气显示"] = server_settings["天气显示"]
|
||||
|
||||
# 只更新UI,不再触发保存
|
||||
if visible:
|
||||
_update_ui_from_settings()
|
||||
_apply_settings_immediately()
|
||||
|
||||
print("已应用来自服务端的游戏设置")
|
||||
|
||||
@@ -23,8 +23,10 @@ corner_radius_bottom_left = 10
|
||||
corner_detail = 20
|
||||
|
||||
[node name="GameSettingPanel" type="Panel"]
|
||||
offset_right = 1398.0
|
||||
offset_bottom = 720.0
|
||||
offset_left = 151.0
|
||||
offset_top = 74.0
|
||||
offset_right = 1549.0
|
||||
offset_bottom = 794.0
|
||||
scale = Vector2(0.8, 0.8)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_0c52c")
|
||||
script = ExtResource("1_0c52c")
|
||||
@@ -78,18 +80,84 @@ layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Label" type="Label" parent="Scroll/Panel"]
|
||||
[node name="BackgroundMusicLabel" type="Label" parent="Scroll/Panel"]
|
||||
layout_mode = 2
|
||||
offset_right = 210.0
|
||||
offset_bottom = 42.0
|
||||
theme_override_font_sizes/font_size = 30
|
||||
offset_left = -1.52588e-05
|
||||
offset_right = 245.0
|
||||
offset_bottom = 49.0
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "背景音乐音量:"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Scroll/Panel"]
|
||||
layout_mode = 0
|
||||
offset_left = 210.0
|
||||
offset_top = 15.0
|
||||
offset_right = 573.0
|
||||
offset_bottom = 31.0
|
||||
[node name="BackgroundMusicHSlider" type="HSlider" parent="Scroll/Panel"]
|
||||
layout_mode = 2
|
||||
offset_left = 245.0
|
||||
offset_right = 574.0
|
||||
offset_bottom = 49.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 1
|
||||
|
||||
[connection signal="pressed" from="QuitButton" to="." method="_on_quit_button_pressed"]
|
||||
[node name="WeatherSystemLabel" type="Label" parent="Scroll/Panel"]
|
||||
layout_mode = 2
|
||||
offset_left = -0.249969
|
||||
offset_top = 48.75
|
||||
offset_right = 209.75
|
||||
offset_bottom = 97.75
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "关闭天气显示:"
|
||||
|
||||
[node name="WeatherSystemCheck" type="CheckButton" parent="Scroll/Panel"]
|
||||
layout_mode = 2
|
||||
offset_left = 244.75
|
||||
offset_top = 48.75
|
||||
offset_right = 288.75
|
||||
offset_bottom = 72.75
|
||||
scale = Vector2(2, 2)
|
||||
theme_override_font_sizes/font_size = 100
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="Scroll/Panel"]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_top = 97.0
|
||||
offset_right = 853.0
|
||||
offset_bottom = 154.0
|
||||
|
||||
[node name="ChangeServer" type="Label" parent="Scroll/Panel/HBox"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "切换服务器"
|
||||
|
||||
[node name="IPInput" type="LineEdit" parent="Scroll/Panel/HBox"]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 35
|
||||
placeholder_text = "请输入服务器IP地址"
|
||||
|
||||
[node name="PortInput" type="LineEdit" parent="Scroll/Panel/HBox"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 35
|
||||
placeholder_text = "端口"
|
||||
alignment = 1
|
||||
|
||||
[node name="ChangeButton" type="Button" parent="Scroll/Panel/HBox"]
|
||||
custom_minimum_size = Vector2(120, 0)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "切换"
|
||||
|
||||
[node name="SureButton" type="Button" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 647.5
|
||||
offset_top = 635.0
|
||||
offset_right = 815.5
|
||||
offset_bottom = 698.0
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "确认修改"
|
||||
|
||||
[node name="RefreshButton" type="Button" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 27.5001
|
||||
offset_top = 25.0001
|
||||
offset_right = 195.5
|
||||
offset_bottom = 88.0001
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "刷新"
|
||||
|
||||
@@ -2,7 +2,7 @@ extends Control
|
||||
#各种面板
|
||||
@onready var game_about_panel: Panel = $GameAboutPanel
|
||||
@onready var game_update_panel: Panel = $GameUpdatePanel
|
||||
@onready var game_setting_panel: Panel = $GameSettingPanel
|
||||
#@onready var game_setting_panel: Panel = $GameSettingPanel
|
||||
|
||||
@onready var game_version_label: Label = $GUI/GameVersionLabel
|
||||
|
||||
@@ -23,7 +23,7 @@ func _on_start_game_button_pressed() -> void:
|
||||
|
||||
#游戏设置
|
||||
func _on_game_setting_button_pressed() -> void:
|
||||
game_setting_panel.show()
|
||||
#game_setting_panel.show()
|
||||
pass
|
||||
|
||||
#游戏更新
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=12 format=3 uid="uid://bypjb28h4ntdr"]
|
||||
[gd_scene load_steps=11 format=3 uid="uid://bypjb28h4ntdr"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://badqjgdfhg7vt" path="res://GUI/MainMenuPanel.gd" id="1_wpehy"]
|
||||
[ext_resource type="Texture2D" uid="uid://ddcmrh50o1y0q" path="res://assets/菜单UI/背景1.webp" id="2_eghpk"]
|
||||
@@ -7,7 +7,6 @@
|
||||
[ext_resource type="Texture2D" uid="uid://dgdootc5bny5q" path="res://assets/菜单UI/QQ群.webp" id="4_eghpk"]
|
||||
[ext_resource type="Script" uid="uid://kj7v1uxk2i6h" path="res://GUI/GameUpdatePanel.gd" id="4_fys16"]
|
||||
[ext_resource type="Texture2D" uid="uid://ccav04woielxa" path="res://assets/菜单UI/柚小青装饰品.webp" id="5_6jmhb"]
|
||||
[ext_resource type="PackedScene" uid="uid://dos15dmc1b6bt" path="res://GUI/GameSettingPanel.tscn" id="6_eghpk"]
|
||||
[ext_resource type="Script" uid="uid://ciwjx67wjubdy" path="res://GUI/CheckUpdatePanel.gd" id="9_6jmhb"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_eghpk"]
|
||||
@@ -129,6 +128,7 @@ theme_override_font_sizes/font_size = 40
|
||||
text = "开始游戏"
|
||||
|
||||
[node name="GameSettingButton" type="Button" parent="VBox"]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(168, 63)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
@@ -140,7 +140,7 @@ custom_minimum_size = Vector2(168, 63)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "游戏更新"
|
||||
text = "更新"
|
||||
|
||||
[node name="GameAboutButton" type="Button" parent="VBox"]
|
||||
custom_minimum_size = Vector2(168, 63)
|
||||
@@ -156,14 +156,6 @@ size_flags_horizontal = 4
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "退出游戏"
|
||||
|
||||
[node name="GameSettingPanel" parent="." instance=ExtResource("6_eghpk")]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_left = 138.0
|
||||
offset_top = 80.0
|
||||
offset_right = 1536.0
|
||||
offset_bottom = 800.0
|
||||
|
||||
[node name="GameAboutPanel" type="Panel" parent="."]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
|
||||
59
GameManager/DayNightSystem.gd
Normal file
59
GameManager/DayNightSystem.gd
Normal file
@@ -0,0 +1,59 @@
|
||||
extends Node2D
|
||||
#昼夜循环系统
|
||||
#时间直接获取现实世界时间
|
||||
#内容就是直接调节背景图片modulate的亮度HEX 白天最亮为c3c3c3 晚上最暗为131313 然后在这之间变化
|
||||
|
||||
# 背景节点引用
|
||||
@onready var background_node=$'../BackgroundUI/BackgroundSwitcher'
|
||||
|
||||
# 白天和夜晚的颜色值
|
||||
var day_color = Color("#c3c3c3")
|
||||
var night_color = Color("#131313")
|
||||
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if background_node == null:
|
||||
return
|
||||
|
||||
# 获取当前时间
|
||||
var current_time = Time.get_datetime_dict_from_system()
|
||||
var hour = current_time.hour
|
||||
var minute = current_time.minute
|
||||
|
||||
# 将时间转换为小数形式(0-24)
|
||||
var time_decimal = hour + minute / 60.0
|
||||
|
||||
# 计算亮度插值因子
|
||||
var brightness_factor = calculate_brightness_factor(time_decimal)
|
||||
|
||||
# 在白天和夜晚颜色之间插值
|
||||
var current_color = night_color.lerp(day_color, brightness_factor)
|
||||
|
||||
# 应用到背景节点
|
||||
background_node.modulate = current_color
|
||||
|
||||
# 计算亮度因子(0为夜晚,1为白天)
|
||||
func calculate_brightness_factor(time: float) -> float:
|
||||
# 定义关键时间点
|
||||
var sunrise = 6.0 # 日出时间 6:00
|
||||
var noon = 12.0 # 正午时间 12:00
|
||||
var sunset = 18.0 # 日落时间 18:00
|
||||
var midnight = 0.0 # 午夜时间 0:00
|
||||
|
||||
if time >= sunrise and time <= noon:
|
||||
# 日出到正午:从0.2逐渐变亮到1.0
|
||||
return 0.2 + 0.8 * (time - sunrise) / (noon - sunrise)
|
||||
elif time > noon and time <= sunset:
|
||||
# 正午到日落:从1.0逐渐变暗到0.2
|
||||
return 1.0 - 0.8 * (time - noon) / (sunset - noon)
|
||||
else:
|
||||
# 夜晚时间:保持较暗状态(0.0-0.2之间)
|
||||
if time > sunset:
|
||||
# 日落后到午夜
|
||||
var night_progress = (time - sunset) / (24.0 - sunset)
|
||||
return 0.2 - 0.2 * night_progress
|
||||
else:
|
||||
# 午夜到日出
|
||||
var dawn_progress = time / sunrise
|
||||
return 0.0 + 0.2 * dawn_progress
|
||||
1
GameManager/DayNightSystem.gd.uid
Normal file
1
GameManager/DayNightSystem.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://di8wjflimodb0
|
||||
@@ -9,8 +9,16 @@ extends Node2D
|
||||
# 天气系统
|
||||
# 要显示哪种天气直接调用相应天气的show()然后一并隐藏其他天气hide()
|
||||
|
||||
# 动态天气显示控制(可以覆盖全局设置)
|
||||
var weather_display_enabled: bool = true
|
||||
|
||||
# 设置天气的统一方法
|
||||
func set_weather(weather_type: String):
|
||||
# 检查全局设置和动态设置
|
||||
if GlobalVariables.DisableWeatherDisplay or not weather_display_enabled:
|
||||
hide_all_weather()
|
||||
return
|
||||
|
||||
# 先隐藏所有天气效果
|
||||
hide_all_weather()
|
||||
|
||||
@@ -37,6 +45,19 @@ func set_weather(weather_type: String):
|
||||
_:
|
||||
print("未知的天气类型: ", weather_type)
|
||||
|
||||
# 动态设置天气显示状态
|
||||
func set_weather_display_enabled(enabled: bool):
|
||||
"""动态设置天气显示是否启用"""
|
||||
weather_display_enabled = enabled
|
||||
if not enabled:
|
||||
hide_all_weather()
|
||||
print("天气显示已", "启用" if enabled else "禁用")
|
||||
|
||||
# 获取当前天气显示状态
|
||||
func is_weather_display_enabled() -> bool:
|
||||
"""获取当前天气显示状态"""
|
||||
return weather_display_enabled and not GlobalVariables.DisableWeatherDisplay
|
||||
|
||||
# 隐藏所有天气效果
|
||||
func hide_all_weather():
|
||||
if cherry_blossom_rain:
|
||||
|
||||
@@ -12,3 +12,6 @@ const server_configs = [
|
||||
#{"host": "47.108.90.0", "port": 4040, "name": "成都内网穿透"}#成都内网穿透
|
||||
#{"host": "47.108.90.0", "port": 6060, "name": "成都公网"}#成都服务器
|
||||
]
|
||||
|
||||
const DisableWeatherDisplay :bool = false #是否禁止显示天气
|
||||
const BackgroundMusicVolume = 1.0 #背景音乐音量
|
||||
|
||||
36
MainGame.gd
36
MainGame.gd
@@ -68,6 +68,7 @@ extends Node
|
||||
@onready var pet_fight_panel: Panel = $UI/BigPanel/PetFightPanel #宠物战斗面板
|
||||
@onready var pet_inform_panel: Panel = $UI/SmallPanel/PetInformPanel #宠物信息面板
|
||||
@onready var player_store_panel: Panel = $UI/BigPanel/PlayerStorePanel #玩家小卖部面板
|
||||
@onready var game_setting_panel: Panel = $UI/BigPanel/GameSettingPanel #游戏设置面板
|
||||
|
||||
|
||||
#小面板
|
||||
@@ -225,6 +226,7 @@ func _ready():
|
||||
one_click_plant_panel.hide()
|
||||
account_setting_panel.hide()
|
||||
global_server_broadcast_panel.hide()
|
||||
game_setting_panel.hide()
|
||||
accept_dialog.hide()
|
||||
|
||||
|
||||
@@ -865,9 +867,9 @@ func _on_player_ranking_button_pressed() -> void:
|
||||
pass
|
||||
|
||||
|
||||
#打开设置面板 暂时没想到可以设置什么
|
||||
#打开设置面板
|
||||
func _on_setting_button_pressed() -> void:
|
||||
pass
|
||||
game_setting_panel.show()
|
||||
|
||||
#查看全服大喇叭按钮点击事件
|
||||
func _on_watch_broadcast_button_pressed() -> void:
|
||||
@@ -1711,14 +1713,6 @@ func _wait_for_crop_data() -> void:
|
||||
|
||||
|
||||
|
||||
#===============================================调试和维护工具===============================================
|
||||
|
||||
|
||||
|
||||
#===============================================调试和维护工具===============================================
|
||||
|
||||
|
||||
|
||||
#===============================================向后兼容性===============================================
|
||||
# 为了保持向后兼容,保留一些原来的函数名
|
||||
func _load_crop_textures(crop_name: String) -> Array:
|
||||
@@ -3320,13 +3314,33 @@ func _handle_weather_change(weather_type: String, weather_name: String):
|
||||
"""处理服务器发送的天气变更消息"""
|
||||
if weather_system and weather_system.has_method("set_weather"):
|
||||
weather_system.set_weather(weather_type)
|
||||
Toast.show("天气已变更为:" + weather_name, Color.CYAN, 3.0)
|
||||
print("天气已切换为:", weather_name)
|
||||
else:
|
||||
print("天气系统不可用")
|
||||
# ======================================= 天气系统 =========================================
|
||||
|
||||
|
||||
# ======================================= 游戏设置系统 =========================================
|
||||
# 处理游戏设置保存响应
|
||||
func _handle_save_game_settings_response(data):
|
||||
"""处理服务器返回的游戏设置保存响应"""
|
||||
var success = data.get("success", false)
|
||||
var message = data.get("message", "")
|
||||
var settings = data.get("settings", {})
|
||||
|
||||
if success:
|
||||
# 设置保存成功,更新本地设置面板
|
||||
if game_setting_panel and game_setting_panel.has_method("apply_settings_from_server"):
|
||||
game_setting_panel.apply_settings_from_server(settings)
|
||||
|
||||
Toast.show("游戏设置保存成功", Color.GREEN)
|
||||
print("游戏设置保存成功: ", settings)
|
||||
else:
|
||||
Toast.show("游戏设置保存失败: " + message, Color.RED)
|
||||
print("游戏设置保存失败: ", message)
|
||||
# ======================================= 游戏设置系统 =========================================
|
||||
|
||||
|
||||
#打开小卖部面板
|
||||
func _on_my_store_button_pressed() -> void:
|
||||
player_store_panel.show()
|
||||
|
||||
1326
MainGame.tscn
1326
MainGame.tscn
File diff suppressed because it is too large
Load Diff
@@ -602,6 +602,10 @@ func _on_data_received(data):
|
||||
var weather_type = data.get("weather_type", "clear")
|
||||
var weather_name = data.get("weather_name", "晴天")
|
||||
main_game._handle_weather_change(weather_type, weather_name)
|
||||
|
||||
# 游戏设置响应
|
||||
elif message_type == "save_game_settings_response":
|
||||
main_game._handle_save_game_settings_response(data)
|
||||
# ============================= 客户端与服务端通信核心 =====================================
|
||||
|
||||
|
||||
|
||||
@@ -521,6 +521,10 @@ func _on_login_response_received(success: bool, message: String, user_data: Dict
|
||||
|
||||
# 调用主游戏的登录成功处理函数
|
||||
main_game.handle_login_success(user_data)
|
||||
|
||||
# 初始化游戏设置
|
||||
if main_game.game_setting_panel and main_game.game_setting_panel.has_method("refresh_settings"):
|
||||
main_game.game_setting_panel.refresh_settings()
|
||||
else:
|
||||
status_label.text = "登录失败:" + message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
170
Server/MongoDB迁移说明.md
Normal file
170
Server/MongoDB迁移说明.md
Normal 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
705
Server/SMYMongoDBAPI.py
Normal 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()
|
||||
@@ -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)
|
||||
is_weed = crop_info.get("是否杂草", False)
|
||||
if is_weed:
|
||||
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。")
|
||||
|
||||
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)
|
||||
|
||||
# 额外检查:如果作物收益为负数,也视为杂草
|
||||
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
|
||||
# 获取作物经验
|
||||
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)
|
||||
is_weed = crop_info.get("是否杂草", False)
|
||||
if is_weed:
|
||||
return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。")
|
||||
|
||||
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 = 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
|
||||
# 获取作物经验(偷菜获得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,17 +1903,66 @@ 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']}"
|
||||
|
||||
@@ -5418,6 +5579,7 @@ class TCPGameServer(TCPServer):
|
||||
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,))
|
||||
|
||||
BIN
Server/__pycache__/SMYMongoDBAPI.cpython-313.pyc
Normal file
BIN
Server/__pycache__/SMYMongoDBAPI.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
178
Server/test_mongodb_migration.py
Normal file
178
Server/test_mongodb_migration.py
Normal 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)
|
||||
106
Server/test_server_mongodb.py
Normal file
106
Server/test_server_mongodb.py
Normal 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)
|
||||
BIN
__pycache__/SMYMongoDBAPI.cpython-313.pyc
Normal file
BIN
__pycache__/SMYMongoDBAPI.cpython-313.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
extends Sprite2D
|
||||
|
||||
#昼夜循环只需调节该节点的modulate值即可
|
||||
# 存储背景图片的路径数组
|
||||
var backgrounds :Array = [
|
||||
"res://assets/背景图片/背景1.webp",
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
{
|
||||
"farm_lots": [
|
||||
{
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"crop_type": "小麦",
|
||||
"grow_time": 300,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 10200,
|
||||
"is_planted": true,
|
||||
"max_grow_time": 300,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
},
|
||||
{
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"crop_type": "小麦",
|
||||
"grow_time": 300,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 7200,
|
||||
"is_planted": true,
|
||||
"max_grow_time": 300,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
},
|
||||
{
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"crop_type": "小麦",
|
||||
"grow_time": 300,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 14400,
|
||||
"is_planted": true,
|
||||
"max_grow_time": 300,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
},
|
||||
{
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"crop_type": "小麦",
|
||||
"grow_time": 300,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 7200,
|
||||
"is_planted": true,
|
||||
"max_grow_time": 300,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
@@ -53,7 +53,7 @@
|
||||
"max_grow_time": 2940,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 0
|
||||
"土地等级": 1
|
||||
},
|
||||
{
|
||||
"crop_type": "",
|
||||
@@ -64,7 +64,7 @@
|
||||
"max_grow_time": 1080,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 0
|
||||
"土地等级": 2
|
||||
},
|
||||
{
|
||||
"crop_type": "",
|
||||
@@ -75,7 +75,7 @@
|
||||
"max_grow_time": 1080,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 0
|
||||
"土地等级": 3
|
||||
},
|
||||
{
|
||||
"crop_type": "龙果",
|
||||
@@ -111,44 +111,44 @@
|
||||
"土地等级": 0
|
||||
},
|
||||
{
|
||||
"crop_type": "土豆",
|
||||
"grow_time": 480,
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 480,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
},
|
||||
{
|
||||
"crop_type": "胡萝卜",
|
||||
"grow_time": 240,
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 240,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
},
|
||||
{
|
||||
"crop_type": "土豆",
|
||||
"grow_time": 540,
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 480,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
"土地等级": 4
|
||||
},
|
||||
{
|
||||
"crop_type": "小麦",
|
||||
"grow_time": 300,
|
||||
"crop_type": "",
|
||||
"grow_time": 0,
|
||||
"is_dead": false,
|
||||
"is_diged": true,
|
||||
"is_planted": true,
|
||||
"is_planted": false,
|
||||
"max_grow_time": 300,
|
||||
"已浇水": false,
|
||||
"已施肥": false,
|
||||
@@ -555,7 +555,7 @@
|
||||
{
|
||||
"name": "小麦",
|
||||
"quality": "普通",
|
||||
"count": 8
|
||||
"count": 4
|
||||
},
|
||||
{
|
||||
"name": "胡萝卜",
|
||||
@@ -566,15 +566,20 @@
|
||||
"name": "土豆",
|
||||
"quality": "普通",
|
||||
"count": 6
|
||||
},
|
||||
{
|
||||
"name": "杂交树2",
|
||||
"quality": "传奇",
|
||||
"count": 8
|
||||
}
|
||||
],
|
||||
"experience": 5164,
|
||||
"experience": 573,
|
||||
"farm_name": "树萌芽の狗窝",
|
||||
"player_name": "树萌芽",
|
||||
"level": 63,
|
||||
"money": 615197045864,
|
||||
"last_login_time": "2025年07月19日15时31分10秒",
|
||||
"total_login_time": "162时4分9秒",
|
||||
"level": 64,
|
||||
"money": 615197019864,
|
||||
"last_login_time": "2025年07月19日21时52分29秒",
|
||||
"total_login_time": "162时47分40秒",
|
||||
"user_name": "3205788256",
|
||||
"user_password": "tyh@19900420",
|
||||
"last_water_reset_date": "2025-06-06",
|
||||
@@ -631,7 +636,7 @@
|
||||
{
|
||||
"name": "小麦",
|
||||
"quality": "普通",
|
||||
"count": 15
|
||||
"count": 16
|
||||
},
|
||||
{
|
||||
"name": "山葵",
|
||||
@@ -681,12 +686,17 @@
|
||||
{
|
||||
"name": "胡萝卜",
|
||||
"quality": "普通",
|
||||
"count": 1
|
||||
"count": 5
|
||||
},
|
||||
{
|
||||
"name": "土豆",
|
||||
"quality": "普通",
|
||||
"count": 3
|
||||
},
|
||||
{
|
||||
"name": "马铃薯",
|
||||
"quality": "普通",
|
||||
"count": 7
|
||||
}
|
||||
],
|
||||
"道具背包": [
|
||||
@@ -696,7 +706,7 @@
|
||||
},
|
||||
{
|
||||
"name": "生长素",
|
||||
"count": 1001
|
||||
"count": 1000
|
||||
},
|
||||
{
|
||||
"name": "时运-镰刀",
|
||||
@@ -844,10 +854,10 @@
|
||||
"爱好": ""
|
||||
},
|
||||
"等级经验": {
|
||||
"宠物等级": 3,
|
||||
"当前经验": 40.0,
|
||||
"最大经验": 144.0,
|
||||
"亲密度": 136.0,
|
||||
"宠物等级": 4,
|
||||
"当前经验": 26.0,
|
||||
"最大经验": 172.8,
|
||||
"亲密度": 204.0,
|
||||
"最大亲密度": 1000.0
|
||||
},
|
||||
"购买信息": {
|
||||
@@ -856,18 +866,18 @@
|
||||
"出售价格": 500
|
||||
},
|
||||
"生命与防御": {
|
||||
"最大生命值": 242.00000000000006,
|
||||
"当前生命值": 242.00000000000006,
|
||||
"最大生命值": 266.2000000000001,
|
||||
"当前生命值": 266.2000000000001,
|
||||
"生命恢复速度": 1.0,
|
||||
"最大护盾值": 0.0,
|
||||
"当前护盾值": 0.0,
|
||||
"护盾恢复速度": 0.0,
|
||||
"最大护甲值": 121.00000000000003,
|
||||
"当前护甲值": 121.00000000000003
|
||||
"最大护甲值": 133.10000000000005,
|
||||
"当前护甲值": 133.10000000000005
|
||||
},
|
||||
"基础攻击属性": {
|
||||
"攻击类型": "MELEE",
|
||||
"基础攻击伤害": 30.250000000000007,
|
||||
"基础攻击伤害": 33.27500000000001,
|
||||
"攻击距离": 100.0,
|
||||
"暴击率": 0.1,
|
||||
"暴击伤害倍数": 1.5,
|
||||
@@ -1122,5 +1132,9 @@
|
||||
"商品数量": 1
|
||||
}
|
||||
],
|
||||
"小卖部格子数": 10
|
||||
"小卖部格子数": 10,
|
||||
"游戏设置": {
|
||||
"背景音乐音量": 0.0,
|
||||
"天气显示": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user