diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 1923686de..955bd9ee6 100644 Binary files a/.voidbot/state/aetheria.cc and b/.voidbot/state/aetheria.cc differ diff --git a/Aetheria.State.Smoke/Program.cs b/Aetheria.State.Smoke/Program.cs index 1ae940fa3..b1bc1c373 100644 --- a/Aetheria.State.Smoke/Program.cs +++ b/Aetheria.State.Smoke/Program.cs @@ -231,6 +231,8 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s } ], DockingBayAssignments = [-1], + Visibility = 12.75, + VisibilitySourceCount = 3, WeaponGroups = [ new AetheriaWeaponGroupSnapshot @@ -623,6 +625,8 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether entitySnapshot.CargoContents[0].Items[0].Item.Quantity != 7 || entitySnapshot.DockingBayAssignments.Length != 1 || entitySnapshot.DockingBayAssignments[0] != -1 || + entitySnapshot.Visibility != 12.75 || + entitySnapshot.VisibilitySourceCount != 3 || entitySnapshot.WeaponGroups.Length != 1 || entitySnapshot.WeaponStates.Length != 1 || entitySnapshot.WeaponStates[0].BehaviorKind != "LockWeapon" || diff --git a/Aetheria.State.Unity.Smoke/Program.cs b/Aetheria.State.Unity.Smoke/Program.cs index a965e34df..fd9e642c4 100644 --- a/Aetheria.State.Unity.Smoke/Program.cs +++ b/Aetheria.State.Unity.Smoke/Program.cs @@ -357,6 +357,8 @@ try } }, DockingBayAssignments = new[] { -1 }, + Visibility = 12.75, + VisibilitySourceCount = 3, WeaponGroups = new[] { new[] { 0 } }, ActiveConsumables = new[] { @@ -689,6 +691,8 @@ try entity.CargoContents[0].Items[0].Item.Quantity == 7 && entity.DockingBayAssignments.Length == 1 && entity.DockingBayAssignments[0] == -1 && + entity.Visibility == 12.75 && + entity.VisibilitySourceCount == 3 && entity.ActiveConsumables[0].ItemKey == "aetheria.item_definition:legacy:smoke:consumable" && entity.ActiveConsumables[0].RemainingDuration == 3.0 && entity.BehaviorProgress.Length == 2 && @@ -812,6 +816,8 @@ try packageEntities[0].CargoContents[0].Items[0].Item.Quantity != 7 || packageEntities[0].DockingBayAssignments.Count != 1 || packageEntities[0].DockingBayAssignments[0] != -1 || + packageEntities[0].Visibility != 12.75 || + packageEntities[0].VisibilitySourceCount != 3 || packageEntities[0].ActiveConsumables[0].ItemKey != "aetheria.item_definition:legacy:smoke:consumable" || packageEntities[0].BehaviorProgress.Count != 2 || packageEntities[0].WeaponStates.Count != 4 || diff --git a/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs b/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs index 869041a94..6622331f1 100644 --- a/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs +++ b/Aetheria.State/AetheriaRuntimeCommitLogApplier.cs @@ -458,7 +458,9 @@ public static class AetheriaRuntimeCommitLogApplier BehaviorStates = ToBehaviorStates(entity.BehaviorStates), CargoContents = ToCargoBays(entity.CargoContents), DockingBayContents = ToCargoBays(entity.DockingBayContents), - DockingBayAssignments = ToIntArray(entity.DockingBayAssignments) + DockingBayAssignments = ToIntArray(entity.DockingBayAssignments), + Visibility = entity.Visibility, + VisibilitySourceCount = entity.VisibilitySourceCount }; } diff --git a/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs b/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs index ce594a17d..bbd1df5d4 100644 --- a/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs +++ b/Aetheria.State/Documents/AetheriaRuntimeStateDocuments.cs @@ -503,6 +503,12 @@ public sealed class AetheriaEntitySnapshot [Key(26)] public int[] DockingBayAssignments { get; set; } = []; + + [Key(27)] + public double Visibility { get; set; } + + [Key(28)] + public int VisibilitySourceCount { get; set; } } [MessagePackObject] diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 8bb345c85..4f7061103 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -785,6 +785,8 @@ public class ActionGameManager : MonoBehaviour DockingBayAssignments = entity.DockingBays? .Select(bay => entity.Children.IndexOf(bay.DockedShip)) .ToArray() ?? Array.Empty(), + Visibility = entity.Visibility, + VisibilitySourceCount = entity.VisibilitySources.Count, ChildEntityIndices = entity.Children? .Select(child => zone.Entities.IndexOf(child)) .Where(index => index >= 0) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs index f20145783..2a2bc4d48 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs @@ -786,7 +786,9 @@ namespace GameCult.Aetheria.State.Unity IReadOnlyList behaviorStates, IReadOnlyList cargoContents, IReadOnlyList dockingBayContents, - IReadOnlyList dockingBayAssignments) + IReadOnlyList dockingBayAssignments, + double visibility, + int visibilitySourceCount) { Name = name; Kind = kind; @@ -819,6 +821,8 @@ namespace GameCult.Aetheria.State.Unity CargoContents = cargoContents; DockingBayContents = dockingBayContents; DockingBayAssignments = dockingBayAssignments; + Visibility = visibility; + VisibilitySourceCount = visibilitySourceCount; } public string Name { get; } @@ -852,6 +856,8 @@ namespace GameCult.Aetheria.State.Unity public IReadOnlyList CargoContents { get; } public IReadOnlyList DockingBayContents { get; } public IReadOnlyList DockingBayAssignments { get; } + public double Visibility { get; } + public int VisibilitySourceCount { get; } } public sealed class AetheriaRuntimeActionBarBindingSnapshot diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogStore.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogStore.cs index 96631cb02..9a0f75fd7 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogStore.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogStore.cs @@ -535,7 +535,9 @@ namespace GameCult.Aetheria.State.Unity var cargoContents = ReadFieldCargoBayLoadouts(ref reader, fields, 24); var dockingBayContents = ReadFieldCargoBayLoadouts(ref reader, fields, 25); var dockingBayAssignments = ReadFieldInt32Array(ref reader, fields, 26); - SkipRemaining(ref reader, fields, 27); + var visibility = ReadFieldDouble(ref reader, fields, 27); + var visibilitySourceCount = ReadFieldInt32(ref reader, fields, 28); + SkipRemaining(ref reader, fields, 29); return new AetheriaRuntimeEntitySnapshot( name, kind, @@ -567,7 +569,9 @@ namespace GameCult.Aetheria.State.Unity behaviorStates, cargoContents, dockingBayContents, - dockingBayAssignments); + dockingBayAssignments, + visibility, + visibilitySourceCount); } private static Vector2Value ReadFieldVector2(ref MessagePackReader reader, int fields, int index) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs index 39a638a52..02d93c112 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs @@ -579,6 +579,12 @@ namespace GameCult.Aetheria.State.Unity [Key(31)] public IReadOnlyList DockingBayAssignments { get; set; } = Array.Empty(); + + [Key(32)] + public double Visibility { get; set; } + + [Key(33)] + public int VisibilitySourceCount { get; set; } } [MessagePackObject] diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 6c5ee6933..05abfcc92 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -152,7 +152,8 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. temperature, thermal mass, armor, max armor, and hull-conductivity axes. 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. + heatstroke/hypothermia accumulators, aggregate visibility/source-count state, + and active consumable item/timer rows. Entity equipment, cargo-bay, and docking-bay slot rows preserve item-instance facts needed for restore: item key, quality, durability, and quantity. Those facts are no longer discarded when pending checkpoint commands become @@ -846,6 +847,9 @@ First Aetheria surfaces to publish: quantity now survive canonical state and Unity package readback. - Done: preserve cargo bay contents, docking bay contents, and docking bay child assignments in typed entity snapshots. + - Done: preserve aggregate entity visibility and visibility-source count in + typed entity snapshots, so `Entity.VisibilitySources` no longer hides + untyped session pressure. - Remaining: add typed documents/mappers for runtime object graphs, typed behavior factory construction, remaining behavior-private state not covered by progress, weapon, sensor, radiator, reactor, or capacitor rows,