in src/managed/DiffGen/DiffGeneration/Diff.cs [126:254]
public void SelectRecipes()
{
HashSet<ItemDefinition> coveredItems = [_sourceTokens.ArchiveItem];
var allRecipesSorted = _sourceTokens.GetAllRecipes().OrderBy(r => r.ItemIngredients.Count).ToList();
bool changed;
do
{
changed = false;
foreach (var recipe in allRecipesSorted)
{
var result = recipe.Result;
if (coveredItems.Contains(result))
{
continue;
}
bool isValid = recipe.ItemIngredients.All(ingredient => coveredItems.Contains(ingredient));
if (isValid)
{
coveredItems.Add(result);
changed = true;
}
}
}
while (changed);
foreach (var entry in _sourceTokens.ReverseRecipes)
{
var result = entry.Key;
if (HasAnyRecipes(result))
{
continue;
}
var recipe = entry.Value;
AddRecipe(recipe);
}
foreach (var entry in _targetTokens.ForwardRecipes)
{
var result = entry.Key;
if (HasAnyRecipes(result))
{
continue;
}
var recipe = entry.Value;
AddRecipe(recipe);
}
Queue<ItemDefinition> itemQueue = new();
itemQueue.Enqueue(_targetTokens.ArchiveItem);
HashSet<ItemDefinition> needed = new();
HashSet<ItemDefinition> covered = new();
_neededItems.Clear();
while (itemQueue.Any())
{
var item = itemQueue.Dequeue();
if (covered.Contains(item))
{
continue;
}
if (HasAnyRecipes(item))
{
var recipes = GetRecipes(item);
if (recipes.Count != 1)
{
throw new Exception($"Expected just one recipe for item: {item}");
}
var recipe = recipes.First();
if (recipe.IsDeltaRecipe())
{
itemQueue.Enqueue(recipe.GetDeltaBasis());
}
else
{
foreach (var ingredient in recipes.First().ItemIngredients)
{
itemQueue.Enqueue(ingredient);
}
}
covered.Add(item);
continue;
}
if (_sourceTokens.ForwardRecipes.TryGetValue(item, out var sourceRecipe))
{
AddRecipe(sourceRecipe);
// This should be already satisfied
if (sourceRecipe.ItemIngredients.Any(i => !HasAnyRecipes(i)))
{
throw new Exception($"Found a recipe in source item, but the ingredients are not available already: {item}");
}
covered.Add(item);
continue;
}
if (_targetTokens.ForwardRecipes.TryGetValue(item, out var targetRecipe))
{
AddRecipe(targetRecipe);
foreach (var ingredient in targetRecipe.ItemIngredients)
{
itemQueue.Enqueue(ingredient);
}
covered.Add(item);
continue;
}
_neededItems.Add(item);
covered.Add(item);
}
}