Spatial

Zone State

Mutable opaque per-zone blob (weather/time/siege), broadcast on change, replayed on entry.

Server
services.AddCrossplayZoneState();
Unity package
com.crossplay.zonestate
Depends on
world

Services you call 1

Crossplay implements these. Resolve them from DI and call them from your own systems.

IZoneStateService

One mutable opaque blob per ZONE — weather, time of day, siege phase, anything the game encodes. SERVER game code sets it (no client mutation path); everyone in the zone gets the change, and anyone entering the zone later gets the current blob replayed.

  • bool Set(string zone, byte[] state)

    Replaces the zone's blob and broadcasts it (null/empty clears). False when the blob exceeds MaxStateBytes or the zone name is empty.

  • bool TryGet(string zone, out byte[] state)

    The zone's current blob, if any.

Configuration 1

Every tunable lives in an options object — there are no magic numbers to hunt for.

ZoneStateOptions

ZoneState tuning (defaults here, never inline).

  • int MaxStateBytes { get; set; }

    Largest zone-state blob, in bytes (bigger sets are refused). The blob broadcasts to every zone occupant on change and replays on each zone entry — keep it a compact summary (weather code, time-of-day, siege phase), not a data dump. Default 256.

Wire messages 1

The protocol this piece speaks. Ids are allocated per piece so they can never collide.

3601 ZoneStateChanged

Server → everyone in the zone: the zone's opaque state blob — weather, time of day, siege phase, anything the game encodes. The framework stores, broadcasts on change and replays on zone entry; it never interprets the bytes. Empty = cleared. Server-set only (no client path).

Unity services you inject 1

Crossplay binds these in the client context. Inject and call them from your own MonoBehaviours and presenters.

IZoneStateClient

The ZoneState piece, client side: observe the current zone's opaque state blob. The bytes are the GAME's vocabulary (weather, time of day, siege phase…) — this client never interprets them; the game binds them to its own skies, lighting and UI.

  • event Action<ZoneStateChanged> Changed

    The latest blob per zone — raised on change and on zone entry (the replay).

  • byte[] LatestFor(string zone)

    The most recent blob seen for a zone (empty when none).

UI views you can replace 1

Each ships a working uGUI panel you can drag into a scene. Substitute your own view to keep the logic and change the look — the presenter never knows.

ICrossplayZoneStateView

Narrow contract the presenter drives. UI-only, read-only: the ZoneState wire is server-set (no client mutation path), so there are no user intents to raise.