From 3cc57960fa6845b7f3858fc08cd145499af7e2e1 Mon Sep 17 00:00:00 2001 From: Dale McCoy <21223975+DaleStan@users.noreply.github.com> Date: Mon, 9 Sep 2024 01:20:53 -0400 Subject: [PATCH] fix(#276): Unlock fixed recipes with their crafters. This needs to be done recursively, in case a fixed recipe creates a crafter with another fixed recipe. --- .../Data/FactorioDataDeserializer_Context.cs | 39 +++++++++++++++++++ changelog.txt | 5 +++ 2 files changed, 44 insertions(+) diff --git a/Yafc.Parser/Data/FactorioDataDeserializer_Context.cs b/Yafc.Parser/Data/FactorioDataDeserializer_Context.cs index f5f85493..5b1f7e98 100644 --- a/Yafc.Parser/Data/FactorioDataDeserializer_Context.cs +++ b/Yafc.Parser/Data/FactorioDataDeserializer_Context.cs @@ -391,6 +391,45 @@ private void CalculateMaps(bool netProduction) { } } + Queue crafters = new(allObjects.OfType()); + + while (crafters.TryDequeue(out EntityCrafter? crafter)) { + // If this is a crafter with a fixed recipe with data.raw.recipe["fixed-recipe-name"].enabled = false + // (Exclude Mechanics; they aren't recipes in Factorio's fixed_recipe sense.) + if (recipeCrafters.GetRaw(crafter).SingleOrDefault(s => s.StartsWith(SpecialNames.FixedRecipe), false) != null + && crafter.recipes.SingleOrDefault(r => r.GetType() == typeof(Recipe), false) is Recipe { enabled: false } fixedRecipe) { + + bool addedUnlocks = false; + foreach (Recipe itemRecipe in crafter.itemsToPlace.SelectMany(i => i.production)) { + // and (a recipe that creates an item that places) the crafter is accessible + // from the beginning of the game, the fixed recipe is also accessible. + if (itemRecipe.enabled) { + fixedRecipe.enabled = true; + addedUnlocks = true; + break; + } + // otherwise, the recipe is also unlocked by all technologies that + // unlock (a recipe that creates an item that places) the crafter. + else if (itemRecipe.technologyUnlock.Except(fixedRecipe.technologyUnlock).Any()) { + // Add the missing technology/ies + fixedRecipe.technologyUnlock = [.. fixedRecipe.technologyUnlock.Union(itemRecipe.technologyUnlock)]; + addedUnlocks = true; + } + } + + if (addedUnlocks) { + // If we added unlocks, and the fixed recipe creates (items that place) crafters, + // queue those crafters for a second check, in case they also have fixed recipes. + Item[] products = [.. fixedRecipe.products.Select(p => p.goods).OfType()]; + foreach (EntityCrafter newCrafter in allObjects.OfType()) { + if (newCrafter.itemsToPlace.Intersect(products).Any()) { + crafters.Enqueue(newCrafter); + } + } + } + } + } + foreach (var mechanic in allMechanics) { mechanic.locName = mechanic.source.locName + " " + mechanic.locName; mechanic.locDescr = mechanic.source.locDescr; diff --git a/changelog.txt b/changelog.txt index b9e1a1d4..6773d5ae 100644 --- a/changelog.txt +++ b/changelog.txt @@ -15,6 +15,11 @@ // Internal changes: // Changes to the code that do not affect the behavior of the program. ---------------------------------------------------------------------------------------------------------------------- +Version: 0.10.1 +Date: + Bugfixes: + - Fixed recipes now become accessible when their crafter does. +---------------------------------------------------------------------------------------------------------------------- Version: 0.10.0 Date: Feature: