Command
The things a player can send. Pong has two:
moveY nudges your paddle, and ready toggles your ready flag between matches.
Each is a directory holding a param schema, a writes
manifest, and a handler.
moveY
Nudges the sending player's paddle. Its one param, axis, is a signed amount (the
renderer clamps it to -1..1) that the handler scales by paddleSpeed. Because it writes
player.y, a shared field, and the move is
incremental, the client can predict it: replaying your pending moveY commands reproduces
your paddle instantly, then reconciles against the server.
[
{
"gamehoster-command-schema-name": "axis",
"gamehoster-command-schema-type": "number"
}
]
{
"writes": ["player.y"]
}
// Move the sending player's paddle by their axis input. `y` is a `shared` field,
// so this handler runs on both sides: on the owner's front end (prediction) and
// on the server (authority). Ignored outside the playing phase.
const here = Gamehoster.Context.instanceId
if (Gamehoster.Instance.State.Get(here, "phase") !== "playing") return
const me = Gamehoster.Context.playerId
const speed = Gamehoster.Instance.State.Get(here, "paddleSpeed")
const half = Gamehoster.Instance.State.Get(here, "paddleH") / 2
const court = Gamehoster.Instance.State.Get(here, "courtH")
const y = Gamehoster.Player.State.Get(me, "y") + Gamehoster.Command.Get("axis") * speed
Gamehoster.Player.State.Set(me, "y", Math.max(half, Math.min(court - half, y)))
ready
Flips the sending player's ready flag while the match is waiting or
over, which is how a game gets started or replayed once both sides are ready. It takes
no params. Because ready is a sent
(server-authoritative) field, the toggle only takes effect on the server; it is ignored during play.
[]
{
"writes": ["player.ready"]
}
// Toggle the sending player's ready flag while gathering or on the results
// screen. `ready` is a `sent` field (server-authoritative), so this only takes
// effect on the server. Ignored during play.
const here = Gamehoster.Context.instanceId
const phase = Gamehoster.Instance.State.Get(here, "phase")
if (phase !== "waiting" && phase !== "over") return
const me = Gamehoster.Context.playerId
Gamehoster.Player.State.Set(me, "ready", !Gamehoster.Player.State.Get(me, "ready"))