feat: add battlepass slider and quest list tabs to lobby HUD

This commit is contained in:
2026-07-09 18:25:07 +08:00
parent 114748a54f
commit 933119ca56
99 changed files with 3861 additions and 417 deletions
+82 -34
View File
@@ -10,6 +10,8 @@ var _active_chat_context: String = "global"
var _dm_tabs: Dictionary = {}
var _dm_messages: Dictionary = {}
var _chat_config: Dictionary = {"prefix": "", "max_messages": 50, "max_age_days": 0}
var _global_chat_loading: bool = false
var _dm_loading: Dictionary = {}
func _init(p_lobby: Control):
lobby = p_lobby
@@ -19,26 +21,41 @@ func _init(p_lobby: Control):
if lobby.chat_input:
lobby.chat_input.text_submitted.connect(func(_t): _on_chat_send_pressed())
lobby.chat_input.text_changed.connect(_on_chat_input_changed)
var global_btn = lobby.get_node_or_null("%GlobalChatTabBtn")
if global_btn:
global_btn.pressed.connect(func(): switch_chat_tab("global"))
var server_btn = lobby.get_node_or_null("%ServerChatTabBtn")
if server_btn:
server_btn.pressed.connect(func(): switch_chat_tab("server"))
_setup_friend_suggest_ui()
func join_global_chat() -> void:
if _chat_channel != null:
if _chat_channel != null or _global_chat_loading:
return
_global_chat_loading = true
_refresh_chat_display()
var socket = NakamaManager.socket
if not socket or not socket.is_connected_to_host():
push_warning("[Chat] Socket not connected, skipping chat join.")
_global_chat_loading = false
_refresh_chat_display()
return
var result = await socket.join_chat_async(GLOBAL_CHAT_ROOM,
NakamaSocket.ChannelType.Room,
true, false)
if result.is_exception():
push_warning("[Chat] Failed to join global chat: " + result.get_exception().message)
_global_chat_loading = false
_refresh_chat_display()
return
_chat_channel = result
print("[Chat] Joined global channel: ", _chat_channel.id)
@@ -51,26 +68,28 @@ func join_global_chat() -> void:
if cfg_res.has("config"):
_chat_config = cfg_res["config"]
_chat_messages.clear()
var limit: int = _chat_config.get("max_messages", 50)
var history_entries: Array = []
var history_result = await NakamaManager.client.list_channel_messages_async(NakamaManager.session, _chat_channel.id, limit, false)
if not history_result.is_exception() and history_result.messages:
var msgs = history_result.messages.duplicate()
msgs.reverse()
for msg in msgs:
_add_chat_message(msg, false)
history_entries.append(_parse_chat_message(msg))
# Inject admin system prefix if configured
var prefix: String = _chat_config.get("prefix", "")
if not prefix.is_empty():
_chat_messages.insert(0, {
history_entries.insert(0, {
"sender": "SYSTEM",
"content": prefix,
"ts": _get_local_time(),
"date": Time.get_date_string_from_system()
})
_chat_messages = history_entries + _chat_messages
_trim_old_messages()
_global_chat_loading = false
_refresh_chat_display()
func _on_chat_message_received(message) -> void:
@@ -80,29 +99,32 @@ func _on_chat_message_received(message) -> void:
return
_add_chat_message(message, true)
func _add_chat_message(message, refresh_display: bool) -> void:
func _parse_chat_message(message) -> Dictionary:
var text: String = ""
var parsed = JSON.parse_string(message.content)
if typeof(parsed) == TYPE_DICTIONARY:
text = parsed.get("msg", message.content)
else:
text = message.content
var sender: String = message.username
if sender.is_empty() and message.sender_id:
sender = message.sender_id.substr(0, 8)
elif sender.is_empty():
sender = "Unknown"
var ts_str: String = _format_nakama_time(message.create_time)
_chat_messages.append({
return {
"sender": sender,
"content": text,
"ts": ts_str,
"date": message.create_time.substr(0, 10) if message.create_time else Time.get_date_string_from_system()
})
}
func _add_chat_message(message, refresh_display: bool) -> void:
_chat_messages.append(_parse_chat_message(message))
if refresh_display:
_trim_old_messages()
_refresh_chat_display()
@@ -209,16 +231,21 @@ func _open_dm_tab(user_id: String, username: String) -> void:
if not _dm_tabs.has(user_id):
_create_dm_tab(user_id, username)
_dm_messages[user_id] = []
_dm_loading[user_id] = true
switch_chat_tab(user_id)
var history = await FriendManager.get_dm_history(user_id)
var my_id = NakamaManager.session.user_id if NakamaManager.session else ""
var history_entries: Array = []
for entry in history:
var is_self = entry.get("from") == my_id
var sender_name = "You" if is_self else username
var ts = _format_nakama_time(entry.get("create_time", ""))
_dm_messages[user_id].append({"sender": sender_name, "content": entry.get("msg", ""), "ts": ts})
history_entries.append({"sender": sender_name, "content": entry.get("msg", ""), "ts": ts})
_dm_messages[user_id] = history_entries + _dm_messages[user_id]
_dm_loading[user_id] = false
if _active_chat_context == user_id:
_refresh_chat_display()
else:
@@ -256,16 +283,34 @@ func _close_dm_tab(user_id: String) -> void:
func switch_chat_tab(context_id: String) -> void:
_active_chat_context = context_id
_refresh_chat_display()
var tabs_container = lobby.get_node_or_null("%ChatTabsContainer")
if tabs_container:
var global_btn = lobby.get_node_or_null("%GlobalChatTabBtn")
if global_btn:
global_btn.modulate = Color(1.0, 1.0, 1.0) if context_id == "global" else Color(0.6, 0.6, 0.6)
for u_id in _dm_tabs:
var tab_hbox = _dm_tabs[u_id]
tab_hbox.modulate = Color(1.0, 1.0, 1.0) if context_id == u_id else Color(0.6, 0.6, 0.6)
var global_btn = lobby.get_node_or_null("%GlobalChatTabBtn")
if global_btn:
global_btn.button_pressed = (context_id == "global")
var server_btn = lobby.get_node_or_null("%ServerChatTabBtn")
if server_btn:
server_btn.button_pressed = (context_id == "server")
for u_id in _dm_tabs:
var tab_hbox = _dm_tabs[u_id]
var dm_btn = tab_hbox.get_node_or_null("DMTabBtn")
if dm_btn:
dm_btn.button_pressed = (context_id == u_id)
if lobby.chat_input:
lobby.chat_input.placeholder_text = "Send to %s..." % _get_context_display_name(context_id)
func _get_context_display_name(context_id: String) -> String:
if context_id == "global":
return "World"
if context_id == "server":
return "Server"
if _dm_tabs.has(context_id):
var btn = _dm_tabs[context_id].get_node_or_null("DMTabBtn")
if btn:
return btn.text
return "Chat"
func _setup_friend_suggest_ui() -> void:
lobby._friend_suggest_panel = lobby.get_node_or_null("%FriendSuggestPanel")
@@ -331,12 +376,15 @@ func _refresh_chat_display() -> void:
messages_to_show = []
for msg in messages_to_show:
var ts: String = msg.get("ts", "")
var sender: String = msg.get("sender", "?")
var text: String = msg.get("content", "")
lobby.chat_display.append_text("[color=#888888][%s][/color] [b]%s:[/b] %s\n" % [ts, sender, text])
lobby.chat_display.append_text("[b]%s[/b]\n[color=#c7d3e0]%s[/color]\n\n" % [sender, text])
var is_loading: bool = _global_chat_loading if _active_chat_context == "global" else _dm_loading.get(_active_chat_context, false)
if is_loading:
lobby.chat_display.append_text("[i][color=#8a97a8]Loading messages...[/color][/i]\n")
if lobby.chat_display:
var scrollbar = lobby.chat_display.get_v_scroll_bar()
if scrollbar: