code wiki / (root) / nx_state_delta_codec.nx

nx_state_delta_codec.nx

buildroot/runtime/nx_state_delta_codec.nx

15056 B368 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind tooltopic state
docsdependenciesstructsconstsfunctions

about

nx_state_delta_codec.nx -- quantized bit-packed entity state delta codec. Foundation for poor-internet multiplayer. The naive "serialize full entity state every frame" approach uses ~32 bytes/entity (x,y,z,yaw, pitch,health,id,flags as i64). At 60Hz x 100 entities = 192 KB/s. On a 56 kbps dial-up link (7 KB/s ceiling) that's 27x over budget. Delta-quantize-bitpack collapses this to typical 1-4 bytes per entity per frame: - Bit cursor over a byte buffer (write_bits / read_bits). - Signed N-bit delta encoding (twos-complement) for position + velocity changes between adjacent frames. - Unsigned N-bit absolute encoding for angles (256-step yaw = ~1.4 deg precision; the GGPO/Skullgirls choice). - Varint (7-bit continuation, identical wire format to Protobuf varint / LEB128) for sparse integer fields. Bandwidth budget on a typical FPS frame: per entity: 1 byte change-mask + ~3 bytes delta = 4 bytes 100 entities at 60Hz = 24 KB/s Compare: full-state baseline 192 KB/s -> 8x reduction. On 56 kbps dial-up, area-of-interest culling brings the entity count down to ~20 in-view -> 4.8 KB/s, fits under the 7 KB/s ceiling. Source references (all open): - GGPO bit-packed input frames (Cannon 2006, pond3r/ggpo) - Slither.io / Agar.io quantized state protocols (ClitherProject reverse-eng) - Protobuf varint / LEB128 (developers.google.com/protocol-buffers/docs/encoding) - Quake 3 delta-compressed entity protocol (Carmack .plan) genealogy_id: ggpo_bitpacked_inputs + protobuf_varint + quake3_delta_entities lineage_id: bandwidth_quantize_entity_state

dependencies 3 imports · 0 importers

nx_syscalls.nx nx_tier.nx nx_zigzag_varint.nx nx_state_delta_codec.nx

imports: nx_syscalls.nxnx_tier.nxnx_zigzag_varint.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nx_delta_writer_new sys_mmap nx_delta_write_bits nx_delta_writer_buf nx_delta_writer_bytes_used nx_delta_reader_new sys_mmap ↻ nx_delta_writer_buf ↻ nx_delta_read_bits nx_delta_write_signed nx_delta_write_bits ↻ nx_delta_read_signed nx_delta_read_bits ↻ nx_delta_write_varint nx_delta_write_bits ↻ nx_delta_read_varint nx_delta_read_bits ↻ nx_delta_write_zigzag_vari nx_zigzag_varint_encode nx_delta_write_varint ↻ nx_delta_read_zigzag_varin nx_delta_read_varint ↻ nx_zigzag_varint_decode

structs

none

consts

44const NX_MAGIC_2047: i64 = 2047
45const NX_MAGIC_2048: i64 = 2048
46const NX_MAGIC_16383: i64 = 16383
47const NX_MAGIC_16384: i64 = 16384
48const NX_MAGIC_1000000: i64 = 1000000
57const NX_DC_OFF_BUF: nx_int = 0
58const NX_DC_OFF_BYTE: nx_int = 1
59const NX_DC_OFF_BIT: nx_int = 2
60const NX_DC_OFF_CAP: nx_int = 3
61const NX_DC_HDR_SIZE: nx_int = 4

functions

63func nx_delta_writer_new(cap_bytes: nx_int) -> *i64
called by 1: main calls 1: sys_mmap
79func nx_delta_writer_bytes_used(w: *i64) -> nx_int
called by 1: main
86func nx_delta_writer_buf(w: *i64) -> *u8
93func nx_delta_write_bits(w: *i64, value: i64, n_bits: nx_int)
128func nx_delta_write_signed(w: *i64, value: i64, n_bits: nx_int)
called by 1: main calls 1: nx_delta_write_bits
143func nx_delta_write_varint(w: *i64, value: i64)
161func nx_delta_reader_new(buf: *u8, n_bytes: nx_int) -> *i64
called by 1: main calls 1: sys_mmap
170func nx_delta_read_bits(r: *i64, n_bits: nx_int) -> i64
207func nx_delta_read_signed(r: *i64, n_bits: nx_int) -> i64
called by 1: main calls 1: nx_delta_read_bits
222func nx_delta_write_zigzag_varint(w: *i64, value: i64)
228func nx_delta_read_varint(r: *i64) -> i64
243func nx_delta_read_zigzag_varint(r: *i64) -> i64
250func main() -> i64