diff --git a/.gitignore b/.gitignore index dfe8a02..085a31f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ Thumbs.db # IDE-specific files .vscode/ -.idea/ \ No newline at end of file +.idea/ + +server/node_modules/ \ No newline at end of file diff --git a/MainGame.gd b/MainGame.gd index 006e909..8131af6 100644 --- a/MainGame.gd +++ b/MainGame.gd @@ -10,13 +10,11 @@ extends Node @onready var show_level = $GUI/level # 显示当前玩家的等级 @onready var tip = $GUI/tip #显示保存相关 -@onready var toast = $ToastShow -@onready var toast2 = $ToastShow2 @onready var land_panel = $GUI/Land_Panel @onready var dig_button = $GUI/Land_Panel/VBox/HBox/Dig_button @onready var crop_grid_container = $ScrollContainer/Crop_GridContainer -#Thread + @onready var green_bar = $Copy_Nodes/Green #普通 @onready var white_blue_bar = $Copy_Nodes/White_Blue #稀有 @onready var orange_bar = $Copy_Nodes/Orange #优良 @@ -59,7 +57,7 @@ var is_blink_on: bool = false # 是否闪烁状态 var blink_counter: float = 0.0 # 计数器,用于控制闪烁 - +#农作物种类JSON var can_planted_crop = { #玩家点击空地块时可以种植的作物 #品质有 普通,优良,稀有,史诗,传奇,品质会影响作物的颜色 @@ -75,12 +73,10 @@ var can_planted_crop = { "玉米": {"花费": 70, "生长时间": 600, "收益": 90, "品质": "普通", "描述": "营养丰富的优良作物,适合稍有经验的玩家", "耐候性": 15, "等级": 2, "经验": 15}, # 5分钟 "土豆": {"花费": 75, "生长时间": 360, "收益": 90, "品质": "普通", "描述": "容易种植的耐寒作物", "耐候性": 12, "等级": 1, "经验": 10}, # 3分钟 "胡萝卜": {"花费": 60, "生长时间": 480, "收益": 80, "品质": "普通", "描述": "适合新手的健康作物", "耐候性": 12, "等级": 1, "经验": 10}, # 4分钟 - # 中级作物 "草莓": {"花费": 120, "生长时间": 960, "收益": 150, "品质": "优良", "描述": "营养丰富的果实,收益不错", "耐候性": 14, "等级": 2, "经验": 20}, # 8分钟 "番茄": {"花费": 100, "生长时间": 720, "收益": 130, "品质": "优良", "描述": "常见作物,适合小规模种植", "耐候性": 12, "等级": 2, "经验": 15}, # 6分钟 "大豆": {"花费": 90, "生长时间": 840, "收益": 110, "品质": "优良", "描述": "富含蛋白质的基础作物", "耐候性": 11, "等级": 2, "经验": 12}, # 7分钟 - # 高级作物 "蓝莓": {"花费": 150, "生长时间": 1200, "收益": 200, "品质": "稀有", "描述": "较为稀有的作物,市场价值较高", "耐候性": 18, "等级": 3, "经验": 25}, # 10分钟 "洋葱": {"花费": 85, "生长时间": 600, "收益": 105, "品质": "稀有", "描述": "烹饪常用的作物,适合中级种植", "耐候性": 10, "等级": 2, "经验": 10}, # 5分钟 @@ -89,22 +85,20 @@ var can_planted_crop = { "柿子": {"花费": 160, "生长时间": 1080, "收益": 240, "品质": "稀有", "描述": "富含营养的秋季作物", "耐候性": 18, "等级": 3, "经验": 28}, # 9分钟 "花椰菜": {"花费": 130, "生长时间": 960, "收益": 170, "品质": "稀有", "描述": "耐寒的高品质作物,适合经验丰富的玩家", "耐候性": 17, "等级": 3, "经验": 22}, # 8分钟 "芦笋": {"花费": 200, "生长时间": 1560, "收益": 280, "品质": "稀有", "描述": "市场需求量高的稀有作物", "耐候性": 15, "等级": 4, "经验": 30}, # 13分钟 - # 史诗作物 "香草": {"花费": 250, "生长时间": 1800, "收益": 400, "品质": "史诗", "描述": "非常稀有且收益极高的作物", "耐候性": 22, "等级": 5, "经验": 40}, # 15分钟 "西瓜": {"花费": 240, "生长时间": 2400, "收益": 420, "品质": "史诗", "描述": "夏季丰产的高价值作物", "耐候性": 21, "等级": 5, "经验": 45}, # 20分钟 "甜菜": {"花费": 220, "生长时间": 2160, "收益": 350, "品质": "史诗", "描述": "营养丰富的根茎作物,收益较高", "耐候性": 20, "等级": 5, "经验": 38}, # 18分钟 "甘蔗": {"花费": 260, "生长时间": 3000, "收益": 450, "品质": "史诗", "描述": "需要充足水源的高价值作物", "耐候性": 18, "等级": 5, "经验": 50}, # 25分钟 - # 传奇作物 "龙果": {"花费": 400, "生长时间": 4800, "收益": 600, "品质": "传奇", "描述": "极为稀有的热带作物,产量和价值都极高", "耐候性": 25, "等级": 6, "经验": 60}, # 40分钟 "松露": {"花费": 500, "生长时间": 7200, "收益": 700, "品质": "传奇", "描述": "极其珍贵的地下作物,市场价格极高", "耐候性": 23, "等级": 7, "经验": 80}, # 60分钟 "人参": {"花费": 450, "生长时间": 6600, "收益": 650, "品质": "传奇", "描述": "需要耐心等待的珍贵药材", "耐候性": 22, "等级": 6, "经验": 75}, # 55分钟 "金橘": {"花费": 420, "生长时间": 4800, "收益": 620, "品质": "传奇", "描述": "少见的耐寒果树,市场需求量极大", "耐候性": 26, "等级": 7, "经验": 70} # 40分钟 -}; + }; var selected_lot_index = -1 # 当前被选择的地块索引 -#电脑版保存路径 +#电脑版本地游戏保存路径 var game_path = "C:/Users/shumengya/Desktop/smyfarm/" var save_time = 10 @@ -122,22 +116,242 @@ var data = null var buttons = [] + + + + + + +##方法分类->Godot自带方法和自定义方法 +#-------------Godot自带方法----------------- # 准备阶段 func _ready(): - - - _update_ui() _init_crop_list2() - toast.Toast("快去偷其他人的菜吧!", Color.GREEN) + Toast.show("快去偷其他人的菜吧!", Color.GREEN,5.0,1.0) # 初始化农场地块 _init_farm_lots(40) _update_farm_lots() crop_grid_container.hide() - # 更新初始显示 +func _physics_process(delta): + update_timer += delta + if update_timer >= update_interval: + update_timer = 0.0 # 重置计时器 + if start_game == true: + _update_save_time() + _update_farm_lots() + pass + + + for i in range(len(farm_lots)): + var lot = farm_lots[i] + if lot["is_planted"]: + lot["grow_time"] += grow_speed * update_interval + _update_blinking(lot) + +func _on_dig_button_pressed(): + if money < dig_money: + print("金钱不足,无法开垦" ) + Toast.show("金钱不足,无法开垦", Color.RED) + else: + money -= dig_money + farm_lots[dig_index]["is_diged"] = true + land_panel.hide() + _update_ui() + _update_farm_lots() + pass + +# 添加按键触发保存和加载的功能 +func _input(event): + if event.is_action_pressed("ui_save"): # 需要在输入设置中定义这个动作 + _save_game() + elif event.is_action_pressed("ui_load"): # 需要在输入设置中定义这个动作 + _load_game() + +#这里处理登录逻辑,如果用户没有账号,直接注册一个新的 +func _on_login_button_pressed(): + + user_name = username_input.text.strip_edges() # 修剪前后的空格 + user_password = password_input.text.strip_edges() + farmname = farmname_input.text.strip_edges() + + login_data = { + "user_name": user_name, + "user_password": user_password + } + + if user_name == "" or user_password == "": + print("用户名或密码不能为空!") + return + + send_request("login", HTTPClient.METHOD_POST, login_data) + +func _on_register_button_pressed(): + user_name = username_input.text.strip_edges() + user_password = password_input.text.strip_edges() + + var user_password_2 = password_input_2.text.strip_edges() + farmname = farmname_input.text.strip_edges() + #压缩后成一坨大便了 + var init_player_data = {"experience":0,"farm_lots":[{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":3},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":false,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":5},{"crop_type":"","grow_time":0,"is_dead":false,"is_diged":true,"is_planted":false,"max_grow_time":5}],"farm_name":farmname,"level":0,"money":1000,"user_name":user_name,"user_password":user_password} + + if user_name == "" or user_password == "": + print("用户名或密码不能为空!") + return + if farmname == "": + print("农场名称不能为空!") + return + if user_password != user_password_2: + print("前后密码不相同!") + return + + if is_valid_qq_number(user_name) == false: + return + + send_request("register", HTTPClient.METHOD_POST, init_player_data) + pass + +#-------------Godot自带方法----------------- + + + +#-------------自定义方法----------------- +# 保存玩家数据到node.js后端 +func save_game_to_server(): + var player_data = { + "user_name":user_name, + "user_password":user_password, + "farm_name":farmname, + "money": money, + "experience": experience, + "level": level, + "farm_lots": farm_lots + } + + send_request("save", HTTPClient.METHOD_POST, player_data) + pass + +# 加载玩家数据从node.js后端 +func load_game_from_server(): + send_request("login", HTTPClient.METHOD_POST, login_data) + pass + +#更新保存玩家数据的时间倒计时 +func _update_save_time(): + tip.text = "游戏自动保存剩余【"+str(save_time)+"】秒" + save_time -= 1 + if save_time < 0: + _save_game() + save_time = 10 + pass + pass + +func _create_crop_button(crop_name: String, crop_quality: String) -> Button: + # 根据品质选择相应的进度条 + var button = null + match crop_quality: + "普通": + button = green_bar.duplicate() + "优良": + button = white_blue_bar.duplicate() + "稀有": + button = orange_bar.duplicate() + "史诗": + button = pink_bar.duplicate() + "传奇": + button = black_blue_bar.duplicate() + + # 添加按钮事件 + button.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name)) + button.text = str(crop_name) + return button + +#地块闪烁代码-已废弃 +func _update_blinking(lot: Dictionary): + if lot["grow_time"] >= lot["max_grow_time"]: + lot["grow_time"] = lot["max_grow_time"] + blink_counter += blink_speed * update_interval + is_blink_on = int(blink_counter) % 2 == 0 + else: + is_blink_on = false + blink_counter = 0.0 + +# 写入 TXT 文件 +func write_txt_file(file_path: String, text: String, append: bool = false) -> void: + var file + if append == true: + file = FileAccess.open(file_path, FileAccess.READ_WRITE) # 追加模式 + if file: + file.seek_end() # 移动光标到文件末尾 + else: + file = FileAccess.open(file_path, FileAccess.WRITE) # 覆盖模式 + if file: + file.store_string(text) + file.close() + Toast.show("游戏已保存!", Color.GREEN) + else: + print("写入文件时打开失败: ", file_path) + Toast.show("写入文件时打开失败!", Color.RED) + +# 读取 TXT 文件 +func read_txt_file(file_path: String) -> String: + var file = FileAccess.open(file_path, FileAccess.READ) + if file: + var text = file.get_as_text() + file.close() + return text + else: + print("打开文件失败: ", file_path) + return "false" + +#生成随机数-用于作物随机死亡 +func random_probability(probability: float) -> bool: + # 确保传入的概率值在 0 到 1 之间 + if probability*0.001 < 0.0 or probability*0.001 > 1.0: + print("概率值必须在 0 和 1 之间") + return false + + # 生成一个 0 到 1 之间的随机数 + var random_value = randf() + + # 如果随机数小于等于概率值,则返回 true + return random_value <= (probability*0.001) + +# 保存游戏数据 +func _save_game(): + ## 创建一个字典来保存游戏状态 + #var save_data = { + #"user_name":username_input.text, + #"user_password":password_input.text, + #"farm_name":farmname_input.text, + #"money": money, + #"experience": experience, + #"level": level, + #"farm_lots": farm_lots + #} + #write_txt_file(game_path+username_input.text+".txt", str(save_data), false) + ## 将字典写入文件 + save_game_to_server() + +# 加载游戏数据 +func _load_game(): + + ## 从本地读取字典 + #var save_data = JSON.parse_string(read_txt_file(game_path+username_input.text+".txt")) + #money = save_data["money"] + #experience = save_data["experience"] + #level = save_data["level"] + #farm_lots = save_data["farm_lots"] + + load_game_from_server() + + Toast.show("游戏已加载!", Color.GREEN) + _update_ui() + _update_farm_lots() + _init_crop_list2() # 初始化农场地块 func _init_farm_lots(num_lots): @@ -152,7 +366,6 @@ func _init_farm_lots(num_lots): }) - # 初始化作物选择列表 func _init_crop_list2(): # 清空已有的作物按钮 @@ -168,10 +381,6 @@ func _init_crop_list2(): var level_btn = _create_crop_button(crop_name, crop["品质"]) crop_grid_container.add_child(level_btn) - - - - # 更新农场地块状态到 GridContainer func _update_farm_lots(): # 每一秒更新一次状态 # 清空当前显示的地块 @@ -274,7 +483,7 @@ func _on_item_selected(index): dig_index = index pass - +#双击切换UI事件-比如按一下打开再按一下关闭 func double_click_close(node): if node.visible == false: node.show() @@ -302,7 +511,7 @@ func _plant_crop(index, crop_name): var crop = can_planted_crop[crop_name] if money < crop["花费"]: print("金钱不足,无法种植 " + crop_name) - toast.Toast("金钱不足,无法种植 " + crop_name, Color.RED) + Toast.show("金钱不足,无法种植 " + crop_name, Color.RED) return money -= crop["花费"] @@ -312,8 +521,8 @@ func _plant_crop(index, crop_name): farm_lots[index]["max_grow_time"] = crop["生长时间"] print("在地块[[" + str(index) + "]种植了[" + crop_name + "]") - toast.Toast("在地块[[" + str(index) + "]种植了[" + crop_name + "]", Color.GREEN) - toast2.Toast( + Toast.show("在地块[[" + str(index) + "]种植了[" + crop_name + "]", Color.GREEN) + Toast.show( "名称:"+crop_name+"\n"+ "花费:"+str(crop["花费"])+"\n"+ "成熟时间:"+str(crop["生长时间"])+"\n"+ @@ -335,7 +544,7 @@ func _harvest_crop(index): var crop = can_planted_crop[lot["crop_type"]] money += crop["收益"]+crop["花费"] experience += crop["经验"] - toast.Toast("从地块[" + str(index) + "]收获了[" + lot["crop_type"] + "]作物", Color.YELLOW) + Toast.show("从地块[" + str(index) + "]收获了[" + lot["crop_type"] + "]作物", Color.YELLOW) print("从地块[" + str(index) + "]收获了[" + lot["crop_type"] + "]作物") lot["is_planted"] = false @@ -347,13 +556,14 @@ func _harvest_crop(index): _update_farm_lots() else: print("作物还未成熟") - toast.Toast("作物还未成熟", Color.RED) - + Toast.show("作物还未成熟", Color.RED) + +#铲除作物-好像还未实现这个功能 func root_out_crop(index): var lot = farm_lots[index] lot["is_planted"] = false lot["grow_time"] = 0 - toast.Toast("从地块[" + str(index) + "]铲除了[" + lot["crop_type"] + "]作物", Color.YELLOW) + Toast.show("从地块[" + str(index) + "]铲除了[" + lot["crop_type"] + "]作物", Color.YELLOW) lot["crop_type"] = "" _check_level_up() _update_ui() @@ -367,561 +577,9 @@ func _check_level_up(): level += 1 experience -= level_up_experience print("恭喜!你升到了等级 ", level) - toast.Toast("恭喜!你升到了" + str(level) + "级 ", Color.SKY_BLUE) + Toast.show("恭喜!你升到了" + str(level) + "级 ", Color.SKY_BLUE) _init_crop_list2() - - -func _physics_process(delta): - update_timer += delta - - if update_timer >= update_interval: - update_timer = 0.0 # 重置计时器 - if start_game == true: - _update_save_time() - _update_farm_lots() - pass - - - for i in range(len(farm_lots)): - var lot = farm_lots[i] - if lot["is_planted"]: - lot["grow_time"] += grow_speed * update_interval - _update_blinking(lot) - - - - -func _on_dig_button_pressed(): - if money < dig_money: - print("金钱不足,无法开垦" ) - toast.Toast("金钱不足,无法开垦", Color.RED) - else: - money -= dig_money - farm_lots[dig_index]["is_diged"] = true - land_panel.hide() - _update_ui() - _update_farm_lots() - pass - - - -# 保存游戏数据 -func _save_game(): - ## 创建一个字典来保存游戏状态 - #var save_data = { - #"user_name":username_input.text, - #"user_password":password_input.text, - #"farm_name":farmname_input.text, - #"money": money, - #"experience": experience, - #"level": level, - #"farm_lots": farm_lots - #} - #write_txt_file(game_path+username_input.text+".txt", str(save_data), false) - ## 将字典写入文件 - save_game_to_server() - -# 加载游戏数据 -func _load_game(): - - ## 从本地读取字典 - #var save_data = JSON.parse_string(read_txt_file(game_path+username_input.text+".txt")) - #money = save_data["money"] - #experience = save_data["experience"] - #level = save_data["level"] - #farm_lots = save_data["farm_lots"] - - load_game_from_server() - - toast.Toast("游戏已加载!", Color.GREEN) - _update_ui() - _update_farm_lots() - _init_crop_list2() - -# 添加按键触发保存和加载的功能 -func _input(event): - if event.is_action_pressed("ui_save"): # 需要在输入设置中定义这个动作 - _save_game() - elif event.is_action_pressed("ui_load"): # 需要在输入设置中定义这个动作 - _load_game() - -# 写入 TXT 文件 -func write_txt_file(file_path: String, text: String, append: bool = false) -> void: - var file - if append == true: - file = FileAccess.open(file_path, FileAccess.READ_WRITE) # 追加模式 - if file: - file.seek_end() # 移动光标到文件末尾 - else: - file = FileAccess.open(file_path, FileAccess.WRITE) # 覆盖模式 - if file: - file.store_string(text) - file.close() - toast.Toast("游戏已保存!", Color.GREEN) - else: - print("写入文件时打开失败: ", file_path) - toast.Toast("写入文件时打开失败!", Color.RED) - -# 读取 TXT 文件 -func read_txt_file(file_path: String) -> String: - var file = FileAccess.open(file_path, FileAccess.READ) - if file: - var text = file.get_as_text() - file.close() - return text - else: - print("打开文件失败: ", file_path) - return "false" - - -func random_probability(probability: float) -> bool: - # 确保传入的概率值在 0 到 1 之间 - if probability*0.001 < 0.0 or probability*0.001 > 1.0: - print("概率值必须在 0 和 1 之间") - return false - - # 生成一个 0 到 1 之间的随机数 - var random_value = randf() - - # 如果随机数小于等于概率值,则返回 true - return random_value <= (probability*0.001) - - -#这里处理登录逻辑,如果用户没有账号,直接注册一个新的 -func _on_login_button_pressed(): - - user_name = username_input.text.strip_edges() # 修剪前后的空格 - user_password = password_input.text.strip_edges() - farmname = farmname_input.text.strip_edges() - - login_data = { - "user_name": user_name, - "user_password": user_password - } - - if user_name == "" or user_password == "": - print("用户名或密码不能为空!") - return - - send_request("login", HTTPClient.METHOD_POST, login_data) - -func _on_register_button_pressed(): - user_name = username_input.text.strip_edges() - user_password = password_input.text.strip_edges() - - var user_password_2 = password_input_2.text.strip_edges() - farmname = farmname_input.text.strip_edges() - - var init_player_data = { - "experience": 0, - "farm_lots": [ - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - } - ], - "farm_name": farmname, - "level": 0, - "money": 1000, - "user_name": user_name, - "user_password": user_password -} - - if user_name == "" or user_password == "": - print("用户名或密码不能为空!") - return - if farmname == "": - print("农场名称不能为空!") - return - if user_password != user_password_2: - print("前后密码不相同!") - return - - if is_valid_qq_number(user_name) == false: - return - - send_request("register", HTTPClient.METHOD_POST, init_player_data) - pass - - -func _update_save_time(): - tip.text = "游戏自动保存剩余【"+str(save_time)+"】秒" - save_time -= 1 - if save_time < 0: - _save_game() - save_time = 10 - pass - pass - -func _create_crop_button(crop_name: String, crop_quality: String) -> Button: - # 根据品质选择相应的进度条 - var button = null - match crop_quality: - "普通": - button = green_bar.duplicate() - "优良": - button = white_blue_bar.duplicate() - "稀有": - button = orange_bar.duplicate() - "史诗": - button = pink_bar.duplicate() - "传奇": - button = black_blue_bar.duplicate() - - # 添加按钮事件 - button.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name)) - button.text = str(crop_name) - return button - - -func _update_blinking(lot: Dictionary): - if lot["grow_time"] >= lot["max_grow_time"]: - lot["grow_time"] = lot["max_grow_time"] - blink_counter += blink_speed * update_interval - is_blink_on = int(blink_counter) % 2 == 0 - else: - is_blink_on = false - blink_counter = 0.0 - - -# 保存玩家数据到node.js后端 -func save_game_to_server(): - var player_data = { - "user_name":user_name, - "user_password":user_password, - "farm_name":farmname, - "money": money, - "experience": experience, - "level": level, - "farm_lots": farm_lots - } - - send_request("save", HTTPClient.METHOD_POST, player_data) - pass - -# 加载玩家数据从node.js后端 -func load_game_from_server(): - send_request("login", HTTPClient.METHOD_POST, login_data) - pass - - #-------------http传输的两个关键方法----------------- func send_request(endpoint: String, method: int, data: Dictionary = {}): var http_request = HTTPRequest.new() @@ -936,7 +594,6 @@ func send_request(endpoint: String, method: int, data: Dictionary = {}): else: #print("请求已发送: ", endpoint, json_body) pass - func _on_request_completed(result, response_code, headers, body): var response_text = body.get_string_from_utf8() #print("返回 code: %d" % response_code) @@ -1002,3 +659,4 @@ func is_valid_qq_number(qq_number: String) -> bool: return qq_regex.search(qq_number) != null +#-------------自定义方法----------------- diff --git a/Servers/Players/1234567.json b/Servers/Players/1234567.json deleted file mode 100644 index 54d10f3..0000000 --- a/Servers/Players/1234567.json +++ /dev/null @@ -1,330 +0,0 @@ -{ - "experience": 0, - "farm_lots": [ - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - } - ], - "farm_name": "1234567", - "level": 0, - "money": 1000, - "user_name": "1234567", - "user_password": "1234567" -} \ No newline at end of file diff --git a/Servers/saves/received_data.json b/Servers/saves/received_data.json deleted file mode 100644 index 71d01a5..0000000 --- a/Servers/saves/received_data.json +++ /dev/null @@ -1,330 +0,0 @@ -{ - "experience": 4193, - "farm_lots": [ - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - } - ], - "farm_name": "3205788256的农场", - "level": 8, - "money": 1493, - "user_name": "3205788256", - "user_password": "tyh@19900420" -} \ No newline at end of file diff --git a/Servers/server.js b/Servers/server.js deleted file mode 100644 index cc03f76..0000000 --- a/Servers/server.js +++ /dev/null @@ -1,137 +0,0 @@ -const express = require('express'); -const fs = require('fs'); -const path = require('path'); -const bodyParser = require('body-parser'); -const cors = require('cors'); - -// 创建 Express 应用 -const app = express(); -const PORT = 3000; - -// 配置中间件 -app.use(cors()); // 允许跨域资源共享 -app.use(bodyParser.json()); // 解析 JSON 请求体 - -// 服务器存储目录,模拟远程存储位置 -const SERVER_STORAGE_PATH = path.join(__dirname, 'game_saves'); - -// 确保存储目录存在 -if (!fs.existsSync(SERVER_STORAGE_PATH)) { - fs.mkdirSync(SERVER_STORAGE_PATH); -} - -/** - * 保存游戏数据到服务器 - * @route POST /save_game - * @param {Object} req.body - 游戏保存数据 - * @returns {Object} 保存结果 - */ -app.post('/save_game', (req, res) => { - try { - // 从请求体中获取用户名和完整的游戏数据 - const { user_name, ...gameData } = req.body; - - // 检查用户名是否存在 - if (!user_name) { - return res.status(400).json({ - success: false, - message: '用户名不能为空' - }); - } - - // 构建保存文件路径 - const filePath = path.join(SERVER_STORAGE_PATH, `${user_name}.json`); - - // 将游戏数据转换为 JSON 字符串 - const saveData = JSON.stringify(req.body, null, 2); - - // 写入文件 - fs.writeFileSync(filePath, saveData, 'utf8'); - - res.json({ - success: true, - message: '游戏数据保存成功' - }); - } catch (error) { - console.error('保存游戏数据时发生错误:', error); - res.status(500).json({ - success: false, - message: '服务器保存数据失败', - error: error.message - }); - } -}); - -/** - * 从服务器加载游戏数据 - * @route POST /load_game - * @param {string} req.body.user_name - 用户名 - * @param {string} req.body.user_password - 用户密码 - * @returns {Object} 游戏数据或错误信息 - */ -app.post('/load_game', (req, res) => { - try { - const { user_name, user_password } = req.body; - - // 检查用户名和密码是否存在 - if (!user_name || !user_password) { - return res.status(400).json({ - success: false, - message: '用户名和密码不能为空' - }); - } - - // 构建文件路径 - const filePath = path.join(SERVER_STORAGE_PATH, `${user_name}.json`); - - // 检查文件是否存在 - if (!fs.existsSync(filePath)) { - return res.status(404).json({ - success: false, - message: '未找到用户数据' - }); - } - - // 读取文件内容 - const fileContent = fs.readFileSync(filePath, 'utf8'); - const userData = JSON.parse(fileContent); - - // 验证密码 - if (userData.user_password !== user_password) { - return res.status(401).json({ - success: false, - message: '密码错误' - }); - } - - res.json({ - success: true, - message: '游戏数据加载成功', - data: userData - }); - } catch (error) { - console.error('加载游戏数据时发生错误:', error); - res.status(500).json({ - success: false, - message: '服务器加载数据失败', - error: error.message - }); - } -}); - -/** - * 服务器健康检查路由 - * @route GET /health - * @returns {Object} 服务器状态 - */ -app.get('/health', (req, res) => { - res.json({ - status: 'healthy', - message: 'Godot农场游戏服务器正在运行' - }); -}); - -// 启动服务器 -app.listen(PORT, () => { - console.log(`农场游戏后端服务已启动,监听端口:${PORT}`); -}); \ No newline at end of file diff --git a/Servers/测试/json.js b/Servers/测试/json.js deleted file mode 100644 index 66e954e..0000000 --- a/Servers/测试/json.js +++ /dev/null @@ -1,21 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -// 构建 JSON 文件的路径 -const filePath = path.join(__dirname, 'Players', 'player.json'); - -// 读取 JSON 文件 -fs.readFile(filePath, 'utf8', (err, data) => { - if (err) { - console.error('读取文件时出错:', err); - return; - } - - try { - // 解析 JSON 数据 - const playerData = JSON.parse(data); - console.log('玩家数据:', playerData); - } catch (parseErr) { - console.error('解析 JSON 数据时出错:', parseErr); - } -}); diff --git a/Servers/测试/json2.js b/Servers/测试/json2.js deleted file mode 100644 index eeba934..0000000 --- a/Servers/测试/json2.js +++ /dev/null @@ -1,52 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -// 构建 JSON 文件的路径 -const filePath = path.join(__dirname, 'Players', '3205788256.json'); - -// 读取 JSON 文件 -fs.readFile(filePath, 'utf8', (err, data) => { - if (err) { - console.error('读取文件时出错:', err); - return; - } - - try { - // 解析 JSON 数据 - const playerData = JSON.parse(data); - //console.log('玩家数据:', playerData); - - // 对解析后的数据进行分析 - analyzePlayerData(playerData); - - } catch (parseErr) { - console.error('解析 JSON 数据时出错:', parseErr); - } -}); - -// 分析玩家数据的函数 -function analyzePlayerData(playerData) { - // 打印玩家的基本信息 - console.log(`用户名: ${playerData.user_name}`); - console.log(`用户密码: ${playerData.user_password}`); - console.log(`农场名称: ${playerData.farm_name}`); - console.log(`金钱: ${playerData.money}`); - console.log(`经验值: ${playerData.experience}`); - console.log(`等级: ${playerData.level}`); - - // 统计农场地块的状态 - const totalLots = playerData.farm_lots.length; - const diggedLots = playerData.farm_lots.filter(lot => lot.is_diged).length; - const plantedLots = playerData.farm_lots.filter(lot => lot.is_planted).length; - const deadLots = playerData.farm_lots.filter(lot => lot.is_dead).length; - - console.log(`总地块数: ${totalLots}`); - console.log(`已挖掘地块数: ${diggedLots}`); - console.log(`已种植地块数: ${plantedLots}`); - console.log(`已枯死地块数: ${deadLots}`); - - // 检查每个地块的生长状态 - playerData.farm_lots.forEach((lot, index) => { - console.log(`地块 ${index + 1}: 已挖掘 - ${lot.is_diged}, 已种植 - ${lot.is_planted}, 已枯死 - ${lot.is_dead}, 作物类型 - ${lot.crop_type}, 生长时间 - ${lot.grow_time}/${lot.max_grow_time}`); - }); -} diff --git a/Servers/测试/login.js b/Servers/测试/login.js deleted file mode 100644 index f227e72..0000000 --- a/Servers/测试/login.js +++ /dev/null @@ -1,19 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const express = require('express'); -const app = express(); -const port = 3000; - -app.get('/', (req, res) => { - res.json({ message: 'GET 请求已收到!' }); - console.log('GET 请求已收到!'); -}); - -app.post('/', (req, res) => { - res.json({ message: 'POST 请求已收到!', data: req.body }); - console.log('POST 请求已收到!'); -}); - -app.listen(port, () => { - console.log(`萌芽后端服务器正在运行在: http://localhost:${port}`); -}); \ No newline at end of file diff --git a/components/ToastShow.gd b/components/ToastShow.gd index e6af94e..db877e3 100644 --- a/components/ToastShow.gd +++ b/components/ToastShow.gd @@ -1,22 +1,35 @@ extends PanelContainer -@onready var label = $Label -var display_time = 4.0 # 显示的时间(秒) -var fade_duration = 1.0 # 渐隐时间(秒) +@export var display_time = 4.0 +@export var fade_duration = 1.0 + +var label: Label # 显式声明类型 + +func _ready(): + # 确保获取Label节点 + label = find_child("Label") as Label + if not label: + push_error("找不到Label子节点!请检查场景结构") + +func setup(text: String, color: Color, duration: float, fade: float): + display_time = duration + fade_duration = fade + # 确保添加到场景树 + Engine.get_main_loop().root.add_child(self) + Toast(text, color) func Toast(text: String, text_color: Color = Color.WHITE): + if !label: + return + label.text = text label.modulate = text_color show() - modulate.a = 1 # 确保初始透明度为 1 - await get_tree().create_timer(display_time).timeout # 等待显示时间 - await fade_out() # 开始渐隐 - -func fade_out() -> void: - var fade_step = 1.0 / (fade_duration / 60) # 每帧减少的透明度 - while modulate.a > 0: - modulate.a -= fade_step - if modulate.a < 0: - modulate.a = 0 - await get_tree().create_timer(0).timeout # 等待下一帧 - hide() # 完全透明时隐藏面板 + modulate.a = 1 + + await get_tree().create_timer(display_time).timeout + + var tween = create_tween() + tween.tween_property(self, "modulate:a", 0.0, fade_duration) + await tween.finished + queue_free() diff --git a/components/toast.gd b/components/toast.gd new file mode 100644 index 0000000..91dfd04 --- /dev/null +++ b/components/toast.gd @@ -0,0 +1,12 @@ +# toast.gd +extends Node + +const ToastScene = preload("res://components/ToastShow.tscn") + +static func show(text: String, + color: Color = Color.WHITE, + duration: float = 3.0, + fade: float = 1.0) -> void: + var toast = ToastScene.instantiate() + # 延迟设置参数确保节点初始化完成 + toast.call_deferred("setup", text, color, duration, fade) diff --git a/components/toast.tscn b/components/toast.tscn new file mode 100644 index 0000000..c494d4b --- /dev/null +++ b/components/toast.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://cvip7owyfmqav"] + +[ext_resource type="Script" path="res://components/toast.gd" id="1_rdgmi"] + +[node name="Toast" type="Node"] +script = ExtResource("1_rdgmi") diff --git a/project.godot b/project.godot index 9049a47..eaa3a84 100644 --- a/project.godot +++ b/project.godot @@ -13,9 +13,13 @@ config_version=5 config/name="萌芽农场" config/description="一款支持多人联机的农场游戏" run/main_scene="res://MainGame.tscn" -config/features=PackedStringArray("4.2", "Mobile") +config/features=PackedStringArray("4.3", "Mobile") config/icon="res://assets/logo2.png" +[autoload] + +Toast="*res://components/toast.gd" + [display] window/size/resizable=false @@ -28,12 +32,12 @@ window/vsync/vsync_mode=0 ui_save={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) ] } ui_load={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":108,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":108,"location":0,"echo":false,"script":null) ] } diff --git a/Servers/Players/123456.json b/server/game_saves/1242423.json similarity index 98% rename from Servers/Players/123456.json rename to server/game_saves/1242423.json index 18e07d5..cc58c0e 100644 --- a/Servers/Players/123456.json +++ b/server/game_saves/1242423.json @@ -322,9 +322,9 @@ "max_grow_time": 5 } ], - "farm_name": "唐译", + "farm_name": "1234", "level": 0, "money": 1000, - "user_name": "123456", - "user_password": "123456" + "user_name": "1242423", + "user_password": "1234" } \ No newline at end of file diff --git a/Servers/Players/3205788256.json b/server/game_saves/3205788256.json similarity index 79% rename from Servers/Players/3205788256.json rename to server/game_saves/3205788256.json index c70217f..6bbeb28 100644 --- a/Servers/Players/3205788256.json +++ b/server/game_saves/3205788256.json @@ -1,302 +1,6 @@ { - "experience": 1626, + "experience": 2407, "farm_lots": [ - { - "crop_type": "人参", - "grow_time": 6600, - "is_dead": true, - "is_diged": true, - "is_planted": true, - "max_grow_time": 6600 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 4800 - }, - { - "crop_type": "松露", - "grow_time": 7200, - "is_dead": true, - "is_diged": true, - "is_planted": true, - "max_grow_time": 7200 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 1200 - }, - { - "crop_type": "西瓜", - "grow_time": 2400, - "is_dead": true, - "is_diged": true, - "is_planted": true, - "max_grow_time": 2400 - }, - { - "crop_type": "葡萄", - "grow_time": 1200, - "is_dead": true, - "is_diged": true, - "is_planted": true, - "max_grow_time": 1200 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "西瓜", - "grow_time": 2400, - "is_dead": true, - "is_diged": true, - "is_planted": true, - "max_grow_time": 2400 - }, - { - "crop_type": "西瓜", - "grow_time": 1906, - "is_dead": false, - "is_diged": true, - "is_planted": true, - "max_grow_time": 2400 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "甜菜", - "grow_time": 1903, - "is_dead": false, - "is_diged": true, - "is_planted": true, - "max_grow_time": 2160 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": false, - "is_planted": false, - "max_grow_time": 5 - }, - { - "crop_type": "", - "grow_time": 0, - "is_dead": false, - "is_diged": true, - "is_planted": false, - "max_grow_time": 3 - }, - { - "crop_type": "金橘", - "grow_time": 1900, - "is_dead": true, - "is_diged": true, - "is_planted": true, - "max_grow_time": 4800 - }, { "crop_type": "", "grow_time": 0, @@ -311,7 +15,287 @@ "is_dead": false, "is_diged": true, "is_planted": false, - "max_grow_time": 4800 + "max_grow_time": 3 + }, + { + "crop_type": "草莓", + "grow_time": 33, + "is_dead": false, + "is_diged": true, + "is_planted": true, + "max_grow_time": 960 + }, + { + "crop_type": "测试作物", + "grow_time": 3, + "is_dead": false, + "is_diged": true, + "is_planted": true, + "max_grow_time": 3 + }, + { + "crop_type": "小麦", + "grow_time": 3, + "is_dead": false, + "is_diged": true, + "is_planted": true, + "max_grow_time": 120 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "花椰菜", + "grow_time": 132, + "is_dead": false, + "is_diged": true, + "is_planted": true, + "max_grow_time": 960 + }, + { + "crop_type": "花椰菜", + "grow_time": 129, + "is_dead": false, + "is_diged": true, + "is_planted": true, + "max_grow_time": 960 }, { "crop_type": "", @@ -319,12 +303,28 @@ "is_dead": false, "is_diged": true, "is_planted": false, - "max_grow_time": 4800 + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 } ], "farm_name": "", - "level": 24, - "money": 35261, + "level": 4, + "money": 30596, "user_name": "3205788256", "user_password": "tyh@19900420" } \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 0000000..01a9926 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,923 @@ +{ + "name": "Servers", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "chalk": "^4.1.2", + "cors": "^2.8.5", + "express": "^4.21.2" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..1e29ab3 --- /dev/null +++ b/server/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "chalk": "^4.1.2", + "cors": "^2.8.5", + "express": "^4.21.2" + } +} diff --git a/Servers/player.js b/server/player.js similarity index 100% rename from Servers/player.js rename to server/player.js diff --git a/server/server.js b/server/server.js new file mode 100644 index 0000000..1de4a2c --- /dev/null +++ b/server/server.js @@ -0,0 +1,199 @@ +const express = require('express'); +const fs = require('fs'); +const path = require('path'); +const bodyParser = require('body-parser'); +const cors = require('cors'); +const chalk = require('chalk'); // 用于控制台颜色 + +// 创建 Express 应用 +const app = express(); +const PORT = 3000; + +// 配置中间件 +app.use(cors()); // 允许跨域资源共享 +app.use(bodyParser.json()); // 解析 JSON 请求体 + +// 服务器存储目录,模拟远程存储位置 +const SERVER_STORAGE_PATH = path.join(__dirname, 'game_saves'); + +// 确保存储目录存在 +if (!fs.existsSync(SERVER_STORAGE_PATH)) { + fs.mkdirSync(SERVER_STORAGE_PATH); +} + +// 日志记录函数 +function logServer(message) { + const timestamp = new Date().toLocaleTimeString(); + console.log(chalk.gray(`[${timestamp}] `) + chalk.cyan('[服务器] ') + message); +} + +function logPlayer(player, message) { + const timestamp = new Date().toLocaleTimeString(); + console.log(chalk.gray(`[${timestamp}] `) + chalk.yellow(`[${player}] `) + message); +} + +function logWarning(message) { + const timestamp = new Date().toLocaleTimeString(); + console.log(chalk.gray(`[${timestamp}] `) + chalk.yellow('[警告] ') + message); +} + +function logError(message) { + const timestamp = new Date().toLocaleTimeString(); + console.log(chalk.gray(`[${timestamp}] `) + chalk.red('[错误] ') + message); +} + +/** + * 登录路由 + * @route POST /login + * @param {string} req.body.user_name - 用户名 + * @param {string} req.body.user_password - 用户密码 + * @returns {Object} 登录结果 + */ +app.post('/login', (req, res) => { + try { + const { user_name, user_password } = req.body; + + if (!user_name || !user_password) { + logWarning(`登录尝试失败: 用户名或密码为空`); + return res.json({ + message: '用户名和密码不能为空' + }); + } + + const filePath = path.join(SERVER_STORAGE_PATH, `${user_name}.json`); + + if (!fs.existsSync(filePath)) { + logWarning(`登录失败: 用户 ${user_name} 不存在`); + return res.json({ + message: '用户不存在' + }); + } + + const fileContent = fs.readFileSync(filePath, 'utf8'); + const userData = JSON.parse(fileContent); + + if (userData.user_password !== user_password) { + logWarning(`用户 ${user_name} 登录失败: 密码错误`); + return res.json({ + message: '密码错误' + }); + } + + logPlayer(user_name, '成功登录游戏'); + res.json({ + message: '登录成功', + data: userData + }); + } catch (error) { + logError(`登录过程发生错误: ${error.message}`); + res.json({ + message: '服务器错误', + error: error.message + }); + } +}); + +/** + * 注册路由 + * @route POST /register + * @param {string} req.body.user_name - 用户名 + * @param {string} req.body.user_password - 用户密码 + * @param {string} req.body.farm_name - 农场名称 + * @returns {Object} 注册结果 + */ +app.post('/register', (req, res) => { + try { + const { user_name, user_password, farm_name } = req.body; + + if (!user_name || !user_password || !farm_name) { + logWarning(`注册失败: 注册信息不完整`); + return res.json({ + message: '注册信息不完整' + }); + } + + const filePath = path.join(SERVER_STORAGE_PATH, `${user_name}.json`); + + if (fs.existsSync(filePath)) { + logWarning(`注册失败: 用户名 ${user_name} 已存在`); + return res.json({ + message: '用户名已存在' + }); + } + + fs.writeFileSync(filePath, JSON.stringify(req.body, null, 2), 'utf8'); + logPlayer(user_name, `注册成功,农场名称: ${farm_name}`); + + res.json({ + message: '注册成功' + }); + } catch (error) { + logError(`注册过程发生错误: ${error.message}`); + res.json({ + message: '服务器错误', + error: error.message + }); + } +}); + +/** + * 保存游戏数据 + * @route POST /save + * @param {string} req.body.user_name - 用户名 + * @param {Object} req.body - 游戏保存数据 + * @returns {Object} 保存结果 + */ +app.post('/save', (req, res) => { + try { + const { user_name, money, level, experience } = req.body; + + if (!user_name) { + logWarning(`保存失败: 用户名为空`); + return res.json({ + message: '用户名不能为空' + }); + } + + const filePath = path.join(SERVER_STORAGE_PATH, `${user_name}.json`); + fs.writeFileSync(filePath, JSON.stringify(req.body, null, 2), 'utf8'); + + logPlayer(user_name, `保存游戏数据 [金钱: ${money}, 等级: ${level}, 经验: ${experience}]`); + res.json({ + message: '保存成功' + }); + } catch (error) { + logError(`保存游戏数据时发生错误: ${error.message}`); + res.json({ + message: '服务器错误', + error: error.message + }); + } +}); + +/** + * 服务器健康检查路由 + * @route GET /health + * @returns {Object} 服务器状态 + */ +app.get('/health', (req, res) => { + logServer('收到健康检查请求'); + res.json({ + status: 'healthy', + message: 'Godot农场游戏服务器正在运行' + }); +}); + +// 启动服务器 +app.listen(PORT, () => { + logServer(chalk.green('农场游戏服务器启动成功')); + logServer(`监听端口: ${PORT}`); + logServer(`存储路径: ${SERVER_STORAGE_PATH}`); + logServer('等待玩家连接...'); +}); + +// 优雅关闭服务器 +process.on('SIGINT', () => { + logServer(chalk.yellow('正在关闭服务器...')); + // 这里可以添加一些清理工作 + process.exit(); +}); \ No newline at end of file diff --git a/server/start.bat b/server/start.bat new file mode 100644 index 0000000..3159c46 --- /dev/null +++ b/server/start.bat @@ -0,0 +1,5 @@ +@echo off +chcp 65001 +title 启动 Node.js 服务器 +node server.js +pause diff --git a/server/start.sh b/server/start.sh new file mode 100644 index 0000000..9d26261 --- /dev/null +++ b/server/start.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo "正在启动服务器..." +node server.js +echo "服务器已启动。"