Table of Contents

Class GameLaunch

Namespace
Valheim.Testing.Game
Assembly
Valheim.Testing.Game.dll

One BepInEx game process's launch, as data: the executable, its working directory and arguments, the variables set for it, the entries put in front of a search list's existing value, and the inherited variables removed. It reproduces what BepInExPack_Valheim's start scripts export, without the script, so the started process ID is the game's own. ForServer(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ServerPlatform?) builds one for a dedicated server and ForClient(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ClientPlatform?, ClientArchitecture?, bool, IEnumerable<string>?) one for a game client. A launch is built for this machine (render it with ToStartInfo()) or, given a host platform, for a host of a multi-machine session, where the hosting layer's server or interactive-client start runs it. It also says what an install on this machine is: DetectServer(string) and DetectClient(string) read the platform from the files, RequireServerExecutable(string) and RequireClientExecutable(string) the executable, and ClientLaunchArchitectures(string) the slices a client can start as.

public sealed class GameLaunch
Inheritance
object
GameLaunch

Remarks

Both kinds share one rule set. The caller's Doorstop variables and --doorstop-* arguments are refused, inherited Doorstop variables are removed apart from the ones the launch sets, and SteamAppId defaults to 892970. On Linux and macOS, Doorstop is enabled for BepInEx's preloader and its library directories are put in front of the existing value. A launch for this machine checks the runtime's or install's files before it is built. A launch for a host checks only the path rules there, and the host checks RequiredFiles when it starts.

Fields

ClientMacBundle

public const string ClientMacBundle = "Valheim.app"

Field Value

string

ClientWindowsExecutable

public const string ClientWindowsExecutable = "valheim.exe"

Field Value

string

ConsoleArgument

public const string ConsoleArgument = "-console"

Field Value

string

MacArchLauncher

public const string MacArchLauncher = "/usr/bin/arch"

Field Value

string

ServerLinuxExecutable

public const string ServerLinuxExecutable = "valheim_server.x86_64"

Field Value

string

ServerMacExecutable

The macOS dedicated server (Steam app 896660's macOS depot), relative to the runtime's root: a universal Mach-O (x86_64 and arm64) beside Unity's player and Mono libraries, with its Data folder next to it. Not an app bundle.

public const string ServerMacExecutable = "valheim_server/Valheim"

Field Value

string

ServerWindowsExecutable

public const string ServerWindowsExecutable = "valheim_server.exe"

Field Value

string

SteamAppId

The game's Steam app id. Both the client and the dedicated server read it from SteamAppId.

public const string SteamAppId = "892970"

Field Value

string

Properties

Arguments

The game's arguments, in order.

public IReadOnlyList<string> Arguments { get; }

Property Value

IReadOnlyList<string>

Environment

Variables set for the game, the caller's first.

public IReadOnlyDictionary<string, string> Environment { get; }

Property Value

IReadOnlyDictionary<string, string>

Executable

The game executable's full path. On macOS, ToStartInfo() starts it through /usr/bin/arch, so the start info's file name is that launcher.

public string Executable { get; }

Property Value

string

LocalServerPlatform

The dedicated-server platform this machine runs: Windows, macOS, or Linux for any other Unix.

public static ServerPlatform LocalServerPlatform { get; }

Property Value

ServerPlatform

Prepended

Entries put in front of a search list's existing value (LD_LIBRARY_PATH, LD_PRELOAD, macOS's DYLD_*), as the pack's scripts do.

public IReadOnlyDictionary<string, string> Prepended { get; }

Property Value

IReadOnlyDictionary<string, string>

RequiredFiles

Files the game and BepInEx loader need: relative to the game directory for a normal install, or absolute loader paths when a disposable profile supplies it.

public IReadOnlyList<string> RequiredFiles { get; }

Property Value

IReadOnlyList<string>

SecretVariables

Names of variables whose values come from this process's environment at launch and reach only the game's environment (a client's join password, for example); never logged or written as evidence. A launch for this machine inherits them anyway.

public IReadOnlyList<string> SecretVariables { get; }

Property Value

IReadOnlyList<string>

Unset

Inherited variables removed before the launch: Doorstop's, apart from the ones set here.

public IReadOnlyList<string> Unset { get; }

Property Value

IReadOnlyList<string>

WorkingDirectory

The directory the process starts in: its game directory, or an owned loader profile for a Unix profile launch.

public string WorkingDirectory { get; }

Property Value

string

Methods

ClientLaunchArchitectures(string)

The architectures this install can be launched as, host aside: x64 for Windows; on macOS, the slices both the game executable and one of the install's Doorstop libraries contain, arm64 only when that core also runs natively (ForClient(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ClientPlatform?, ClientArchitecture?, bool, IEnumerable<string>?) explains the rule). Empty when no Doorstop library matches.

public static IReadOnlyList<ClientArchitecture> ClientLaunchArchitectures(string installDirectory)

Parameters

installDirectory string

Returns

IReadOnlyList<ClientArchitecture>

DetectClient(string)

Decides the platform from the install's contents, never from the host: valheim.exe or a Valheim.app bundle. Refuses an install holding more than one, an empty one, the bundle itself instead of the directory holding it, a dedicated-server runtime (which ForServer(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ServerPlatform?) launches) and a Linux client (valheim.x86_64) with System.PlatformNotSupportedException: Linux hosts run the dedicated server only.

public static ClientPlatform DetectClient(string installDirectory)

Parameters

installDirectory string

Returns

ClientPlatform

DetectServer(string)

Decides the platform from the runtime's contents, never from the host: ServerWindowsExecutable, ServerLinuxExecutable, or ServerMacExecutable with its Data folder. Refuses an ambiguous or empty runtime, and a macOS game client (a Valheim.app bundle, or a directory holding one) with System.PlatformNotSupportedException.

public static ServerPlatform DetectServer(string runtimeDirectory)

Parameters

runtimeDirectory string

Returns

ServerPlatform

ForClient(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ClientPlatform?, ClientArchitecture?, bool, IEnumerable<string>?)

The launch of one BepInEx game client. A client needs an interactive desktop session with a display, a GPU and a running, signed-in Steam client. Starting it inside that session is ClientSession's job on this machine and an interactive client's on a host. -console is added first unless console is false or the caller passed it; other arguments follow unchanged. On Windows the pack's winhttp.dll proxy loads BepInEx and no variable is needed. On macOS, Doorstop is enabled for BepInEx's preloader and its library inserted. Without hostPlatform it is for this machine. install is then the install directory here, whose contents decide the platform (DetectClient(string)). BepInEx's preloader and the platform's Doorstop loader must be present, and on Windows doorstop_config.ini must enable Doorstop and target BepInEx's preloader. macOS starts the bundle through /usr/bin/arch as the requested architecture, inserting a Doorstop library that has that slice. arch fails rather than run another slice, so an arm64 request never falls back to Rosetta. On Apple Silicon, arm64 is the default; x64 selects the Rosetta compatibility path explicitly. Arm64 also needs a BepInEx core whose MonoMod.RuntimeDetour.dll is version 25 or later (legacy MonoMod cannot hook on arm64); an install without it is refused here, before anything starts. The machine must be the client's own OS. A Linux machine or host is refused with System.PlatformNotSupportedException: Linux hosts run the dedicated server only; start the client on Windows or macOS. With hostPlatform (Windows or macOS) the launch is for a host of that platform. install is then an absolute path there: a drive or UNC path on Windows, and on macOS a path without ':', ';' or '='. The caller's variables must be plain names. The Windows client is x64 only.

public static GameLaunch ForClient(string install, IEnumerable<string> arguments, IReadOnlyDictionary<string, string>? environment = null, ClientPlatform? hostPlatform = null, ClientArchitecture? architecture = null, bool console = true, IEnumerable<string>? secretVariables = null)

Parameters

install string
arguments IEnumerable<string>
environment IReadOnlyDictionary<string, string>
hostPlatform ClientPlatform?
architecture ClientArchitecture?
console bool
secretVariables IEnumerable<string>

For a host only: variables (for example the join password's) read from this process at launch and given only to the game; never logged or written as evidence. A launch for this machine inherits this process's environment and refuses them.

Returns

GameLaunch

ForServer(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ServerPlatform?)

The launch of one owned BepInEx dedicated server. Without hostPlatform it is for this machine. runtime is then a runtime directory here, whose files decide the platform (DetectServer(string)). BepInEx's preloader and core and the platform's Doorstop loader must be present, and on Windows doorstop_config.ini must enable Doorstop and target BepInEx's preloader. On macOS the server starts through /usr/bin/arch as the machine's own architecture (arm64 on Apple Silicon). Doorstop is enabled for BepInEx's preloader, with a Doorstop library at the runtime's root that has that slice inserted (DYLD_INSERT_LIBRARIES, passed with -e because the kernel strips DYLD_* from the SIP-protected arch). The stock BepInExPack's Doorstop and core are x86_64-only, so a native launch needs a universal libdoorstop.dylib and a BepInEx core that runs natively. On Linux the runtime's linux64 and doorstop_libs go in front of LD_LIBRARY_PATH, and libdoorstop_x64.so in front of LD_PRELOAD. A caller's own values are kept behind them. A server runs only on its own OS, except that a Windows machine may build a Linux launch for inspection. Any other mismatch refuses with System.PlatformNotSupportedException. With hostPlatform the launch is for a host of that platform. runtime is then an absolute path there: a drive path on Windows, and on Unix a path without ':', ';' or '=', which the loader's search lists and env cannot hold. The caller's variables must be plain names, and on Linux they may not set LD_LIBRARY_PATH/LD_PRELOAD, which the host session supplies.

public static GameLaunch ForServer(string runtime, IEnumerable<string> arguments, IReadOnlyDictionary<string, string>? environment = null, ServerPlatform? hostPlatform = null)

Parameters

runtime string
arguments IEnumerable<string>
environment IReadOnlyDictionary<string, string>
hostPlatform ServerPlatform?

Returns

GameLaunch

RequireClientExecutable(string)

Returns the detected client executable's full path (inside the bundle on macOS). A client runs only on its own OS: another host refuses with System.PlatformNotSupportedException, a Linux one too (Linux hosts run the dedicated server only). On macOS it must carry the user-execute bit.

public static string RequireClientExecutable(string installDirectory)

Parameters

installDirectory string

Returns

string

RequireServerExecutable(string)

Returns the detected server executable's full path. A server runs only on its own OS (a Windows host may resolve a Linux server for inspection); another host refuses with System.PlatformNotSupportedException. On Linux and macOS the server must carry the user-execute bit.

public static string RequireServerExecutable(string runtimeDirectory)

Parameters

runtimeDirectory string

Returns

string

ToStartInfo()

The start info for a launch built for this machine. The caller's variables are set, inherited Doorstop variables are removed apart from the ones the launch sets, and Prepended entries go in front of this process's own value. On Windows a dedicated server gets a console of its own (with no window), so stopping it signals that console rather than the runner's. A launch for a host refuses with System.InvalidOperationException.

public ProcessStartInfo ToStartInfo()

Returns

ProcessStartInfo