Cut ambient runtime catalog lookup

This commit is contained in:
Meta Vens 2026-06-13 17:38:05 +01:00
commit b3e91999be
14 changed files with 79 additions and 46 deletions

Binary file not shown.

View file

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

View file

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

View file

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

View file

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

View file

@ -58,6 +58,34 @@ public class ItemManager
return _itemData.Get<T>(id);
}
public RuntimeCatalogLink<ItemData> CreateLink(ItemData item)
{
return new RuntimeCatalogLink<ItemData>(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<ItemData>{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<ItemData> {LinkID = item.ID}, Quality = quality, Durability = equippableItemData.Durability
Data = CreateLink(item), Quality = quality, Durability = equippableItemData.Durability
};
}
var newCommodity = new CompoundCommodity
{
Data = new RuntimeCatalogLink<ItemData>{LinkID = item.ID},
Data = CreateLink(item),
Quality = quality
};
return newCommodity;

View file

@ -28,29 +28,27 @@ public abstract class RuntimeCatalogEntry
public class RuntimeCatalogLink<T> : RuntimeCatalogLinkBase where T : ItemData
{
public T Value => ResolveRuntimeItemCatalog<T>(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<T>(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<T>(linkId);
}
public static void BindRuntimeItemCatalog(IRuntimeItemCatalogReader catalog)
{
if (catalog == null) throw new ArgumentNullException(nameof(catalog));
Catalog = catalog;
}
}
public interface ITintInspector

View file

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

View file

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

View file

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

View file

@ -222,7 +222,7 @@ public class TradeMenu : MonoBehaviour
data => data.Shape.Width*data.Shape.Height));
var items = Inventory.Cargo.Keys
.Select<ItemInstance, (ItemInstance item, ItemData data)>(ii=>(ii, ii.Data.Value));
.Select<ItemInstance, (ItemInstance item, ItemData data)>(ii=>(ii, GameManager.ItemManager.GetData(ii)));
if (MinimumSizeFilter.gameObject.activeSelf)
items = items.Where(i =>

View file

@ -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
$"<color=#{ColorUtility.ToHtmlStringRGB(tier.Color.ToColor())}>{data.Name}</color><smallcaps><size=60%> ({tier.Name}{new string('+', upgrades)})";

View file

@ -584,7 +584,7 @@ public class ZoneRenderer : MonoBehaviour
var itemPickup = gridObject.gameObject.GetComponent<ItemPickup>();
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();

View file

@ -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<T>`; 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