Commands
A player acts by sending one of the game's own commands.
Gamehoster.Command(name, params) is generated for your game, so it validates the call against that
command's schema, then encodes and sends it. A command runs on the server's next tick and you see the result
in a later frame; there is no return value.
Sending a command
| Member | Description |
|---|---|
Gamehoster.Command(name, params, predict) |
Validate params against the named command's schema, then encode and send. The
optional predict patch is applied over the view at once and retired when the
server acks the command — see optimistic
overrides. |
Gamehoster.Input.Set(name, value) |
Feed the local prediction input your predict body reads. |
Validation runs before anything goes on the wire:
- an unknown command name throws
- an unexpected param key throws
- each param passed is type- and range-checked against the schema
Gamehoster.Command('fire', {})
Gamehoster.Command('aim', { angle: 1.2 })
Throttling
A high-frequency command, aim that follows the pointer, does not need to send on every event. A
rate map in gamehoster-frontend-settings.json coalesces a command to the latest
value at that many times per second.
{
"rate": {
"aim": 20
}
}
Feeding prediction
To make your own object respond the instant you act, feed the same value into the local prediction with
Gamehoster.Input.Set(name, value). Call it from the input body alongside the command; the
gamehoster-player-predict.js body reads it each tick.
var a = Gamehoster.Mouse.angle
Gamehoster.Command('aim', { angle: a })
Gamehoster.Input.Set('angle', a)
Optimistic overrides
Prediction with Input.Set is the continuous tool: it re-simulates your own object
every tick. For a discrete action — a chess move, a card played, a door opened — pass a
predict patch as the third argument to Gamehoster.Command. The patch is laid over
the world the moment you act and retired automatically once the server acks the command, whether it
accepted it or not; an ignored (illegal) action simply snaps back on the next update.
The patch is an object addressing the world by each object's stable id. Only the fields you
name change; everything else keeps its authoritative value. The fields you write are the same top-level
view fields the renderer reads, so an override rides on top of any smooth
shaping of that field.
| Key | Patches |
|---|---|
instance | the instance view's fields. |
players | a map of player id to the fields to override. |
entities | a map of entity id to the fields to override. |
// chess: show the move at once — the piece jumps, the captured piece leaves, the turn passes
var patch = { entities: {}, instance: { turn: Gamehoster.Instance.turn === 'white' ? 'black' : 'white' } }
patch.entities[moverId] = { file: file, rank: rank }
if (capturedId != null) patch.entities[capturedId] = { file: -1, rank: -1 }
Gamehoster.Command('move', { from: from, to: to }, patch)
A patch may instead be a function (view) => void for richer edits, but the function form
runs only on the lower-level Gamehoster.connect
frame; through Gamehoster.Command use the object form above.