Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

zigsel/magnet

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

magnet

A generic, zero-allocation UDP game-networking stack in Zig.

Reliable channels, real congestion control, optional encryption, a compile-time bit-level serializer, and a complete client-prediction / rollback replication layer - all monomorphized from one comptime Config, and all sans-IO: the protocol never touches a socket, a clock, or an allocator.

const magnet = @import("magnet");

const Update = union(enum) {
    spawn:  struct { id: u32, x: i16, y: i16 },
    damage: struct { id: u32, hp: i16 },
    chat:   magnet.wire.Bounded(u8, 64),
};
const Move = struct { dx: i8, dy: i8 };

const Schema = magnet.proto.channels(.{
    .updates = .{ .mode = .reliable_ordered,     .Message = Update },
    .moves   = .{ .mode = .unreliable_sequenced, .Message = Move },
});

const Cfg = magnet.Config{ .channels = Schema, .protocol_id = 0= .aead } };
const Endpoint = magnet.Endpoint(Cfg);

try server.sendTo(client, .updates, .{ .chat = .fromSlice("gg") });

var it = server.receive(.moves);
while (it.next()) |r| applyMove(r.addr, r.msg);

Why magnet

  • Zero steady-state allocation. Every ring, pool, and buffer is sized from the comptime config and allocated once. After init the hot path never sees an allocator; pool exhaustion is a defined, observable event, never a crash.
  • Pay only for what you use. Comptime monomorphization compiles out the machinery you don't enable - an unreliable channel carries no retransmit state, security.mode = .none links no crypto, replication = null links none of L5.
  • Sans-IO. The core is a pure feed / pollTransmit / pollDeadline state machine, so it runs single-threaded, sharded, fiber-per-connection, or polled from a game loop - whichever driver you pick - and is fully deterministic-testable over a simulated link.
  • Genre-agnostic. No fps / rts / mmo modules. Genres are configuration over the same generic systems.
  • std-only. std.crypto, std.Io, std.mem. No libsodium, no third-party dependencies.

The stack

Six layers; take only what you need (unused layers are never linked):

L5  replication/   snapshots · prediction · rollback · interpolation · interest · lag-comp
L4  wire/          @typeInfo serde · bitpack · quantize · delta
L3  proto/channel/ reliability taxonomy · ordering streams · WFQ scheduler · packer
L2  proto/delivery/ packet numbers · ack-ranges · RACK · RTT/PTO · congestion · fragmentation
L1  proto/conn/    handshake · tokens · AEAD · replay · connection IDs · migration
L0  runtime/       std.Io drivers (poll · reactor · sharded · task) · network simulator
        core/      SequenceBuffer · seq · pool · ring · bitset · fixed
  • Stop at L3 for secure-optional reliable UDP with typed channels.
  • Stop at L4 to also get a comptime, bit-level serializer.
  • Go to L5 for the full prediction / rollback / interest machinery.

Features

  • Six reliability modes per channel, with independent ordering streams (no head-of-line blocking) and a weighted-fair scheduler.
  • Decoupled packet numbers, RLE ack-ranges, RACK loss detection, integer RTT/PTO, and four pluggable congestion controllers (NewReno · CUBIC · BBR · Fixed) - all integer/fixed-point.
  • Message fragmentation, path-MTU discovery, token-bucket pacing.
  • AEAD encryption with a stateless SipHash challenge, sliding replay window, 3× anti-amplification, connect tokens, Ed25519 cert identity, and connection-ID migration.
  • A @typeInfo-derived serializer (plain data needs no serde code), with quantization and bounded slices.
  • L5: server-authoritative replication, client prediction + whole-world rollback, snapshot interpolation, rooms + spatial-grid interest, replication priority, lag compensation, client authority + transfer, lockstep and P2P-rollback authority, ICE-lite NAT punch.
  • Real std.Io socket drivers plus a Linux backend (sendmmsg/recvmmsg, GSO/GRO), and a seeded deterministic network simulator for tests.
  • A comptime, zero-cost tracer; live stats(); record/replay.

Quick start

zig build test       # unit + integration + conformance + fuzz/soak
zig build examples   # build every example
zig build run-fps    # run one (try: echo, channels, encrypted, replicate, lockstep_rts …)
zig build bench      # perf benchmarks (ReleaseFast)
zig build docs       # API docs → zig-out/docs/

Requires Zig 0.16.

Documentation

Start with docs/readme.md and docs/getting-started.md. There's a guide per layer, genre recipes, concept explainers (sans-IO, comptime, the wire format, the security model), and a config/error reference. Every guide links a runnable example in examples/.

Status

Implemented across all six layers and hardened (fuzz, soak, golden conformance vectors, zero-allocation proof, cross-driver equivalence; The remaining release step is freezing the v1 wire format and tagging.

Acknowledgements

magnet stands on a deep reading of the field. It fuses the classic game lineage's zero-alloc data structures with QUIC's delivery engine, and owns the replication core lightyear charts - all re-expressed through Zig's comptime and std.Io. With thanks to:

  • reliable.io / netcode.io / yojimbo (Glenn Fiedler)
    • the SequenceBuffer, redundant ack bitfield, stateless AEAD connect-token handshake, the unified bitpacked serializer, and the packet→message ack bridge.
  • RakNet - the reliability taxonomy, independent ordering streams, the ordered+sequenced blend, DF-probe MTU discovery, and refcounted fragments.
  • Valve GameNetworkingSockets - WFQ lanes, the packet-number-derived AEAD nonce, the SipHash SYN-cookie, token-bucket pacing, and the HKDF key schedule.
  • quinn / QUIC (RFC 9000/9002) - decoupled packet numbers, ack-ranges, RACK, the RTT/PTO estimator, the pluggable Controller, NAT-rebind migration and anti-amplification, and the sans-IO architecture itself.
  • laminar - clean module boundaries and the injectable-transport test seam.
  • Bevy lightyear - the entire L5 toolkit: prediction, rollback, interpolation, input handling, interest management, priority, tick-sync, and prespawn reconciliation.

Standards: QUIC loss/recovery (RFC 9000, 9002), CUBIC (RFC 8312), ICE (RFC 8445), and serial number arithmetic (RFC 1982).

The borrowed ideas are theirs; the bugs are ours.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.