extends Node3D ## World manager. Owns the multiplayer spawners and the world-space main menu, ## and turns NetworkManager's session events into spawned/despawned players and ## seeded items. ## ## Startup: ## - Command-line session (--server/--join): skip the menu, behave headlessly. ## - Otherwise: embody a local player (so they can point) and show the menu; the ## Host/Join/Solo buttons start the actual session. const PLAYER_SCENE := preload("res://Player/Player.tscn") const CUBE_SCENE := "res://Items/PickupCube.tscn" @onready var _players_spawner: MultiplayerSpawner = $PlayersSpawner @onready var _items_spawner: MultiplayerSpawner = $ItemsSpawner @onready var _menu: Node3D = $NetworkMenu func _ready() -> void: NetworkManager.register_world(self, _players_spawner, _items_spawner) NetworkManager.player_joined.connect(_on_player_joined) NetworkManager.player_left.connect(_on_player_left) NetworkManager.session_started.connect(_on_session_started) NetworkManager.connection_failed.connect(_on_connection_failed) _menu.host_pressed.connect(_on_menu_host) _menu.join_pressed.connect(_on_menu_join) _menu.solo_pressed.connect(_on_menu_solo) # Start any command-line driven session now that we are listening. NetworkManager.world_ready() if NetworkManager.is_online(): # Command-line session: no menu. _menu.hide_menu() if _owns_spawning(): _spawn_starting_items() else: # Show the menu; embody a local player so they can point at it. _spawn_player(1) _menu.show_menu() # --- Menu button handlers -------------------------------------------------- func _on_menu_host() -> void: _menu.hide_menu() NetworkManager.host() # keeps the already-spawned local player (id 1) _spawn_starting_items() func _on_menu_solo() -> void: _menu.hide_menu() _spawn_starting_items() func _on_menu_join(ip: String) -> void: _menu.set_status("Connecting to %s ..." % ip) # Our placeholder id "1" belongs to the host once we join; drop it and let # the server spawn our real player. _despawn_player(1) NetworkManager.join(ip) func _on_session_started(is_server: bool) -> void: if not is_server: # Connected to a host as a client. _menu.hide_menu() func _on_connection_failed() -> void: _menu.set_status("Connection failed — check the IP") _spawn_player(1) # restore embodiment _menu.show_menu() # --- Player / item spawning ------------------------------------------------ func _on_player_joined(peer_id: int) -> void: if NetworkManager.is_server(): _spawn_player(peer_id) func _on_player_left(peer_id: int) -> void: if NetworkManager.is_server(): _despawn_player(peer_id) func _spawn_player(peer_id: int) -> void: if has_node(str(peer_id)): return var p := PLAYER_SCENE.instantiate() p.name = str(peer_id) add_child(p) func _despawn_player(peer_id: int) -> void: var n := get_node_or_null(str(peer_id)) if n: n.queue_free() func _owns_spawning() -> bool: return not NetworkManager.is_online() or NetworkManager.is_server() func _spawn_starting_items() -> void: NetworkManager.spawn_item(CUBE_SCENE, Transform3D(Basis(), Vector3(-0.705, 1.576, -1.032))) NetworkManager.spawn_item(CUBE_SCENE, Transform3D(Basis(), Vector3(0.283, 1.561, -1.066)))