From 597d6dde2d701563e2bb1edeba9e3e1108cdfdf6 Mon Sep 17 00:00:00 2001 From: Shawn Date: Fri, 3 Jul 2026 16:21:35 -0400 Subject: [PATCH] Fix server clock reset in NetworkTimeSynchronizer and client-side peer 1 avatar duplicate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move _clock.set_time(0.) inside the 'if not server' block in NetworkTimeSynchronizer.start() so the server's SystemClock isn't reset to zero — fixes -1.78 billion second offset panic on client - Skip spawning peer 1's avatar on clients (the server replicates all avatars; spawning peer 1 locally creates a duplicate that the dedicated server doesn't have) --- addons/netfox/network-time-synchronizer.gd | 3 +-- examples/multiplayer-fps/scripts/player-spawner.gd | 9 ++++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/netfox/network-time-synchronizer.gd b/addons/netfox/network-time-synchronizer.gd index 2a97934..b2df22b 100644 --- a/addons/netfox/network-time-synchronizer.gd +++ b/addons/netfox/network-time-synchronizer.gd @@ -142,10 +142,9 @@ signal on_panic(offset: float) func start() -> void: if _active: return - - _clock.set_time(0.) if not multiplayer.is_server(): + _clock.set_time(0.) _active = true _sample_idx = 0 _sample_buffer = _RingBuffer.new(sync_samples) diff --git a/examples/multiplayer-fps/scripts/player-spawner.gd b/examples/multiplayer-fps/scripts/player-spawner.gd index 0e6d08b..da8f38b 100644 --- a/examples/multiplayer-fps/scripts/player-spawner.gd +++ b/examples/multiplayer-fps/scripts/player-spawner.gd @@ -73,8 +73,15 @@ func _handle_host(): round_manager.start_match() func _handle_new_peer(id: int): + # On a dedicated server, peer 1 (the server process) has no avatar. + # When a client connects, it receives on_peer_join for peer 1, but + # should skip spawning because the server doesn't have that avatar. + # This also applies to listen-server: the server replicates peer 1's + # avatar to clients; spawning a local copy would duplicate it. + if id == 1 and not multiplayer.is_server(): + print("[PlayerSpawner] Client skipping spawn for peer 1 (server has no dedicated avatar)") + return if _dedicated_server and id == 1: - # Peer 1 is the server itself — no avatar needed return if id == 1 and not spawn_host_avatar: print("[PlayerSpawner] Skipping spawn for peer 1 (spawn_host_avatar=false)")