diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index fcbc6d4b8..a4a8636be 100644 Binary files a/.voidbot/state/aetheria.cc and b/.voidbot/state/aetheria.cc differ diff --git a/Assets/Scripts/Gameplay/ActionBarSlot.cs b/Assets/Scripts/Gameplay/ActionBarSlot.cs index 39fcc14c5..b966a7311 100644 --- a/Assets/Scripts/Gameplay/ActionBarSlot.cs +++ b/Assets/Scripts/Gameplay/ActionBarSlot.cs @@ -150,7 +150,7 @@ public class ActionBarGearBinding : ActionBarBinding private static AetheriaRuntimeCatalogItem FindTypedGearItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index e091c5519..8f6d5b37f 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -388,7 +388,7 @@ public class ActionGameManager : MonoBehaviour return new AetheriaRuntimeLoadoutItemCommit { - ItemDefinitionLegacyId = item.Data?.ItemId.ToString("D") ?? "", + ItemDefinitionLegacyId = item.ItemId == Guid.Empty ? "" : item.ItemId.ToString("D"), Quality = item is CraftedItemInstance crafted ? crafted.Quality : 1.0, Durability = item is EquippableItem equippable ? equippable.Durability : 1.0, Quantity = item is SimpleCommodity commodity ? commodity.Quantity : 1 @@ -453,7 +453,7 @@ public class ActionGameManager : MonoBehaviour DirectionX = entity.Direction.x, DirectionY = entity.Direction.y, CorporationLegacyId = entity.Faction?.ID.ToString("D") ?? "", - HullItemDefinitionLegacyId = entity.Hull?.Data?.ItemId.ToString("D") ?? "", + HullItemDefinitionLegacyId = entity.Hull?.ItemId == Guid.Empty ? "" : entity.Hull.ItemId.ToString("D"), Equipment = ProjectEquippedSlots(entity.Equipment), CargoBays = ProjectEquippedSlots(entity.CargoBays), DockingBays = ProjectEquippedSlots(entity.DockingBays), @@ -772,7 +772,7 @@ public class ActionGameManager : MonoBehaviour AetheriaRuntimeCatalogItem FindTypedActionBarItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/Gameplay/EntityInstance.cs b/Assets/Scripts/Gameplay/EntityInstance.cs index 34068707b..6fec10ad5 100644 --- a/Assets/Scripts/Gameplay/EntityInstance.cs +++ b/Assets/Scripts/Gameplay/EntityInstance.cs @@ -62,7 +62,7 @@ public class EntityInstance : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedHull(ItemInstance hull) { - var itemId = hull?.Data?.ItemId ?? Guid.Empty; + var itemId = hull?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/Gameplay/ShipInstance.cs b/Assets/Scripts/Gameplay/ShipInstance.cs index 8b05f0e56..34e408dfd 100644 --- a/Assets/Scripts/Gameplay/ShipInstance.cs +++ b/Assets/Scripts/Gameplay/ShipInstance.cs @@ -148,7 +148,7 @@ public class ShipInstance : EntityInstance private static AetheriaRuntimeCatalogItem FindTypedItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index 0f280b0d6..f1a43ef60 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -263,7 +263,7 @@ public abstract class Entity Hull = hull; var typedHull = itemManager.GetRuntimeItem(hull); if (typedHull == null) - throw new InvalidOperationException($"Unable to construct entity: missing typed hull row for {hull?.Data?.ItemId}"); + throw new InvalidOperationException($"Unable to construct entity: missing typed hull row for {hull?.ItemId}"); Name = typedHull.Name; MapEntity(); WeaponGroups = new (List weapons, List items)[itemManager.GameplaySettings.WeaponGroupCount]; @@ -316,7 +316,7 @@ public abstract class Entity public ConsumableItemEffect FindActiveConsumable(Guid itemId) { - return _activeConsumables.FirstOrDefault(ac => ac.Item?.Data?.ItemId == itemId); + return _activeConsumables.FirstOrDefault(ac => ac.Item?.ItemId == itemId); } public bool CanActivateConsumable(AetheriaRuntimeCatalogItem item) @@ -350,7 +350,7 @@ public abstract class Entity { var typedHull = ItemManager.GetRuntimeItem(Hull); if (typedHull == null) - throw new InvalidOperationException($"Unable to map entity {Name}: missing typed hull row for {Hull?.Data?.ItemId}"); + throw new InvalidOperationException($"Unable to map entity {Name}: missing typed hull row for {Hull?.ItemId}"); var hullShape = GetHullShape(typedHull); EquippedHull = new EquippedItem(ItemManager, Hull, int2.zero, this); @@ -391,7 +391,7 @@ public abstract class Entity public void GenerateWeaponGroups() { foreach (var group in Weapons - .GroupBy(w => w.Item.EquippableItem.Data.ItemId) + .GroupBy(w => w.Item.EquippableItem.ItemId) .OrderBy(wg=>wg.Average(w=>w.Range)) .Select((weapons, index) => (weapons, index))) { @@ -1718,9 +1718,9 @@ public class EquippedCargoBay : EquippedItem } Cargo[item] = cargoCoord; - if(!ItemsOfType.ContainsKey(item.Data.ItemId)) - ItemsOfType[item.Data.ItemId] = new List(); - ItemsOfType[item.Data.ItemId].Add(item); + if(!ItemsOfType.ContainsKey(item.ItemId)) + ItemsOfType[item.ItemId] = new List(); + ItemsOfType[item.ItemId].Add(item); } else if (Occupancy[cargoCoord.x, cargoCoord.y] is SimpleCommodity cargoCommodity && cargoCommodity.Data == item.Data) { @@ -1762,9 +1762,9 @@ public class EquippedCargoBay : EquippedItem } Cargo[item] = cargoCoord; - if(!ItemsOfType.ContainsKey(item.Data.ItemId)) - ItemsOfType[item.Data.ItemId] = new List(); - ItemsOfType[item.Data.ItemId].Add(item); + if(!ItemsOfType.ContainsKey(item.ItemId)) + ItemsOfType[item.ItemId] = new List(); + ItemsOfType[item.ItemId].Add(item); Mass += ItemManager.GetMass(item); ThermalMass += ItemManager.GetThermalMass(item); @@ -1786,9 +1786,9 @@ public class EquippedCargoBay : EquippedItem Occupancy[v.x, v.y] = null; Cargo.Remove(item); - ItemsOfType[item.Data.ItemId].Remove(item); - if (!ItemsOfType[item.Data.ItemId].Any()) - ItemsOfType.Remove(item.Data.ItemId); + ItemsOfType[item.ItemId].Remove(item); + if (!ItemsOfType[item.ItemId].Any()) + ItemsOfType.Remove(item.ItemId); Mass -= ItemManager.GetMass(item); ThermalMass -= ItemManager.GetThermalMass(item); @@ -1814,9 +1814,9 @@ public class EquippedCargoBay : EquippedItem Occupancy[v.x, v.y] = null; Cargo.Remove(item); - ItemsOfType[item.Data.ItemId].Remove(item); - if (!ItemsOfType[item.Data.ItemId].Any()) - ItemsOfType.Remove(item.Data.ItemId); + ItemsOfType[item.ItemId].Remove(item); + if (!ItemsOfType[item.ItemId].Any()) + ItemsOfType.Remove(item.ItemId); Mass -= ItemManager.GetMass(item); ThermalMass -= ItemManager.GetThermalMass(item); diff --git a/Assets/Scripts/ServerShared/ItemInstance.cs b/Assets/Scripts/ServerShared/ItemInstance.cs index a6c3ee869..57ace52ec 100644 --- a/Assets/Scripts/ServerShared/ItemInstance.cs +++ b/Assets/Scripts/ServerShared/ItemInstance.cs @@ -14,6 +14,7 @@ public abstract class ItemInstance { public RuntimeItemReference Data; public ItemRotation Rotation; + public Guid ItemId => Data?.ItemId ?? Guid.Empty; } public abstract class CraftedItemInstance : ItemInstance diff --git a/Assets/Scripts/ServerShared/ItemManager.cs b/Assets/Scripts/ServerShared/ItemManager.cs index 93b2eeb61..87ca94297 100644 --- a/Assets/Scripts/ServerShared/ItemManager.cs +++ b/Assets/Scripts/ServerShared/ItemManager.cs @@ -91,8 +91,7 @@ public class ItemManager public AetheriaRuntimeCatalogItem GetRuntimeItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; - return GetRuntimeItem(itemId); + return GetRuntimeItem(item?.ItemId ?? Guid.Empty); } public AetheriaRuntimeCatalogItem GetRuntimeItem(Guid itemId) @@ -363,7 +362,7 @@ public class ItemManager var durability = pow(item.Durability / maxDurability, durabilityExponent * stat.DurabilityExponentMultiplier); var result = lerp(stat.Min, stat.Max, quality * durability); if (float.IsNaN(result)) - throw new InvalidOperationException($"Performance Stat on {typedItem?.Name ?? item.Data?.ItemId.ToString() ?? "unknown item"} evaluating as NaN: input data is invalid! Durability: {item.Durability} / {maxDurability}"); + throw new InvalidOperationException($"Performance Stat on {typedItem?.Name ?? item.ItemId.ToString()} evaluating as NaN: input data is invalid! Durability: {item.Durability} / {maxDurability}"); return result; } @@ -413,7 +412,7 @@ public class ItemManager var typedItem = GetRuntimeItem(item); if (typedItem == null) { - _logger($"Attempted to instantiate missing item id {item?.Data?.ItemId}"); + _logger($"Attempted to instantiate missing item id {item?.ItemId}"); return null; } diff --git a/Assets/Scripts/ServerShared/LoadoutGenerator.cs b/Assets/Scripts/ServerShared/LoadoutGenerator.cs index 1927cf08e..e46beb748 100644 --- a/Assets/Scripts/ServerShared/LoadoutGenerator.cs +++ b/Assets/Scripts/ServerShared/LoadoutGenerator.cs @@ -337,7 +337,7 @@ public class LoadoutGenerator var previousItem = itemRow == null ? null : Guid.TryParse(itemRow.LegacyId, out var previousItemId) - ? entity.Equipment.FirstOrDefault(item => item.EquippableItem.Data.ItemId == previousItemId) + ? entity.Equipment.FirstOrDefault(item => item.EquippableItem.ItemId == previousItemId) : null; itemRow ??= RandomCatalogItem(RuntimeItemCandidateKind.Gear, hardpoint, 2); if (itemRow == null) ItemManager.Log($"No compatible item found for entity {hardpoint.Type} hardpoint!"); diff --git a/Assets/Scripts/UI/HUD/SchematicDisplay.cs b/Assets/Scripts/UI/HUD/SchematicDisplay.cs index c32c2639d..77f28e509 100644 --- a/Assets/Scripts/UI/HUD/SchematicDisplay.cs +++ b/Assets/Scripts/UI/HUD/SchematicDisplay.cs @@ -144,7 +144,7 @@ public class SchematicDisplay : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedWeapon(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; var typedItem = itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); @@ -288,7 +288,7 @@ public class SchematicDisplay : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/UI/Menu/InventoryMenu.cs b/Assets/Scripts/UI/Menu/InventoryMenu.cs index b36741493..948aa4bad 100644 --- a/Assets/Scripts/UI/Menu/InventoryMenu.cs +++ b/Assets/Scripts/UI/Menu/InventoryMenu.cs @@ -219,7 +219,7 @@ public class InventoryMenu : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedInventoryItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/UI/Menu/InventoryPanel.cs b/Assets/Scripts/UI/Menu/InventoryPanel.cs index 48bf471ff..9cf9f12aa 100644 --- a/Assets/Scripts/UI/Menu/InventoryPanel.cs +++ b/Assets/Scripts/UI/Menu/InventoryPanel.cs @@ -925,7 +925,7 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler private static AetheriaRuntimeCatalogItem FindTypedInventoryItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/UI/Menu/SectorRenderer.cs b/Assets/Scripts/UI/Menu/SectorRenderer.cs index b2ca4433b..dd89b0d7b 100644 --- a/Assets/Scripts/UI/Menu/SectorRenderer.cs +++ b/Assets/Scripts/UI/Menu/SectorRenderer.cs @@ -123,7 +123,7 @@ public class SectorRenderer : MonoBehaviour, IBeginDragHandler, IDragHandler, IS private static AetheriaRuntimeCatalogItem FindTypedHull(RuntimeEntityBlueprint entity) { - var itemId = entity?.Hull?.Data?.ItemId ?? Guid.Empty; + var itemId = entity?.Hull?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/UI/Menu/TradeMenu.cs b/Assets/Scripts/UI/Menu/TradeMenu.cs index 964708c55..bb36ffd74 100644 --- a/Assets/Scripts/UI/Menu/TradeMenu.cs +++ b/Assets/Scripts/UI/Menu/TradeMenu.cs @@ -293,7 +293,7 @@ public class TradeMenu : MonoBehaviour x => () => { if (x.IsHull) - return GameManager.DockedEntity.Children.Count(s => s.Hull.Data.ItemId == x.LegacyId && s is Ship {IsPlayerShip: true}).ToString(); + return GameManager.DockedEntity.Children.Count(s => s.Hull.ItemId == x.LegacyId && s is Ship {IsPlayerShip: true}).ToString(); if(x.Item is SimpleCommodity) return (_targetCargo.ItemsOfType.ContainsKey(x.LegacyId) ? _targetCargo.ItemsOfType[x.LegacyId].Cast().Sum(s=>s.Quantity) : 0).ToString(); return (_targetCargo.ItemsOfType.ContainsKey(x.LegacyId) ? _targetCargo.ItemsOfType[x.LegacyId].Count : 0).ToString(); @@ -301,7 +301,7 @@ public class TradeMenu : MonoBehaviour x => { if (x.IsHull) - return GameManager.DockedEntity.Children.Count(s => s.Hull.Data.ItemId == x.LegacyId && s is Ship {IsPlayerShip: true}); + return GameManager.DockedEntity.Children.Count(s => s.Hull.ItemId == x.LegacyId && s is Ship {IsPlayerShip: true}); if(x.Item is SimpleCommodity) return _targetCargo.ItemsOfType.ContainsKey(x.LegacyId) ? _targetCargo.ItemsOfType[x.LegacyId].Cast().Sum(s=>s.Quantity) : 0; return _targetCargo.ItemsOfType.ContainsKey(x.LegacyId) ? _targetCargo.ItemsOfType[x.LegacyId].Count : 0; @@ -393,12 +393,13 @@ public class TradeMenu : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedTradeItem(ItemInstance item) { - if (item?.Data == null || item.Data.ItemId == Guid.Empty) + var itemId = item?.ItemId ?? Guid.Empty; + if (itemId == Guid.Empty) { return null; } - return ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(item.Data.ItemId.ToString("D")); + return ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); } private static double GetTypedBehaviorNumber(TradeRow row, BehaviorFilter behaviorFilter, AetheriaRuntimeBehaviorFieldMetadata field) @@ -468,7 +469,7 @@ public class TradeMenu : MonoBehaviour public AetheriaRuntimeCatalogItem TypedItem { get; } - public Guid LegacyId => Item?.Data?.ItemId ?? Guid.Empty; + public Guid LegacyId => Item?.ItemId ?? Guid.Empty; public string Name => !string.IsNullOrWhiteSpace(TypedItem?.Name) ? TypedItem.Name : "Unknown Item"; diff --git a/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs b/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs index 4e770765e..d369a92a6 100644 --- a/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs +++ b/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs @@ -417,7 +417,7 @@ public class PropertiesPanel : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedPropertyItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/Assets/Scripts/Zone Display/ZoneRenderer.cs b/Assets/Scripts/Zone Display/ZoneRenderer.cs index 74bd497c4..d5d849e7d 100644 --- a/Assets/Scripts/Zone Display/ZoneRenderer.cs +++ b/Assets/Scripts/Zone Display/ZoneRenderer.cs @@ -611,7 +611,7 @@ public class ZoneRenderer : MonoBehaviour private static AetheriaRuntimeCatalogItem FindTypedZoneItem(ItemInstance item) { - var itemId = item?.Data?.ItemId ?? Guid.Empty; + var itemId = item?.ItemId ?? Guid.Empty; return itemId == Guid.Empty ? null : ActionGameManager.RuntimeCatalog?.FindItemByLegacyId(itemId.ToString("D")); diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 9114d9a8b..8c689faed 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -545,9 +545,10 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. escape `ItemManager`; gameplay stat modifiers target live behavior instances and package-owned behavior metadata instead of rebuilding config DTOs for lookup. - `RuntimeItemReference.ItemId` is the only item reference value. The reader - interface for this bridge is named `IRuntimeItemCatalogReader` and exposes - only typed catalog row lookup. Behavior + `ItemInstance.ItemId` is the runtime identity surface; `RuntimeItemReference` + remains only the backing compatibility reference until native typed item + instances replace it. The reader interface for this bridge is named + `IRuntimeItemCatalogReader` and exposes only typed catalog row lookup. Behavior 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. @@ -1052,6 +1053,10 @@ First Aetheria surfaces to publish: - Done: demote `RuntimeItemReference.Value` to an item-definition id, then delete `RuntimeItemReference.Projection`; item references no longer carry hydrated `ItemData` DTOs. + - Done: add `ItemInstance.ItemId` as the direct runtime identity surface and + move live runtime/UI/catalog lookup call sites off `.Data.ItemId`. The old + `Data` field is now compatibility backing state rather than the identity + API callers use. - Done: delete the dead `ItemManager.GetRuntimeItemProjection` bridge after loadout generation stopped hydrating selected typed rows into `EquippableItemData` merely to instantiate equipment.