From b3e91999be0a07709d48accf89205bd769685679 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 13 Jun 2026 17:38:05 +0100 Subject: [PATCH] Cut ambient runtime catalog lookup --- .voidbot/state/aetheria.cc | Bin 42143 -> 42730 bytes Assets/Scripts/Gameplay/ActionBarSlot.cs | 2 +- Assets/Scripts/Gameplay/ActionGameManager.cs | 3 +- Assets/Scripts/ServerShared/Entity.cs | 6 +-- .../Scripts/ServerShared/EntitySerializer.cs | 4 +- Assets/Scripts/ServerShared/ItemManager.cs | 48 ++++++++++++++---- .../RuntimeProjection/RuntimeCatalogEntry.cs | 34 ++++++------- Assets/Scripts/UI/Menu/InventoryMenu.cs | 2 +- Assets/Scripts/UI/Menu/InventoryPanel.cs | 8 +-- Assets/Scripts/UI/Menu/SectorRenderer.cs | 6 +-- Assets/Scripts/UI/Menu/TradeMenu.cs | 2 +- .../UI/Properties Panel/PropertiesPanel.cs | 4 +- Assets/Scripts/Zone Display/ZoneRenderer.cs | 2 +- docs/aetheria-perfect-machine-map.md | 8 +++ 14 files changed, 81 insertions(+), 48 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index b974bbd3d400ddecbbaf00daa72150c83f36431f..972db108280a37e3802661b8186c40c95872c988 100644 GIT binary patch delta 1634 zcmZuy-D_M$6gO#1O>8mRC>FI&r8Q7?Z#G|>H3>pZ&@Lo2EwxCB53_U6?j18bbD5dD zaVeVCibZ@VIw0B?1AY`l(Xy|CL{ad;j|X2`#6Livd=lS0bMMVfZGF3(ojK<>zmKyY z{Luf$kNsbM(my;kJvUhkW~QE6d%N#J_g(*6JC*5~w6gX7piB1HqMDt%XW+5^cfaV3 z4g7wnH+Vtb=U%;H+$$FzAm@&QjX-lsSYio&l2|JS#*|w^HK=eGUq7%(G#Dj1ph;7! zHhErh+a)d9hFH)p;TGD&SZX2omV_I2g``780;WW$4AT}XR8kK?s*Mar`nbe$B?}au2iuMDw#J9JQhnd71{!+c zF-R<@JorMDY8^Y$4wRc*0HKMEltysDr|1v-JPl3r+g&gArpAs9E-$ap7-uo1Lz8lu znznckLIQ0f9;YerPRZo)7`!IPF{FwJRM-79^Jwq;^1flWRvTGf`OoXUtryWM7QE+6 zWOwaBr=){rKKXA8KgcsJp|p!>+Qr_nkMN zbpH&GY_dDe+1>S!u4BB1TA|LaTRX#_}w{sBGzKLPXkA{*3X?}RY;3_6}01{sO- z8I&WTV#a;-#?jun7yf=?HY-+iYcBB53eNhVjX%R>m?QMeF7O2Y^WXu&?&$Tc?Hn8N%haPc1R|fCBt!dv8w_O=sAdQ3zRGA5& zI3&MyH1SKT+@O|4J~MOGN~ID^2b0Z-+uE$IX8Wx;it{lOKJ|Iabd~t<`|x`2;ff;> z4gG%0OPYYz=+lT><4&EQAFa;ii+iHB_K~G6wC35~*7@cD`Mhv$8B=#%K#Q_&d3Ou+ z?3MjPL&a_P%btTf%e`7jSN=EeeO*+l`JX^iRBCBu`s&4<%It)%^nSg%Jyeut*8T;S Cs85Fg delta 1161 zcmY*Z&r2Ow6pk-eq9JG!BqSm66d~54!+Yb?Mw5*Y5f^q*lz?<|-<>mWZk)Myxc82~ zDA=yL5GiuANH8IrB!#w%miYrDi!QP#WNQe4Ze0}mAN1VuJ!xQI;Jate`Of!!b5H)N zy?9&u{dH|1tj{&WU}|c5?VxAa{aM@VBF#pHsPj8#$W(<~=)F~Y9F=3eA8)(22gZFj zdL{gE9&LhJFkn%H5irn&v?4=TU4j**(sf}W*Jw~$)DSD}zJGG_q5&o&;DrU_M%uv@ z6TIRn6WQ^Hl>|ZJCb;?d^FhcNUuSKEOi@?k_TBZtNbw@0ZU$nlGH}1n-q-~pt)ht! zI%i-Lt%`O+Z-j-7PspTd6E#uU6gE*rpsg7ZmhGxmql~IkW0^%@1=VO_w}YQ8N+Xnf z-*abG5&$h`d6KCJVFP!yhy`bs&Ve4A2m=}8iI50|K?4hsuu8*By(qUh-`yauOvX-dSNRNM)ggzGWt? z^&XRZ)Oo!c9{j<$@3EBSX-9+Oldo~h`T*q27%(Jr8j;?_qq_-t;x^);j&Y2dORkX= zHylYc(uy(@vsM)ojd@DsNm`O~k=l|Bh{T%Ql_Wo@zg^k+e?2ENZxFFPwF^%jpvE*T zMJDMaXA7t4;^Y;2X)Lk`R1A!B%&Smz0!ZB?07q^`~DXL?(xIn zFkG^jEqCTg1*wvLGH&I{XNhvgQq=~O^c(0Zbnc(U@$#p|GmPxQHe57imktm<~3{m?}kb&r%I&)@W)LCv-Q0LfOIjsO4v diff --git a/Assets/Scripts/Gameplay/ActionBarSlot.cs b/Assets/Scripts/Gameplay/ActionBarSlot.cs index 8f5c12791..0c6f29c76 100644 --- a/Assets/Scripts/Gameplay/ActionBarSlot.cs +++ b/Assets/Scripts/Gameplay/ActionBarSlot.cs @@ -99,7 +99,7 @@ public class ActionBarGearBinding : ActionBarBinding public ActionBarGearBinding(Entity entity, ActionBarSlot slot, EquippedItem item, IActivatedBehavior behavior) : base(entity, slot) { Item = item; - var data = item.EquippableItem.Data.Value as EquippableItemData; + var data = entity.ItemManager.GetData(item.EquippableItem); Behavior = behavior; Slot.QuantityRemaining.gameObject.SetActive(false); Slot.Icon.gameObject.SetActive(true); diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index d2648ebf0..923e91f57 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -485,7 +485,6 @@ public class ActionGameManager : MonoBehaviour } var runtimeItemCatalog = new AetheriaRuntimeItemCatalog(RuntimeCatalog); - RuntimeCatalogLinkBase.BindRuntimeItemCatalog(runtimeItemCatalog); ItemManager = new ItemManager( runtimeItemCatalog, Settings.GameplaySettings, @@ -666,7 +665,7 @@ public class ActionGameManager : MonoBehaviour slot.Binding = new ActionBarGearBinding(CurrentEntity, slot, equippedItemDragAction.EquippedItem, trigger); return true; case ItemInstanceDragObject itemInstanceDragAction: - if (!(itemInstanceDragAction.Item.Data.Value is ConsumableItemData consumable)) return false; + if (!(ItemManager.GetData(itemInstanceDragAction.Item) is ConsumableItemData consumable)) return false; slot.Binding = new ActionBarConsumableBinding(CurrentEntity, slot, consumable); return true; case WeaponGroupDragObject weaponGroupDragAction: diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index 64133c42d..4a0513e14 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -1089,7 +1089,7 @@ public class ConsumableItemEffect { Item = item; Entity = entity; - Data = (ConsumableItemData) item.Data.Value; + Data = entity.ItemManager.GetData(item) as ConsumableItemData; RemainingDuration = Data.Duration; Behaviors = Data.Behaviors @@ -1399,7 +1399,7 @@ public class EquippedCargoBay : EquippedItem // Check whether the given item will fit when its origin is placed at the given coordinate public bool ItemFits(ItemInstance item, int2 cargoCoord) { - var itemData = item.Data.Value; + var itemData = ItemManager.GetData(item); // Check every cell of the item's shape foreach (var i in itemData.Shape.Coordinates) { @@ -1707,4 +1707,4 @@ public class BehaviorGroup } //public IAnalogBehavior Axis; -} \ No newline at end of file +} diff --git a/Assets/Scripts/ServerShared/EntitySerializer.cs b/Assets/Scripts/ServerShared/EntitySerializer.cs index a9679f7c9..6a6081de9 100644 --- a/Assets/Scripts/ServerShared/EntitySerializer.cs +++ b/Assets/Scripts/ServerShared/EntitySerializer.cs @@ -209,7 +209,7 @@ public abstract class EntityPack { foreach (var (_, item) in t) { - var itemData = item.Data.Value; + var itemData = itemManager.GetData(item); if (item is SimpleCommodity s) _price += itemData.Price * s.Quantity; else @@ -221,7 +221,7 @@ public abstract class EntityPack { foreach (var (_, item) in t) { - var itemData = item.Data.Value; + var itemData = itemManager.GetData(item); if (item is SimpleCommodity s) _price += itemData.Price * s.Quantity; else diff --git a/Assets/Scripts/ServerShared/ItemManager.cs b/Assets/Scripts/ServerShared/ItemManager.cs index 0cd297a1b..5121425b9 100644 --- a/Assets/Scripts/ServerShared/ItemManager.cs +++ b/Assets/Scripts/ServerShared/ItemManager.cs @@ -58,6 +58,34 @@ public class ItemManager return _itemData.Get(id); } + public RuntimeCatalogLink CreateLink(ItemData item) + { + return new RuntimeCatalogLink(item); + } + + public ItemData GetData(ItemInstance item) + { + Hydrate(item); + return item?.Data?.Value; + } + + public void Hydrate(ItemInstance item) + { + if (item?.Data == null || item.Data.Value != null) + { + return; + } + + var data = _itemData.Get(item.Data.LinkID); + if (data == null) + { + _logger($"Attempted to hydrate missing item id {item.Data.LinkID}"); + return; + } + + item.Data.SetValue(data); + } + public void Log(string s) { _logger(s); @@ -65,32 +93,32 @@ public class ItemManager public SimpleCommodityData GetData(SimpleCommodity item) { - return item.Data.Value as SimpleCommodityData; + return GetData((ItemInstance)item) as SimpleCommodityData; } public CraftedItemData GetData(CraftedItemInstance item) { - return item.Data.Value as CraftedItemData; + return GetData((ItemInstance)item) as CraftedItemData; } public EquippableItemData GetData(EquippableItem item) { - return item.Data.Value as EquippableItemData; + return GetData((ItemInstance)item) as EquippableItemData; } public float GetMass(ItemInstance item) { return item switch { - CraftedItemInstance _ => item.Data.Value.Mass, - SimpleCommodity commodity => item.Data.Value.Mass * commodity.Quantity, + CraftedItemInstance _ => GetData(item).Mass, + SimpleCommodity commodity => GetData(item).Mass * commodity.Quantity, _ => 0 }; } public float GetThermalMass(ItemInstance item) { - var data = item.Data.Value; + var data = GetData(item); return item switch { CraftedItemInstance _ => data.Mass * data.SpecificHeat, @@ -128,7 +156,7 @@ public class ItemManager { var newItem = new SimpleCommodity { - Data = new RuntimeCatalogLink{LinkID = item.ID}, + Data = CreateLink(item), Quantity = count }; //ItemData.Add(newItem); @@ -141,7 +169,7 @@ public class ItemManager public ItemInstance Instantiate(ItemInstance item) { - var data = item.Data.Value; + var data = GetData(item); if(data is CraftedItemData c) { var i = CreateInstance(c); @@ -163,13 +191,13 @@ public class ItemManager { return new EquippableItem { - Data = new RuntimeCatalogLink {LinkID = item.ID}, Quality = quality, Durability = equippableItemData.Durability + Data = CreateLink(item), Quality = quality, Durability = equippableItemData.Durability }; } var newCommodity = new CompoundCommodity { - Data = new RuntimeCatalogLink{LinkID = item.ID}, + Data = CreateLink(item), Quality = quality }; return newCommodity; diff --git a/Assets/Scripts/ServerShared/RuntimeProjection/RuntimeCatalogEntry.cs b/Assets/Scripts/ServerShared/RuntimeProjection/RuntimeCatalogEntry.cs index a5e807047..fd4f059b7 100644 --- a/Assets/Scripts/ServerShared/RuntimeProjection/RuntimeCatalogEntry.cs +++ b/Assets/Scripts/ServerShared/RuntimeProjection/RuntimeCatalogEntry.cs @@ -28,29 +28,27 @@ public abstract class RuntimeCatalogEntry public class RuntimeCatalogLink : RuntimeCatalogLinkBase where T : ItemData { - public T Value => ResolveRuntimeItemCatalog(LinkID); + public T Value { get; private set; } + + public RuntimeCatalogLink() + { + } + + public RuntimeCatalogLink(T value) + { + SetValue(value); + } + + public void SetValue(T value) + { + Value = value; + LinkID = value?.ID ?? Guid.Empty; + } } public class RuntimeCatalogLinkBase { public Guid LinkID; - - private static IRuntimeItemCatalogReader Catalog { get; set; } - - protected static T ResolveRuntimeItemCatalog(Guid linkId) where T : ItemData - { - if (Catalog == null) - throw new InvalidOperationException("Runtime item catalog resolution is not bound. Open typed Aetheria runtime state before reading item object graphs."); - - return Catalog.Get(linkId); - } - - public static void BindRuntimeItemCatalog(IRuntimeItemCatalogReader catalog) - { - if (catalog == null) throw new ArgumentNullException(nameof(catalog)); - - Catalog = catalog; - } } public interface ITintInspector diff --git a/Assets/Scripts/UI/Menu/InventoryMenu.cs b/Assets/Scripts/UI/Menu/InventoryMenu.cs index 3d7f60bdd..5388e6aa9 100644 --- a/Assets/Scripts/UI/Menu/InventoryMenu.cs +++ b/Assets/Scripts/UI/Menu/InventoryMenu.cs @@ -117,7 +117,7 @@ public class InventoryMenu : MonoBehaviour _selectedPanel = panel; _selectedPosition = cargoEvent.CargoBay.Cargo[item]; _selectedItem = item; - _selectedItemData = item.Data.Value; + _selectedItemData = GameManager.ItemManager.GetData(item); foreach (var v in _selectedItemData.Shape.Coordinates) { var v2 = _selectedItemData.Shape.Rotate(v, _selectedItem.Rotation) + _selectedPosition; diff --git a/Assets/Scripts/UI/Menu/InventoryPanel.cs b/Assets/Scripts/UI/Menu/InventoryPanel.cs index dc8614cc4..724af2ccb 100644 --- a/Assets/Scripts/UI/Menu/InventoryPanel.cs +++ b/Assets/Scripts/UI/Menu/InventoryPanel.cs @@ -410,7 +410,7 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler //Debug.Log("Entity Pointer Enter"); if (!(GameManager.DragObject is ItemDragObject itemDragObject)) return; var item = itemDragObject.Item; - var itemData = item.Data.Value; + var itemData = GameManager.ItemManager.GetData(item); if (!(item is EquippableItem equippableItem)) return; var placementPosition = v + itemDragObject.OriginCellOffset; if (entity.ItemFits(equippableItem, placementPosition)) @@ -586,7 +586,7 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler if (item != null) { var itemPosition = cargo.Cargo[item]; - var itemData = item.Data.Value; + var itemData = GameManager.ItemManager.GetData(item); var originalOccupancy = cargo.Data.InteriorShape.Inset(itemData.Shape, itemPosition, item.Rotation); _dragCells = originalOccupancy.Coordinates .Select(v1 => Instantiate(CellInstances[v1], DragParent, true).transform).ToArray(); @@ -633,7 +633,7 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler //Debug.Log("Inventory Pointer Enter"); if (!(GameManager.DragObject is ItemDragObject itemDragObject)) return; var item = itemDragObject.Item; - var itemData = item.Data.Value; + var itemData = GameManager.ItemManager.GetData(item); var placementPosition = v + itemDragObject.OriginCellOffset; if (cargo.ItemFits(item, placementPosition)) { @@ -851,7 +851,7 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler return Color.white * .25f; var c = float3(1); - if (item.Data.Value is EquippableItemData equippable) + if (GameManager.ItemManager.GetData(item) is EquippableItemData equippable) c = HardpointData.GetColor(equippable.HardpointType); if(!highlight) diff --git a/Assets/Scripts/UI/Menu/SectorRenderer.cs b/Assets/Scripts/UI/Menu/SectorRenderer.cs index ad27b9a8d..6a73054c1 100644 --- a/Assets/Scripts/UI/Menu/SectorRenderer.cs +++ b/Assets/Scripts/UI/Menu/SectorRenderer.cs @@ -90,17 +90,17 @@ public class SectorRenderer : MonoBehaviour, IBeginDragHandler, IDragHandler, IS Properties.AddProperty("Stars", () => starCount); var stationCount = zone.PackedContents.Entities - .Count(entity => ((HullData) entity.Hull.Data.Value).HullType == HullType.Station) + .Count(entity => (GameManager.ItemManager.GetData(entity.Hull) as HullData).HullType == HullType.Station) .ToString(); Properties.AddProperty("Stations", () => stationCount); var turretCount = zone.PackedContents.Entities - .Count(entity => ((HullData) entity.Hull.Data.Value).HullType == HullType.Turret) + .Count(entity => (GameManager.ItemManager.GetData(entity.Hull) as HullData).HullType == HullType.Turret) .ToString(); Properties.AddProperty("Turrets", () => turretCount); var shipCount = zone.PackedContents.Entities - .Count(entity => ((HullData) entity.Hull.Data.Value).HullType == HullType.Ship) + .Count(entity => (GameManager.ItemManager.GetData(entity.Hull) as HullData).HullType == HullType.Ship) .ToString(); Properties.AddProperty("Ships", () => shipCount); } diff --git a/Assets/Scripts/UI/Menu/TradeMenu.cs b/Assets/Scripts/UI/Menu/TradeMenu.cs index e9b0e403e..0a8d2e717 100644 --- a/Assets/Scripts/UI/Menu/TradeMenu.cs +++ b/Assets/Scripts/UI/Menu/TradeMenu.cs @@ -222,7 +222,7 @@ public class TradeMenu : MonoBehaviour data => data.Shape.Width*data.Shape.Height)); var items = Inventory.Cargo.Keys - .Select(ii=>(ii, ii.Data.Value)); + .Select(ii=>(ii, GameManager.ItemManager.GetData(ii))); if (MinimumSizeFilter.gameObject.activeSelf) items = items.Where(i => diff --git a/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs b/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs index 12c818fb7..5dd9be2af 100644 --- a/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs +++ b/Assets/Scripts/UI/Properties Panel/PropertiesPanel.cs @@ -382,7 +382,7 @@ public class PropertiesPanel : MonoBehaviour private void AddItemProperties(ItemInstance item) { - var data = item.Data.Value; + var data = GameManager.ItemManager.GetData(item); AddProperty(data.Description); @@ -442,7 +442,7 @@ public class PropertiesPanel : MonoBehaviour private string GetTitle(EquippableItem item) { - var data = item.Data.Value; + var data = GameManager.ItemManager.GetData(item); var (tier, upgrades) = GameManager.ItemManager.GetTier(item); return $"{data.Name} ({tier.Name}{new string('+', upgrades)})"; diff --git a/Assets/Scripts/Zone Display/ZoneRenderer.cs b/Assets/Scripts/Zone Display/ZoneRenderer.cs index 86d617cf9..c8174e271 100644 --- a/Assets/Scripts/Zone Display/ZoneRenderer.cs +++ b/Assets/Scripts/Zone Display/ZoneRenderer.cs @@ -584,7 +584,7 @@ public class ZoneRenderer : MonoBehaviour var itemPickup = gridObject.gameObject.GetComponent(); itemPickup.Item = item; itemPickup.ZoneRenderer = this; - itemPickup.ScanLabel.text = item.Data.Value.Name; + itemPickup.ScanLabel.text = ItemManager.GetData(item).Name; if (item is CraftedItemInstance craftedItemInstance) { var c = ItemManager.GetTier(craftedItemInstance).tier.Color.ToColor(); diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index ac5aae43c..5af24a752 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -623,6 +623,9 @@ First Aetheria surfaces to publish: Unity-side custom MessagePack resolver/formatter source. - Done: demote `PlayerSettings` and nested settings from MessagePack shapes after the legacy settings writer was disabled. + - Done: delete the process-global runtime catalog resolver from + `RuntimeCatalogLink`; item instances now carry hydrated identifiers and + `ItemManager` owns resolution through the typed runtime catalog reader. - Remaining: delete or quarantine old cache abstractions that no longer protect an invariant once catalog migration has a typed reader. @@ -656,6 +659,11 @@ First Aetheria surfaces to publish: can apply them into canonical typed settings/run/zone/entity state, and commands are cleared after application. It also proves renderer-emitted Eve commands are queued as typed command envelopes separately from state commits. +- Unity batchmode compile with Editor `6000.4.2f1` returned cleanly after the + runtime catalog resolver cut; `Logs/codex-unity-compile.log` has no compiler + error hits. +- `rg ".Data.Value|BindRuntimeItemCatalog|ResolveRuntimeItemCatalog|private static IRuntimeItemCatalogReader"` in + `Assets/Scripts` now finds only `ItemManager` checking its own hydrated value. - `Aetheria.State.Smoke` proves the provider-owned Eve command bridge drains `gamecult.eve.command.v1` envelopes, accepts advertised refresh commands, rejects unknown commands, persists `AetheriaEveCommandDrainStatus`, and exposes