From b32a412df20afc00b07cac3fc73f19e418682e85 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 28 Jun 2026 12:16:19 +0100 Subject: [PATCH] Move catalog enum parsing onto typed items --- .../AetheriaCatalogEnumProbeTypes.cs | 38 +++++++++++ Aetheria.State.Verify/Program.cs | 67 ++++++++++++++++++- Assets/Scripts/UI/Menu/InventoryPanel.cs | 11 +-- Assets/Scripts/UI/Menu/TradeMenu.cs | 42 +++--------- .../Runtime/AetheriaRuntimeCatalogSnapshot.cs | 21 ++++++ 5 files changed, 136 insertions(+), 43 deletions(-) create mode 100644 Aetheria.State.Verify/AetheriaCatalogEnumProbeTypes.cs diff --git a/Aetheria.State.Verify/AetheriaCatalogEnumProbeTypes.cs b/Aetheria.State.Verify/AetheriaCatalogEnumProbeTypes.cs new file mode 100644 index 000000000..24334c355 --- /dev/null +++ b/Aetheria.State.Verify/AetheriaCatalogEnumProbeTypes.cs @@ -0,0 +1,38 @@ +internal enum AetheriaVerifyHardpointType +{ + Hull, + Tool, + Thermal, + Thruster, + WarpDrive, + Reactor, + Radiator, + Shield, + Sensors, + Energy, + Ballistic, + Launcher, + ControlModule, + AetherDrive +} + +internal enum AetheriaVerifySimpleCommodityCategory +{ + Minerals, + Metals, + Alloys, + Compounds, + Organics, + Ammo, + Consumer +} + +internal enum AetheriaVerifyCompoundCommodityCategory +{ + Wearables, + Consumables, + Luxuries, + Tools, + Manufacturing, + Assemblies +} diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 5a0e94c03..2a005109b 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -480,6 +480,19 @@ if (!catalog.FindItemsByHardpoint(hardpointType).Any()) throw new InvalidOperationException($"Typed catalog hardpoint query failed for {hardpointType}."); } +var typedHardpointItem = catalog.Items.FirstOrDefault(item => item.TryGetHardpointType(out _)) + ?? throw new InvalidOperationException("Typed catalog item hardpoint enum accessor failed."); +var typedSimpleCommodityItem = catalog.Items.FirstOrDefault(item => item.TryGetSimpleCommodityCategory(out _)) + ?? throw new InvalidOperationException("Typed catalog item simple commodity enum accessor failed."); +var typedCompoundCommodityItem = catalog.Items.FirstOrDefault(item => item.TryGetCompoundCommodityCategory(out _)) + ?? throw new InvalidOperationException("Typed catalog item compound commodity enum accessor failed."); +if (string.IsNullOrWhiteSpace(typedHardpointItem.HardpointType) || + string.IsNullOrWhiteSpace(typedSimpleCommodityItem.SimpleCommodityCategory) || + string.IsNullOrWhiteSpace(typedCompoundCommodityItem.CompoundCommodityCategory)) +{ + throw new InvalidOperationException("Typed catalog item enum accessors returned an item without its source field."); +} + var manufacturedItem = catalog.Items.FirstOrDefault(item => !string.IsNullOrWhiteSpace(item.ManufacturerKey)) ?? throw new InvalidOperationException("Cannot verify typed catalog manufacturer lookup: no manufactured item."); if (string.IsNullOrWhiteSpace(manufacturedItem.ManufacturerKey) || @@ -6011,6 +6024,13 @@ static void RequireTradeItemDetailsUseEveSurface(string root) static void RequireTradeItemValuesUseRuntimeQueries(string root) { var tradeMenuPath = Path.Combine(root, "Assets", "Scripts", "UI", "Menu", "TradeMenu.cs"); + var inventoryPanelPath = Path.Combine(root, "Assets", "Scripts", "UI", "Menu", "InventoryPanel.cs"); + var catalogSnapshotPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.state", + "Runtime", + "AetheriaRuntimeCatalogSnapshot.cs"); var tradeQueriesPath = Path.Combine( root, "Packages", @@ -6021,12 +6041,22 @@ static void RequireTradeItemValuesUseRuntimeQueries(string root) { throw new InvalidOperationException("Cannot verify trade item value projection; TradeMenu.cs is missing."); } + if (!File.Exists(inventoryPanelPath)) + { + throw new InvalidOperationException("Cannot verify typed catalog item enum accessors; InventoryPanel.cs is missing."); + } + if (!File.Exists(catalogSnapshotPath)) + { + throw new InvalidOperationException("Cannot verify typed catalog item enum accessors; AetheriaRuntimeCatalogSnapshot.cs is missing."); + } if (!File.Exists(tradeQueriesPath)) { throw new InvalidOperationException("Cannot verify trade item value projection; shared runtime trade item queries are missing."); } var tradeMenu = File.ReadAllText(tradeMenuPath); + var inventoryPanel = File.ReadAllText(inventoryPanelPath); + var catalogSnapshot = File.ReadAllText(catalogSnapshotPath); var tradeQueries = File.ReadAllText(tradeQueriesPath); var requiredTradeMenuSymbols = new[] { @@ -6036,7 +6066,11 @@ static void RequireTradeItemValuesUseRuntimeQueries(string root) "AetheriaRuntimeDaemonTradeItemQueries.ProjectTradeItem(", "AetheriaRuntimeTradeItemProjection TradeProjection", "public int Price => TradeProjection.Price", - "public string TierColorHex => TradeProjection.TierColorHex" + "public string TierColorHex => TradeProjection.TierColorHex", + "x.TypedItem.TryGetSimpleCommodityCategory(", + "x.TypedItem.TryGetCompoundCommodityCategory(", + "x.TypedItem.TryGetHardpointType(", + "row.TypedItem.TryGetSimpleCommodityCategory(out SimpleCommodityCategory _)" }; var missingTradeMenuSymbols = requiredTradeMenuSymbols .Where(symbol => !tradeMenu.Contains(symbol, StringComparison.Ordinal)) @@ -6056,7 +6090,10 @@ static void RequireTradeItemValuesUseRuntimeQueries(string root) "GameManager.ObservedTradeValueSettings()", "AetheriaUnityProjectionSettings.TradeValueSettings", "private readonly ItemManager _itemManager", - "new TradeRow(item, FindTypedTradeItem(item), GameManager.ItemManager)" + "new TradeRow(item, FindTypedTradeItem(item), GameManager.ItemManager)", + "TryGetTypedSimpleCommodityCategory(", + "TryGetTypedCompoundCommodityCategory(", + "TryGetTypedHardpoint(" }; var tradeMenuHits = forbiddenTradeMenuSymbols .Where(symbol => tradeMenu.Contains(symbol, StringComparison.Ordinal)) @@ -6068,6 +6105,32 @@ static void RequireTradeItemValuesUseRuntimeQueries(string root) string.Join(", ", tradeMenuHits)); } + var requiredCatalogItemEnumSymbols = new[] + { + "public bool TryGetHardpointType(out TEnum hardpointType) where TEnum : struct", + "public bool TryGetSimpleCommodityCategory(out TEnum category) where TEnum : struct", + "public bool TryGetCompoundCommodityCategory(out TEnum category) where TEnum : struct", + "Enum.TryParse(HardpointType, true, out hardpointType)", + "Enum.TryParse(SimpleCommodityCategory, true, out category)", + "Enum.TryParse(CompoundCommodityCategory, true, out category)" + }; + var missingCatalogItemEnumSymbols = requiredCatalogItemEnumSymbols + .Where(symbol => !catalogSnapshot.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (missingCatalogItemEnumSymbols.Length > 0) + { + throw new InvalidOperationException( + "AetheriaRuntimeCatalogItem must own typed enum accessors for catalog category/hardpoint fields: " + + string.Join(", ", missingCatalogItemEnumSymbols)); + } + + if (!inventoryPanel.Contains("FindTypedInventoryItem(item)?.TryGetHardpointType(out HardpointType typedHardpoint) == true", StringComparison.Ordinal) || + inventoryPanel.Contains("TryGetTypedHardpointType(", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "InventoryPanel must ask AetheriaRuntimeCatalogItem for typed hardpoint classification instead of parsing catalog strings locally."); + } + var requiredQuerySymbols = new[] { "public static class AetheriaRuntimeDaemonTradeItemQueries", diff --git a/Assets/Scripts/UI/Menu/InventoryPanel.cs b/Assets/Scripts/UI/Menu/InventoryPanel.cs index d6b5c7e80..b67d39eab 100644 --- a/Assets/Scripts/UI/Menu/InventoryPanel.cs +++ b/Assets/Scripts/UI/Menu/InventoryPanel.cs @@ -967,7 +967,7 @@ private void Update() return Color.white * .25f; var c = float3(1); - if (TryGetTypedHardpointType(item, out var typedHardpoint)) + if (FindTypedInventoryItem(item)?.TryGetHardpointType(out HardpointType typedHardpoint) == true) c = HardpointData.GetColor(typedHardpoint).ToUnityFloat3(); if(!highlight) @@ -977,15 +977,6 @@ private void Update() } } - private bool TryGetTypedHardpointType(ItemInstance item, out HardpointType hardpointType) - { - hardpointType = HardpointType.Hull; - var typedItem = FindTypedInventoryItem(item); - return typedItem != null && - !string.IsNullOrWhiteSpace(typedItem.HardpointType) && - Enum.TryParse(typedItem.HardpointType, true, out hardpointType); - } - private float GetMaxDurability(ItemInstance item) { var typedItem = FindTypedInventoryItem(item); diff --git a/Assets/Scripts/UI/Menu/TradeMenu.cs b/Assets/Scripts/UI/Menu/TradeMenu.cs index 0f438d04b..7f7c0e293 100644 --- a/Assets/Scripts/UI/Menu/TradeMenu.cs +++ b/Assets/Scripts/UI/Menu/TradeMenu.cs @@ -106,22 +106,22 @@ public class TradeMenu : MonoBehaviour columns.Add(("Type", 2, x => () => { - if (x.TryGetTypedSimpleCommodityCategory(out _)) + if (x.TypedItem.TryGetSimpleCommodityCategory(out SimpleCommodityCategory _)) return x.TypedItem.SimpleCommodityCategory; - if (x.TryGetTypedCompoundCommodityCategory(out _)) + if (x.TypedItem.TryGetCompoundCommodityCategory(out CompoundCommodityCategory _)) return x.TypedItem.CompoundCommodityCategory; - if (x.TryGetTypedHardpoint(out var hardpointType)) return Enum.GetName(typeof(HardpointType), hardpointType); + if (x.TypedItem.TryGetHardpointType(out HardpointType hardpointType)) return Enum.GetName(typeof(HardpointType), hardpointType); return "None"; }, x => { - if (x.TryGetTypedSimpleCommodityCategory(out var simpleCategory)) + if (x.TypedItem.TryGetSimpleCommodityCategory(out SimpleCommodityCategory simpleCategory)) return (int)simpleCategory; var offset = Enum.GetValues(typeof(SimpleCommodityCategory)).Length; - if(x.TryGetTypedCompoundCommodityCategory(out var compoundCategory)) + if(x.TypedItem.TryGetCompoundCommodityCategory(out CompoundCommodityCategory compoundCategory)) return (int)compoundCategory + offset; offset += Enum.GetValues(typeof(CompoundCommodityCategory)).Length; - if (x.TryGetTypedHardpoint(out var hardpointType)) return (int) hardpointType + offset; + if (x.TypedItem.TryGetHardpointType(out HardpointType hardpointType)) return (int) hardpointType + offset; return 0; })); columns.Add(("Mass", 1, @@ -147,13 +147,13 @@ public class TradeMenu : MonoBehaviour MaximumSizeFilter.Height.text.Length > 0 && i.ShapeHeight > int.Parse(MaximumSizeFilter.Height.text))); if(_commodityFilter.filter != null) - items = items.Where(i => i.TryGetTypedSimpleCommodityCategory(out var category) && category == _commodityFilter.type); + items = items.Where(i => i.TypedItem.TryGetSimpleCommodityCategory(out SimpleCommodityCategory category) && category == _commodityFilter.type); if(_compoundCommodityFilter.filter != null) - items = items.Where(i => i.TryGetTypedCompoundCommodityCategory(out var category) && category == _compoundCommodityFilter.type); + items = items.Where(i => i.TypedItem.TryGetCompoundCommodityCategory(out CompoundCommodityCategory category) && category == _compoundCommodityFilter.type); if (_hardpointFilter.filter != null) - items = items.Where(i => i.TryGetTypedHardpoint(out var hardpointType) && hardpointType == _hardpointFilter.type); + items = items.Where(i => i.TypedItem.TryGetHardpointType(out HardpointType hardpointType) && hardpointType == _hardpointFilter.type); foreach (var behaviorFilter in _behaviorFilters) { @@ -224,7 +224,7 @@ public class TradeMenu : MonoBehaviour }, OnRightClick = () => { - if (i.TryGetTypedSimpleCommodityCategory(out _)) + if (i.TypedItem.TryGetSimpleCommodityCategory(out SimpleCommodityCategory _)) { RenderRowActionSurface( $"Buying {i.Name}", @@ -394,26 +394,6 @@ public class TradeMenu : MonoBehaviour public bool IsHull => !string.IsNullOrWhiteSpace(TypedItem?.HullType); - public bool TryGetTypedSimpleCommodityCategory(out SimpleCommodityCategory category) - { - category = SimpleCommodityCategory.Minerals; - return !string.IsNullOrWhiteSpace(TypedItem?.SimpleCommodityCategory) && - Enum.TryParse(TypedItem.SimpleCommodityCategory, true, out category); - } - - public bool TryGetTypedCompoundCommodityCategory(out CompoundCommodityCategory category) - { - category = CompoundCommodityCategory.Wearables; - return !string.IsNullOrWhiteSpace(TypedItem?.CompoundCommodityCategory) && - Enum.TryParse(TypedItem.CompoundCommodityCategory, true, out category); - } - - public bool TryGetTypedHardpoint(out HardpointType hardpointType) - { - hardpointType = HardpointType.Hull; - return !string.IsNullOrWhiteSpace(TypedItem?.HardpointType) && - Enum.TryParse(TypedItem.HardpointType, true, out hardpointType); - } } private void UpdateCreditsLabel() @@ -492,7 +472,7 @@ public class TradeMenu : MonoBehaviour var purchaseKind = createsDockedShip ? "docked_ship" - : row.TryGetTypedSimpleCommodityCategory(out _) + : row.TypedItem.TryGetSimpleCommodityCategory(out SimpleCommodityCategory _) ? "commodity" : "crafted"; diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs index 32711c9be..5f2ebe905 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCatalogSnapshot.cs @@ -261,6 +261,27 @@ namespace GameCult.Aetheria.State.Verse public IReadOnlyList EffectivenessCurveKeys { get; } public string SimpleCommodityCategory { get; } public string CompoundCommodityCategory { get; } + + public bool TryGetHardpointType(out TEnum hardpointType) where TEnum : struct + { + hardpointType = default; + return !string.IsNullOrWhiteSpace(HardpointType) && + Enum.TryParse(HardpointType, true, out hardpointType); + } + + public bool TryGetSimpleCommodityCategory(out TEnum category) where TEnum : struct + { + category = default; + return !string.IsNullOrWhiteSpace(SimpleCommodityCategory) && + Enum.TryParse(SimpleCommodityCategory, true, out category); + } + + public bool TryGetCompoundCommodityCategory(out TEnum category) where TEnum : struct + { + category = default; + return !string.IsNullOrWhiteSpace(CompoundCommodityCategory) && + Enum.TryParse(CompoundCommodityCategory, true, out category); + } } public sealed class AetheriaRuntimeAudioStat