Make daemon witness prove destruction loot

This commit is contained in:
Meta Vens 2026-07-16 03:35:03 +01:00
commit 879f6deb9c
9 changed files with 90 additions and 38 deletions

View file

@ -90,17 +90,8 @@ internal static class AetheriaDaemonZoneGenerator
GravityTerrainDepthExponent = 1.18,
GravityTerrainBoundaryFog = 0.25,
GravityTerrainWaveFrequency = 0.55,
NextPickupIndex = 1,
DroppedPickups =
[
new AetheriaDroppedPickupSnapshot
{
PickupIndex = 0,
Position = Vec3(-50, 0, 40),
Velocity = Vec3(0, 0, 0),
Item = new AetheriaLoadoutItem { ItemKey = "scrap-metal", Quantity = 1 }
}
]
NextPickupIndex = 0,
DroppedPickups = Array.Empty<AetheriaDroppedPickupSnapshot>()
}).ConfigureAwait(false);
for (var i = 0; i < entities.Length; i++)
@ -230,7 +221,7 @@ internal static class AetheriaDaemonZoneGenerator
Entity(loadouts, availabilityFactions, "Torch Three", "ship", -235, 210, 8, -4, "player", 500, keys[7], [keys[0], keys[1], keys[7]], ["micro-missile", "coolant-pack"]),
Entity(loadouts, availabilityFactions, "Foundry Tug", "ship", 330, -155, -2, 3, "player", 390, keys[6], [keys[0], keys[1], keys[6], keys[10]], ["ore-canister", "field-rations"]),
Entity(loadouts, availabilityFactions, "Derelict Relay", "station", -390, 270, 0, 0, "neutral", 160, "", [keys[0], keys[3]], ["ancient-transponder"]),
Entity(loadouts, availabilityFactions, "Ash Raider", "ship", 20, -30, -5, -2, "raider", 320, "", [keys[0], keys[1], keys[2], keys[4]], ["scrap-metal", "stolen-capacitor"]),
Entity(loadouts, availabilityFactions, "Ash Raider", "ship", 20, -30, -5, -2, "raider", 320, "", [keys[0], keys[1], keys[2], keys[4]], []),
Entity(loadouts, availabilityFactions, "Cinder Knife", "ship", 585, -115, -7, 1, "raider", 280, "", [keys[0], keys[3]], ["volatile-fuel"]),
Entity(loadouts, availabilityFactions, "Blackwake", "ship", 690, 300, -4, -3, "raider", 230, "", [keys[2]], ["ore-cache", "burned-relay-core"]),
Entity(loadouts, availabilityFactions, "Vesper Sloop", "ship", 960, 620, -3, -5, "raider", 250, "", [keys[4]], ["stolen-map-fragment"]),
@ -246,6 +237,51 @@ internal static class AetheriaDaemonZoneGenerator
Items = Array.Empty<AetheriaLoadoutItemSlot>()
}
];
entities[6].StatGrids =
[
StatGrid("hull", 1),
StatGrid("shield", 0),
StatGrid("heat", 0)
];
var salvage = entities[6].Equipment.FirstOrDefault()
?? throw new InvalidOperationException("The starter raider loadout produced no canonical salvage item.");
var salvageSelection = entities[6].LoadoutGeneration.Selections.First(selection =>
string.Equals(selection.Role, "equipment", StringComparison.Ordinal) &&
string.Equals(selection.ItemKey, salvage.ItemKey, StringComparison.Ordinal));
entities[6].CargoContents =
[
new AetheriaCargoBayLoadout
{
Items =
[
new AetheriaLoadoutItemSlot
{
Item = new AetheriaLoadoutItem
{
ItemKey = salvage.ItemKey,
Quality = salvage.Quality,
Durability = salvage.Durability,
Quantity = 1,
Enabled = true
}
}
]
}
];
entities[6].Equipment = Array.Empty<AetheriaEntityItemSlot>();
entities[6].WeaponGroups = Array.Empty<AetheriaWeaponGroupSnapshot>();
entities[6].LoadoutGeneration.Selections = entities[6].LoadoutGeneration.Selections
.Where(selection => string.Equals(selection.Role, "hull", StringComparison.Ordinal))
.Append(new AetheriaLoadoutGenerationSelection
{
Role = "cargo",
ItemKey = salvageSelection.ItemKey,
ManufacturerKey = salvageSelection.ManufacturerKey,
Price = salvageSelection.Price,
ManufacturerDistance = salvageSelection.ManufacturerDistance,
Allegiance = salvageSelection.Allegiance
})
.ToArray();
entities[2].AgentTaskCapabilities = ["attack", "defend", "explore"];
entities[3].AgentTaskCapabilities = ["attack", "defend"];
entities[4].AgentTaskCapabilities = ["mine", "haul", "tow", "explore"];

View file

@ -6,9 +6,9 @@
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.render-pipelines.universal": "17.4.0",
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14",
"org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3",
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.49"
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50"
}
}

View file

@ -119,11 +119,11 @@
}
},
"org.gamecult.cultlib": {
"version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14",
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "feb5c71513e71d681699f462fe3682b3168c6f73"
"hash": "4b7162022a8976f7941b5a7a69acf50f1b6d532b"
},
"org.gamecult.eve.plugin-fields": {
"version": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3",
@ -144,18 +144,18 @@
"hash": "140e1bd963a0033e66777a3b2c5fe6e9c97dfe32"
},
"org.gamecult.eve.unity-scene": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.49",
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50",
"depth": 0,
"source": "git",
"dependencies": {
"org.gamecult.cultlib": "1.0.13",
"org.gamecult.cultlib": "1.0.14",
"org.gamecult.eve.plugin-fields": "0.2.3",
"org.gamecult.eve.surface": "0.2.2",
"com.unity.mathematics": "1.3.2",
"com.unity.render-pipelines.universal": "17.4.0",
"com.unity.modules.particlesystem": "1.0.0"
},
"hash": "e6ba1a36f6f0bce8df2c9834c25a8a980f03413c"
"hash": "7c8442e12264806a53a9e0e08b7b090dcddb8c90"
},
"com.unity.modules.assetbundle": {
"version": "1.0.0",

View file

@ -21,7 +21,7 @@
"org.gamecult.aetheria.eve-runtime": "file:org.gamecult.aetheria.eve-runtime",
"org.gamecult.aetheria.state": "file:org.gamecult.aetheria.state",
"org.gamecult.cultmath": "file:../../CultMath",
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14",
"org.gamecult.eve.surface": "file:../../EveUnity/packages/org.gamecult.eve.surface",
"org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3",
"org.gamecult.eve.unity-scene": "file:../../EveUnity/packages/org.gamecult.eve.unity-scene",

View file

@ -311,11 +311,11 @@
}
},
"org.gamecult.cultlib": {
"version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14",
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "feb5c71513e71d681699f462fe3682b3168c6f73"
"hash": "4b7162022a8976f7941b5a7a69acf50f1b6d532b"
},
"org.gamecult.cultmath": {
"version": "file:../../CultMath",
@ -345,7 +345,7 @@
"depth": 0,
"source": "local",
"dependencies": {
"org.gamecult.cultlib": "1.0.13",
"org.gamecult.cultlib": "1.0.14",
"org.gamecult.eve.plugin-fields": "0.2.3",
"org.gamecult.eve.surface": "0.2.2",
"com.unity.mathematics": "1.3.2",

View file

@ -2433,6 +2433,21 @@ predicate that still needs legacy DTO objects must earn that dependency by
using behavior objects or simulation-only methods that typed facets do not yet
expose.
The released-package proof keeps two lifecycle claims separate. The
`cold-start-lowering` profile begins with an empty cache, receives and verifies
the 46,412,384-byte provider body through `cultmesh.content.v1`, promotes the
exact hash with no partial, and proves generic world, field-volume, movement,
environment, and pilot/map camera lowering. The `full-session-gameplay` profile
starts a fresh warm daemon session, begins with no pickup, destroys the
deterministic salvage target, observes its canonical cargo drop, and collects
it exactly once from a persisted Ymir Begin fact. Witness runners use the
daemon's native 20 ms wall interval for its 20 ms simulation delta; download
latency is not allowed to redefine transient world lifetime. The managed
network content path is proven, while negotiated mapped/zero-copy body delivery
remains CultMesh work. The fog contract and provider shader execute, but the
current brown-black output is not visual parity with the fossil's blue gravity
sea.
Ymir restart ownership is deliberately private and asymmetric:
- Owner: `AetheriaYmirPersistenceCoordinator` owns reconstruction durability;

View file

@ -34,12 +34,12 @@ validation proves contract shape, not wiring, exclusivity, lowering, or parity.
| Pilot camera | ARPG follow/dock cameras | Eve view semantics + runtime | camera rig and semantic view id | EveUnity camera rig | daemon dock state selects distinct contracts instead of collapsing both fossil cameras: undocked flight advertises the entity-forward `Third Person Rig` framing (distance 30, screen 0.64/0.19, FOV 60, lens 1-4096) and the shared `aim.presentation` convergence point as its look-at; Aetheria translates the fossil Cinemachine top-origin screen Y of `0.81` to Eve's bottom-origin viewport Y of `0.19`; EveUnity solves native pose while preserving both optical aim and advertised entity framing, without provider types; the retained dock projection remains separate | reproduce the dock camera's separate follow/look-at subjects, blend timeline, noise, and reconnect state |
| Render channels | Unity layers/culling masks | provider surface policy + runtime asset variant | semantic channel exclusions | EveUnity native layer mapping | wired, exclusive, and lowered: the pilot surface excludes the semantic `map` channel; the Unity asset variant maps `map` to its authored native layer; EveUnity subtracts that layer from the configured camera mask; portable state contains no Unity layer or mask; the released warm witness proves the pilot camera excludes map glyphs while the map camera retains them | preserve the channel proof while world presentation and transport continue to evolve |
| Minimap/tactical map | `ZoneRenderer`, map cameras | daemon world facts | explicit map projections | Unity and Electron | facts fragmented; generic lowerers absent | same state in both runtimes |
| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | daemon publishes canonical gravity/fog splat layers through `field.volume3d`; Eve Fields `0.2.3` owns portable `PowerPulse` and `AnimatedRadialCosine` semantics; Aetheria emits the fossil global animated simplex/cellular/ambient stack, body-owned radial waves, and separate negative gameplay `gravity.height` and positive visual `fog.surface_height`; the field viewport matches the fossil splat cameras' 2000-by-2000 orthographic footprint while the larger 3000-scale brush parent remains brush coverage, not sampling extent; daemon entities follow fossil terrain height plus hull grid offset after Ymir XZ motion; released EveUnity `0.3.49` lowers the authored 2048/256/512 layer topology, provider shader ABI, pre-postprocess URP pass, authoritative flow time, explicit camera matrix, and float32 packed-output diagnostics without provider code. Translating the fossil camera's top-origin screen Y into Eve's bottom-origin convention places the camera above the field and restores a live fog horizon with the original `-36.17` noise amplitude; both camera-channel screenshots pass | restore the old blue tint, luminance, patch structure, gravity-wave readability, and surrounding world geometry; visual parity remains explicitly open |
| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | daemon publishes canonical gravity/fog splat layers through `field.volume3d`; Eve Fields `0.2.3` owns portable `PowerPulse` and `AnimatedRadialCosine` semantics; Aetheria emits the fossil global animated simplex/cellular/ambient stack, body-owned radial waves, and separate negative gameplay `gravity.height` and positive visual `fog.surface_height`; the field viewport matches the fossil splat cameras' 2000-by-2000 orthographic footprint while the larger 3000-scale brush parent remains brush coverage, not sampling extent; daemon entities follow fossil terrain height plus hull grid offset after Ymir XZ motion; released EveUnity `0.3.50` lowers the authored 2048/256/512 layer topology, provider shader ABI, pre-postprocess URP pass, authoritative flow time, explicit camera matrix, and float32 packed-output diagnostics without provider code. Translating the fossil camera's top-origin screen Y into Eve's bottom-origin convention places the camera above the field and restores a live fog horizon with the original `-36.17` noise amplitude; both camera-channel screenshots pass | restore the old blue tint, luminance, patch structure, gravity-wave readability, and surrounding world geometry; visual parity remains explicitly open |
| HUD/schematic | ARPG HUD and `SchematicDisplay` | Eve composition from daemon facts | semantic status/components | EveUnity UI | provider-authored transparent cockpit is wired, projected, and lowered through generic UI Toolkit panes, metrics, and progress components for hull, shield, capacitor, temperature, cargo, weapon cooldown/groups, selected target, target lock, target shield, and target hull; the original armor/equipment schematic and transient warning choreography remain reference-only | schematic topology, warning timelines, dynamic action state, and composited live capture |
| Hit/lock/warnings | `ActionGameManager` feedback | daemon event facts | transient feedback stream | VFX/UI/audio | bounded deduplicated game-event ledger and Eve `feedback.stream` wired for pickup outcomes, projectile launch/impact, entity damage, alive-to-dead destruction, authoritative weapon reload chronology, and episode-deduplicated `weapon.fire.refused` facts for insufficient energy or missing ammunition; refusal identity, authored weapon, target, reason, and remaining magazine state are runtime-independent cockpit inputs | add lock transitions, thermal and docking event families, negative transaction fixtures, and runtime effect consumption |
| Assets | `Assets/Resources` | Aetheria provider | asset catalog + CultMesh CDN | runtime cache/load | provider manifests name deterministic bundle-internal paths; the authoring build derives presentation-only prefabs, strips missing and non-Eve `MonoBehaviour` components, verifies both saved prefabs and the loaded bundle, and publishes the immutable bundle through CultMesh; released-client warm-cache loading, content verification, and rendered provider identity are proven, while cold transfer still times out because the 46.1 MB body travels through batched snapshot records | mapped/network body transport followed by empty-cache download, atomic promotion, and cache reuse proof |
| Assets | `Assets/Resources` | Aetheria provider | asset catalog + CultMesh CDN | runtime cache/load | provider manifests name deterministic bundle-internal paths; the authoring build derives presentation-only prefabs, strips missing and non-Eve `MonoBehaviour` components, verifies both saved prefabs and the loaded bundle, and publishes the immutable bundle through CultMesh; the released cold profile starts empty, receives and verifies the 46,412,384-byte body through `cultmesh.content.v1`, atomically promotes the exact hash with no partial, and lowers rendered provider identity; the warm profile reuses the committed body. Negotiated mapped/zero-copy delivery remains unproven | negotiated mapped/network body selection and same-machine zero-copy proof |
| Save/resume | original persistence paths | daemon/CultCache | published current state | clients rehydrate | owner-exists; not parity-proven | mid-loop restart |
| Terminus loop | original game composition | daemon/Ymir/Eve | pilot surface | Aetheria.Unity | live minimum-loop proof: generic Unity discovers the provider, lowers the pilot world/assets, single-steps dock and undock while paused, buys daemon-priced station stock, single-steps Ymir salvage collection, resumes, moves, targets, fires, and presents authoritative receipts/shot outcome | destruction-created loot pickup, richer trade content, docking transitions, and sustained combat encounters |
| Terminus loop | original game composition | daemon/Ymir/Eve | pilot surface | Aetheria.Unity | live minimum-loop proof: generic Unity discovers the provider, lowers the pilot world/assets, single-steps dock and undock while paused, buys daemon-priced station stock, single-steps Ymir salvage collection, resumes, moves, targets, fires, and presents authoritative receipts/shot outcome; the released full-session profile starts with no pickup, destroys a deterministic target, observes its canonical cargo drop, tractors it into a Ymir Begin contact, and proves exactly one `ymir-fact:` collection receipt plus cargo `0` to `1` | richer trade content, docking transitions, and sustained combat encounters |
| Starbridge | original/shared architecture intent | one daemon session | pilot + commander surfaces | Unity + Electron | commander task board and autonomous explore execution wired; Electron Eve lowering and split-target proof missing | commander orders plus four pilots and autonomous workers |
| Behavior engine | `ServerShared/Behaviors` composition | daemon | executable action/status projection | action bar and feedback | tick reconciles equipped catalog payloads into persistent behavior state; shared evaluated-stat query proven; execution families remain partial | every behavior family, ordering, resource transaction and modifier lifecycle |
| Sensors/visibility | installed sensor sensitivity, decaying signature sources, and observer information thresholds | daemon | contacts and ping events | indicators/maps | passive reach derives from enabled installed Sensor behaviors with diminishing-return array composition regardless of entity kind; station-scale arrays are ordinary gear installed into larger hull-authored sensor hardpoints, with smaller same-type arrays remaining valid fallbacks; generation prefers the largest fitting footprint and contains no station/ship sensor-count branch; contact refresh no longer overwrites emitted visibility; docked craft consume one daemon-derived union of craft and dock-parent contacts through both Eve rows and SoA bodies, with sensor-source provenance; the old station range survives only as obsolete snapshot compatibility | prove shutdown, threshold decay, ping, classification timelines, and canonical catalog station-array data |
@ -151,12 +151,13 @@ These are source-confirmed ownership failures, not feature backlog:
gameplay assemblies. EveUnity now publishes each committed SoA generation
through a read-only presented-entity registry; richer selection and HUD
adapters still need to consume it instead of rebuilding parallel indexes.
11. **Remote provider asset delivery remains unproven.** The authoring build now
derives deterministic presentation-only variants, strips missing and
non-Eve scripts, verifies the saved prefabs and loaded AssetBundle, and the
daemon advertises those bundle-internal paths. A clean EveUnity client must
still prove cold download, content verification, cache reuse, and rendered
identity without access to the authoring project.
11. **Remote provider asset delivery is proven through the managed content
session.** The authoring build derives deterministic presentation-only
variants, strips missing and non-Eve scripts, verifies the saved prefabs and
loaded AssetBundle, and the daemon advertises those bundle-internal paths.
A clean released EveUnity client downloads, verifies, atomically promotes,
reuses, and renders the provider body without access to the authoring
project. This does not prove the negotiated mapped/zero-copy representation.
12. **The negotiated local SoA fast path remains unproven.** The daemon publishes
exact immutable generations; the external Unity client rejects stale or
mismatched bodies and now resolves the same generation through the

View file

@ -54,7 +54,7 @@ $daemon = Start-Process dotnet -ArgumentList @(
"--client-cultmesh-host", "127.0.0.1",
"--client-cultmesh-advertise-host", "127.0.0.1",
"--client-cultmesh-port", $Port,
"--tick-interval-ms", 250,
"--tick-interval-ms", 20,
"--fixed-delta-ms", 20,
"--no-odin-announcements"
) -PassThru -WindowStyle Hidden -RedirectStandardOutput $daemonLog -RedirectStandardError "$daemonLog.error"

View file

@ -14,14 +14,14 @@ $manifest = Get-Content (Join-Path $ProjectPath "Packages/manifest.json") -Raw |
$lock = Get-Content (Join-Path $ProjectPath "Packages/packages-lock.json") -Raw | ConvertFrom-Json
$expected = @{
"org.gamecult.cultlib" = @(
"https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"feb5c71513e71d681699f462fe3682b3168c6f73")
"https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14",
"4b7162022a8976f7941b5a7a69acf50f1b6d532b")
"org.gamecult.eve.surface" = @(
"https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2",
"140e1bd963a0033e66777a3b2c5fe6e9c97dfe32")
"org.gamecult.eve.unity-scene" = @(
"https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.32",
"817912a041ac1911e1e27a4b88617754d90ad4b7")
"https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50",
"7c8442e12264806a53a9e0e08b7b090dcddb8c90")
}
foreach ($packageName in $expected.Keys) {
@ -34,7 +34,7 @@ foreach ($packageName in $expected.Keys) {
$cultLibPackage = Get-ChildItem (Join-Path $ProjectPath "Library/PackageCache") -Directory |
Where-Object Name -Like "org.gamecult.cultlib@*" |
Where-Object { (Get-Content (Join-Path $_.FullName "package.json") -Raw | ConvertFrom-Json).version -eq "1.0.13" } |
Where-Object { (Get-Content (Join-Path $_.FullName "package.json") -Raw | ConvertFrom-Json).version -eq "1.0.14" } |
Select-Object -First 1
if (-not $cultLibPackage) { throw "Resolved CultLib package is missing from Library/PackageCache." }