Delete runtime item DTO hydration

This commit is contained in:
Meta Vens 2026-06-14 07:52:18 +01:00
commit c0d0fbf656
7 changed files with 49 additions and 327 deletions

View file

@ -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(

View file

@ -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)

View file

@ -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);

View file

@ -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