Fensalir/README.md
2026-05-09 00:04:45 +01:00

168 lines
6.4 KiB
Markdown

# Aquarium Engine
![Aquarium Engine icon](Aquarium-Engine-Icon.png)
C# engine core for Aquarium: a native, owned renderer and interaction runtime
for a living Epiphany client.
## Intent
- C# host with renderer architecture kept legible in Rider.
- Vortice/D3D11 first, with the native boundary kept explicit.
- DirectWrite/Direct2D overlay text after the scene pass for crisp debug and UI
typography.
- Grid-centered camera and world-space interaction invariants as first-class
engine contracts.
- Diegetic UI surfaces driven by Aquarium objects instead of admin chrome.
- CultNet for Epiphany communication.
- CultCache for settings, persistent client state, and reload recovery.
- Procedural audio and visual state treated as coupled signals.
## Current Shape
The engine opens a Win32 window, owns a D3D11 swapchain, raymarches the visible
Aquarium world in HLSL, and draws crisp overlay text through DirectWrite. The
camera target is the Grid center. Grid radius follows zoom distance. Body anchors
remain world-space.
The live runtime is split behind `Aquarium.Engine.Contracts`, so gameplay code
can reload while the host, window, renderer, and D3D device stay alive. Runtime
state is banked through CultCache MessagePack documents instead of loose JSON.
## Run
Aquarium currently expects the sibling `CultMath` and `CultLib` repos at
`E:\Projects\CultMath` and `E:\Projects\CultLib`, or the equivalent
`..\..\..\CultMath` / `..\..\..\CultLib` paths from the engine project.
```powershell
dotnet build Aquarium.Engine.slnx
dotnet run --project src\Aquarium.Engine\Aquarium.Engine.csproj
```
For iteration while an Aquarium window is already open, use the dev reload
runner instead of `dotnet run`:
```powershell
.\scripts\dev-reload.ps1
```
It builds an apphost executable into a fresh disposable slot under
`artifacts\dev-reload`, records the slot/PID in PowerShell CLIXML, and launches
the runtime with a MessagePack CultCache store at
`artifacts\dev-reload\cultcache\aquarium-client.msgpack`.
The previous script-owned process is stopped only after the replacement build
succeeds. This keeps MSBuild away from the locked normal `bin\Debug` output
while a live window is still open.
If the visible dev window was closed but the last slot is still present, reopen
it without rebuilding:
```powershell
.\scripts\dev-reload.ps1 -Reopen
```
Visible and headless runs keep separate PID state and logs, so a headless smoke
does not replace the visible dev window.
For automatic rebuild/restart on source changes, use the watcher:
```powershell
.\scripts\dev-watch.ps1
```
The watcher polls source files, waits for writes to settle, builds into a new
slot, and only replaces the running Aquarium after the new build succeeds. If a
build fails, the previous good process keeps running and that same broken source
fingerprint is not retried until files change again.
It also watches the recorded script-owned process. If the visible window is
closed or the recorded process dies, the watcher relaunches from a fresh slot on
the next poll instead of sitting there with its hands folded like this is fine.
To reopen a closed visible window from the last good slot without rebuilding,
run the watcher with:
```powershell
.\scripts\dev-watch.ps1 -ReopenWhenClosed
```
Shader edits do not restart the process. The dev reload runner passes the
source `Aquarium.hlsl` path into the live app, and the renderer polls that file,
compiles changed shaders in the running process, then swaps the D3D shader
objects only after compilation succeeds. A bad shader edit leaves the previous
working shaders bound and writes the compiler failure to stderr.
Live gameplay/runtime code is split into `Aquarium.Engine.Live` behind
`Aquarium.Engine.Contracts`. The host loads that live DLL through a collectible
assembly load context, while `dev-watch.ps1` builds live-only changes into
`artifacts\dev-reload\live-slots` and updates `live-current.txt`. The running
host sees the pointer change, loads and starts the new runtime first, then
disposes the old one only after the replacement is valid. A bad live DLL leaves
the previous runtime alive and reports the reload failure to stderr. The watcher
waits for the host log to acknowledge the exact live DLL path before calling a
live reload successful; pointer updates without host acknowledgement are treated
as reload failures. Successful reloads rehydrate through CultCache without
restarting the window or D3D device.
Host, renderer, contract, project, script, and `src\Aquarium.Engine\Assets`
content changes still rebuild and restart the apphost. Runtime content belongs
to the process image; shader hot reload cannot make a running renderer discover
new files it never loaded.
Runtime live state is a typed CultCache document, not a loose sidecar file. The
first document is `epiphany.aquarium.live_state`, currently banking camera
target, yaw, pitch, distance, time, and save generation every few frames so a
reload can rehydrate without pretending memory is vibes.
Stop the script-owned Aquarium process:
```powershell
.\scripts\dev-stop.ps1
```
Headless smoke:
```powershell
dotnet run --project src\Aquarium.Engine\Aquarium.Engine.csproj -- --headless
```
Headless reload smoke without touching the normal build output:
```powershell
.\scripts\dev-reload.ps1 -Headless
```
Headless watch smoke:
```powershell
.\scripts\dev-watch.ps1 -Headless
```
Shipping publish:
```powershell
.\scripts\publish-win-x64.ps1 -Clean -Zip
```
This writes a self-contained Windows build to
`artifacts\publish\win-x64`, verifies the executable, live runtime DLL,
contracts DLL, icon, bundled fonts, and shader source, then optionally creates
`artifacts\publish\EpiphanyAquariumEngine-win-x64.zip`.
## Persistent State
This repo carries its own Aquarium memory:
- `state/map.yaml`: canonical project map and next actions.
- `state/memory.json`: durable taste, doctrine, renderer rules, and warnings.
- `state/evidence.jsonl`: compact lessons that should change future behavior.
- `state/scratch.md`: disposable working context for the current pass.
Keep that state current when the engine learns something durable. Dead lessons
go out with the trash; the repo is not a scrapbook.
## Docs
- `docs/aquarium-engine-doctrine.md`: engine doctrine and invariants.
- `docs/vortice-spine.md`: native host/renderer spine.
- `docs/hlsl-renderer.md`: current shader path.
- `docs/input.md`: camera and input contract.
- `docs/cult-runtime-surface.md`: CultCache/CultNet runtime surface.