feat: Add initial lobby and main scenes with Nakama and lobby management scripts.

This commit is contained in:
2025-12-06 02:27:08 +08:00
parent 5000f3e269
commit 438c0c0d6e
9 changed files with 1061 additions and 39 deletions
+73 -38
View File
@@ -9,7 +9,6 @@ var ui_manager
var obstacle_manager
# Minimal local state
var match_id_input: LineEdit
var _connection_check_timer: float = 0.0
func _ready():
@@ -27,7 +26,12 @@ func _ready():
ui_manager.setup_action_buttons(_set_action_state_callback)
ui_manager.setup_playerboard_ui()
_setup_obstacle_ui()
_setup_match_input()
# Auto-start game if coming from lobby (already connected to match)
if NakamaManager.is_connected_to_nakama() and multiplayer.get_unique_id() != 0:
print("Coming from lobby - auto-starting game...")
await get_tree().process_frame
_auto_start_from_lobby()
func _init_managers():
# Create and attach scene managers
@@ -41,13 +45,6 @@ func _init_managers():
add_child(obstacle_manager)
obstacle_manager.initialize($EnhancedGridMap)
func _setup_match_input():
match_id_input = LineEdit.new()
match_id_input.placeholder_text = "Enter Match ID to Join"
match_id_input.custom_minimum_size = Vector2(200, 30)
match_id_input.position = Vector2(10, 50)
$Menu.add_child(match_id_input)
func _setup_obstacle_ui():
var obstacle_button = Button.new()
obstacle_button.text = "Place Obstacle"
@@ -80,34 +77,9 @@ func _process(delta):
verify_all_connections()
# =============================================================================
# Network Button Handlers
# Network Callbacks
# =============================================================================
func _on_host_pressed():
$NetworkPanel/NetworkInfo/NetworkSideDisplay.text = "Server (Creating Match...)"
$Menu.visible = false
var success = await NakamaManager.connect_to_nakama_async()
if not success:
$NetworkPanel/NetworkInfo/NetworkSideDisplay.text = "Connection Failed"
$Menu.visible = true
return
NakamaManager.host_game()
func _on_join_pressed():
var match_id = match_id_input.text.strip_edges()
if match_id.is_empty():
print("Please enter a Match ID")
return
$NetworkPanel/NetworkInfo/NetworkSideDisplay.text = "Client (Joining...)"
$Menu.visible = false
var success = await NakamaManager.connect_to_nakama_async()
if not success:
$NetworkPanel/NetworkInfo/NetworkSideDisplay.text = "Connection Failed"
$Menu.visible = true
return
NakamaManager.join_game(match_id)
func _on_match_joined(match_id: String):
$NetworkPanel/NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id())
@@ -151,16 +123,79 @@ func _setup_host_game():
_update_player_goals_ui(0, host_goals)
ui_manager.update_playerboard_ui()
# Add bots
if GameStateManager.enable_bots:
# Spawn client players that joined via lobby
var lobby_players = LobbyManager.get_players()
for lobby_player in lobby_players:
var peer_id = lobby_player.get("id", 0)
if peer_id != 1 and peer_id != 0: # Skip host (1) and invalid (0)
print("Spawning lobby player: ", peer_id)
await get_tree().create_timer(0.3).timeout
_spawn_lobby_client(peer_id)
# Add bots (only if no lobby players connected)
if GameStateManager.enable_bots and lobby_players.size() <= 1:
for i in range(2, GameStateManager.max_players + 1):
_add_bot(i)
_start_game()
func _spawn_lobby_client(peer_id: int):
"""Spawn a client player that was in the lobby."""
if has_node(str(peer_id)):
return
var player_character = PlayerManager.add_player_character(peer_id)
add_child(player_character)
player_character.add_to_group("Players", true)
GameStateManager.add_player(peer_id)
# Tell all clients to create this player
rpc("add_newly_connected_player_character", peer_id)
# Wait for player to be ready then assign goals
await get_tree().create_timer(0.3).timeout
var player_index = GameStateManager.players.find(peer_id)
if player_index >= 0 and player_index < GoalManager.preset_goals.size():
var player_goals = GoalManager.preset_goals[player_index].duplicate()
player_character.goals = player_goals
call_deferred("_deferred_set_player_goals", peer_id, player_goals)
func _setup_client_game():
"""Setup client when transitioning from lobby."""
var my_id = multiplayer.get_unique_id()
print("Client setup - my peer ID: ", my_id)
# Create local player immediately
if not has_node(str(my_id)):
var player_character = PlayerManager.add_player_character(my_id)
add_child(player_character)
player_character.add_to_group("Players", true)
GameStateManager.add_player(my_id)
GameStateManager.local_player_character = player_character
ui_manager.set_local_player(player_character)
ui_manager.update_button_states()
print("Created local player for client: ", my_id)
# Wait for host to be ready, then request full sync
await get_tree().create_timer(2.0).timeout
rpc_id(1, "request_full_player_sync", multiplayer.get_unique_id())
rpc_id(1, "request_full_player_sync", my_id)
func _auto_start_from_lobby():
"""Called when main.tscn is loaded from lobby - game is already connected."""
$NetworkPanel/NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id())
# Get match ID from LobbyManager
var match_id = LobbyManager.current_room.get("match_id", "")
var short_id = match_id.substr(0, 8) if match_id.length() > 8 else match_id
if multiplayer.is_server():
print("Auto-starting as HOST - Match: ", short_id)
$NetworkPanel/NetworkInfo/NetworkSideDisplay.text = "Host (Match: %s)" % short_id
_setup_host_game()
else:
print("Auto-starting as CLIENT - Match: ", short_id)
$NetworkPanel/NetworkInfo/NetworkSideDisplay.text = "Client (Match: %s)" % short_id
_setup_client_game()
func _start_game():
if multiplayer.is_server():