From 8337d5f5c7446d98d6deeb5e9e610d480cb4ad09 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 14 Jun 2026 22:58:02 +0100 Subject: [PATCH] Move runtime item references to typed keys --- .voidbot/state/aetheria.cc | Bin 88691 -> 89628 bytes Aetheria.State/README.md | 6 +- .../AetheriaRuntimeItemCatalog.cs | 43 ++++++++++++- .../AetheriaRuntimeItemReference.cs | 60 ++++++++++++++++++ ...a => AetheriaRuntimeItemReference.cs.meta} | 0 Assets/Scripts/ServerShared/ItemInstance.cs | 5 +- Assets/Scripts/ServerShared/ItemManager.cs | 30 +++++++-- .../RuntimeItemDefinitionReference.cs | 30 --------- docs/aetheria-perfect-machine-map.md | 39 +++++++----- 9 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 Assets/Scripts/ServerShared/AetheriaRuntimeItemReference.cs rename Assets/Scripts/ServerShared/{RuntimeItemDefinitionReference.cs.meta => AetheriaRuntimeItemReference.cs.meta} (100%) delete mode 100644 Assets/Scripts/ServerShared/RuntimeItemDefinitionReference.cs diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 14c2243f7b0324d8b9cc4da809b4283f9ee5806d..a2323796edbca39a97ad55666b52e26ac8fe872c 100644 GIT binary patch delta 1731 zcmZuyUu+ab7+#rw=>`TzTfxz zee>7lP48UU^y!CfUBe@zr2~a0O2z2alW2!tYkR#j4UOnOGg~#!ENxB$j~A!Up+4Q2 z-PLyDm&Rb$`f}i{${C$USb#H!%`um$dJfVm%xnrrsyZg2a=3th zg%2#3Fz-?@y5Z)2&r0A$LcDF!$mSGe%-ETIq;j1){2Gd8U- zpDD)u(FEM+L1vH577}=Ai3Nl8IAj2@CS@R)N1$BMtUKd=Se z2gI^~PXif(R;ZvL1Z;&0TMqH7u$(XYR7i&fSUM!2cn-eVJQj<>Ns&p3`{nN17)U>Nb6mfYK_7kw0{^Zv_bAXIxQKK}FE&RrpF6Xr{z(nE- zaoss$)%4k$JKlVuC;E9GdbDxqr|)_uCSp!fcVK!Z0I|p>J!b2=ZvlJa@8mlW*;0K= zIr`=o&oth?^>?P@wf7)+<0*a48_?hA4pT@s43sW?ezqqvw^X~MY>>MS~O|N-e`6hz0%0sF5jQRI2e&E+TLSSm2YN`ma=I7(XlCT zK^>H*EXU(E=n6&`7~aNDOG!aSO#l{3Q3hY-L>*i^xLy&FPhfZ z5B0W#Ntmnj&avH*|1j!!(7f7tNyP#cpyE*3pow(zq@I1Fw=IYD{BzsP1O3w%r|MNP zN#I-p+LRuz!7$P*7q+8ZwCfSH4F&q@?Lm#!`lILD(Vi{ov@e#X-&dpx%6xHkr5&Bm z?!J@`x4bD|UQTGtS3%))x~l8@zWTcE&#nFbYVC{1 zP3`-Kj`SaNhlctm?>QaG$hfmEe%Exj5k8!TW7&LbC6XJ=BCRc5O=k|(dRn}Fx80eJZ4xROAw-AKAn4k2_Fao;LRxD9yg#W!tfBGfMqt# zrAq4~RKr;oGiE^XLd76>0n^l$%H8xe!V)0NAi?l4Ktks}q7)u3y-dUzr}H+~ppB|{ zrlMF7RG}mVLQ%=^Z{jZG>jZ3r1~yB=0@5j62>&4k7uq26K^6&~kcJs9#VN`cFgkI* z&y%9aOBO$B_lZHFDPieZ-e8z!*rwxFhZA)fPG(if*ImwbS(hk%$x5dtYFe9`* z7Gy>EOjX^dOn7Cf#<8eBtr@IcU)Z}opC4lpVfUmWP!X#JlKJ~mbCRLze#%@!f@PLk zF>s%4nmJqPGLPctvL}8Yx5i6TopIOl=6GSM^H^$LQckaW_80xF$Eo5-n2PKx74@C!QA9S!%8I8<=IW`&V!cOj~ktylWmRb z_(SuK`Uc7MXFDZbHLqK3LT(`b*1V0j%(`UvMMthA4jjmK(#wm^okl3DoxL#O%(tz? I1_vg80>g5;l>h($ diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index 2ca309856..b8fa63432 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -81,8 +81,10 @@ Dead legacy catalog roots for user records and galaxy map-layer resources have been deleted from live Unity source. Surviving runtime DTOs no longer carry legacy catalog group/table annotations; their remaining metadata is projection and inspection metadata for the typed runtime bridge. -Item instances now carry `RuntimeItemDefinitionReference`, a narrow -item-definition id. +Item instances now carry `AetheriaRuntimeItemReference`, a typed item-key +facade. `ItemInstance.ItemKey` is the identity surface, while `ItemId` is a +derived legacy-GUID compatibility projection for unfinished cargo and +simulation paths. 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/ServerShared/AetheriaRuntimeItemCatalog.cs b/Assets/Scripts/ServerShared/AetheriaRuntimeItemCatalog.cs index 4f1f87f4f..2b3754f23 100644 --- a/Assets/Scripts/ServerShared/AetheriaRuntimeItemCatalog.cs +++ b/Assets/Scripts/ServerShared/AetheriaRuntimeItemCatalog.cs @@ -5,25 +5,62 @@ using GameCult.Aetheria.State.Unity; public interface IRuntimeItemCatalogReader { + AetheriaRuntimeCatalogItem GetRuntimeItem(string itemKey); AetheriaRuntimeCatalogItem GetRuntimeItem(Guid guid); } public sealed class AetheriaRuntimeItemCatalog : IRuntimeItemCatalogReader { - private readonly Dictionary _typedItems; + private const string ItemDefinitionPrefix = "aetheria.item_definition:"; + private const string LegacyItemDefinitionPrefix = "aetheria.item_definition:legacy:"; + + private readonly Dictionary _typedItemsByKey; + private readonly Dictionary _typedItemsByLegacyId; public AetheriaRuntimeItemCatalog(AetheriaRuntimeCatalogSnapshot catalog) { if (catalog == null) throw new ArgumentNullException(nameof(catalog)); - _typedItems = catalog.Items + _typedItemsByKey = catalog.Items + .Where(item => !string.IsNullOrWhiteSpace(item.LegacyId)) + .ToDictionary(item => ToItemKey(item.LegacyId), item => item, StringComparer.OrdinalIgnoreCase); + + _typedItemsByLegacyId = catalog.Items .Where(item => Guid.TryParse(item.LegacyId, out _)) .ToDictionary(item => Guid.Parse(item.LegacyId), item => item); } + public AetheriaRuntimeCatalogItem GetRuntimeItem(string itemKey) + { + if (string.IsNullOrWhiteSpace(itemKey)) + return null; + + if (_typedItemsByKey.TryGetValue(itemKey, out var item)) + return item; + + return Guid.TryParse(RemoveItemPrefix(itemKey), out var legacyId) + ? GetRuntimeItem(legacyId) + : null; + } + public AetheriaRuntimeCatalogItem GetRuntimeItem(Guid guid) { - _typedItems.TryGetValue(guid, out var item); + _typedItemsByLegacyId.TryGetValue(guid, out var item); return item; } + + private static string ToItemKey(string legacyId) + { + return string.IsNullOrWhiteSpace(legacyId) ? "" : $"{LegacyItemDefinitionPrefix}{legacyId}"; + } + + private static string RemoveItemPrefix(string itemKey) + { + if (itemKey.StartsWith(LegacyItemDefinitionPrefix, StringComparison.OrdinalIgnoreCase)) + return itemKey.Substring(LegacyItemDefinitionPrefix.Length); + + return itemKey.StartsWith(ItemDefinitionPrefix, StringComparison.OrdinalIgnoreCase) + ? itemKey.Substring(ItemDefinitionPrefix.Length) + : itemKey; + } } diff --git a/Assets/Scripts/ServerShared/AetheriaRuntimeItemReference.cs b/Assets/Scripts/ServerShared/AetheriaRuntimeItemReference.cs new file mode 100644 index 000000000..b7df3cabd --- /dev/null +++ b/Assets/Scripts/ServerShared/AetheriaRuntimeItemReference.cs @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +using System; +using Unity.Mathematics; + +public interface INamedEntry +{ + string EntryName { get; set; } +} + +public class AetheriaRuntimeItemReference +{ + private const string ItemDefinitionPrefix = "aetheria.item_definition:"; + private const string LegacyItemDefinitionPrefix = "aetheria.item_definition:legacy:"; + + public string ItemKey; + + public AetheriaRuntimeItemReference() + { + } + + public AetheriaRuntimeItemReference(string itemKey) + { + ItemKey = itemKey; + } + + public AetheriaRuntimeItemReference(Guid legacyItemId) + : this(FromLegacyId(legacyItemId)) + { + } + + public Guid LegacyItemId => TryParseLegacyId(ItemKey, out var itemId) ? itemId : Guid.Empty; + + public static string FromLegacyId(Guid legacyItemId) + { + return legacyItemId == Guid.Empty ? "" : $"{LegacyItemDefinitionPrefix}{legacyItemId:D}"; + } + + private static bool TryParseLegacyId(string itemKey, out Guid itemId) + { + itemId = Guid.Empty; + if (string.IsNullOrWhiteSpace(itemKey)) + return false; + + var legacyId = itemKey.StartsWith(LegacyItemDefinitionPrefix, StringComparison.OrdinalIgnoreCase) + ? itemKey.Substring(LegacyItemDefinitionPrefix.Length) + : itemKey.StartsWith(ItemDefinitionPrefix, StringComparison.OrdinalIgnoreCase) + ? itemKey.Substring(ItemDefinitionPrefix.Length) + : itemKey; + + return Guid.TryParse(legacyId, out itemId); + } +} + +public interface ITintInspector +{ + float3 TintColor { get; } +} diff --git a/Assets/Scripts/ServerShared/RuntimeItemDefinitionReference.cs.meta b/Assets/Scripts/ServerShared/AetheriaRuntimeItemReference.cs.meta similarity index 100% rename from Assets/Scripts/ServerShared/RuntimeItemDefinitionReference.cs.meta rename to Assets/Scripts/ServerShared/AetheriaRuntimeItemReference.cs.meta diff --git a/Assets/Scripts/ServerShared/ItemInstance.cs b/Assets/Scripts/ServerShared/ItemInstance.cs index cbfcab064..6c13c7941 100644 --- a/Assets/Scripts/ServerShared/ItemInstance.cs +++ b/Assets/Scripts/ServerShared/ItemInstance.cs @@ -12,10 +12,11 @@ using static Unity.Mathematics.math; public abstract class ItemInstance { - public RuntimeItemDefinitionReference Reference; + public AetheriaRuntimeItemReference Reference; public ItemRotation Rotation; - public Guid ItemId => Reference?.ItemId ?? Guid.Empty; + public string ItemKey => Reference?.ItemKey ?? ""; + public Guid ItemId => Reference?.LegacyItemId ?? Guid.Empty; } public abstract class CraftedItemInstance : ItemInstance diff --git a/Assets/Scripts/ServerShared/ItemManager.cs b/Assets/Scripts/ServerShared/ItemManager.cs index e93188204..23c577840 100644 --- a/Assets/Scripts/ServerShared/ItemManager.cs +++ b/Assets/Scripts/ServerShared/ItemManager.cs @@ -52,7 +52,11 @@ public class ItemManager public AetheriaRuntimeCatalogItem GetRuntimeItem(ItemInstance item) { - return GetRuntimeItem(item?.ItemId ?? Guid.Empty); + return item == null + ? null + : !string.IsNullOrWhiteSpace(item.ItemKey) + ? _runtimeItems.GetRuntimeItem(item.ItemKey) + : GetRuntimeItem(item.ItemId); } public AetheriaRuntimeCatalogItem GetRuntimeItem(Guid itemId) @@ -532,9 +536,21 @@ public class ItemManager return shape; } - public RuntimeItemDefinitionReference CreateReference(Guid itemId) + public AetheriaRuntimeItemReference CreateReference(AetheriaRuntimeCatalogItem item) { - return new RuntimeItemDefinitionReference(itemId); + return new AetheriaRuntimeItemReference(ToItemKey(item)); + } + + public AetheriaRuntimeItemReference CreateReference(Guid itemId) + { + return new AetheriaRuntimeItemReference(itemId); + } + + private static string ToItemKey(AetheriaRuntimeCatalogItem item) + { + return item != null && Guid.TryParse(item.LegacyId, out var itemId) + ? AetheriaRuntimeItemReference.FromLegacyId(itemId) + : ""; } public void Log(string s) @@ -628,7 +644,7 @@ public class ItemManager { return new SimpleCommodity { - Reference = CreateReference(itemId), + Reference = CreateReference(item), Quantity = count }; } @@ -674,14 +690,14 @@ public class ItemManager { return new ConsumableItem { - Reference = CreateReference(itemId), + Reference = CreateReference(item), Quality = quality }; } return new CompoundCommodity { - Reference = CreateReference(itemId), + Reference = CreateReference(item), Quality = quality }; } @@ -701,7 +717,7 @@ public class ItemManager return new EquippableItem { - Reference = CreateReference(itemId), + Reference = CreateReference(item), Quality = quality, Durability = item.Durability > 0 ? (float)item.Durability : 1f }; diff --git a/Assets/Scripts/ServerShared/RuntimeItemDefinitionReference.cs b/Assets/Scripts/ServerShared/RuntimeItemDefinitionReference.cs deleted file mode 100644 index 5c09e10d8..000000000 --- a/Assets/Scripts/ServerShared/RuntimeItemDefinitionReference.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -using System; -using Unity.Mathematics; - -public interface INamedEntry -{ - string EntryName { get; set; } -} - -public class RuntimeItemDefinitionReference -{ - public Guid ItemId; - - public RuntimeItemDefinitionReference() - { - } - - public RuntimeItemDefinitionReference(Guid itemId) - { - ItemId = itemId; - } -} - -public interface ITintInspector -{ - float3 TintColor { get; } -} diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 2173bdb7a..7db5aea08 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -52,8 +52,8 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. the provider-owned Eve command bridge on startup and on a daemon polling loop while hosting the CultMesh state node. `Aetheria.State.ApplyPending` remains a bounded local operator applicator for both pending lanes. -- Shared item domain state is still partly built around `RuntimeItemDefinitionReference`, - `ItemData`, `BehaviorData`, GUID identity, and runtime catalog metadata. Dead +- Shared item domain state is still partly built around `AetheriaRuntimeItemReference`, + `ItemData`, `RuntimeBehaviorConfig`, derived GUID compatibility, and runtime catalog metadata. Dead user-record and galaxy-map-layer catalog roots have been deleted, and surviving runtime DTOs no longer carry legacy catalog group/table annotations. Newtonsoft, JsonKnownTypes, RethinkDB, LiteNetLib client transport, and the broken @@ -204,8 +204,8 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. - `ActionGameManager` opens `AetheriaRuntimeCatalogStore` over `aetheria-world.cc`, projects it through `AetheriaRuntimeItemCatalog`, and gives `ItemManager` explicit item lookup authority. Item instances carry - `RuntimeItemDefinitionReference`, an item-definition id, not a process-global catalog - resolver, hydrated projection cache, or durable item-data owner. The old + `AetheriaRuntimeItemReference`, a typed item key, not a process-global catalog + resolver, hydrated projection cache, bare GUID owner, or durable item-data owner. The old `LegacyItemCatalogBoundary`, `LegacyItemCatalogCache`, and runtime MessagePack deserializer path have been deleted. The old `DatabaseEntry`/`RuntimeCatalogEntry`/`RuntimeItemProjectionEntry` @@ -354,8 +354,8 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. `Faction` DTOs, including allegiance edges, for the existing simulation shape and resolves full name arrays from `aetheria.name_file.v2` records. The runtime no longer opens the old `GameData/NameFile/*.msgpack` directory. -- Item instances carry `RuntimeItemDefinitionReference`, a narrow item-definition id - resolved by `ItemManager` against the typed runtime item catalog projected +- Item instances carry `AetheriaRuntimeItemReference`, a typed item key resolved + by `ItemManager` against the typed runtime item catalog projected from `aetheria-world.cc`. Runtime item references no longer carry hydrated DTO projection caches or global link-resolution authority. MessagePack catalog construction no longer grabs global link-resolution authority, and the old generic `RuntimeCatalogLink` abstraction is gone. @@ -618,8 +618,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. config reads no longer escape `ItemManager`; gameplay stat modifiers target live behavior instances and package-owned behavior metadata instead of rebuilding config DTOs for lookup. - `ItemInstance.ItemId` is the runtime identity surface and - `ItemInstance.Reference` is the explicit item-reference API; + `ItemInstance.Reference` stores the typed item key, `ItemInstance.ItemKey` + is the runtime identity surface, and `ItemInstance.ItemId` is a derived + legacy-GUID compatibility projection; 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 @@ -1197,8 +1198,10 @@ First Aetheria surfaces to publish: - Done: remove the stale `MessagePack` assembly reference from `Aetheria.Shared.Unity`; the remaining MessagePack reference is contained in the typed state package's `.cc` reader. - - Convert domain references from GUID/base-class patterns to typed record - refs. + - In progress: convert domain references from GUID/base-class patterns to + typed record refs. Item instances now carry typed item keys; remaining + cargo/simulation dictionaries still derive legacy GUIDs until those + structures move to typed keys. - Remove runtime dependency on `ItemData` DTOs as item instance owners. 5. Mesh host @@ -1300,17 +1303,21 @@ 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: add `ItemInstance.ItemId` as an intermediate runtime identity + surface and move live runtime/UI/catalog lookup call sites off + `.Data.ItemId`. The old `Data` field became compatibility backing state + before it was deleted. - Done: add `ItemInstance.Reference` as the explicit item-reference API and move factories/cargo stacking off direct `.Data` comparisons and assignments. - Done: rename `RuntimeItemReference` to `RuntimeItemDefinitionReference` and delete the `ItemInstance.Data` - compatibility field; item instances now expose item identity through - `Reference` and `ItemId` only. + compatibility field; this was the intermediate reference shape before + typed item keys became the owner. + - Done: rename `RuntimeItemDefinitionReference` to + `AetheriaRuntimeItemReference` and make the reference typed-key-first. + `ItemInstance.ItemKey` is now the primary identity surface; `ItemId` is + derived legacy compatibility for unfinished cargo and simulation paths. - Done: delete the dead `ItemManager.GetRuntimeItemProjection` bridge after loadout generation stopped hydrating selected typed rows into `EquippableItemData` merely to instantiate equipment.