Table of Contents

Class PlayerPlacement

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

Puts a joined client's player where a check needs it and proves it stands there: protection, arrival arranged by the server, and stationary support read on the client. The server moves the player with the game's own teleport (cli_teleport_peer), which runs on the player's client and needs nothing installed there, so this works on a client that is not an admin and has cheats off. Arrival is established only by the client's own observations; a teleport reply is not arrival.

public static class PlayerPlacement
Inheritance
object
PlayerPlacement

Fields

ArrivalCapabilities

What Arrive(GameActor?, GameActor, HeightExpectation, TimeSpan, CancellationToken, bool, bool) needs from the client's ValheimCLI: the default plugin's bounded teleport commands (cli_wait_teleportable, cli_teleport_trace_arm/cli_teleport_trace_wait), World Tools' support wait, and its support reading (the flying check). ClientRounds checks them for an arriving client.

public static readonly IReadOnlyList<string> ArrivalCapabilities

Field Value

IReadOnlyList<string>

Methods

Arrive(GameActor?, GameActor, HeightExpectation, TimeSpan, CancellationToken, bool, bool)

Teleports the player to point, a little above it so the character settles onto the ground, exactly once, at the game's ordinary teleport timing, and returns once the client's own observation shows the player supported there (Supported(Observation, HeightExpectation, float, float, float)). Who moves the player: with a server, the server teleports its only connected player (OnlyPeer(GameActor); cli_teleport_peer, which needs nothing on the client); with none, the client teleports its own player (cli_teleport), which needs the client's test access (cheats acknowledged and, on a client joined to a server, ValheimCLI's AllowOnServerClients) and is the way to place one of several players. Unless skipIntro is false it first ends a first-join intro (SkipIntro(GameActor, TimeSpan)), a no-op for a character that has spawned before. The intro skip is one mutating game command and cannot be cancelled while it is in flight. The subsequent read-only game waits use bounded intervals, without repeatedly reading remote state: ValheimCLI waits until the player can be teleported (the game silently drops a teleport within 2 s of a spawn or of the previous teleport), arms a one-hop trace, and after the one teleport request waits for the teleport to finish with a ready floor, then for supported arrival. A player shown flying is refused before the teleport (see SetFly(GameActor, bool)). The read-only game waits use short bounded intervals so cancellation is checked between them; the trace stays armed and the teleport is never issued again. With loadedGround, the point's height is only the teleport target: once the floor is ready the client measures the loaded ground there (TerrainProbe, loaded-ground) and the landing must be supported at that height (Target). Use it for a check that is not about terrain, where a location's levelling can move the ground from the generator's height; a terrain check leaves it off, so a different ground fails. The loaded-ground comparison is one observation, not a sliced game wait. timeout (at most 600 s) covers the intro and every wait. Only a named in-game wait timeout starts another interval; a lost reply is an unknown outcome, not a failure to act. Needs ArrivalCapabilities on the client, and valheim.world/terrain with loadedGround.

public static PlayerPlacement.TeleportArrival Arrive(GameActor? server, GameActor client, HeightExpectation point, TimeSpan timeout, CancellationToken cancellation = default, bool skipIntro = true, bool loadedGround = false)

Parameters

server GameActor
client GameActor
point HeightExpectation
timeout TimeSpan
cancellation CancellationToken
skipIntro bool
loadedGround bool

Returns

PlayerPlacement.TeleportArrival

OnlyPeer(GameActor)

The server's only connected peer that has a character, as cli_peers numbers it. Refuses none or several: with more than one player the test cannot tell which one it would move.

public static int OnlyPeer(GameActor server)

Parameters

server GameActor

Returns

int

PeerCount(GameActor)

How many peers are connected to the server, from one cli_peers reading (World Tools). Refuses a reply whose count line (OK: N peer(s)) disagrees with the peers it lists.

public static int PeerCount(GameActor server)

Parameters

server GameActor

Returns

int

Protect(GameActor)

Turns on god, ghost and debug modes for the local player (cli_set_player_safety true) and requires the game to read all three back, and ghost mode to be written where every other peer reads it (ghostReplicated=True): the game keeps ghost mode in the player's own process, while a creature's AI runs in whichever process owns it, so a ghost only the local game knows about is still hunted by creatures another client simulates (#261). The command sets the modes rather than toggling them, so running it again changes nothing; it is issued once and an unconfirmed reply fails. Debug flying stays off, so support observations remain meaningful. WaitForWorld(string, TimeSpan, CancellationToken, bool) calls this by default once the world is ready.

public static void Protect(GameActor client)

Parameters

client GameActor

Protect(GameActor, bool)

Protect(GameActor), or with targetable god and debug modes without ghost mode (cli_set_player_safety true targetable): the player cannot die but creatures notice it, for a test of AI or targeting that opts out of ghost mode on purpose (Targetable).

public static void Protect(GameActor client, bool targetable)

Parameters

client GameActor
targetable bool

RequireSupported(GameActor, HeightExpectation, int, TimeSpan?, CancellationToken)

readings client observations interval apart (default three, half a second), each of which must show the player settled on point: stationary support, not walking usability. A reading that shows the player flying refuses the check (an System.InvalidOperationException, not a SupportException): support cannot be measured while fly is on. cancellation also ends the pause between readings.

public static IReadOnlyList<JsonElement> RequireSupported(GameActor client, HeightExpectation point, int readings = 3, TimeSpan? interval = null, CancellationToken cancellation = default)

Parameters

client GameActor
point HeightExpectation
readings int
interval TimeSpan?
cancellation CancellationToken

Returns

IReadOnlyList<JsonElement>

SetFly(GameActor, bool)

Turns the local player's debug fly on or off (cli_fly on|off, which sets rather than toggles) and requires the game to read the requested state back. Fly is for review and visual steps only, such as looking at a site from above: a flying player is never supported, so Arrive(GameActor?, GameActor, HeightExpectation, TimeSpan, CancellationToken, bool, bool) and RequireSupported(GameActor, HeightExpectation, int, TimeSpan?, CancellationToken) refuse while it is on. Turn it off before measuring again.

public static void SetFly(GameActor client, bool on)

Parameters

client GameActor
on bool

SkipIntro(GameActor, TimeSpan)

Ends a new character's first-spawn intro (the Valkyrie ride) as the menu's Skip button does, or stops it before it starts, and waits until the player has respawned on the ground (cli_skip_intro, not a cheat command). Returns whether an intro was running; a character that has spawned before returns false and nothing changes. The game records the skipped intro in the character, as it does after a normal first spawn.

public static bool SkipIntro(GameActor client, TimeSpan timeout)

Parameters

client GameActor
timeout TimeSpan

Returns

bool