diff --git a/Assets/Scripts/ServerShared/EconomyChecks.cs b/Assets/Scripts/ServerShared/EconomyChecks.cs index 274e9990b..20bfdefa4 100644 --- a/Assets/Scripts/ServerShared/EconomyChecks.cs +++ b/Assets/Scripts/ServerShared/EconomyChecks.cs @@ -417,20 +417,20 @@ public static class EconomyChecks { var recipes = AllRecipes(catalog).Where(p => catalog.Get(p.Recipe.Output) != null).ToDictionary(p => p.Recipe.Output.Key.Value, p => p.Recipe, StringComparer.Ordinal); var drawn = Drawn(catalog); - bool IsCommodityKey(string key) => recipes.TryGetValue(key, out var r) && Recipes.IsCommodity(catalog.Get(r.Output)); + bool IsCommodityRecipe(RecipeData r) => Recipes.IsCommodity(catalog.Get(r.Output)); var consumerRoles = new HashSet(recipes.Values.Where(r => Recipes.IsConsumerGood(catalog, r)) .SelectMany(r => Recipes.RolesOf(catalog.Get(r.Output))).Select(role => role.Name), StringComparer.Ordinal); var gearRoles = new HashSet(recipes.Values.Where(r => !Recipes.IsCommodity(catalog.Get(r.Output))) .SelectMany(r => Recipes.RolesOf(catalog.Get(r.Output))).Select(role => role.Name), StringComparer.Ordinal); var upkeep = new HashSet(recipes.Values.SelectMany(r => r.Upkeep).Select(c => c.Commodity.Key.Value), StringComparer.Ordinal); - var takenBy = recipes.Values.Where(r => IsCommodityKey(r.Output.Key.Value)) + var takenBy = recipes.Values.Where(IsCommodityRecipe) .SelectMany(r => r.Inputs.Select(input => (Input: input.Commodity.Key.Value, Output: r.Output.Key.Value))) .ToLookup(edge => edge.Input, edge => edge.Output, StringComparer.Ordinal); var faults = new List(); foreach (var key in recipes.Keys.OrderBy(k => k, StringComparer.Ordinal)) { var recipe = recipes[key]; - if (!IsCommodityKey(key) || Recipes.IsRaw(catalog, recipe) || Recipes.IsConsumerGood(catalog, recipe)) continue; + if (!IsCommodityRecipe(recipe) || Recipes.IsRaw(catalog, recipe) || Recipes.IsConsumerGood(catalog, recipe)) continue; var reached = new HashSet(StringComparer.Ordinal) { key }; var open = new Stack(reached); while (open.Count > 0) diff --git a/tests/Aetheria.Shared.Tests/EconomyChecksTests.cs b/tests/Aetheria.Shared.Tests/EconomyChecksTests.cs index d3bf3d591..a0ae40c86 100644 --- a/tests/Aetheria.Shared.Tests/EconomyChecksTests.cs +++ b/tests/Aetheria.Shared.Tests/EconomyChecksTests.cs @@ -377,14 +377,16 @@ public sealed class EconomyChecksTests using var f = new EconomyFixture(); f.Good("ore"); f.Good("coke", inputs: new[] { ("ore", 1) }); - f.Good("plate", inputs: new[] { ("ore", 1) }, fills: new[] { "Plate" }, upkeep: new[] { ("coke", 1) }); + f.Good("fuel", inputs: new[] { ("coke", 1) }); + f.Good("plate", inputs: new[] { ("ore", 1) }, fills: new[] { "Plate" }, upkeep: new[] { ("fuel", 1) }); f.Hull("tug", HullType.Ship, new[] { ("Plate", 1) }); - var fault = Assert.Single(EconomyChecks.ConsumerDemand(f.Cache)); - Assert.Equal("recipe:commodity:coke", fault.Record); - Assert.Contains("'coke' leads into upkeep but no use leads into a consumer good.", fault.Message); + // Fuel is upkeep itself; coke is shared because a good it leads into is. + var faults = EconomyChecks.ConsumerDemand(f.Cache); + Assert.Equal(new[] { "recipe:commodity:coke", "recipe:commodity:fuel" }, faults.Select(x => x.Record)); + Assert.Contains("'fuel' leads into upkeep but no use leads into a consumer good.", faults[1].Message); f.Good("pot", roles: new[] { ("Casing", 1) }); - f.EditRecipe("commodity:coke", r => r.Fills.Add("Casing")); + f.EditRecipe("commodity:fuel", r => r.Fills.Add("Casing")); Assert.Empty(EconomyChecks.ConsumerDemand(f.Cache)); }