Catalog subtraction: commodity records lose DemandProfile and both stored categories; the trade menu stops filtering by them

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
soul 2026-10-22 17:31:08 +02:00
commit d3cd7813d7
4 changed files with 39 additions and 117 deletions

View file

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

View file

@ -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<CultRecordRef<PersonalityAttribute>, float> DemandProfile = new Dictionary<CultRecordRef<PersonalityAttribute>, 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]

View file

@ -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<SimpleCommodityCategory> commodityTypes = (SimpleCommodityCategory[]) Enum.GetValues(typeof(SimpleCommodityCategory));
if (_commodityFilter.filter != null)
commodityTypes = commodityTypes.Where(x => x != _commodityFilter.type);
IEnumerable<CompoundCommodityCategory> compoundCommodityTypes = (CompoundCommodityCategory[]) Enum.GetValues(typeof(CompoundCommodityCategory));
if (_compoundCommodityFilter.filter != null)
compoundCommodityTypes = compoundCommodityTypes.Where(x => x != _compoundCommodityFilter.type);
ContextMenu.AddDropdown("Gear Type", hardpointTypes
.Select<HardpointType, (string, Action, bool)>(x => (Enum.GetName(typeof(HardpointType), x), () =>
{
@ -82,75 +72,10 @@ public class TradeMenu : MonoBehaviour
Populate();
};
}
if(_commodityFilter.filter)
{
_commodityFilter.filter.GetComponent<Prototype>().ReturnToPool();
_commodityFilter.filter = null;
}
if(_compoundCommodityFilter.filter)
{
_compoundCommodityFilter.filter.GetComponent<Prototype>().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<SimpleCommodityCategory, (string, Action, bool)>(x => (Enum.GetName(typeof(SimpleCommodityCategory), x), () =>
{
if (!_commodityFilter.filter)
{
_commodityFilter.filter = FilterPrototype.Instantiate<ItemFilter>();
_commodityFilter.filter.OnDisable += () =>
{
_commodityFilter.filter = null;
Populate();
};
}
if(_hardpointFilter.filter)
{
_hardpointFilter.filter.GetComponent<Prototype>().ReturnToPool();
_hardpointFilter.filter = null;
}
if(_compoundCommodityFilter.filter)
{
_compoundCommodityFilter.filter.GetComponent<Prototype>().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<CompoundCommodityCategory, (string, Action, bool)>(x => (Enum.GetName(typeof(CompoundCommodityCategory), x), () =>
{
if (!_compoundCommodityFilter.filter)
{
_compoundCommodityFilter.filter = FilterPrototype.Instantiate<ItemFilter>();
_compoundCommodityFilter.filter.OnDisable += () =>
{
_compoundCommodityFilter.filter = null;
Populate();
};
}
if(_hardpointFilter.filter)
{
_hardpointFilter.filter.GetComponent<Prototype>().ReturnToPool();
_hardpointFilter.filter = null;
}
if(_commodityFilter.filter)
{
_commodityFilter.filter.GetComponent<Prototype>().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<RuntimeInspectable>() != null && _behaviorFilters.All(f => f.type != x))
.Select<Type, (string, Action, bool)>(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);

View file

@ -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<SimpleCommodityData>().Count());
Assert.Equal(51, cache.GetAll<CompoundCommodityData>().Count());
Assert.Contains(cache.GetAll<SimpleCommodityData>(), c => c.Name == "Ammo");
Assert.All(cache.GetAll<CompoundCommodityData>(), 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<KeyAttribute>()?.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"));
}
}