feat: Implement core lobby system including UI, player management, and game mode settings.

This commit is contained in:
2026-03-16 05:21:49 +08:00
parent f4307a8405
commit 71d688ed63
7 changed files with 84 additions and 13 deletions
+7
View File
@@ -7,6 +7,7 @@ extends Control
@onready var browse_rooms_btn = $MainMenuPanel/VBoxContainer/ButtonSection/BrowseRoomsBtn
@onready var main_menu_profile_btn = $MainMenuPanel/VBoxContainer/ButtonSection/ProfileBtn
@onready var lobby_settings_btn = $MainMenuPanel/VBoxContainer/ButtonSection/SettingsBtn
@onready var quit_btn = $MainMenuPanel/VBoxContainer/ButtonSection/QuitBtn
# UI References - Server Selection
@onready var server_option = $MainMenuPanel/VBoxContainer/ServerSelectionSection/ServerOption
@@ -142,6 +143,8 @@ func _ready():
lobby_settings_btn.pressed.connect(_on_settings_pressed)
if leaderboard_btn:
leaderboard_btn.pressed.connect(_on_leaderboard_pressed)
if quit_btn:
quit_btn.pressed.connect(_on_quit_pressed)
# Connect Server Selection signals
if server_option:
@@ -585,6 +588,10 @@ func _on_logout_pressed() -> void:
AuthManager.logout()
_go_to_login()
func _on_quit_pressed() -> void:
print("[Lobby] Quitting game...")
get_tree().quit()
func _on_settings_pressed():
var settings_menu = get_node_or_null("SettingsMenu")
if not settings_menu:
+7 -1
View File
@@ -151,11 +151,17 @@ theme_override_font_sizes/font_size = 16
text = "SETTINGS"
[node name="ProfileBtn" type="Button" parent="MainMenuPanel/VBoxContainer/ButtonSection" unique_id=1640960506]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
custom_minimum_size = Vector2(0, 36)
theme_override_font_sizes/font_size = 14
text = "PROFILE"
[node name="QuitBtn" type="Button" parent="MainMenuPanel/VBoxContainer/ButtonSection" unique_id=123456780]
layout_mode = 2
custom_minimum_size = Vector2(0, 36)
theme_override_font_sizes/font_size = 14
text = "QUIT GAME"
[node name="RoomListPanel" type="PanelContainer" parent="." unique_id=1782359692]
visible = false
layout_mode = 1
+25 -9
View File
@@ -1286,7 +1286,8 @@ func create_bot_with_state(bot_id: int, pos: Vector2i, p_score: int, p_goals: Ar
func _on_host_disconnected():
"""Called when the host leaves. Returns clients to the main menu."""
print("[Main] Host disconnected. Match terminated. Returning to lobby...")
print("[Main] Host disconnected. Match terminated. Cleaning up and returning to lobby...")
LobbyManager.leave_room()
get_tree().change_scene_to_file("res://scenes/lobby.tscn")
func _on_rematch_starting():
@@ -1575,6 +1576,14 @@ func sync_grid_item(x: int, y: int, z: int, item: int):
# OR Layer 1 is already a wall (4)
if f0 in [4, -1] or f1 == 4:
return
# TEKTON DOORS: Prevent placing items on portal doors
if LobbyManager.is_game_mode(GameMode.Mode.TEKTON_DOORS):
var doors = get_tree().get_nodes_in_group("PortalDoors")
for door in doors:
var door_grid = enhanced_gridmap.local_to_map(enhanced_gridmap.to_local(door.global_position))
if door_grid.x == x and door_grid.z == z:
return
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
# Force visual update
@@ -1601,6 +1610,17 @@ func sync_grid_items_batch(data: Array):
if f0 in [4, -1] or f1 == 4:
continue
# TEKTON DOORS: Prevent placing items on portal doors
if LobbyManager.is_game_mode(GameMode.Mode.TEKTON_DOORS) and y == 1:
var doors = get_tree().get_nodes_in_group("PortalDoors")
var on_door = false
for door in doors:
var door_grid = enhanced_gridmap.local_to_map(enhanced_gridmap.to_local(door.global_position))
if door_grid.x == x and door_grid.z == z:
on_door = true
break
if on_door: continue
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
# Force visual update ONCE after batch
@@ -2084,12 +2104,8 @@ func _on_back_to_menu_pressed():
"""Return to lobby/main menu and clean up game state."""
print("[Main] Returning to lobby...")
# Proper ordered cleanup to avoid ghost players
GameStateManager.end_game()
LobbyManager.reset()
# Properly disconnect from Nakama match
_cleanup_multiplayer()
# Proper ordered cleanup to avoid ghost players and desync
LobbyManager.leave_room()
# Small delay to let cleanup settle
await get_tree().create_timer(0.2).timeout
@@ -2357,8 +2373,8 @@ func _on_settings_pressed():
func _on_quit_match_pressed():
get_tree().paused = false # Ensure unpaused when returning to menu
# Properly disconnect from Nakama match
_cleanup_multiplayer()
# Properly disconnect from Nakama and clear lobby state to prevent desync
LobbyManager.leave_room()
# Return to lobby or main menu
get_tree().change_scene_to_file("res://scenes/lobby.tscn")
+5
View File
@@ -50,6 +50,11 @@ properties/3/replication_mode = 2
[node name="PortalDoor" type="StaticBody3D"]
script = ExtResource("1_script")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1, 0)
shape = SubResource("BoxShape3D_trigger")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_portal")