Skip to content

Fix VR host: empty world, missing jobs, and control-grab failures#145

Open
bdazzledev wants to merge 2 commits into
AMacro:betafrom
bdazzledev:fix/load-authority-and-position
Open

Fix VR host: empty world, missing jobs, and control-grab failures#145
bdazzledev wants to merge 2 commits into
AMacro:betafrom
bdazzledev:fix/load-authority-and-position

Conversation

@bdazzledev

@bdazzledev bdazzledev commented Jul 3, 2026

Copy link
Copy Markdown

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.

- Fixed issue where VR player position was not being updated in the server
- Fixed issue where player's hand sometimes stopped gripping a control
- Spawning into a save file now works correctly

Fixes #136, #124

Symptoms this resolves (all VR host)

  • New games spawn no station locomotives and no cars.
  • Jobs/quests never generate.
  • Grabbing any held control (brake hoses, cab levers, instruments) latches then instantly releases (authority denied "too far away" — only visible in VR because grabs are held rather than clicked).
  • Desktop was unaffected because that controller runs there.

Changes

Stream host position in VR

  • Drive position streaming from the network client lifecycle (NetworkLifecycle.StartClient/Stop) instead of the desktop-only player controller, so it runs in both VR and desktop.
  • OnTick now polls PlayerManager directly, guards against pre-world/null state, and tolerates a missing controller (move direction falls back to zero in VR).
  • Never distance-deny the host for train control authority — it's the authoritative server and its networked position can lag, so it must not be able to deny itself control of things it's holding.

Host/load authority and position races

  • NetworkedJunction / NetworkedTurntable: the host gated sends on an Awake-time IsHost() snapshot and is excluded from the railway-state sync packet, so after loading a save it could never send switch/rotation changes. Now re-checks IsHost() 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

bdazzledev and others added 2 commits July 3, 2026 08:52
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>
@bdazzledev bdazzledev marked this pull request as draft July 3, 2026 13:37
@bdazzledev

Copy link
Copy Markdown
Author

Dev is complete, I just need to test this with someone in my multiplayer session

@bdazzledev

Copy link
Copy Markdown
Author

Just finished testing - this works. Also motion feels a lot more snappier

@bdazzledev bdazzledev marked this pull request as ready for review July 5, 2026 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cant operate certain switches and levers in VR (Quest 3)

1 participant