Delete runtime item DTO hydration
This commit is contained in:
parent
4d5b6cda22
commit
c0d0fbf656
7 changed files with 49 additions and 327 deletions
Binary file not shown.
|
|
@ -10,13 +10,11 @@ public interface IRuntimeItemProjectionReader
|
|||
{
|
||||
AetheriaRuntimeCatalogItem GetRuntimeItem(Guid guid);
|
||||
IReadOnlyList<BehaviorData> GetBehaviorProjections(Guid guid);
|
||||
ItemData Get(Guid guid);
|
||||
}
|
||||
|
||||
public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemProjectionReader
|
||||
{
|
||||
private readonly Dictionary<Guid, AetheriaRuntimeCatalogItem> _typedItems;
|
||||
private readonly Dictionary<Guid, ItemData> _items;
|
||||
private static readonly IReadOnlyDictionary<int, Type> BehaviorTypesByUnionKey = new Dictionary<int, Type>
|
||||
{
|
||||
{ 0, typeof(GuidedWeaponData) },
|
||||
|
|
@ -59,11 +57,6 @@ public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemProjectionReader
|
|||
_typedItems = catalog.Items
|
||||
.Where(item => Guid.TryParse(item.LegacyId, out _))
|
||||
.ToDictionary(item => Guid.Parse(item.LegacyId), item => item);
|
||||
|
||||
_items = catalog.Items
|
||||
.Select(ProjectItem)
|
||||
.Where(item => item != null)
|
||||
.ToDictionary(item => item.ID, item => item);
|
||||
}
|
||||
|
||||
public AetheriaRuntimeCatalogItem GetRuntimeItem(Guid guid)
|
||||
|
|
@ -80,95 +73,6 @@ public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemProjectionReader
|
|||
: ProjectBehaviors(item);
|
||||
}
|
||||
|
||||
public ItemData Get(Guid guid)
|
||||
{
|
||||
ItemData item;
|
||||
_items.TryGetValue(guid, out item);
|
||||
return item;
|
||||
}
|
||||
|
||||
private static ItemData ProjectItem(AetheriaRuntimeCatalogItem item)
|
||||
{
|
||||
if (!Guid.TryParse(item.LegacyId, out var id))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var projected = CreateItemData(item);
|
||||
if (projected == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
projected.ID = id;
|
||||
projected.Name = item.Name;
|
||||
projected.Description = item.Description;
|
||||
projected.Manufacturer = ParseGuid(item.ManufacturerLegacyId);
|
||||
projected.Mass = (float)item.Mass;
|
||||
projected.SpecificHeat = (float)item.SpecificHeat;
|
||||
projected.Conductivity = (float)item.Conductivity;
|
||||
projected.Shape = ProjectShape(item.ShapeWidth, item.ShapeHeight, item.ShapeCells);
|
||||
projected.Price = item.Price;
|
||||
|
||||
if (projected is SimpleCommodityData simple)
|
||||
{
|
||||
simple.MaxStack = item.MaxStack;
|
||||
}
|
||||
|
||||
if (projected is ConsumableItemData consumable)
|
||||
{
|
||||
consumable.Stackable = item.Stackable;
|
||||
consumable.Duration = (float)item.Duration;
|
||||
consumable.Effectiveness = ProjectCurve(item.EffectivenessCurveKeys);
|
||||
consumable.Behaviors = ProjectBehaviors(item).ToList();
|
||||
}
|
||||
|
||||
if (projected is EquippableItemData equippable)
|
||||
{
|
||||
equippable.Durability = (float)item.Durability;
|
||||
equippable.ActionBarIcon = item.ActionBarIcon;
|
||||
equippable.ThermalResilience = (float)item.ThermalResilience;
|
||||
equippable.AudioStats = ProjectAudioStats(item).ToList();
|
||||
equippable.Behaviors = ProjectBehaviors(item).ToList();
|
||||
}
|
||||
|
||||
if (projected is GearData gear)
|
||||
{
|
||||
gear.Hardpoint = ParseEnum(item.HardpointType, HardpointType.Tool);
|
||||
}
|
||||
|
||||
if (projected is CargoBayData cargoBay)
|
||||
{
|
||||
cargoBay.InteriorShape = ProjectShape(item.InteriorShapeWidth, item.InteriorShapeHeight, item.InteriorShapeCells);
|
||||
}
|
||||
|
||||
if (projected is DockingBayData dockingBay)
|
||||
{
|
||||
dockingBay.MaxSize = new int2(item.DockingMaxSizeX, item.DockingMaxSizeY);
|
||||
}
|
||||
|
||||
if (projected is WeaponItemData weapon)
|
||||
{
|
||||
weapon.WeaponRange = ParseEnum(item.WeaponRange, WeaponRange.Short);
|
||||
weapon.WeaponCaliber = ParseEnum(item.WeaponCaliber, WeaponCaliber.Small);
|
||||
weapon.WeaponType = ParseEnum(item.WeaponType, WeaponType.Laser);
|
||||
weapon.WeaponFireTypes = ParseFlags(item.WeaponFireTypes, WeaponFireType.None);
|
||||
weapon.WeaponModifiers = ParseFlags(item.WeaponModifiers, WeaponModifiers.None);
|
||||
}
|
||||
|
||||
if (projected is HullData hull)
|
||||
{
|
||||
hull.HullType = ParseEnum(item.HullType, HullType.Ship);
|
||||
hull.Hardpoints = item.Hardpoints.Select(ProjectHardpoint).ToList();
|
||||
hull.GridOffset = (float)item.HullGridOffset;
|
||||
hull.Armor = (float)item.HullArmor;
|
||||
hull.Drag = (float)item.HullDrag;
|
||||
hull.CanTow = item.HullCanTow;
|
||||
}
|
||||
|
||||
return projected;
|
||||
}
|
||||
|
||||
private static BehaviorData[] ProjectBehaviors(AetheriaRuntimeCatalogItem item)
|
||||
{
|
||||
return item.BehaviorPayloads
|
||||
|
|
@ -177,29 +81,6 @@ public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemProjectionReader
|
|||
.ToArray();
|
||||
}
|
||||
|
||||
private static BezierCurve ProjectCurve(IReadOnlyList<AetheriaRuntimeCurveKey> keys)
|
||||
{
|
||||
return new BezierCurve
|
||||
{
|
||||
Keys = keys == null || keys.Count == 0
|
||||
? new[] { new float4(0, 1, 0, 0), new float4(1, 1, 0, 0) }
|
||||
: keys.Select(key => new float4(
|
||||
(float)key.Time,
|
||||
(float)key.Value,
|
||||
(float)key.InTangent,
|
||||
(float)key.OutTangent)).ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<AudioStat> ProjectAudioStats(AetheriaRuntimeCatalogItem item)
|
||||
{
|
||||
return item.AudioStats.Select(audioStat => new AudioStat
|
||||
{
|
||||
Parameter = audioStat.Parameter,
|
||||
Stat = ProjectPerformanceStat(audioStat.Stat)
|
||||
});
|
||||
}
|
||||
|
||||
private static PerformanceStat ProjectPerformanceStat(AetheriaRuntimePerformanceStat stat)
|
||||
{
|
||||
return new PerformanceStat
|
||||
|
|
@ -212,60 +93,6 @@ public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemProjectionReader
|
|||
};
|
||||
}
|
||||
|
||||
private static ItemData CreateItemData(AetheriaRuntimeCatalogItem item)
|
||||
{
|
||||
switch (item.Category)
|
||||
{
|
||||
case "SimpleCommodityData":
|
||||
return new SimpleCommodityData();
|
||||
case "CompoundCommodityData":
|
||||
return new CompoundCommodityData();
|
||||
case "ConsumableItemData":
|
||||
return new ConsumableItemData();
|
||||
case "GearData":
|
||||
return new GearData();
|
||||
case "CargoBayData":
|
||||
return new CargoBayData();
|
||||
case "DockingBayData":
|
||||
return new DockingBayData();
|
||||
case "WeaponItemData":
|
||||
return new WeaponItemData();
|
||||
case "HullData":
|
||||
return new HullData();
|
||||
default:
|
||||
return !string.IsNullOrWhiteSpace(item.HardpointType) ? new GearData() : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Shape ProjectShape(int width, int height, IReadOnlyList<AetheriaRuntimeShapeCell> cells)
|
||||
{
|
||||
var shape = new Shape(Math.Max(width, 1), Math.Max(height, 1));
|
||||
foreach (var coordinate in shape.AllCoordinates)
|
||||
{
|
||||
shape[coordinate] = false;
|
||||
}
|
||||
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
shape[new int2(cell.X, cell.Y)] = true;
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
private static HardpointData ProjectHardpoint(AetheriaRuntimeHardpoint hardpoint)
|
||||
{
|
||||
return new HardpointData
|
||||
{
|
||||
Type = ParseEnum(hardpoint.Type, HardpointType.Hull),
|
||||
Position = new int2(hardpoint.PositionX, hardpoint.PositionY),
|
||||
Shape = ProjectShape(hardpoint.ShapeWidth, hardpoint.ShapeHeight, hardpoint.ShapeCells),
|
||||
Transform = hardpoint.Transform,
|
||||
Rotation = ParseEnum(hardpoint.Rotation, ItemRotation.None),
|
||||
Armor = (float)hardpoint.Armor
|
||||
};
|
||||
}
|
||||
|
||||
private static BehaviorData ProjectBehavior(AetheriaRuntimeBehaviorPayload payload)
|
||||
{
|
||||
if (!BehaviorTypesByUnionKey.TryGetValue(payload.UnionKey, out var behaviorType))
|
||||
|
|
@ -390,28 +217,6 @@ public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemProjectionReader
|
|||
return Guid.TryParse(value, out var result) ? result : Guid.Empty;
|
||||
}
|
||||
|
||||
private static T ParseEnum<T>(string value, T fallback) where T : struct
|
||||
{
|
||||
return Enum.TryParse(value, true, out T parsed) ? parsed : fallback;
|
||||
}
|
||||
|
||||
private static T ParseFlags<T>(string value, T fallback) where T : struct
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return value
|
||||
.Split('|')
|
||||
.Select(part => part.Trim())
|
||||
.Where(part => part.Length > 0)
|
||||
.Aggregate(fallback, (current, part) =>
|
||||
Enum.TryParse(part, true, out T parsed)
|
||||
? (T)Enum.ToObject(typeof(T), Convert.ToInt32(current) | Convert.ToInt32(parsed))
|
||||
: current);
|
||||
}
|
||||
|
||||
private static float2 ConvertFloat2(AetheriaRuntimeBehaviorValue value)
|
||||
{
|
||||
return new float2(
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,6 @@ public class ConsumableItemEffect
|
|||
public float RemainingDuration { get; private set; }
|
||||
public Entity Entity { get; }
|
||||
public ConsumableItem Item { get; }
|
||||
public ConsumableItemData Data { get; }
|
||||
public Behavior[] Behaviors { get; }
|
||||
public AetheriaRuntimeCatalogItem RuntimeItem { get; }
|
||||
public float Duration => Math.Max(_duration, float.Epsilon);
|
||||
|
|
@ -1260,9 +1259,8 @@ public class ConsumableItemEffect
|
|||
Item = item;
|
||||
Entity = entity;
|
||||
RuntimeItem = entity.ItemManager.GetRuntimeItem(item);
|
||||
Data = entity.ItemManager.GetData(item) as ConsumableItemData;
|
||||
_duration = RuntimeItem?.Duration > 0 ? (float)RuntimeItem.Duration : Data?.Duration ?? 0;
|
||||
_effectiveness = CreateEffectivenessCurve(RuntimeItem, Data);
|
||||
_duration = RuntimeItem?.Duration > 0 ? (float)RuntimeItem.Duration : 0;
|
||||
_effectiveness = CreateEffectivenessCurve(RuntimeItem);
|
||||
RemainingDuration = _duration;
|
||||
|
||||
Behaviors = entity.ItemManager.GetRuntimeBehaviorProjections(item)
|
||||
|
|
@ -1297,7 +1295,7 @@ public class ConsumableItemEffect
|
|||
return result;
|
||||
}
|
||||
|
||||
private static BezierCurve CreateEffectivenessCurve(AetheriaRuntimeCatalogItem item, ConsumableItemData fallback)
|
||||
private static BezierCurve CreateEffectivenessCurve(AetheriaRuntimeCatalogItem item)
|
||||
{
|
||||
if (item?.EffectivenessCurveKeys != null && item.EffectivenessCurveKeys.Count > 0)
|
||||
{
|
||||
|
|
@ -1313,7 +1311,7 @@ public class ConsumableItemEffect
|
|||
};
|
||||
}
|
||||
|
||||
return fallback?.Effectiveness ?? new BezierCurve
|
||||
return new BezierCurve
|
||||
{
|
||||
Keys = new[] { new float4(0, 1, 0, 0), new float4(1, 1, 0, 0) }
|
||||
};
|
||||
|
|
@ -1342,7 +1340,6 @@ public class EquippedItem
|
|||
public float Wear { get; private set; }
|
||||
public Shape InsetShape { get; }
|
||||
public Entity Entity { get; }
|
||||
public EquippableItemData Data { get; }
|
||||
public AetheriaRuntimeCatalogItem RuntimeItem { get; }
|
||||
|
||||
public ReactiveProperty<bool> ThermalOnline { get; } = new ReactiveProperty<bool>(false);
|
||||
|
|
@ -1443,16 +1440,15 @@ public class EquippedItem
|
|||
public EquippedItem(ItemManager itemManager, EquippableItem item, int2 position, Entity entity)
|
||||
{
|
||||
ItemManager = itemManager;
|
||||
Data = ItemManager.GetData(item);
|
||||
Entity = entity;
|
||||
EquippableItem = item;
|
||||
Position = position;
|
||||
RuntimeItem = ItemManager.GetRuntimeItem(item);
|
||||
Conductivity = RuntimeItem != null ? (float)RuntimeItem.Conductivity : Data.Conductivity;
|
||||
Conductivity = RuntimeItem != null ? (float)RuntimeItem.Conductivity : 0;
|
||||
MaxDurability = RuntimeItem?.Durability > 0 ? (float)RuntimeItem.Durability : Math.Max(item.Durability, 1f);
|
||||
ThermalResilience = RuntimeItem?.ThermalResilience > 0 ? (float)RuntimeItem.ThermalResilience : Data.ThermalResilience;
|
||||
ThermalResilience = RuntimeItem?.ThermalResilience > 0 ? (float)RuntimeItem.ThermalResilience : 1;
|
||||
_thermalPerformanceCurve = CreateThermalPerformanceCurve(RuntimeItem);
|
||||
_audioStats = CreateAudioStatBindings(RuntimeItem, Data);
|
||||
_audioStats = CreateAudioStatBindings(RuntimeItem);
|
||||
ThermalExponent = lerp(
|
||||
ItemManager.GameplaySettings.ThermalQualityMin,
|
||||
ItemManager.GameplaySettings.ThermalQualityMax,
|
||||
|
|
@ -1541,7 +1537,7 @@ public class EquippedItem
|
|||
RuntimeItem == null ||
|
||||
RuntimeItem.MaximumTemperature <= RuntimeItem.MinimumTemperature)
|
||||
{
|
||||
return Data.Performance(temperature);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var t = unlerp((float)RuntimeItem.MinimumTemperature, (float)RuntimeItem.MaximumTemperature, temperature);
|
||||
|
|
@ -1594,9 +1590,7 @@ public class EquippedItem
|
|||
return null;
|
||||
}
|
||||
|
||||
private static EquippedItemAudioStatBinding[] CreateAudioStatBindings(
|
||||
AetheriaRuntimeCatalogItem item,
|
||||
EquippableItemData fallback)
|
||||
private static EquippedItemAudioStatBinding[] CreateAudioStatBindings(AetheriaRuntimeCatalogItem item)
|
||||
{
|
||||
if (item?.AudioStats != null)
|
||||
{
|
||||
|
|
@ -1607,9 +1601,7 @@ public class EquippedItem
|
|||
.ToArray();
|
||||
}
|
||||
|
||||
return fallback.AudioStats
|
||||
.Select(audioStat => new EquippedItemAudioStatBinding(audioStat.Parameter, audioStat.Stat))
|
||||
.ToArray();
|
||||
return Array.Empty<EquippedItemAudioStatBinding>();
|
||||
}
|
||||
|
||||
private static PerformanceStat CreatePerformanceStat(AetheriaRuntimePerformanceStat stat)
|
||||
|
|
|
|||
|
|
@ -94,49 +94,11 @@ public class ItemManager
|
|||
return new RuntimeItemReference(itemId);
|
||||
}
|
||||
|
||||
public ItemData GetData(ItemInstance item)
|
||||
{
|
||||
Hydrate(item);
|
||||
return item?.Data?.Projection;
|
||||
}
|
||||
|
||||
public void Hydrate(ItemInstance item)
|
||||
{
|
||||
if (item?.Data == null || item.Data.Projection != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var data = _itemProjections.Get(item.Data.ItemId);
|
||||
if (data == null)
|
||||
{
|
||||
_logger($"Attempted to hydrate missing item id {item.Data.ItemId}");
|
||||
return;
|
||||
}
|
||||
|
||||
item.Data.SetProjection(data);
|
||||
}
|
||||
|
||||
public void Log(string s)
|
||||
{
|
||||
_logger(s);
|
||||
}
|
||||
|
||||
public SimpleCommodityData GetData(SimpleCommodity item)
|
||||
{
|
||||
return GetData((ItemInstance)item) as SimpleCommodityData;
|
||||
}
|
||||
|
||||
public CraftedItemData GetData(CraftedItemInstance item)
|
||||
{
|
||||
return GetData((ItemInstance)item) as CraftedItemData;
|
||||
}
|
||||
|
||||
public EquippableItemData GetData(EquippableItem item)
|
||||
{
|
||||
return GetData((ItemInstance)item) as EquippableItemData;
|
||||
}
|
||||
|
||||
public float GetMass(ItemInstance item)
|
||||
{
|
||||
var typedItem = GetRuntimeItem(item);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ public abstract class RuntimeItemProjectionEntry
|
|||
|
||||
public class RuntimeItemReference
|
||||
{
|
||||
public ItemData Projection { get; private set; }
|
||||
public Guid ItemId;
|
||||
|
||||
public RuntimeItemReference()
|
||||
|
|
@ -39,17 +38,6 @@ public class RuntimeItemReference
|
|||
{
|
||||
ItemId = itemId;
|
||||
}
|
||||
|
||||
public RuntimeItemReference(ItemData value)
|
||||
{
|
||||
SetProjection(value);
|
||||
}
|
||||
|
||||
public void SetProjection(ItemData value)
|
||||
{
|
||||
Projection = value;
|
||||
ItemId = value?.ID ?? Guid.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ITintInspector
|
||||
|
|
|
|||
|
|
@ -346,29 +346,6 @@ public class PropertiesPanel : MonoBehaviour
|
|||
OnPropertyAdded?.Invoke(field.gameObject);
|
||||
}
|
||||
|
||||
// public void Inspect(Entity entity)
|
||||
// {
|
||||
// Clear();
|
||||
// Title.text = entity.Name;
|
||||
// var hullData = Context.GetData(entity.Hull) as HullData;
|
||||
// AddSection(
|
||||
// hullData.HullType == HullType.Ship ? "Ship" :
|
||||
// hullData.HullType == HullType.Station ? "Station" :
|
||||
// "Platform");
|
||||
// //AddList(hullData.Name).Inspect(hull, entity);
|
||||
// //PropertiesPanel.AddProperty("Hull", () => $"{hullData.Name}");
|
||||
// AddEntityProperties(entity);
|
||||
// //cargoList.SetExpanded(false,true);
|
||||
//
|
||||
// RefreshValues();
|
||||
// }
|
||||
|
||||
// private void AddEntityProperties(Entity entity)
|
||||
// {
|
||||
// AddField("Name", () => entity.Name, name => entity.Name = name);
|
||||
// AddProperty("Mass", () => $"{entity.Mass.SignificantDigits(Context.GameplaySettings.SignificantDigits)}");
|
||||
// }
|
||||
|
||||
private void AddItemProperties(ItemInstance item)
|
||||
{
|
||||
var typedItem = FindTypedPropertyItem(item);
|
||||
|
|
|
|||
|
|
@ -80,11 +80,10 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted.
|
|||
same typed player-settings commit after mutating the runtime projection. The
|
||||
action bar also uses typed runtime catalog category rows to reject
|
||||
non-consumable inventory drops and creates consumable bindings around typed
|
||||
catalog rows before hydrating any legacy DTO. Missing typed rows are rejected
|
||||
for consumable binding instead of falling through to legacy DTO classification.
|
||||
Consumable activation and active-duration fill still resolve legacy
|
||||
`ConsumableItemData` lazily because runtime effects and duration are not typed
|
||||
execution surfaces yet. Gear action-bar bindings read custom icon resource
|
||||
catalog rows. Missing typed rows are rejected for consumable binding instead
|
||||
of falling through to legacy DTO classification. Consumable activation,
|
||||
active-duration fill, runtime duration, and effectiveness curves now use typed
|
||||
item rows with neutral defaults for missing optional facets. Gear action-bar bindings read custom icon resource
|
||||
paths from typed item rows, then use typed weapon and hardpoint facets for
|
||||
fallback icon selection, and finally fall back to a generic tool icon when
|
||||
typed facets are incomplete. The current legacy catalog has zero populated
|
||||
|
|
@ -134,20 +133,19 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted.
|
|||
- `ActionGameManager` opens `AetheriaRuntimeCatalogStore` over
|
||||
`aetheria-world.cc`, projects it through `AetheriaRuntimeItemCatalog`, and
|
||||
gives `ItemManager` explicit item lookup authority. Item instances carry
|
||||
`RuntimeItemReference`, an item-definition id plus optional hydrated
|
||||
projection cache, not a process-global catalog resolver or durable item-data
|
||||
owner. The old `LegacyItemCatalogBoundary`,
|
||||
`RuntimeItemReference`, an item-definition id, not a process-global catalog
|
||||
resolver, hydrated projection cache, or durable item-data owner. The old
|
||||
`LegacyItemCatalogBoundary`,
|
||||
`LegacyItemCatalogCache`, and runtime MessagePack deserializer path have been
|
||||
deleted. The old `DatabaseEntry`/`RuntimeCatalogEntry` base has been demoted
|
||||
to `RuntimeItemProjectionEntry` for surviving item DTOs, and the old generic
|
||||
`DatabaseLink<T>`/`RuntimeCatalogLink<T>` path has collapsed into the
|
||||
item-specific runtime reference.
|
||||
- `ItemManager` no longer exposes the raw runtime item catalog reader as public
|
||||
gameplay/UI API. Temporary item projection hydration now goes through
|
||||
`ItemManager.GetData` over `RuntimeItemReference.ItemId`. `ItemManager` no
|
||||
longer exposes a legacy catalog enumeration API or a catalog-entry-shaped
|
||||
single-item API. This prevents catalog authority from leaking into every
|
||||
caller that only needs a projection lookup. The item properties UI no longer uses
|
||||
gameplay/UI API, and its old `GetData`/`Hydrate` item DTO projection path has
|
||||
been deleted. `AetheriaRuntimeItemCatalog` no longer materializes whole
|
||||
`ItemData` DTOs as a runtime cache; it exposes typed item rows plus the
|
||||
temporary behavior payload projection bridge. The item properties UI no longer uses
|
||||
`ItemManager` for manufacturer display; it resolves the manufacturer through
|
||||
the package-owned `ActionGameManager.RuntimeCatalog` typed snapshot. Entity
|
||||
restore and loadout manufacturer-distance weighting no longer use `ItemManager`
|
||||
|
|
@ -241,13 +239,13 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted.
|
|||
conduction, durability performance, thermal performance, and wear scaling.
|
||||
Thermal resilience is also typed and feeds wear scaling. Audio parameter stat
|
||||
bindings are typed item rows and feed equipped-item Wwise parameter updates;
|
||||
the legacy equippable DTO is now only an incomplete-row projection fallback
|
||||
for equipped-item simulation. Consumable stackability, duration, and
|
||||
missing optional thermal/audio facets now degrade to neutral runtime defaults
|
||||
instead of hydrating legacy equippable DTOs. Consumable stackability, duration, and
|
||||
effectiveness curve slots are part of typed item rows, and action-bar
|
||||
consumable activation/fill now command typed item IDs. The current mapped
|
||||
legacy catalog has no consumable item rows, so `ConsumableItemData` remains a
|
||||
compatibility fallback for any future/unmapped consumable instance until
|
||||
consumable behavior execution is fully typed.
|
||||
legacy catalog has no consumable item rows, so consumable runtime behavior
|
||||
still needs future typed data coverage, but it no longer hydrates
|
||||
`ConsumableItemData` as a fallback.
|
||||
Inventory drag preview occupancy now projects typed item shape cells only into
|
||||
the local `Shape` grid, and final fit/equip acceptance shares the typed
|
||||
runtime catalog geometry path in `Entity.ItemFits` and `TryEquip`.
|
||||
|
|
@ -772,6 +770,10 @@ First Aetheria surfaces to publish:
|
|||
typed runtime item rows; `ItemManager.Instantiate` now clones simple
|
||||
commodities, crafted items, consumables, and equippables from
|
||||
`AetheriaRuntimeCatalogItem` identity and facets.
|
||||
- Done: delete the runtime item DTO hydration bridge; `ItemManager.GetData`,
|
||||
`ItemManager.Hydrate`, `IRuntimeItemProjectionReader.Get`, the
|
||||
`AetheriaRuntimeItemCatalog` whole-item DTO cache, and
|
||||
`RuntimeItemReference.Projection` are gone.
|
||||
- Done: move final `Entity.ItemFits`, `TryFindSpace`, `TryEquip`, and
|
||||
`TryUnequip` gear occupancy/mass deltas onto typed catalog rows for item
|
||||
shape, hull shape/interior, hardpoint masks, cargo/docking category, and
|
||||
|
|
@ -790,24 +792,23 @@ First Aetheria surfaces to publish:
|
|||
typed runtime item rows; legacy `EquippableItemData.Durability` no longer
|
||||
owns that stat-evaluation path.
|
||||
- Done: move new equippable instance durability initialization onto typed
|
||||
runtime item rows; legacy `EquippableItemData.Durability` remains only as
|
||||
an incomplete-row fallback in the instantiation bridge.
|
||||
runtime item rows.
|
||||
- Done: move `EquippedItem` conductivity and max-durability performance/wear
|
||||
inputs onto typed runtime item rows; legacy thermal resilience and audio
|
||||
stats remain explicit DTO residues.
|
||||
inputs onto typed runtime item rows.
|
||||
- Done: move `EquippedItem` thermal performance evaluation onto typed
|
||||
runtime item thermal bounds and curve keys; legacy `Data.Performance`
|
||||
remains only as an incomplete-row fallback.
|
||||
runtime item thermal bounds and curve keys; missing typed curve/range data
|
||||
uses a neutral runtime default.
|
||||
- Done: import typed thermal resilience and move equipped-item wear scaling
|
||||
off `EquippableItemData.ThermalResilience`; it remains only as an
|
||||
incomplete-row fallback.
|
||||
off `EquippableItemData.ThermalResilience`; missing typed resilience uses
|
||||
a neutral runtime default.
|
||||
- Done: import typed audio parameter stat bindings and move equipped-item
|
||||
Wwise parameter updates off `EquippableItemData.AudioStats`; it remains
|
||||
only as an incomplete-row fallback.
|
||||
Wwise parameter updates off `EquippableItemData.AudioStats`; missing
|
||||
typed audio stat bindings produce no parameter updates.
|
||||
- Done: add typed consumable stackability, duration, and effectiveness curve
|
||||
fields and route action-bar consumable activation through typed item rows;
|
||||
verifier records that the current mapped catalog has `0` consumable item
|
||||
rows, so the old DTO path cannot be fully deleted yet.
|
||||
fields and route action-bar consumable activation/runtime evaluation
|
||||
through typed item rows; verifier records that the current mapped catalog
|
||||
has `0` consumable item rows, so future consumable content still needs
|
||||
typed coverage.
|
||||
- Done: import action-bar icon resource paths into typed item definitions and
|
||||
move `ActionBarSlot` custom gear icon lookup onto typed runtime item rows.
|
||||
- Done: move `Ship` drag, combat/turret predicted shot height, and thruster
|
||||
|
|
@ -946,10 +947,9 @@ First Aetheria surfaces to publish:
|
|||
- Done: collapse the old generic `RuntimeCatalogLink<T>` abstraction into
|
||||
`RuntimeItemReference`, an item-specific runtime projection reference owned
|
||||
by `ItemManager`.
|
||||
- Done: demote `RuntimeItemReference.Value` to
|
||||
`RuntimeItemReference.Projection`, making the hydrated `ItemData` DTO a
|
||||
cache/display/behavior bridge derived from `ItemId` instead of the
|
||||
reference's apparent state value.
|
||||
- Done: demote `RuntimeItemReference.Value` to an item-definition id, then
|
||||
delete `RuntimeItemReference.Projection`; item references no longer carry
|
||||
hydrated `ItemData` DTOs.
|
||||
- Done: delete the dead `ItemManager.GetRuntimeItemProjection<T>` bridge
|
||||
after loadout generation stopped hydrating selected typed rows into
|
||||
`EquippableItemData` merely to instantiate equipment.
|
||||
|
|
@ -1048,11 +1048,9 @@ First Aetheria surfaces to publish:
|
|||
|
||||
## Immediate Cut Line
|
||||
|
||||
Do not add behavior to `ItemData`, `RuntimeItemProjectionEntry`, or the
|
||||
temporary `AetheriaRuntimeItemCatalog` DTO materializer. The typed state spine
|
||||
and migration quarantine exist; the next cuts should replace surviving
|
||||
projection consumers with typed item facets, typed behavior factories, and Eve
|
||||
surfaces until the remaining `GetData` hydration users are gone and the old DTO
|
||||
bridge can be deleted. Any predicate that still needs `ItemData` must earn that
|
||||
Do not add behavior to `ItemData` or `RuntimeItemProjectionEntry`. The typed
|
||||
state spine and migration quarantine exist; the next cuts should replace the
|
||||
surviving behavior DTO projection bridge with typed behavior factories and Eve
|
||||
surfaces. Any predicate that still needs legacy DTO objects must earn that
|
||||
dependency by using behavior objects or simulation-only methods that typed
|
||||
facets do not yet expose.
|
||||
|
|
|
|||
Loading…
Reference in a new issue