diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index bceb553d2..0ebdf5bdd 100644 Binary files a/.voidbot/state/aetheria.cc and b/.voidbot/state/aetheria.cc differ diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index efafe588c..c73a41408 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -847,6 +847,7 @@ static void RequireMainMenuContinueRunState(string root) "CreateEntityConstructionBlueprint(entitySnapshot, true)", "BindToEntity(entity)", "RestoreActiveConsumablesFromTypedEntitySnapshot(entity, entitySnapshot)", + "entity.RestoreStatGrids(entitySnapshot.StatGrids)", "RestoreThermalExposure((float)entitySnapshot.Heatstroke, (float)entitySnapshot.Hypothermia)", "entity.HeatsinksEnabled = entitySnapshot.HeatsinksEnabled", "ContinueRunState = null", @@ -891,6 +892,8 @@ static void RequireMainMenuContinueRunState(string root) { "RestoreThermalExposure", "RestoreActiveConsumable", + "RestoreStatGrids", + "RestoreHullConductivityGrid", "new ConsumableItemEffect(item, this, remainingDuration, duration)" }; var missingEntityRestoreSymbols = requiredEntityRestoreSymbols diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index 662968395..0ff4ab401 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -179,7 +179,8 @@ persist hull simulation grids into `AetheriaEntitySnapshot`, so `EntityConstructionBlueprint` is no longer the only surface carrying those live values. Continue restore lowers the current player entity from the exact typed entity snapshot record, including position, velocity, shutdown/heatsink state, -thermal exposure, and active consumable timers. Broader runtime object graphs +thermal exposure, active consumable timers, and typed stat grids for +temperature, thermal mass, armor, max armor, and hull conductivity. Broader runtime object graphs and behavior-private simulation state remain legacy until dedicated typed runtime documents exist. Live behavior instances expose typed behavior kind and group through `Behavior.Kind` and `Behavior.Group`; behavior construction now reads typed payload fields through diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 18447c545..591a5b092 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -2544,6 +2544,7 @@ public class ActionGameManager : MonoBehaviour Zone.Entities.Add(entity); entity.Activate(); entity.HeatsinksEnabled = entitySnapshot.HeatsinksEnabled; + entity.RestoreStatGrids(entitySnapshot.StatGrids); entity.RestoreThermalExposure((float)entitySnapshot.Heatstroke, (float)entitySnapshot.Hypothermia); RestoreActiveConsumablesFromTypedEntitySnapshot(entity, entitySnapshot); BindToEntity(entity); diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index f57559215..91cb9a549 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -329,11 +329,81 @@ public abstract class Entity _activeConsumables.Add(new ConsumableItemEffect(item, this, remainingDuration, duration)); } + public void RestoreStatGrids(IReadOnlyList grids) + { + if (grids == null) + return; + + foreach (var grid in grids) + { + switch (grid.Name) + { + case "temperature": + RestoreFloatGrid(grid, Temperature); + RestoreFloatGrid(grid, NewTemperature); + break; + case "thermal_mass": + RestoreFloatGrid(grid, ThermalMass); + break; + case "armor": + RestoreFloatGrid(grid, Armor); + break; + case "max_armor": + RestoreFloatGrid(grid, MaxArmor); + break; + case "hull_conductivity_x": + RestoreHullConductivityGrid(grid, axis: 0); + break; + case "hull_conductivity_y": + RestoreHullConductivityGrid(grid, axis: 1); + break; + } + } + } + public ConsumableItemEffect FindActiveConsumable(string itemKey) { return _activeConsumables.FirstOrDefault(ac => ac.Item?.ItemKey == itemKey); } + private static void RestoreFloatGrid(AetheriaRuntimeEntityStatGridSnapshot grid, float[,] target) + { + if (!CanRestoreGrid(grid, target)) + return; + + var index = 0; + for (var y = 0; y < grid.Height; y++) + for (var x = 0; x < grid.Width; x++) + target[x, y] = (float)grid.Values[index++]; + } + + private void RestoreHullConductivityGrid(AetheriaRuntimeEntityStatGridSnapshot grid, int axis) + { + if (!CanRestoreGrid(grid, HullConductivity)) + return; + + var index = 0; + for (var y = 0; y < grid.Height; y++) + for (var x = 0; x < grid.Width; x++) + { + var conductivity = HullConductivity[x, y]; + if (axis == 0) + conductivity.x = grid.Values[index++] >= 0.5; + else + conductivity.y = grid.Values[index++] >= 0.5; + HullConductivity[x, y] = conductivity; + } + } + + private static bool CanRestoreGrid(AetheriaRuntimeEntityStatGridSnapshot grid, T[,] target) + { + return grid != null && + target != null && + grid.Width == target.GetLength(0) && + grid.Height == target.GetLength(1) && + grid.Values?.Count == grid.Width * grid.Height; + } + public bool CanActivateConsumable(AetheriaRuntimeCatalogItem item) { var itemKey = GetItemKey(item); diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 56c2b59a4..ebf7c4556 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -975,8 +975,10 @@ First Aetheria surfaces to publish: through the existing construction blueprint path, restores hull, equipment, cargo, docking contents, weapon groups, position, direction, velocity, shutdown override, heatsink toggle, tractor power, - heatstroke/hypothermia exposure, and active consumable item/timer rows, - then binds the lowered entity as the current player ship. + heatstroke/hypothermia exposure, active consumable item/timer rows, + and typed stat grids for temperature, thermal mass, armor, max armor, + and hull-conductivity axes, then binds the lowered entity as the current + player ship. - Remaining: add typed documents/mappers for runtime object graphs, complete full Continue/run entity graph reconstruction from typed state for non-current entities, child/docked entity activation, targets,