Move catalog enum parsing onto typed items

This commit is contained in:
Meta Vens 2026-06-28 12:16:19 +01:00
commit b32a412df2
5 changed files with 136 additions and 43 deletions

View file

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

View file

@ -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<AetheriaVerifyHardpointType>(out _))
?? throw new InvalidOperationException("Typed catalog item hardpoint enum accessor failed.");
var typedSimpleCommodityItem = catalog.Items.FirstOrDefault(item => item.TryGetSimpleCommodityCategory<AetheriaVerifySimpleCommodityCategory>(out _))
?? throw new InvalidOperationException("Typed catalog item simple commodity enum accessor failed.");
var typedCompoundCommodityItem = catalog.Items.FirstOrDefault(item => item.TryGetCompoundCommodityCategory<AetheriaVerifyCompoundCommodityCategory>(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<TEnum>(out TEnum hardpointType) where TEnum : struct",
"public bool TryGetSimpleCommodityCategory<TEnum>(out TEnum category) where TEnum : struct",
"public bool TryGetCompoundCommodityCategory<TEnum>(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",

View file

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

View file

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

View file

@ -261,6 +261,27 @@ namespace GameCult.Aetheria.State.Verse
public IReadOnlyList<AetheriaRuntimeCurveKey> EffectivenessCurveKeys { get; }
public string SimpleCommodityCategory { get; }
public string CompoundCommodityCategory { get; }
public bool TryGetHardpointType<TEnum>(out TEnum hardpointType) where TEnum : struct
{
hardpointType = default;
return !string.IsNullOrWhiteSpace(HardpointType) &&
Enum.TryParse(HardpointType, true, out hardpointType);
}
public bool TryGetSimpleCommodityCategory<TEnum>(out TEnum category) where TEnum : struct
{
category = default;
return !string.IsNullOrWhiteSpace(SimpleCommodityCategory) &&
Enum.TryParse(SimpleCommodityCategory, true, out category);
}
public bool TryGetCompoundCommodityCategory<TEnum>(out TEnum category) where TEnum : struct
{
category = default;
return !string.IsNullOrWhiteSpace(CompoundCommodityCategory) &&
Enum.TryParse(CompoundCommodityCategory, true, out category);
}
}
public sealed class AetheriaRuntimeAudioStat