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, not null — 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"]
ExportDescription
PPArrayOpsMarkerType: { __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 removed
Critical: 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.