# 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): ```text 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 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. ```rust #[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. | Setting | Type | Default | Range or values | Meaning | |---|---|---|---|---| | `snapshotHz` | integer | `20` | 1–120 | Server → clients state rate (Hz). | | `publishHz` | integer | `20` | 1–120 | Owner → server state rate (Hz). | | `leaseMs` | integer | `750` | 100–60000 | An owner silent this long loses its objects (they revert to the server). | | `stickyMs` | integer | `250` | 0–10000 | Minimum hold before another peer may take an object (anti ping-pong). | | `maxHoldMs` | integer | `0` | 0–3600000 | Cap on one hold (0 = none). | | `stealPolicy` | string | `"priority"` | `never`, `priority`, `always` | Owned object claimed by another peer: never (first wins), priority (strictly higher priority wins), always (latest wins). | | `maxClaimsPerPeer` | integer | `64` | 1–4096 | Objects one peer may hold at once. | | `maxObjectsPerPeer` | integer | `256` | 0–65536 | Objects one peer may create. | | `maxObjects` | integer | `4096` | 1–1000000 | Cap on all replicated objects: clients cannot create beyond it. | | `keyframeEvery` | integer | `20` | 1–1000 | Every Nth snapshot carries every object (heals lost deltas). | | `maxSpeed` | number | `300` | 0–10000 | Plausibility: max speed of a published object in m/s (0 = off). | | `worldLimit` | number | `2000` | 1–1000000 | Positions beyond ±worldLimit m are rejected. | | `maxAngularSpeed` | number | `1000` | 0–1000000 | Published angular velocities beyond this (rad/s, per axis) are rejected. | | `antiCheat` | boolean | `true` | | Plausibility check of published moves (maxSpeed × plausibilitySlack + plausibilityMarginM over the elapsed time); false = trust… | | `plausibilitySlack` | number | `1.5` | 1–10 | Anti-cheat: tolerance factor on maxSpeed (jitter, bursts). | | `plausibilityMarginM` | number | `0.5` | 0–100 | Anti-cheat: distance always allowed on top (m). | | `plausibilityMinDtMs` | integer | `50` | 1–1000 | Anti-cheat: the elapsed time counts as at least this (two publishes arriving together). | | `onOwnerLeave` | string | `"revert"` | `revert`, `destroy` | Objects created by a peer that leaves: kept (server-owned) or destroyed. | | `interpolationMs` | integer | `100` | 0–1000 | Remote objects are drawn this far in the past. | | `interpolationBuffer` | integer | `32` | 2–256 | Remote samples kept per object. | | `extrapolateMs` | integer | `250` | 0–1000 | Extrapolate at most this long past the newest remote sample. | | `reclaimMs` | integer | `500` | 50–10000 | A pending claim is sent again after this long without an answer. | | `handoverMinMs` | integer | `200` | 0–5000 | Blend from the local simulation to the new owner: at least… | | `handoverMaxMs` | integer | `2000` | 0–10000 | …at most (the blend lasts about one RTT). | | `snapDistance` | number | `4` | 0.01–1000 | Errors above this (m) snap instead of blending. | | `optimistic` | boolean | `true` | | Drive a claimed object at once, before the grant arrives. | | `sleepKeyframeMs` | | `0` | | Owner: a sleeping body is still published this often, so its lease never expires (0 = auto: min(1000, leaseMs / 3)); must stay… | | `pushExtrapolateMs` | integer | `100` | 0–1000 | physics: the server predicts a pushed body at most this far ahead. | | `maxStepsPerUpdate` | integer | `16` | 1–256 | physics: server steps per host frame at most (the backlog of a stalled host is dropped). | | `clientMaxStepsPerUpdate` | integer | `8` | 1–256 | physics: client steps per host frame at most. | | `maxClientBodySize` | number | `50` | 0.01–1000 | physics shared: largest extent / radius (m) of a body a client creates. | | `maxClientBodyMass` | number | `10000` | 0–1000000 | physics shared: largest mass (kg) of a body a client creates. | | `autoClaimRadius` | number | `0` | 0–1000 | Web runtime: claim objects tagged net_claimable within this distance of the player (0 = only explicit claims); released beyond… | | `physics` | string | `"none"` | `none`, `native`, `shared` | Bodies: none; native = the engine physics simulates (owner / dedicated server), the core replicates states, sleep and… | | `avatar` | boolean | `true` | | Web 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.