If the job is shared game state, start here before inventing a fourth drawer
and pretending the label makes it furniture.
| Job | Start With | Owns | Use When | Do Not Use It For |
| --- | --- | --- | --- | --- |
| Local typed state | `GameCult.Caching` / CultCache | Document identity, schema compatibility, record keys, indexes, globals, and local persistence | You need a typed cache, file-compatible save data, local reactive reads, or a stable domain document model | Peer discovery, transport security, shard routing, or mesh consensus |
| Procedural geometry state | `GameCult.Geometry` | CultCache-native domain trees, LOD build requests, selected-cut diagnostics, and chunk artifact payloads | Rust, Unity, or remote workers need to share CSG/LOD geometry and graph metadata as typed state | Transport policy, peer discovery, or gameplay authority |
| Network transport and database plumbing | `GameCult.Networking` / CultNet | Native RUDP sessions, LiteNetLib/TCP adapters, an authenticated WebSocket host adapter, schema-v0 wire contracts, shard authority, raw document replication, snapshots, and subscriptions | You need a client/server pipe, login/session flow, schema discovery, reliable UDP, or a low-level distributed CultCache lane | Gameplay-facing mesh ergonomics, Verse policy, mod branches, or simulation consensus composition |
| Distributed realtime gameplay state | `GameCult.Mesh` / CultMesh | Public mesh entrypoints, Verse discovery, peer exchange, shard replication defaults, authority leases, client prediction, and witness consensus | You want the game to treat clients and servers as one reactive database for persistent state, input state, and simulation facts | A tiny local-only tool, a bare transport client, or a storage format contract |
| Daemon-published UI | Eve / CultUI | Typed operator and user-facing surfaces over CultMesh state | A daemon should expose controls, inspection, or workflow UI that can lower into GUI, TUI, web, native, overlay, or agent clients | One-off vendor dashboards, untyped debug panels, or runtime-local UI that cannot travel with the daemon |
-`GameCult.Unity`: CultUI, a Unity runtime UI composition framework with reflective inspector generation, prefab-backed field resolvers, reusable controls, and a demo project packaged for UPM-style consumption
The cache-centric libraries revolve around `DatabaseEntry`. Every entry has a stable `Guid` identifier and can optionally:
- expose a human-readable name through `INamedEntry`
- participate in generic indexes registered at runtime
- be treated as a global singleton entry through `GlobalSettingsAttribute`
Typical entry shape:
```csharp
using GameCult.Caching;
public class ItemData : DatabaseEntry, INamedEntry
{
public string Name = string.Empty;
public int Value;
public string EntryName
{
get => Name;
set => Name = value;
}
}
```
### `CultCache` and Backing Stores
`CultCache` is an in-memory index over `DatabaseEntry` objects. It can operate entirely in memory, or it can be attached to one or more backing stores for persistence and synchronization.
- the cache is the query surface
- backing stores are persistence adapters
- indexes and name maps are maintained inside the cache, not inside the store
### Important: Multiple Backing Stores
When multiple backing stores are added, behavior depends on how they are registered.
then that store becomes the direct persistence target for those types.
If a store is added without domain types:
```csharp
cache.AddBackingStore(primaryStore);
cache.AddBackingStore(mirrorStore);
```
then the first generic store acts as the primary writable store for non-domain-specific entries. Additional generic stores subscribe to the existing stores and mirror their change events.
Implications:
- order matters for generic stores
-`AddAsync` writes to the type-specific store when one exists
- otherwise `AddAsync` writes to the first generic store
- later generic stores do not become co-primaries; they mirror earlier stores
-`PullAllBackingStoresAsync` pulls from every registered store
Recommended patterns:
- use one generic primary store if you want simple persistence
- use domain-specific stores when different entry types belong in different persistence layers
- treat additional generic stores as mirrors or downstream replicas, not independent write targets
## Example: Cache + Networking
```csharp
using GameCult.Caching;
using GameCult.Logging;
using GameCult.Networking;
var cache = new CultCache
{
Logger = new ConsoleLogger()
};
var server = new Server(cache)
{
Logger = new ConsoleLogger()
};
server.Start();
```
## Secrets and Runtime Configuration
`GameCult.Networking` uses two pieces of deployment configuration:
-`GAMECULT_CONNECTION_KEY`
-`GAMECULT_SESSION_SIGNING_SECRET`
Production guidance:
- set both values before starting the server
- treat `GAMECULT_CONNECTION_KEY` as shared client/server protocol configuration
- treat `GAMECULT_SESSION_SIGNING_SECRET` as a server-only secret
- generate high-entropy random values and store the server-side value in your platform's secret store
- do not rely on local-development defaults in production
- partial configuration is rejected at startup
Recommended value format:
- at least 32 random bytes per value
- encode as Base64 or Base64Url if you want a portable text representation
- inject `GAMECULT_SESSION_SIGNING_SECRET` and the server copy of `GAMECULT_CONNECTION_KEY` as environment variables from Docker secrets, Kubernetes secrets, systemd environment files, or your cloud secret manager
- ship the matching `GAMECULT_CONNECTION_KEY` to the client through a build-generated config asset, code-generated constants, or another explicit client configuration mechanism
- scope them per environment so development, staging, and production do not share values