diff --git a/scenes/main.gd b/scenes/main.gd index 541bf18..f662968 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -325,41 +325,76 @@ func _on_peer_connected(new_peer_id): # Increase delay to ensure scene is ready await get_tree().create_timer(1.5).timeout - # Sync full state first + # First sync game state rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode) + rpc_id(new_peer_id, "sync_preset_goals", preset_goals) - # Then add players in correct order - for peer_id in players: - if peer_id != new_peer_id: # Don't add the new player yet - rpc_id(new_peer_id, "add_player_character", peer_id) - # Sync existing player's goals immediately + # Wait a bit for the client to process state + await get_tree().create_timer(0.5).timeout + + # Then sync all existing players in order + var sorted_players = players.duplicate() + sorted_players.sort() + for peer_id in sorted_players: + if peer_id != new_peer_id: + # First ensure player exists var player = get_node_or_null(str(peer_id)) if player: - rpc_id(new_peer_id, "sync_player_goals", peer_id, player.goals) + # Sync player's full state + var player_data = { + "position": player.current_position, + "goals": player.goals, + "playerboard": player.playerboard + } + rpc_id(new_peer_id, "sync_existing_player", peer_id, player_data) + await get_tree().create_timer(0.1).timeout # Small delay between players # Finally add the new player + await get_tree().create_timer(0.5).timeout add_player_character(new_peer_id) rpc("add_newly_connected_player_character", new_peer_id) - # Get next available bot ID and replace it + # Replace bot if needed if bots.size() > 0: replace_bot_with_player(new_peer_id) - - # Force sync all players' goals to everyone - for player in get_tree().get_nodes_in_group("Players"): - var player_id = String(player.name).to_int() - rpc("sync_player_goals", player_id, player.goals) - # Update everyone's UI + # Final sync of all goals + await get_tree().create_timer(0.5).timeout rpc("force_update_all_goals") -@rpc("call_local") -func force_update_all_goals(): - # Force update the UI for all players - update_all_players_goals() +@rpc("reliable") +func sync_existing_player(peer_id: int, player_data: Dictionary): + # Create player if doesn't exist + if not has_node(str(peer_id)): + var player_character = player_scene.instantiate() + player_character.set_multiplayer_authority(peer_id) + player_character.name = str(peer_id) + player_character.current_position = player_data["position"] + add_child(player_character) + player_character.add_to_group("Players", true) - # Also update the boards - update_all_players_boards() + # Get player node and wait a frame to ensure it's ready + await get_tree().create_timer(0.1).timeout + var player = get_node_or_null(str(peer_id)) + if player: + # Apply synced state + player.current_position = player_data["position"] + player.goals = player_data["goals"].duplicate() + player.playerboard = player_data["playerboard"].duplicate() + + # Ensure proper grid-aligned positioning + player.global_position = Vector3( + player_data["position"].x * 2 + 1, # cell_size.x = 2 + 1.0, + player_data["position"].y * 2 + 1 # cell_size.z = 2 + ) + + # Force position sync + player.rpc("sync_position", player_data["position"]) + + # Update UI + update_all_players_goals() + update_all_players_boards() func _on_peer_disconnected(peer_id): if multiplayer.is_server(): @@ -369,17 +404,35 @@ func _on_peer_disconnected(peer_id): @rpc("any_peer", "call_local") func add_player_character(peer_id): + # Check if player already exists + if has_node(str(peer_id)): + return + connected_peer_ids.append(peer_id) var player_character = player_scene.instantiate() player_character.set_multiplayer_authority(peer_id) + player_character.name = str(peer_id) + # Handle bot replacement position if multiplayer.is_server() and bots.size() > 0: var bot_to_replace = get_node_or_null(str(bots[0])) if bot_to_replace: player_character.current_position = bot_to_replace.current_position + # Set initial grid-aligned position + player_character.global_position = Vector3( + bot_to_replace.current_position.x * 2 + 1, + 1.0, + bot_to_replace.current_position.y * 2 + 1 + ) add_child(player_character) player_character.add_to_group("Players", true) + + # Force position sync after adding to tree + if multiplayer.is_server(): + await get_tree().create_timer(0.1).timeout + player_character.rpc("sync_position", player_character.current_position) + # Set goals based on player ID if server if multiplayer.is_server(): var goal_index = peer_id - 1 @@ -620,13 +673,12 @@ func update_all_players_boards(): # Board 1 should show host (server) var host_player = null - # Find host player (ID 1) for player in all_players: if int(String(player.name)) == 1: host_player = player break - # Update host board + # Update host board (board 1) var host_board = all_player_boards.get_node("1") if host_player and host_board and host_board.has_node("PlayerboardUI"): host_board.visible = true @@ -634,22 +686,34 @@ func update_all_players_boards(): for slot_idx in range(25): update_board_slot(board_ui, slot_idx, host_player.playerboard[slot_idx]) - # Sort remaining players by ID for boards 2-4 - var other_players = all_players.filter(func(p): return int(String(p.name)) != 1) - other_players.sort_custom(func(a, b): return int(String(a.name)) < int(String(b.name))) + # Sort remaining players by ID for boards 2,3,4 + var other_players = all_players.filter(func(p): + var id = int(String(p.name)) + return id != 1 and not p.is_in_group("Bots") # Exclude host and bots + ) + other_players.sort_custom(func(a, b): + return int(String(a.name)) < int(String(b.name)) + ) - # Update boards 2-4 with remaining players + # Update client boards - board 2 for first client, board 3 for second client, etc. for i in range(min(other_players.size(), 3)): - var board_num = i + 2 # boards 2,3,4 + var board_idx = i + 2 # Start from board 2 var player = other_players[i] - var board = all_player_boards.get_node(str(board_num)) + var board = all_player_boards.get_node(str(board_idx)) if board and board.has_node("PlayerboardUI"): board.visible = true + board.name = str(board_idx) # Ensure board name matches index var board_ui = board.get_node("PlayerboardUI") for slot_idx in range(25): update_board_slot(board_ui, slot_idx, player.playerboard[slot_idx]) + # Hide unused boards + for i in range(other_players.size() + 2, 5): + var unused_board = all_player_boards.get_node_or_null(str(i)) + if unused_board: + unused_board.visible = false + # Restore previous active tab all_player_boards.current_tab = current_tab diff --git a/scenes/player.gd b/scenes/player.gd index 529691b..916e500 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -40,9 +40,13 @@ var rotation_speed: float = 10.0 var highlighted_cells = [] func _ready(): + # Ensure name is set first name = str(get_multiplayer_authority()) $Name.text = str(name) + # Wait briefly to ensure proper scene setup + await get_tree().create_timer(0.1).timeout + # More robust way to get the main scene var main_scene = get_tree().get_root().get_node_or_null("Main") if not main_scene: @@ -100,7 +104,15 @@ func _ready(): #append_random_goals() playerboard.resize(25) playerboard.fill(-1) - + + # Ensure proper initial positioning + global_position = Vector3( + current_position.x * cell_size.x + cell_size.x * 0.5, + 1.0, + current_position.y * cell_size.z + cell_size.z * 0.5 + ) + if is_multiplayer_authority(): + rpc("sync_position", current_position) @rpc("any_peer", "call_local") func sync_bot_status(is_bot_status: bool): @@ -1041,3 +1053,23 @@ func bot_arrange_item(from_slot: int, to_slot: int): has_performed_action = true action_points -= 2 _after_action_completed() + +func update_visual_position(): + # Ensure proper grid-aligned positioning + global_position = Vector3( + current_position.x * cell_size.x + cell_size.x * 0.5, + 1.0, + current_position.y * cell_size.z + cell_size.z * 0.5 + ) + if is_multiplayer_authority(): + rpc("sync_position", current_position) + +@rpc("any_peer", "call_local") +func sync_position(pos: Vector2): + current_position = pos + # Ensure proper grid-aligned positioning + global_position = Vector3( + current_position.x * cell_size.x + cell_size.x * 0.5, + 1.0, + current_position.y * cell_size.z + cell_size.z * 0.5 + )