Network sync: claim (distributed authority)

Shares authority between players by claim: each client simulates the objects it has claimed, such as its avatar or a car it drives, while the server only arbitrates and everything else is shown interpolated.

Source: module-kits:kits/net_claim/usage/en.mdView Markdown source

Also read offline — CLI: grip-forge docs net-claimMCP tool: gripforge_docs { "topic": "net-claim" }

Network sync: claim (distributed authority) (net.claim) #

What it is for #

Shares authority between players by claim: each client simulates the objects it has claimed, such as its avatar or a car it drives, while the server only arbitrates and everything else is shown interpolated.

It needs net.transport, 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.claim" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "net.claim",
                              config: { "snapshotHz": 20, "publishHz": 20 } }

First example #

<!-- test: kits/net_claim/tests/net_claim.rs::connecting_publishes_the_player_as_a_locked_avatar_once --> This is the body of the passing test connecting_publishes_the_player_as_a_locked_avatar_once; the helper functions it calls are defined at the top of the same test file.

#[test]
fn connecting_publishes_the_player_as_a_locked_avatar_once() {
    let mut s = online(json!({}));
    player(&mut s, 1.0, 2.0);
    answer(&mut s, "c:create", json!(40));
    connect(&mut s, 3);
    let sent = commands(&mut s);
    let creates: Vec<&Json> = sent.iter().filter(|c| c["c"] == "create").collect();
    assert_eq!(creates.len(), 1);
    assert_eq!(creates[0]["state"]["p"], json!([1, 0, 2]));
    assert_eq!(creates[0]["state"]["d"], json!({ "kind": "avatar" }));
    assert_eq!(creates[0]["lock"], true);
    assert_eq!(call(&mut s, KIT, "netIdOf", json!(["e1"])), json!(40));
    assert_eq!(call(&mut s, KIT, "entityOf", json!([40])), json!("e1"));
    step(&mut s, 2);
    assert!(
        commands(&mut s).iter().all(|c| c["c"] != "create"),
        "never created twice"
    );
}

Settings and defaults #

Descriptions come from the kit manifest and stay in English.

SettingTypeDefaultRange or valuesMeaning
snapshotHzinteger201–120Server → clients state rate (Hz).
publishHzinteger201–120Owner → server state rate (Hz).
leaseMsinteger750100–60000An owner silent this long loses its objects (they revert to the server).
stickyMsinteger2500–10000Minimum hold before another peer may take an object (anti ping-pong).
maxHoldMsinteger00–3600000Cap on one hold (0 = none).
stealPolicystring"priority"never, priority, alwaysOwned object claimed by another peer: never (first wins), priority (strictly higher priority wins), always (latest wins).
maxClaimsPerPeerinteger641–4096Objects one peer may hold at once.
maxObjectsPerPeerinteger2560–65536Objects one peer may create.
maxObjectsinteger40961–1000000Cap on all replicated objects: clients cannot create beyond it.
keyframeEveryinteger201–1000Every Nth snapshot carries every object (heals lost deltas).
maxSpeednumber3000–10000Plausibility: max speed of a published object in m/s (0 = off).
worldLimitnumber20001–1000000Positions beyond ±worldLimit m are rejected.
maxAngularSpeednumber10000–1000000Published angular velocities beyond this (rad/s, per axis) are rejected.
antiCheatbooleantruePlausibility check of published moves (maxSpeed × plausibilitySlack + plausibilityMarginM over the elapsed time); false = trust…
plausibilitySlacknumber1.51–10Anti-cheat: tolerance factor on maxSpeed (jitter, bursts).
plausibilityMarginMnumber0.50–100Anti-cheat: distance always allowed on top (m).
plausibilityMinDtMsinteger501–1000Anti-cheat: the elapsed time counts as at least this (two publishes arriving together).
onOwnerLeavestring"revert"revert, destroyObjects created by a peer that leaves: kept (server-owned) or destroyed.
interpolationMsinteger1000–1000Remote objects are drawn this far in the past.
interpolationBufferinteger322–256Remote samples kept per object.
extrapolateMsinteger2500–1000Extrapolate at most this long past the newest remote sample.
reclaimMsinteger50050–10000A pending claim is sent again after this long without an answer.
handoverMinMsinteger2000–5000Blend from the local simulation to the new owner: at least…
handoverMaxMsinteger20000–10000…at most (the blend lasts about one RTT).
snapDistancenumber40.01–1000Errors above this (m) snap instead of blending.
optimisticbooleantrueDrive a claimed object at once, before the grant arrives.
sleepKeyframeMs0Owner: a sleeping body is still published this often, so its lease never expires (0 = auto: min(1000, leaseMs / 3)); must stay…
pushExtrapolateMsinteger1000–1000physics: the server predicts a pushed body at most this far ahead.
maxStepsPerUpdateinteger161–256physics: server steps per host frame at most (the backlog of a stalled host is dropped).
clientMaxStepsPerUpdateinteger81–256physics: client steps per host frame at most.
maxClientBodySizenumber500.01–1000physics shared: largest extent / radius (m) of a body a client creates.
maxClientBodyMassnumber100000–1000000physics shared: largest mass (kg) of a body a client creates.
autoClaimRadiusnumber00–1000Web runtime: claim objects tagged net_claimable within this distance of the player (0 = only explicit claims); released beyond…
physicsstring"none"none, native, sharedBodies: none; native = the engine physics simulates (owner / dedicated server), the core replicates states, sleep and…
avatarbooleantrueWeb runtime: publish the local player entity as this client's avatar object.

Services, events, variables #

  • Service net.sync: The project replication model (one per project: the net.* sync kits conflict with each other).
  • Service net.claim: claim(entity, priority) / release(entity) / isOwner(entity) / create(state); ownership events.
  • Events emitted:
    • net.owner (entity, netId, owner, mine) — Ownership of a replicated object changed.
    • net.denied (entity, netId, why) — A claim was refused (owned, sticky, quota, locked, unknown).
  • Variables:
    • net.status (string) — Network status
    • net.rtt (number) — Ping (ms)
    • net.peers (number) — Players online

Hooks and modding #

This kit declares no hook and no collection to mod.

Engines #

Declared targets: web, godot, unity, unreal. gripforge kit api net.claim lists the exact settings and services of your version.

Versions #

Kit version 1.2.0.