diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 6714b531d..d627d6c65 100644 Binary files a/.voidbot/state/aetheria.cc and b/.voidbot/state/aetheria.cc differ diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index 3c8102e49..3071b78a7 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -126,7 +126,9 @@ 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. +documents exist. Live behavior instances expose typed behavior kind through +`Behavior.Kind`; the remaining `BehaviorData` objects are construction configs, +not runtime identity owners. 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 diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 183a6d7a1..7fa8e52bd 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -1041,7 +1041,7 @@ public class ActionGameManager : MonoBehaviour state.OwnerKind = ownerKind; state.OwnerIndex = ownerIndex; state.BehaviorIndex = behaviorIndex; - state.BehaviorKind = behavior.Data?.Kind ?? ""; + state.BehaviorKind = behavior.Kind; yield return state; } } @@ -1079,7 +1079,7 @@ public class ActionGameManager : MonoBehaviour OwnerKind = ownerKind, OwnerIndex = ownerIndex, BehaviorIndex = behaviorIndex, - BehaviorKind = weapon.Data?.Kind ?? "", + BehaviorKind = weapon.Kind, Firing = weapon.Firing, Ammo = weapon.Ammo }; @@ -1149,7 +1149,7 @@ public class ActionGameManager : MonoBehaviour OwnerKind = ownerKind, OwnerIndex = ownerIndex, BehaviorIndex = behaviorIndex, - BehaviorKind = behaviors[behaviorIndex].Data?.Kind ?? "", + BehaviorKind = behaviors[behaviorIndex].Kind, Progress = progressBehavior.Progress }; } diff --git a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs index 9e72b19b3..fd0424373 100644 --- a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs +++ b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs @@ -13,6 +13,7 @@ using static Unity.Mathematics.noise; public abstract class Behavior { public BehaviorData Data { get; } + public string Kind { get; } public EquippedItem Item { get; } private ConsumableItemEffect Consumable { get; } protected ItemManager ItemManager { get; } @@ -45,6 +46,7 @@ public abstract class Behavior protected Behavior(BehaviorData data, EquippedItem item) { Data = data; + Kind = data?.Kind ?? ""; Item = item; ItemManager = Item.ItemManager; } @@ -52,6 +54,7 @@ public abstract class Behavior protected Behavior(BehaviorData data, ConsumableItemEffect consumable) { Data = data; + Kind = data?.Kind ?? ""; Consumable = consumable; ItemManager = consumable.Entity.ItemManager; } diff --git a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs index af3904052..9b0a66a4d 100644 --- a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs +++ b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs @@ -61,7 +61,7 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa _stats = Entity.Equipment .Where(HasRequiredBehavior) .SelectMany(gear => gear.Behaviors ?? Array.Empty()) - .Where(behavior => BehaviorKindMatches(behavior.Data.Kind, _data.Stat.Target)) + .Where(behavior => BehaviorKindMatches(behavior.Kind, _data.Stat.Target)) .Select(FindTargetStat) .Where(stat => stat != null) .ToArray(); @@ -103,7 +103,7 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa { return string.IsNullOrWhiteSpace(_data.RequireBehavior) || (gear?.Behaviors ?? Array.Empty()) - .Any(behavior => BehaviorKindMatches(behavior.Data.Kind, _data.RequireBehavior)); + .Any(behavior => BehaviorKindMatches(behavior.Kind, _data.RequireBehavior)); } private void ApplyModifier() diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 0032d88f6..297d7705d 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -618,6 +618,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. type selection now uses an explicit runtime catalog map instead of `UnionAttribute` reflection, and the temporary behavior config constructor map is keyed by typed behavior payload kind rather than legacy union key. + Live `Behavior` instances expose their typed payload kind directly, so runtime + state projection and stat-modifier matching no longer reach back through + `BehaviorData.Kind` for behavior identity. Runtime item category classification uses package-owned `AetheriaRuntimeItemCategories` tokens; gameplay code should not ask C# legacy DTO class names to classify typed catalog rows. The typed state @@ -987,6 +990,9 @@ First Aetheria surfaces to publish: - Done: move `StatModifier` behavior kind/family matching onto `AetheriaRuntimeBehaviorMetadataCatalog`; the behavior only normalizes migrated `*Data` tokens before asking the package-owned metadata owner. + - Done: move live behavior identity reads from the temporary `BehaviorData` + config bridge onto `Behavior.Kind`, so state snapshots, weapon snapshots, + progress rows, and stat-modifier matching use runtime instance identity. - Done: delete the legacy `Behaviors` lists from `ConsumableItemData` and `EquippableItemData`; item DTOs can no longer carry behavior config state. - Done: move runtime blueprint price aggregation and conductivity restore