Class ServerRunPlan
A plan for owned dedicated-server runs on pinned fixtures (see PinnedServerRun). Derive a mod's plan
from it and add the mod's scenario fields; Read<T>(string) refuses unknown fields. {runtime},
{world} and {port} in arguments and environment values expand to the copies and the CLI port.
public class ServerRunPlan
- Inheritance
-
objectServerRunPlan
Fields
MaximumStartupSeconds
Largest bounded server-start budget, in seconds, including mods that generate a network on first load.
public const int MaximumStartupSeconds = 3600
Field Value
- int
Properties
Arguments
public string[] Arguments { get; set; }
Property Value
- string[]
CommandSeconds
public int CommandSeconds { get; set; }
Property Value
- int
Crossplay
Launches the server with -crossplay, the game's PlayFab backend: clients join its lobby
(WaitForLobby(GameActor, string, TimeSpan, CancellationToken), JoinCrossplay(string, string, string, string, TimeSpan, bool, CancellationToken, string?)), not its address, and the
report records crossplay. -crossplay in Arguments is refused. A crossplay plan names
its game port (-port N): the lobby is keyed by the public IP and that port, so two crossplay servers behind
one public IP need different ports. Keep a crossplay fixture separate from a Steam one rather than switching one
server between modes: a client remembers each server's mode in its recent-server list.
public bool Crossplay { get; set; }
Property Value
- bool
Environment
public Dictionary<string, string> Environment { get; set; }
Property Value
- Dictionary<string, string>
Executable
Optional: documents the plan's platform and must match what the copied runtime contains.
public string Executable { get; set; }
Property Value
- string
ExpectCommand
The strict cli_expect command for the plan's complete bound pins.
public string ExpectCommand { get; }
Property Value
- string
LogScan
This run's severities for the teardown log scan's patterns (Names), each with a written
reason, for example "rpc-method-missing": { "severity": "Failure", "reason": "..." }; under a new name, a pattern
of the run's own with a line regex (Line).
public Dictionary<string, LogClassification> LogScan { get; set; }
Property Value
- Dictionary<string, LogClassification>
Pins
Strict ValheimCLI expectations: worlduid and an exact MD5 for every listed plugin. A standalone runner
observes any omitted pins from the fixture and staged profile before launch.
public Dictionary<string, string> Pins { get; set; }
Property Value
- Dictionary<string, string>
Port
public int Port { get; set; }
Property Value
- int
QuitSeconds
How long stopping the owned server (at teardown and for each restart) waits for it to quit after it is asked (SIGINT, or Ctrl+Break on Windows over SSH, Ctrl+C on other Windows hosts): the game can save the world and retire its crossplay lobby. Killed only after that. 0 kills at once, without the game's shutdown. Default 120, at most 1800.
public int QuitSeconds { get; set; }
Property Value
- int
Runtime
public PinnedDirectory Runtime { get; set; }
Property Value
RuntimePins
The runtime's game build, loader and patchers by SHA256 (Of(string) computes them), checked on the copy before launch: what ValheimCLI cannot report in game. A standalone runner observes them from the staged profile when omitted; supplied values remain expected pins and are checked against the source install before staging.
public InstallPins? RuntimePins { get; set; }
Property Value
Scenario
public string Scenario { get; set; }
Property Value
- string
StartupSeconds
public int StartupSeconds { get; set; }
Property Value
- int
World
public PinnedDirectory World { get; set; }
Property Value
Methods
CheckCrossplay()
Refuses -crossplay in Arguments (in any case, as the game reads it) and, for a
Crossplay plan, anything but exactly one explicit -port N. The runner checks this for every plan.
public void CheckCrossplay()
CheckExecutable(ServerPlatform)
The runtime decides the platform (DetectServer(string)); a stated executable must agree with it.
public void CheckExecutable(ServerPlatform platform)
Parameters
platformServerPlatform
CheckLaunchHost(ServerPlatform, bool)
A launch needs a host that can execute the runtime's server: a Windows host or not (then Linux).
public static void CheckLaunchHost(ServerPlatform platform, bool windowsHost)
Parameters
platformServerPlatformwindowsHostbool
CheckLaunchHost(ServerPlatform, ServerPlatform)
A launch needs a host of the runtime's own platform: each dedicated server runs only on its own OS (see LocalServerPlatform for this machine's).
public static void CheckLaunchHost(ServerPlatform platform, ServerPlatform host)
Parameters
platformServerPlatformhostServerPlatform
CheckLogScan()
The plan's log scan classifications are well formed (the runner checks them for every plan).
public void CheckLogScan()
CheckOutput(string)
public void CheckOutput(string output)
Parameters
outputstring
DedicatedStartupEvents(string)
What an owned dedicated server's startup waits on: ValheimCLI's listening line in this boot's BepInEx log (a previous boot's lines never count; a plugin-load failure, a type-load or missing-member exception, or ValheimCLI's "core is not ready" ends startup at once: StartupFailures), then the loaded-world push on a loopback connection of its own. A world state is not mod readiness: the session observation decides that.
public StartupEvents DedicatedStartupEvents(string runtime)
Parameters
runtimestring
Returns
ExecutableFor(ServerPlatform)
public static string ExecutableFor(ServerPlatform platform)
Parameters
platformServerPlatform
Returns
- string
Expand(string, string, string)
public string Expand(string value, string runtime, string world)
Parameters
valuestringruntimestringworldstring
Returns
- string
GameLogFile(string, string)
The file the arguments' -logFile names, expanded (for example {runtime}/toolkit-unity.log), or null. The game
writes all its own lines there, lobby lines included; BepInEx's log carries them only when BepInEx copies Unity's log.
public string? GameLogFile(string runtime, string world)
Parameters
runtimestringworldstring
Returns
- string
LaunchArguments(string, string)
The server's launch arguments: Arguments expanded (Expand(string, string, string)), then -crossplay for a Crossplay plan.
public string[] LaunchArguments(string runtime, string world)
Parameters
runtimestringworldstring
Returns
- string[]
OnlyForScenario(string, bool, params string[])
Refuses settings (the plan fields, as the plan spells them) when supplied is
true and the plan's Scenario is not one of scenarios: a setting another scenario
reads would otherwise be ignored silently, and the plan would not test what its author thinks.
public void OnlyForScenario(string settings, bool supplied, params string[] scenarios)
Parameters
settingsstringsuppliedboolscenariosstring[]
Read<T>(string)
public static T Read<T>(string path) where T : ServerRunPlan
Parameters
pathstring
Returns
- T
Type Parameters
T
RequireEnvironmentFlag(string, string)
Requires variable in Environment set to exactly 1, the explicit opt-in a test
fixture in the mod needs (for example one that writes terrain when the world loads). Anything else is refused:
missing, another value such as true, or a key that differs only in case, which the server's platform may
or may not treat as the same variable. purpose completes "set it to 1 to ...".
public void RequireEnvironmentFlag(string variable, string purpose)
Parameters
variablestringpurposestring
RequireScenario(params string[])
Refuses a Scenario that is not one of known.
public void RequireScenario(params string[] known)
Parameters
knownstring[]
ValidateServerPlan(IEnumerable<string>, string)
The rules every dedicated-server plan follows: fully qualified sources, port and time bounds, a known executable,
no runner-owned session token or Doorstop variable in the environment, -batchmode -nographics and exactly
one -savedir {world}, and exact values for every pin the plan supplies: plugin MD5s, no worldfiles,
full fixture hashes and RuntimePins. A standalone runner observes omitted pins from what it stages;
after that binding, every requiredPlugins entry must be in the staged plugin set.
Each log scan classification names a known pattern
with a reason. -crossplay comes only from Crossplay (CheckCrossplay()).
public void ValidateServerPlan(IEnumerable<string> requiredPlugins, string sessionTokenVariable)
Parameters
requiredPluginsIEnumerable<string>sessionTokenVariablestring