DocumentationCore Protocol
@painda/gaming
The Delta Engine. Real-time state synchronization with minimal bandwidth — object diffs, array delta ops, and Myers-optimal patching.
Why the Delta Engine?
- Bandwidth Saver: At 60 FPS, sending full JSON every frame kills the network. Only changed fields are sent.
- Array Delta Ops: Arrays are diffed with Myers O(ND) — only splice/set operations sent, not the full array.
- Deletion Sentinels: Deleted keys are marked with
PP_DELETED, notnull— survives JSON round-trips safely.
Object Diff — Server & Client
Server: create and broadcast patches
import { StateManager } from "@painda/gaming";
const gameState = new StateManager({
players: { hero1: { x: 10, y: 20, hp: 100 } }
});
// Game loop tick
gameState.update({ players: { hero1: { x: 15 } } }); // only X changed
const delta = gameState.getDelta();
if (delta) {
// { players: { hero1: { x: 15 } } } — only the diff
server.broadcast({ type: "game-update", payload: delta });
}
Client: apply patches in-place
import { patch } from "@painda/gaming";
let localState = { players: { hero1: { x: 10, y: 20, hp: 100 } } };
client.on("message", (msg) => {
if (msg.type === "game-update") {
patch(localState, msg.payload); // in-place mutation
// localState.players.hero1.x is now 15
}
});Array Delta Ops
Arrays are diffed with Myers O(ND) algorithm. Instead of sending the whole array, only splice and set operations are transmitted. This is unique to PaindaProtocol — no other WebSocket framework has built-in array-level delta sync.
import { diff, patch, isArrayOps } from "@painda/gaming";
const prev = { items: ["a", "b", "c", "d"] };
const next = { items: ["a", "x", "c", "d"] }; // only index 1 changed
const delta = diff(prev, next);
// delta.items === { __pp_array_ops: [{ op: "set", index: 1, value: "x" }] }
// NOT the full array — just the change
patch(prev, delta);
// prev.items === ["a", "x", "c", "d"]| Export | Description |
|---|---|
| PPArrayOpsMarker | Type: { __pp_array_ops: ArrayOp[] } |
| ArrayOp | { op: "set", index, value } or { op: "splice", index, deleteCount, items } |
| isArrayOps(v) | Type guard for PPArrayOpsMarker |
Breaking change note: Server and client must use the same version of
@painda/gaming. Array delta ops use a __pp_array_ops sentinel that older versions do not understand — they will replace the array wholesale (backwards-compatible fallback).Deletion Sentinel
import { diff, patch, PP_DELETED, isDeleted } from "@painda/gaming";
const prev = { score: 10, bonus: 5 };
const next = { score: 12 }; // bonus deleted
const delta = diff(prev, next);
// delta === { score: 12, bonus: PP_DELETED }
// PP_DELETED = { __pp_deleted: true } — NOT null
patch(prev, delta);
// prev === { score: 12 } // bonus removedCritical: Core's built-in diff uses
null for deletions. If you use patch from @painda/gaming on the client, the server must also use diff from @painda/gaming (via diffAlgorithm). Mixing them silently breaks deletions.