Skip to content

Add client car spawning, demonstrator sync and fix control jank#131

Merged
AMacro merged 30 commits into
betafrom
alpha
Apr 25, 2026
Merged

Add client car spawning, demonstrator sync and fix control jank#131
AMacro merged 30 commits into
betafrom
alpha

Conversation

@AMacro
Copy link
Copy Markdown
Owner

@AMacro AMacro commented Apr 25, 2026

No description provided.

AMacro added 30 commits March 22, 2026 12:34
Added ServerboundTrainSpawnRequestPacket and server-side validation for client-initiated car spawns.

Updated NetworkedCarSpawner and related patches to support new spawn flow and play spawn sounds for player-initiated spawns.

Removed unused ClientboundSpawnTrainCarPacket
Removed call to `ClearAvailableJobOverviewGOs` in `NetworkedStationController`.  Fixes issue where clearing a carriage for an available job causes all client job overviews to despawn at the station.
Moved the logic for destroying JobOverview and JobBooklet items into dedicated methods in NetworkedJob. Updated NetworkedStationController to use these new methods, improving code clarity and encapsulation.

Fixed error where a job overview could be destroyed while in a client's inventory, and slot would remain used (item not properly removed)
Allow clients to request work trains.
Add a basic player loading state machine and use PlayerLoadingState throughout the codebase to coordinate world synchronisation. Replaces boolean IsLoaded checks with LoadingState and introduces ClientboundLoadStateInfoPacket and ServerboundLoadStateUpdatePacket (removing older single-step packets). Client now runs a SyncWorldState coroutine that advances through discrete states (game data, world state, trainsets, items, jobs, tiles, complete) and requests the server for each phase; server handles those states and streams the appropriate data (including trainset counts). Trainset and restoration support updated: TrainsetSpawnPart now encodes RestorationType and optional second-car netId, RestorationData/RestorationType structs added, and NetworkedCarSpawner collects/apply restoration states after spawning. Add Harmony transpiler patch for LocoRestorationController start logic to respect world sync completion. Misc: ServerPlayer gains LoadingState/LastLogin/TotalPlaytime, various managers (item/culling/savegame) check LoadingState thresholds, logging and minor serialization fixes.
Add debug utility to dump saves as readable JSON
Introduce a PlayerLoadingState filter to Server.SendPacketToAll so the server skips peers that haven't reached a minimum load state. Update the SendPacketToAll signature and calling sites across the server to supply appropriate minimumLoadState values (ReadyForWorldState, ReadyForTrainSets, ReadyForJobs, Complete, etc.), preventing premature packet delivery. Also add handling for the Complete load state and kick on unexpected load-state in server load-state processing. Minor client tweaks: mark railwayStateLoaded instead of requesting cars and remove small whitespace/noise in brake update handling. Add DV.Customization using directive.
Convert station network IDs from ushort to uint across networking code and packets. Update NetworkedStationController to use uint generic ID, compute NetId from station ID (Fnv1a hash) during registration, and set IsIdServerAuthoritative to false. Adjust job-related APIs: JobData.FromJob signature simplified, JobUpdateStruct.ValidationStationId changed to uint (with corresponding serialization), and client/server job packets updated to use uint StationNetId. Remove an unused GetAll helper.
Reorganise NetworkClient.Subscribe() into logical groups for readability
Update NetworkClient loading flow and UI: show dynamic progress percent (based on LoadingState/PlayerLoadingState.Complete) instead of hardcoded 100, add/loading status updates for rolling stock and final Complete, and log when requesting cars. Change railway wait to use railwayStateLoaded and move the ReadyForTrainSets state update to after railway state is loaded. Reduce several artificial waits from 0.5s to 0.25s for snappier loading transitions.
Patch LocoRestorationController.SetState() to replace the call to LocoRestorationView.GetStatusMessageFor with a custom method which checks the player's distance to the loco and tender. If the player is beyond the threshold range from vehicle the method returns null to prevent the restoration popup from showing.
Validate payment using CashRegister.DepositedCash instead of the player's Inventory money so the register checks the actual deposited amount against the total cost. Also add null-conditional access for _cullingManager.ActivePlayers when sending the packet to avoid a potential null reference if the culling manager or its ActivePlayers collection is not set.
Send parts purchased event to all clients.
Increase distance at which LocoRestorationState notifications are displayed from 50m to 100m.
Add null checks in NetworkClient.SendHoseConnected to avoid null reference exceptions when either coupler is missing
Add a debug-only Harmony patch that triggers ExportSaveData.DumpSaveData when StartGameData_FromSaveGame.GetSaveGameData runs.
Port update subscription refactored so that ports for controls inheriting from OverridableBaseControl are not subscribed to, instead using the OverridableBaseControl.ControlUpdated() event.

ControlUpdated() is not triggered by MU propagation.
- Add ObiRopeGrabAreaHandler and ObiRopeGrabAreaPatch to wrap ObiRopeGrabAreas, surface Grabbed/Ungrabbed events and handle interaction enable/disable requests.

- Update NetworkedTrainCar:
  - Add INTERIOR_CONTROLS_TIMEOUT and state for InteriorControlsManager, scroll delegates and active scrolling coroutines.
  - Use a coroutine-based HookControls flow that waits for control initialisation, hooks standard controls and ObiRope handlers, registers scroll events, and logs warnings for missing ports/implementations.
  - Block control port updates from being transmitted when a control is marked blocked.
  - Implement Client_ControlScrolled / Client_CheckScrolling to request authority while scrolling and release when done.
  - Implement WaitForControlToSettle before releasing authority on physics-driven controls.
  - Improve cleanup: stop scrolling coroutines and remove delegates on teardown.
  - Update Client_ReceiveAuthorityUpdate to properly enable/disable controls and related components (hinges, whistle rope, handcar bar) and stop active scroll coroutines when blocking.
- Fix NetworkServer send-to-all logic: change excludeSelf handling when broadcasting packets.
Add PlayerListPosition enum and window constants to PlayerListGUI and compute the player list window Rect based on a new setting (TopLeft, TopRight, TopCenter). Adjust positioning logic (including special-case centering when ShowStats is enabled) and keep dynamic height. Expose the new PlayerListPosition setting in Settings with default TopCenter and visible only when ShowPlayerListInAltMouseMode is enabled.
Add defensive checks, logging and safer event wiring to avoid NREs. Adds null checks and warnings for TrainCar, couplers, controlsOverrider, simulationFlow and brakeSystem; protects coupler/control/fuse/port subscription loops; guards brake event hookups; improves debug/warning messages; and wraps control-settling loop in a try/finally so authority is always released. Overall improves robustness and diagnostics during initialisation and control handling.
Add a log entry when receiving a player-joined packet.
Adjust the loading UI text from "Syncing Rolling Stock" to "Syncing rolling stock" for consistent casing.
…sting playerId

Add a guard in ClientPlayerManager.AddPlayer to detect if a player with the same playerId already exists. If found, log a warning  and remove the existing player before instantiating a new player.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

1 participant