From d3cd7813d7458a4825a44a093248db2e015d46db Mon Sep 17 00:00:00 2001 From: soul Date: Thu, 22 Oct 2026 17:31:08 +0200 Subject: [PATCH] Catalog subtraction: commodity records lose DemandProfile and both stored categories; the trade menu stops filtering by them Co-Authored-By: Claude Sonnet 5.5 --- Assets/Scripts/ServerShared/Enums.cs | 21 ----- Assets/Scripts/ServerShared/ItemData.cs | 10 +- Assets/Scripts/UI/Menu/TradeMenu.cs | 91 +------------------ .../CommodityRecordsTests.cs | 34 +++++++ 4 files changed, 39 insertions(+), 117 deletions(-) create mode 100644 tests/Aetheria.Shared.Tests/CommodityRecordsTests.cs diff --git a/Assets/Scripts/ServerShared/Enums.cs b/Assets/Scripts/ServerShared/Enums.cs index 63d2674db..0a6449dc1 100644 --- a/Assets/Scripts/ServerShared/Enums.cs +++ b/Assets/Scripts/ServerShared/Enums.cs @@ -152,27 +152,6 @@ public enum MegaPlacementType Isolated = 4 } -public enum SimpleCommodityCategory -{ - Minerals = 0, - Metals = 1, - Alloys = 2, - Compounds = 3, - Organics = 4, - Ammo = 5, - Consumer = 6 -} - -public enum CompoundCommodityCategory -{ - Wearables = 0, - Consumables = 1, - Luxuries = 2, - Tools = 3, - Manufacturing = 4, - Assemblies = 5 -} - public enum LocationType { Station, diff --git a/Assets/Scripts/ServerShared/ItemData.cs b/Assets/Scripts/ServerShared/ItemData.cs index ca1484e36..dcb38456a 100644 --- a/Assets/Scripts/ServerShared/ItemData.cs +++ b/Assets/Scripts/ServerShared/ItemData.cs @@ -322,13 +322,11 @@ public abstract class ItemData [CultDocument("aetheria.simplecommoditydata", "1"), Inspectable, MessagePackObject] public class SimpleCommodityData : ItemData { - // MessagePack keys 6, 7, 8 and 11 belonged to removed resource-distribution fields; do not reuse them. + // MessagePack keys 6, 7, 8, 10 and 11 belonged to removed resource-distribution fields; do not reuse them. [Inspectable, JsonProperty("maxStackSize"), Key(9)] public int MaxStack = 10; - [Inspectable, JsonProperty("category"), Key(10)] - public SimpleCommodityCategory Category; } [JsonObject(MemberSerialization.OptIn)] @@ -352,11 +350,7 @@ public class ItemRole [CultDocument("aetheria.compoundcommoditydata", "1"), Inspectable, MessagePackObject] public class CompoundCommodityData : CraftedItemData { - [Inspectable, CultReference(typeof(PersonalityAttribute), many: true), JsonProperty("demandProfile"), Key(10)] - public Dictionary, float> DemandProfile = new Dictionary, float>(); - - [Inspectable, JsonProperty("category"), Key(11)] - public CompoundCommodityCategory Category; + // MessagePack keys 10 and 11 belonged to the removed demand weights and classification; do not reuse them. } [CultDocument("aetheria.consumableitemdata", "1"), Inspectable, MessagePackObject] diff --git a/Assets/Scripts/UI/Menu/TradeMenu.cs b/Assets/Scripts/UI/Menu/TradeMenu.cs index 1adadcf15..3d448f64d 100644 --- a/Assets/Scripts/UI/Menu/TradeMenu.cs +++ b/Assets/Scripts/UI/Menu/TradeMenu.cs @@ -28,8 +28,6 @@ public class TradeMenu : MonoBehaviour // False lists the station's wares to buy; true lists the selected bay's goods to sell. private bool _selling; private (ItemFilter filter, HardpointType type) _hardpointFilter; - private (ItemFilter filter, SimpleCommodityCategory type) _commodityFilter; - private (ItemFilter filter, CompoundCommodityCategory type) _compoundCommodityFilter; private List<(ItemFilter filter, Type type)> _behaviorFilters = new List<(ItemFilter filter, Type type)>(); public EquippedCargoBay Inventory { get; set; } @@ -62,14 +60,6 @@ public class TradeMenu : MonoBehaviour if (_hardpointFilter.filter != null) hardpointTypes = hardpointTypes.Where(x => x != _hardpointFilter.type); - IEnumerable commodityTypes = (SimpleCommodityCategory[]) Enum.GetValues(typeof(SimpleCommodityCategory)); - if (_commodityFilter.filter != null) - commodityTypes = commodityTypes.Where(x => x != _commodityFilter.type); - - IEnumerable compoundCommodityTypes = (CompoundCommodityCategory[]) Enum.GetValues(typeof(CompoundCommodityCategory)); - if (_compoundCommodityFilter.filter != null) - compoundCommodityTypes = compoundCommodityTypes.Where(x => x != _compoundCommodityFilter.type); - ContextMenu.AddDropdown("Gear Type", hardpointTypes .Select(x => (Enum.GetName(typeof(HardpointType), x), () => { @@ -82,75 +72,10 @@ public class TradeMenu : MonoBehaviour Populate(); }; } - if(_commodityFilter.filter) - { - _commodityFilter.filter.GetComponent().ReturnToPool(); - _commodityFilter.filter = null; - } - if(_compoundCommodityFilter.filter) - { - _compoundCommodityFilter.filter.GetComponent().ReturnToPool(); - _compoundCommodityFilter.filter = null; - } - _hardpointFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(HardpointType), x)}"; _hardpointFilter.type = x; Populate(); }, true))); - ContextMenu.AddDropdown("Simple Commodity", commodityTypes - .Select(x => (Enum.GetName(typeof(SimpleCommodityCategory), x), () => - { - if (!_commodityFilter.filter) - { - _commodityFilter.filter = FilterPrototype.Instantiate(); - _commodityFilter.filter.OnDisable += () => - { - _commodityFilter.filter = null; - Populate(); - }; - } - if(_hardpointFilter.filter) - { - _hardpointFilter.filter.GetComponent().ReturnToPool(); - _hardpointFilter.filter = null; - } - if(_compoundCommodityFilter.filter) - { - _compoundCommodityFilter.filter.GetComponent().ReturnToPool(); - _compoundCommodityFilter.filter = null; - } - - _commodityFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(SimpleCommodityCategory), x)}"; - _commodityFilter.type = x; - Populate(); - }, true))); - ContextMenu.AddDropdown("Compound Commodity", compoundCommodityTypes - .Select(x => (Enum.GetName(typeof(CompoundCommodityCategory), x), () => - { - if (!_compoundCommodityFilter.filter) - { - _compoundCommodityFilter.filter = FilterPrototype.Instantiate(); - _compoundCommodityFilter.filter.OnDisable += () => - { - _compoundCommodityFilter.filter = null; - Populate(); - }; - } - if(_hardpointFilter.filter) - { - _hardpointFilter.filter.GetComponent().ReturnToPool(); - _hardpointFilter.filter = null; - } - if(_commodityFilter.filter) - { - _commodityFilter.filter.GetComponent().ReturnToPool(); - _commodityFilter.filter = null; - } - - _compoundCommodityFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(CompoundCommodityCategory), x)}"; - _compoundCommodityFilter.type = x; - Populate(); - }, true))); ContextMenu.AddDropdown("Item Behavior", typeof(BehaviorData).GetAllChildClasses() .Where(x=> x.GetCustomAttribute() != null && _behaviorFilters.All(f => f.type != x)) .Select(x=> (x.Name.FormatTypeName(), () => @@ -199,19 +124,15 @@ public class TradeMenu : MonoBehaviour columns.Add(("Type", 2, x => () => { - if (x.data is SimpleCommodityData s) return Enum.GetName(typeof(SimpleCommodityCategory), s.Category); - if(x.data is CompoundCommodityData c) return Enum.GetName(typeof(CompoundCommodityCategory), c.Category); + if (x.data is SimpleCommodityData || x.data is CompoundCommodityData) return "Commodity"; if(x.data is EquippableItemData e) return Enum.GetName(typeof(HardpointType), e.HardpointType); return "None"; }, x => { var data = x.data; - if (data is SimpleCommodityData s) return (int) s.Category; - var offset = Enum.GetValues(typeof(SimpleCommodityCategory)).Length; - if(data is CompoundCommodityData c) return (int) c.Category + offset; - offset += Enum.GetValues(typeof(CompoundCommodityCategory)).Length; - if(data is EquippableItemData e) return (int) e.HardpointType + offset; + if (data is SimpleCommodityData || data is CompoundCommodityData) return 0; + if (data is EquippableItemData e) return 1 + (int) e.HardpointType; return 0; })); columns.Add(("Mass", 1, @@ -237,12 +158,6 @@ public class TradeMenu : MonoBehaviour !(MaximumSizeFilter.Width.text.Length > 0 && i.data.Shape.Width > int.Parse(MaximumSizeFilter.Width.text) || MaximumSizeFilter.Height.text.Length > 0 && i.data.Shape.Height > int.Parse(MaximumSizeFilter.Height.text))); - if(_commodityFilter.filter != null) - items = items.Where(i => i.data is SimpleCommodityData s && s.Category == _commodityFilter.type); - - if(_compoundCommodityFilter.filter != null) - items = items.Where(i => i.data is CompoundCommodityData c && c.Category == _compoundCommodityFilter.type); - if (_hardpointFilter.filter != null) items = items.Where(i => i.data is EquippableItemData e && e.HardpointType == _hardpointFilter.type); diff --git a/tests/Aetheria.Shared.Tests/CommodityRecordsTests.cs b/tests/Aetheria.Shared.Tests/CommodityRecordsTests.cs new file mode 100644 index 000000000..7f1c376c3 --- /dev/null +++ b/tests/Aetheria.Shared.Tests/CommodityRecordsTests.cs @@ -0,0 +1,34 @@ +using System; +using System.Linq; +using System.Reflection; +using MessagePack; +using Xunit; + +// Commodity records carry no stored classification and no demand weights (aetheria-living-world, cut +// catalog-subtraction): stage, component-ness and consumer-ness are derived later from recipes, roles and needs. +public sealed class CommodityRecordsTests +{ + // The shipped bytes still hold values at the retired keys; MessagePack skips them and every record loads by name. + [Fact] + public void ShippedCatalogOpensWithTheRetiredKeysGone() + { + using var cache = RestoredHullsTests.OpenCatalog(); + Assert.Equal(13, cache.GetAll().Count()); + Assert.Equal(51, cache.GetAll().Count()); + Assert.Contains(cache.GetAll(), c => c.Name == "Ammo"); + Assert.All(cache.GetAll(), c => Assert.False(string.IsNullOrEmpty(c.Name))); + } + + // Keys 10 and 11 are retired: no commodity member may reuse them for a different meaning. + [Fact] + public void RetiredKeysStayRetired() + { + int[] KeysOf(Type type) => type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Select(f => f.GetCustomAttribute()?.IntKey).Where(k => k.HasValue).Select(k => k.Value).ToArray(); + Assert.Equal(new[] { 9 }, KeysOf(typeof(SimpleCommodityData))); + Assert.Empty(KeysOf(typeof(CompoundCommodityData))); + Assert.Null(typeof(SimpleCommodityData).GetField("Category")); + Assert.Null(typeof(CompoundCommodityData).GetField("Category")); + Assert.Null(typeof(CompoundCommodityData).GetField("DemandProfile")); + } +}