Nebula
World partition

NebulaChunkedWorld

The whole server and client side of an unbounded chunked world, wired from configuration alone (NebulaConfig.ChunkedWorld plus a NebulaConfig.RuntimeWorld).

generated from the sources
[DefaultExecutionOrder(-500)]
public sealed class NebulaChunkedWorld : MonoBehaviour

The whole server and client side of an unbounded chunked world, wired from configuration alone (NebulaConfig.ChunkedWorld plus a NebulaConfig.RuntimeWorld). NebulaBootstrap adds one of these on every role, and the game writes no world-management code at all: chunks are containers, containers are leased, content arrives through NebulaChunks.

  • every role: the RuntimeGrid from the world definition's cell size, installed as the container-bounds hook and as the spatial-hash bucket size, and NebulaChunks activated.
  • worker: a RuntimeGridAllocator keeping a ring of chunks leased around every pawn it simulates (and around the origin, so a first player always has somewhere to appear), retiring what nobody has wanted for NebulaConfig.ChunkRetireSeconds. The origin follows the centroid of the cells this worker leases.
  • client: the origin follows the content anchor — the local pawn by default, or whatever NebulaClient.SetContentAnchor was given (a strategy camera).
  • gateway / orchestrator: passive. They need the container arithmetic and nothing else.

The allocator's ring is InterestSettings.NearCells plus NebulaConfig.ChunkedWorldServerRingMargin (1 unless set), so a chunk is always leased — and its content built — before interest can put an entity standing on it into a client's set. Raising InterestRadius therefore widens the chunk ring by itself; nothing to keep in step. NearCells alone already holds every chunk interest can reach; the margin is the time to build one (a pawn crossing a chunk edge requests the new ring at that moment), so a margin of 0 is only as safe as InterestSettings.ChunkLoadLeadSeconds says.

Besides its root grid, a scope can hold chunk grids hosted by containers with physics frames of their own (ActivateHostedGrid, docs/container-tree.md D22): a planet's ground carried through a system's space, a station's decks.

Properties

Config

public NebulaConfig Config { get; }

Worker

public NebulaWorker Worker { get; }

Client

public NebulaClient Client { get; }

Grid

public RuntimeGrid Grid { get; }

The grid every role shares. Also reachable as NebulaChunks.Grid.

Allocator

public RuntimeGridAllocator Allocator { get; }

The worker's chunk allocator; null on other roles.

Ring

public int Ring { get; }

Chebyshev ring of chunks the worker keeps leased around every pawn.

ScopedAllocators

public IReadOnlyDictionary<string, RuntimeGridAllocator> ScopedAllocators { get; }

The scoped grids' allocators on a worker, by scope key. Empty on every other role.

HostedGeometry

public static System.Func<string, ChunkGridDefinition, IChunkGridGeometry> HostedGeometry { get; set; }

The shape of hosted grids (IChunkGridGeometry), asked with each grid's key and definition when this process builds the grid. Null, or a null answer, gives the definition's ChunkLattice. Set it at boot on every process (workers, gateways that build grids, clients) for a grid whose cells are not a box lattice, such as a cube-sphere's faces.

Methods

ActivateGrid

public static void ActivateGrid(IControlPlane controlPlane, string scopeKey, ChunkGridDefinition definition, string requester = "", string preferredWorkerId = "");

Bring a second (third, hundredth) chunk grid into being, namespaced by scopeKey: an instanced open area, a second map, a per-party copy of a procedural region. One control-plane write (IControlPlane.ActivateScope) with ScopeKind.Grid; the definition travels in the scope row's payload, so every role builds the same grid from the row alone and none of them has to be told separately. Idempotent by key, exactly like every other activation: two callers naming the same key with the same definition get one world (docs/scope-activation.md §3).

Only the scope's ChunkGridDefinition.Anchor chunk is created — a grid is unbounded, so activation must not enumerate it. Every other chunk is leased on demand by the allocator of whichever worker a pawn of that scope is simulated on.

EnsureLocalGrid

public RuntimeGrid EnsureLocalGrid(string scopeKey, ChunkGridDefinition definition);

Make sure this process has a local grid for a scope whose row the control plane shows, and — on a worker — an allocator for it. Called for a scope the first time one of its containers turns up here, which is the one rule that works on every role: a worker gets the anchor dealt to it or an entity transferred into it, a client is told about a chunk of the scope it joined, a gateway mirrors the lease. A process that never touches a scope never pays for it.

ActivateHostedGrid

public static void ActivateHostedGrid(IControlPlane controlPlane, string scopeKey, string gridKey, string hostContainerId, ChunkGridDefinition definition);
public static void ActivateHostedGrid(IControlPlane controlPlane, Container host, string gridKey, ChunkGridDefinition definition);

Host a chunk grid in a container of a scope (docs/container-tree.md D22): chunks of definition's size, leased as children of hostContainerId (a container with a physics frame of its own, usually a carrier's: a planet, a station), laid out in the host's own coordinates. A planar grid is one layer of columns centred on the host's y = 0, and its host's frame never shifts its origin vertically.

The grid is registered under gridKey, its own key, which must not be any scope's: every role finds it with NebulaChunks.GridFor, NebulaChunks.EnsureAt and NebulaChunks.AllocatorFor by that key, and its chunk ids are ChunkKeys.RuntimeId of that key and the coordinate. Its chunks belong to scopeKey: what stands in them is in that scope, and the scope's lifecycle retires them with the rest of it.

One control-plane write, a mesh setting row (IControlPlane.SetSetting), which every worker applies: each builds the grid and an allocator that leases chunks around the pawns it simulates on or near the host (ChunkGridDefinition.Reach), ahead of them by ChunkGridDefinition.LeadSeconds. Clients and gateways learn the grid from the chunks' own rows. Calling it again with the same arguments changes nothing; a carrier that came back under a new container id (a restart) is hosted again by calling it with the new id, and chunk rows still naming the old one are replaced. Nothing is leased while the host is not in a worker's process. The anchor is not pinned: pin chunks that must stay with RuntimeGridAllocator.AddPin.

DeactivateHostedGrid

public static void DeactivateHostedGrid(IControlPlane controlPlane, string gridKey);

Stop hosting a grid: every worker forgets it and leases nothing more for it. Chunk rows already leased are not removed; they retire as usual once nobody wants them, or with their scope.

EnsureHostedGrid

public RuntimeGrid EnsureHostedGrid(string scopeKey, string gridKey, string hostContainerId, ChunkGridDefinition definition);

Make sure this process has a hosted grid (ActivateHostedGrid) and, on a worker, its allocator. A worker calls it for every hosted-grid row the control plane shows; a grid already here with another host or another definition is replaced. Returns the grid.

On this page