From ec94e10fdaa86fe316ce8f7e2f86ca1908031eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A0=91=E8=90=8C=E8=8A=BD?= <3205788256@qq.com> Date: Sun, 20 Jul 2025 21:05:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=83=A8=E5=88=86=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E6=95=B0=E6=8D=AE=E5=90=91MongoDB=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/GameBGMPlayer.gd | 78 +- Components/GameBGMPlayer2.gd | 131 -- Components/GameBGMPlayer2.gd.uid | 1 - CopyItems/crop_item.tscn | 6 - GUI/GameSettingPanel.gd | 198 ++- GUI/GameSettingPanel.tscn | 94 +- GUI/MainMenuPanel.gd | 4 +- GUI/MainMenuPanel.tscn | 14 +- GameManager/DayNightSystem.gd | 59 + GameManager/DayNightSystem.gd.uid | 1 + GameManager/WeatherSystem.gd | 21 + GlobalScript/GlobalVariables.gd | 3 + MainGame.gd | 36 +- MainGame.tscn | 1326 +---------------- Network/TCPNetworkManager.gd | 4 + Script/BigPanel/LoginPanel.gd | 4 + Server/MongoDB迁移说明.md | 170 +++ Server/SMYMongoDBAPI.py | 705 +++++++++ Server/TCPGameServer.py | 624 ++++++-- .../__pycache__/SMYMongoDBAPI.cpython-313.pyc | Bin 0 -> 24880 bytes .../__pycache__/TCPGameServer.cpython-313.pyc | Bin 49870 -> 350744 bytes .../config/initial_player_data_template.json | 141 +- Server/game_saves/2143323382.json | 151 +- Server/test_mongodb_migration.py | 178 +++ Server/test_server_mongodb.py | 106 ++ __pycache__/SMYMongoDBAPI.cpython-313.pyc | Bin 0 -> 14409 bytes background.gd | 2 +- server/game_saves/3205788256.json | 114 +- 28 files changed, 2386 insertions(+), 1785 deletions(-) delete mode 100644 Components/GameBGMPlayer2.gd delete mode 100644 Components/GameBGMPlayer2.gd.uid create mode 100644 GameManager/DayNightSystem.gd create mode 100644 GameManager/DayNightSystem.gd.uid create mode 100644 Server/MongoDB迁移说明.md create mode 100644 Server/SMYMongoDBAPI.py create mode 100644 Server/__pycache__/SMYMongoDBAPI.cpython-313.pyc create mode 100644 Server/test_mongodb_migration.py create mode 100644 Server/test_server_mongodb.py create mode 100644 __pycache__/SMYMongoDBAPI.cpython-313.pyc diff --git a/Components/GameBGMPlayer.gd b/Components/GameBGMPlayer.gd index 2f763c6..c01f5c1 100644 --- a/Components/GameBGMPlayer.gd +++ b/Components/GameBGMPlayer.gd @@ -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() @@ -163,4 +172,71 @@ func add_music_file(file_path: String) -> bool: return true else: print("音乐文件不存在: ", file_path) - return false + 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 diff --git a/Components/GameBGMPlayer2.gd b/Components/GameBGMPlayer2.gd deleted file mode 100644 index d6341e5..0000000 --- a/Components/GameBGMPlayer2.gd +++ /dev/null @@ -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 "" diff --git a/Components/GameBGMPlayer2.gd.uid b/Components/GameBGMPlayer2.gd.uid deleted file mode 100644 index b511fa3..0000000 --- a/Components/GameBGMPlayer2.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cq0ug1c7nibf1 diff --git a/CopyItems/crop_item.tscn b/CopyItems/crop_item.tscn index 06dc577..dcab7c4 100644 --- a/CopyItems/crop_item.tscn +++ b/CopyItems/crop_item.tscn @@ -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") diff --git a/GUI/GameSettingPanel.gd b/GUI/GameSettingPanel.gd index 2628b13..672424a 100644 --- a/GUI/GameSettingPanel.gd +++ b/GUI/GameSettingPanel.gd @@ -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("已应用来自服务端的游戏设置") diff --git a/GUI/GameSettingPanel.tscn b/GUI/GameSettingPanel.tscn index 67e361b..61883ed 100644 --- a/GUI/GameSettingPanel.tscn +++ b/GUI/GameSettingPanel.tscn @@ -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 = "刷新" diff --git a/GUI/MainMenuPanel.gd b/GUI/MainMenuPanel.gd index 484a6ad..d5eab75 100644 --- a/GUI/MainMenuPanel.gd +++ b/GUI/MainMenuPanel.gd @@ -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 #游戏更新 diff --git a/GUI/MainMenuPanel.tscn b/GUI/MainMenuPanel.tscn index 8da9e46..27afb16 100644 --- a/GUI/MainMenuPanel.tscn +++ b/GUI/MainMenuPanel.tscn @@ -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 diff --git a/GameManager/DayNightSystem.gd b/GameManager/DayNightSystem.gd new file mode 100644 index 0000000..109e9c4 --- /dev/null +++ b/GameManager/DayNightSystem.gd @@ -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 diff --git a/GameManager/DayNightSystem.gd.uid b/GameManager/DayNightSystem.gd.uid new file mode 100644 index 0000000..34142fd --- /dev/null +++ b/GameManager/DayNightSystem.gd.uid @@ -0,0 +1 @@ +uid://di8wjflimodb0 diff --git a/GameManager/WeatherSystem.gd b/GameManager/WeatherSystem.gd index 138f18e..dd3f5fa 100644 --- a/GameManager/WeatherSystem.gd +++ b/GameManager/WeatherSystem.gd @@ -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: diff --git a/GlobalScript/GlobalVariables.gd b/GlobalScript/GlobalVariables.gd index 4800ec3..55aceef 100644 --- a/GlobalScript/GlobalVariables.gd +++ b/GlobalScript/GlobalVariables.gd @@ -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 #背景音乐音量 diff --git a/MainGame.gd b/MainGame.gd index c363721..8296125 100644 --- a/MainGame.gd +++ b/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() diff --git a/MainGame.tscn b/MainGame.tscn index ab5478b..385fc98 100644 --- a/MainGame.tscn +++ b/MainGame.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=96 format=3 uid="uid://dgh61dttaas5a"] +[gd_scene load_steps=97 format=3 uid="uid://dgh61dttaas5a"] [ext_resource type="Script" uid="uid://2pt11sfcaxf7" path="res://MainGame.gd" id="1_v3yaj"] [ext_resource type="Texture2D" uid="uid://du2pyiojliasy" path="res://assets/游戏UI/经验球.webp" id="2_6jgly"] @@ -39,6 +39,7 @@ [ext_resource type="Script" uid="uid://bvhupqlw2h1j8" path="res://Script/SmallPanel/DebugPanel.gd" id="28_8kysg"] [ext_resource type="Script" uid="uid://ca2chgx5w3g1y" path="res://Components/GameBGMPlayer.gd" id="28_m6fch"] [ext_resource type="Script" uid="uid://d4fvv2sjngajr" path="res://Script/Dialog/BatchBuyPopup.gd" id="29_5b81d"] +[ext_resource type="PackedScene" uid="uid://dos15dmc1b6bt" path="res://GUI/GameSettingPanel.tscn" id="30_game_setting"] [ext_resource type="Texture2D" uid="uid://2sdfbvf1isif" path="res://icon.svg" id="31_uc6q1"] [ext_resource type="Script" uid="uid://doo34ll0yb078" path="res://Script/SmallPanel/PetInformPanel.gd" id="31_vygm6"] [ext_resource type="Script" uid="uid://bakeq8tm6r4j4" path="res://Script/SmallPanel/GlobalServerBroadcastPanel.gd" id="34_k1sw4"] @@ -47,7 +48,6 @@ [ext_resource type="Texture2D" uid="uid://cbe0f8ex17csy" path="res://assets/稻草人图片/稻草人3.webp" id="37_6ylhg"] [ext_resource type="PackedScene" uid="uid://ibl5wbbw3pwc" path="res://CopyItems/item_button.tscn" id="39_cdkxt"] [ext_resource type="Script" uid="uid://dwf28j01ckg3y" path="res://Script/SmallPanel/WisdomTreePanel.gd" id="39_np7ck"] -[ext_resource type="Texture2D" uid="uid://bt1i2yhhlor5e" path="res://assets/地块/土块1.webp" id="41_cdkxt"] [ext_resource type="Script" uid="uid://b185o1hjnlrv5" path="res://Script/SmallPanel/CropInformPanel.gd" id="41_iluto"] [ext_resource type="Texture2D" uid="uid://3ff2lnbc0op7" path="res://assets/稻草人图片/稻草人1.webp" id="43_6rkns"] [ext_resource type="Script" uid="uid://dsmmxivba06ab" path="res://Script/Dialog/BatchSellPopup.gd" id="44_av1bx"] @@ -72,6 +72,7 @@ [ext_resource type="Texture2D" uid="uid://deow5dqdm412v" path="res://assets/装饰物图片/宠物商店.webp" id="57_rlmnt"] [ext_resource type="Script" uid="uid://o4mcuqoivqri" path="res://GameManager/WeatherSystem.gd" id="62_uyv6e"] [ext_resource type="Texture2D" uid="uid://bnv6wb0k443fv" path="res://assets/天气系统图片/柳叶2.webp" id="69_uyv6e"] +[ext_resource type="Script" uid="uid://di8wjflimodb0" path="res://GameManager/DayNightSystem.gd" id="73_6fhdl"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_adtqp"] @@ -145,16 +146,6 @@ border_width_top = 15 border_width_right = 15 border_width_bottom = 15 -[sub_resource type="Environment" id="Environment_m6fch"] -background_mode = 3 -ambient_light_energy = 0.0 -glow_intensity = 1.0 -glow_bloom = 0.3 -glow_blend_mode = 0 -glow_hdr_threshold = 2.0 -volumetric_fog_emission_energy = 281.25 -volumetric_fog_gi_inject = 1.38 - [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6ylhg"] border_width_left = 10 border_width_top = 10 @@ -272,6 +263,15 @@ turbulence_noise_speed = Vector3(10, 0, 0) turbulence_influence_min = 0.02 turbulence_influence_max = 0.07 +[sub_resource type="Environment" id="Environment_uyv6e"] +background_mode = 3 +glow_enabled = true +glow_intensity = 1.0 +glow_strength = 0.75 +glow_bloom = 1.0 +glow_blend_mode = 1 +fog_enabled = true + [node name="main" type="Node"] script = ExtResource("1_v3yaj") @@ -678,7 +678,6 @@ theme_override_font_sizes/font_size = 40 text = "游玩小游戏" [node name="SettingButton" type="Button" parent="UI/GUI/OtherVBox"] -visible = false modulate = Color(0.345098, 0.764706, 1, 1) layout_mode = 2 theme_override_font_sizes/font_size = 40 @@ -912,6 +911,9 @@ visible = false [node name="LoginPanel" parent="UI/BigPanel" instance=ExtResource("11_6jgly")] +[node name="GameSettingPanel" parent="UI/BigPanel" instance=ExtResource("30_game_setting")] +visible = false + [node name="SmallPanel" type="CanvasLayer" parent="UI"] [node name="LoadProgressPanel" parent="UI/SmallPanel" instance=ExtResource("27_vygm6")] @@ -1866,7 +1868,6 @@ text = "取消" layer = -1 [node name="BackgroundSwitcher" type="Sprite2D" parent="BackgroundUI"] -self_modulate = Color(0.5, 0.5, 0.5, 1) show_behind_parent = true z_index = -100 z_as_relative = false @@ -1875,7 +1876,6 @@ scale = Vector2(0.92, 0.92) script = ExtResource("17_0igvr") [node name="Background2" type="Sprite2D" parent="BackgroundUI/BackgroundSwitcher"] -self_modulate = Color(0.5, 0.5, 0.5, 1) [node name="Timer" type="Timer" parent="BackgroundUI/BackgroundSwitcher"] @@ -1998,9 +1998,6 @@ bounds_enabled = true bounds_min = Vector2(-500, -400) bounds_max = Vector2(500, 500) -[node name="WorldEnvironment" type="WorldEnvironment" parent="."] -environment = SubResource("Environment_m6fch") - [node name="GameManager" type="Node" parent="."] [node name="GameBGMPlayer" type="Node" parent="."] @@ -2008,1292 +2005,6 @@ script = ExtResource("28_m6fch") play_mode = 1 music_files_list = Array[String](["res://assets/音乐/Anibli&RelaxingPianoMusic-StrollThroughtheSky.ogg", "res://assets/音乐/BanAM-Futatabi.ogg", "res://assets/音乐/MCMZebra-AlwaysandManyTimes.ogg", "res://assets/音乐/MicMusicbox-Ashitakasekki.ogg", "res://assets/音乐/Nemuネム-PromiseoftheWorld.ogg", "res://assets/音乐/α-WaveRelaxationHealingMusicLab-いつも何度でも[「千と千尋の神隠し」より][ピアノ].ogg", "res://assets/音乐/久石让-ふたたび.ogg", "res://assets/音乐/广桥真纪子-いのちの名前(生命之名).ogg", "res://assets/音乐/日本群星-PromiseoftheWorld.ogg"]) -[node name="GroundBackground" type="Node2D" parent="."] -visible = false -modulate = Color(0.929412, 1, 0.431373, 1) -position = Vector2(3786, -1016) -scale = Vector2(1.5, 1.5) - -[node name="土块1" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2203, 576) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块2" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2165, 598) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块3" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2240, 598) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块4" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2202, 620) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块5" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2127, 621) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块6" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2089, 643) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块7" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2164, 643) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块8" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2126, 665) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块9" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2278, 621) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块10" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2240, 643) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块11" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2315, 643) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块12" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2277, 665) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块13" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2202, 666) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块14" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2164, 688) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块15" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 688) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块16" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2201, 710) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块17" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2052, 666) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块18" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2014, 688) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块19" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2089, 688) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块20" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2051, 710) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块21" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1976, 711) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块22" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1938, 733) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块23" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2013, 733) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块24" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1975, 755) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块25" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2127, 711) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块26" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2089, 733) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块27" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2164, 733) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块28" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2126, 755) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块29" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2051, 756) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块30" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2013, 778) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块31" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2088, 778) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块32" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2050, 800) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块33" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2353, 667) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块34" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2315, 689) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块35" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2390, 689) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块36" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2352, 711) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块37" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2277, 712) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块38" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 734) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块39" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 734) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块40" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2276, 756) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块41" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2428, 712) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块42" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2390, 734) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块43" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2465, 734) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块44" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2427, 756) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块45" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2352, 757) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块46" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 779) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块47" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2389, 779) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块48" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2351, 801) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块49" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2202, 757) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块50" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2164, 779) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块51" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 779) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块52" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2201, 801) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块53" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2126, 802) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块54" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2088, 824) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块55" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2163, 824) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块56" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2125, 846) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块57" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2277, 802) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块58" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 824) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块59" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 824) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块60" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2276, 846) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块61" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2201, 847) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块62" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2163, 869) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块63" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2238, 869) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块64" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2200, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块65" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1900, 756) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块66" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1862, 778) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块67" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1937, 778) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块68" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1899, 800) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块69" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1824, 801) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块70" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1786, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块71" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1861, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块72" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1823, 845) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块73" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1975, 801) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块74" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1937, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块75" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2012, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块76" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1974, 845) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块77" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1899, 846) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块78" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1861, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块79" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1936, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块80" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1898, 890) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块81" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1749, 846) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块82" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1711, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块83" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1786, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块84" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1748, 890) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块85" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1673, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块86" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1635, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块87" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1710, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块88" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1672, 935) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块89" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1824, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块90" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1786, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块91" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1861, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块92" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1823, 935) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块93" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1748, 936) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块94" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1710, 958) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块95" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1785, 958) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块96" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1747, 980) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块97" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2050, 847) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块98" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2012, 869) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块99" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2087, 869) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块100" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2049, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块101" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1974, 892) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块102" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1936, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块103" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2011, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块104" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1973, 936) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块105" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2125, 892) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块106" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2087, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块107" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2162, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块108" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2124, 936) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块109" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2049, 937) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块110" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2011, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块111" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2086, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块112" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2048, 981) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块113" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1899, 937) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块114" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1861, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块115" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1936, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块116" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1898, 981) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块117" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1823, 982) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块118" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1785, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块119" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1860, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块120" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1822, 1026) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块121" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1974, 982) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块122" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1936, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块123" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2011, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块124" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1973, 1026) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块125" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1898, 1027) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块126" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1860, 1049) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块127" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1935, 1049) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块128" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1897, 1071) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块129" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2504, 756) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块130" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2466, 778) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块131" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2541, 778) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块132" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2503, 800) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块133" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2428, 801) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块134" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2390, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块135" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2465, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块136" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2427, 845) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块137" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2579, 801) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块138" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2541, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块139" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2616, 823) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块140" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2578, 845) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块141" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2503, 846) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块142" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2465, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块143" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2540, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块144" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2502, 890) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块145" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2353, 846) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块146" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2315, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块147" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2390, 868) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块148" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2352, 890) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块149" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2277, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块150" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块151" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块152" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2276, 935) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块153" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2428, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块154" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2390, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块155" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2465, 913) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块156" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2427, 935) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块157" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2352, 936) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块158" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 958) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块159" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2389, 958) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块160" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2351, 980) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块161" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2654, 847) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块162" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2616, 869) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块163" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2691, 869) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块164" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2653, 891) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块165" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2578, 892) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块166" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2540, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块167" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2615, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块168" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2577, 936) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块169" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2729, 892) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块170" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2691, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块171" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2766, 914) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块172" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2728, 936) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块173" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2653, 937) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块174" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2615, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块175" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2690, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块176" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2652, 981) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块177" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2503, 937) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块178" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2465, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块179" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2540, 959) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块180" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2502, 981) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块181" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2427, 982) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块182" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2389, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块183" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2464, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块184" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2426, 1026) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块185" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2578, 982) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块186" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2540, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块187" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2615, 1004) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块188" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2577, 1026) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块189" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2502, 1027) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块190" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2464, 1049) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块191" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2539, 1049) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块192" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2501, 1071) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块193" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2202, 935) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块194" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2164, 957) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块195" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 957) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块196" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2201, 979) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块197" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2126, 980) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块198" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2088, 1002) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块199" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2163, 1002) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块200" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2125, 1024) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块201" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2277, 980) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块202" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2239, 1002) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块203" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 1002) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块204" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2276, 1024) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块205" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2201, 1025) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块206" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2163, 1047) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块207" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2238, 1047) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块208" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2200, 1069) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块209" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2051, 1025) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块210" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2013, 1047) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块211" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2088, 1047) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块212" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2050, 1069) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块213" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1975, 1070) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块214" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1937, 1092) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块215" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2012, 1092) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块216" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-1974, 1114) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块217" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2126, 1070) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块218" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2088, 1092) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块219" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2163, 1092) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块220" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2125, 1114) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块221" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2050, 1115) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块222" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2012, 1137) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块223" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2087, 1137) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块224" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2049, 1159) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块225" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2352, 1026) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块226" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2314, 1048) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块227" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2389, 1048) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块228" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2351, 1070) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块229" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2276, 1071) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块230" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2238, 1093) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块231" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2313, 1093) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块232" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2275, 1115) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块233" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2427, 1071) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块234" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2389, 1093) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块235" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2464, 1093) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块236" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2426, 1115) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块237" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2351, 1116) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块238" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2313, 1138) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块239" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2388, 1138) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块240" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2350, 1160) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块241" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2201, 1116) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块242" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2163, 1138) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块243" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2238, 1138) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块244" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2200, 1160) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块245" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2125, 1161) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块246" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2087, 1183) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块247" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2162, 1183) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块248" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2124, 1205) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块249" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2276, 1161) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块250" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2238, 1183) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块251" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2313, 1183) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块252" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2275, 1205) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块253" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2200, 1206) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块254" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2162, 1228) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块255" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2237, 1228) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - -[node name="土块256" type="Sprite2D" parent="GroundBackground"] -position = Vector2(-2199, 1250) -scale = Vector2(0.1, 0.1) -texture = ExtResource("41_cdkxt") - [node name="Decoration" type="Node2D" parent="."] [node name="ScareCrow" type="Button" parent="Decoration"] @@ -4837,6 +3548,13 @@ visibility_rect = Rect2(-900, 0, 2300, 2000) process_material = SubResource("ParticleProcessMaterial_nf3jg") [node name="DayNightSystem" type="Node2D" parent="."] +script = ExtResource("73_6fhdl") + +[node name="CanvasModulate" type="CanvasModulate" parent="DayNightSystem"] +visible = false + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_uyv6e") [connection signal="pressed" from="UI/GUI/GameInfoHBox3/WatchBroadcast" to="." method="_on_watch_broadcast_button_pressed"] [connection signal="pressed" from="UI/GUI/FarmVBox/SeedStoreButton" to="." method="_on_open_store_button_pressed"] diff --git a/Network/TCPNetworkManager.gd b/Network/TCPNetworkManager.gd index 9a997a1..6bda69e 100644 --- a/Network/TCPNetworkManager.gd +++ b/Network/TCPNetworkManager.gd @@ -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) # ============================= 客户端与服务端通信核心 ===================================== diff --git a/Script/BigPanel/LoginPanel.gd b/Script/BigPanel/LoginPanel.gd index 64f5672..e8029ff 100644 --- a/Script/BigPanel/LoginPanel.gd +++ b/Script/BigPanel/LoginPanel.gd @@ -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 diff --git a/Server/MongoDB迁移说明.md b/Server/MongoDB迁移说明.md new file mode 100644 index 0000000..3f5e345 --- /dev/null +++ b/Server/MongoDB迁移说明.md @@ -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文件的备选方案,为后续的全面迁移奠定了坚实的基础。 \ No newline at end of file diff --git a/Server/SMYMongoDBAPI.py b/Server/SMYMongoDBAPI.py new file mode 100644 index 0000000..5e1c7c6 --- /dev/null +++ b/Server/SMYMongoDBAPI.py @@ -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() \ No newline at end of file diff --git a/Server/TCPGameServer.py b/Server/TCPGameServer.py index 49d500b..614c02d 100644 --- a/Server/TCPGameServer.py +++ b/Server/TCPGameServer.py @@ -1,4 +1,5 @@ from TCPServer import TCPServer +from SMYMongoDBAPI import SMYMongoDBAPI import time import json import os @@ -84,9 +85,17 @@ class TCPGameServer(TCPServer): # 配置文件目录 self.config_dir = "config" # 配置文件存储目录 + # 初始化MongoDB API(优先使用MongoDB,失败则使用JSON文件) + self._init_mongodb_api() + # 性能优化相关配置 self._init_performance_settings() + # 数据缓存 + self.crop_data_cache = None + self.crop_data_cache_time = 0 + self.cache_expire_duration = 300 # 缓存过期时间5分钟 + self.log('INFO', f"萌芽农场TCP游戏服务器初始化完成 - 版本: {server_version}", 'SERVER') # 启动定时器 @@ -96,6 +105,28 @@ class TCPGameServer(TCPServer): self.start_wisdom_tree_health_decay_timer() self.start_verification_code_cleanup_timer() + #初始化MongoDB API + def _init_mongodb_api(self): + """初始化MongoDB API连接""" + try: + # 根据配置决定使用测试环境还是生产环境 + # 这里默认使用测试环境,实际部署时可以修改为 "production" + environment = "test" # 或者从配置文件读取 + + self.mongo_api = SMYMongoDBAPI(environment) + if self.mongo_api.is_connected(): + self.use_mongodb = True + self.log('INFO', f"MongoDB API初始化成功 [{environment}]", 'SERVER') + else: + self.use_mongodb = False + self.mongo_api = None + self.log('WARNING', "MongoDB连接失败,将使用JSON配置文件", 'SERVER') + + except Exception as e: + self.use_mongodb = False + self.mongo_api = None + self.log('ERROR', f"MongoDB API初始化异常: {e},将使用JSON配置文件", 'SERVER') + #初始化性能操作 def _init_performance_settings(self): """初始化性能优化配置""" @@ -400,12 +431,22 @@ class TCPGameServer(TCPServer): return player_data, username, None - #加载作物配置数据 + #加载作物配置数据(优化版本) def _load_crop_data(self): - """加载作物配置数据""" + """加载作物配置数据(带缓存优化)""" + current_time = time.time() + + # 检查缓存是否有效 + if (self.crop_data_cache is not None and + current_time - self.crop_data_cache_time < self.cache_expire_duration): + return self.crop_data_cache + + # 缓存过期或不存在,重新加载 try: with open("config/crop_data.json", 'r', encoding='utf-8') as file: - return json.load(file) + self.crop_data_cache = json.load(file) + self.crop_data_cache_time = current_time + return self.crop_data_cache except Exception as e: self.log('ERROR', f"无法加载作物数据: {str(e)}", 'SERVER') return {} @@ -810,6 +851,8 @@ class TCPGameServer(TCPServer): return self._handle_buy_store_product(client_id, message) elif message_type == "buy_store_booth":#购买小卖部格子 return self._handle_buy_store_booth(client_id, message) + elif message_type == "save_game_settings":#保存游戏设置 + return self._handle_save_game_settings(client_id, message) #--------------------------------------------------------------------------- elif message_type == "message":#处理聊天消息(暂未实现) @@ -1340,7 +1383,7 @@ class TCPGameServer(TCPServer): #==========================收获作物处理========================== #处理收获作物请求 def _handle_harvest_crop(self, client_id, message): - """处理收获作物请求""" + """处理收获作物请求(优化版本)""" # 检查用户是否已登录 logged_in, response = self._check_user_logged_in(client_id, "收获作物", "harvest_crop") if not logged_in: @@ -1354,6 +1397,11 @@ class TCPGameServer(TCPServer): lot_index = message.get("lot_index", -1) target_username = message.get("target_username", "") + # 预加载作物配置数据(只加载一次) + crop_data = self._load_crop_data() + if not crop_data: + return self._send_action_error(client_id, "harvest_crop", "无法加载作物配置数据") + # 确定操作目标:如果有target_username就是访问模式(偷菜),否则是自己的农场 if target_username and target_username != current_username: # 访问模式:偷菜(收益给自己,清空目标玩家的作物) @@ -1396,7 +1444,7 @@ class TCPGameServer(TCPServer): return self._send_action_error(client_id, "harvest_crop", "作物尚未成熟,无法偷菜") # 处理偷菜 - return self._process_steal_crop(client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index) + return self._process_steal_crop_optimized(client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index, crop_data) else: # 正常模式:收获自己的作物 # 验证地块索引 @@ -1434,55 +1482,55 @@ class TCPGameServer(TCPServer): return self._send_action_error(client_id, "harvest_crop", "作物尚未成熟") # 处理正常收获 - return self._process_harvest(client_id, current_player_data, current_username, lot, lot_index) + return self._process_harvest_optimized(client_id, current_player_data, current_username, lot, lot_index, crop_data) - #辅助函数-处理作物收获 - def _process_harvest(self, client_id, player_data, username, lot, lot_index): - """处理作物收获逻辑""" - # 读取作物配置 - crop_data = self._load_crop_data() - - # 获取作物类型和经验 + #辅助函数-处理作物收获(优化版本) + def _process_harvest_optimized(self, client_id, player_data, username, lot, lot_index, crop_data): + """处理作物收获逻辑(优化版本)""" + # 获取作物类型和基本信息 crop_type = lot["crop_type"] + crop_info = crop_data.get(crop_type, {}) # 检查是否为杂草类型(杂草不能收获,只能铲除) - if crop_type in crop_data: - crop_info = crop_data[crop_type] - is_weed = crop_info.get("是否杂草", False) - - if is_weed: - return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。") - - crop_exp = crop_info.get("经验", 10) - - # 额外检查:如果作物收益为负数,也视为杂草 - crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0) - if crop_income < 0: - return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。") - else: - # 默认经验 - crop_exp = 10 + is_weed = crop_info.get("是否杂草", False) + if is_weed: + return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。") + + # 额外检查:如果作物收益为负数,也视为杂草 + crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0) + if crop_income < 0: + return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能收获,只能铲除!请使用铲除功能清理杂草。") + + # 获取作物经验 + crop_exp = crop_info.get("经验", 10) # 生成成熟物收获(1-5个) import random harvest_count = random.randint(1, 5) - crop_harvest = { - "name": crop_type, - "count": harvest_count - } # 10%概率获得1-2个该作物的种子 - seed_reward = self._generate_harvest_seed_reward(crop_type) + seed_reward = None + if random.random() <= 0.1: + seed_reward = { + "name": crop_type, + "count": random.randint(1, 2) + } - # 更新玩家经验(不再直接给钱) + # 更新玩家经验 player_data["experience"] += crop_exp - # 添加成熟物到作物仓库 - self._add_crop_to_warehouse(player_data, crop_harvest) + # 检查是否会获得成熟物 + mature_name = crop_info.get("成熟物名称") + will_get_mature_item = mature_name is not None + mature_item_name = mature_name if mature_name and mature_name.strip() else crop_type + + # 添加成熟物到作物仓库(如果允许) + if will_get_mature_item: + self._add_crop_to_warehouse_optimized(player_data, {"name": crop_type, "count": harvest_count}, mature_item_name, crop_info.get("品质", "普通")) # 添加种子奖励到背包 if seed_reward: - self._add_seeds_to_bag(player_data, seed_reward) + self._add_seeds_to_bag_optimized(player_data, seed_reward, crop_info.get("品质", "普通")) # 检查升级 level_up_experience = 100 * player_data["level"] @@ -1491,12 +1539,14 @@ class TCPGameServer(TCPServer): player_data["experience"] -= level_up_experience self.log('INFO', f"玩家 {username} 升级到 {player_data['level']} 级", 'SERVER') - # 清理地块 - lot["is_planted"] = False - lot["crop_type"] = "" - lot["grow_time"] = 0 - lot["已浇水"] = False - lot["已施肥"] = False + # 清理地块(批量更新) + lot.update({ + "is_planted": False, + "crop_type": "", + "grow_time": 0, + "已浇水": False, + "已施肥": False + }) # 清除施肥时间戳 if "施肥时间" in lot: @@ -1509,7 +1559,11 @@ class TCPGameServer(TCPServer): self._push_crop_update_to_player(username, player_data) # 构建消息 - message = f"收获成功,获得 {crop_type} x{harvest_count} 和 {crop_exp} 经验" + if will_get_mature_item: + message = f"收获成功,获得 {mature_item_name} x{harvest_count} 和 {crop_exp} 经验" + else: + message = f"收获成功,获得 {crop_exp} 经验({crop_type}无成熟物产出)" + if seed_reward: message += f",额外获得 {seed_reward['name']} 种子 x{seed_reward['count']}" @@ -1529,9 +1583,9 @@ class TCPGameServer(TCPServer): } }) - #辅助函数-处理偷菜逻辑(访问模式下收获其他玩家作物的操作) - def _process_steal_crop(self, client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index): - """处理偷菜逻辑(收益给当前玩家,清空目标玩家的作物)""" + #辅助函数-处理偷菜逻辑(访问模式下收获其他玩家作物的操作)(优化版本) + def _process_steal_crop_optimized(self, client_id, current_player_data, current_username, target_player_data, target_username, target_lot, lot_index, crop_data): + """处理偷菜逻辑(收益给当前玩家,清空目标玩家的作物)(优化版本)""" # 偷菜体力值消耗 stamina_cost = 2 @@ -1554,40 +1608,34 @@ class TCPGameServer(TCPServer): target_player_data, target_username, patrol_pets[0] ) - # 读取作物配置 - crop_data = self._load_crop_data() - - # 获取作物类型和经验(偷菜获得的经验稍微少一些,比如50%) + # 获取作物类型和基本信息 crop_type = target_lot["crop_type"] + crop_info = crop_data.get(crop_type, {}) # 检查是否为杂草类型(杂草不能偷取,只能铲除) - if crop_type in crop_data: - crop_info = crop_data[crop_type] - is_weed = crop_info.get("是否杂草", False) - - if is_weed: - return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。") - - crop_exp = int(crop_info.get("经验", 10) * 0.5) # 偷菜获得50%经验 - - # 额外检查:如果作物收益为负数,也视为杂草 - crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0) - if crop_income < 0: - return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。") - else: - # 默认经验 - crop_exp = 5 + is_weed = crop_info.get("是否杂草", False) + if is_weed: + return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。") + + # 额外检查:如果作物收益为负数,也视为杂草 + crop_income = crop_info.get("收益", 100) + crop_info.get("花费", 0) + if crop_income < 0: + return self._send_action_error(client_id, "harvest_crop", f"{crop_type}不能偷取,只能铲除!这是杂草,没有收益价值。") + + # 获取作物经验(偷菜获得50%经验) + crop_exp = int(crop_info.get("经验", 10) * 0.5) # 生成成熟物收获(偷菜获得较少,1-3个) import random harvest_count = random.randint(1, 3) - crop_harvest = { - "name": crop_type, - "count": harvest_count - } # 10%概率获得1-2个该作物的种子(偷菜也有机会获得种子) - seed_reward = self._generate_harvest_seed_reward(crop_type) + seed_reward = None + if random.random() <= 0.1: + seed_reward = { + "name": crop_type, + "count": random.randint(1, 2) + } # 消耗当前玩家的体力值 stamina_success, stamina_message = self._consume_stamina(current_player_data, stamina_cost, "偷菜") @@ -1597,12 +1645,18 @@ class TCPGameServer(TCPServer): # 更新当前玩家数据(获得经验) current_player_data["experience"] += crop_exp - # 添加成熟物到作物仓库 - self._add_crop_to_warehouse(current_player_data, crop_harvest) + # 检查是否会获得成熟物 + mature_name = crop_info.get("成熟物名称") + will_get_mature_item = mature_name is not None + mature_item_name = mature_name if mature_name and mature_name.strip() else crop_type + + # 添加成熟物到作物仓库(如果允许) + if will_get_mature_item: + self._add_crop_to_warehouse_optimized(current_player_data, {"name": crop_type, "count": harvest_count}, mature_item_name, crop_info.get("品质", "普通")) # 添加种子奖励到背包 if seed_reward: - self._add_seeds_to_bag(current_player_data, seed_reward) + self._add_seeds_to_bag_optimized(current_player_data, seed_reward, crop_info.get("品质", "普通")) # 检查当前玩家升级 level_up_experience = 100 * current_player_data["level"] @@ -1611,12 +1665,14 @@ class TCPGameServer(TCPServer): current_player_data["experience"] -= level_up_experience self.log('INFO', f"玩家 {current_username} 升级到 {current_player_data['level']} 级", 'SERVER') - # 清理目标玩家的地块 - target_lot["is_planted"] = False - target_lot["crop_type"] = "" - target_lot["grow_time"] = 0 - target_lot["已浇水"] = False - target_lot["已施肥"] = False + # 清理目标玩家的地块(批量更新) + target_lot.update({ + "is_planted": False, + "crop_type": "", + "grow_time": 0, + "已浇水": False, + "已施肥": False + }) # 清除施肥时间戳 if "施肥时间" in target_lot: @@ -1630,7 +1686,11 @@ class TCPGameServer(TCPServer): self._push_crop_update_to_player(target_username, target_player_data) # 构建消息 - message = f"偷菜成功!从 {target_username} 那里获得 {crop_type} x{harvest_count} 和 {crop_exp} 经验,{stamina_message}" + if will_get_mature_item: + message = f"偷菜成功!从 {target_username} 那里获得 {mature_item_name} x{harvest_count} 和 {crop_exp} 经验,{stamina_message}" + else: + message = f"偷菜成功!从 {target_username} 那里获得 {crop_exp} 经验,{stamina_message}({crop_type}无成熟物产出)" + if seed_reward: message += f",额外获得 {seed_reward['name']} 种子 x{seed_reward['count']}" @@ -1810,6 +1870,24 @@ class TCPGameServer(TCPServer): crop_name = crop_harvest["name"] crop_count = crop_harvest["count"] + # 从作物数据检查"成熟物名称"字段 + crop_data = self._load_crop_data() + if crop_data and crop_name in crop_data: + mature_name = crop_data[crop_name].get("成熟物名称") + # 如果成熟物名称为null,则不添加成熟物到仓库 + if mature_name is None: + self.log('DEBUG', f"作物 {crop_name} 的成熟物名称为null,跳过添加到作物仓库", 'SERVER') + return + + # 如果有指定的成熟物名称,使用它作为仓库中的名称 + if mature_name and mature_name.strip(): + warehouse_item_name = mature_name + else: + warehouse_item_name = crop_name + else: + # 如果作物数据中没有该作物,使用原名称 + warehouse_item_name = crop_name + # 确保作物仓库存在 if "作物仓库" not in player_data: player_data["作物仓库"] = [] @@ -1817,7 +1895,7 @@ class TCPGameServer(TCPServer): # 查找仓库中是否已有该成熟物 crop_found = False for item in player_data["作物仓库"]: - if item.get("name") == crop_name: + if item.get("name") == warehouse_item_name: item["count"] += crop_count crop_found = True break @@ -1825,16 +1903,65 @@ class TCPGameServer(TCPServer): # 如果仓库中没有该成熟物,添加新条目 if not crop_found: # 从作物数据获取品质信息 - crop_data = self._load_crop_data() quality = "普通" if crop_data and crop_name in crop_data: quality = crop_data[crop_name].get("品质", "普通") player_data["作物仓库"].append({ - "name": crop_name, + "name": warehouse_item_name, "quality": quality, "count": crop_count }) + + # 添加种子到玩家背包(优化版本) + def _add_seeds_to_bag_optimized(self, player_data, seed_reward, quality="普通"): + """将种子奖励添加到玩家背包(优化版本)""" + if not seed_reward: + return + + seed_name = seed_reward["name"] + seed_count = seed_reward["count"] + + # 确保背包存在 + if "player_bag" not in player_data: + player_data["player_bag"] = [] + + # 查找背包中是否已有该种子 + for item in player_data["player_bag"]: + if item.get("name") == seed_name: + item["count"] += seed_count + return + + # 如果背包中没有该种子,添加新条目 + player_data["player_bag"].append({ + "name": seed_name, + "quality": quality, + "count": seed_count + }) + + def _add_crop_to_warehouse_optimized(self, player_data, crop_harvest, warehouse_item_name, quality="普通"): + """将成熟物添加到玩家作物仓库(优化版本)""" + if not crop_harvest: + return + + crop_count = crop_harvest["count"] + + # 确保作物仓库存在 + if "作物仓库" not in player_data: + player_data["作物仓库"] = [] + + # 查找仓库中是否已有该成熟物 + for item in player_data["作物仓库"]: + if item.get("name") == warehouse_item_name: + item["count"] += crop_count + return + + # 如果仓库中没有该成熟物,添加新条目 + player_data["作物仓库"].append({ + "name": warehouse_item_name, + "quality": quality, + "count": crop_count + }) #==========================收获作物处理========================== @@ -4427,8 +4554,21 @@ class TCPGameServer(TCPServer): # 检查是否升级 self._check_level_up(player_data) - # 添加成熟物到作物仓库 - self._add_crop_to_warehouse(player_data, crop_harvest) + # 检查是否会获得成熟物 + crop_data = self._load_crop_data() + will_get_mature_item = True + mature_item_name = crop_type + + if crop_data and crop_type in crop_data: + mature_name = crop_data[crop_type].get("成熟物名称") + if mature_name is None: + will_get_mature_item = False + elif mature_name and mature_name.strip(): + mature_item_name = mature_name + + # 添加成熟物到作物仓库(如果允许) + if will_get_mature_item: + self._add_crop_to_warehouse(player_data, crop_harvest) # 添加种子奖励到背包 if seed_reward: @@ -4452,7 +4592,11 @@ class TCPGameServer(TCPServer): self._push_crop_update_to_player(username, player_data) # 构建消息 - message = f"使用 {item_name} 收获成功,获得 {crop_type} x{harvest_count} 和 {crop_exp} 经验{message_suffix}" + if will_get_mature_item: + message = f"使用 {item_name} 收获成功,获得 {mature_item_name} x{harvest_count} 和 {crop_exp} 经验{message_suffix}" + else: + message = f"使用 {item_name} 收获成功,获得 {crop_exp} 经验{message_suffix}({crop_type}无成熟物产出)" + if seed_reward: message += f",额外获得 {seed_reward['name']} x{seed_reward['count']}" @@ -4546,8 +4690,21 @@ class TCPGameServer(TCPServer): # 检查当前玩家是否升级 self._check_level_up(current_player_data) - # 收获物给当前玩家 - self._add_crop_to_warehouse(current_player_data, crop_harvest) + # 检查是否会获得成熟物 + crop_data = self._load_crop_data() + will_get_mature_item = True + mature_item_name = crop_type + + if crop_data and crop_type in crop_data: + mature_name = crop_data[crop_type].get("成熟物名称") + if mature_name is None: + will_get_mature_item = False + elif mature_name and mature_name.strip(): + mature_item_name = mature_name + + # 收获物给当前玩家(如果允许) + if will_get_mature_item: + self._add_crop_to_warehouse(current_player_data, crop_harvest) # 种子奖励给当前玩家 if seed_reward: @@ -4572,7 +4729,11 @@ class TCPGameServer(TCPServer): self._push_crop_update_to_player(target_username, target_player_data) # 构建消息 - message = f"使用 {item_name} 帮助收获成功!从 {target_username} 那里获得 {crop_type} x{harvest_count} 和 {crop_exp} 经验{message_suffix}" + if will_get_mature_item: + message = f"使用 {item_name} 帮助收获成功!从 {target_username} 那里获得 {mature_item_name} x{harvest_count} 和 {crop_exp} 经验{message_suffix}" + else: + message = f"使用 {item_name} 帮助收获成功!从 {target_username} 那里获得 {crop_exp} 经验{message_suffix}({crop_type}无成熟物产出)" + if seed_reward: message += f",额外获得 {seed_reward['name']} x{seed_reward['count']}" @@ -5417,7 +5578,8 @@ class TCPGameServer(TCPServer): stamina_system = player_data.get("体力系统", {}) current_stamina = stamina_system.get("当前体力值", 20) return current_stamina >= amount - + + def _check_and_update_register_time(self, player_data, username): """检查并更新已存在玩家的注册时间""" default_register_time = "2025年05月21日15时00分00秒" @@ -5516,6 +5678,81 @@ class TCPGameServer(TCPServer): +#==========================游戏设置处理========================== + def _handle_save_game_settings(self, client_id, message): + """处理保存游戏设置请求""" + # 检查用户是否已登录 + logged_in, response = self._check_user_logged_in(client_id, "保存游戏设置", "save_game_settings") + if not logged_in: + return self.send_data(client_id, response) + + # 获取玩家数据 + player_data, username, response = self._load_player_data_with_check(client_id, "save_game_settings") + if not player_data: + return self.send_data(client_id, response) + + # 获取设置数据 + settings = message.get("settings", {}) + if not settings: + return self.send_data(client_id, { + "type": "save_game_settings_response", + "success": False, + "message": "设置数据为空" + }) + + # 验证设置数据格式 + valid_settings = {} + + # 验证背景音乐音量 (0.0-1.0) + if "背景音乐音量" in settings: + volume = settings["背景音乐音量"] + if isinstance(volume, (int, float)) and 0.0 <= volume <= 1.0: + valid_settings["背景音乐音量"] = float(volume) + else: + return self.send_data(client_id, { + "type": "save_game_settings_response", + "success": False, + "message": "背景音乐音量值无效,应在0.0-1.0之间" + }) + + # 验证天气显示设置 + if "天气显示" in settings: + weather_display = settings["天气显示"] + if isinstance(weather_display, bool): + valid_settings["天气显示"] = weather_display + else: + return self.send_data(client_id, { + "type": "save_game_settings_response", + "success": False, + "message": "天气显示设置值无效,应为布尔值" + }) + + # 保存设置到玩家数据 + if "游戏设置" not in player_data: + player_data["游戏设置"] = {} + + player_data["游戏设置"].update(valid_settings) + + # 保存到数据库 + if self.save_player_data(username, player_data): + self.log('INFO', f"用户 {username} 保存游戏设置: {valid_settings}", 'SERVER') + + return self.send_data(client_id, { + "type": "save_game_settings_response", + "success": True, + "message": "游戏设置保存成功", + "settings": valid_settings + }) + else: + return self.send_data(client_id, { + "type": "save_game_settings_response", + "success": False, + "message": "保存游戏设置失败" + }) +#==========================游戏设置处理========================== + + + #==========================玩家游玩时间处理========================== #处理获取玩家游玩时间请求 def _handle_get_play_time(self, client_id): @@ -6506,16 +6743,32 @@ class TCPGameServer(TCPServer): #==========================每日签到处理========================== #加载每日签到配置 def _load_daily_check_in_config(self): - """加载每日签到配置""" + """加载每日签到配置 - 优先使用MongoDB,失败则回退到JSON文件""" + # 优先尝试从MongoDB获取配置 + if hasattr(self, 'use_mongodb') and self.use_mongodb and self.mongo_api: + try: + config = self.mongo_api.get_daily_checkin_config() + if config: + self.log('INFO', "从MongoDB成功加载每日签到配置", 'SERVER') + return config + else: + self.log('WARNING', "MongoDB中未找到每日签到配置,尝试使用JSON文件", 'SERVER') + except Exception as e: + self.log('ERROR', f"从MongoDB加载每日签到配置失败: {e},回退到JSON文件", 'SERVER') + + # 回退到JSON文件 try: config_path = os.path.join(self.config_dir, "daily_checkin_config.json") if os.path.exists(config_path): with open(config_path, 'r', encoding='utf-8') as f: - return json.load(f) - except: - pass + config = json.load(f) + self.log('INFO', "从JSON文件成功加载每日签到配置", 'SERVER') + return config + except Exception as e: + self.log('ERROR', f"从JSON文件加载每日签到配置失败: {e}", 'SERVER') # 默认配置 + self.log('WARNING', "使用默认每日签到配置", 'SERVER') return { "基础奖励": { "金币": {"最小值": 200, "最大值": 500, "图标": "💰", "颜色": "#FFD700"}, @@ -6537,6 +6790,25 @@ class TCPGameServer(TCPServer): } } + #更新每日签到配置到MongoDB + def _update_daily_checkin_config_to_mongodb(self, config_data): + """更新每日签到配置到MongoDB""" + if hasattr(self, 'use_mongodb') and self.use_mongodb and self.mongo_api: + try: + success = self.mongo_api.update_daily_checkin_config(config_data) + if success: + self.log('INFO', "成功更新每日签到配置到MongoDB", 'SERVER') + return True + else: + self.log('ERROR', "更新每日签到配置到MongoDB失败", 'SERVER') + return False + except Exception as e: + self.log('ERROR', f"更新每日签到配置到MongoDB异常: {e}", 'SERVER') + return False + else: + self.log('WARNING', "MongoDB未连接,无法更新配置", 'SERVER') + return False + #处理每日签到请求 def _handle_daily_check_in_request(self, client_id, message): """处理每日签到请求""" @@ -7126,16 +7398,32 @@ class TCPGameServer(TCPServer): #加载抽奖配置 def _load_lucky_draw_config(self): - """加载抽奖配置""" + """加载抽奖配置(优先从MongoDB读取)""" + # 优先尝试从MongoDB读取 + if self.use_mongodb and self.mongo_api: + try: + config = self.mongo_api.get_lucky_draw_config() + if config: + self.log('INFO', "成功从MongoDB加载幸运抽奖配置", 'SERVER') + return config + else: + self.log('WARNING', "MongoDB中未找到幸运抽奖配置,尝试从JSON文件读取", 'SERVER') + except Exception as e: + self.log('ERROR', f"从MongoDB读取幸运抽奖配置失败: {e},尝试从JSON文件读取", 'SERVER') + + # 回退到JSON文件 try: config_path = os.path.join(self.config_dir, "lucky_draw_config.json") if os.path.exists(config_path): with open(config_path, 'r', encoding='utf-8') as f: - return json.load(f) - except: - pass + config = json.load(f) + self.log('INFO', "成功从JSON文件加载幸运抽奖配置", 'SERVER') + return config + except Exception as e: + self.log('ERROR', f"从JSON文件读取幸运抽奖配置失败: {e},使用默认配置", 'SERVER') # 默认配置 + self.log('WARNING', "使用默认幸运抽奖配置", 'SERVER') return { "抽奖费用": {"单抽": 800, "五连抽": 3600, "十连抽": 6400}, "概率配置": { @@ -7151,16 +7439,31 @@ class TCPGameServer(TCPServer): #加载在线礼包配置 def _load_online_gift_config(self): """加载在线礼包配置""" + # 优先从MongoDB读取配置 + if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected(): + try: + config = self.mongo_api.get_online_gift_config() + if config: + self.log('INFO', '成功从MongoDB加载在线礼包配置', 'SERVER') + return config + else: + self.log('WARNING', '从MongoDB未找到在线礼包配置,尝试从JSON文件加载', 'SERVER') + except Exception as e: + self.log('ERROR', f'从MongoDB加载在线礼包配置失败: {str(e)},尝试从JSON文件加载', 'SERVER') + + # 回退到JSON文件 try: config_path = os.path.join(self.config_dir, "online_gift_config.json") if os.path.exists(config_path): with open(config_path, 'r', encoding='utf-8') as f: - return json.load(f) + config = json.load(f) + self.log('INFO', '成功从JSON文件加载在线礼包配置', 'SERVER') + return config except Exception as e: - self.log('ERROR', f"加载在线礼包配置失败: {str(e)}", 'SERVER') - pass + self.log('ERROR', f"从JSON文件加载在线礼包配置失败: {str(e)}", 'SERVER') # 默认配置 + self.log('WARNING', '使用默认在线礼包配置', 'SERVER') return { "在线礼包配置": { "1分钟": {"时长秒数": 60, "奖励": {"金币": 100, "经验": 50, "种子": [{"名称": "小麦", "数量": 5}]}}, @@ -7174,15 +7477,31 @@ class TCPGameServer(TCPServer): #加载新手礼包配置 def _load_new_player_config(self): """加载新手礼包配置""" + # 优先从MongoDB读取配置 + if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected(): + try: + config = self.mongo_api.get_new_player_config() + if config: + self.log('INFO', '成功从MongoDB加载新手大礼包配置', 'SERVER') + return config + else: + self.log('WARNING', '从MongoDB未找到新手大礼包配置,尝试从JSON文件加载', 'SERVER') + except Exception as e: + self.log('ERROR', f'从MongoDB加载新手大礼包配置失败: {str(e)},尝试从JSON文件加载', 'SERVER') + + # 回退到JSON文件 try: config_path = os.path.join(self.config_dir, "new_player_config.json") if os.path.exists(config_path): with open(config_path, 'r', encoding='utf-8') as f: - return json.load(f) + config = json.load(f) + self.log('INFO', '成功从JSON文件加载新手大礼包配置', 'SERVER') + return config except Exception as e: - self.log('ERROR', f"加载新手礼包配置失败: {str(e)}", 'SERVER') + self.log('ERROR', f"从JSON文件加载新手礼包配置失败: {str(e)}", 'SERVER') # 默认配置 + self.log('WARNING', '使用默认新手大礼包配置', 'SERVER') return { "新手礼包配置": { "奖励内容": { @@ -8279,7 +8598,7 @@ class TCPGameServer(TCPServer): # 从智慧树消息库中随机获取一条消息 random_message = self._get_random_wisdom_tree_message() if random_message: - wisdom_tree_config["智慧树显示的话"] = random_message + wisdom_tree_config["智慧树显示的话"] = random_message.get("content", "") # 保存数据 self.save_player_data(username, player_data) @@ -8347,7 +8666,7 @@ class TCPGameServer(TCPServer): random_message = self._get_random_wisdom_tree_message() if random_message: - wisdom_tree_config["智慧树显示的话"] = random_message + wisdom_tree_config["智慧树显示的话"] = random_message.get("content", "") # 保存数据 self.save_player_data(username, player_data) @@ -8505,6 +8824,22 @@ class TCPGameServer(TCPServer): import json import random + # 优先从MongoDB读取 + if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected(): + try: + wisdom_tree_data = self.mongo_api.get_wisdom_tree_config() + if wisdom_tree_data: + messages = wisdom_tree_data.get("messages", []) + if messages: + selected_message = random.choice(messages) + self.log('INFO', f"成功从MongoDB获取智慧树消息", 'SERVER') + return selected_message + else: + return None + except Exception as e: + self.log('ERROR', f"从MongoDB读取智慧树消息失败: {e}", 'SERVER') + + # 回退到JSON文件 wisdom_tree_data_path = os.path.join(os.path.dirname(__file__), "config", "wisdom_tree_data.json") try: @@ -8514,12 +8849,13 @@ class TCPGameServer(TCPServer): messages = wisdom_tree_data.get("messages", []) if messages: selected_message = random.choice(messages) - return selected_message.get("content", "") + self.log('INFO', f"成功从JSON文件获取智慧树消息", 'SERVER') + return selected_message else: - return "" + return None except Exception as e: - print(f"读取智慧树消息失败:{e}") - return "" + self.log('ERROR', f"从JSON文件读取智慧树消息失败: {e}", 'SERVER') + return None def _save_wisdom_tree_message(self, username, message_content): """保存智慧树消息到消息库""" @@ -8528,6 +8864,46 @@ class TCPGameServer(TCPServer): import time import uuid + # 创建新消息 + new_message = { + "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "sender": username, + "content": message_content, + "id": str(uuid.uuid4()) + } + + # 优先保存到MongoDB + if hasattr(self, 'mongo_api') and self.mongo_api and self.mongo_api.is_connected(): + try: + # 获取现有数据 + wisdom_tree_data = self.mongo_api.get_wisdom_tree_config() + if not wisdom_tree_data: + wisdom_tree_data = { + "messages": [], + "total_messages": 0, + "last_update": "" + } + + # 添加新消息 + wisdom_tree_data["messages"].append(new_message) + wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"]) + wisdom_tree_data["last_update"] = new_message["timestamp"] + + # 保持最多1000条消息 + if len(wisdom_tree_data["messages"]) > 1000: + wisdom_tree_data["messages"] = wisdom_tree_data["messages"][-1000:] + wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"]) + + # 保存到MongoDB + if self.mongo_api.update_wisdom_tree_config(wisdom_tree_data): + self.log('INFO', f"成功保存智慧树消息到MongoDB: {username}", 'SERVER') + return True + else: + self.log('ERROR', f"保存智慧树消息到MongoDB失败: {username}", 'SERVER') + except Exception as e: + self.log('ERROR', f"MongoDB保存智慧树消息异常: {e}", 'SERVER') + + # 回退到JSON文件 wisdom_tree_data_path = os.path.join(os.path.dirname(__file__), "config", "wisdom_tree_data.json") try: @@ -8542,14 +8918,6 @@ class TCPGameServer(TCPServer): "last_update": "" } - # 创建新消息 - new_message = { - "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), - "sender": username, - "content": message_content, - "id": str(uuid.uuid4()) - } - # 添加到消息列表 wisdom_tree_data["messages"].append(new_message) wisdom_tree_data["total_messages"] = len(wisdom_tree_data["messages"]) @@ -8564,9 +8932,10 @@ class TCPGameServer(TCPServer): with open(wisdom_tree_data_path, 'w', encoding='utf-8') as f: json.dump(wisdom_tree_data, f, ensure_ascii=False, indent=4) + self.log('INFO', f"成功保存智慧树消息到JSON文件: {username}", 'SERVER') return True except Exception as e: - print(f"保存智慧树消息失败:{e}") + self.log('ERROR', f"保存智慧树消息到JSON文件失败: {e}", 'SERVER') return False def check_wisdom_tree_health_decay(self): @@ -9543,17 +9912,6 @@ if __name__ == "__main__": server_thread.start() print("✅ 服务器启动成功!") - print("📋 功能列表:") - print(" ├── 用户注册/登录系统") - print(" ├── 作物种植与收获") - print(" ├── 浇水与施肥系统") - print(" ├── 每日签到奖励") - print(" ├── 幸运抽奖系统") - print(" ├── 玩家互动功能") - print(" ├── 性能优化缓存") - print(" └── 控制台命令系统") - print("=" * 60) - print("🔥 服务器运行中...") # 启动控制台输入线程 console_thread = threading.Thread(target=console_input_thread, args=(server,)) @@ -9584,4 +9942,4 @@ if __name__ == "__main__": except Exception as e: print(f"\n❌ 服务器启动失败: {str(e)}") print("🔧 请检查配置并重试") - sys.exit(1) \ No newline at end of file + sys.exit(1) \ No newline at end of file diff --git a/Server/__pycache__/SMYMongoDBAPI.cpython-313.pyc b/Server/__pycache__/SMYMongoDBAPI.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8eac0053ca1544a38e04e6c108ad71fb7231ed50 GIT binary patch literal 24880 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 literal 0 HcmV?d00001 diff --git a/Server/__pycache__/TCPGameServer.cpython-313.pyc b/Server/__pycache__/TCPGameServer.cpython-313.pyc index 74b2cb7793e39dc668d5e2b6bccca043a32ccba1..41499a15f249ce1efb2361f1c186677ef81cafd5 100644 GIT binary patch literal 350744 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
yMS4TEa}g=m^U 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�_2AV7*a0GWV! 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�y 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 OSXH>ZSpUmnI{&|!YWi>h delta 19585 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 diff --git a/Server/config/initial_player_data_template.json b/Server/config/initial_player_data_template.json index f847dd9..bb664df 100644 --- a/Server/config/initial_player_data_template.json +++ b/Server/config/initial_player_data_template.json @@ -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 + } } \ No newline at end of file diff --git a/Server/game_saves/2143323382.json b/Server/game_saves/2143323382.json index dcb9c04..66320b0 100644 --- a/Server/game_saves/2143323382.json +++ b/Server/game_saves/2143323382.json @@ -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 + } } \ No newline at end of file diff --git a/Server/test_mongodb_migration.py b/Server/test_mongodb_migration.py new file mode 100644 index 0000000..f9c25b1 --- /dev/null +++ b/Server/test_mongodb_migration.py @@ -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) \ No newline at end of file diff --git a/Server/test_server_mongodb.py b/Server/test_server_mongodb.py new file mode 100644 index 0000000..4d6034e --- /dev/null +++ b/Server/test_server_mongodb.py @@ -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) \ No newline at end of file diff --git a/__pycache__/SMYMongoDBAPI.cpython-313.pyc b/__pycache__/SMYMongoDBAPI.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..767d4e93b372247da0c4604a0b30d491eac6e6b1 GIT binary patch literal 14409 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%0Dd(F1w~bDB7^w3GOUGvV ze5t!*1ATr23vu||Mh+E_Gejs6;=v#!G-QT6Iv%|k9=)j9J+(agjRcF|e-O@E4&&KG zo8SMSB?i}(cR`egqbij6F})jONV|A+X!EEZ z_`5OKi@`n&f*6D$5a=)%>bM*{j{#09|82~0`r#N-ARZ2aQxlFO?N7i7O~3ygihLv| zD8-{xkN};(u{bQsGt_ncVzzp$>rWKia-F)xZ0(84oA6Nk$4(u~-kP)PS?`I#n-tt~ zCL6nAJb06WTh8TTYsTAi6x=2@Cc7sqCWDhT=X%raJ8xoIu3J|R1y)R~OVUX$X?p+m z^evq?DM-tCo7h^c3Ag0l$t9Dq$rb1Jk;l|Mdv9WLZkx`{)=tEeU6U2bZSOypqu}vk z^G&?vcIc|1;aHA>TXJx+{USZN@mz#FruKY2b>IEzJ^OBAW^OIDOLvbhv!wYt-NaUn z2eFT;WOFh$*_Hg(xmNO+X>jE*7tT(N4^Ffv>4}Z+MADuuf5JoW9@4ul)H07o1_x^eCc@u3;3QXyYYY^MkObRqZOL8Q@zWqe@qd2H+u- z)@Kg6-3ZwGa@&DGLE9?dpsHm!MWE@&G_9s&hNPKq&gU2T7xJ@YQTZCQd$HzQkqw-} z*6y~d#%hzxxYTo2l20Y)NwoNtT`mKMWb@;5sK%%GUqJbkwyV|w=3B$JA5V}mt2446Ec1d%D(a8)zgn> z&%Ba-?)_`ezL-sZckbwu*^@tquSKXt)Y%C{Zm|scQgrq0W7&5{#j4@~f6@Ass;aZ4 z5xweKXv`uL5MOYu{DP9jton_P=t1(5?_mifvf>#TR|1uS>q_z`;um?5+K6r@V!?{Z zVka;>+@=;XLF5+*;>r3%1GYyJ=6?0;)$!-AB;Uz{lAI1bTsp$`WE9hYbI&dgV4*!y$1;8n= z7%_YKBTy-Zh)7tv$k9#slLbFkKw~BVk{Ls9&EwP+#+oaAQGi5F5vX-f`wh_a> zTFXee4b!$;F;dw&{_xpH-+46Ida-G$ZTC#uo^;!uRNsB6fqheL{#5HXQsseZ+kUa= zPh%4sKJdQpO-3&6pK9MT)z+74rR-~_O>2J#zjiQ{ z!LJq4rurFEL)z4UhkMz^&trGN{2p7`y@fj0SqtH(6`t-I>eJimA^z(cOShN)b(6h& zJ^ky|ET*hyF~v(`e2ZmkJN+AD)7Dn{H?1th@kba31L26@?{Nr5zaI!E5UMulKwut> zMI(X%j{V{3DO8;zbs|iPFeDUC9=AB~E+{J=(I6xUcL1Sr{8JcPiUCTzV7g5tb+_~A zphWbJZG!;jLZ`cKV06q48>Msnj