extends Node2D @onready var tile_map = $TileMapLayer @onready var players_container = $PlayersContainer var player_nodes := {} # id -> Node func _ready(): # Visual setup tile_map.scale = Vector2(0.5, 0.5) NetworkManager.login_ok.connect(_on_login_ok) NetworkManager.player_joined.connect(_on_player_joined) NetworkManager.player_left.connect(_on_player_left) NetworkManager.player_moved.connect(_on_player_moved) NetworkManager.disconnected.connect(_on_disconnected) # Handle disconnect NetworkManager.chat_message_received.connect(_on_chat_message_received) # Reuse chat logic if desired # Spawn myself manually since scene_peers excludes self _spawn_player(NetworkManager.my_id, NetworkManager.player_info["name"], 0, 0, NetworkManager.player_info["skin_id"]) # Spawn existing players (including self if already in list, but we usually spawn self manually or via list) # Since we just transitioned, NetworkManager.players contains the new list from 'scene_peers' message for id in NetworkManager.players: var p = NetworkManager.players[id] _spawn_player(id, p["name"], p["x"], p["y"], p.get("skin_id", 0)) # Chat UI var chat = preload("res://Scenes/UI/ChatHUD.tscn").instantiate() add_child(chat) func _spawn_player(id, _p_name, x, y, _skin_id): if player_nodes.has(id): return # Prevent duplicate var p = preload("res://Scenes/Player.tscn").instantiate() p.name = str(id) # For local player in Room, we might want a fixed spawn point (0,0) or the one from server # If it's local player, we usually force it to (0,0) on entry if id == NetworkManager.my_id: p.position = Vector2(0, 0) else: p.position = Vector2(x, y) p.player_id = id p.is_local = (id == NetworkManager.my_id) players_container.add_child(p) player_nodes[id] = p if p.is_local: var camera = Camera2D.new() camera.make_current() p.add_child(camera) func _on_login_ok(_my_id, _players): # Refresh players if we get a full update for id in player_nodes: if id != NetworkManager.my_id: player_nodes[id].queue_free() player_nodes.clear() for id in NetworkManager.players: var p = NetworkManager.players[id] _spawn_player(id, p["name"], p["x"], p["y"], p.get("skin_id", 0)) func _on_player_joined(id, p_name, x, y, skin_id): _spawn_player(id, p_name, x, y, skin_id) func _on_player_left(id): if player_nodes.has(id): player_nodes[id].queue_free() player_nodes.erase(id) func _on_player_moved(id, x, y, flip_h, frame): if player_nodes.has(id): player_nodes[id].set_remote_state(Vector2(x, y), flip_h, frame) func _on_chat_message_received(sender_id, text): # Chat HUD handles it via signals usually, but if we need bubbles: if player_nodes.has(sender_id): player_nodes[sender_id].show_bubble(text) func _on_disconnected(): get_tree().change_scene_to_file("res://Scenes/StartMenu.tscn") func _on_exit_body_entered(body): if body.name == str(NetworkManager.my_id): # Return to the world NetworkManager.send_change_scene("world", NetworkManager.next_spawn_position) get_tree().change_scene_to_file("res://Scenes/World.tscn")