Files
mmo/scenes/world/world_manager.gd
Marek Le 2d4002bd3f refactor
2026-05-09 23:37:26 +02:00

75 lines
2.6 KiB
GDScript

extends Node3D
const PLAYER_SCENE: PackedScene = preload("res://scenes/entities/player/player.tscn")
@onready var players_root: Node3D = $EntityRoot/Players
@onready var ground_shape: CollisionShape3D = $Ground/GroundShape
@onready var npc_system: Node = $Systems/NpcSystem
@onready var wave_system: Node = $Systems/WaveSystem
func _ready() -> void:
add_to_group("world")
_setup_ground_collision()
Net.world_ready.connect(_on_world_ready)
Net.peer_world_loaded.connect(_on_peer_world_loaded)
if Net.is_host():
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
Net.reset_world_ready()
Net.mark_world_loaded()
func _exit_tree() -> void:
if Net.is_host():
if multiplayer.peer_connected.is_connected(_on_peer_connected):
multiplayer.peer_connected.disconnect(_on_peer_connected)
if multiplayer.peer_disconnected.is_connected(_on_peer_disconnected):
multiplayer.peer_disconnected.disconnect(_on_peer_disconnected)
if Net.world_ready.is_connected(_on_world_ready):
Net.world_ready.disconnect(_on_world_ready)
if Net.peer_world_loaded.is_connected(_on_peer_world_loaded):
Net.peer_world_loaded.disconnect(_on_peer_world_loaded)
func _setup_ground_collision() -> void:
var shape := WorldBoundaryShape3D.new()
shape.plane = Plane(Vector3.UP, 0.0)
ground_shape.shape = shape
func _on_world_ready() -> void:
if not Net.is_host():
return
_spawn_player(1)
for id in multiplayer.get_peers():
_spawn_player(id)
npc_system.spawn_default_npcs()
if wave_system and wave_system.has_method("start_wave"):
wave_system.start_wave(GameState.current_wave)
func _on_peer_connected(id: int) -> void:
Net.tell_peer_to_load_scene(id, GameState.SCENE_WORLD)
func _on_peer_world_loaded(peer_id: int) -> void:
if not Net.is_host():
return
_spawn_player(peer_id)
func _on_peer_disconnected(id: int) -> void:
var node := players_root.get_node_or_null(str(id))
if node:
node.queue_free()
func _spawn_player(peer_id: int) -> void:
if players_root.get_node_or_null(str(peer_id)) != null:
return
var p: CharacterBody3D = PLAYER_SCENE.instantiate()
p.name = str(peer_id)
var spawn := _spawn_position_for(peer_id)
players_root.add_child(p, true)
p.global_position = spawn
func _spawn_position_for(peer_id: int) -> Vector3:
if GameState.portal_return_position != Vector3.ZERO:
var off: float = float(peer_id) * 0.7
return GameState.portal_return_position + Vector3(cos(off) * 1.2, 1.5, sin(off) * 1.2)
var angle: float = wrapf(float(peer_id) * 1.7, 0.0, TAU)
return Vector3(cos(angle) * 5.0, 1.5, sin(angle) * 5.0)