Table of Contents

SetNet modules — implemented & planned

SetNet is a small core plus optional companion packages added by composition. Each depends only on SetNet (unless noted) and is wired by an xxxRuntime.Enable() call + server.UseXxx() / client.UseXxx() extensions, so the core stays lean and users pull only what they need.

Unified messaging (SetNet.Protocol, in core). Every command/reply/event companion module below speaks the same three verbs over one shared envelope wire id (ProtocolTypes.Envelope), demultiplexed by a per-module Channels.X id + an op: correlated request/reply (client.RequestAsync/RequestRawAsync), fire-and-forget (client.PostAsync/PostRawAsync), and server push (client.On<T>/OnRawpeer.PublishRawAsync), with the server side handled by an auto-discovered [ProtocolChannel(Channels.X)] IChannelService. This means no per-module wire-type reservations and one shared correlation/subscription mechanism instead of each module hand-rolling its own. SetNet.Rpc rides it too — client.CallAsync(methodId, req) is a typed alias of RequestAsync on the Channels.Rpc channel. A handful of modules with a genuinely different message shape stay off it and keep their own reserved ids: SetNet.StateSync (+ .Rpc), SetNet.Voice, SetNet.Fragmentation, SetNet.Multiplex, SetNet.Streams, SetNet.Cluster, SetNet.Auth, SetNet.ProofOfWork.

Shipped

Grouped by purpose (mirrors the src/<category>/ layout). Each depends only on SetNet unless noted.

Serializers (src/serializers/)

Package What it adds
SetNet.MessagePack MessagePackNetSerializer (ISerializer, UntrustedData-hardened) — the recommended serializer
SetNet.Json System.Text.Json serializer — human-readable, web-friendly
SetNet.MemoryPack MemoryPack serializer — fast, zero-encoding, AOT/IL2CPP-friendly
SetNet.Protobuf protobuf-net serializer — compact, cross-language
SetNet.Compression decorator ISerializer wrapping any inner one with transparent Brotli

Transports (src/transports/)

Package What it adds
SetNet.WebSockets WebSocket transport via config.UseWebSockets()
SetNet.InMemory in-process loopback transport via config.UseInMemory() (no sockets; great for tests)

Messaging (src/messaging/)

Package What it adds
SetNet.Rpc await client.CallAsync<TReq,TResp>() + [RpcMethod] handlers
SetNet.Streams large-payload streaming both directions: offer/accept, sequential chunks, progress, resume after disconnect; pluggable sinks (memory/file)

Security (src/security/)

Package What it adds
SetNet.Auth enforced gate + token auth + sessions (TTL, rotation, sweep) + ISessionStore + reconnect-resume
SetNet.Auth.Jwt JWT IAuthenticator (deps SetNet.Auth)
SetNet.Auth.OAuth OpenID Connect authenticator (auto-refreshed JWKS) (deps SetNet.Auth)
SetNet.BanList inbound gate dropping banned peers (IP/custom key) + kick; pluggable IBanStore
SetNet.DdosGuard per-IP connection-flood detection + timed auto-ban (deps SetNet.BanList)
SetNet.GeoBlock reject connections by country (blocklist/allowlist) via a pluggable IGeoResolver; kick-on-connect
SetNet.ProofOfWork hashcash admission gate — drop a peer's frames until it solves a SHA-256 challenge (anti-bot)

Net / QoS (src/net/)

Package What it adds
SetNet.RateLimit per-peer token-bucket inbound gate
SetNet.Fragmentation split/reassemble oversize UDP messages transparently
SetNet.Priority priority send queue with an optional per-flush byte budget
SetNet.Congestion AIMD congestion controller → per-tick byte budget
SetNet.Relay TURN-style relay hub: allocate/join a session by code, forward opaque bytes (NAT fallback/tunnel)
SetNet.NatPunch UDP hole-punching: coordinator exchanges public/private endpoint candidates + NatPuncher.TryPunchAsync opens the direct path (fallback: Relay)
SetNet.Upnp UPnP IGD port mapping: SSDP discovery + AddPortMapping/DeletePortMapping/GetExternalIPAddress; config.MapServerPortsAsync() (no wire types)
SetNet.Multiplex logical channels over one connection: SendMuxAsync(channel, type, msg) → per-channel ordered dispatch lanes (head-of-line-blocking fix)

Realtime / game (src/realtime/)

Package What it adds
SetNet.Rooms rooms/lobbies by code, broadcast, join/leave events + IRoomStore
SetNet.Rooms.HostMigration designate + migrate room host on leave (deps SetNet.Rooms)
SetNet.Matchmaking FIFO/skill queues with a widening window → creates a room (deps SetNet.Rooms)
SetNet.Party party/group by code, leader + ready state, events
SetNet.Chat channel-based text chat + moderation
SetNet.Voice codec-agnostic voice-chat relay: numeric channels, opaque audio frames, unreliable fan-out
SetNet.Lockstep deterministic wait-for-all turn engine
SetNet.Inventory server-authoritative stackable inventory: grant/revoke by player key, atomic TryRevoke, read + push; pluggable IInventoryStore
SetNet.Trade player-to-player escrow trading: two-phase ready→confirm lock, atomic cross-swap through Inventory with rollback (deps SetNet.Inventory)
SetNet.Mail offline mail with item attachments escrowed from the sender and granted on claim; pluggable IMailStore (deps SetNet.Inventory)
SetNet.Zones seamless player handoff between world nodes: stash carried state under a one-time token, push a migrate instruction, claim on the destination; pluggable IHandoffStore
SetNet.Wallet server-authoritative currencies: atomic deposit/withdraw/transfer by player key, read + push; pluggable IWalletStore
SetNet.Vendor NPC shops: buy/sell catalogs with stock, settled atomically through Wallet + Inventory (deps SetNet.Inventory + SetNet.Wallet)
SetNet.Auction player auction house: escrow item + bids, timer-settled, outbid refunds + won/sold/returned events (deps SetNet.Inventory + SetNet.Wallet)
SetNet.Crafting recipes (inputs → outputs) crafted atomically through Inventory with rollback (deps SetNet.Inventory)
SetNet.Loot weighted server-side drop tables (guaranteed + weighted draws), granted through Inventory; gated client-open (deps SetNet.Inventory)
SetNet.Quests quests with objectives + item rewards: server-driven progress, QuestCompleted event, claim grants via Inventory (deps SetNet.Inventory)
SetNet.Progression levels/XP with a configurable curve, multi-level rollover, LeveledUp event, read + push; pluggable IProgressionStore
SetNet.Guilds guilds/clans: roles (member/officer/leader), promote/kick, shared bank as a guild-keyed inventory (deps SetNet.Inventory)
SetNet.Marketplace continuous double-sided order book: limit buy/sell, price-time matching at the resting price, escrow via Wallet + Inventory (deps SetNet.Inventory + SetNet.Wallet)
SetNet.StatusEffects server-authoritative buffs/debuffs on any target key: timed, stacking, timer-expired, pushed to the target + watchers
SetNet.StateSync server-authoritative entity replication: delta snapshots, interpolation, interest, input
SetNet.StateSync.SpatialGrid grid interest manager (deps SetNet.StateSync)
SetNet.StateSync.LagCompensation server rewind for fair hit detection (deps SetNet.StateSync)
SetNet.StateSync.Prediction client input buffer + reconciliation (deps SetNet.StateSync)
SetNet.StateSync.NetworkVariable typed change-tracked NetworkVariable<T> (deps SetNet.StateSync)
SetNet.StateSync.Rpc entity-scoped RPCs both directions (deps SetNet.StateSync)

World / AI (src/realtime/) — server-side spatial libraries (GeoData/PathFinding have no wire protocol) + entity modules

Package What it adds
SetNet.GeoData server-side world geometry behind one IGeoData: walkability, line-of-sight, can-walk-straight, ground height, raycast — over a 2.5D nav-grid (GridGeoData), an L2-style multi-storey grid (LayeredGridGeoData — stacked height layers per cell → floors/bridges without a nav-mesh), or a Y-aware nav-mesh (NavMeshGeoData); SectoredGeoData stitches many per-sector geodatas into one seamless world (+ GeoDataManifest .geomap); bake portable GeoDataFiles (no wire protocol)
SetNet.PathFinding A* over GridGeoData (octile, no corner-cut), LayeredGridGeoData (per-layer, climbs stairs between floors), NavMeshGeoData (triangle A* → portals → string-pull), or SectoredGeoData (delegate within a sector + stitch across borders) + PathFollower; pooled + generation-stamped search (allocation-free hot path, built-once-reused for MMO scale) (deps SetNet.GeoData)
SetNet.NPC non-living interactive entities (vendors/buffers/teleporters/dialogue): one INpcBehaviour per type + spawn/zone-interest/interact, delegating to the economy/status modules via a capability hand-off (deps SetNet.GeoData for Vec3)
SetNet.Mobs hostile AI entities with per-mob AI (IMobBrain: ready aggressive / retaliate-only / ranged-kiter / caster brains + a composer), server-authoritative tick loop, perception, threat, telegraphed abilities, loot/respawn on death. StateSync-optional — replicates via an IMobReplication seam (drive it with Update(dtMs) and no StateSync at all, or plug the adapter below) (deps SetNet.GeoData + SetNet.PathFinding)
SetNet.Mobs.StateSync optional adapter that replicates mobs over StateSync (IMobReplicationServerReplication) (deps SetNet.Mobs + SetNet.StateSync)
SetNet.Locomotion one unified server-side movement tick: create a Mover (auto-subscribed) and it advances along a pathfound route N Hz; replicates nothing (a Started hook lets you send just the destination, L2-style) (deps SetNet.GeoData + SetNet.PathFinding)
SetNet.Mobs.Locomotion opt-in bridge (loco.AsMobMover()MobOptions.Mover) that advances mob positions through the shared SetNet.Locomotion tick instead of the built-in follower — players + mobs in one system (deps SetNet.Mobs + SetNet.Locomotion)
SetNet.StateMachine tiny generic finite-state machine (states / guards / any-state transitions) for AI/gameplay — no wire protocol
SetNet.BehaviorTree generic behavior tree (Sequence/Selector/Parallel + Inverter/Repeat/Cooldown decorators + Action/Condition/Wait leaves, fluent builder) — no wire protocol
SetNet.Spawning zone-based mob spawning over SetNet.Mobs: box/circle areas + per-type counts + respawn delay, walkable-snapped via GeoData (deps SetNet.Mobs + SetNet.GeoData)
SetNet.Ticks one central update loop: register anything (ITickable/lambda) into a named channel with its own rate (Hz) + priority; drives them all from one place (30 Hz movement, 10 Hz AI, 1 Hz housekeeping) with per-channel fixed timestep; Start() internal timer or Pump(dt) from your loop. Auto-subscription: new TickScheduler().MakeCurrent() before your UseXxx(...) and MobServer/LocomotionSystem/SpawningServer subscribe themselves (no manual wiring); behaviour trees/state machines plug in via Bind(ctx). Zero deps — the tick foundation lives here (not core), and the game-loop modules depend on it — no wire protocol
SetNet.Notifications server→client notifications / toasts with an offline queue flushed on reconnect
SetNet.Dialogue server-authoritative branching dialogue trees (guarded choices + side-effects), StartAsync/ChooseAsync

Character / RPG systems (src/realtime/) — the combat foundation; Stats underpins the rest

Package What it adds
SetNet.Stats your own stat schema + a StatSet whose values compute from a base plus flat / additive-% / multiplicative-% modifiers (clamped, cached, remove-by-source) — no wire protocol
SetNet.Combat damage resolution between two StatSets: pluggable ICombatFormula, configurable CombatStatKeys, crit + armor mitigation, a Health pool (deps SetNet.Stats)
SetNet.Abilities abilities/skills with cooldown, resource cost, range and composable effects (damage / heal / timed buff) over stats/health/position seams — players and mobs alike (deps SetNet.Stats + SetNet.Combat)
SetNet.Equipment custom equip slots (with accept rules); equipped items apply stat modifiers to the wearer's StatSet, moved in/out of Inventory (deps SetNet.Stats + SetNet.Inventory)

Infra (src/infra/)

Package What it adds
SetNet.DependencyInjection construct every discovered component (message handlers, [ProtocolChannel] channel services + [Op] classes, client [Event] handlers, [RpcMethod] RPC handlers) via an IServiceProvider with constructor injection — provider.UseSetNet() (Microsoft.Extensions.DependencyInjection)
SetNet.Services tiny service locator so you don't hand-store every UseXxx() instance: hub.Add(server.UseInventory()) once, then Service.Get<InventoryServer>() anywhere — ambient (MakeCurrent) or per-server (server.Services()). Lets brains/handlers/helpers reach loco/ticks/dialogue/… without constructor plumbing (deps SetNet)
SetNet.Hosting run a server as an IHostedService (Microsoft.Extensions.Hosting)
SetNet.HealthChecks IHealthCheck for liveness + connections (Microsoft.Extensions.Diagnostics.HealthChecks)
SetNet.Inspector HttpListener dashboard (/metrics JSON + HTML)
SetNet.Gateway raw-relay reverse proxy: accept clients → forward to per-client backend
SetNet.Cluster server-to-server broadcast bus (mesh of nodes): Publish/Received/On<T> across nodes
SetNet.Redis Redis backplane: shared ISessionStore/IBanStore/IRoomStore across nodes (deps SetNet.Auth+SetNet.Rooms+SetNet.BanList+StackExchange.Redis)
SetNet.Sharding consistent-hash ShardRing (virtual nodes) + a shard directory every node answers: clients ask any node which node owns a key, then connect there
SetNet.LoadBalancer least-loaded node selection: an entry node keeps a registry of nodes with reported load/capacity and directs clients to the emptiest one
SetNet.Persistence durable-state seam for module stores: IDocumentStore<T> (get/set/enumerate) + ISnapshotStore (byte blobs), with in-memory and JSON-file implementations (deps System.Text.Json)
SetNet.Docs reflects [MessageHandler] / [ProtocolChannel]+[Op]/[Event] / [RpcMethod] into a Markdown protocol report (ProtocolDocs.Generate())

Logging (src/logging/)

Package What it adds
SetNet.Logging.Serilog SerilogLogger : ILogger routing diagnostics into Serilog
SetNet.Logging.NLog NLogLogger : ILogger routing diagnostics into NLog
SetNet.Logging.ZLogger ZLoggerLogger : ILogger routing diagnostics into ZLogger (zero-alloc, via Microsoft.Extensions.Logging)

Engine bindings (src/engine/)

Package What it adds
SetNet.Unity MainThreadDispatcher for Unity's main thread
SetNet.StateSync.Unity Unity components: NetworkObject/Transform/Animator/Rigidbody/Behaviour + NetworkManager (UPM source, not NuGet)
SetNet.GeoData.Unity Editor tool to bake a SetNet.GeoData file from a Unity NavMesh, colliders (flat grid), a multi-surface sweep (multi-storey layered grid), or tiled sectors (+ .geomap manifest); one-click auto-bounds + a Scene-view debug visualizer (GeoDataGizmo) (UPM source, not NuGet)
SetNet.Locomotion.Unity client-side NavAgent component: walks a GameObject along a path (that the client computed from the destination point the server sent) at a Speed you set (your replicated move-speed) (UPM source, not NuGet)
SetNet.Godot Godot 4 (C#) main-thread dispatcher + math conversions (deps SetNet.StateSync + GodotSharp)
SetNet.StateSync.Godot Godot 4 replication components: NetworkObject/Transform/AnimationPlayer/RigidBody/Behaviour + NetworkManager (deps SetNet.StateSync + SetNet.Godot + GodotSharp)

Core extension points already in place (for composition packages)

  • SetNetSerializer.Use/Serialize/Deserialize — pluggable serialization.
  • Auto-discovered typed and byte[] handlers (IServer/ClientMessageHandler<T>) via [MessageHandler].
  • Unified messaging protocol (SetNet.Protocol, in core): client.RequestAsync/PostAsync/On<T> + server [ProtocolChannel] IChannelService + peer.PublishRawAsync — one envelope wire id, per-module Channels, shared correlation + subscription registries. The composition layer most game modules build on.
  • BaseClient/BasePeer.SendAsync<T> and SendRawAsyncpublic.
  • BaseSocket.OnRawFrame (intercept/consume) + SendRawAsync — relay/proxy primitive.
  • BaseServer.InboundAuthorizer + BaseSocket.AllowInbound — per-frame inbound gate.
  • BaseClient.Connected event (after connect+reconnect), BaseServer.PeerDisconnected + BaseServer.PeerConnected events (once per peer).
  • Public BasePeer.CurrentPeerInfo + PeerInfo.Server; PeerInfo.RemoteEndPoint + BasePeer.RemoteEndPoint (used by BanList/DdosGuard/Inspector/Gateway).
  • BaseSocket.InjectFrame(type, data) — feed a reconstructed frame into normal dispatch (used by Fragmentation reassembly; also relays/testing).
  • HandlerActivator.Factory — route handler construction through a container (used by DependencyInjection; default falls back to the parameterless ctor).
  • RoomServer.RoomHooks() — server-side room join/leave events (used by Rooms.HostMigration).
  • Custom transport registrationTransportType.Custom + Configuration.CustomTransport : ITransportProvider, resolved in TransportFactory. Lets an external package supply ITransportConnector/ITransportListener without editing core (used by SetNet.WebSockets / SetNet.InMemory; also the path for future SetNet.WebRTC / SetNet.Quic / SetNet.Steam).

Planned / future ideas

  • SetNet.Logging.MicrosoftExtensions — an ILogger adapter over Microsoft.Extensions.Logging (sibling to the Serilog package).
  • SetNet.WebRTC / SetNet.Quic / SetNet.Steam — additional transports via the same ITransportProvider hook.
  • SetNet.RateLimit per-message-type budgets (PerType = {...}) on top of the current per-peer bucket.