Table of Contents

Class SessionControl

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

Actions affect an attached game, never launch or terminate its process. Mod readiness is separate.

public sealed class SessionControl
Inheritance
object
SessionControl

Constructors

SessionControl(GameActor)

Actions affect an attached game, never launch or terminate its process. Mod readiness is separate.

public SessionControl(GameActor actor)

Parameters

actor GameActor

Methods

EnableDevcommands()

Turns the client's devcommands on at its menu: Ensure(GameActor, TestActorRole, bool) as ClientMenu, which reads ValheimCLI's cli_access, toggles once only if needed and verifies the result. ValheimCLI refuses mutating extension commands, the session join among them, until devcommands is on, and a fresh game starts with it off. Cheats are acknowledged after joining (ClientRounds does it for an owned client). On a client joined to a server, Valheim 1.0 also needs ValheimCLI's AllowOnServerClients = true for mutating test commands.

public void EnableDevcommands()

Join(string, string, string?, bool)

Joins a server. Turns devcommands on first unless enableDevcommands is false, because the join is refused without it; pass false when an operator manages that flag and the join should fail instead. Credentials stay in the game host's environment, never in command text or transcripts. The join invalidates the actor's pins; verify the destination world, then WaitForWorld(string, TimeSpan, CancellationToken, bool), which protects the joined player.

public void Join(string address, string character, string? passwordEnvironmentVariable = null, bool enableDevcommands = true)

Parameters

address string
character string
passwordEnvironmentVariable string
enableDevcommands bool

JoinCrossplay(string, string, string, string, TimeSpan, bool, CancellationToken, string?)

Joins a crossplay (PlayFab) server's lobby with the given existing character: cli_select_character, then cli_connect_playfab_user <remotePlayerId> exactly once (devcommands first, as Join(string, string, string?, bool)), each reply read back. remotePlayerId comes from the server (WaitForLobby(GameActor, string, TimeSpan, CancellationToken)). No password is passed: the command would carry it as text, so a crossplay fixture server runs private without one. The command only starts the join, so this then re-pins the client with menuExpectations (plugins only) and waits, reading the session state, until the client is connected in worldUid with its player ready, as the session join does. Fails when the game reports a load error or another world, or returns to the menu with an error status after the join started. Then verify the world pins and WaitForWorld(string, TimeSpan, CancellationToken, bool). A strict client refuses its menu pins as soon as the join loads the world between two reads ("loaded but not listed"); with worldExpectations (the plugins and the server's world, as WorldExpectations(string) gives them) the client is then re-pinned to that world, once, and the wait goes on; another world fails that pin check. The same holds when the join loads the world before the menu pins are first checked. Found in the native crossplay run: the join completes within a read.

public SessionState JoinCrossplay(string remotePlayerId, string character, string worldUid, string menuExpectations, TimeSpan timeout, bool enableDevcommands = true, CancellationToken cancellation = default, string? worldExpectations = null)

Parameters

remotePlayerId string
character string
worldUid string
menuExpectations string
timeout TimeSpan
enableDevcommands bool
cancellation CancellationToken
worldExpectations string

Returns

SessionState

JoinExpectingRefusal(string, string, GameConnectionStatus, string, TimeSpan, string?, bool, CancellationToken)

Joins a server that must refuse this client with expected, for example ErrorVersion (3) from a mod's version check. Issues the session join exactly once (devcommands first, as Join(string, string, string?, bool)), requires ValheimCLI to report that the game refused it (join_failed: the new connection ended in an error status), re-pins the client with menuExpectations (plugins only, such as MenuExpectations), waits within timeout until the client is back at its main menu, then reads cli_connection_status, which the game keeps until the next join, and requires the expected status. Fails when the join succeeds (the client is then in the server's world: leave it before another join), when it ends any other way (another ValheimCLI code, a timeout or a lost reply: nothing is retried) and when the refusal has another status. On success the client is at its menu, pinned, and a normal Join(string, string, string?, bool) may follow.

public JoinRefusal JoinExpectingRefusal(string address, string character, GameConnectionStatus expected, string menuExpectations, TimeSpan timeout, string? passwordEnvironmentVariable = null, bool enableDevcommands = true, CancellationToken cancellation = default)

Parameters

address string
character string
expected GameConnectionStatus
menuExpectations string
timeout TimeSpan
passwordEnvironmentVariable string
enableDevcommands bool
cancellation CancellationToken

Returns

JoinRefusal

JoinHost(ClientRunPlan, GameActor, string, bool, CancellationToken)

Joins a client plan's disposable character, a host's peer (JoinsHost), to the world a hosting client hosts (HostingClientActor), whose in-game handle is host and world worldUid. A listen server on the game's Steam backend is reached through Steam rather than at an address, so this reads the host's multiplayer identity (cli_multiplayer_identity, read-only: it must be an open server), then joins the host's Steam user once (cli_connect_steam_user <steamId>, after cli_select_character, with devcommands first), and waits as a crossplay join does until the client is connected in the host's world with its player. Then, as JoinWorld(ClientRunPlan, string, CrossplayLobby?, bool, CancellationToken): the world pins, the world awaited within the plan's join time, test access on an owned client's character, and protection unless protectPlayer is false. A crossplay (PlayFab) host is refused: its peer join is not supported yet.

public SessionState JoinHost(ClientRunPlan plan, GameActor host, string worldUid, bool protectPlayer = true, CancellationToken cancellation = default)

Parameters

plan ClientRunPlan
host GameActor
worldUid string
protectPlayer bool
cancellation CancellationToken

Returns

SessionState

JoinWorld(ClientRunPlan, string, CrossplayLobby?, bool, CancellationToken)

Joins a client plan's disposable character to the owned dedicated server whose world is worldUid: the one join that ClientRounds, LogoutCycle and a scenario that joins several clients itself all use. Devcommands first and the join exactly once, by the plan's address (Join(string, string, string?, bool)) or, for a Crossplay plan, into the server's lobby (JoinCrossplay(string, string, string, string, TimeSpan, bool, CancellationToken, string?)); then the client's world pins (WorldExpectations(string)) are verified and the world awaited within the plan's join seconds. An owned client then gets test access on its disposable character (Ensure(GameActor, TestActorRole, bool) as ClientInWorld, requiring ValheimCLI's AllowOnServerClients when the player is protected, since protection is a mutating command there); an operator's attached client keeps devcommands only. Last, unless protectPlayer is false, the player is protected (Protect(GameActor); see WaitForWorld(string, TimeSpan, CancellationToken, bool) for what protection changes).

public SessionState JoinWorld(ClientRunPlan plan, string worldUid, CrossplayLobby? lobby = null, bool protectPlayer = true, CancellationToken cancellation = default)

Parameters

plan ClientRunPlan
worldUid string
lobby CrossplayLobby
protectPlayer bool
cancellation CancellationToken

Returns

SessionState

Leave()

public void Leave()

Read()

public SessionState Read()

Returns

SessionState

Save(string, TimeSpan)

public uint Save(string worldUid, TimeSpan timeout)

Parameters

worldUid string
timeout TimeSpan

Returns

uint

WaitForWorld(string, TimeSpan, CancellationToken, bool)

Waits until worldUid is loaded and ready, polling the read-only session state. Then, unless protectPlayer is false, protects the game's local player (Protect(GameActor): god, ghost and debug modes, read back), so a fall, the water or a mob between the join and the check cannot cost the character. A protection the game does not confirm fails the wait; it is issued once and never toggled. Debug fly stays off. A dedicated server has no local player and is left alone. A game hosting its own world reports ready before its player spawns, so the wait goes on, within the same timeout, until that player exists.

Protection changes gameplay, as the game does in 1.0.16: monsters neither notice nor target a player in ghost mode, an egg hatches only near a player who is not, and a creature hit by a player in god or ghost mode is marked cheated, which marks the items it drops. Pass false for combat, aggro, taming, hatching or loot checks, when a check needs a vulnerable player, or when an operator manages these modes; call Protect(GameActor) yourself for the steps that should be protected.

public SessionState WaitForWorld(string worldUid, TimeSpan timeout, CancellationToken cancellation = default, bool protectPlayer = true)

Parameters

worldUid string
timeout TimeSpan
cancellation CancellationToken
protectPlayer bool

Returns

SessionState