diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 21d152db9..fd5dbed1b 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 45a6c2e4d..a4e1e2bce 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -170,8 +170,10 @@ values. Broader runtime object graphs, typed behavior factory construction, 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`; the remaining -`RuntimeBehaviorConfig` objects are construction configs, not runtime identity -owners. `ItemManager` currently owns the explicit typed-payload-to-config bridge. +`RuntimeBehaviorConfig` objects are private construction configs, not runtime +identity owners or a public behavior API. Stat modifiers ask live behavior +instances for target stats instead of reading behavior config objects directly. +`ItemManager` currently owns the explicit typed-payload-to-config bridge. 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/ServerShared/Behaviors/Behaviors.cs b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs index 9e422182c..6c72328ce 100644 --- a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs +++ b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs @@ -12,7 +12,7 @@ using static Unity.Mathematics.noise; public abstract class Behavior { - public RuntimeBehaviorConfig Config { get; } + private readonly RuntimeBehaviorConfig _config; public string Kind { get; } public int Group { get; } public EquippedItem Item { get; } @@ -46,7 +46,7 @@ public abstract class Behavior protected Behavior(RuntimeBehaviorConfig config, EquippedItem item) { - Config = config; + _config = config; Kind = config?.Kind ?? ""; Group = config?.Group ?? 0; Item = item; @@ -55,7 +55,7 @@ public abstract class Behavior protected Behavior(RuntimeBehaviorConfig config, ConsumableItemEffect consumable) { - Config = config; + _config = config; Kind = config?.Kind ?? ""; Group = config?.Group ?? 0; Consumable = consumable; @@ -63,6 +63,23 @@ public abstract class Behavior } public float Evaluate(PerformanceStat stat) => Item?.Evaluate(stat) ?? Consumable.Evaluate(stat); + + public bool TryGetPerformanceStat(string statName, out PerformanceStat stat) + { + stat = null; + if (_config == null || string.IsNullOrWhiteSpace(statName)) + { + return false; + } + + var statField = _config + .GetType() + .GetFields() + .FirstOrDefault(field => field.FieldType == typeof(PerformanceStat) && field.Name == statName); + stat = statField?.GetValue(_config) as PerformanceStat; + return stat != null; + } + protected void AddHeat(float heat) => Item?.AddHeat(heat); // TODO: Heat for Consumables protected void CauseDamage(float damage) diff --git a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs index 74d8162e7..93920cde4 100644 --- a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs +++ b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs @@ -18,7 +18,6 @@ public class StatModifierConfig : RuntimeBehaviorConfig [Inspectable] public StatModifierType Type; - [InspectableType(typeof(RuntimeBehaviorConfig))] public string RequireBehavior; public override Behavior CreateInstance(EquippedItem item) @@ -69,14 +68,7 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa private PerformanceStat FindTargetStat(Behavior behavior) { - var data = behavior.Config; - var statField = data - .GetType() - .GetFields() - .Where(f => f.FieldType == typeof(PerformanceStat)) - .FirstOrDefault(f => f.Name == _data.Stat.Stat); - - return statField?.GetValue(data) as PerformanceStat; + return behavior.TryGetPerformanceStat(_data.Stat.Stat, out var stat) ? stat : null; } private static bool BehaviorKindMatches(string runtimeKind, string expectedKind) @@ -153,7 +145,6 @@ public enum StatModifierType [Inspectable] public class StatReference { - [InspectableType(typeof(RuntimeBehaviorConfig))] public string Target; [Inspectable] diff --git a/Assets/Scripts/ServerShared/RuntimeProjection/Attributes.cs b/Assets/Scripts/ServerShared/RuntimeProjection/Attributes.cs index f14fccd1b..206a819d7 100644 --- a/Assets/Scripts/ServerShared/RuntimeProjection/Attributes.cs +++ b/Assets/Scripts/ServerShared/RuntimeProjection/Attributes.cs @@ -49,16 +49,6 @@ public class InspectableRangedIntAttribute : PreferredInspectorAttribute } } -public class InspectableTypeAttribute : PreferredInspectorAttribute -{ - public readonly Type Type; - - public InspectableTypeAttribute(Type type) - { - Type = type; - } -} - public class OrderAttribute : Attribute { public int Order; diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 54b7f5295..32baf62d3 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -243,7 +243,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. `StatModifier` requirement and stat-target lookup now inspects the live equipped behavior instances and asks package-owned typed behavior metadata for kind/family matching, not a freshly rebuilt config list or a - behavior-local class taxonomy. The unused `TradeMenuDebug` script has been + behavior-local class taxonomy. Live behaviors no longer expose their + construction config object as a public runtime authority; stat targeting now + crosses a behavior-owned stat lookup. The unused `TradeMenuDebug` script has been deleted instead of preserving an old uGUI debug path that turned typed trade rows back into legacy `ItemData` objects. That hydration now comes from typed state, not `AetherDB.msgpack`. The surviving trade menu @@ -1402,9 +1404,12 @@ First Aetheria surfaces to publish: construction machinery. - Done: rename the temporary behavior construction DTO family from `BehaviorData`/`*Data` to `RuntimeBehaviorConfig`/`*Config`; live - `Behavior` instances expose `Config`, while typed behavior kind strings - such as `Cockpit`, `TurretController`, and `Capacitor` remain stable - catalog facts rather than class-name-derived selectors. + `Behavior` instances expose typed kind/group values while typed behavior + kind strings such as `Cockpit`, `TurretController`, and `Capacitor` remain + stable catalog facts rather than class-name-derived selectors. + - Done: remove the public `Behavior.Config` runtime API; stat modifiers ask + behavior instances for target performance stats instead of reflecting over + exposed construction config objects. - Done: replace `ItemManager` behavior config reflection with an explicit typed behavior-kind mapper. - Done: delete `LegacyPayloadKeyAttribute` from live Unity source after