diff --git a/Assets/Scripts/ServerShared/LoadoutGenerator.cs b/Assets/Scripts/ServerShared/LoadoutGenerator.cs index ce8569965..9f4829eee 100644 --- a/Assets/Scripts/ServerShared/LoadoutGenerator.cs +++ b/Assets/Scripts/ServerShared/LoadoutGenerator.cs @@ -200,11 +200,8 @@ public class LoadoutGenerator var candidates = ItemManager.ItemData.GetAll() .Select(product => (product, design: ItemManager.ItemData.Get(product.Design) as T)) .Where(entry => - entry.design != null && - entry.design.Price > 0 && - entry.product.Manufacturer.IsSet() && // A not-offered product is never a candidate, so the any-manufacturer fallback below cannot reach it either. - IsOffered(ItemManager.ItemData, entry.product) && + IsDrawable(ItemManager.ItemData, entry.product, entry.design) && (!(entry.design is EquippableItemData equippable) || HasHome(equippable, hulls)) && (filter?.Invoke(entry.design) ?? true)) .ToArray(); @@ -246,6 +243,12 @@ public class LoadoutGenerator Galaxy == null || Faction == null || ItemManager.ItemData.Get(product.Manufacturer) == Faction || Faction.Allegiance.ContainsKey(product.Manufacturer)); + // Whether a product can be drawn for its design at all: the design resolves, has a price, the product names a maker and is + // offered. The one definition of 'a maker offers this design'; AvailableProducts selects by it and StationKinds decides which + // station kinds a hull can be drawn for by it, so a kind is kept exactly when a hull of it can be drawn. + public static bool IsDrawable(CultCache items, FactionProductData product, CraftedItemData design) => + design != null && design.Price > 0 && product.Manufacturer.IsSet() && IsOffered(items, product); + // Whether a product is on the market at all (ruling off-market-is-unoffered-product). The one reader of NotOffered. A bin is // offered only if both it and its line are (ruling bin-inherits-line-offered); the catalog read guarantees a bin's line exists. public static bool IsOffered(CultCache items, FactionProductData product) => diff --git a/Assets/Scripts/ServerShared/StationKinds.cs b/Assets/Scripts/ServerShared/StationKinds.cs index 6b1d617a6..d40beeb56 100644 --- a/Assets/Scripts/ServerShared/StationKinds.cs +++ b/Assets/Scripts/ServerShared/StationKinds.cs @@ -138,17 +138,17 @@ public static class StationKinds // The hull kinds some maker offers: the pool a station can always be drawn from. private static HashSet OfferedKinds(CultCache catalog) => - new HashSet( - catalog.GetAll().Where(product => LoadoutGenerator.IsOffered(catalog, product)) - .Select(product => catalog.Get(product.Design) as HullData) - .Where(hull => hull != null && hull.HullType == HullType.Station && hull.Kind.IsSet()) - .Select(hull => hull.Kind.Key.Value), StringComparer.Ordinal); + new HashSet(DrawableStationProducts(catalog).Select(entry => entry.hull.Kind.Key.Value), StringComparer.Ordinal); private static IEnumerable OfferedStationHulls(CultCache catalog, Faction faction) => + DrawableStationProducts(catalog).Where(entry => catalog.Get(entry.product.Manufacturer) == faction).Select(entry => entry.hull); + + // The station hulls a hull draw can reach (LoadoutGenerator.IsDrawable, the one definition), with the product that sells each. + private static IEnumerable<(FactionProductData product, HullData hull)> DrawableStationProducts(CultCache catalog) => catalog.GetAll() - .Where(product => LoadoutGenerator.IsOffered(catalog, product) && catalog.Get(product.Manufacturer) == faction) - .Select(product => catalog.Get(product.Design) as HullData) - .Where(hull => hull != null && hull.HullType == HullType.Station && hull.Kind.IsSet()); + .Select(product => (product, hull: catalog.Get(product.Design) as HullData)) + .Where(entry => entry.hull != null && entry.hull.HullType == HullType.Station && entry.hull.Kind.IsSet() && + LoadoutGenerator.IsDrawable(catalog, entry.product, entry.hull)); private static CultRecordRef[] Ordered(IEnumerable keys) => keys.OrderBy(key => key, StringComparer.Ordinal).Select(key => new CultRecordRef(new CultRecordKey(key))).ToArray();