Fix VR host: empty world, missing jobs, and control-grab failures#145
Open
bdazzledev wants to merge 2 commits into
Open
Fix VR host: empty world, missing jobs, and control-grab failures#145bdazzledev wants to merge 2 commits into
bdazzledev wants to merge 2 commits into
Conversation
Fixes a family of bugs where host-side state that races with world load left the host unable to interact after loading a saved multiplayer game: - NetworkedJunction/NetworkedTurntable: the host gated sends on an Awake-time `initialised = IsHost()` snapshot. If the object awoke before the server started (observed when loading a save), the snapshot was false and, since the host is excluded from the railway-state sync packet, it could never send switch/rotation changes. Now re-checks IsHost() live. - CustomFirstPersonControllerPatch: sent a car-local position tagged with CarId 0 when TrainCar.GetNetId() was momentarily 0 (NetId assignment races with load). The server read the local offset as a world position, placing the host kilometres away, so cab-control authority was denied and VR grips force-released after ~10ms. Only reports on-car with a valid NetId, else sends a world-absolute position; self-corrects next tick. - ServerPlayer.WorldPosition/AbsoluteWorldPosition/WorldRotationY: returned garbage (car-local treated as world) when CarId != 0 but the car couldn't be resolved. Now returns the last known-good value, protecting every consumer (authority, culling, item reach, paint/rerail distance). - NetworkedItemManager: nearby-items prune mutated a Dictionary while walking it by ElementAt index, skipping entries and running O(n^2). Replaced with a collect-then-remove pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root cause: the local player's position was only sent from CustomFirstPersonController.Awake/OnTick. That controller is desktop-only — DV never instantiates it in VR — so a VR host never sent a position and the server pinned it at (0,0,0). Every proximity-gated system then failed for the host: station locomotives never spawned, procedural jobs never generated, and cab/hose control-authority requests were denied as "too far away" (which in VR manifested as controls latching then instantly releasing). Desktop worked only because the controller runs there. Fix: drive position streaming from the network client lifecycle (NetworkLifecycle.StartClient/Stop) instead of the player controller, so it runs in both VR and desktop. OnTick now polls PlayerManager directly, guards for pre-world/null state, and tolerates a missing controller (move direction falls back to zero in VR). Also: never distance-deny the host for train control authority. The host is the authoritative server and fully trusted; its networked position can lag, so it must not be able to deny itself control of things it's holding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author
|
Dev is complete, I just need to test this with someone in my multiplayer session |
Author
|
Just finished testing - this works. Also motion feels a lot more snappier |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a family of host-side bugs that traced back to a single root cause: the local player's position was only streamed from
CustomFirstPersonController, which DV never instantiates in VR. As a result a VR host never sent a position and the server pinned it at(0,0,0), breaking every proximity-gated system for that player.Fixes #136, #124
Symptoms this resolves (all VR host)
Changes
Stream host position in VR
NetworkLifecycle.StartClient/Stop) instead of the desktop-only player controller, so it runs in both VR and desktop.OnTicknow pollsPlayerManagerdirectly, guards against pre-world/null state, and tolerates a missing controller (move direction falls back to zero in VR).Host/load authority and position races
NetworkedJunction/NetworkedTurntable: the host gated sends on an Awake-timeIsHost()snapshot and is excluded from the railway-state sync packet, so after loading a save it could never send switch/rotation changes. Now re-checksIsHost()live.ServerPlayer.WorldPosition/AbsoluteWorldPosition/WorldRotationY: return last-known-good instead of garbage when a car can't be resolved (protects authority, culling, item reach, paint/rerail distance).NetworkedItemManager: fixed a nearby-items prune that mutated a dictionary while iterating it by index (skipped entries, O(n^2)).Testing
Verified in VR by the reporter: fresh new game (tutorial skipped) now spawns trains and jobs; controls can be grabbed and held; state persists correctly across save → quit → reload. Desktop behaviour unchanged.
🤖 Generated with Claude Code - Edited by me, the human