From f276f9bcb31e7a75ce6f25f2d10fb2f7d3e9d985 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 14 Jun 2026 13:03:57 +0100 Subject: [PATCH] Persist entity simulation grids in checkpoints --- .voidbot/state/aetheria.cc | Bin 85954 -> 85788 bytes Aetheria.State.Unity.Smoke/Program.cs | 22 ++++++- .../AetheriaRuntimeCommitLogApplier.cs | 17 ++++- Aetheria.State/README.md | 16 +++-- Assets/Scripts/Gameplay/ActionGameManager.cs | 62 +++++++++++++++++- .../AetheriaRuntimeStateCommitDocument.cs | 19 ++++++ docs/aetheria-perfect-machine-map.md | 18 +++-- 7 files changed, 140 insertions(+), 14 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 1079ad251f8829cbe2a58e9290030e983bb3664a..29aeb69073f7fd67b6ae458663cb3943afe849b3 100644 GIT binary patch delta 1641 zcmZ`)&2Jk;6xSq81p&37qB?+}4XSOr5 zPNE)isD#LQ1#>}g0EE;7ghQ!>RG}hq-~`w9!ihhiC$79%Z|o42n?3X9z4!ZgZ-4!2 z+XdU z4=$V_AI_HRl-Y=BPAg1WZg(rjQd{Y09-4~XO;}h7A{J~Vic9OJ&XZeb<<(Te;1GK6 z+^LJCbWZRt1HT6A*Ra5<&tLsE5R}JH$o)p(qgQFn)~KW% zrmO2(ear&e%zL^fX<{N}A?ckOuq;lPrZ&~A48H%Eip`iBQwFMIrOOc0oz3EBlnSvK zC>f?$rdvahn>!dML-_BFzu1MgRx#u_dd0yL!rZ-!(hD-BrKSnW$IIUy7cRoVxFM`dW?e;fJKc~#$2QA8>bN+KO#Qr-2`Dk*k> z8fb}>B^r5!HfI8<{LV6IxN6GBe=M_zcDd3O4CrF(pi^WqMqNA*;HKzNBB8m$Rk$t@ zJG7_`qF9B@UA;smJ~9eAs7NB{E`o>?E|?cUwL!C(a%muyv`e|5ExhqHM3IOFHl+eP zRS9-AQ9MS~qCA5aHoJZQ%-$0+{C?^+JYt#Le++^Y=|jy^5qbtKmnp;dTBV%`o^1{< zsIQP?@*T(A0!Hei6ky6;{=)}g zm_gztgepj5oCSk+HkRsfi{u^F9OYC*ALtNj!+2$v+IA4FYF<;Ddjf Q7%Q6xJk7P*FsYN+GnDfr3zkcek$XI8A9{J1(?`&@`zf6jey$-LXA*cV?NH zO=5ZoQUnr5w1<@tq6a`+DxgBBCse6de#C`C+Z$(u+7nma?E0^%CCjpB-+b?T-}~O% zFTa|(cXQ^)Z>Hw*%ccBs@r+$4m9{@eCz91QG#mdqbufCcc*Z=4#q{2@!{EjE@$}-< z>L&*aNA4^fL05~f*@Ws2m5f*)2~I7S`c!E~d`tI2>RCz?O_Tf^=(^wBj5u~X)a{0X zag9wpR-A;YBecR??BbA0#gxWv%Bh5l9u~66w9^z`54VU5VQ^F66dPCjnYRIG%jB`Y zb$!Bu2k5srPfjgBKFtDZ9@qSchSFqB0Wsko9)TvOmQiD$1{wHMu=t80q0&n=;W4Um z5b64n$9TIBc)1RTA(0ePq`y6=gK(ERVTUN{wAdb06AHyN6FiqC?=tQ=oCMSXR{Kon zu%t>v(lr^{lI$?u%W4lIU$f9>pid4HrKuDQDxki`kWr?TOigW~90fA(FclHs5CU|F zRyLlfhNJ;u97@A(LvW>K(vRG!U1XG=1oo(HWCScZ39X_IH|c1veg` zdV|9OZW8Tw0^ylZ=KINw^T@ems8yAsLDTP9Yg-*6!?7OslR@zr87{ar$UrpPp-`wx zB1LihNBm-Z_tEV87(_K(fKf=?E@@M^-J&2rXlG;l-HX@yR8=6lRGESR2b|jXjw^xy zSUDsN{hp(=kOoP2pfiz9Zk)0)5h&-SrpXLE8ipkQ3OfD_(J4bP@5^(h3r!JmkH}uU zzjh*C|L53+tQnH-7*P~~ulltsz)fOb5D(gni8Oa6HakIYqT_L)@y^ovM%G@H&EVLK zNwKSNONwAJ!WS3NXF01*Ta1IISrKEmjZ$VLjJQl=081XOpzBU?aKk0gTjqj@PY>A$ zC%L?W-YXQ=VKcx+$RI~g4eS$ZAloCxm$6gcSgmYQS4imCM8kVD5UImkAlh(Q^*d%Z zOfpwNH{wex^U2K$dOjAP&Lmq^R8Ib@pyy6z6{iUg5lTL;puO%}8w6YqbN-|dsmW4% z;a#RX<4euNOG8N62VaAQ@8=JXQQuVAdNn)CN>eAlR}n^y((qr+ED{AhX}UP80U i={gFAvBko

8K?T-%2XU*ZAs~6GTqodQM^7j8gWPPRp diff --git a/Aetheria.State.Unity.Smoke/Program.cs b/Aetheria.State.Unity.Smoke/Program.cs index 1269b6076..00abdd28c 100644 --- a/Aetheria.State.Unity.Smoke/Program.cs +++ b/Aetheria.State.Unity.Smoke/Program.cs @@ -273,7 +273,24 @@ try } } }, - WeaponGroups = new[] { new[] { 0 } } + WeaponGroups = new[] { new[] { 0 } }, + StatGrids = new[] + { + new AetheriaRuntimeEntityStatGridCommit + { + Name = "temperature", + Width = 2, + Height = 1, + Values = new[] { 280.0, 281.0 } + }, + new AetheriaRuntimeEntityStatGridCommit + { + Name = "hull_conductivity_x", + Width = 2, + Height = 1, + Values = new[] { 1.0, 0.0 } + } + } } } } @@ -325,6 +342,9 @@ try zone.Bodies[0].Asteroids.Length == 1 && entity?.Equipment.Length == 1 && entity.WeaponGroups.Length == 1 && + entity.StatGrids.Length == 2 && + entity.StatGrids.Any(grid => grid.Name == "temperature" && grid.Values.Length == 2 && grid.Values[1] == 281.0) && + entity.StatGrids.Any(grid => grid.Name == "hull_conductivity_x" && grid.Values.Length == 2 && grid.Values[0] == 1.0) && AetheriaRuntimeStateCommitLog.ReadPending(commitSmokeStatePath).Count == 0; } diff --git a/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs b/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs index c234a9b47..19494c2df 100644 --- a/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs +++ b/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs @@ -424,10 +424,25 @@ public static class AetheriaRuntimeCommitLogApplier .ToArray(), WeaponGroups = ToIntArrayArray(entity.WeaponGroups) .Select(group => new AetheriaWeaponGroupSnapshot { EquipmentIndices = group }) - .ToArray() + .ToArray(), + StatGrids = ToEntityStatGrids(entity.StatGrids) }; } + private static AetheriaEntityStatGrid[] ToEntityStatGrids( + IReadOnlyList? grids) + { + return (grids ?? Array.Empty()) + .Select(grid => new AetheriaEntityStatGrid + { + Name = grid.Name ?? "", + Width = grid.Width, + Height = grid.Height, + Values = (grid.Values ?? Array.Empty()).ToArray() + }) + .ToArray(); + } + private static int[] ToIntArray(IReadOnlyList? values) { return (values ?? Array.Empty()).ToArray(); diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index 5ca0a7baf..3c8102e49 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -21,7 +21,8 @@ typed corporation references plus relationship tokens and numeric standings. Zone checkpoints include typed orbit and body rows for generated celestial state: orbit IDs, parent IDs, distance, phase, fixed positions, body kind, resources, gravity/body multipliers, asteroid entries, and gas/sun visual -parameters. +parameters. Entity checkpoints include typed simulation stat grids for +temperature, thermal mass, armor, max armor, and hull-conductivity axes. Player settings include player name, tutorial flag, story-file hash cursors, gameplay formatting, graphics preferences, input binding overrides, and action-bar inputs. Do not preserve `SavedGame`, Unity @@ -120,9 +121,12 @@ needs actual allegiance weights, not only display counts. Runtime checkpoints now persist session faction relationships into typed run state, and runtime sessions publish typed state-host liveness. Zone checkpoints persist generated orbit/body rows into `AetheriaZoneState`, so `RuntimeZoneBlueprint` is no -longer the only surface carrying celestial graph facts. Broader runtime object -graphs, typed behavior factory construction, and simulation state remain legacy -until dedicated typed runtime documents exist. +longer the only surface carrying celestial graph facts. Entity checkpoints +persist hull simulation grids into `AetheriaEntitySnapshot`, so +`RuntimeEntityBlueprint` is no longer the only surface carrying those live +values. Broader runtime object graphs, typed behavior factory construction, and +behavior-private simulation state remain legacy until dedicated typed runtime +documents exist. Typed name-file documents are `aetheria.name_file.v2` records. They carry the legacy ID, display name, count, compact sample names for surfaces, and the full name array needed to move `Galaxy`/Markov name generation off legacy @@ -170,8 +174,8 @@ an entity snapshot. It also writes and reopens `AetheriaRuntimeSession` and checks that the Eve provider advertises the runtime-session schema. The run smoke proves a typed run can reference a typed zone, the zone can preserve orbit/body rows and reference typed entity snapshots, and entity snapshots can -preserve equipment slots, weapon groups, and stat grids without reviving -`PlayerSettings.msgpack`, `.loadout`, or `.zone` serialization. +preserve equipment slots, weapon groups, and simulation stat grids without +reviving `PlayerSettings.msgpack`, `.loadout`, or `.zone` serialization. `Aetheria.State.Verify` opens a materialized state file and checks that the typed migration ledger matches the actual item, corporation, and name-file diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 9a16353bc..bb566e9f1 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -655,7 +655,67 @@ public class ActionGameManager : MonoBehaviour .ToArray() ?? Array.Empty(), WeaponGroups = entity.WeaponGroups? .Select(group => (IReadOnlyList)group.items.Select(item => entity.Equipment.IndexOf(item)).Where(index => index >= 0).ToArray()) - .ToArray() ?? Array.Empty>() + .ToArray() ?? Array.Empty>(), + StatGrids = ProjectEntityStatGrids(entity) + }; + } + + private static AetheriaRuntimeEntityStatGridCommit[] ProjectEntityStatGrids(Entity entity) + { + return new[] + { + ProjectFloatGrid("temperature", entity.Temperature), + ProjectFloatGrid("thermal_mass", entity.ThermalMass), + ProjectFloatGrid("armor", entity.Armor), + ProjectFloatGrid("max_armor", entity.MaxArmor), + ProjectBool2Grid("hull_conductivity_x", entity.HullConductivity, axis: 0), + ProjectBool2Grid("hull_conductivity_y", entity.HullConductivity, axis: 1) + } + .Where(grid => grid != null) + .ToArray(); + } + + private static AetheriaRuntimeEntityStatGridCommit ProjectFloatGrid(string name, float[,] values) + { + if (values == null) + return null; + + var width = values.GetLength(0); + var height = values.GetLength(1); + var flattened = new double[width * height]; + var index = 0; + for (var y = 0; y < height; y++) + for (var x = 0; x < width; x++) + flattened[index++] = values[x, y]; + + return new AetheriaRuntimeEntityStatGridCommit + { + Name = name, + Width = width, + Height = height, + Values = flattened + }; + } + + private static AetheriaRuntimeEntityStatGridCommit ProjectBool2Grid(string name, bool2[,] values, int axis) + { + if (values == null) + return null; + + var width = values.GetLength(0); + var height = values.GetLength(1); + var flattened = new double[width * height]; + var index = 0; + for (var y = 0; y < height; y++) + for (var x = 0; x < width; x++) + flattened[index++] = (axis == 0 ? values[x, y].x : values[x, y].y) ? 1.0 : 0.0; + + return new AetheriaRuntimeEntityStatGridCommit + { + Name = name, + Width = width, + Height = height, + Values = flattened }; } diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs index c9d37c630..6684fd028 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs @@ -525,5 +525,24 @@ namespace GameCult.Aetheria.State.Unity [Key(14)] public IReadOnlyList> WeaponGroups { get; set; } = Array.Empty>(); + + [Key(15)] + public IReadOnlyList StatGrids { get; set; } = Array.Empty(); + } + + [MessagePackObject] + public sealed class AetheriaRuntimeEntityStatGridCommit + { + [Key(0)] + public string Name { get; set; } = ""; + + [Key(1)] + public int Width { get; set; } + + [Key(2)] + public int Height { get; set; } + + [Key(3)] + public IReadOnlyList Values { get; set; } = Array.Empty(); } } diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index def2d152c..4997c0e09 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -135,6 +135,10 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. visual parameters now survive through the typed pending commit lane into `AetheriaZoneState`. `RuntimeZoneBlueprint` feeds this projector, but it is no longer the only place generated celestial graph facts can live. +- Run checkpoint entity snapshots include typed simulation stat grids for + temperature, thermal mass, armor, max armor, and hull-conductivity axes. + `RuntimeEntityBlueprint` still exists for construction/loadout projection, + but those live hull grids no longer survive only as blueprint fields. - `Aetheria.State` now defines `AetheriaLoadoutTemplate` as the typed Verse replacement for bespoke `.loadout` files. It stores structured hull, equipment, cargo bay, docking bay, child-entity, assignment, and weapon-group @@ -738,9 +742,13 @@ First Aetheria surfaces to publish: - Done: extend run checkpoint commits and smoke coverage to carry typed zone orbit/body rows into `AetheriaZoneState`, so generated celestial graph facts no longer live only inside `RuntimeZoneBlueprint`. + - Done: extend run checkpoint commits and smoke coverage to carry typed + entity simulation stat grids into `AetheriaEntitySnapshot`, so + temperature/armor/conductivity no longer live only in runtime blueprints. - Remaining: add typed documents/mappers for runtime object graphs, - typed behavior factory construction, simulation state, and any catalog - fields not covered by the stable scalar/fingerprint/payload pass. + typed behavior factory construction, behavior-private simulation state, + and any catalog fields not covered by the stable scalar/fingerprint/ + payload pass. 4. Runtime cutover - Done: add a Unity-facing typed catalog read facade and smoke proving it can @@ -1130,9 +1138,9 @@ First Aetheria surfaces to publish: resolution, including full player settings as the `PlayerSettings.msgpack` replacement, loadout templates as the `.loadout` replacement, and a run -> zone -> entity snapshot graph as the `.zone` replacement. The zone smoke - includes orbit/body rows for generated celestial state. It also proves - `aetheria.runtime_session.v1` is advertised and survives reopen as the typed - daemon-session signal. + includes orbit/body rows for generated celestial state, and the entity smoke + includes typed simulation stat grids. It also proves `aetheria.runtime_session.v1` + is advertised and survives reopen as the typed daemon-session signal. - CultMesh smoke proves node start, typed put/get, subscription, flush, and reopen. - Eve surface smoke proves provider-owned surface documents are generated from