extends Node2D @onready var players_container = $PlayersContainer @onready var tile_map = $Ground var player_nodes := {} # id -> Node func _ready(): $Ground.scale = Vector2(1, 1) if has_node("Water"): $Water.scale = Vector2(1, 1) # Clean setup: trust the scene file var entrance = get_node_or_null("NeighborhoodEntrance") if entrance: entrance.monitorable = true entrance.monitoring = true # Ensure it detects Player (Layer 2) OR Layer 1 just in case entrance.collision_mask = 3 # Layers 1 and 2 if not entrance.body_entered.is_connected(_on_neighborhood_entrance_body_entered): entrance.body_entered.connect(_on_neighborhood_entrance_body_entered) if not entrance.body_exited.is_connected(_on_neighborhood_entrance_body_exited): entrance.body_exited.connect(_on_neighborhood_entrance_body_exited) 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) # Explicitly spawn local player if logged in if NetworkManager.my_id != -1: _spawn_player(NetworkManager.my_id, NetworkManager.player_info["name"], 0, 0, NetworkManager.player_info["skin_id"]) for id in NetworkManager.players: var p = NetworkManager.players[id] _spawn_player(id, p["name"], p["x"], p["y"], p.get("skin_id", 0)) var chat = preload("res://Scenes/UI/ChatHUD.tscn").instantiate() add_child(chat) var player_in_entrance := false func _on_neighborhood_entrance_body_entered(body): print("Body ENTERED Trigger: ", body.name, " (My ID: ", NetworkManager.my_id, ")") # Check if it's the local player if body.name == str(NetworkManager.my_id): player_in_entrance = true print("Player ENTERED entrance area") func _on_neighborhood_entrance_body_exited(body): if body.name == str(NetworkManager.my_id): player_in_entrance = false print("Player EXITED entrance area") func _physics_process(_delta): if player_in_entrance: # Check for Up input while inside the entrance if Input.is_action_pressed("ui_up") or Input.is_key_pressed(KEY_W): _do_room_transition() func _do_room_transition(): var entrance = get_node_or_null("NeighborhoodEntrance") if not entrance: return var local_player = player_nodes.get(NetworkManager.my_id) if not local_player: return player_in_entrance = false # Prevent re-trigger NetworkManager.next_spawn_position = local_player.position + Vector2(0, 32) NetworkManager.send_change_scene("room_" + str(NetworkManager.my_id), Vector2(0, 0)) get_tree().change_scene_to_file("res://Scenes/Room.tscn") func _fill_background(): # Fill base stone floor (standard blue brick at 0,0) # Procedural generation for background # Procedural generation for background for x in range(-50, 150): for y in range(-50, 100): var tile_pos = Vector2i(x, y) # Plaza in the center (0 to 15) if x >= 0 and x < 15 and y >= 0 and y < 15: # Use light gray stone coordinates confirmed in TownTileset.tres var rand_var = randi() % 3 tile_map.set_cell(tile_pos, 5, Vector2i(4 + rand_var, 0)) # (4,0), (5,0), (6,0) else: # Regular floor (blue-ish / darker) if (x + y) % 2 == 0: tile_map.set_cell(tile_pos, 5, Vector2i(1, 0)) else: tile_map.set_cell(tile_pos, 5, Vector2i(2, 0)) func _on_login_ok(_my_id, _players): pass 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_disconnected(): get_tree().change_scene_to_file("res://Scenes/StartMenu.tscn") func _spawn_player(id, _p_name, x, y, _skin_id): # Anti-Ghosting: Check if this player already exists in the tree if players_container.has_node(str(id)): var old_node = players_container.get_node(str(id)) old_node.name = "Ghost_" + str(id) # Rename to avoid duplicate name error during queue_free old_node.queue_free() # Also clean dictionary if player_nodes.has(id): player_nodes.erase(id) var p = preload("res://Scenes/Player.tscn").instantiate() p.name = str(id) # Override position if returning from another scene var spawn_pos = Vector2(x, y) if id == NetworkManager.my_id and NetworkManager.next_spawn_position != Vector2.ZERO: spawn_pos = NetworkManager.next_spawn_position # Reset after use NetworkManager.next_spawn_position = Vector2.ZERO p.position = spawn_pos p.player_id = id p.is_local = (id == NetworkManager.my_id) print("Spawning Player ID: ", id, " Name: ", _p_name, " Is Local: ", p.is_local, " (My ID: ", NetworkManager.my_id, ")") if p.is_local: p.interaction_request.connect(_on_interaction_request) players_container.add_child(p) player_nodes[id] = p func _on_interaction_request(target_id, target_name): print("World received interaction request for: ", target_name) var chat = get_node_or_null("ChatHUD") if chat: if chat.has_method("set_private_target"): chat.set_private_target(target_id, target_name) else: print("ChatHUD missing set_private_target method")