2026-06-22 01:11:56 +01:00
|
|
|
|
# Aetheria Current Codebase Model
|
|
|
|
|
|
|
2026-07-20 01:52:05 +01:00
|
|
|
|
Date: 2026-07-20
|
2026-06-22 01:11:56 +01:00
|
|
|
|
|
|
|
|
|
|
This is a modeling pass over the live codebase as it exists now. It is not the
|
|
|
|
|
|
ideal architecture; it is the current control-flow map, with migration pressure
|
|
|
|
|
|
points called out where Unity still acts like more than a thin renderer/input
|
|
|
|
|
|
lowerer.
|
|
|
|
|
|
|
|
|
|
|
|
## Topology
|
|
|
|
|
|
|
|
|
|
|
|
- `Aetheria.State` owns the CultCache/CultNet typed state node, document
|
|
|
|
|
|
registry, Eve surface state, provider advertisement projection, command
|
|
|
|
|
|
acceptance, and durable Aetheria state documents.
|
|
|
|
|
|
- `Aetheria.State.Daemon` is the local Verse member. It opens an
|
|
|
|
|
|
`AetheriaStateNode`, starts the CultMesh server, publishes discovery, accepts
|
|
|
|
|
|
typed Eve commands, reads typed daemon commands, ticks the authoritative run
|
|
|
|
|
|
document, and republishes daemon witnesses.
|
|
|
|
|
|
- `Packages/org.gamecult.aetheria.state/Runtime` is the embedded Unity-facing
|
|
|
|
|
|
runtime package. It contains the shared daemon frame documents, typed command
|
|
|
|
|
|
clients, render query helpers, stat recipe surfaces, replica/discovery code,
|
|
|
|
|
|
and the SoA publication schema that Unity can map.
|
|
|
|
|
|
- `Assets/Scripts` is the Unity client. It still contains the gameplay facade
|
|
|
|
|
|
graph, behavior simulation classes, zone renderer, UI shells, and Ymir query
|
|
|
|
|
|
bridge. During the migration it is partly renderer/input client and partly
|
|
|
|
|
|
legacy simulation host.
|
|
|
|
|
|
- `Aetheria.State.Verify` is the migration fence. It asserts that deleted
|
|
|
|
|
|
authority paths stay dead: stringly public command APIs, queues as public API,
|
|
|
|
|
|
Unity physics authority, direct Unity-side zone rendering ownership, old
|
|
|
|
|
|
serializer/database paths, and several daemon publication invariants.
|
|
|
|
|
|
|
|
|
|
|
|
## Boot And Daemon Tick
|
|
|
|
|
|
|
|
|
|
|
|
The daemon entry point is `Aetheria.State.Daemon/Program.cs`.
|
|
|
|
|
|
|
|
|
|
|
|
Current daemon control flow:
|
|
|
|
|
|
|
|
|
|
|
|
1. Parse daemon options: state path, daemon id, session id, Verse id, CultMesh
|
|
|
|
|
|
address, tick interval, fixed delta.
|
2026-07-20 01:52:05 +01:00
|
|
|
|
2. Open `AetheriaStateNode` with `startServer: true` and the daemon boot
|
|
|
|
|
|
hydration profile. The indexed CultCache manifest selects the control-plane
|
|
|
|
|
|
schemas and exact singleton records required to start; authored name files,
|
|
|
|
|
|
the compiled name corpus, asset bodies, and unrelated history remain cold.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
3. Start `AetheriaVerseDiscoveryHost`.
|
|
|
|
|
|
4. Ensure world, Verse host settings, runtime session, compatibility surfaces,
|
|
|
|
|
|
and first daemon tick.
|
|
|
|
|
|
5. On each interval:
|
|
|
|
|
|
- accept observed Eve commands through `AetheriaEveCommandBridge`;
|
|
|
|
|
|
- read the current daemon frame from the state path;
|
|
|
|
|
|
- collect typed loadout templates from the node cache;
|
|
|
|
|
|
- collect observed daemon command documents from the state graph;
|
|
|
|
|
|
- call `AetheriaRuntimeDaemonTickRunner.Tick`;
|
2026-07-19 00:36:41 +01:00
|
|
|
|
- publish the resulting frame, provider advertisement, health, command
|
|
|
|
|
|
boundary, assets, input capability, pilot/map control surfaces, SoA body
|
|
|
|
|
|
and entity view, then the remaining topology surfaces back into the typed
|
|
|
|
|
|
state node;
|
|
|
|
|
|
- flush the public state only after the private Ymir restart material and
|
|
|
|
|
|
the prepared public documents have both been written.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
|
2026-07-19 00:36:41 +01:00
|
|
|
|
`AetheriaRuntimeDaemonTickRunner.Tick` is the authoritative simulation tick
|
|
|
|
|
|
boundary. It filters already-accounted commands, executes new daemon commands
|
|
|
|
|
|
through `AetheriaRuntimeDaemonOperations.Execute`, stamps zone simulation time,
|
|
|
|
|
|
and prepares the frame and publication facts. `Aetheria.State.Daemon/Program.cs`
|
|
|
|
|
|
owns persistence and ordered publication of those prepared facts; the tick
|
|
|
|
|
|
runner does not independently commit client-visible state.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
|
|
|
|
|
|
Important nuance: the current tick applies command effects to a typed run
|
|
|
|
|
|
checkpoint. It is authoritative for many menu, inventory, targeting, movement
|
|
|
|
|
|
intent, docking, loot, trade, loadout, and action-bar operations, but it is not
|
|
|
|
|
|
yet a complete standalone simulation engine for every behavior that still lives
|
|
|
|
|
|
under Unity `Assets/Scripts/ServerShared/Behaviors`.
|
|
|
|
|
|
|
2026-07-20 01:52:05 +01:00
|
|
|
|
### Daemon boot working set
|
|
|
|
|
|
|
|
|
|
|
|
- **Owner:** `AetheriaStateNode` owns the daemon boot record selection;
|
|
|
|
|
|
`DirectoryMessagePackBackingStore` owns key-to-page discovery and durable
|
|
|
|
|
|
retention. A service registry contains only Aetheria's explicitly declared
|
|
|
|
|
|
document types.
|
|
|
|
|
|
- **Inputs:** the indexed manifest, exact singleton boot keys, and the schema
|
2026-07-20 03:00:28 +01:00
|
|
|
|
identities for live commands, receipts, and loadout definitions. The latest
|
|
|
|
|
|
committed daemon frame supplies restored gameplay truth; source run, zone,
|
|
|
|
|
|
and entity records remain cold.
|
2026-07-20 01:52:05 +01:00
|
|
|
|
- **Outputs:** a compact live CultCache working set. The runtime catalog core
|
|
|
|
|
|
contains items, corporations, trade settings, and name-file summaries; the
|
|
|
|
|
|
full name corpus is a separate typed cold record loaded explicitly only when
|
|
|
|
|
|
generation needs it.
|
|
|
|
|
|
- **Derived state:** the catalog Eve surface and ordinary daemon ticks use the
|
2026-07-20 03:00:28 +01:00
|
|
|
|
compact core. Authored name files and source run/zone/entity documents remain
|
|
|
|
|
|
migration, generation, and missing-frame recovery inputs, not ordinary boot
|
2026-07-20 01:52:05 +01:00
|
|
|
|
dependencies.
|
|
|
|
|
|
- **Forbidden writers:** daemon boot must not rescan record pages, reread legacy
|
|
|
|
|
|
name files, or let global assembly discovery expand its registry. A filtered
|
|
|
|
|
|
flush must not erase cold records.
|
|
|
|
|
|
- **Shared paths:** first import writes the indexed representation; daemon boot
|
2026-07-20 03:00:28 +01:00
|
|
|
|
selects its working set from that index; new-run generation and missing-frame
|
|
|
|
|
|
recovery use CultCache's selective pull primitive to hydrate exact bootstrap
|
|
|
|
|
|
records through the same open store.
|
2026-07-20 01:52:05 +01:00
|
|
|
|
- **Cut line:** the monolithic runtime catalog no longer embeds twelve megabytes
|
|
|
|
|
|
of names, and menu bootstrap no longer rescans loadout pages from disk.
|
|
|
|
|
|
- **Verification layer:** backing-store tests hold an unrelated cold page under
|
|
|
|
|
|
an exclusive lock while selectively hydrating another record. Startup phase
|
|
|
|
|
|
traces report state open, catalog, Ymir restore, and client publication costs.
|
|
|
|
|
|
|
2026-07-20 02:31:55 +01:00
|
|
|
|
The compact runtime catalog is the daemon's catalog read model. Individual item
|
|
|
|
|
|
definition pages remain import/editor state and are not a second simulation
|
|
|
|
|
|
catalog. Daemon boot hydrates only the four item records required to validate or
|
|
|
|
|
|
regenerate the native dockyard hull and berth. On the current artifact this cut
|
|
|
|
|
|
reduced the selected state pages from 174 to 52 and cache-open wall time from
|
|
|
|
|
|
about 471 ms to 358 ms. The remaining page cost is being attributed by schema;
|
|
|
|
|
|
the lower count alone did not earn an order-of-magnitude claim.
|
|
|
|
|
|
|
2026-07-20 02:38:48 +01:00
|
|
|
|
The .NET state assembly directly consumes CultCache's document metadata source
|
|
|
|
|
|
generator. Project-reference analyzers are not transitive, so relying on the
|
|
|
|
|
|
MessagePack library's analyzer dependency left Aetheria on runtime typed
|
|
|
|
|
|
formatter dispatch. Generated payload codecs are used only for dense-slot,
|
|
|
|
|
|
constructible document shapes; immutable or sparse-slot contracts retain the
|
|
|
|
|
|
canonical MessagePack fallback. This reduced the profiled 52-page hydration
|
|
|
|
|
|
from about 295 ms to 223 ms and cache open from about 353 ms to 296 ms. The
|
|
|
|
|
|
1.12 MB daemon frame and 574 KB runtime catalog remain the largest hot records.
|
|
|
|
|
|
|
2026-07-20 03:00:28 +01:00
|
|
|
|
The daemon frame is also the sole restored-run owner. `AetheriaRunState`,
|
|
|
|
|
|
`AetheriaZoneState`, and `AetheriaEntitySnapshot` are bootstrap/import records;
|
|
|
|
|
|
they are not tick-time mirrors and cannot override a playable committed frame.
|
|
|
|
|
|
Removing their schema-wide boot hydration reduced the profiled working set from
|
|
|
|
|
|
52 to 38 pages and one measured state-node open from 485 ms to 385 ms. If no
|
|
|
|
|
|
playable frame exists, checkpoint reconstruction explicitly pulls the active
|
|
|
|
|
|
run, then its referenced zones and entities by exact key. The state smoke proves
|
|
|
|
|
|
both that these records remain cold on an ordinary daemon boot and that the
|
|
|
|
|
|
durable fallback graph can still be recovered.
|
|
|
|
|
|
|
2026-07-20 01:58:26 +01:00
|
|
|
|
Ymir reconstruction remains full replay within a session generation, but it is
|
|
|
|
|
|
now bounded by an explicit quiescent generation rollover. When a private world
|
|
|
|
|
|
or payload journal reaches 64 commands, `AetheriaYmirWorldPhysics` asks Ymir to
|
|
|
|
|
|
create a replacement baseline before private capture. Ymir refuses while a
|
|
|
|
|
|
contact episode is active or a mutation has not reached Step; Aetheria keeps
|
|
|
|
|
|
the old replay path in that case and never infers contact safety itself. A
|
|
|
|
|
|
successful replacement is captured before the matching public frame commits,
|
|
|
|
|
|
and the prior session is disposed only after the in-memory owner swaps.
|
|
|
|
|
|
|
|
|
|
|
|
The migration witness paid 733 ms once to restore the historical generation;
|
|
|
|
|
|
the following restart restored the compact generation in 74 ms, including
|
|
|
|
|
|
private-cache open, selected journal hydration, and native world creation.
|
|
|
|
|
|
Historical journal pages remain durable and cold. Retention/garbage collection
|
|
|
|
|
|
of obsolete generations is separate from restart authority and must not be
|
|
|
|
|
|
smuggled into filtered hydration.
|
2026-07-20 01:52:05 +01:00
|
|
|
|
|
2026-07-20 02:24:29 +01:00
|
|
|
|
### Clean restart persistence
|
|
|
|
|
|
|
|
|
|
|
|
- **Owner:** the durable world document owns its creation and last world-state
|
|
|
|
|
|
mutation timestamps. Daemon process liveness belongs to runtime/session
|
|
|
|
|
|
documents, not the world record.
|
|
|
|
|
|
- **Inputs:** the selectively hydrated working set plus the backing store's
|
|
|
|
|
|
durable key index, including records deliberately left cold.
|
|
|
|
|
|
- **Outputs:** schema defaults are created only for genuinely absent global
|
|
|
|
|
|
records. An existing world is read without being rewritten merely because a
|
|
|
|
|
|
daemon process started.
|
|
|
|
|
|
- **Derived state:** an unhydrated durable global is cold, not missing. The
|
|
|
|
|
|
backing store exposes that fact without loading its payload.
|
|
|
|
|
|
- **Forbidden writers:** constructor defaults cannot preempt durable globals,
|
|
|
|
|
|
and daemon startup cannot mutate `AetheriaWorldState.UpdatedAtUtc` as a
|
|
|
|
|
|
heartbeat.
|
|
|
|
|
|
- **Cut line:** CultCache hydrates before materializing missing global defaults;
|
|
|
|
|
|
clean indexed directory flushes perform no manifest transaction.
|
|
|
|
|
|
- **Verification layer:** CultCache tests exclude a persisted global from the
|
|
|
|
|
|
initial hydration set, prove the cache remains clean, then hydrate it on
|
|
|
|
|
|
demand and recover the durable value. On the Aetheria restart artifact the
|
|
|
|
|
|
initial flush fell from 115–140 ms to 3.0–3.2 ms.
|
|
|
|
|
|
|
2026-07-20 02:44:28 +01:00
|
|
|
|
The direct client QUIC listener uses a stable daemon-service certificate stored
|
|
|
|
|
|
beside the state file by default; `--client-cultmesh-certificate-path` selects a
|
|
|
|
|
|
provisioned location. The advertised-host hash is part of the default filename,
|
|
|
|
|
|
and the daemon replaces certificates that are unreadable, lack a private key,
|
|
|
|
|
|
target another host, or are within one day of expiry. This transport identity
|
|
|
|
|
|
does not own Eve provider or body-producer identity. On the restart witness,
|
|
|
|
|
|
certificate setup fell from 153 ms of RSA generation to 27 ms of PFX loading,
|
|
|
|
|
|
and total client-host startup fell from about 319 ms to 183 ms. The first boot
|
|
|
|
|
|
still pays certificate creation once.
|
|
|
|
|
|
|
2026-07-20 03:06:30 +01:00
|
|
|
|
### Provider-owned CDN bodies
|
|
|
|
|
|
|
|
|
|
|
|
- **Owner:** the Aetheria bundle artifact set owns the immutable packed chunks
|
|
|
|
|
|
and manifests for the lifetime of the daemon. The TCP content server owns
|
|
|
|
|
|
framing and byte delivery, not storage.
|
|
|
|
|
|
- **Inputs:** provider-authored bundle files are packed once into content-addressed
|
|
|
|
|
|
manifests and chunks. The control plane indexes manifests by exact record key;
|
|
|
|
|
|
the content plane resolves chunks by normalized SHA-256 hash.
|
|
|
|
|
|
- **Outputs:** requested manifests remain typed CultNet snapshot records, while
|
|
|
|
|
|
chunk payloads travel on the dedicated TCP byte stream outside snapshot
|
|
|
|
|
|
messages.
|
|
|
|
|
|
- **Derived state:** raw manifest snapshot records are serialized only when a
|
|
|
|
|
|
client requests that manifest. No second CultCache mirrors the packed chunk
|
|
|
|
|
|
set.
|
|
|
|
|
|
- **Forbidden writers:** client-host startup must not republish provider-owned
|
|
|
|
|
|
chunks into an in-memory cache merely to satisfy a transport constructor, and
|
|
|
|
|
|
asset bodies must not fall back into batched state snapshots.
|
|
|
|
|
|
- **Cut line:** `CultMeshTcpContentServer` accepts a provider-owned chunk resolver;
|
|
|
|
|
|
its CultCache constructor is now only a convenience adapter for providers that
|
|
|
|
|
|
genuinely keep content in CultCache.
|
|
|
|
|
|
- **Verification layer:** CultMesh content-session and transport-modularity tests
|
|
|
|
|
|
stream a 700 KB provider-owned body directly and retain warm-cache reuse. On
|
|
|
|
|
|
the Aetheria artifact, eager CDN setup fell from about 132 ms to 1.9 ms. The
|
|
|
|
|
|
13 MB cold released-client transfer still requires a fresh live witness before
|
|
|
|
|
|
it can be claimed healthy.
|
|
|
|
|
|
|
2026-07-20 02:07:48 +01:00
|
|
|
|
### Restored-frame client readiness
|
|
|
|
|
|
|
|
|
|
|
|
- **Owner:** the latest hard-flushed daemon frame owns restart world truth. Its
|
|
|
|
|
|
frame-versioned Eve input, pilot topology, reactive fragment, and map surface
|
|
|
|
|
|
are durable projections of that same boundary.
|
|
|
|
|
|
- **Inputs:** exact persisted Eve bootstrap record keys plus the latest frame;
|
|
|
|
|
|
the daemon boot filter hydrates those records without loading unrelated menu
|
|
|
|
|
|
surfaces or history.
|
|
|
|
|
|
- **Outputs:** on an ordinary restored daemon run, CultMesh can advertise the
|
|
|
|
|
|
committed Eve surfaces and publish a fresh hot SoA body before frame N+1 is
|
|
|
|
|
|
simulated. New stores and explicit `--once` runs retain the initialization
|
|
|
|
|
|
tick path.
|
|
|
|
|
|
- **Derived state:** provider advertisement and asset catalog are stable
|
|
|
|
|
|
bootstrap projections. Input and Eve surfaces qualify for the fast path only
|
|
|
|
|
|
when every record version exactly equals the durable frame id; missing or
|
|
|
|
|
|
stale records force a normal rebuild.
|
|
|
|
|
|
- **Forbidden writers:** startup must not advance simulation merely to make an
|
|
|
|
|
|
already committed frame presentable. It also must not pair a current frame
|
|
|
|
|
|
with stale client projections or let existence alone prove consistency.
|
|
|
|
|
|
- **Cut line:** restored readiness no longer calls the simulation tick,
|
|
|
|
|
|
`BuildPublications`, or the surface lowerers. Ordinary ticking resumes after
|
|
|
|
|
|
readiness and owns frame N+1.
|
|
|
|
|
|
- **Verification layer:** the restored artifact reached client bootstrap in
|
|
|
|
|
|
under one millisecond and playable readiness in 1.41–1.55 seconds, down from
|
|
|
|
|
|
2.19 seconds after Ymir compaction alone. The explicit `--once` witness still
|
|
|
|
|
|
executed and committed one new frame.
|
|
|
|
|
|
|
2026-07-19 00:36:41 +01:00
|
|
|
|
## Materialized Import And Publication Ownership
|
|
|
|
|
|
|
|
|
|
|
|
### Catalog import
|
|
|
|
|
|
|
|
|
|
|
|
- **Owner:** the full `Aetheria.State.Import` materialization pass owns creation
|
|
|
|
|
|
of the daemon-readable catalog store. `AetheriaStateNode` owns the actual
|
|
|
|
|
|
directory-backed CultCache writes.
|
|
|
|
|
|
- **Inputs:** quarantined legacy catalog/name files and the bounded supplemental
|
|
|
|
|
|
rows selected by the importer.
|
|
|
|
|
|
- **Outputs:** typed catalog, quarantine, migration-ledger, and trade-policy
|
|
|
|
|
|
records under `<state-path>.records`, plus catalog projections read from that
|
|
|
|
|
|
same store.
|
|
|
|
|
|
- **Derived state:** `RuntimeCatalog` and `CatalogSurface` are projections of
|
|
|
|
|
|
the typed records. Legacy MessagePack files are provenance and migration
|
|
|
|
|
|
inputs only; they are not runtime catalog owners.
|
|
|
|
|
|
- **Forbidden writers:** a temporary single-file CultCache import must not
|
|
|
|
|
|
create catalog truth which is expected to migrate implicitly when the daemon
|
|
|
|
|
|
opens the directory store. The full importer opens with
|
|
|
|
|
|
`useDirectoryStore: true` from its first write.
|
|
|
|
|
|
- **Shared path:** importer writes, in-process catalog validation, reopen
|
|
|
|
|
|
validation, and daemon boot all read the directory-backed state representation.
|
|
|
|
|
|
- **Cut line:** `ResetMaterializedStateOutput` deletes the prior state file,
|
|
|
|
|
|
`.records` directory, and CultMesh materialization before a full import. The
|
|
|
|
|
|
old single-file-first import path is dead rather than retained as a migration
|
|
|
|
|
|
authority.
|
|
|
|
|
|
- **Verification layer:** after flushing, the importer checks the projected
|
|
|
|
|
|
corporation count in-process, reopens a new directory-backed node, and checks
|
|
|
|
|
|
that the same corporation count remains visible. Daemon boot then rejects a
|
|
|
|
|
|
catalog whose required corporation keys are absent.
|
|
|
|
|
|
|
|
|
|
|
|
### Client publication ordering
|
|
|
|
|
|
|
|
|
|
|
|
- **Owner:** `PublishDaemonApiDocumentsAsync` owns client-visible ordering for a
|
|
|
|
|
|
prepared daemon result. The simulation tick owns values, not stream priority.
|
|
|
|
|
|
- **Inputs:** the prepared frame, topology facts, command boundary, health,
|
|
|
|
|
|
asset manifest, session state, runtime catalog, and optional SoA frame/view.
|
|
|
|
|
|
- **Outputs:** frame/render facts first; then provider/health/command/assets and
|
|
|
|
|
|
pilot input capability; then the pilot and sector-map Eve surfaces; then the
|
|
|
|
|
|
daemon SoA view, CultMesh body publication, and Eve entity view; finally the
|
|
|
|
|
|
remaining topology surfaces when topology publication is requested.
|
2026-07-19 11:17:13 +01:00
|
|
|
|
- **Reactive combat state:** the retained pilot topology advertises an embedded
|
|
|
|
|
|
reactive-surface slot. `combat.presentation` exists only in that
|
|
|
|
|
|
frame-versioned fragment alongside feedback and shot receipts; the topology
|
|
|
|
|
|
cannot retain an older selection, visibility, lock, or target-meter value.
|
|
|
|
|
|
Current combat variables are republished at the fragment version; feedback
|
|
|
|
|
|
events and shot receipts include only facts newer than the previously
|
|
|
|
|
|
published fragment. Their retained daemon arrays remain persistence/history,
|
|
|
|
|
|
not a growing payload retransmitted to every client.
|
2026-07-19 00:36:41 +01:00
|
|
|
|
- **Derived state:** pilot/map surfaces and input capability are projections of
|
|
|
|
|
|
the prepared authoritative frame and catalog. SoA documents are bulk render
|
|
|
|
|
|
projections; they do not own command acceptance, beam feedback, or gameplay
|
|
|
|
|
|
state.
|
|
|
|
|
|
- **Forbidden writers:** `AetheriaRuntimeDaemonSoaFramePublisher` may produce
|
|
|
|
|
|
body/view documents but may not choose their position relative to control
|
|
|
|
|
|
facts. No client or renderer may repair delayed control state from a newer
|
|
|
|
|
|
entity slab.
|
|
|
|
|
|
- **Shared path:** initial publication and ordinary prepared-frame publication
|
2026-07-19 11:17:13 +01:00
|
|
|
|
both call `PublishDaemonApiDocumentsAsync`. The live loop publishes hot SoA
|
|
|
|
|
|
bodies every simulation tick and periodic control/reactive documents on the
|
|
|
|
|
|
prepared-publication cadence, so those planes are not one atomic generation.
|
|
|
|
|
|
Consumers must use each document's version; a static topology value may not
|
|
|
|
|
|
impersonate newer reactive state.
|
2026-07-19 00:36:41 +01:00
|
|
|
|
- **Cut line:** bulk SoA publication no longer precedes the pilot/map control
|
|
|
|
|
|
surfaces on the ordered state stream.
|
|
|
|
|
|
- **Verification layer:** daemon tests should assert record order at the
|
|
|
|
|
|
publication boundary; the released generic EveUnity warm witness verifies
|
|
|
|
|
|
the visible consequence by receiving responsive command/beam feedback while
|
|
|
|
|
|
the entity body continues to stream. Transport subscriptions may separate
|
|
|
|
|
|
control and entity traffic, but that does not move publication authority out
|
|
|
|
|
|
of the daemon.
|
|
|
|
|
|
|
2026-06-22 01:11:56 +01:00
|
|
|
|
## Command Flow
|
|
|
|
|
|
|
|
|
|
|
|
Unity public gameplay calls mostly route through typed operation wrappers now:
|
|
|
|
|
|
|
|
|
|
|
|
- `AetheriaDaemonObserver` polls observed daemon state and owns
|
|
|
|
|
|
`AetheriaDaemonOperations`.
|
|
|
|
|
|
- `AetheriaDaemonOperations` exposes typed methods such as `SetTarget`,
|
|
|
|
|
|
`SetMoveVector`, `TransferCargoItem`, `TradePurchase`, `RestoreLoadout`,
|
|
|
|
|
|
`ToggleHullConductivity`, and `SetBehaviorActive`.
|
|
|
|
|
|
- `AetheriaRuntimeDaemonOperationClient` builds
|
|
|
|
|
|
`AetheriaRuntimeDaemonCommandDocument` values and submits them through
|
|
|
|
|
|
`AetheriaRuntimeCommandSubmitter.TrySubmitDaemonCommand`.
|
|
|
|
|
|
- The daemon reads those typed command documents and applies them in
|
|
|
|
|
|
`AetheriaRuntimeDaemonOperations`.
|
|
|
|
|
|
|
|
|
|
|
|
This is much healthier than the earlier `Apply(command, payload)` shape. The
|
|
|
|
|
|
remaining compromise is that the command document is one broad record with many
|
|
|
|
|
|
optional fields, selected by `AetheriaRuntimeDaemonCommandKinds`. That is typed
|
|
|
|
|
|
at the document boundary, but not as strong as distinct command body types per
|
|
|
|
|
|
operation. The verifier now prevents public Unity-facing queue/string APIs from
|
|
|
|
|
|
returning, but the command shape is still a union-ish document rather than
|
|
|
|
|
|
fully discriminated typed bodies.
|
|
|
|
|
|
|
|
|
|
|
|
Eve commands are a parallel typed edge for operator/runtime UI surfaces. The
|
|
|
|
|
|
daemon accepts observed Eve commands, applies known surface commands, and
|
|
|
|
|
|
publishes acceptance status. Daemon-published game/editor surfaces should keep
|
|
|
|
|
|
moving toward command templates that point at typed daemon command documents or
|
|
|
|
|
|
typed state refs, not generic payload maps.
|
|
|
|
|
|
|
|
|
|
|
|
## Observation And Render Flow
|
|
|
|
|
|
|
|
|
|
|
|
Unity observes daemon state through `AetheriaDaemonObserver`:
|
|
|
|
|
|
|
|
|
|
|
|
1. Poll `AetheriaRuntimeStateReader.TryReadObservedDaemonState`.
|
|
|
|
|
|
2. Feed the result through `AetheriaRuntimeDaemonObservationCursor`.
|
|
|
|
|
|
3. If the SoA view changed, map daemon memory through
|
|
|
|
|
|
`AetheriaDaemonSoaMemoryMap`.
|
|
|
|
|
|
4. Lower the mapped columns to `AetheriaDaemonRenderNativeView`, which exposes
|
|
|
|
|
|
`NativeArray<T>` columns for Burst/Jobs-friendly rendering.
|
|
|
|
|
|
|
|
|
|
|
|
The daemon SoA hot slab is written by
|
|
|
|
|
|
`AetheriaRuntimeDaemonSoaFramePublisher.PublishCurrentZoneEntities`. It
|
|
|
|
|
|
currently publishes entity index, position, rotation, velocity, physics body
|
|
|
|
|
|
radius/mass/inverse mass, render scale, visibility, LOD, and render group. This
|
|
|
|
|
|
is the right direction for a thin Unity client: daemon state appears as a native
|
|
|
|
|
|
view instead of a serialized object graph.
|
|
|
|
|
|
|
2026-07-19 09:47:22 +01:00
|
|
|
|
The publisher's `LayoutVersion` owns byte interpretation. Column offsets,
|
|
|
|
|
|
strides, and the mapped body extent are therefore derived from the fixed SoA
|
|
|
|
|
|
capacity, not the current active row count. Active element counts, identities,
|
|
|
|
|
|
and render groups remain reactive metadata. A mapped generation may advance
|
|
|
|
|
|
before that metadata notification without changing what any existing offset
|
|
|
|
|
|
means: removed rows are cleared, and newly added rows remain outside the old
|
|
|
|
|
|
element count until the matching metadata arrives. Neither EveUnity nor the
|
|
|
|
|
|
transport may repair or reinterpret a mismatched generation.
|
|
|
|
|
|
|
2026-06-22 01:11:56 +01:00
|
|
|
|
Current limitation: physics body radius, mass, inverse mass, render scale, LOD,
|
|
|
|
|
|
and render group are still generic defaults in the publisher. Entity identity
|
|
|
|
|
|
and position are real; body semantics are not yet rich enough to replace all
|
|
|
|
|
|
renderer/gameplay guesses.
|
|
|
|
|
|
|
|
|
|
|
|
`ActionGameManager.ApplyLatestAuthoritativeDaemonFrame` is the main Unity frame
|
|
|
|
|
|
consumer. It reads the newest authoritative daemon frame, restores or updates
|
|
|
|
|
|
the Unity observed facade graph, calls `ZoneRenderer.ApplyDaemonFrame`, and
|
|
|
|
|
|
loads the daemon zone view when the zone changes.
|
|
|
|
|
|
|
|
|
|
|
|
`ZoneRenderer` is currently a projection cache. It lowers daemon zone snapshots
|
|
|
|
|
|
into Unity GameObjects for bodies, belts, wormholes, entities, compass markers,
|
|
|
|
|
|
loot visuals, and gravity presentation. Per frame, it asks
|
|
|
|
|
|
`AetheriaRuntimeDaemonRenderQueries` for body poses, asteroid poses, visible
|
|
|
|
|
|
entity indices, compass markers, wormhole exits, gravity terrain height, and
|
|
|
|
|
|
gravity terrain bands.
|
|
|
|
|
|
|
|
|
|
|
|
This means `ZoneRenderer` is no longer the canonical level hierarchy owner, but
|
|
|
|
|
|
it still exists as a persistent Unity hierarchy cache. The migration target is
|
|
|
|
|
|
smaller: a per-frame query/lowering layer that feeds native render buffers and
|
|
|
|
|
|
presentation objects only where GameObject views are still unavoidable.
|
|
|
|
|
|
|
|
|
|
|
|
## Physics And Ymir
|
|
|
|
|
|
|
|
|
|
|
|
Unity physics is already fenced as forbidden gameplay authority by
|
|
|
|
|
|
`Aetheria.State.Verify`.
|
|
|
|
|
|
|
2026-07-12 01:29:28 +01:00
|
|
|
|
`Assets/Resources/Prefabs/Lightning.prefab` is published under the
|
|
|
|
|
|
`effect.shot.bolt` presentation role. Its `LightningCompute` component and
|
|
|
|
|
|
shader/material bundle are owned by EveUnity with their original Unity GUIDs;
|
|
|
|
|
|
Aetheria owns only the configured prefab and its asset-manifest advertisement.
|
2026-07-12 01:24:30 +01:00
|
|
|
|
|
2026-07-15 08:27:36 +01:00
|
|
|
|
Texture production currently uses checked-in, pre-generated provider assets.
|
|
|
|
|
|
Substance is not part of the toolchain. A later asset-pipeline pass may move
|
|
|
|
|
|
texture generation into Blender baking, but that pipeline remains provider-side
|
|
|
|
|
|
and cannot become an EveUnity runtime dependency.
|
|
|
|
|
|
|
2026-06-22 01:11:56 +01:00
|
|
|
|
Current Ymir control flow:
|
|
|
|
|
|
|
2026-07-14 21:38:46 +01:00
|
|
|
|
- Ymir is deliberately a Box3D wrapper and physics-daemon boundary; its name
|
|
|
|
|
|
means **Not Invented Here**. Box3D owns integration and contact lifecycle.
|
|
|
|
|
|
Ymir owns stable game-facing body identity, session revisions, command
|
|
|
|
|
|
receipts, and typed contact-fact identity.
|
2026-07-14 22:25:05 +01:00
|
|
|
|
- `AetheriaYmirWorldPhysics` owns the retained physics transaction for each
|
|
|
|
|
|
`(RunId, ZoneIndex)`: a world session for ships and pickups, and an isolated
|
|
|
|
|
|
payload session for ordnance. Aetheria owns the active run/zone set and
|
|
|
|
|
|
disposes both sessions when a run or zone leaves it. Each fixed simulation
|
|
|
|
|
|
substep has its own physics-step identity even when several substeps share
|
|
|
|
|
|
one publication frame. Entity bodies use stable `EntityId`, never mutable
|
|
|
|
|
|
zone-list indices; current indices are projection data and may change during
|
|
|
|
|
|
cross-zone moves.
|
2026-07-14 21:38:46 +01:00
|
|
|
|
- Session creation is the only full body bootstrap. Ordinary ticks lower
|
|
|
|
|
|
membership changes, movement/orientation changes, tractor forces, gravity
|
|
|
|
|
|
fields, and pickup-rejection velocity into explicit retained-session
|
|
|
|
|
|
commands. Post-step body values in the run checkpoint are projections from
|
|
|
|
|
|
Ymir, not an independent physics solver.
|
2026-07-15 08:27:36 +01:00
|
|
|
|
- Restart material lives in a second daemon-private CultCache at
|
|
|
|
|
|
`<public-state>.ymir.cc`; it is absent from the public Aetheria document
|
|
|
|
|
|
registry and client subscription database. Ymir emits immutable incremental
|
|
|
|
|
|
journal chunks plus bounded per-frame resume descriptors. The daemon flushes
|
|
|
|
|
|
chunks, then resumes, then the public frame. That public frame is the commit
|
|
|
|
|
|
marker. Startup restores the exact `(RunId, FrameId, ZoneIndex)` records
|
|
|
|
|
|
before the client CultMesh host starts, and fails closed on incomplete active
|
|
|
|
|
|
persistence.
|
2026-07-17 11:54:00 +01:00
|
|
|
|
- Cargo collection runs after Ymir motion and accepts only live pickups within
|
|
|
|
|
|
the fixed XZ distance of an active, undocked ship. The daemon removes the
|
|
|
|
|
|
durable pickup row in the same transaction that inserts cargo, so restart or
|
|
|
|
|
|
repeated proximity evaluation cannot add it twice. Ymir contact facts and
|
|
|
|
|
|
client loot commands do not collect cargo.
|
2026-07-12 01:05:25 +01:00
|
|
|
|
- Ordinary direct, constant, and charged weapon fire resolves through
|
|
|
|
|
|
deterministic shot receipts. It does not create a Ymir body or derive damage
|
|
|
|
|
|
from collision.
|
2026-07-14 22:25:05 +01:00
|
|
|
|
- The payload phase follows the world phase in the same retained zone owner.
|
|
|
|
|
|
Ymir advances payload bodies without world fields or payload-to-payload
|
|
|
|
|
|
response, then revision-checked Box3D circle casts or overlaps query the
|
|
|
|
|
|
current world session against explicit stable entity-body candidates.
|
|
|
|
|
|
Aetheria interprets those query facts; Ymir does not own damage policy.
|
2026-07-12 01:50:18 +01:00
|
|
|
|
- Authored `DeployableWeapon` behavior now creates retained mine payloads.
|
|
|
|
|
|
Aetheria owns deployment admission, arming time, trigger transition,
|
|
|
|
|
|
detonation delay, blast selection, damage, and lifecycle events. Ymir moves
|
|
|
|
|
|
the unarmed payload and reports overlap/contact facts after it becomes a
|
|
|
|
|
|
stationary trigger body. Eve projects the payload kind, age, armed,
|
|
|
|
|
|
triggered, stationary, radius, delay, and magnitude state.
|
2026-07-12 01:33:16 +01:00
|
|
|
|
- The fossil `Projectile`, `GuidedProjectile`, their managers, Unity-side Ymir
|
|
|
|
|
|
stepping adapter, and dedicated proof tests are deleted. EveUnity lowers
|
|
|
|
|
|
ordinary weapon travel from daemon `shot.receipt` facts.
|
2026-07-12 01:38:18 +01:00
|
|
|
|
- Fossil laser, lightning, hitscan, and constant weapon effect managers are
|
|
|
|
|
|
also deleted. They no longer cast against Ymir from Unity to choose endpoints
|
|
|
|
|
|
or shield responses; EveUnity consumes the receipt trajectory, impact kind,
|
|
|
|
|
|
intensity, and provider presentation-role assets.
|
|
|
|
|
|
- The remaining Unity `AetheriaYmirPhysicsBridge` lowers clickable presentation
|
|
|
|
|
|
bounds into `YmirPhysicsQueries.CastSphere`; it knows nothing about daemon
|
|
|
|
|
|
entities, hulls, shields, targets, zones, or combat.
|
|
|
|
|
|
|
|
|
|
|
|
This is the right authority direction: daemon physics enters Ymir from daemon
|
|
|
|
|
|
state, while Unity only asks Ymir a local presentation-picking question.
|
|
|
|
|
|
Remaining debt:
|
|
|
|
|
|
|
2026-07-14 22:25:05 +01:00
|
|
|
|
- World and payload sessions are still in-process organs of the Aetheria
|
|
|
|
|
|
daemon. A future remote Ymir lowering must preserve the same ordered zone
|
|
|
|
|
|
transaction, stable body identities, revisions, and query facts rather than
|
|
|
|
|
|
restoring a second Aetheria physics authority.
|
2026-07-15 08:27:36 +01:00
|
|
|
|
- The in-process session registry is the live daemon implementation. Private
|
|
|
|
|
|
replay reconstruction is wired and restart-proven for a consumed pickup
|
|
|
|
|
|
contact, including no duplicate receipt, event, or rejection kick. Ymir's
|
|
|
|
|
|
complete in-memory journal is not compacted yet; disk writes are incremental,
|
|
|
|
|
|
memory retention is not.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
- Clickable raycasts still construct query bodies from Unity click bounds. That
|
|
|
|
|
|
is presentation picking, not simulation authority, but it should stay clearly
|
|
|
|
|
|
labeled as renderer/UI picking.
|
2026-07-12 02:25:40 +01:00
|
|
|
|
- The original `Mine Launcher` item was recovered from the quarantined
|
|
|
|
|
|
2021-03-05 catalog by stable legacy ID, normalized from its historical effect
|
|
|
|
|
|
reference to `DeployableWeapon`, and merged into canonical typed provider
|
|
|
|
|
|
state. The supplemental MessagePack file is migration provenance only.
|
|
|
|
|
|
- `Mine`, `MineManager`, `InstantWeaponEffectManager`, and their serialized
|
|
|
|
|
|
launcher prefab are deleted. A script-free provider prefab supplies the
|
|
|
|
|
|
original mesh/materials. Eve publishes lifecycle and pulse properties;
|
|
|
|
|
|
EveUnity generically lowers those semantic properties to material emission.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
|
|
|
|
|
|
## Gravity Terrain
|
|
|
|
|
|
|
2026-07-14 16:26:14 +01:00
|
|
|
|
Daemon zone/body state owns gravity as positive depth magnitudes. The Ymir
|
|
|
|
|
|
adapter passes `GravityWellDepth` directly into positive-strength radial fields,
|
|
|
|
|
|
which attract. Shared render queries subtract those magnitudes into negative
|
|
|
|
|
|
terrain wells, and `AetheriaRuntimeGameDocuments.RenderSplatsViewport` performs
|
|
|
|
|
|
the same derived sign conversion for `gravity.height` splats.
|
|
|
|
|
|
|
|
|
|
|
|
`AetheriaRuntimeDaemonRenderQueries` owns gravity influence brushes, terrain
|
|
|
|
|
|
sampling, and terrain bands. `ZoneRenderer` consumes those queries. The main
|
|
|
|
|
|
menu embeds the typed gravity, render-splat, and object viewport documents; its
|
|
|
|
|
|
old fallback body/object world has been deleted.
|
|
|
|
|
|
|
|
|
|
|
|
The old `Assets/Scripts/Gravity.cs` remains a legacy Unity-local visual
|
|
|
|
|
|
evaluator. It does not own gameplay gravity or canonical terrain facts. Unity
|
|
|
|
|
|
receives provider projections for the active camera/minimap/render pass, while
|
|
|
|
|
|
`AetheriaYmirWorldPhysics` receives physics fields from the same daemon state.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
|
|
|
|
|
|
## Stats And Behaviors
|
|
|
|
|
|
|
|
|
|
|
|
Stats are mid-migration.
|
|
|
|
|
|
|
|
|
|
|
|
Designer-facing recipe state exists in
|
|
|
|
|
|
`AetheriaRuntimeStatRecipes` and `AetheriaRuntimeStatRecipeSurfaceBuilder`.
|
|
|
|
|
|
Runtime item stat inspection exists in
|
|
|
|
|
|
`AetheriaRuntimeDaemonItemStatQueries`. Recipes are explicit: base value plus
|
|
|
|
|
|
enabled condition modifiers for quality, durability, heat, charge, ammo, range,
|
|
|
|
|
|
integrity, pilot skill, and environment. The recipe evaluator caches enabled
|
|
|
|
|
|
modifiers and dependency masks on the Unity-side `StatRecipe`.
|
|
|
|
|
|
|
|
|
|
|
|
The live behavior system still uses `PerformanceStat` heavily. Every behavior
|
|
|
|
|
|
constructs stat objects, registers them, and calls `Evaluate(...)` during
|
|
|
|
|
|
runtime. If a recipe exists, it uses the recipe evaluator. If not, it falls back
|
|
|
|
|
|
to the legacy exponent model:
|
|
|
|
|
|
|
|
|
|
|
|
- quality exponent;
|
|
|
|
|
|
- durability exponent multiplier;
|
|
|
|
|
|
- heat exponent multiplier;
|
|
|
|
|
|
- curve sampling for behavior-specific effects.
|
|
|
|
|
|
|
|
|
|
|
|
`StatModifier` still mutates target `PerformanceStat` modifier dictionaries at
|
|
|
|
|
|
runtime by behavior and entity. This is a partial modifier system, but it is
|
|
|
|
|
|
attached to the old `PerformanceStat` object graph rather than a compact
|
|
|
|
|
|
blueprint/instance stat set.
|
|
|
|
|
|
|
2026-07-17 02:55:07 +01:00
|
|
|
|
The daemon translation does not retain those object-owned dictionaries.
|
2026-07-17 03:03:30 +01:00
|
|
|
|
`AetheriaRuntimeBehaviorSimulation` persists switch, trigger, and modifier
|
2026-07-17 02:55:07 +01:00
|
|
|
|
lifecycle state in the authoritative snapshot. Runtime stat reads derive the
|
|
|
|
|
|
fossil multiplier-product and constant-sum result from those sources, including
|
|
|
|
|
|
required-behavior and descendant-kind targeting. This makes reconnect replay
|
|
|
|
|
|
idempotent and keeps the Unity fossil out of the gameplay authority path.
|
2026-07-19 10:24:57 +01:00
|
|
|
|
Behavior-state projection is a reconciliation write only: when equipment and
|
|
|
|
|
|
catalog behavior shape already match, reads preserve the existing state array
|
|
|
|
|
|
and every mutable daemon-owned value. An actual shape change rebuilds the
|
|
|
|
|
|
projection while retaining states whose owner, equipment index, behavior index,
|
|
|
|
|
|
and kind still match.
|
|
|
|
|
|
|
|
|
|
|
|
Each equipped-behavior query also derives one ephemeral set of operational
|
|
|
|
|
|
`StatModifier` behaviors and binds that set to every wrapper returned by the
|
|
|
|
|
|
query. All stat evaluations through those wrappers reuse the same set instead
|
|
|
|
|
|
of recursively rebuilding the equipment graph for every field. The set is not
|
|
|
|
|
|
persisted, cannot outlive the query result, and cannot write authority; modifier
|
|
|
|
|
|
lifecycle remains in the entity snapshot.
|
2026-07-17 03:03:30 +01:00
|
|
|
|
The same daemon organ executes common resource gates in group order. Energy,
|
|
|
|
|
|
thermal cells, cargo, and durability remain owned by their narrow transaction
|
|
|
|
|
|
subsystems; behavior composition decides only whether and when to call them.
|
2026-07-17 03:08:56 +01:00
|
|
|
|
Thermotoggle target temperature is also daemon-owned behavior state. Authored
|
|
|
|
|
|
data seeds it, adjustable commands mutate it, and its high/low-pass predicate
|
|
|
|
|
|
gates the same ordered chain.
|
2026-07-17 02:55:07 +01:00
|
|
|
|
|
2026-07-19 10:00:18 +01:00
|
|
|
|
Within one combat step, authoritative equipment, online state, durability, and
|
|
|
|
|
|
catalog payloads are read once into a tick-local operational behavior set.
|
|
|
|
|
|
Deployable, charged, constant, and instant weapon projections derive from that
|
|
|
|
|
|
same set. It is not persisted and cannot outlive the step; mutations still land
|
|
|
|
|
|
on the referenced authoritative item and behavior state. This prevents each
|
|
|
|
|
|
weapon family from independently rebuilding the same equipment graph without
|
|
|
|
|
|
introducing a cache owner beside the entity snapshot.
|
2026-07-19 10:24:57 +01:00
|
|
|
|
Entities without an operational descendant of `Weapon` do not enter the weapon
|
|
|
|
|
|
actor loop. They remain valid targets and physical-payload participants.
|
2026-07-19 10:00:18 +01:00
|
|
|
|
|
2026-06-22 01:11:56 +01:00
|
|
|
|
Migration target:
|
|
|
|
|
|
|
|
|
|
|
|
- blueprint/catalog rows define base stat ids and default values;
|
|
|
|
|
|
- designer recipes define explicit condition dependencies per stat;
|
|
|
|
|
|
- item/entity instances carry only condition values and sparse modifier state;
|
|
|
|
|
|
- each stat has a dependency mask so hot paths sample only required conditions;
|
|
|
|
|
|
- current stat queries are daemon-owned and can answer "what is this stat now?"
|
|
|
|
|
|
without Unity spelunking behavior objects;
|
|
|
|
|
|
- Unity behavior code consumes resolved current stat values or cached stat
|
|
|
|
|
|
handles, not raw `PerformanceStat` exponent objects.
|
|
|
|
|
|
|
|
|
|
|
|
## UI Surfaces
|
|
|
|
|
|
|
|
|
|
|
|
The current UI direction is Eve/CultUI:
|
|
|
|
|
|
|
|
|
|
|
|
- daemon publishes game/editor GUI and TUI surfaces;
|
|
|
|
|
|
- compatibility state surfaces exist for operations, player settings, catalog,
|
|
|
|
|
|
loadout templates, zone details, trade item details, and stat recipes;
|
2026-07-17 01:45:33 +01:00
|
|
|
|
- the daemon's pilot surface publishes docked spatial equipment and cargo grids
|
|
|
|
|
|
with generic Eve drop commands; Unity and browser lowerers own transient drag
|
|
|
|
|
|
state but not fit, access, mutation, or receipts;
|
2026-07-20 05:24:07 +01:00
|
|
|
|
- the generic EveUnity playable-world host mounts the same provider-owned pilot
|
|
|
|
|
|
surface as a themed UI Toolkit overlay. Aetheria owns cockpit values, menu
|
|
|
|
|
|
visibility, commands, and receipts; EveUnity owns only lowering and native
|
|
|
|
|
|
control wiring;
|
2026-07-17 01:45:33 +01:00
|
|
|
|
- Unity still lowers local surfaces through UI Toolkit for several remaining
|
|
|
|
|
|
menu/trade panels;
|
2026-06-22 01:11:56 +01:00
|
|
|
|
- Brokkr should be considered just another daemon publishing Unity editor Eve
|
|
|
|
|
|
surfaces, not a special Codex socket.
|
|
|
|
|
|
|
2026-07-16 13:45:56 +01:00
|
|
|
|
The architectural note in `Aetheria.State/docs/verse-daemon-shape.md` still
|
|
|
|
|
|
describes optional ecosystem indexing, but it is not the Aetheria session path.
|
|
|
|
|
|
Aetheria clients connect directly to the daemon's advertised CultMesh endpoint;
|
|
|
|
|
|
directly configured daemon peers exchange typed committed facts there as well.
|
|
|
|
|
|
Odin may index the provider only when explicitly enabled. Eve/CultUI defines
|
|
|
|
|
|
presentation, and the daemon owns side effects.
|
2026-06-22 01:11:56 +01:00
|
|
|
|
|
|
|
|
|
|
Remaining UI debt is not mostly visual. It is resolution semantics: if an Eve
|
|
|
|
|
|
surface contains a typed pointer to daemon state, the runtime should resolve it
|
|
|
|
|
|
automatically. Current surfaces still often duplicate display values into
|
|
|
|
|
|
component props. That works for rendering, but it is weaker than state-ref
|
|
|
|
|
|
driven UI where agents and clients can inspect or invoke the same typed daemon
|
|
|
|
|
|
state.
|
|
|
|
|
|
|
|
|
|
|
|
## Remaining Unity Responsibility
|
|
|
|
|
|
|
|
|
|
|
|
Unity is already less authoritative than it was, but not detached.
|
|
|
|
|
|
|
|
|
|
|
|
Still in Unity:
|
|
|
|
|
|
|
|
|
|
|
|
- observed `Galaxy`, `Zone`, `Entity`, `Ship`, `EquippedItem`, and behavior
|
|
|
|
|
|
facade graph projection;
|
|
|
|
|
|
- live behavior classes and much stat evaluation;
|
|
|
|
|
|
- `ActionGameManager` as a large input/UI/projection coordinator;
|
|
|
|
|
|
- `ZoneRenderer` persistent GameObject projection cache;
|
|
|
|
|
|
- prefab/hull visual instantiation and effect attachment;
|
|
|
|
|
|
- some presentation picking and clickable queries;
|
|
|
|
|
|
- old gravity material evaluator in `Gravity`;
|
|
|
|
|
|
- Unity-specific rendering settings and asset palette lowering.
|
|
|
|
|
|
|
|
|
|
|
|
Moved or moving out:
|
|
|
|
|
|
|
|
|
|
|
|
- durable world/catalog/player/run/zone/entity state;
|
|
|
|
|
|
- typed daemon command acceptance and operation application;
|
|
|
|
|
|
- provider advertisements, health, command boundaries, and surfaces;
|
|
|
|
|
|
- current-zone entity hot slab for native rendering and Ymir body construction;
|
|
|
|
|
|
- shared render queries for body poses, gravity terrain, wormholes, markers,
|
|
|
|
|
|
visible entities, and asteroid poses;
|
|
|
|
|
|
- Unity physics authority.
|
|
|
|
|
|
|
|
|
|
|
|
## High-Value Next Cuts
|
|
|
|
|
|
|
2026-07-04 22:46:04 +01:00
|
|
|
|
1. Enrich daemon SoA physics columns. Publish body radius/mass/inverse mass
|
2026-06-22 01:11:56 +01:00
|
|
|
|
from typed entity/hull state instead of `1.0` placeholders.
|
2026-07-04 22:46:04 +01:00
|
|
|
|
2. Add daemon current-stat query documents/surfaces. Designers and clients
|
2026-06-22 01:11:56 +01:00
|
|
|
|
should query current resolved stats through daemon-owned state refs, not
|
|
|
|
|
|
inspect Unity behavior objects.
|
2026-07-04 22:46:04 +01:00
|
|
|
|
3. Convert hot behavior reads from `PerformanceStat` to stat handles with
|
2026-06-22 01:11:56 +01:00
|
|
|
|
dependency masks and cached condition sampling. Leave legacy exponent
|
|
|
|
|
|
evaluation only as migration import/readback.
|
2026-07-04 22:46:04 +01:00
|
|
|
|
4. Shrink `ZoneRenderer` toward stateless per-frame render lowering. Persistent
|
2026-06-22 01:11:56 +01:00
|
|
|
|
GameObjects can remain for prefabs, but zone/body/entity discovery should be
|
|
|
|
|
|
query-driven from daemon state.
|
2026-07-04 22:46:04 +01:00
|
|
|
|
5. Promote Ymir's typed local query surface to CultNet/CultMesh query handles
|
2026-06-22 01:11:56 +01:00
|
|
|
|
when the Ymir daemon interface is ready.
|
2026-07-04 22:46:04 +01:00
|
|
|
|
6. Make Eve state refs first-class in the UI runtime so surfaces can point to
|
2026-06-22 01:11:56 +01:00
|
|
|
|
daemon state and clients resolve it automatically.
|
|
|
|
|
|
|
|
|
|
|
|
## Mental Model
|
|
|
|
|
|
|
|
|
|
|
|
The current machine is no longer "Unity owns the game and exports some state."
|
|
|
|
|
|
It is now "the Aetheria daemon owns typed state and publications, while Unity is
|
|
|
|
|
|
a powerful but still-too-large observer/projection runtime." The main migration
|
|
|
|
|
|
task is to keep deleting places where Unity turns observed daemon facts back
|
|
|
|
|
|
into local authority.
|