diff --git a/examples/multiplayer-fps/scripts/player-spawner.gd b/examples/multiplayer-fps/scripts/player-spawner.gd index a50d19d..d247d6c 100644 --- a/examples/multiplayer-fps/scripts/player-spawner.gd +++ b/examples/multiplayer-fps/scripts/player-spawner.gd @@ -2,6 +2,10 @@ extends Node @export var player_scene: PackedScene +## Whether to spawn an avatar for the host (peer 1) when on_server_start fires. +## Set to false for dedicated server operation. +@export var spawn_host_avatar: bool = true + var t_spawn_points: Array[Marker3D] = [] var ct_spawn_points: Array[Marker3D] = [] var team_manager: TeamManager @@ -43,12 +47,20 @@ func _handle_connected(id: int): _spawn(id) func _handle_host(): + if not spawn_host_avatar: + print("[PlayerSpawner] Dedicated server mode — skipping host avatar") + if round_manager: + round_manager.start_match() + return _spawn(1) # Auto-start match if round_manager: round_manager.start_match() func _handle_new_peer(id: int): + if id == 1 and not spawn_host_avatar: + print("[PlayerSpawner] Skipping spawn for peer 1 (dedicated server)") + return _spawn(id) if multiplayer.is_server(): team_manager.sync_to_peer(id) diff --git a/run_server.sh b/run_server.sh new file mode 100644 index 0000000..70358a9 --- /dev/null +++ b/run_server.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd /home/oplabs/tactical-shooter +exec ~/.local/bin/godot --headless --scene res://scenes/headless_server.tscn -- --port 34201 --rcon-password test123 > /tmp/server_output.log 2>&1 \ No newline at end of file diff --git a/scripts/headless_server.gd b/scripts/headless_server.gd index ad65710..fee8c8c 100644 --- a/scripts/headless_server.gd +++ b/scripts/headless_server.gd @@ -55,6 +55,14 @@ func _ready() -> void: # Start RCON admin console _start_rcon() + # Set dedicated server flag on the player spawner to prevent + # spawning a host avatar (peer 1) that would cause rollback errors. + # Must be set before the ENet server starts (before on_server_start fires). + var spawner = _game_scene.get_node_or_null("Network/Player Spawner") + if spawner: + spawner.spawn_host_avatar = false + print("[HeadlessServer] Set spawn_host_avatar=false on PlayerSpawner") + # Wait for game scene to enter the tree await get_tree().process_frame await get_tree().process_frame