From 3c4fe6fd100bfa5b8c2b305a79a494f90a5acfd9 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 14 Jun 2026 14:08:59 +0100 Subject: [PATCH] Persist behavior progress in entity snapshots --- .voidbot/state/aetheria.cc | Bin 86857 -> 86651 bytes Aetheria.State.Unity.Smoke/Program.cs | 25 +++++++++++ .../AetheriaRuntimeCommitLogApplier.cs | 18 +++++++- .../AetheriaRuntimeStateDocuments.cs | 22 ++++++++++ Assets/Scripts/Gameplay/ActionGameManager.cs | 41 +++++++++++++++++- .../AetheriaRuntimeStateCommitDocument.cs | 22 ++++++++++ docs/aetheria-perfect-machine-map.md | 14 ++++-- 7 files changed, 137 insertions(+), 5 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index b7a170583dd7afaecebe50a52a853784d9ad4cbb..3c04805430a166f7e37b857fc675b553bf89fd22 100644 GIT binary patch delta 1474 zcmZuxL5vhd6iw{_LGWS%VuD!<51SBnhIMz?S$09(WkEKgPKYZBF-lGM@9AQ@tJ+Y1PIXtz3oXkndr^42XCH?2hLphRXyFUvdLspUG?hM`|rR1e|xz9 z+5P=L-k&{Wt&o&lwEwJ-nHe+8AfzRRmKdt!wr)KL62{X% z$X&a1j=XnkZxr2vp$jpja$A6+TU>;*lQk}3XSNRi|L+3JL|8vOU`Y=4=^QySLNd1? zFuFdBluRjnp7RV@H@Sh7y2~sud;rZr3Z18{mq7KRrY2^Fa$!IiE(J@HA%&exYM>k4 zi6Cneg=T%Q)roM|?C3n1KIo864ExP_GBY9{#avVT327*!flRXmO#L2;%m)lNv~m9_ z?q$xIo@$V7lY4 zE*%~Hx{0}$;*?@hDNw=)+4TX-jd3?OPIKX2af#No(z%LQ0J=rjrI$;aJc=k&J#G|J zLqrx*MVMHKq6#A^H!C#CO|DSVk4xhgS_U~fLB}#rLK-M=@)qWG)$xP`OaJXKa7)Yy0E^(I;lsA>sm@jzxRa#IdL;H};En$j!IrOIW~!6g*(b9v8G= z84@$jC-#+9@?q-|s#RF`1(SI*dAi=mDf-fWyGC9mdVK1&*T>Vh589ts$?2t~)eI}M zCqbXEm#bz~a?q9>A>FH2-)9+B5J-i}zL=u#RCHA49j_o|TsW_l$jZhc^o+gJA%9PQ z&_y$$yxZKw6|NF(_mg$9MNYLh1vf+5Vhk~DC-}~Y>{pMrMu>GrMv(GM**5PVkwmakB8^`Ja+L?C) w)F$tepX$xC3zMmOz;>^Yv^r?d`2+js6*8*kZF|m*<=rng$di|9l~yzqf`i?wq^M zLel5jlq19Ypjg&~ZA?QJB7&~m-FhPE23*CJ3Gm>h9|&2*c9%65@s^37#*YisLunW#ssWd<;09n)%Ho3G+X z1=2-=kxf5&0tCTV0+JzuKn2m zvX0I-_br!66pZui+uRmK%H5rWg8e2jT3Pb0Ne|pj70Y9=yn!kYk25u>kA9w+n`G?b tVv?~*_ grid.Name == "temperature" && grid.Values.Length == 2 && grid.Values[1] == 281.0) && diff --git a/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs b/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs index c6907d188..8f3884892 100644 --- a/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs +++ b/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs @@ -440,10 +440,26 @@ public static class AetheriaRuntimeCommitLogApplier .Select(group => new AetheriaWeaponGroupSnapshot { EquipmentIndices = group }) .ToArray(), StatGrids = ToEntityStatGrids(entity.StatGrids), - ActiveConsumables = ToActiveConsumables(entity.ActiveConsumables) + ActiveConsumables = ToActiveConsumables(entity.ActiveConsumables), + BehaviorProgress = ToBehaviorProgress(entity.BehaviorProgress) }; } + private static AetheriaBehaviorProgressSnapshot[] ToBehaviorProgress( + IReadOnlyList? progress) + { + return (progress ?? Array.Empty()) + .Select(entry => new AetheriaBehaviorProgressSnapshot + { + OwnerKind = entry.OwnerKind ?? "", + OwnerIndex = entry.OwnerIndex, + BehaviorIndex = entry.BehaviorIndex, + BehaviorKind = entry.BehaviorKind ?? "", + Progress = entry.Progress + }) + .ToArray(); + } + private static AetheriaActiveConsumableSnapshot[] ToActiveConsumables( IReadOnlyList? consumables) { diff --git a/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs b/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs index fcd9336ba..2ba8c0e6e 100644 --- a/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs +++ b/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs @@ -482,6 +482,9 @@ public sealed class AetheriaEntitySnapshot [Key(20)] public AetheriaActiveConsumableSnapshot[] ActiveConsumables { get; set; } = []; + + [Key(21)] + public AetheriaBehaviorProgressSnapshot[] BehaviorProgress { get; set; } = []; } [MessagePackObject] @@ -534,6 +537,25 @@ public sealed class AetheriaActiveConsumableSnapshot public double Duration { get; set; } } +[MessagePackObject] +public sealed class AetheriaBehaviorProgressSnapshot +{ + [Key(0)] + public string OwnerKind { get; set; } = ""; + + [Key(1)] + public int OwnerIndex { get; set; } = -1; + + [Key(2)] + public int BehaviorIndex { get; set; } = -1; + + [Key(3)] + public string BehaviorKind { get; set; } = ""; + + [Key(4)] + public double Progress { get; set; } +} + [MessagePackObject] public sealed class AetheriaActionBarBinding { diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index a43d8d701..be72265ac 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -787,10 +787,49 @@ public class ActionGameManager : MonoBehaviour .Select(group => (IReadOnlyList)group.items.Select(item => entity.Equipment.IndexOf(item)).Where(index => index >= 0).ToArray()) .ToArray() ?? Array.Empty>(), StatGrids = ProjectEntityStatGrids(entity), - ActiveConsumables = ProjectActiveConsumables(entity) + ActiveConsumables = ProjectActiveConsumables(entity), + BehaviorProgress = ProjectBehaviorProgress(entity) }; } + private static AetheriaRuntimeBehaviorProgressCommit[] ProjectBehaviorProgress(Entity entity) + { + var progress = new List(); + + for (var ownerIndex = 0; ownerIndex < entity.Equipment.Count; ownerIndex++) + progress.AddRange(ProjectBehaviorProgress("equipment", ownerIndex, entity.Equipment[ownerIndex].Behaviors)); + + var activeConsumables = entity.ActiveConsumables; + for (var ownerIndex = 0; ownerIndex < activeConsumables.Count; ownerIndex++) + progress.AddRange(ProjectBehaviorProgress("active_consumable", ownerIndex, activeConsumables[ownerIndex].Behaviors)); + + return progress.ToArray(); + } + + private static IEnumerable ProjectBehaviorProgress( + string ownerKind, + int ownerIndex, + IReadOnlyList behaviors) + { + if (behaviors == null) + yield break; + + for (var behaviorIndex = 0; behaviorIndex < behaviors.Count; behaviorIndex++) + { + if (!(behaviors[behaviorIndex] is IProgressBehavior progressBehavior)) + continue; + + yield return new AetheriaRuntimeBehaviorProgressCommit + { + OwnerKind = ownerKind, + OwnerIndex = ownerIndex, + BehaviorIndex = behaviorIndex, + BehaviorKind = behaviors[behaviorIndex].Data?.Kind ?? "", + Progress = progressBehavior.Progress + }; + } + } + private static AetheriaRuntimeActiveConsumableCommit[] ProjectActiveConsumables(Entity entity) { return entity.ActiveConsumables? diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs index 8e01bd9f2..964fd0046 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs @@ -558,6 +558,9 @@ namespace GameCult.Aetheria.State.Unity [Key(25)] public IReadOnlyList ActiveConsumables { get; set; } = Array.Empty(); + + [Key(26)] + public IReadOnlyList BehaviorProgress { get; set; } = Array.Empty(); } [MessagePackObject] @@ -591,4 +594,23 @@ namespace GameCult.Aetheria.State.Unity [Key(3)] public double Duration { get; set; } } + + [MessagePackObject] + public sealed class AetheriaRuntimeBehaviorProgressCommit + { + [Key(0)] + public string OwnerKind { get; set; } = ""; + + [Key(1)] + public int OwnerIndex { get; set; } = -1; + + [Key(2)] + public int BehaviorIndex { get; set; } = -1; + + [Key(3)] + public string BehaviorKind { get; set; } = ""; + + [Key(4)] + public double Progress { get; set; } + } } diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 0327f4869..813fb14d9 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -142,6 +142,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. They also carry public runtime session state: velocity, target entity reference, active flag, heatsink toggle, shutdown override, tractor power, heatstroke/hypothermia accumulators, and active consumable item/timer rows. + Equipped-item and active-consumable behaviors that intentionally expose + `IProgressBehavior` now publish typed progress rows keyed by owner kind, + owner index, behavior index, behavior kind, and progress value. `RuntimeEntityBlueprint` still exists for construction/loadout projection, but those live hull grids and session scalars are not blueprint fields and cannot be restored by the old blueprint projector path. @@ -761,13 +764,17 @@ First Aetheria surfaces to publish: entity session state into `AetheriaEntitySnapshot`: velocity, target references, active/toggle scalars, thermal injury accumulators, and active consumable timers. + - Done: extend run checkpoint commits and smoke coverage to carry typed + behavior progress rows for equipped-item and active-consumable behaviors + that expose `IProgressBehavior`. - Done: cut live simulation grids out of `RuntimeEntityBlueprint`; loadout and construction templates no longer capture or restore temperature, armor, max-armor, or hull-conductivity state. - Remaining: add typed documents/mappers for runtime object graphs, typed behavior factory construction, behavior-private simulation state - such as weapon cooldown/charge/ammo and sensor/shield progress, and any - catalog fields not covered by the stable scalar/fingerprint/payload pass. + such as weapon cooldown/charge/ammo internals and sensor ping 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 @@ -1159,7 +1166,8 @@ First Aetheria surfaces to publish: zone -> entity snapshot graph as the `.zone` replacement. The zone smoke includes orbit/body rows for generated celestial state, and the entity smoke includes typed simulation stat grids, public entity session scalars, and - active consumable timer rows. The Unity runtime smoke also proves + active consumable timer rows, plus typed behavior progress rows for + `IProgressBehavior` surfaces. The Unity runtime smoke also proves package-owned readback of typed loadout templates from `.cc` records. It also proves `aetheria.runtime_session.v1` is advertised and survives reopen as the typed daemon-session signal.