Files
Sprout-Farm/Script/BigPanel/PlayerRankingPanel.gd
2025-07-12 19:12:13 +08:00

321 lines
12 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Panel
@onready var player_ranking_list : VBoxContainer = $Scroll/PlayerList
@onready var refresh_button : Button = $RefreshButton #刷新玩家排行榜面板按钮
@onready var quit_button : Button = $QuitButton #关闭面板按钮
@onready var search_button: Button = $SearchButton #搜索玩家按钮
@onready var register_player_num: Label = $RegisterPlayerNum #显示注册总人数
#搜索玩家输入框通过输入QQ号来查询
@onready var search_line_edit: LineEdit = $SearchLineEdit
#排序筛选玩家面板按钮,默认按从大到小排序
#排序元素:种子数,等级,在线时长,最后登录时长,点赞数
#筛选元素:是否在线 筛选出在线玩家
@onready var seed_sort_btn: Button = $FiterAndSortHBox/SeedSortBtn
@onready var level_sort_btn: Button = $FiterAndSortHBox/LevelSortBtn
@onready var online_time_sort_btn: Button = $FiterAndSortHBox/OnlineTimeSortBtn
@onready var login_time_sort_btn: Button = $FiterAndSortHBox/LoginTimeSortBtn
@onready var like_num_sort_btn: Button = $FiterAndSortHBox/LikeNumSortBtn
@onready var money_sort_btn: Button = $FiterAndSortHBox/MoneySortBtn
@onready var is_online_sort_btn: Button = $FiterAndSortHBox/IsOnlineSortBtn
#预添加常用的面板
@onready var main_game = get_node("/root/main")
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
@onready var item_store_panel: Panel = $'../ItemStorePanel'
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
@onready var login_panel: PanelContainer = $'../LoginPanel'
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
@onready var crop_store_panel: Panel = $'../CropStorePanel'
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
# 排序状态管理
var current_sort_by = "level" # 当前排序字段
var current_sort_order = "desc" # 当前排序顺序
var filter_online_only = false # 是否只显示在线玩家
var current_search_qq = "" # 当前搜索的QQ号
#下面这是每个玩家要展示的信息直接获取服务器玩家数据json文件来实现
#模板用于复制创建新的玩家条目
@onready var player_info_template : VBoxContainer = $Scroll/PlayerList/PlayerRankingItem
@onready var player_entry_scene : PackedScene = preload("res://GUI/PlayerRankingItem.tscn")
func _ready() -> void:
# 隐藏模板
player_info_template.visible = false
# 连接按钮信号
refresh_button.pressed.connect(_on_refresh_button_pressed)
quit_button.pressed.connect(_on_quit_button_pressed)
search_button.pressed.connect(_on_search_button_pressed)
# 连接排序按钮信号
seed_sort_btn.pressed.connect(func(): _on_sort_button_pressed("seed_count"))
level_sort_btn.pressed.connect(func(): _on_sort_button_pressed("level"))
online_time_sort_btn.pressed.connect(func(): _on_sort_button_pressed("online_time"))
login_time_sort_btn.pressed.connect(func(): _on_sort_button_pressed("login_time"))
like_num_sort_btn.pressed.connect(func(): _on_sort_button_pressed("like_num"))
money_sort_btn.pressed.connect(func(): _on_sort_button_pressed("money"))
is_online_sort_btn.pressed.connect(_on_online_filter_pressed)
# 初始化按钮状态
_update_button_states()
# 排序按钮点击处理
func _on_sort_button_pressed(sort_field: String):
# 如果点击的是当前排序字段,切换排序顺序
if current_sort_by == sort_field:
current_sort_order = "asc" if current_sort_order == "desc" else "desc"
else:
# 切换到新的排序字段,默认降序
current_sort_by = sort_field
current_sort_order = "desc"
# 更新按钮状态
_update_button_states()
# 重新请求排行榜
request_player_rankings()
# 在线筛选按钮点击处理
func _on_online_filter_pressed():
filter_online_only = !filter_online_only
_update_button_states()
request_player_rankings()
# 更新按钮状态显示
func _update_button_states():
# 重置所有排序按钮
var sort_buttons = [seed_sort_btn, level_sort_btn, online_time_sort_btn, login_time_sort_btn, like_num_sort_btn, money_sort_btn]
var sort_fields = ["seed_count", "level", "online_time", "login_time", "like_num", "money"]
var sort_names = ["种子数", "等级", "游玩时间", "登录时间", "点赞数", "金币数"]
for i in range(sort_buttons.size()):
var btn = sort_buttons[i]
var field = sort_fields[i]
var name = sort_names[i]
if current_sort_by == field:
# 当前排序字段,显示排序方向
var arrow = "" if current_sort_order == "desc" else ""
btn.text = name + arrow
btn.modulate = Color.YELLOW
else:
# 非当前排序字段
btn.text = name
btn.modulate = Color.WHITE
# 更新在线筛选按钮
if filter_online_only:
is_online_sort_btn.text = "仅在线✓"
is_online_sort_btn.modulate = Color.GREEN
else:
is_online_sort_btn.text = "全部玩家"
is_online_sort_btn.modulate = Color.WHITE
# 请求玩家排行榜数据
func request_player_rankings():
if not tcp_network_manager_panel:
register_player_num.text = "网络管理器不可用"
register_player_num.modulate = Color.RED
return false
if not tcp_network_manager_panel.is_connected_to_server():
register_player_num.text = "未连接服务器"
register_player_num.modulate = Color.RED
return false
var success = tcp_network_manager_panel.sendGetPlayerRankings(current_sort_by, current_sort_order, filter_online_only, current_search_qq)
if not success:
register_player_num.text = "请求发送失败"
register_player_num.modulate = Color.RED
return false
return true
# 处理玩家排行榜响应
func handle_player_rankings_response(data):
# 重新启用刷新按钮
refresh_button.disabled = false
refresh_button.text = "刷新"
# 检查响应是否成功
if not data.get("success", false):
register_player_num.text = "获取注册人数失败"
register_player_num.modulate = Color.RED
Toast.show("获取排行榜失败:" + data.get("message", "未知错误"), Color.RED)
return
# 显示注册总人数和在线人数
var total_registered = data.get("total_registered_players", 0)
var players_list = data.get("players", [])
var online_count = 0
for player in players_list:
if player.get("is_online", false):
online_count += 1
# 显示搜索和筛选信息
var info_text = "总人数:" + str(int(total_registered)) + "| 在线:" + str(online_count)
if current_search_qq != "":
info_text += "| 搜索:" + current_search_qq
if filter_online_only:
info_text += "| 仅在线"
register_player_num.text = info_text
register_player_num.modulate = Color.CYAN
# 清除现有的玩家条目(除了模板)
for child in player_ranking_list.get_children():
if child != player_info_template:
child.queue_free()
# 添加玩家条目
var players = players_list
for player_data in players:
add_player_entry(player_data)
print("排行榜数据已更新,显示", players.size(), "个玩家,注册总人数:", total_registered)
var result_text = "排行榜已刷新!显示 " + str(players.size()) + " 个玩家"
if current_search_qq != "":
result_text += "(搜索:" + current_search_qq + ""
if filter_online_only:
result_text += "(仅在线)"
Toast.show(result_text, Color.GREEN)
# 添加单个玩家条目
func add_player_entry(player_data):
# 实例化新的玩家条目场景,避免 duplicate 引发的复制错误
var player_entry = player_entry_scene.instantiate()
player_entry.visible = true
player_ranking_list.add_child(player_entry)
# 设置玩家信息
var player_name = player_entry.get_node("HBox/PlayerName")
var player_level = player_entry.get_node("HBox/PlayerLevel")
var player_money = player_entry.get_node("HBox/PlayerMoney")
var player_seed_num = player_entry.get_node("HBox/SeedNum")
var player_online_time = player_entry.get_node("HBox2/OnlineTime")
var player_last_login_time = player_entry.get_node("HBox2/LastLoginTime")
var player_avatar = player_entry.get_node("HBox/PlayerAvatar")
var visit_button = player_entry.get_node("HBox/VisitButton")
var player_is_online_time = player_entry.get_node("HBox2/IsOnlineTime")
var player_like_num = player_entry.get_node("HBox2/LikeNum")
# 填充数据
var username = player_data.get("user_name", "未知")
var display_name = player_data.get("player_name", username)
player_name.text = display_name
#都是整数,不要乱用浮点数
player_level.text = "等级: " + str(int(player_data.get("level", 0)))
player_money.text = "金币: " + str(int(player_data.get("money", 0)))
player_seed_num.text = "种子: " + str(int(player_data.get("seed_count", 0)))
player_online_time.text = "游玩时间: " + player_data.get("total_login_time", "0时0分0秒")
player_last_login_time.text = "最后登录: " + player_data.get("last_login_time", "未知")
# 设置在线状态显示
var is_online = player_data.get("is_online", false)
if is_online:
player_is_online_time.text = "🟢 在线"
player_is_online_time.modulate = Color.GREEN
else:
player_is_online_time.text = "🔴 离线"
player_is_online_time.modulate = Color.GRAY
# 设置点赞数显示
player_like_num.text = "点赞: " + str(int(player_data.get("like_num", 0)))
# 尝试加载玩家头像(使用用户名/QQ号加载头像而不是显示名
if username.is_valid_int():
player_avatar.load_from_url("http://q1.qlogo.cn/g?b=qq&nk=" + username + "&s=100")
# 设置访问按钮
visit_button.pressed.connect(func(): _on_visit_player_pressed(username))
# 访问玩家按钮点击
func _on_visit_player_pressed(username):
#访问玩家后取消禁用相机功能,否则无法恢复
GlobalVariables.isZoomDisabled = false
# 检查网络连接
if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server():
Toast.show("未连接服务器,无法访问玩家", Color.RED)
return
# 检查是否尝试访问自己
if main_game and main_game.user_name == username:
Toast.show("不能访问自己的农场", Color.ORANGE)
return
# 发送访问玩家请求
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("sendVisitPlayer"):
var success = tcp_network_manager_panel.sendVisitPlayer(username)
if success:
Toast.show("正在访问 " + username + " 的农场...", Color.YELLOW)
else:
Toast.show("发送访问请求失败", Color.RED)
else:
Toast.show("网络管理器不可用", Color.RED)
# 刷新按钮点击
func _on_refresh_button_pressed():
# 检查网络连接
if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server():
register_player_num.text = "未连接服务器,无法刷新"
register_player_num.modulate = Color.RED
Toast.show("未连接服务器,无法刷新排行榜", Color.RED)
return
# 显示加载状态
register_player_num.text = "正在刷新排行榜..."
register_player_num.modulate = Color.YELLOW
refresh_button.disabled = true
refresh_button.text = "刷新中..."
# 请求排行榜数据
request_player_rankings()
# 5秒后重新启用按钮防止卡住
await get_tree().create_timer(5.0).timeout
if refresh_button.disabled:
refresh_button.disabled = false
refresh_button.text = "刷新"
if register_player_num.text == "正在刷新排行榜...":
register_player_num.text = "刷新超时,请重试"
register_player_num.modulate = Color.RED
# 退出按钮点击
func _on_quit_button_pressed():
#打开面板后暂时禁用相机功能
GlobalVariables.isZoomDisabled = false
self.hide()
#搜索按钮点击 - 通过QQ号查询玩家
func _on_search_button_pressed():
var search_text = search_line_edit.text.strip_edges()
# 如果搜索框为空,清除搜索条件
if search_text == "":
current_search_qq = ""
Toast.show("已清除搜索条件", Color.YELLOW)
else:
# 验证输入是否为数字QQ号
if not search_text.is_valid_int():
Toast.show("请输入有效的QQ号纯数字", Color.RED)
return
current_search_qq = search_text
Toast.show("搜索QQ号" + search_text, Color.YELLOW)
# 重新请求排行榜
request_player_rankings()