From d2996bc072f468587e2fc7b02ad97d7f0e665b00 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 15 Jun 2026 00:06:17 +0100 Subject: [PATCH] Prefer typed item keys in runtime commits --- .voidbot/state/aetheria.cc | Bin 91288 -> 91948 bytes Aetheria.State.Unity.Smoke/Program.cs | 27 ++++++++++------ .../AetheriaRuntimeCommitLogApplier.cs | 17 +++++++--- Aetheria.State/README.md | 4 +++ Assets/Scripts/Gameplay/ActionBarSlot.cs | 12 +++---- Assets/Scripts/Gameplay/ActionGameManager.cs | 18 +++++++++-- .../AetheriaRuntimeStateCommitDocument.cs | 15 +++++++++ docs/aetheria-perfect-machine-map.md | 30 +++++++++++------- 8 files changed, 90 insertions(+), 33 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 89a4bc4891926e450f629d023ee4fcf26230229b..c286ac588a130bb497459f0610b1a82eda9ab672 100644 GIT binary patch delta 1887 zcmah~O=w(I6!xY~n$RY#n3$Ssd&GsbWG0bB^HWihCeSfc8mBRsL5O$WyEE^a_uhTI z_r4k5YAAwWSBAHE?p)YXD5Vra$)f%&q+k&Rca6AqBPG&}8yBAUGnpi$xS2QHd+xd4 z`M&R*`_-e)JHK|`yU}rMY4OcOlGsz`nof@&xbbtb`X(WdgZG;uCAxfL*FG=&7e;E?m}t_`*Ca zFy=u+Vm`MPQ{*IGgK9>hXgjiD#eDvsyTO#a&VYKJ9Uw{CQYm*aYk+QM2C|6QRsJ@0 z4NJ%ptExYqoA~S-6n(20(vRQX82;_2uJH8JzV{YVMv<bGa@}Z+0@4Rlj|h> zSN1J0Ur8$S6{6uTx-y1GZ7d$`f_$~lfEIWe8aYFqPJ?*RB-V@>3NeQ3pASYq_K|CsE~P5$vVZ1&XmD-quXAUlVaKFU zQq>Vz%xko|M9xKD9w)_)ZbLN4cuoMZ}{nZbxF zr>oRfEF|v?ymEhUZ>Fu7Whq1tkCC^IWBcPc&&6^kxAygtm#5X925paw_KYYL7Z=e& zI1{Me0B5U3DVO!bT@NzE`@m8kLOp8+n%@i{s4LX!qHu4Bf3HccOJ5-vE(6(9(+i? rYcGzEC6Ayu)D?ZbLY!S26Y)lrE0bn>@y*eAar2il`Jrdm>R97&nfX8e2XQkn_uc#6x#ygF zZ~QRy#hsy>R|lS$n34Na$lLs zbF)VeJUg&_v3=se(w*jWv*baYsONP`qesyvj{qmq5LTmWUHlb|@)e%m0s-n~c!-4}6N*zBXXk2UX~(WIaw50o0_ zl8qBxR9tA^@kk*(Zlj;%5_vF}xP)NRFWngGLH)%FaLi$(3{lwpGiOt_ROol11{(muEBH()) .Select(resource => new AetheriaBodyResource { - ItemKey = ReferenceKey("aetheria.item_definition", resource.ItemDefinitionLegacyId ?? ""), + ItemKey = ReferenceKey(resource.ItemKey, "aetheria.item_definition", resource.ItemDefinitionLegacyId ?? ""), Amount = resource.Amount }) .ToArray(); @@ -464,7 +464,7 @@ public static class AetheriaRuntimeCommitLogApplier Heatstroke = entity.Heatstroke, Hypothermia = entity.Hypothermia, FactionKey = ReferenceKey("aetheria.corporation", entity.CorporationLegacyId ?? ""), - HullItemKey = ReferenceKey("aetheria.item_definition", entity.HullItemDefinitionLegacyId ?? ""), + HullItemKey = ReferenceKey(entity.HullItemKey, "aetheria.item_definition", entity.HullItemDefinitionLegacyId ?? ""), Equipment = ToEntityItemSlots(entity.Equipment), CargoBays = ToEntityItemSlots(entity.CargoBays), DockingBays = ToEntityItemSlots(entity.DockingBays), @@ -624,7 +624,7 @@ public static class AetheriaRuntimeCommitLogApplier return (consumables ?? Array.Empty()) .Select(consumable => new AetheriaActiveConsumableSnapshot { - ItemKey = ReferenceKey("aetheria.item_definition", consumable.ItemDefinitionLegacyId ?? ""), + ItemKey = ReferenceKey(consumable.ItemKey, "aetheria.item_definition", consumable.ItemDefinitionLegacyId ?? ""), Quality = consumable.Quality, RemainingDuration = consumable.RemainingDuration, Duration = consumable.Duration @@ -666,7 +666,7 @@ public static class AetheriaRuntimeCommitLogApplier { ControlPath = binding.ControlPath ?? "", Kind = binding.Kind ?? "", - TargetKey = ReferenceKey("aetheria.item_definition", binding.ItemDefinitionLegacyId ?? ""), + TargetKey = ReferenceKey(binding.ItemKey, "aetheria.item_definition", binding.ItemDefinitionLegacyId ?? ""), EquipmentIndex = binding.EquipmentIndex, BehaviorIndex = binding.BehaviorIndex, WeaponGroup = binding.WeaponGroup @@ -712,6 +712,13 @@ public static class AetheriaRuntimeCommitLogApplier return string.IsNullOrWhiteSpace(legacyId) ? "" : $"{documentName}:legacy:{legacyId}"; } + private static string ReferenceKey(string typedKey, string documentName, string legacyId) + { + return !string.IsNullOrWhiteSpace(typedKey) + ? typedKey + : ReferenceKey(documentName, legacyId); + } + private static string StableToken(string value) { var chars = (string.IsNullOrWhiteSpace(value) ? "unnamed" : value.Trim().ToLowerInvariant()) diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index caf391c09..781f45dec 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -87,6 +87,10 @@ derived legacy-GUID compatibility projection for broader simulation paths. Cargo inventory indexes, consumable activation lookup, action-bar consumable quantity/fill, transfer lookup, trade owned counts, weapon ammo references, and item-use behavior references now use item keys. +Unity runtime commit DTOs also carry typed `ItemKey`/`HullItemKey` fields for +loadout items, action-bar targets, body resources, entity hulls, and active +consumables. Their old `*LegacyId` fields remain import/export compatibility +only; the commit applier prefers typed keys whenever present. The old generic `RuntimeCatalogLink` abstraction, `ItemManager.GetData` hydration path, vague `ItemInstance.Data` identity field, and old `RuntimeItemReference.Projection` cache have been deleted; runtime item facts diff --git a/Assets/Scripts/Gameplay/ActionBarSlot.cs b/Assets/Scripts/Gameplay/ActionBarSlot.cs index e9b4e3d9e..904785c3e 100644 --- a/Assets/Scripts/Gameplay/ActionBarSlot.cs +++ b/Assets/Scripts/Gameplay/ActionBarSlot.cs @@ -94,8 +94,8 @@ public class ActionBarConsumableBinding : ActionBarBinding else Slot.Fill.fillAmount = instance.RemainingDuration / instance.Duration; } - private string TargetItemKey => - Guid.TryParse(Target.LegacyId, out var legacyId) ? AetheriaRuntimeItemReference.FromLegacyId(legacyId) : ""; + public string TargetItemKey => + Guid.TryParse(Target?.LegacyId, out var legacyId) ? AetheriaRuntimeItemReference.FromLegacyId(legacyId) : ""; public string TargetItemDefinitionLegacyId => Target?.LegacyId ?? ""; @@ -116,14 +116,14 @@ public class ActionBarGearBinding : ActionBarBinding { get { - var itemKey = Item?.EquippableItem?.ItemKey ?? ""; - const string legacyPrefix = "aetheria.item_definition:legacy:"; - return itemKey.StartsWith(legacyPrefix, StringComparison.OrdinalIgnoreCase) - ? itemKey.Substring(legacyPrefix.Length) + return AetheriaRuntimeItemReference.ToLegacyId(TargetItemKey) is var legacyId && legacyId != Guid.Empty + ? legacyId.ToString("D") : ""; } } + public string TargetItemKey => Item?.EquippableItem?.ItemKey ?? ""; + public ActionBarGearBinding(Entity entity, ActionBarSlot slot, EquippedItem item, IActivatedBehavior behavior) : base(entity, slot) { Item = item; diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index c99a6b007..5e4eda815 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -523,6 +523,7 @@ public class ActionGameManager : MonoBehaviour return new AetheriaRuntimeLoadoutItemCommit { ItemDefinitionLegacyId = item.ItemId == Guid.Empty ? "" : item.ItemId.ToString("D"), + ItemKey = item.ItemKey, 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, @@ -569,7 +570,8 @@ public class ActionGameManager : MonoBehaviour { ControlPath = slot.ControlPath ?? "", Kind = "consumable", - ItemDefinitionLegacyId = consumable.TargetItemDefinitionLegacyId + ItemDefinitionLegacyId = consumable.TargetItemDefinitionLegacyId, + ItemKey = consumable.TargetItemKey }; case ActionBarGearBinding gear: return new AetheriaRuntimeActionBarBindingCommit @@ -577,6 +579,7 @@ public class ActionGameManager : MonoBehaviour ControlPath = slot.ControlPath ?? "", Kind = "gear", ItemDefinitionLegacyId = gear.TargetItemDefinitionLegacyId, + ItemKey = gear.TargetItemKey, EquipmentIndex = gear.EquipmentIndex, BehaviorIndex = gear.BehaviorIndex }; @@ -676,6 +679,7 @@ public class ActionGameManager : MonoBehaviour .Select(pair => new AetheriaRuntimeBodyResourceCommit { ItemDefinitionLegacyId = LegacyId(pair.Key), + ItemKey = AetheriaRuntimeItemReference.FromLegacyId(pair.Key), Amount = pair.Value }) .ToArray() ?? Array.Empty(), @@ -707,6 +711,7 @@ public class ActionGameManager : MonoBehaviour .Select(pair => new AetheriaRuntimeBodyResourceCommit { ItemDefinitionLegacyId = LegacyId(pair.Key), + ItemKey = AetheriaRuntimeItemReference.FromLegacyId(pair.Key), Amount = pair.Value }) .ToArray() ?? Array.Empty(), @@ -821,6 +826,7 @@ public class ActionGameManager : MonoBehaviour Hypothermia = entity.Hypothermia, CorporationLegacyId = entity.Faction?.ID.ToString("D") ?? "", HullItemDefinitionLegacyId = entity.Hull?.ItemId == Guid.Empty ? "" : entity.Hull.ItemId.ToString("D"), + HullItemKey = entity.Hull?.ItemKey ?? "", Equipment = ProjectEquippedSlots(entity.Equipment), CargoBays = ProjectEquippedSlots(entity.CargoBays), DockingBays = ProjectEquippedSlots(entity.DockingBays), @@ -1183,6 +1189,7 @@ public class ActionGameManager : MonoBehaviour .Select(effect => new AetheriaRuntimeActiveConsumableCommit { ItemDefinitionLegacyId = effect.Item?.ItemId == Guid.Empty ? "" : effect.Item.ItemId.ToString("D"), + ItemKey = effect.Item?.ItemKey ?? "", Quality = effect.Item?.Quality ?? 1.0, RemainingDuration = effect.RemainingDuration, Duration = effect.Duration @@ -1334,7 +1341,7 @@ public class ActionGameManager : MonoBehaviour { item ??= new AetheriaRuntimeLoadoutItemCommit(); return new AetheriaRuntimeLoadoutItemSnapshot( - ReferenceKey("aetheria.item_definition", item.ItemDefinitionLegacyId ?? ""), + ReferenceKey(item.ItemKey, "aetheria.item_definition", item.ItemDefinitionLegacyId ?? ""), item.Quality, item.Durability, item.Quantity, @@ -1366,6 +1373,13 @@ public class ActionGameManager : MonoBehaviour return string.IsNullOrWhiteSpace(legacyId) ? "" : $"{prefix}:{legacyId}"; } + private static string ReferenceKey(string typedKey, string prefix, string legacyId) + { + return !string.IsNullOrWhiteSpace(typedKey) + ? typedKey + : ReferenceKey(prefix, legacyId); + } + private void OnApplicationQuit() => QueueRunCheckpoint("application-quit"); private void QueueRunCheckpoint(string reason) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs index 3367fbc56..e001c76d7 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateCommitDocument.cs @@ -187,6 +187,9 @@ namespace GameCult.Aetheria.State.Unity [Key(4)] public bool Enabled { get; set; } = true; + + [Key(5)] + public string ItemKey { get; set; } = ""; } [MessagePackObject] @@ -266,6 +269,9 @@ namespace GameCult.Aetheria.State.Unity [Key(5)] public int WeaponGroup { get; set; } = -1; + + [Key(6)] + public string ItemKey { get; set; } = ""; } [MessagePackObject] @@ -388,6 +394,9 @@ namespace GameCult.Aetheria.State.Unity [Key(1)] public double Amount { get; set; } + + [Key(2)] + public string ItemKey { get; set; } = ""; } [MessagePackObject] @@ -610,6 +619,9 @@ namespace GameCult.Aetheria.State.Unity [Key(34)] public IReadOnlyList Contacts { get; set; } = Array.Empty(); + + [Key(35)] + public string HullItemKey { get; set; } = ""; } [MessagePackObject] @@ -658,6 +670,9 @@ namespace GameCult.Aetheria.State.Unity [Key(3)] public double Duration { get; set; } + + [Key(4)] + public string ItemKey { get; set; } = ""; } [MessagePackObject] diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 97bb73f2b..77190137b 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -496,10 +496,13 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. - The dead Unity `NameFile` projection class has been deleted. Runtime name generation reads `AetheriaRuntimeNameFile` records from the typed catalog facade; legacy `GameData/NameFile/*.msgpack` remains migration input only. -- Pending Unity runtime commit envelopes now name their source catalog IDs as - `CorporationLegacyId`, `ItemDefinitionLegacyId`, and - `HullItemDefinitionLegacyId`; the applier has always projected those fields - into typed corporation and item-definition record keys. +- Pending Unity runtime commit envelopes now carry typed item keys for loadout + items, action-bar targets, body resources, entity hulls, and active + consumables. The older `ItemDefinitionLegacyId` and + `HullItemDefinitionLegacyId` fields remain compatibility import/export + fields; the applier prefers `ItemKey`/`HullItemKey` whenever present. + Corporation legacy IDs still translate to typed corporation record keys at + the commit boundary. - Entity restore and loadout manufacturer-distance weighting no longer read legacy `Faction` entries through `ItemManager`; they use `Galaxy.ResolveFaction` over the typed corporation projection. @@ -626,7 +629,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. transfer lookup, and trade owned-count rows now use item keys rather than GUID-owned cargo indexes. Weapon ammo and item-use behavior config item references are also typed-key-first (`AmmoItemKey`/`ItemKey`), with - `AmmoType`/`Item` only derived GUID compatibility; + `AmmoType`/`Item` only derived GUID compatibility. Runtime commit DTOs now + publish item and hull identity through `ItemKey`/`HullItemKey`, with legacy + ID fields demoted to compatibility; there is no remaining `ItemInstance.Data` identity/backing field. The reader interface for this bridge is named `IRuntimeItemCatalogReader` and exposes only typed catalog row lookup. Behavior @@ -1206,9 +1211,9 @@ First Aetheria surfaces to publish: in the typed state package's `.cc` reader. - In progress: convert domain references from GUID/base-class patterns to typed record refs. Item instances, cargo inventory indexes, weapon ammo - references, and item-use behavior references now carry typed item keys; - remaining broader simulation paths still derive legacy GUIDs until those - structures move to typed keys. + references, item-use behavior references, and runtime commit item/hull + surfaces now carry typed item keys; remaining broader simulation paths + still derive legacy GUIDs until those structures move to typed keys. - Remove runtime dependency on `ItemData` DTOs as item instance owners. 5. Mesh host @@ -1327,13 +1332,16 @@ First Aetheria surfaces to publish: derived legacy compatibility for unfinished cargo and simulation paths. - Done: move `EquippedCargoBay.ItemsOfType`, consumable activation lookup, action-bar consumable quantity/fill, item transfer lookup, and trade owned - counts from derived `Guid ItemId` keys to typed `ItemKey` strings. GUID - behavior-config fields still translate at the cargo boundary until - behavior config construction moves to typed item references. + counts from derived `Guid ItemId` keys to typed `ItemKey` strings. - Done: move weapon ammo and `ItemUsage` config references from GUID fields to typed item-key fields. `AmmoType` and `Item` remain derived compatibility properties, but runtime ammo consumption, item use, and HUD ammo counts use `AmmoItemKey`/`ItemKey`. + - Done: add typed `ItemKey`/`HullItemKey` fields to runtime commit item + surfaces and make the applier prefer them over stale legacy-ID fields. + Loadout items, action-bar targets, body resources, entity hulls, cargo + contents, and active consumables now prove typed-key ownership in the + Unity smoke by carrying intentionally stale legacy IDs. - Done: delete the dead `ItemManager.GetRuntimeItemProjection` bridge after loadout generation stopped hydrating selected typed rows into `EquippableItemData` merely to instantiate equipment.