Network: asynchronous multiplayer (ghosts, replays, async PvP, boards)
Supports asynchronous multiplayer with nobody online at the same time: record a run, upload it, and let other players race it as a ghost, replay it or compete on boards.
Network: asynchronous multiplayer (ghosts, replays, async PvP, boards) (net.async) #
What it is for #
Supports asynchronous multiplayer with nobody online at the same time: record a run, upload it, and let other players race it as a ghost, replay it or compete on boards.
It needs net.transport, input.actions, game.engine; installing it brings them in.
Turn it on #
Install the kit in a project, then change a setting (the values shown are its defaults):
gripforge_gamekit_install { project_id: "gkp_…", id: "net.async" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "net.async",
config: { "preset": "none", "game": "arena" } }
First example #
<!-- test: kits/net_async/tests/net_async.rs::a_server_in_the_transport_makes_the_session_connect --> This is the body of the passing test a_server_in_the_transport_makes_the_session_connect; the helper functions it calls are defined at the top of the same test file.
#[test]
fn a_server_in_the_transport_makes_the_session_connect() {
let mut s = session(
&[
("net.transport", json!({ "url": "ws://127.0.0.1:9" })),
(KIT, json!({})),
],
true,
);
let sessions = call(&mut s, "probe.core", "sessions", json!([]));
assert_eq!(sessions[0]["config"]["model"], "async");
assert_eq!(
sessions[0]["config"]["transport"]["url"],
"ws://127.0.0.1:9"
);
assert!(commands(&mut s).iter().any(|c| c["c"] == "connect"));
}
Settings and defaults #
Descriptions come from the kit manifest and stay in English.
| Setting | Type | Default | Range or values | Meaning |
|---|---|---|---|---|
preset | string | "none" | none, ghost-race, async-pvp, daily-challenge | Ready-made option set applied between the defaults and this config (defaults ← preset ← your keys, merged key by key; rules too):… |
game | string | "arena" | arena / physics = deterministic games of the core (replayable, verified by server replay); any other name = your engine game… | |
physics | string | "none" | none, native, shared | shared = the game physics (net.physics) inside the core; native = your engine physics, recorded as samples (game must then be… |
record | string | "both" | inputs, samples, both | What a run stores: input streams (net.rollback format), transform samples, or both. |
players | integer | 1 | 1–8 | Slots of the recorded game (2+ for async PvP). |
slot | integer | 0 | 0–7 | The recording player's slot (< players). |
opponentSlot | integer | -1 | -1–7 | Async PvP: slot played by the loaded opponent run (< players, ≠ slot; -1 = auto: the first slot other than slot when an opponent… |
frameHz | integer | 60 | 10–120 | Frames per second of a run. |
sampleHz | integer | 10 | 1–60 | Transform samples per second. |
maxFrames | integer | 36000 | 60–216000 | Longest recording (frames); recording stops there. |
clock | string | "core" | core, host | core = frames advance with time; host = on step() (your fixed update drives the run). |
board | string | "" | Board / challenge key of the runs (daily-YYYY-MM-DD for daily challenges). | |
order | string | "desc" | desc, asc | Boards: higher (desc) or lower (asc) scores first. |
app | string | "" | Application id written in runs (the wrappers fill it from net.transport app). | |
player | string | "" | Player name written in runs. | |
engine | string | "" | Engine tag written in runs (web, godot, unity, unreal; set by the wrappers). | |
apiUrl | string | "" | Run API up to /api/v1/async (GripForge: https://<host>/api/v1/async; self-hosted: gf-async-server). | |
apiKey | string | "" | x-api-key for the GripForge API. | |
rules | object | {"minFrames": 1, "maxSpeed": 0, "speedSlack":… | Server checks of a submitted run (merged key by key over the preset's). | |
maxRuns | integer | 1000 | 1–100000 | Async gfnet server (gf-net-server --model async): runs kept in memory. |
maxRunBytes | integer | 262144 | 1024–1048576 | Largest run accepted (bytes). |
uploadChunksPerSecond | number | 6 | 1–60 | Client: run upload rate (chunks of 32000 base64 characters per second). |
maxPartialUploadsPerPeer | integer | 2 | 1–64 | Server: uploads in progress per peer. |
boardRows | integer | 100 | 1–1000 | Largest board / run list a query or a client asks for. |
boardDefaultRows | integer | 10 | 1–1000 | Rows of a board / run list when the query does not say. |
Services, events, variables #
- Service
net.async: recordStart / recordStop / export, loadGhost / play / ghost, submit / fetch / board / daily (HTTP), verify (local). - Service
net.replay: Compact recordings of a run (inputs + samples), replayed bit-exactly for the deterministic games. - Events emitted:
net.async.recorded(id,bytes,frames,score) — A recording stopped; export() returns it.net.async.submitted(ok,id,score,rank) — The server verified (or refused) a run.net.async.ghost_end(ghost,id) — A ghost reached the end of its run.net.refused(code,msg) — 1.2: the server of the session path refused the handshake (version, app, model, full…; mods: it runs other mods than this game,…
- Variables:
net.async.frame(number) — Run framenet.async.score(number) — Run scorenet.async.recording(boolean) — Recording
Hooks and modding #
This kit declares no hook and no collection to mod.
Engines #
Declared targets: web, godot, unity, unreal. gripforge kit api net.async lists the exact settings and services of your version.
Versions #
Kit version 1.2.0.