From 09b1f19a8f700485a4e868f6b6b9c0564554b3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A0=91=E8=90=8C=E8=8A=BD?= <3205788256@qq.com> Date: Sat, 12 Jul 2025 21:08:36 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A8=8D=E5=BE=AE=E4=BC=98=E5=8C=96=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=8B=E7=AD=BE=E5=88=B0=E7=B3=BB=E7=BB=9F=E5=92=8C?= =?UTF-8?q?=E6=8A=BD=E5=A5=96=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MainGame.gd | 2 +- MainGame.tscn | 51 +- Scene/Particle/snow.tscn | 37 ++ Script/BigPanel/DailyCheckInPanel.gd | 296 ++------- Script/BigPanel/LuckyDrawPanel.gd | 293 +++------ Server/TCPGameServer.py | 769 ++++++++++++------------ Server/config/daily_checkin_config.json | 82 +++ Server/config/lucky_draw_config.json | 113 ++++ Server/game_saves/2143323382.json | 317 +--------- server/game_saves/3205788256.json | 15 +- 10 files changed, 791 insertions(+), 1184 deletions(-) create mode 100644 Scene/Particle/snow.tscn create mode 100644 Server/config/daily_checkin_config.json create mode 100644 Server/config/lucky_draw_config.json diff --git a/MainGame.gd b/MainGame.gd index 725a532..9a3fd05 100644 --- a/MainGame.gd +++ b/MainGame.gd @@ -1984,7 +1984,7 @@ func _handle_daily_check_in_response(response: Dictionary) -> void: player_bag_panel.update_player_bag_ui() # 向签到面板传递响应 - daily_check_in_panel.handle_check_in_response(response) + daily_check_in_panel.handle_daily_check_in_response(response) # 显示签到结果通知 var success = response.get("success", false) diff --git a/MainGame.tscn b/MainGame.tscn index 72cebc4..ff32014 100644 --- a/MainGame.tscn +++ b/MainGame.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=67 format=3 uid="uid://dgh61dttaas5a"] +[gd_scene load_steps=72 format=3 uid="uid://dgh61dttaas5a"] [ext_resource type="Script" uid="uid://2pt11sfcaxf7" path="res://MainGame.gd" id="1_v3yaj"] [ext_resource type="Texture2D" uid="uid://du2pyiojliasy" path="res://assets/游戏UI/经验球.webp" id="2_6jgly"] @@ -136,6 +136,34 @@ scale_min = 0.5 scale_max = 0.5 turbulence_enabled = true +[sub_resource type="Curve" id="Curve_4ka7t"] +_data = [Vector2(0, 0.951807), 0.0, 0.0, 0, 0, Vector2(0.0153846, 1), 0.0, 0.0, 0, 0, Vector2(0.0461538, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 4 + +[sub_resource type="CurveTexture" id="CurveTexture_nf3jg"] +curve = SubResource("Curve_4ka7t") + +[sub_resource type="Gradient" id="Gradient_adtqp"] +offsets = PackedFloat32Array(0.52, 0.697143) +colors = PackedColorArray(1, 1, 1, 0.352941, 1, 1, 1, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_5dq3w"] +gradient = SubResource("Gradient_adtqp") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_jiccn"] +lifetime_randomness = 0.07 +particle_flag_disable_z = true +emission_shape = 3 +emission_box_extents = Vector3(1000, 1, 1) +gravity = Vector3(46, 80, 0) +scale_min = 0.2 +scale_max = 0.3 +color_initial_ramp = SubResource("GradientTexture1D_5dq3w") +alpha_curve = SubResource("CurveTexture_nf3jg") +turbulence_enabled = true +turbulence_influence_min = 0.02 +turbulence_influence_max = 0.08 + [node name="main" type="Node"] script = ExtResource("1_v3yaj") @@ -4249,15 +4277,6 @@ vertical_alignment = 1 [node name="WeatherSystem" type="Node2D" parent="."] -[node name="Snow" type="GPUParticles2D" parent="WeatherSystem"] -position = Vector2(-170, -272) -amount = 16 -sub_emitter = NodePath(".") -texture = ExtResource("53_4ka7t") -lifetime = 15.0 -randomness = 0.5 -process_material = SubResource("ParticleProcessMaterial_nf3jg") - [node name="Rain" type="GPUParticles2D" parent="WeatherSystem"] visible = false position = Vector2(-170, -272) @@ -4268,6 +4287,18 @@ lifetime = 15.0 randomness = 0.5 process_material = SubResource("ParticleProcessMaterial_nf3jg") +[node name="Snow" type="GPUParticles2D" parent="WeatherSystem"] +z_index = 10 +position = Vector2(249, -262) +amount = 300 +texture = ExtResource("53_4ka7t") +lifetime = 15.0 +preprocess = 30.0 +visibility_rect = Rect2(-900, 0, 2000, 2000) +trail_sections = 2 +trail_section_subdivisions = 1 +process_material = SubResource("ParticleProcessMaterial_jiccn") + [node name="DayNightSystem" type="Node2D" parent="."] [connection signal="pressed" from="UI/GUI/GameInfoHBox3/WatchBroadcast" to="." method="_on_watch_broadcast_button_pressed"] diff --git a/Scene/Particle/snow.tscn b/Scene/Particle/snow.tscn new file mode 100644 index 0000000..08cdda5 --- /dev/null +++ b/Scene/Particle/snow.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=7 format=3 uid="uid://b5j2tonaoiku5"] + +[ext_resource type="Texture2D" uid="uid://dk4yl4ghmxaa2" path="res://assets/天气系统图片/雪花.webp" id="1_nqr5d"] + +[sub_resource type="Curve" id="Curve_4ka7t"] +_data = [Vector2(0, 0.951807), 0.0, 0.0, 0, 0, Vector2(0.0153846, 1), 0.0, 0.0, 0, 0, Vector2(0.0461538, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 4 + +[sub_resource type="CurveTexture" id="CurveTexture_nf3jg"] +curve = SubResource("Curve_4ka7t") + +[sub_resource type="Gradient" id="Gradient_adtqp"] +offsets = PackedFloat32Array(0.52, 0.697143) +colors = PackedColorArray(1, 1, 1, 0.352941, 1, 1, 1, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_5dq3w"] +gradient = SubResource("Gradient_adtqp") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_jiccn"] +particle_flag_disable_z = true +emission_shape = 3 +emission_box_extents = Vector3(1000, 1, 1) +gravity = Vector3(45, 98, 0) +scale_min = 0.4 +scale_max = 0.8 +color_initial_ramp = SubResource("GradientTexture1D_5dq3w") +alpha_curve = SubResource("CurveTexture_nf3jg") +turbulence_enabled = true +turbulence_influence_min = 0.02 +turbulence_influence_max = 0.08 + +[node name="Snow" type="GPUParticles2D"] +amount = 200 +texture = ExtResource("1_nqr5d") +lifetime = 10.0 +preprocess = 30.0 +process_material = SubResource("ParticleProcessMaterial_jiccn") diff --git a/Script/BigPanel/DailyCheckInPanel.gd b/Script/BigPanel/DailyCheckInPanel.gd index 6dd8efb..46a419c 100644 --- a/Script/BigPanel/DailyCheckInPanel.gd +++ b/Script/BigPanel/DailyCheckInPanel.gd @@ -1,136 +1,31 @@ extends Panel class_name DailyCheckInPanel -## 每日签到系统 - 后端对接版本 -## 功能:与服务器对接的签到系统,支持实时数据同步 -## 奖励平衡性已根据 crop_data.json 调整 +signal check_in_completed(rewards: Dictionary) +signal check_in_failed(error_message: String) -# ============================================================================= -# 信号定义 - 用于与后端系统通信 -# ============================================================================= -signal check_in_completed(rewards: Dictionary) # 签到完成信号 -signal reward_claimed(reward_type: String, amount: int) # 奖励领取信号 -signal check_in_data_loaded(data: Dictionary) # 签到数据加载完成信号 -signal check_in_failed(error_message: String) # 签到失败信号 - -# ============================================================================= -# 节点引用 -# ============================================================================= @onready var daily_check_in_history: RichTextLabel = $Scroll/DailyCheckInHistory @onready var daily_check_in_reward: RichTextLabel = $DailyCheckInReward @onready var daily_check_in_button: Button = $DailyCheckInButton +@onready var main_game = get_node("/root/main") +@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel' -# ============================================================================= -# 数据存储 -# ============================================================================= -var check_in_data: Dictionary = {} -var today_date: String +var check_in_history: Dictionary = {} var consecutive_days: int = 0 var has_checked_in_today: bool = false -# 网络管理器引用 -@onready var main_game = get_node("/root/main") - -@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel' -@onready var daily_check_in_panel: DailyCheckInPanel = $'.' -@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel' -@onready var item_store_panel: Panel = $'../ItemStorePanel' -@onready var item_bag_panel: Panel = $'../ItemBagPanel' -@onready var player_bag_panel: Panel = $'../PlayerBagPanel' -@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel' -@onready var crop_store_panel: Panel = $'../CropStorePanel' -@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel' -@onready var login_panel: PanelContainer = $'../LoginPanel' - - -# ============================================================================= -# 奖励配置系统 - 根据 crop_data.json 平衡调整 -# ============================================================================= -var reward_configs: Dictionary = { - "coins": { - "min": 200, - "max": 500, - "name": "钱币", - "color": "#FFD700", - "icon": "💰" - }, - "exp": { - "min": 50, - "max": 120, - "name": "经验", - "color": "#00BFFF", - "icon": "⭐" - }, - # 种子配置根据 crop_data.json 的作物等级和价值设定 - "seeds": { - "普通": [ - {"name": "小麦", "color": "#F4A460", "icon": "🌱", "rarity_color": "#FFFFFF"}, - {"name": "胡萝卜", "color": "#FFA500", "icon": "🌱", "rarity_color": "#FFFFFF"}, - {"name": "土豆", "color": "#D2691E", "icon": "🌱", "rarity_color": "#FFFFFF"}, - {"name": "稻谷", "color": "#DAA520", "icon": "🌱", "rarity_color": "#FFFFFF"} - ], - "优良": [ - {"name": "玉米", "color": "#FFD700", "icon": "🌱", "rarity_color": "#00FF00"}, - {"name": "番茄", "color": "#FF6347", "icon": "🌱", "rarity_color": "#00FF00"}, - {"name": "洋葱", "color": "#DDA0DD", "icon": "🌱", "rarity_color": "#00FF00"}, - {"name": "大豆", "color": "#8FBC8F", "icon": "🌱", "rarity_color": "#00FF00"}, - {"name": "豌豆", "color": "#90EE90", "icon": "🌱", "rarity_color": "#00FF00"}, - {"name": "黄瓜", "color": "#32CD32", "icon": "🌱", "rarity_color": "#00FF00"}, - {"name": "大白菜", "color": "#F0FFF0", "icon": "🌱", "rarity_color": "#00FF00"} - ], - "稀有": [ - {"name": "草莓", "color": "#FF69B4", "icon": "🌱", "rarity_color": "#0080FF"}, - {"name": "花椰菜", "color": "#F5F5DC", "icon": "🌱", "rarity_color": "#0080FF"}, - {"name": "柿子", "color": "#FF4500", "icon": "🌱", "rarity_color": "#0080FF"}, - {"name": "蓝莓", "color": "#4169E1", "icon": "🌱", "rarity_color": "#0080FF"}, - {"name": "树莓", "color": "#DC143C", "icon": "🌱", "rarity_color": "#0080FF"} - ], - "史诗": [ - {"name": "葡萄", "color": "#9370DB", "icon": "🌱", "rarity_color": "#8A2BE2"}, - {"name": "南瓜", "color": "#FF8C00", "icon": "🌱", "rarity_color": "#8A2BE2"}, - {"name": "芦笋", "color": "#9ACD32", "icon": "🌱", "rarity_color": "#8A2BE2"}, - {"name": "茄子", "color": "#9400D3", "icon": "🌱", "rarity_color": "#8A2BE2"}, - {"name": "向日葵", "color": "#FFD700", "icon": "🌱", "rarity_color": "#8A2BE2"}, - {"name": "蕨菜", "color": "#228B22", "icon": "🌱", "rarity_color": "#8A2BE2"} - ], - "传奇": [ - {"name": "西瓜", "color": "#FF69B4", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "甘蔗", "color": "#DDA0DD", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "香草", "color": "#98FB98", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "甜菜", "color": "#DC143C", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "人参", "color": "#DAA520", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "富贵竹", "color": "#32CD32", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "芦荟", "color": "#9ACD32", "icon": "🌱", "rarity_color": "#FF8C00"}, - {"name": "哈密瓜", "color": "#FFB6C1", "icon": "🌱", "rarity_color": "#FF8C00"} - ] - } -} - -# ============================================================================= -# 系统初始化 -# ============================================================================= func _ready() -> void: + visibility_changed.connect(_on_visibility_changed) _initialize_system() func _initialize_system() -> void: - """初始化签到系统""" daily_check_in_reward.hide() - today_date = Time.get_date_string_from_system() - - - _update_display() _check_daily_status() - # 从服务器加载签到数据 if tcp_network_manager_panel and tcp_network_manager_panel.is_connected_to_server(): tcp_network_manager_panel.sendGetCheckInData() -# ============================================================================= -# 网络后端交互方法 -# ============================================================================= - -## 处理服务器签到响应 func handle_daily_check_in_response(response: Dictionary) -> void: var success = response.get("success", false) var message = response.get("message", "") @@ -140,71 +35,39 @@ func handle_daily_check_in_response(response: Dictionary) -> void: consecutive_days = response.get("consecutive_days", 0) has_checked_in_today = true - # 显示奖励 _show_reward_animation(rewards) - - # 更新按钮状态 _set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1)) - # 发送完成信号 check_in_completed.emit(rewards) - - # 发送奖励信号 - for reward_type in rewards.keys(): - if reward_type == "seeds": - for seed_reward in rewards.seeds: - reward_claimed.emit("seed_" + seed_reward.name, seed_reward.quantity) - elif reward_type in ["coins", "exp", "bonus_coins", "bonus_exp"]: - reward_claimed.emit(reward_type, rewards[reward_type]) - Toast.show(message, Color.GREEN) - print("签到成功: ", message) else: has_checked_in_today = response.get("has_checked_in", false) _set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1)) if has_checked_in_today else _set_button_state(true, "签到", Color(1, 1, 0.52549, 1)) check_in_failed.emit(message) Toast.show(message, Color.RED) - print("签到失败: ", message) -## 处理服务器签到数据响应 func handle_check_in_data_response(response: Dictionary) -> void: var success = response.get("success", false) if success: - check_in_data = response.get("check_in_data", {}) + check_in_history = response.get("check_in_data", {}) consecutive_days = response.get("consecutive_days", 0) has_checked_in_today = response.get("has_checked_in_today", false) - today_date = response.get("current_date", Time.get_date_string_from_system()) - # 更新显示 _update_display() _check_daily_status() - - # 发送数据加载完成信号 - check_in_data_loaded.emit(check_in_data) - - print("签到数据加载成功,连续签到:", consecutive_days, "天") - else: - print("加载签到数据失败") -# ============================================================================= -# 核心业务逻辑 -# ============================================================================= - -## 检查今日签到状态 func _check_daily_status() -> void: if has_checked_in_today: _set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1)) else: _set_button_state(true, "签到", Color(1, 1, 0.52549, 1)) -## 设置按钮状态 func _set_button_state(enabled: bool, text: String, color: Color) -> void: daily_check_in_button.disabled = not enabled daily_check_in_button.text = text daily_check_in_button.modulate = color -## 执行签到 func execute_check_in() -> void: if has_checked_in_today: Toast.show("今日已签到,请明日再来", Color.ORANGE) @@ -214,41 +77,30 @@ func execute_check_in() -> void: Toast.show("未连接到服务器,无法签到", Color.RED) return - # 发送签到请求到服务器 tcp_network_manager_panel.sendDailyCheckIn() daily_check_in_button.disabled = true daily_check_in_button.text = "签到中..." - # 3秒后重新启用按钮(防止网络超时) await get_tree().create_timer(3.0).timeout if daily_check_in_button.disabled and daily_check_in_button.text == "签到中...": daily_check_in_button.disabled = false daily_check_in_button.text = "签到" -## 显示奖励动画 func _show_reward_animation(rewards: Dictionary) -> void: daily_check_in_reward.text = _format_reward_text(rewards) daily_check_in_reward.show() - # 创建动画效果 var tween = create_tween() tween.parallel().tween_method(_animate_reward_display, 0.0, 1.0, 0.5) -## 奖励显示动画 func _animate_reward_display(progress: float) -> void: daily_check_in_reward.modulate.a = progress var scale = 0.8 + (0.2 * progress) daily_check_in_reward.scale = Vector2(scale, scale) -# ============================================================================= -# UI显示格式化 -# ============================================================================= - -## 格式化奖励显示文本 func _format_reward_text(rewards: Dictionary) -> String: var text = "" - # 显示连续签到信息 text += "[center][color=#FF69B4]🔥 连续签到第%d天 🔥[/color][/center]\n" % consecutive_days if consecutive_days > 1: var multiplier = 1.0 + (consecutive_days - 1) * 0.1 @@ -257,58 +109,32 @@ func _format_reward_text(rewards: Dictionary) -> String: else: text += "\n" - # 基础奖励 if rewards.has("coins"): - text += "[color=%s]%s +%d %s[/color]\n" % [ - reward_configs.coins.color, - reward_configs.coins.icon, - rewards.coins, - reward_configs.coins.name - ] + text += "[color=#FFD700]💰 +%d 金币[/color]\n" % rewards.coins if rewards.has("exp"): - text += "[color=%s]%s +%d %s[/color]\n" % [ - reward_configs.exp.color, - reward_configs.exp.icon, - rewards.exp, - reward_configs.exp.name - ] + text += "[color=#00BFFF]⭐ +%d 经验[/color]\n" % rewards.exp - # 种子奖励 if rewards.has("seeds") and rewards.seeds.size() > 0: for seed_reward in rewards.seeds: var seed_name = seed_reward.name var quantity = seed_reward.quantity var quality = seed_reward.quality + var rarity_color = _get_rarity_color(quality) - # 从配置中找到对应的种子信息 - var seed_info = _get_seed_info(seed_name, quality) - if seed_info: - text += "[color=%s]%s[/color] [color=%s]%s[/color] x%d [color=%s](%s)[/color]\n" % [ - seed_info.color, seed_info.icon, seed_info.color, seed_name, quantity, seed_info.rarity_color, quality - ] + text += "[color=%s]🌱 %s x%d[/color] [color=%s](%s)[/color]\n" % [ + rarity_color, seed_name, quantity, rarity_color, quality + ] - # 连续签到额外奖励 if rewards.has("bonus_coins"): text += "\n[color=#FFD700]🎁 连续签到奖励:[/color]\n" - text += "[color=%s]%s +%d %s[/color] [color=#FFD700]✨[/color]\n" % [ - reward_configs.coins.color, - reward_configs.coins.icon, - rewards.bonus_coins, - reward_configs.coins.name - ] + text += "[color=#FFD700]💰 +%d 额外金币[/color] [color=#FFD700]✨[/color]\n" % rewards.bonus_coins if rewards.has("bonus_exp"): if not rewards.has("bonus_coins"): text += "\n[color=#FFD700]🎁 连续签到奖励:[/color]\n" - text += "[color=%s]%s +%d %s[/color] [color=#FFD700]✨[/color]\n" % [ - reward_configs.exp.color, - reward_configs.exp.icon, - rewards.bonus_exp, - reward_configs.exp.name - ] + text += "[color=#00BFFF]⭐ +%d 额外经验[/color] [color=#FFD700]✨[/color]\n" % rewards.bonus_exp - # 下一个奖励预告 var next_bonus_day = 0 if consecutive_days < 3: next_bonus_day = 3 @@ -318,6 +144,8 @@ func _format_reward_text(rewards: Dictionary) -> String: next_bonus_day = 14 elif consecutive_days < 21: next_bonus_day = 21 + elif consecutive_days < 30: + next_bonus_day = 30 if next_bonus_day > 0: var days_needed = next_bonus_day - consecutive_days @@ -325,52 +153,18 @@ func _format_reward_text(rewards: Dictionary) -> String: return text -## 获取种子信息 -func _get_seed_info(seed_name: String, quality: String) -> Dictionary: - if quality in reward_configs.seeds: - for seed in reward_configs.seeds[quality]: - if seed.name == seed_name: - return seed - return {} +func _get_rarity_color(rarity: String) -> String: + match rarity: + "普通": return "#90EE90" + "优良": return "#87CEEB" + "稀有": return "#DDA0DD" + "史诗": return "#9932CC" + "传奇": return "#FF8C00" + _: return "#FFFFFF" -## 格式化历史记录文本 -func _format_history_text(date: String, rewards: Dictionary) -> String: - var text = "[color=#87CEEB]📅 %s[/color] " % date - - var reward_parts = [] - if rewards.has("coins"): - reward_parts.append("[color=%s]%s %d[/color]" % [ - reward_configs.coins.color, - reward_configs.coins.name, - rewards.coins - ]) - - if rewards.has("exp"): - reward_parts.append("[color=%s]%s %d[/color]" % [ - reward_configs.exp.color, - reward_configs.exp.name, - rewards.exp - ]) - - if rewards.has("seeds") and rewards.seeds.size() > 0: - for seed_reward in rewards.seeds: - var seed_name = seed_reward.name - var quantity = seed_reward.quantity - var quality = seed_reward.quality - var seed_info = _get_seed_info(seed_name, quality) - if seed_info: - reward_parts.append("[color=%s]%s x%d[/color]" % [ - seed_info.color, seed_name, quantity - ]) - - text += " ".join(reward_parts) - return text - -## 更新显示内容 func _update_display() -> void: var history_text = "[center][color=#FFB6C1]📋 签到历史[/color][/center]\n" - # 显示连续签到状态 if consecutive_days > 0: history_text += "[center][color=#FF69B4]🔥 当前连续签到: %d天[/color][/center]\n" % consecutive_days if consecutive_days >= 30: @@ -380,61 +174,43 @@ func _update_display() -> void: history_text += "\n" - if check_in_data.size() == 0: + if check_in_history.size() == 0: history_text += "[center][color=#DDDDDD]暂无签到记录[/color][/center]" else: - # 按日期排序显示历史记录 - var sorted_dates = check_in_data.keys() - sorted_dates.sort() - sorted_dates.reverse() # 最新的在前 + # 按时间排序显示历史记录 + var sorted_times = check_in_history.keys() + sorted_times.sort() + sorted_times.reverse() - for date in sorted_dates: - var day_data = check_in_data[date] - var rewards = day_data.get("rewards", {}) - var day_consecutive = day_data.get("consecutive_days", 1) - - history_text += _format_history_text(date, rewards) - history_text += " [color=#90EE90](连续%d天)[/color]\n" % day_consecutive - history_text += "-----------------------------------------------------------------------------------------------------------------\n" + for time_key in sorted_times: + var reward_text = check_in_history[time_key] + history_text += "[color=#87CEEB]%s[/color] [color=#90EE90]%s[/color]\n" % [time_key, reward_text] + history_text += "---------------------------------------------\n" daily_check_in_history.text = history_text -# ============================================================================= # 事件处理 -# ============================================================================= - -## 关闭面板按钮 func _on_quit_button_pressed() -> void: self.hide() -## 签到按钮 func _on_daily_check_in_button_pressed() -> void: execute_check_in() - -#面板显示与隐藏切换处理 func _on_visibility_changed(): if visible: GlobalVariables.isZoomDisabled = true - pass else: GlobalVariables.isZoomDisabled = false - pass -# ============================================================================= -# 公共接口方法 - 供主游戏调用 -# ============================================================================= -## 刷新签到数据 +# 公共接口 func refresh_check_in_data() -> void: if tcp_network_manager_panel and tcp_network_manager_panel.is_connected_to_server(): tcp_network_manager_panel.sendGetCheckInData() -## 获取当前签到状态 func get_check_in_status() -> Dictionary: return { "has_checked_in_today": has_checked_in_today, - "consecutive_days": consecutive_days, - "today_date": today_date + "consecutive_days": consecutive_days } diff --git a/Script/BigPanel/LuckyDrawPanel.gd b/Script/BigPanel/LuckyDrawPanel.gd index 55342a6..17d8802 100644 --- a/Script/BigPanel/LuckyDrawPanel.gd +++ b/Script/BigPanel/LuckyDrawPanel.gd @@ -1,79 +1,46 @@ extends Panel class_name LuckyDrawPanel +signal draw_completed(rewards: Array, draw_type: String) +signal draw_failed(error_message: String) -signal draw_completed(rewards: Array, draw_type: String) # 抽奖完成信号 -signal reward_obtained(reward_type: String, amount: int) # 奖励获得信号 -signal draw_failed(error_message: String) # 抽奖失败信号 - - -#这个展示抽奖获得的奖励 @onready var lucky_draw_reward: RichTextLabel = $LuckyDrawReward -#这个是展示有哪些奖励选项,最多15个,奖励就在这里面随机挑选 @onready var grid: GridContainer = $Grid -#这个是奖励模板 @onready var reward_item: RichTextLabel = $Grid/RewardItem +@onready var main_game = get_node("/root/main") +@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel' var reward_templates: Array[RichTextLabel] = [] var current_rewards: Array = [] -@onready var main_game = get_node("/root/main") - -@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel' -@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel' -@onready var item_store_panel: Panel = $'../ItemStorePanel' -@onready var item_bag_panel: Panel = $'../ItemBagPanel' -@onready var player_bag_panel: Panel = $'../PlayerBagPanel' -@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel' -@onready var crop_store_panel: Panel = $'../CropStorePanel' -@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel' -@onready var login_panel: PanelContainer = $'../LoginPanel' - - -# 15种不同的模板颜色 -var template_colors: Array[Color] = [ - Color(1.0, 0.8, 0.8, 1.0), # 淡红色 - Color(0.8, 1.0, 0.8, 1.0), # 淡绿色 - Color(0.8, 0.8, 1.0, 1.0), # 淡蓝色 - Color(1.0, 1.0, 0.8, 1.0), # 淡黄色 - Color(1.0, 0.8, 1.0, 1.0), # 淡紫色 - Color(0.8, 1.0, 1.0, 1.0), # 淡青色 - Color(1.0, 0.9, 0.8, 1.0), # 淡橙色 - Color(0.9, 0.8, 1.0, 1.0), # 淡紫蓝色 - Color(0.8, 1.0, 0.9, 1.0), # 淡薄荷色 - Color(1.0, 0.8, 0.9, 1.0), # 淡粉色 - Color(0.9, 1.0, 0.8, 1.0), # 淡柠檬色 - Color(0.8, 0.9, 1.0, 1.0), # 淡天蓝色 - Color(1.0, 0.95, 0.8, 1.0), # 淡香槟色 - Color(0.85, 0.8, 1.0, 1.0), # 淡薰衣草色 - Color(0.95, 1.0, 0.85, 1.0) # 淡春绿色 -] - +var seed_rewards: Dictionary = {} var anticipation_tween: Tween = null +# 15种模板颜色 +var template_colors: Array[Color] = [ + Color(1.0, 0.8, 0.8, 1.0), Color(0.8, 1.0, 0.8, 1.0), Color(0.8, 0.8, 1.0, 1.0), + Color(1.0, 1.0, 0.8, 1.0), Color(1.0, 0.8, 1.0, 1.0), Color(0.8, 1.0, 1.0, 1.0), + Color(1.0, 0.9, 0.8, 1.0), Color(0.9, 0.8, 1.0, 1.0), Color(0.8, 1.0, 0.9, 1.0), + Color(1.0, 0.8, 0.9, 1.0), Color(0.9, 1.0, 0.8, 1.0), Color(0.8, 0.9, 1.0, 1.0), + Color(1.0, 0.95, 0.8, 1.0), Color(0.85, 0.8, 1.0, 1.0), Color(0.95, 1.0, 0.85, 1.0) +] + var base_rewards: Dictionary = { "coins": {"name": "金币", "icon": "💰", "color": "#FFD700"}, "exp": {"name": "经验", "icon": "⭐", "color": "#00BFFF"}, "empty": {"name": "谢谢惠顾", "icon": "😅", "color": "#CCCCCC"} } -var seed_rewards: Dictionary = {} - -# 抽奖费用配置 var draw_costs: Dictionary = { "single": 800, - "five": 3600, # 800 * 5 * 0.9 = 3600 - "ten": 6400 # 800 * 10 * 0.8 = 6400 + "five": 3600, + "ten": 6400 } -var server_reward_pools: Dictionary = {} - func _ready() -> void: + visibility_changed.connect(_on_visibility_changed) _initialize_system() -#初始化抽奖系统 func _initialize_system() -> void: - - # 连接信号 if main_game: draw_completed.connect(main_game._on_lucky_draw_completed) draw_failed.connect(main_game._on_lucky_draw_failed) @@ -83,21 +50,18 @@ func _initialize_system() -> void: _generate_reward_templates() _update_template_display() -#从主游戏加载作物数据并构建种子奖励 func _load_crop_data_and_build_rewards() -> void: if main_game and main_game.has_method("get_crop_data"): var crop_data = main_game.get_crop_data() if crop_data: _build_seed_rewards_from_crop_data(crop_data) -#根据 crop_data.json 构建种子奖励配置 func _build_seed_rewards_from_crop_data(crop_data: Dictionary) -> void: seed_rewards.clear() for crop_name in crop_data.keys(): var crop_info = crop_data[crop_name] - # 跳过测试作物和不能购买的作物 if crop_name == "测试作物" or not crop_info.get("能否购买", true): continue @@ -105,59 +69,43 @@ func _build_seed_rewards_from_crop_data(crop_data: Dictionary) -> void: var rarity_color = _get_rarity_color(quality) seed_rewards[crop_name] = { - "icon": "🌱", - "color": rarity_color, + "icon": "🌱", + "color": rarity_color, "rarity": quality, "level": crop_info.get("等级", 1), "cost": crop_info.get("花费", 50) } -#根据稀有度获取颜色 func _get_rarity_color(rarity: String) -> String: match rarity: - "普通": - return "#90EE90" - "优良": - return "#87CEEB" - "稀有": - return "#DDA0DD" - "史诗": - return "#9932CC" - "传奇": - return "#FF8C00" - _: - return "#FFFFFF" + "普通": return "#90EE90" + "优良": return "#87CEEB" + "稀有": return "#DDA0DD" + "史诗": return "#9932CC" + "传奇": return "#FF8C00" + _: return "#FFFFFF" - -## 生成15个奖励模板 func _generate_reward_templates() -> void: - # 清空现有模板 for child in grid.get_children(): if child != reward_item: child.queue_free() reward_templates.clear() - # 生成15个模板(包括原有的一个) for i in range(15): var template: RichTextLabel if i == 0: - # 使用原有的模板 template = reward_item else: - # 创建新的模板 template = reward_item.duplicate() grid.add_child(template) - # 设置不同的颜色 template.self_modulate = template_colors[i] template.bbcode_enabled = true template.threaded = true - reward_templates.append(template) -## 更新模板显示 func _update_template_display() -> void: var sample_rewards = _generate_sample_rewards() @@ -170,16 +118,13 @@ func _update_template_display() -> void: else: template.hide() -## 生成示例奖励显示 func _generate_sample_rewards() -> Array: var sample_rewards = [] - # 添加基础奖励示例 sample_rewards.append({"type": "coins", "amount_range": [100, 300], "rarity": "普通"}) sample_rewards.append({"type": "exp", "amount_range": [50, 150], "rarity": "普通"}) sample_rewards.append({"type": "empty", "name": "谢谢惠顾", "rarity": "空奖"}) - # 添加各品质种子示例 var quality_examples = ["普通", "优良", "稀有", "史诗", "传奇"] for quality in quality_examples: var example_seeds = [] @@ -188,26 +133,22 @@ func _generate_sample_rewards() -> Array: example_seeds.append(seed_name) if example_seeds.size() > 0: - var seed_name = example_seeds[0] # 取第一个作为示例 + var seed_name = example_seeds[0] sample_rewards.append({ - "type": "seed", - "name": seed_name, + "type": "seed", + "name": seed_name, "rarity": quality, "amount_range": [1, 3] if quality != "传奇" else [1, 1] }) - # 添加礼包示例 sample_rewards.append({"type": "package", "name": "成长套餐", "rarity": "优良"}) sample_rewards.append({"type": "package", "name": "稀有礼包", "rarity": "稀有"}) sample_rewards.append({"type": "package", "name": "传奇大礼包", "rarity": "传奇"}) - - # 添加高级奖励示例 sample_rewards.append({"type": "coins", "amount_range": [1000, 2000], "rarity": "史诗"}) sample_rewards.append({"type": "exp", "amount_range": [500, 1000], "rarity": "传奇"}) - return sample_rewards.slice(0, 15) # 只取前15个 + return sample_rewards.slice(0, 15) -## 格式化模板文本 func _format_template_text(reward: Dictionary) -> String: var text = "[center]" @@ -251,44 +192,30 @@ func _format_template_text(reward: Dictionary) -> String: text += "[/center]" return text -## 执行网络抽奖 func _perform_network_draw(draw_type: String) -> void: if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server(): _show_error_message("网络未连接,无法进行抽奖") return - # 检查费用 var cost = draw_costs.get(draw_type, 800) if main_game and main_game.money < cost: _show_error_message("金币不足,需要 %d 金币" % cost) return - # 发送抽奖请求 var success = tcp_network_manager_panel.sendLuckyDraw(draw_type) if not success: _show_error_message("发送抽奖请求失败") return - # 显示等待动画 - _show_waiting_animation(draw_type) + _show_waiting_animation() -## 显示等待动画 -func _show_waiting_animation(draw_type: String) -> void: - # 禁用抽奖按钮 +func _show_waiting_animation() -> void: _set_draw_buttons_enabled(false) - - # 隐藏结果区域 lucky_draw_reward.hide() - - # 播放期待动画 _play_anticipation_animation() -## 处理服务器抽奖响应 func handle_lucky_draw_response(response: Dictionary) -> void: - # 停止期待动画 _stop_anticipation_animation() - - # 重新启用按钮 _set_draw_buttons_enabled(true) if response.get("success", false): @@ -296,44 +223,30 @@ func handle_lucky_draw_response(response: Dictionary) -> void: var draw_type = response.get("draw_type", "single") var cost = response.get("cost", 0) - # 显示抽奖结果 _show_server_draw_results(rewards, draw_type, cost) - - # 发送信号 draw_completed.emit(rewards, draw_type) - else: var error_message = response.get("message", "抽奖失败") _show_error_message(error_message) draw_failed.emit(error_message) -## 显示服务器返回的抽奖结果 func _show_server_draw_results(rewards: Array, draw_type: String, cost: int) -> void: current_rewards = rewards - # 显示结果(动画已在handle_lucky_draw_response中停止) var result_text = _format_server_draw_results(rewards, draw_type, cost) lucky_draw_reward.text = result_text lucky_draw_reward.show() - # 播放结果动画 _play_result_animation() -## 格式化服务器抽奖结果文本 func _format_server_draw_results(rewards: Array, draw_type: String, cost: int) -> String: - var type_names = { - "single": "单抽", - "five": "五连抽", - "ten": "十连抽" - } + var type_names = {"single": "单抽", "five": "五连抽", "ten": "十连抽"} var text = "[center][color=#FFD700]🎊 %s结果 🎊[/color][/center]\n" % type_names.get(draw_type, draw_type) text += "[center][color=#87CEEB]消费 %d 金币[/color][/center]\n" % cost - # 统计稀有度 var stats = _count_server_reward_rarity(rewards) - # 显示稀有度统计 var stat_parts = [] if stats.legendary > 0: stat_parts.append("[color=#FF8C00]🏆传奇x%d[/color]" % stats.legendary) @@ -349,11 +262,9 @@ func _format_server_draw_results(rewards: Array, draw_type: String, cost: int) - text += "\n" - # 显示具体奖励 for reward in rewards: text += _format_single_server_reward(reward) + "\n" - # 鼓励文案 if stats.empty_only: text += "[center][color=#87CEEB]💪 别灰心,下次一定能中大奖![/color][/center]" elif stats.legendary > 0: @@ -363,28 +274,16 @@ func _format_server_draw_results(rewards: Array, draw_type: String, cost: int) - return text -## 统计服务器奖励稀有度 func _count_server_reward_rarity(rewards: Array) -> Dictionary: - var stats = { - "legendary": 0, - "epic": 0, - "rare": 0, - "package": 0, - "empty": 0, - "empty_only": false - } + var stats = {"legendary": 0, "epic": 0, "rare": 0, "package": 0, "empty": 0, "empty_only": false} for reward in rewards: var rarity = reward.get("rarity", "普通") match rarity: - "传奇": - stats.legendary += 1 - "史诗": - stats.epic += 1 - "稀有": - stats.rare += 1 - "空奖": - stats.empty += 1 + "传奇": stats.legendary += 1 + "史诗": stats.epic += 1 + "稀有": stats.rare += 1 + "空奖": stats.empty += 1 if reward.get("type") == "package": stats.package += 1 @@ -392,21 +291,17 @@ func _count_server_reward_rarity(rewards: Array) -> Dictionary: stats.empty_only = (stats.empty == rewards.size() and rewards.size() == 1) return stats -## 格式化单个服务器奖励显示 func _format_single_server_reward(reward: Dictionary) -> String: - var text = "" var reward_type = reward.get("type", "") var rarity = reward.get("rarity", "普通") var rarity_color = _get_rarity_color(rarity) match reward_type: "empty": - var reward_name = reward.get("name", "空奖励") - text = "[color=%s]😅 %s[/color]" % [rarity_color, reward_name] + return "[color=%s]😅 %s[/color]" % [rarity_color, reward.get("name", "空奖励")] "package": - var reward_name = reward.get("name", "礼包") - text = "[color=%s]🎁 %s[/color]\n" % [rarity_color, reward_name] + var text = "[color=%s]🎁 %s[/color]\n" % [rarity_color, reward.get("name", "礼包")] text += "[color=#DDDDDD]内含:[/color] " var content_parts = [] @@ -417,50 +312,35 @@ func _format_single_server_reward(reward: Dictionary) -> String: content_parts.append(part) text += " ".join(content_parts) + return text "coins": - var amount = reward.get("amount", 0) - text = "[color=%s]💰 金币 +%d[/color]" % [rarity_color, amount] + return "[color=%s]💰 金币 +%d[/color]" % [rarity_color, reward.get("amount", 0)] "exp": - var amount = reward.get("amount", 0) - text = "[color=%s]⭐ 经验 +%d[/color]" % [rarity_color, amount] + return "[color=%s]⭐ 经验 +%d[/color]" % [rarity_color, reward.get("amount", 0)] "seed": - var reward_name = reward.get("name", "种子") - var amount = reward.get("amount", 0) - text = "[color=%s]🌱 %s x%d[/color] [color=#CCCCCC](%s)[/color]" % [ - rarity_color, reward_name, amount, rarity + return "[color=%s]🌱 %s x%d[/color] [color=#CCCCCC](%s)[/color]" % [ + rarity_color, reward.get("name", "种子"), reward.get("amount", 0), rarity ] _: - text = "[color=#CCCCCC]未知奖励[/color]" - - return text + return "[color=#CCCCCC]未知奖励[/color]" -## 格式化礼包内容 func _format_package_content(content: Dictionary) -> String: var content_type = content.get("type", "") var amount = content.get("amount", 0) match content_type: - "coins": - return "[color=#FFD700]💰%d[/color]" % amount - "exp": - return "[color=#00BFFF]⭐%d[/color]" % amount - "seed": - var seed_name = content.get("name", "种子") - return "[color=#90EE90]🌱%sx%d[/color]" % [seed_name, amount] - _: - return "" + "coins": return "[color=#FFD700]💰%d[/color]" % amount + "exp": return "[color=#00BFFF]⭐%d[/color]" % amount + "seed": return "[color=#90EE90]🌱%sx%d[/color]" % [content.get("name", "种子"), amount] + _: return "" -## 播放期待动画(简化版) func _play_anticipation_animation() -> void: - """播放期待动画""" - # 停止之前的动画 _stop_anticipation_animation() - # 创建简单的闪烁动画 anticipation_tween = create_tween() anticipation_tween.set_loops() @@ -468,72 +348,42 @@ func _play_anticipation_animation() -> void: if template.visible: anticipation_tween.parallel().tween_method( func(progress: float): _anticipation_flash(template, progress), - 0.0, 1.0, 0.5 + 0.0, 1.0, 0.8 ) - - func _anticipation_flash(template: RichTextLabel, progress: float) -> void: - """期待动画闪烁效果""" - var flash_intensity = 1.0 + sin(progress * PI * 2) * 0.3 + var flash_intensity = 1.0 + sin(progress * PI * 2) * 0.2 template.modulate = Color(flash_intensity, flash_intensity, flash_intensity, 1.0) -## 停止期待动画 func _stop_anticipation_animation() -> void: if anticipation_tween: anticipation_tween.kill() anticipation_tween = null - # 恢复所有模板的正常颜色 - for i in range(reward_templates.size()): - var template = reward_templates[i] + for template in reward_templates: template.modulate = Color.WHITE -## 播放结果动画 func _play_result_animation() -> void: var tween = create_tween() - # 奖励区域动画 lucky_draw_reward.modulate.a = 0.0 lucky_draw_reward.scale = Vector2(0.8, 0.8) tween.parallel().tween_property(lucky_draw_reward, "modulate:a", 1.0, 0.5) tween.parallel().tween_property(lucky_draw_reward, "scale", Vector2(1.0, 1.0), 0.5) + tween.tween_callback(func(): lucky_draw_reward.modulate.a = 1.0) -## 显示错误信息 func _show_error_message(message: String) -> void: lucky_draw_reward.text = "[center][color=#FF6B6B]❌ %s[/color][/center]" % message lucky_draw_reward.show() - # 2秒后隐藏错误信息 await get_tree().create_timer(2.0).timeout lucky_draw_reward.hide() -# ============================================================================= -# 事件处理 -# ============================================================================= - -## 关闭面板 -func _on_quit_button_pressed() -> void: - self.hide() - -## 单次抽奖 -func _on_lucky_draw_button_pressed() -> void: - _perform_network_draw("single") - -## 五连抽 -func _on_five_lucky_draw_button_pressed() -> void: - _perform_network_draw("five") - -## 十连抽 -func _on_ten_lucky_draw_button_pressed() -> void: - _perform_network_draw("ten") - -## 设置抽奖按钮可用状态 func _set_draw_buttons_enabled(enabled: bool) -> void: var buttons = [ $HBox/LuckyDrawButton, - $HBox/FiveLuckyDrawButton, + $HBox/FiveLuckyDrawButton, $HBox/TenLuckyDrawButton ] @@ -541,30 +391,33 @@ func _set_draw_buttons_enabled(enabled: bool) -> void: if button: button.disabled = not enabled -# ============================================================================= -# 公共接口方法 -# ============================================================================= +# 事件处理 +func _on_quit_button_pressed() -> void: + self.hide() -## 获取当前奖励结果 +func _on_lucky_draw_button_pressed() -> void: + _perform_network_draw("single") + +func _on_five_lucky_draw_button_pressed() -> void: + _perform_network_draw("five") + +func _on_ten_lucky_draw_button_pressed() -> void: + _perform_network_draw("ten") + +func _on_visibility_changed(): + if visible: + GlobalVariables.isZoomDisabled = true + else: + GlobalVariables.isZoomDisabled = false + +# 公共接口 func get_current_rewards() -> Array: return current_rewards -## 清空抽奖结果 func clear_draw_results() -> void: current_rewards.clear() lucky_draw_reward.hide() -## 刷新奖励显示(当作物数据更新时调用) func refresh_reward_display() -> void: _load_crop_data_and_build_rewards() _update_template_display() - - -#面板显示与隐藏切换处理 -func _on_visibility_changed(): - if visible: - GlobalVariables.isZoomDisabled = true - pass - else: - GlobalVariables.isZoomDisabled = false - pass diff --git a/Server/TCPGameServer.py b/Server/TCPGameServer.py index 5f411bc..48334ea 100644 --- a/Server/TCPGameServer.py +++ b/Server/TCPGameServer.py @@ -65,6 +65,7 @@ server_version: str = "2.0.1" # TCP游戏服务器类 # ============================================================================ class TCPGameServer(TCPServer): + """ 萌芽农场TCP游戏服务器 """ @@ -6206,6 +6207,39 @@ class TCPGameServer(TCPServer): #==========================每日签到处理========================== + #加载每日签到配置 + def _load_daily_check_in_config(self): + """加载每日签到配置""" + try: + config_path = os.path.join(self.config_dir, "daily_checkin_config.json") + if os.path.exists(config_path): + with open(config_path, 'r', encoding='utf-8') as f: + return json.load(f) + except: + pass + + # 默认配置 + return { + "基础奖励": { + "金币": {"最小值": 200, "最大值": 500, "图标": "💰", "颜色": "#FFD700"}, + "经验": {"最小值": 50, "最大值": 120, "图标": "⭐", "颜色": "#00BFFF"} + }, + "种子奖励": { + "普通": {"概率": 0.6, "数量范围": [2, 5], "种子池": ["小麦", "胡萝卜", "土豆", "稻谷"]}, + "优良": {"概率": 0.25, "数量范围": [2, 4], "种子池": ["玉米", "番茄", "洋葱", "大豆", "豌豆", "黄瓜", "大白菜"]}, + "稀有": {"概率": 0.12, "数量范围": [1, 3], "种子池": ["草莓", "花椰菜", "柿子", "蓝莓", "树莓"]}, + "史诗": {"概率": 0.025, "数量范围": [1, 2], "种子池": ["葡萄", "南瓜", "芦笋", "茄子", "向日葵", "蕨菜"]}, + "传奇": {"概率": 0.005, "数量范围": [1, 1], "种子池": ["西瓜", "甘蔗", "香草", "甜菜", "人参", "富贵竹", "芦荟", "哈密瓜"]} + }, + "连续签到奖励": { + "第3天": {"额外金币": 100, "额外经验": 50, "描述": "连续签到奖励"}, + "第7天": {"额外金币": 200, "额外经验": 100, "描述": "一周连击奖励"}, + "第14天": {"额外金币": 500, "额外经验": 200, "描述": "半月连击奖励"}, + "第21天": {"额外金币": 800, "额外经验": 300, "描述": "三周连击奖励"}, + "第30天": {"额外金币": 1500, "额外经验": 500, "描述": "满月连击奖励"} + } + } + #处理每日签到请求 def _handle_daily_check_in_request(self, client_id, message): """处理每日签到请求""" @@ -6219,36 +6253,41 @@ class TCPGameServer(TCPServer): if not player_data: return self.send_data(client_id, response) - # 检查今日是否已签到 - current_date = datetime.datetime.now().strftime("%Y-%m-%d") - check_in_data = player_data.get("daily_check_in", {}) + # 清理过期签到记录并使用新格式 + self._cleanup_check_in_history(player_data) - if current_date in check_in_data: - return self.send_data(client_id, { - "type": "daily_check_in_response", - "success": False, - "message": "今日已签到,请明日再来", - "has_checked_in": True - }) + # 检查今日是否已签到 + current_time = datetime.datetime.now() + today_key = current_time.strftime("%Y年%m月%d日") + check_in_history = player_data.get("签到历史", {}) + + # 检查今日是否已签到 + for time_key in check_in_history.keys(): + if time_key.startswith(today_key): + return self.send_data(client_id, { + "type": "daily_check_in_response", + "success": False, + "message": "今日已签到,请明日再来", + "has_checked_in": True + }) # 计算连续签到天数 - consecutive_days = self._calculate_consecutive_check_in_days(check_in_data, current_date) + consecutive_days = self._calculate_consecutive_check_in_days_new(check_in_history) # 生成签到奖励 - rewards = self._generate_check_in_rewards(consecutive_days) + config = self._load_daily_check_in_config() + rewards = self._generate_check_in_rewards_new(consecutive_days, config) # 发放奖励 self._apply_check_in_rewards(player_data, rewards) - # 保存签到记录 - if "daily_check_in" not in player_data: - player_data["daily_check_in"] = {} + # 保存签到记录 - 使用新格式 + if "签到历史" not in player_data: + player_data["签到历史"] = {} - player_data["daily_check_in"][current_date] = { - "rewards": rewards, - "consecutive_days": consecutive_days, - "timestamp": time.time() - } + time_key = current_time.strftime("%Y年%m月%d日%H时%M分%S秒") + reward_text = self._format_reward_text_simple(rewards) + player_data["签到历史"][time_key] = reward_text # 保存玩家数据 self.save_player_data(username, player_data) @@ -6282,144 +6321,201 @@ class TCPGameServer(TCPServer): if not player_data: return self.send_data(client_id, response) - current_date = datetime.datetime.now().strftime("%Y-%m-%d") - check_in_data = player_data.get("daily_check_in", {}) + # 清理过期签到记录 + self._cleanup_check_in_history(player_data) + + check_in_history = player_data.get("签到历史", {}) # 计算连续签到天数 - consecutive_days = self._calculate_consecutive_check_in_days(check_in_data, current_date) + consecutive_days = self._calculate_consecutive_check_in_days_new(check_in_history) # 检查今日是否已签到 - has_checked_in_today = current_date in check_in_data + current_time = datetime.datetime.now() + today_key = current_time.strftime("%Y年%m月%d日") + has_checked_in_today = any(time_key.startswith(today_key) for time_key in check_in_history.keys()) return self.send_data(client_id, { "type": "check_in_data_response", "success": True, - "check_in_data": check_in_data, + "check_in_data": check_in_history, "consecutive_days": consecutive_days, "has_checked_in_today": has_checked_in_today, - "current_date": current_date + "current_date": current_time.strftime("%Y年%m月%d日") }) - #计算连续签到天数 - def _calculate_consecutive_check_in_days(self, check_in_data, current_date): - """计算连续签到天数""" - if not check_in_data: + #清理过期签到记录 + def _cleanup_check_in_history(self, player_data): + """清理过期签到记录,只保留最近30天的记录""" + if "签到历史" not in player_data: + return + + current_time = datetime.datetime.now() + cutoff_time = current_time - datetime.timedelta(days=30) + + # 清理过期记录 + history = player_data["签到历史"] + keys_to_remove = [] + + for time_key in history.keys(): + try: + # 解析时间字符串 + check_time = datetime.datetime.strptime(time_key, "%Y年%m月%d日%H时%M分%S秒") + if check_time < cutoff_time: + keys_to_remove.append(time_key) + except: + # 如果解析失败,删除这条记录 + keys_to_remove.append(time_key) + + for key in keys_to_remove: + del history[key] + + #计算连续签到天数(新版本) + def _calculate_consecutive_check_in_days_new(self, check_in_history): + """计算连续签到天数(新版本)""" + if not check_in_history: return 0 - # 获取所有签到日期并排序 - sorted_dates = sorted(check_in_data.keys()) - if not sorted_dates: + # 提取所有签到日期(只取日期部分) + check_dates = set() + for time_key in check_in_history.keys(): + try: + check_time = datetime.datetime.strptime(time_key, "%Y年%m月%d日%H时%M分%S秒") + date_str = check_time.strftime("%Y-%m-%d") + check_dates.add(date_str) + except: + continue + + if not check_dates: return 0 - # 从最新日期开始向前计算连续天数 + # 从今天开始向前计算连续天数 consecutive_days = 0 - current_datetime = datetime.datetime.strptime(current_date, "%Y-%m-%d") + current_date = datetime.datetime.now() - # 如果今天已经签到,从今天开始计算,否则从昨天开始 - if current_date in check_in_data: - check_date = current_datetime + # 检查今天是否已签到 + today_str = current_date.strftime("%Y-%m-%d") + if today_str in check_dates: + consecutive_days += 1 + check_date = current_date - datetime.timedelta(days=1) else: - check_date = current_datetime - datetime.timedelta(days=1) + check_date = current_date - datetime.timedelta(days=1) # 向前查找连续签到天数 while True: - date_string = check_date.strftime("%Y-%m-%d") - if date_string in check_in_data: + date_str = check_date.strftime("%Y-%m-%d") + if date_str in check_dates: consecutive_days += 1 check_date -= datetime.timedelta(days=1) else: break - # 限制最大连续天数为30天,避免过度奖励 + # 限制最大连续天数为30天 if consecutive_days >= 30: break return consecutive_days - #生成签到奖励 - def _generate_check_in_rewards(self, consecutive_days): - """生成签到奖励""" + #生成签到奖励(新版本) + def _generate_check_in_rewards_new(self, consecutive_days, config): + """生成签到奖励(新版本)""" import random - # 加载作物配置 - crop_data = self._load_crop_data() - rewards = {} - # 基础奖励倍数(根据连续签到天数) - base_multiplier = 1.0 + (consecutive_days - 1) * 0.1 # 每连续签到一天增加10% - max_multiplier = 3.0 # 最大3倍奖励 + # 基础奖励倍数 + base_multiplier = 1.0 + (consecutive_days - 1) * 0.1 + max_multiplier = 3.0 multiplier = min(base_multiplier, max_multiplier) - # 钱币奖励 (基础200-500,受连续签到影响) - base_coins = random.randint(200, 500) + # 基础金币奖励 + coin_config = config.get("基础奖励", {}).get("金币", {}) + base_coins = random.randint(coin_config.get("最小值", 200), coin_config.get("最大值", 500)) rewards["coins"] = int(base_coins * multiplier) - # 经验奖励 (基础50-120,受连续签到影响) - base_exp = random.randint(50, 120) + # 基础经验奖励 + exp_config = config.get("基础奖励", {}).get("经验", {}) + base_exp = random.randint(exp_config.get("最小值", 50), exp_config.get("最大值", 120)) rewards["exp"] = int(base_exp * multiplier) - # 种子奖励 (根据连续签到天数获得更好的种子) - seeds = self._generate_check_in_seeds(consecutive_days, crop_data) + # 种子奖励 + seeds = self._generate_check_in_seeds_new(consecutive_days, config) if seeds: rewards["seeds"] = seeds # 连续签到特殊奖励 - if consecutive_days >= 3: - rewards["bonus_coins"] = int(100 * (consecutive_days // 3)) - - if consecutive_days >= 7: - rewards["bonus_exp"] = int(200 * (consecutive_days // 7)) + consecutive_rewards = config.get("连续签到奖励", {}) + for milestone, bonus in consecutive_rewards.items(): + milestone_days = int(milestone.replace("第", "").replace("天", "")) + if consecutive_days >= milestone_days: + if "额外金币" in bonus: + rewards["bonus_coins"] = bonus["额外金币"] + if "额外经验" in bonus: + rewards["bonus_exp"] = bonus["额外经验"] return rewards - #生成签到种子奖励 - def _generate_check_in_seeds(self, consecutive_days, crop_data): - """生成签到种子奖励""" + #生成签到种子奖励(新版本) + def _generate_check_in_seeds_new(self, consecutive_days, config): + """生成签到种子奖励(新版本)""" import random seeds = [] + seed_configs = config.get("种子奖励", {}) - # 根据连续签到天数确定种子类型和数量 + # 根据连续签到天数确定种子稀有度 if consecutive_days <= 2: - # 1-2天:普通种子 - common_seeds = ["小麦", "胡萝卜", "土豆", "稻谷"] + rarity = "普通" elif consecutive_days <= 5: - # 3-5天:优良种子 - common_seeds = ["玉米", "番茄", "洋葱", "大豆", "豌豆", "黄瓜", "大白菜"] + rarity = "优良" elif consecutive_days <= 10: - # 6-10天:稀有种子 - common_seeds = ["草莓", "花椰菜", "柿子", "蓝莓", "树莓"] + rarity = "稀有" elif consecutive_days <= 15: - # 11-15天:史诗种子 - common_seeds = ["葡萄", "南瓜", "芦笋", "茄子", "向日葵", "蕨菜"] + rarity = "史诗" else: - # 16天以上:传奇种子 - common_seeds = ["西瓜", "甘蔗", "香草", "甜菜", "人参", "富贵竹", "芦荟", "哈密瓜"] + rarity = "传奇" + + # 获取对应稀有度的种子池 + rarity_config = seed_configs.get(rarity, {}) + seed_pool = rarity_config.get("种子池", []) + quantity_range = rarity_config.get("数量范围", [1, 2]) + + if not seed_pool: + return seeds # 生成1-3个种子 - seed_count = random.randint(1, min(3, len(common_seeds))) - selected_seeds = random.sample(common_seeds, seed_count) + seed_count = random.randint(1, min(3, len(seed_pool))) + selected_seeds = random.sample(seed_pool, seed_count) for seed_name in selected_seeds: - if seed_name in crop_data: - # 根据种子等级确定数量 - seed_level = crop_data[seed_name].get("等级", 1) - if seed_level <= 2: - quantity = random.randint(2, 5) - elif seed_level <= 4: - quantity = random.randint(1, 3) - else: - quantity = 1 - - seeds.append({ - "name": seed_name, - "quantity": quantity, - "quality": crop_data[seed_name].get("品质", "普通") - }) + quantity = random.randint(quantity_range[0], quantity_range[1]) + seeds.append({ + "name": seed_name, + "quantity": quantity, + "quality": rarity + }) return seeds + #格式化奖励文本(简单版本) + def _format_reward_text_simple(self, rewards): + """格式化奖励文本(简单版本)""" + parts = [] + + if "coins" in rewards: + parts.append(f"金币{rewards['coins']}") + if "exp" in rewards: + parts.append(f"经验{rewards['exp']}") + if "bonus_coins" in rewards: + parts.append(f"额外金币{rewards['bonus_coins']}") + if "bonus_exp" in rewards: + parts.append(f"额外经验{rewards['bonus_exp']}") + + if "seeds" in rewards: + for seed in rewards["seeds"]: + parts.append(f"{seed['name']}x{seed['quantity']}") + + return " ".join(parts) + #应用签到奖励到玩家数据 def _apply_check_in_rewards(self, player_data, rewards): """应用签到奖励到玩家数据""" @@ -6620,22 +6716,27 @@ class TCPGameServer(TCPServer): if not player_data: return self.send_data(client_id, response) + # 删除历史记录(如果存在) + if "lucky_draw_history" in player_data: + del player_data["lucky_draw_history"] + draw_type = message.get("draw_type", "single") # single, five, ten - draw_count = 1 - base_cost = 800 # 基础抽奖费用 + + # 从配置文件获取费用 + config = self._load_lucky_draw_config() + costs = config.get("抽奖费用", {"单抽": 800, "五连抽": 3600, "十连抽": 6400}) # 计算抽奖费用和数量 if draw_type == "single": draw_count = 1 - total_cost = base_cost + total_cost = costs.get("单抽", 800) elif draw_type == "five": draw_count = 5 - total_cost = int(base_cost * 5 * 0.9) # 五连抽九折 + total_cost = costs.get("五连抽", 3600) elif draw_type == "ten": draw_count = 10 - total_cost = int(base_cost * 10 * 0.8) # 十连抽八折 + total_cost = costs.get("十连抽", 6400) else: - self.log('WARNING', f"玩家 {username} 使用了无效的抽奖类型: {draw_type}", 'SERVER') return self.send_data(client_id, { "type": "lucky_draw_response", "success": False, @@ -6644,44 +6745,21 @@ class TCPGameServer(TCPServer): # 检查玩家金钱是否足够 if player_data.get("money", 0) < total_cost: - self.log('WARNING', f"玩家 {username} 金币不足进行{draw_type}抽奖,需要{total_cost},当前{player_data.get('money', 0)}", 'SERVER') return self.send_data(client_id, { "type": "lucky_draw_response", "success": False, - "message": f"金钱不足,{draw_type}抽奖需要 {total_cost} 金币" + "message": f"金钱不足,需要 {total_cost} 金币" }) # 扣除金钱 player_data["money"] -= total_cost # 生成奖励 - rewards = self._generate_lucky_draw_rewards(draw_count, draw_type) - - # 验证奖励格式 - for reward in rewards: - if not reward.get("rarity"): - reward["rarity"] = "普通" - self.log('WARNING', f"奖励缺少稀有度字段,已设置为普通: {reward}", 'SERVER') + rewards = self._generate_lucky_draw_rewards(draw_count, draw_type, config) # 应用奖励到玩家数据 self._apply_lucky_draw_rewards(player_data, rewards) - # 记录抽奖历史 - if "lucky_draw_history" not in player_data: - player_data["lucky_draw_history"] = [] - - draw_record = { - "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "type": draw_type, - "cost": total_cost, - "rewards": rewards - } - player_data["lucky_draw_history"].append(draw_record) - - # 只保留最近100次记录 - if len(player_data["lucky_draw_history"]) > 100: - player_data["lucky_draw_history"] = player_data["lucky_draw_history"][-100:] - # 保存玩家数据 self.save_player_data(username, player_data) @@ -6703,24 +6781,40 @@ class TCPGameServer(TCPServer): }) except Exception as e: - # 捕获所有异常,防止服务器崩溃 self.log('ERROR', f"处理玩家抽奖请求时出错: {str(e)}", 'SERVER') - # 尝试获取用户名 - try: - username = self.user_data[client_id].get("username", "未知用户") - except: - username = "未知用户" - - # 发送错误响应 return self.send_data(client_id, { "type": "lucky_draw_response", "success": False, "message": "服务器处理抽奖时出现错误,请稍后重试" }) + #加载抽奖配置 + def _load_lucky_draw_config(self): + """加载抽奖配置""" + try: + config_path = os.path.join(self.config_dir, "lucky_draw_config.json") + if os.path.exists(config_path): + with open(config_path, 'r', encoding='utf-8') as f: + return json.load(f) + except: + pass + + # 默认配置 + return { + "抽奖费用": {"单抽": 800, "五连抽": 3600, "十连抽": 6400}, + "概率配置": { + "普通": {"概率": 0.45, "金币范围": [100, 300], "经验范围": [50, 150], "种子数量": [2, 4]}, + "优良": {"概率": 0.25, "金币范围": [300, 600], "经验范围": [150, 300], "种子数量": [1, 3]}, + "稀有": {"概率": 0.12, "金币范围": [600, 1000], "经验范围": [300, 500], "种子数量": [1, 2]}, + "史诗": {"概率": 0.025, "金币范围": [1000, 1500], "经验范围": [500, 800], "种子数量": [1, 1]}, + "传奇": {"概率": 0.005, "金币范围": [1500, 2500], "经验范围": [800, 1200], "种子数量": [1, 1]}, + "空奖": {"概率": 0.15, "提示语": ["谢谢惠顾", "下次再来", "再试一次", "继续努力"]} + } + } + #生成幸运抽奖奖励 - def _generate_lucky_draw_rewards(self, count: int, draw_type: str): + def _generate_lucky_draw_rewards(self, count: int, draw_type: str, config: dict): """生成幸运抽奖奖励""" import random @@ -6730,42 +6824,28 @@ class TCPGameServer(TCPServer): rewards = [] # 根据 crop_data.json 构建奖励池 - common_seeds = [] - good_seeds = [] - rare_seeds = [] - epic_seeds = [] - legendary_seeds = [] + seed_pools = {"普通": [], "优良": [], "稀有": [], "史诗": [], "传奇": []} for crop_name, crop_info in crop_data.items(): if not crop_info.get("能否购买", True): - continue # 跳过不能购买的作物 + continue quality = crop_info.get("品质", "普通") - if quality == "普通": - common_seeds.append(crop_name) - elif quality == "优良": - good_seeds.append(crop_name) - elif quality == "稀有": - rare_seeds.append(crop_name) - elif quality == "史诗": - epic_seeds.append(crop_name) - elif quality == "传奇": - legendary_seeds.append(crop_name) + if quality in seed_pools: + seed_pools[quality].append(crop_name) - # 十连抽保底机制:至少一个稀有以上 + # 十连抽保底机制 guaranteed_rare = (draw_type == "ten") rare_given = False for i in range(count): # 生成单个奖励 reward = self._generate_single_lucky_reward( - common_seeds, good_seeds, rare_seeds, epic_seeds, legendary_seeds, - guaranteed_rare and i == count - 1 and not rare_given + seed_pools, config, guaranteed_rare and i == count - 1 and not rare_given ) - # 检查是否给出了稀有奖励(使用安全的方式访问) - reward_rarity = reward.get("rarity", "普通") - if reward_rarity in ["稀有", "史诗", "传奇"]: + # 检查是否给出了稀有奖励 + if reward.get("rarity", "普通") in ["稀有", "史诗", "传奇"]: rare_given = True rewards.append(reward) @@ -6773,278 +6853,166 @@ class TCPGameServer(TCPServer): return rewards #生成单个抽奖奖励 - def _generate_single_lucky_reward(self, common_seeds, good_seeds, rare_seeds, epic_seeds, legendary_seeds, force_rare=False): + def _generate_single_lucky_reward(self, seed_pools: dict, config: dict, force_rare=False): """生成单个幸运抽奖奖励""" import random - # 概率配置 + prob_config = config.get("概率配置", {}) + + # 决定稀有度 if force_rare: # 强制稀有:33%稀有,33%史诗,34%传奇 rand = random.random() if rand < 0.33: - reward_type = "rare" + rarity = "稀有" elif rand < 0.66: - reward_type = "epic" + rarity = "史诗" else: - reward_type = "legendary" + rarity = "传奇" else: - # 正常概率:45%普通,25%优良,15%空奖,12%稀有,2.5%史诗,0.5%传奇 + # 正常概率 rand = random.random() - if rand < 0.45: - reward_type = "common" - elif rand < 0.70: - reward_type = "good" - elif rand < 0.85: - reward_type = "empty" - elif rand < 0.97: - reward_type = "rare" - elif rand < 0.995: - reward_type = "epic" - else: - reward_type = "legendary" + cumulative = 0 + rarity = "普通" + + for r, config_data in prob_config.items(): + prob = config_data.get("概率", 0) + cumulative += prob + if rand < cumulative: + rarity = r + break - reward = {} - - if reward_type == "empty": - # 谢谢惠顾 - empty_messages = ["谢谢惠顾", "下次再来", "再试一次", "继续努力"] - reward = { + # 根据稀有度生成奖励 + if rarity == "空奖": + empty_messages = prob_config.get("空奖", {}).get("提示语", ["谢谢惠顾"]) + return { "type": "empty", "name": random.choice(empty_messages), "rarity": "空奖", "amount": 0 } - elif reward_type == "common": - # 普通奖励:金币、经验或普通种子 - reward_choice = random.choice(["coins", "exp", "seed"]) - if reward_choice == "coins": - reward = { + # 获取稀有度配置 + rarity_config = prob_config.get(rarity, {}) + + # 根据奖励类型权重选择奖励类型 + type_weights = config.get("奖励类型权重", {}).get(rarity, {"金币": 0.5, "经验": 0.3, "种子": 0.2}) + + # 随机选择奖励类型 + rand = random.random() + cumulative = 0 + reward_type = "金币" + + for r_type, weight in type_weights.items(): + cumulative += weight + if rand < cumulative: + reward_type = r_type + break + + # 生成具体奖励 + if reward_type == "金币": + coin_range = rarity_config.get("金币范围", [100, 300]) + return { + "type": "coins", + "name": "金币", + "rarity": rarity, + "amount": random.randint(coin_range[0], coin_range[1]) + } + + elif reward_type == "经验": + exp_range = rarity_config.get("经验范围", [50, 150]) + return { + "type": "exp", + "name": "经验", + "rarity": rarity, + "amount": random.randint(exp_range[0], exp_range[1]) + } + + elif reward_type == "种子": + seeds = seed_pools.get(rarity, []) + if not seeds: + # 如果没有对应稀有度的种子,给金币 + coin_range = rarity_config.get("金币范围", [100, 300]) + return { "type": "coins", "name": "金币", - "rarity": "普通", - "amount": random.randint(100, 300) + "rarity": rarity, + "amount": random.randint(coin_range[0], coin_range[1]) } - elif reward_choice == "exp": - reward = { - "type": "exp", - "name": "经验", - "rarity": "普通", - "amount": random.randint(50, 150) - } - else: # seed - if common_seeds: - seed_name = random.choice(common_seeds) - reward = { - "type": "seed", - "name": seed_name, - "rarity": "普通", - "amount": random.randint(2, 4) - } - else: - reward = { - "type": "coins", - "name": "金币", - "rarity": "普通", - "amount": random.randint(100, 300) - } + + seed_count_range = rarity_config.get("种子数量", [1, 2]) + return { + "type": "seed", + "name": random.choice(seeds), + "rarity": rarity, + "amount": random.randint(seed_count_range[0], seed_count_range[1]) + } - elif reward_type == "good": - # 优良奖励:更多金币经验或优良种子 - reward_choice = random.choice(["coins", "exp", "seed", "package"]) - if reward_choice == "coins": - reward = { + elif reward_type == "礼包": + package_config = config.get("礼包配置", {}) + package_names = [name for name, info in package_config.items() if info.get("稀有度") == rarity] + + if not package_names: + # 如果没有对应稀有度的礼包,给金币 + coin_range = rarity_config.get("金币范围", [100, 300]) + return { "type": "coins", "name": "金币", - "rarity": "优良", - "amount": random.randint(300, 600) + "rarity": rarity, + "amount": random.randint(coin_range[0], coin_range[1]) } - elif reward_choice == "exp": - reward = { - "type": "exp", - "name": "经验", - "rarity": "优良", - "amount": random.randint(150, 300) - } - elif reward_choice == "seed": - if good_seeds: - seed_name = random.choice(good_seeds) - reward = { - "type": "seed", - "name": seed_name, - "rarity": "优良", - "amount": random.randint(1, 3) - } - else: - reward = { - "type": "coins", - "name": "金币", - "rarity": "优良", - "amount": random.randint(300, 600) - } - else: # package - reward = { - "type": "package", - "name": "成长套餐", - "rarity": "优良", - "amount": 1, - "contents": [ - {"type": "coins", "amount": random.randint(200, 400)}, - {"type": "exp", "amount": random.randint(100, 200)}, - {"type": "seed", "name": random.choice(common_seeds) if common_seeds else "小麦", "amount": random.randint(2, 3)} - ] - } - - elif reward_type == "rare": - # 稀有奖励 - reward_choice = random.choice(["coins", "exp", "seed", "package"]) - if reward_choice == "coins": - reward = { + + package_name = random.choice(package_names) + package_info = package_config[package_name] + contents = [] + + # 生成礼包内容 + content_config = package_info.get("内容", {}) + + if "金币" in content_config: + coin_range = content_config["金币"] + contents.append({ "type": "coins", - "name": "金币", - "rarity": "稀有", - "amount": random.randint(600, 1000) - } - elif reward_choice == "exp": - reward = { + "amount": random.randint(coin_range[0], coin_range[1]), + "rarity": rarity + }) + + if "经验" in content_config: + exp_range = content_config["经验"] + contents.append({ "type": "exp", - "name": "经验", - "rarity": "稀有", - "amount": random.randint(300, 500) - } - elif reward_choice == "seed": - if rare_seeds: - seed_name = random.choice(rare_seeds) - reward = { + "amount": random.randint(exp_range[0], exp_range[1]), + "rarity": rarity + }) + + if "种子数量" in content_config: + seed_count_range = content_config["种子数量"] + lower_rarity = {"优良": "普通", "稀有": "优良", "史诗": "稀有", "传奇": "史诗"}.get(rarity, "普通") + seeds = seed_pools.get(lower_rarity, []) + if seeds: + contents.append({ "type": "seed", - "name": seed_name, - "rarity": "稀有", - "amount": random.randint(1, 2) - } - else: - reward = { - "type": "coins", - "name": "金币", - "rarity": "稀有", - "amount": random.randint(600, 1000) - } - else: # package - reward = { - "type": "package", - "name": "稀有礼包", - "rarity": "稀有", - "amount": 1, - "contents": [ - {"type": "coins", "amount": random.randint(400, 700)}, - {"type": "exp", "amount": random.randint(200, 350)}, - {"type": "seed", "name": random.choice(good_seeds) if good_seeds else "番茄", "amount": random.randint(2, 3)} - ] - } + "name": random.choice(seeds), + "amount": random.randint(seed_count_range[0], seed_count_range[1]), + "rarity": rarity + }) + + return { + "type": "package", + "name": package_name, + "rarity": rarity, + "amount": 1, + "contents": contents + } - elif reward_type == "epic": - # 史诗奖励 - reward_choice = random.choice(["coins", "exp", "seed", "package"]) - if reward_choice == "coins": - reward = { - "type": "coins", - "name": "金币", - "rarity": "史诗", - "amount": random.randint(1000, 1500) - } - elif reward_choice == "exp": - reward = { - "type": "exp", - "name": "经验", - "rarity": "史诗", - "amount": random.randint(500, 800) - } - elif reward_choice == "seed": - if epic_seeds: - seed_name = random.choice(epic_seeds) - reward = { - "type": "seed", - "name": seed_name, - "rarity": "史诗", - "amount": 1 - } - else: - reward = { - "type": "coins", - "name": "金币", - "rarity": "史诗", - "amount": random.randint(1000, 1500) - } - else: # package - reward = { - "type": "package", - "name": "史诗礼包", - "rarity": "史诗", - "amount": 1, - "contents": [ - {"type": "coins", "amount": random.randint(700, 1200)}, - {"type": "exp", "amount": random.randint(350, 600)}, - {"type": "seed", "name": random.choice(rare_seeds) if rare_seeds else "草莓", "amount": random.randint(1, 2)} - ] - } - - else: # legendary - # 传奇奖励 - reward_choice = random.choice(["coins", "exp", "seed", "package"]) - if reward_choice == "coins": - reward = { - "type": "coins", - "name": "金币", - "rarity": "传奇", - "amount": random.randint(1500, 2500) - } - elif reward_choice == "exp": - reward = { - "type": "exp", - "name": "经验", - "rarity": "传奇", - "amount": random.randint(800, 1200) - } - elif reward_choice == "seed": - if legendary_seeds: - seed_name = random.choice(legendary_seeds) - reward = { - "type": "seed", - "name": seed_name, - "rarity": "传奇", - "amount": 1 - } - else: - reward = { - "type": "coins", - "name": "金币", - "rarity": "传奇", - "amount": random.randint(1500, 2500) - } - else: # package - reward = { - "type": "package", - "name": "传奇大礼包", - "rarity": "传奇", - "amount": 1, - "contents": [ - {"type": "coins", "amount": random.randint(1000, 2000)}, - {"type": "exp", "amount": random.randint(600, 1000)}, - {"type": "seed", "name": random.choice(epic_seeds) if epic_seeds else "葡萄", "amount": 1}, - {"type": "seed", "name": random.choice(rare_seeds) if rare_seeds else "草莓", "amount": random.randint(2, 3)} - ] - } - - # 确保所有奖励都有基本字段 - if not reward.get("rarity"): - reward["rarity"] = "普通" - if not reward.get("amount"): - reward["amount"] = 0 - if not reward.get("type"): - reward["type"] = "empty" - if not reward.get("name"): - reward["name"] = "未知奖励" - - return reward + # 默认给金币 + coin_range = rarity_config.get("金币范围", [100, 300]) + return { + "type": "coins", + "name": "金币", + "rarity": rarity, + "amount": random.randint(coin_range[0], coin_range[1]) + } #应用幸运抽奖奖励到玩家数据 def _apply_lucky_draw_rewards(self, player_data, rewards): @@ -7640,6 +7608,10 @@ class TCPGameServer(TCPServer): "success": False, "message": message }) +#==========================稻草人系统处理========================== + + + #==========================智慧树系统处理========================== def _handle_wisdom_tree_operation(self, client_id, message): @@ -8303,7 +8275,6 @@ class TCPGameServer(TCPServer): # 更新杀虫时间为当前时间,避免重复扣血 wisdom_tree_config["距离上一次杀虫时间"] = current_time #==========================智慧树系统处理========================== -#==========================稻草人系统处理========================== diff --git a/Server/config/daily_checkin_config.json b/Server/config/daily_checkin_config.json new file mode 100644 index 0000000..0071462 --- /dev/null +++ b/Server/config/daily_checkin_config.json @@ -0,0 +1,82 @@ +{ + "基础奖励": { + "金币": { + "最小值": 200, + "最大值": 500, + "图标": "💰", + "颜色": "#FFD700" + }, + "经验": { + "最小值": 50, + "最大值": 120, + "图标": "⭐", + "颜色": "#00BFFF" + } + }, + "种子奖励": { + "普通": { + "概率": 0.6, + "数量范围": [2, 5], + "种子池": ["小麦", "胡萝卜", "土豆", "稻谷"] + }, + "优良": { + "概率": 0.25, + "数量范围": [2, 4], + "种子池": ["玉米", "番茄", "洋葱", "大豆", "豌豆", "黄瓜", "大白菜"] + }, + "稀有": { + "概率": 0.12, + "数量范围": [1, 3], + "种子池": ["草莓", "花椰菜", "柿子", "蓝莓", "树莓"] + }, + "史诗": { + "概率": 0.025, + "数量范围": [1, 2], + "种子池": ["葡萄", "南瓜", "芦笋", "茄子", "向日葵", "蕨菜"] + }, + "传奇": { + "概率": 0.005, + "数量范围": [1, 1], + "种子池": ["西瓜", "甘蔗", "香草", "甜菜", "人参", "富贵竹", "芦荟", "哈密瓜"] + } + }, + "连续签到奖励": { + "第3天": { + "额外金币": 100, + "额外经验": 50, + "描述": "连续签到奖励" + }, + "第7天": { + "额外金币": 200, + "额外经验": 100, + "描述": "一周连击奖励" + }, + "第14天": { + "额外金币": 500, + "额外经验": 200, + "描述": "半月连击奖励" + }, + "第21天": { + "额外金币": 800, + "额外经验": 300, + "描述": "三周连击奖励" + }, + "第30天": { + "额外金币": 1500, + "额外经验": 500, + "描述": "满月连击奖励" + } + }, + "连击倍率": { + "启用": true, + "基础倍率": 1.0, + "每日递增": 0.1, + "最大倍率": 3.0, + "说明": "连续签到可提升奖励倍率" + }, + "历史记录": { + "保存天数": 30, + "清理规则": "超过30天的记录自动清理", + "格式": "年月日时分秒: 奖励描述" + } +} diff --git a/Server/config/lucky_draw_config.json b/Server/config/lucky_draw_config.json new file mode 100644 index 0000000..fefd620 --- /dev/null +++ b/Server/config/lucky_draw_config.json @@ -0,0 +1,113 @@ +{ + "抽奖费用": { + "单抽": 800, + "五连抽": 3600, + "十连抽": 6400 + }, + "概率配置": { + "普通": { + "概率": 0.45, + "金币范围": [100, 300], + "经验范围": [50, 150], + "种子数量": [2, 4] + }, + "优良": { + "概率": 0.25, + "金币范围": [300, 600], + "经验范围": [150, 300], + "种子数量": [1, 3] + }, + "稀有": { + "概率": 0.12, + "金币范围": [600, 1000], + "经验范围": [300, 500], + "种子数量": [1, 2] + }, + "史诗": { + "概率": 0.025, + "金币范围": [1000, 1500], + "经验范围": [500, 800], + "种子数量": [1, 1] + }, + "传奇": { + "概率": 0.005, + "金币范围": [1500, 2500], + "经验范围": [800, 1200], + "种子数量": [1, 1] + }, + "空奖": { + "概率": 0.15, + "提示语": ["谢谢惠顾", "下次再来", "再试一次", "继续努力"] + } + }, + "礼包配置": { + "成长套餐": { + "稀有度": "优良", + "内容": { + "金币": [200, 400], + "经验": [100, 200], + "种子数量": [2, 3] + } + }, + "稀有礼包": { + "稀有度": "稀有", + "内容": { + "金币": [400, 700], + "经验": [200, 350], + "种子数量": [2, 3] + } + }, + "史诗礼包": { + "稀有度": "史诗", + "内容": { + "金币": [700, 1200], + "经验": [350, 600], + "种子数量": [1, 2] + } + }, + "传奇大礼包": { + "稀有度": "传奇", + "内容": { + "金币": [1000, 2000], + "经验": [600, 1000], + "史诗种子数量": [1, 1], + "稀有种子数量": [2, 3] + } + } + }, + "保底机制": { + "十连抽保底": true, + "保底最低稀有度": "稀有" + }, + "奖励类型权重": { + "普通": { + "金币": 0.4, + "经验": 0.3, + "种子": 0.3 + }, + "优良": { + "金币": 0.3, + "经验": 0.2, + "种子": 0.3, + "礼包": 0.2 + }, + "稀有": { + "金币": 0.2, + "经验": 0.2, + "种子": 0.4, + "礼包": 0.2 + }, + "史诗": { + "金币": 0.2, + "经验": 0.2, + "种子": 0.4, + "礼包": 0.2 + }, + "传奇": { + "金币": 0.1, + "经验": 0.1, + "种子": 0.5, + "礼包": 0.3 + } + } +} diff --git a/Server/game_saves/2143323382.json b/Server/game_saves/2143323382.json index f01217a..1498153 100644 --- a/Server/game_saves/2143323382.json +++ b/Server/game_saves/2143323382.json @@ -1,13 +1,13 @@ { - "experience": 1858, - "level": 26, - "money": 1223582, + "experience": 1826, + "level": 27, + "money": 1214966, "farm_name": "柚大青の小农场", "player_name": "柚大青", "user_name": "2143323382", "user_password": "tyh@19900420", - "last_login_time": "2025年07月09日19时17分38秒", - "total_login_time": "5时0分7秒", + "last_login_time": "2025年07月12日21时05分43秒", + "total_login_time": "5时10分30秒", "farm_lots": [ { "crop_type": "", @@ -560,286 +560,23 @@ "土地等级": 0 } ], - "player_bag": [], + "player_bag": [ + { + "name": "稻谷", + "quality": "普通", + "count": 2 + }, + { + "name": "土豆", + "quality": "普通", + "count": 3 + } + ], "total_likes": 3, "last_water_reset_date": "2025-06-05", - "daily_check_in": { - "2025-06-03": { - "rewards": { - "coins": 259, - "exp": 75, - "seeds": [ - { - "name": "土豆", - "quantity": 5, - "quality": "普通" - }, - { - "name": "小麦", - "quantity": 4, - "quality": "普通" - }, - { - "name": "稻谷", - "quantity": 4, - "quality": "普通" - } - ] - }, - "consecutive_days": 0, - "timestamp": 1748950405.029992 - }, - "2025-06-04": { - "rewards": { - "coins": 455, - "exp": 93, - "seeds": [ - { - "name": "小麦", - "quantity": 3, - "quality": "普通" - }, - { - "name": "胡萝卜", - "quantity": 3, - "quality": "普通" - } - ] - }, - "consecutive_days": 1, - "timestamp": 1749033203.8079362 - }, - "2025-06-08": { - "rewards": { - "coins": 376, - "exp": 83, - "seeds": [ - { - "name": "胡萝卜", - "quantity": 3, - "quality": "普通" - } - ] - }, - "consecutive_days": 0, - "timestamp": 1749387590.7727287 - }, - "2025-06-15": { - "rewards": { - "coins": 329, - "exp": 58, - "seeds": [ - { - "name": "胡萝卜", - "quantity": 3, - "quality": "普通" - }, - { - "name": "稻谷", - "quantity": 2, - "quality": "普通" - }, - { - "name": "土豆", - "quantity": 5, - "quality": "普通" - } - ] - }, - "consecutive_days": 0, - "timestamp": 1749994853.8761835 - }, - "2025-06-16": { - "rewards": { - "coins": 219, - "exp": 107, - "seeds": [ - { - "name": "稻谷", - "quantity": 5, - "quality": "普通" - }, - { - "name": "胡萝卜", - "quantity": 4, - "quality": "普通" - } - ] - }, - "consecutive_days": 1, - "timestamp": 1750048317.4814892 - }, - "2025-06-17": { - "rewards": { - "coins": 292, - "exp": 125, - "seeds": [ - { - "name": "胡萝卜", - "quantity": 2, - "quality": "普通" - }, - { - "name": "小麦", - "quantity": 4, - "quality": "普通" - }, - { - "name": "土豆", - "quantity": 5, - "quality": "普通" - } - ] - }, - "consecutive_days": 2, - "timestamp": 1750171931.7031996 - }, - "2025-06-19": { - "rewards": { - "coins": 325, - "exp": 93, - "seeds": [ - { - "name": "小麦", - "quantity": 4, - "quality": "普通" - } - ] - }, - "consecutive_days": 0, - "timestamp": 1750313565.2168045 - }, - "2025-06-20": { - "rewards": { - "coins": 491, - "exp": 119, - "seeds": [ - { - "name": "稻谷", - "quantity": 3, - "quality": "普通" - }, - { - "name": "胡萝卜", - "quantity": 3, - "quality": "普通" - }, - { - "name": "小麦", - "quantity": 2, - "quality": "普通" - } - ] - }, - "consecutive_days": 1, - "timestamp": 1750391114.5208066 - }, - "2025-06-21": { - "rewards": { - "coins": 419, - "exp": 111, - "seeds": [ - { - "name": "小麦", - "quantity": 2, - "quality": "普通" - }, - { - "name": "胡萝卜", - "quantity": 4, - "quality": "普通" - }, - { - "name": "稻谷", - "quantity": 3, - "quality": "普通" - } - ] - }, - "consecutive_days": 2, - "timestamp": 1750474647.3564475 - }, - "2025-06-22": { - "rewards": { - "coins": 312, - "exp": 128, - "seeds": [ - { - "name": "番茄", - "quantity": 5, - "quality": "优良" - }, - { - "name": "豌豆", - "quantity": 5, - "quality": "优良" - }, - { - "name": "玉米", - "quantity": 2, - "quality": "优良" - } - ], - "bonus_coins": 100 - }, - "consecutive_days": 3, - "timestamp": 1750595733.8604188 - }, - "2025-06-23": { - "rewards": { - "coins": 403, - "exp": 67, - "seeds": [ - { - "name": "大豆", - "quantity": 2, - "quality": "优良" - }, - { - "name": "番茄", - "quantity": 4, - "quality": "优良" - } - ], - "bonus_coins": 100 - }, - "consecutive_days": 4, - "timestamp": 1750645219.0674949 - }, - "2025-06-25": { - "rewards": { - "coins": 285, - "exp": 71, - "seeds": [ - { - "name": "胡萝卜", - "quantity": 2, - "quality": "普通" - } - ] - }, - "consecutive_days": 0, - "timestamp": 1750843274.268298 - }, - "2025-06-27": { - "rewards": { - "coins": 264, - "exp": 71, - "seeds": [ - { - "name": "土豆", - "quantity": 3, - "quality": "普通" - } - ] - }, - "consecutive_days": 0, - "timestamp": 1750985100.9851904 - } - }, "体力值": 20, - "体力上次刷新时间": "2025-07-09", - "体力上次恢复时间": 1752023968.6234932, + "体力上次刷新时间": "2025-07-12", + "体力上次恢复时间": 1752323298.9468062, "new_player_gift_claimed": true, "new_player_gift_time": "2025-06-08 20:58:40", "daily_likes": { @@ -971,6 +708,11 @@ "start_time": 1752023968.623608, "claimed_gifts": {}, "total_online_time": 1282.0 + }, + "2025-07-12": { + "start_time": 1752323298.9470074, + "claimed_gifts": {}, + "total_online_time": 623.0 } }, "注册时间": "2025年05月21日15时00分00秒", @@ -1083,12 +825,8 @@ } } ], - "巡逻宠物": [ - "1751716398095" - ], - "出战宠物": [ - "1751716398095" - ], + "巡逻宠物": ["1751716398095"], + "出战宠物": ["1751716398095"], "稻草人配置": { "已拥有稻草人类型": [ "稻草人1" @@ -1126,5 +864,8 @@ "最大经验值": 480, "最大生命值": 106, "当前生命值": 106 + }, + "签到历史": { + "2025年07月12日21时05分47秒": "金币249 经验75 土豆x3" } } \ No newline at end of file diff --git a/server/game_saves/3205788256.json b/server/game_saves/3205788256.json index 8674c92..70b9ac0 100644 --- a/server/game_saves/3205788256.json +++ b/server/game_saves/3205788256.json @@ -557,16 +557,13 @@ "player_name": "树萌芽", "level": 63, "money": 615397111148, - "last_login_time": "2025年07月12日18时58分12秒", - "total_login_time": "161时31分59秒", + "last_login_time": "2025年07月12日19时41分20秒", + "total_login_time": "161时39分12秒", "user_name": "3205788256", "user_password": "tyh@19900420", "last_water_reset_date": "2025-06-06", "daily_likes": {}, "last_check_in_date": "2025-06-01", - "check_in_count": 1, - "daily_check_in": {}, - "lucky_draw_history": [], "total_likes": 1, "体力值": 20, "体力上次刷新时间": "2025-07-12", @@ -574,7 +571,13 @@ "new_player_gift_claimed": true, "new_player_gift_time": "2025-06-08 19:22:41", "session_start_time": 1749878790.288913, - "online_gift": {}, + "online_gift": { + "2025-07-12": { + "start_time": 1752319030.8083963, + "claimed_gifts": {}, + "total_online_time": 433.0 + } + }, "个人简介": "人生啊,就这样吧", "注册时间": "2025年05月21日15时00分00秒", "作物仓库": [],