Skip to content

Added Server Browser and Lobby Server (#10, #45, #35), in-game chat (#8) and minor bug fixes (#36)#46

Open
AMacro wants to merge 591 commits into
Insprill:masterfrom
AMacro:beta
Open

Added Server Browser and Lobby Server (#10, #45, #35), in-game chat (#8) and minor bug fixes (#36)#46
AMacro wants to merge 591 commits into
Insprill:masterfrom
AMacro:beta

Conversation

@AMacro
Copy link
Copy Markdown

@AMacro AMacro commented Jul 14, 2024

@Insprill

This is a consolidation PR that covers multiple issues.

Work is ongoing for #6 and #11.

Jarnster pushed a commit to Jarnster/dv-multiplayer that referenced this pull request Nov 27, 2024
Fix project board link in the README
@AMacro AMacro force-pushed the beta branch 3 times, most recently from 1e8fee4 to 48e900a Compare March 2, 2025 10:27
AMacro added 30 commits March 7, 2026 18:14
Introduces a new setting 'Show Player List in Alt Mouse Mode' to control the visibility of the player list when mouse mode is active. Updates PlayerListGUI to respect this setting when toggling the player list display.
Added null checks and improved error handling across multiple components to prevent null reference exceptions.
isUnloading and isQuitting are not set until after scene unload has begun, causing unnecessary logging.

Introduces an IsReturningToMenu property to track when a scene switch to the main menu is requested. Updated NetworkLifecycle.OnTick() invocation and error logging to avoid processing during game scene unload.
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)
Introduced additional Log statements throughout NetworkClient and NetworkServer to improve traceability of key connection events.
If the host shows the pause menu and then changes focus to a new window, the simulation pauses. Clients will continue to run the simulation, but when the host returns to the game the simulation will reset to the pre-pause state. On Clients this can cause a large jump and physics glitches.
Disable Teleport and Pause Menu inputs when chat is toggled. This fixes an issue where the 'F' key teleports the player and allows 'escape' to be used to close the chat window.
Register MessageBox and BetterModUI as Client compatibility in ModCompatibilityManager so they are treated as client-side only mods.
Patch HoseSeparationChecker to prevent clients from breaking the hose connection if carriages are too far from each other.
Expanded instructions for building the mod and clarified installation steps.
Updated the instructions for building the project to use numbered steps for clarity.
Player coupling interaction was being stored and not cleared on the host, resulting in subsequent interactions being rejected and not correctly restoring state
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
Introduce a generic RPC response mechanism: adds RpcManager (discovery/registration of IRpcResponse types, FNV-1a hashing, ticket creation/resolution and expiry handling), RpcTicket (callbacks for resolve/timeout), and IRpcResponse interface for serialisation. Adds ClientboundRpcResponsePacket to carry ticket id, response type hash and serialised response data. NetworkClient now subscribes to and handles RPC response packets by resolving tickets via RpcManager; NetworkServer exposes SendRpcResponse to send responses to peers. Reflection-based type discovery ensures server/client can instantiate correct response types during deserialisation.
Allow clients to request work trains.
Low pings cause premature timeout for CommsRadio WorkTrain RPC packets, added a minimum of 2 seconds. Added a German translation for a "work train in use". Removed an extra "\n" that was causing the LCD text field to overflow.
Move various Multiplayer.Networking.Data types into focused subnamespaces and folders (Items, Jobs, World, RPCs) and update all affected using directives and references across the codebase.
Add base framework for inventory initial load.
Add dummy test items for all clients. Items are selected for running steam locos, i.e. Oiler, Lighter, Shovel and Lantern
Increase client timeout to be 8x the one-way ping
Attempting to fix a null reference issue that may be related to a CCL car misconfig.
Ensure lastRemoteValueDict contains an entry for the current resourceType before calling SetUnits. If the resource has a corresponding loco resource module, initialize to rm.Data.unitsToBuy; otherwise default to 0f.
Use null-safe coupler?.train?.ID instead of coupler.name/otherCoupler.name in the SendHoseConnected warning.
* Add CrewName and DisplayName to player objects

Player objects updated to add a crew name designation and a display name that returns the username and if set, CrewName.

Exposed properties for IPlayer objects.

* Add support username override at login and sync of crewnames

Pass and store a player's crew name and handle server-provided username overrides. Changes: ClientPlayerManager.AddPlayer now accepts crewName and sets NetworkedPlayer.CrewName; NetworkClient stores Username and CrewName, exposes DisplayName, initializes Username from settings, and applies packet.OverrideUsername on login; NetworkServer includes OverrideUsername in the login response and sends CrewName in the PlayerJoined packet; clientbound packets (LoginResponse, PlayerJoined) get new fields for OverrideUsername and CrewName. This enables showing crew tags in player names and resolving duplicate-username conflicts.

* Update MapMarkers to use the DisplayName

Map markers will now show the crewname if available

* Update PlayerListGUI to show crewnames if available and overridden username when applicable

Replace cached localPlayerUsername with a read-only property that returns NetworkLifecycle.Instance.Client.DisplayName or falls back to Multiplayer.Settings.GetUserName(). Use player.DisplayName when building the list and use the new LocalPlayerUsername for the local entry. Removes stale initialization and adds null-safe access to the client display name so the UI shows up-to-date names.

* Add a method for syncing player preferences

Add a clientbound packet and handlers to propagate player preferences (currently crew name) to clients. Introduces ClientboundPlayerPreferencesUpdatePacket, NetworkServer.SendPlayerPreferencesUpdate, and a client handler in NetworkClient. Adds ClientPlayerManager.UpdatePreferences and OnPlayerPrefsUpdated event to update the local NetworkedPlayer state, and updates NetworkedMapMarkersController to refresh displayed crew names when preferences change.

* Update ChatManager.cs

* Add player management API methods (kick, set crew name)

* Move player wrapper caching into network managers

* Increase crew name max and fix truncation

Bump MAX_CREW_NAME_LENGTH from 5 to 6 to allow a longer crew name. Fix a bug in the CrewName setter where a truncated name was immediately overwritten by the original value

* Add /crew chat command and crew name setting

Introduce support for setting player crew names via chat: add new /crew (and /sc) command handling in ChatManager with a SetCrewNameMessage handler that supports host-managed and optional client-set crew names. Add a new AllowClientCrewNames setting (with UI attributes) to control whether clients can change their own crew. Add related locale keys and translations (help texts and messages for disallowed, player not found, and joined announcements) and corresponding constants in Locale.cs.

* Use player wrapper API for remote dispatch

Replace direct NetworkedPlayer/Transform usage with the MPAPI IPlayer wrappers and unify host/client handling. The patch iterates ServerPlayerWrappers or ClientPlayerWrappers via IPlayer, reads Position and RotationY properties (adjusted by WorldMover), and adds the player's CrewName to the dispatched JSON. Also updates usings (adds MPAPI, LINQ, Collections) and removes direct Transform access to improve compatibility with the new player abstraction.
* Reorganise packet subscriptions in NetworkServer

* Enable client car spawning

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

* Fix job overview despawn on clients

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.

* Refactor job item destruction logic

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)

* Initial commit for Work Train Functionality

Allow clients to request work trains.

* Refactored sync process for players joining the server

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 save export and tidy settings

Add debug utility to dump saves as readable JSON

* Improve debug logging for IdMonoBehaviours

* Filter outgoing packets by player loading state

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.

* Remove playerSpawned param from SendSpawnTrainset

* Change NetworkedStationController netId Generation to use hashes

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 client packet subscriptions

Reorganise NetworkClient.Subscribe() into logical groups for readability

* Improve client loading progress and timing

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.

* Skip loco restoration popup when player is far from loco

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.

* Add transportCars sync for Demonstrators

* Fix deposited cash check and null-safe player list

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.

* Add sync for restoration parts purchased

Send parts purchased event to all clients.
Increase distance at which LocoRestorationState notifications are displayed from 50m to 100m.

* Complete loco restoration sync

* Send generic switch states on player join

* Add null check in SendHoseConnected

Add null checks in NetworkClient.SendHoseConnected to avoid null reference exceptions when either coupler is missing

* Add a debug mode to export savegame data at load

Add a debug-only Harmony patch that triggers ExportSaveData.DumpSaveData when StartGameData_FromSaveGame.GetSaveGameData runs.

* Fix issues with MU Jank

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.

* Fix issues with control jank with multiple players in the cab

- 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.

* Make player list position configurable

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.

* Ready for Pre-release testing

* Clean up incorrect logging

* Harden NetworkedTrainCar.Start()

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 null checks for cleanup handlers

* Improve logging

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.

* Attempt to fix a bug where a newly added playerId clashes with an existing 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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants