NetworkRoles¶
How NetworkManager.IsActive, IsServer, and IsClient combine across single-player, multiplayer host, multiplayer client, and dedicated server modes, and why the IsActive && !IsServer guard is the correct remote-client check.
Role flag matrix¶
| Scenario | IsActive | IsServer | IsClient |
|---|---|---|---|
| Single-player | false | false | false |
| Multiplayer host (listen host) | true | true | false |
| Multiplayer client | true | false | true |
| Dedicated server | true | true | false |
The IsActive && !IsServer guard correctly identifies remote clients without catching single-player.
A listen host and a dedicated server are indistinguishable by these three flags. Both reach NetworkManager.StartServer through the same GameManager.StartGame branch (if (Settings.CurrentData.StartLocalHost || IsBatchMode), Assembly-CSharp.decompiled.cs:204603), so the two rows cannot differ. To tell them apart, read GameManager.IsBatchMode, or NetworkManager.LocalClientId (0 on a dedicated server, because Cookie is only loaded when not in batch mode, :273983). See ListenHost.md.
The three flags are one enum, not three booleans¶
(:272571-272576)
public static NetworkRole NetworkRole = NetworkRole.None; // :272668
public static bool IsActive => NetworkRole != NetworkRole.None; // :272706-272710
public static bool IsClient => NetworkRole == NetworkRole.Client;
public static bool IsServer => NetworkRole == NetworkRole.Server;
There is no Host value, and IsServer and IsClient are mutually exclusive by construction. No process can ever report both. Beyond the representation, CanBecome (:273434-273451) returns NetworkRole == NetworkRole.None for both the Server and Client cases, so a process that is already one cannot become the other without first resetting to None (:272777).
Every write to NetworkRole across every decompiled assembly (Assembly-CSharp, StationeersLaunchPad, LaunchPadBooster, BlueprintMod) lives inside NetworkManager, five in total: = None at :272777 (network reset), = Server at :273120 (ProcessP2PSessionRequest) and :273274 (StartServer), = Client at :273402 and :273423 (the two StartClient overloads). No third-party assembly writes it.
NetworkManager.HostClient and the Client record with IsHost = true created by NetworkServer.PopulateHostClient() (:213672) describe the host player in the roster. They are not role flags and do not affect IsClient.
Verification history¶
- 2026-04-20: page created from the Research migration; verbatim content lifted from F0017 (Mods/SprayPaintPlus/RESEARCH.md:128-137).
- 2026-08-09: conflict on "IsClient on a multiplayer host". Previous claim: a multiplayer host reports
IsActive/IsServer/IsClientas true/true/true. New finding: a listen host reports true/true/false, because the three properties are mutually exclusive views of oneNetworkRoleenum that has noHostvalue. Fresh validator verdict: the new finding is correct, quoting the enum declaration at Assembly-CSharp.decompiled.cs:272571-272576 and the property definitions at :272706-272710. Result: the host row'sIsClientcolumn corrected to false; a new section added recording the single-enum representation, the five write sites, andCanBecome's refusal; note added that a listen host and a dedicated server cannot be distinguished by these flags; page restamped to 0.2.6403.27689.
Open questions¶
None.