Mawu · Features

The Realm Model & Danu Massive Population

A focused page within the Mawu Features documentation. The full map and every sibling page live in the Features hub.

5sections11 minread1diagram

On this page

V7's whole pitch is one sentence: build the world, don't just play it, and let a thousand people live in it at once. A realm is what a player builds — a single running Mawu world they own and others inhabit: its terrain, its rules, its jobs and economy and laws, composed from a base world and an ordered stack of Ixchel mod layers, pinned to a lock file so every joiner gets the byte-identical world. Danu is what makes that world hold a crowd: a server-meshing control plane that lets many simulation nodes behave as one seamless space, carrying 1000+ concurrent inhabitants past the ceiling GTA Online's 32-player peer-to-peer lobbies cannot reach. This page is the feature tour of both — what a realm is and how it scales — and it deliberately hands two adjacent stories to siblings: the persistent-character, jobs, and economy framework lives in the Moremi roleplay framework, and the precise platform-vs-realm vocabulary lives in the surfaces and trust-boundary glossary. The deep engine treatment — the handoff sequencer, the fencing-token broker, the rehydrate path — is the architecture companion, Danu Server Meshing & Nephthys Persistence. For the full scope this slots into, start at the hub: ../V7_features.md.

What ships, honestly#

The realm-composition and meshing logic is real, deterministic, and guarded by falsifiable CI gates — but it is library-grade simulation, not a deployed distributed cluster. Four honest layers:

  • Real and test-covered. The Danu meshing core (apps/v7/danu-mesh-cluster/src/lib.rs, 22 #[test] cases) implements the atomic two-phase authority handoff, grid interest management, density split/merge, and the time-dilation overload valve as genuine algorithms with named numeric budgets. The realm wire (libs/v7/realm-protocol/src/lib.rs, 30 tests) carries signed envelopes, prediction/reconciliation, snapshot interpolation, and ack-relative delta compression. The Nephthys persistence layer (apps/v7/nephthys-replica-service/src/lib.rs, 15 tests) is an event-sourced store with a single-writer replication broker. Each eval emits a typed report with a strict passed() predicate that fails against a regression.
  • The realm is composed for real on the UE client. AMawuComposedRealmActor::ApplyLockFile (V7/ue/Source/MawuRealm/Private/MawuComposedRealmActor.cpp:27) takes a FMawuRealmLockFile, walks its layers in composition order, and realises every primitive — engine BasicShape static meshes plus procedural UDynamicMesh geometry built by real UE5 Geometry Script ops — into a live actor with a FMawuCompositionReport. This is the "join the exact same composed world" promise in C++, not a stub.
  • The daemons are health-only. The three realm-backbone binaries — Moremi (:47201), Danu (:47202), Nephthys (:47203) — each have a one-line main.rs calling run_service(), which binds a TCP health endpoint emitting the crate's ServiceDescriptor JSON. There is no accept loop ingesting live sim-node traffic. Treat the backbone as a verified library, not a running fleet.
  • One reused persistence substrate is wired today. libs/v7/substrate-bridge consumes the real V6 Egbe Ori event store, projection materializer, and operator-read audit primitives for the identity path; Nephthys's own store is in-memory with a documented Postgres+pgvector target the byte-canonical encoding makes a safe swap.

The realm model#

A realm is a composed world, not a copy of a game#

A realm bundles a base world, an ordered set of Ixchel mod layers (its assets, rules, and logic), a Nàná configuration, a membership policy, a governance charter, and a hosting binding. Its identity, version, and lock file are recorded so any client can join the same composed world — a 1920s-bootlegger economy, a hospital sim where every doctor is a player, a city with no rules. The platform supplies engine, netcode, persistence, safety, and economy; the community supplies the world.

The lock file is the load-bearing artifact, and it is concrete in code. FMawuRealmLockFile (MawuRealmLockTypes.h:84) carries a SchemaVersion, a RealmId, a LockFileHash, and an array of FMawuRealmLayers — each with a LayerId, a ContentHash, a Priority, and its Primitives. GetLayersInCompositionOrder() resolves the deterministic stack, and on join the client calls UMawuRealmLockFileLibrary::LoadLockFileFromPath (MawuRealmLockTypes.h:163) then ApplyLockFile. The actor sorts primitives by id for determinism, loads each one, and for any primitive whose OperationKind is non-None runs a real Geometry Script operation — Voxel solidify, CsgUnion/Subtract/Intersect booleans, Sculpt Perlin displacement, UvProject planar UVs — through BuildProceduralPrimitive (MawuComposedRealmActor.cpp:164), folding triangle, vertex, and watertight stats into the report. The FMawuCompositionReport (MawuRealmLockTypes.h:106) is the proof: it reports bLockValid, PrimitiveCount, RenderableComponentCount, bounds, and bRendered (true only when every declared primitive realised). Two clients applying the same lock-file hash compose the same world. This is "modding without load order" made physical: a stack of composable layers resolved to one deterministic scene, never fragile file-override priority.

The hosting continuum: Solo → Listen → Dedicated → Meshed#

A realm owner picks where it runs, on a continuum: Solo (local, population 1, private build/test), Listen (host client, up to ~16, small co-op), Dedicated (a single authoritative Rust node, up to ~256), and Meshed (a Danu node cluster, 1000+). The promise is promotion without rebuild: the same composed world and lock file run from Solo to Meshed, with persistence migrating into Nephthys the moment the realm leaves Solo.

That promotion path is one of the strongest things actually proven in code. run_realm_promotion_eval (nephthys-replica-service/src/lib.rs:2685) promotes a Solo-authored realm to Dedicated then Meshed, byte-verifying that the composition lock file is identical at every tier and that persistence migrates into Nephthys at the Solo→non-Solo boundary with no save lost. The Listen tier is proven too: run_listen_host_migration_eval (lib.rs:2505) migrates a peer-hosted session to a successor host, using a fencing token to reject the stale host's write while byte-verifying zero character-state loss — so a Listen host quitting does not end the session.

Membership and the identity firewall#

A realm gates entry one of four ways — Open (anyone, platform safety floor applies), Whitelisted (an application/backstory review, the serious-RP norm), Invite (a closed roster), or Federated (two realms agree to a character corridor under Themis-adjudicated terms). Whatever the policy, the realm never sees the player's platform account. V7IdentityFirewall (libs/v7/substrate-bridge/src/lib.rs:325) projects an authenticated principal into an opaque per-realm handle via project (lib.rs:343), gated on the v7:realm:join scope (lib.rs:32). The handle is deterministic, realm-scoped, and is not a platform id — run_identity_leak_eval and run_trust_boundary_eval (lib.rs:582) prove that no platform session token, payout credential, or real-money entitlement is reachable from realm process code or a creator web view. When a realm writes a character memory, it does so through the real V6 Egbe Ori event storeEgbeOriFacade (lib.rs:1248) appends to a PartitionedPostgresOriEventStore, materializes a projection, and reads it back through the audited operator-read path — so the durable character truth rides V6's identity substrate, not a reinvented one.

Persistence: Nephthys, the decoupled truth#

Realm and character state live in Nephthys, modeled on Star Citizen's replication-layer split: the authoritative store of the whole realm's state is separate from the simulation nodes, so a node crash never loses the world. NephthysEventSourcedStateStore (nephthys-replica-service/src/lib.rs:1271) is an append-only event log that checkpoints every third version (NEPHTHYS_CHECKPOINT_INTERVAL = 3); realm and character live as separate aggregates (NephthysAggregateKind, lib.rs:42) with independent projections, so a federated character can travel carrying only its own aggregate. Recovery is snapshot + tail replay (rehydrate_aggregate, lib.rs:1357), and run_nephthys_persistence_api_smoke (lib.rs:1746) writes a full character, restarts onto a replacement node, and proves the post-restart bytes are exactly equal. A replacement node is bit-identical to the one it replaces — that is the whole point, and the precondition for true roleplay and economy.

Danu — meshing for a 1000+ population#

A single authoritative node has a hard cap. Serious persistent worlds need hundreds-to-thousands in one seamless space, so Danu partitions a meshed realm across simulation nodes, each authoritative for a region, with Nephthys holding the durable truth. The control plane (DESCRIPTOR port :47202, danu-mesh-cluster/src/lib.rs:46) implements six invariants, each as a data structure plus a deterministic eval that proves it.

flowchart TB subgraph nodes["Moremi sim nodes (Rust, authoritative)"] W["node:west<br/>writer for cell range"] E["node:east<br/>writer for cell range"] end subgraph danu["Danu control plane (:47202)"] AOI["grid interest mgmt<br/>≤64 working set / ≤4096 B frame"] HO["2-phase handoff<br/>Freeze → Transfer → Ack → Release"] SM["density split/merge<br/>+ time-dilation valve"] end subgraph neph["Nephthys (:47203)"] BRK["replication broker<br/>fencing-token leases"] ES["event-sourced store<br/>snapshot every 3 events"] end Client(["1000+ inhabitants"]) -- "intent" --> W Client -- "intent" --> E W -- "write (lease + token)" --> BRK E -- "read-only view" --> BRK HO -- "freeze / transfer / commit owner" --> BRK BRK --> ES ES -- "rehydrate (snapshot + tail)" --> W AOI -- "bounded delta" --> Client SM --> HO

The bounded working set: no client sees the whole realm#

What makes 1000+ inhabitants tractable on commodity hardware is that no client ever receives the whole realm. run_danu_area_of_interest_eval (lib.rs:2002) populates a 1,000-inhabitant grid (DANU_AOI_EVAL_INHABITANTS = 1_000, a 40×25 cell field) and, for every inhabitant, computes a working set culled three ways — by proximity (radius 2 cells), by line-of-sight, and by channel (Public / Crew / Trade subscriptions must intersect). The gate requires the maximum working set stay ≤ 64 entities (DANU_AOI_MAX_WORKING_SET, lib.rs:22) and the per-frame estimate stay ≤ 4096 bytes (DANU_AOI_FRAME_BUDGET_BYTES, lib.rs:23), that all three culling paths actually removed entities, and that no working set is empty. Because the budget bounds visible density, not population, per-client bandwidth is independent of realm size — the same property the realm-protocol delta layer enforces with its 32-snapshot ack-relative ring (REALM_DELTA_SNAPSHOT_RING_SIZE, realm-protocol/src/lib.rs:58) and a 64–256 kbit/s budget, the wire Danu's interest sets feed.

Single-writer authority and the atomic handoff#

Exactly one node holds write authority over an entity; everyone else reads a Nephthys-sourced view. Crossing a partition boundary therefore means moving authority, and the dangerous window is two writers (or zero) for one entity. DanuMeshCluster::move_entity_across_boundary (lib.rs:1822) runs a four-phase sequence against the handoff ledger: it freezes the entity, records Freeze then Transfer, commits the new owner, records Ack, flips owner_node_id, and finally records Release and unfreezes. The mid-handoff crash is explicit — when the source node is killed between Transfer and Ack, the recovery path toggles alive back and increments a recovered counter so the handoff still completes. The gate run_danu_mesh_handoff_eval (lib.rs:1973) crosses 200 entities a boundary 10,000 times each — two million handoffs — with a node death injected mid-run, and demands zero lost entities, zero duplicate authority, zero owner mismatches, and client_reconnects == 0. Your character crosses from the casino floor to the street and the client never reconnects, never sees a loading screen.

Density-driven split and merge#

Node assignment is dynamic. When population density at a location crosses the split threshold (DANU_DYNAMIC_SPLIT_DENSITY_THRESHOLD = 120), Danu splits the region onto another node; when the crowd disperses below the merge threshold (= 40), regions merge back. run_danu_dynamic_meshing_eval (lib.rs:2121) proves this static-first — it refuses to proceed unless the full handoff eval passed — then drives a crowd to gather and disperse under a smoothness budget (≤ 16 entity remaps per tick, ≤ one 60 Hz frame of cost), requiring the topology return to Static with the original partition count. A split that never merges back fails the gate. The SpatialOS lesson — never straddle tightly-coupled physics across nodes — is enforced separately by run_danu_colocation_eval (lib.rs:2073), which pins both members of 128 coupled pairs (PhysicsJoint, VehicleRider, CombatGrapple) to one anchor node.

The overload valve and graceful degradation#

When a node cannot simulate a hot region in real time, Danu slows the region's clock EVE-style rather than dropping players. danu_overload_clock_percent (lib.rs:2500) is the real formula: at or below capacity the clock runs at 100%; above it, capacity × 100 / load, clamped to a 10% floor (DANU_OVERLOAD_CLOCK_FLOOR_PERCENT). run_danu_overload_eval drives 256 players through a load spike to 18,000 units against a 1,000-unit capacity and requires the clock dilated, never fell below the floor, dropped zero players and zero authority records, and kept per-player lag fair. And run_danu_degradation_eval (lib.rs:2345) is the chaos gate: node failure must rehydrate from Nephthys, capacity exhaustion must queue excess joins rather than reject them, and control-plane loss must fall back to single-node operation — all with zero reconnects, zero lost entities, zero authority drops. The Spot-reclaim path handle_spot_preemption (lib.rs:517) reallocates a preempted server from a checkpoint with no player-visible loss: the literal reason persistent RP realms are safe on cheap, preemptible compute.

The trust seam underneath#

Meshing only matters if a hostile community operator cannot forge the writes Danu routes. The realm wire binds every cross-trust message to a platform-issued RealmSecurityToken (HMAC-SHA256 over the claims, realm-protocol/src/lib.rs:121) and a sequence-numbered signed intent; RealmEventTamperEvalReport::passed (lib.rs:1131) proves only a valid signed client intent mutates authoritative state and the post-hostile state hash is identical to the baseline. The sim node itself, the Moremi realm server (moremi-realm-server, which depends directly on DanuMeshCluster, src/lib.rs:7), treats a Nephthys mutation as a signed receipt: validate_moremi_nephthys_receipt (lib.rs:3417) rejects realm-mismatched, actor-mismatched, rule-mismatched, replayed, or signature-mismatched mutations before they touch state, and the ClientGrantCurrency / ClientGrantItem / ClientTeleport intent variants are exactly the cheats a tampered client cannot self-authorize because the server owns those values. That is the structural anti-cheat foundation under the whole realm model.

Where this connects#