Skip to content

Commit

Permalink
1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Ishigh1 committed May 20, 2021
1 parent 72bc4a1 commit 33f79fe
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 25 deletions.
42 changes: 36 additions & 6 deletions CompoundRecipe.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
using System.Collections.Generic;
using System.Linq;
using Terraria;
using Terraria.ModLoader;

namespace RecursiveCraft
{
public class CompoundRecipe
{
public Recipe CurrentRecipe;
public Dictionary<int, int> DropItems;
public RecipeInfo RecipeInfo;
public Recipe OverridenRecipe;
public int RecipeId;

public CompoundRecipe(int recipeId, Dictionary<int, int> dictionary)
public CompoundRecipe(int recipeId, RecipeInfo recipeInfo)
{
RecipeId = recipeId;
OverridenRecipe = Main.recipe[recipeId];

if (recipeInfo.UsedItems.Count > Recipe.maxRequirements)
Recipe.maxRequirements = recipeInfo.UsedItems.Count;//This may be a bit bigger than the needed value

CurrentRecipe = new Recipe
{
createItem = OverridenRecipe.createItem,
alchemy = OverridenRecipe.alchemy
createItem = OverridenRecipe.createItem
};
DropItems = new Dictionary<int, int>();

List<KeyValuePair<int, int>> keyValuePairs = dictionary.ToList();
keyValuePairs.Reverse();
RecipeInfo = recipeInfo;

List<KeyValuePair<int, int>> keyValuePairs = recipeInfo.UsedItems.ToList();
int i = 0;
foreach (KeyValuePair<int, int> keyValuePair in keyValuePairs.Where(keyValuePair => keyValuePair.Value > 0))
{
CurrentRecipe.requiredItem[i] = new Item();
CurrentRecipe.requiredItem[i].SetDefaults(keyValuePair.Key);
CurrentRecipe.requiredItem[i].stack = keyValuePair.Value;
++i;
}
}

public void BeforeCraft()
{
List<KeyValuePair<int, int>> keyValuePairs = RecipeInfo.TrueUsedItems.ToList();
int i = 0;
foreach (KeyValuePair<int, int> keyValuePair in keyValuePairs)
if (keyValuePair.Value < 0)
Expand All @@ -37,12 +55,24 @@ public CompoundRecipe(int recipeId, Dictionary<int, int> dictionary)
CurrentRecipe.requiredItem[i].stack = keyValuePair.Value;
++i;
}

for (; i < RecipeInfo.UsedItems.Count; i++)
{
CurrentRecipe.requiredItem[i].stack = 0;
}
}

public void OnCraft()
{
foreach (KeyValuePair<int, int> keyValuePair in DropItems)
Main.player[Main.myPlayer].QuickSpawnItem(keyValuePair.Key, keyValuePair.Value);

foreach (KeyValuePair<Recipe, int> keyValuePair in RecipeInfo.RecipeUsed)
for (int i = 0; i < keyValuePair.Value; i++)
{
RecipeHooks.OnCraft(Main.mouseItem, keyValuePair.Key);
ItemLoader.OnCraft(Main.mouseItem, keyValuePair.Key);
}
}
}
}
2 changes: 2 additions & 0 deletions CraftingSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public abstract class CraftingSource
public abstract bool AdjHoney{ get; }
public abstract bool AdjLava{ get; }
public abstract bool ZoneSnow{ get; }
public abstract bool AlchemyTable { get; }
}

public class PlayerAsCraftingSource : CraftingSource
Expand All @@ -18,5 +19,6 @@ public class PlayerAsCraftingSource : CraftingSource
public override bool AdjHoney => Main.LocalPlayer.adjHoney;
public override bool AdjLava => Main.LocalPlayer.adjLava;
public override bool ZoneSnow => Main.LocalPlayer.ZoneSnow;
public override bool AlchemyTable => Main.LocalPlayer.alchemyTable;
}
}
20 changes: 20 additions & 0 deletions RecipeInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using Terraria;

namespace RecursiveCraft
{
public class RecipeInfo
{
public Dictionary<int, int> UsedItems;
public readonly Dictionary<int, int> TrueUsedItems;
public Dictionary<Recipe, int> RecipeUsed;

public RecipeInfo(Dictionary<int, int> usedItems, Dictionary<int, int> trueUsedItems,
Dictionary<Recipe, int> recipeUsed)
{
UsedItems = usedItems;
TrueUsedItems = trueUsedItems;
RecipeUsed = recipeUsed;
}
}
}
92 changes: 74 additions & 18 deletions RecursiveCraft.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace RecursiveCraft
public class RecursiveCraft : Mod
{
public static Dictionary<int, List<Recipe>> RecipeByResult;
public static Dictionary<Recipe, Dictionary<int, int>> RecipeCache;
public static Dictionary<Recipe, RecipeInfo> RecipeCache;
public static CompoundRecipe CurrentCompound;

public static int DepthSearch;
Expand All @@ -30,7 +30,7 @@ public override void Load()
OnMain.Update += ApplyKey;
On.Terraria.Recipe.Create += CraftCompoundRecipe;
RecipeByResult = new Dictionary<int, List<Recipe>>();
RecipeCache = new Dictionary<Recipe, Dictionary<int, int>>();
RecipeCache = new Dictionary<Recipe, RecipeInfo>();

Hotkeys = new[]
{
Expand Down Expand Up @@ -73,12 +73,17 @@ public override void PostAddRecipes()

public static void CraftCompoundRecipe(On.Terraria.Recipe.orig_Create orig, Recipe self)
{
orig(self);
if (CurrentCompound != null && self == CurrentCompound.CurrentRecipe)
{
CurrentCompound.BeforeCraft();
orig(self);
CurrentCompound.OnCraft();
Recipe.FindRecipes();
}
else
{
orig(self);
}
}

public void ApplyKey(OnMain.orig_Update orig, Main self, GameTime gameTime)
Expand Down Expand Up @@ -129,9 +134,9 @@ public static void EditFocusRecipe(OnMain.orig_DrawInventory orig, Main self)
if (CurrentCompound != null) Main.recipe[CurrentCompound.RecipeId] = CurrentCompound.OverridenRecipe;
int i = Main.availableRecipe[Main.focusRecipe];
Recipe recipe = Main.recipe[i];
if (RecipeCache.TryGetValue(recipe, out Dictionary<int, int> dictionary))
if (RecipeCache.TryGetValue(recipe, out RecipeInfo recipeInfo))
{
CurrentCompound = new CompoundRecipe(i, dictionary);
CurrentCompound = new CompoundRecipe(i, recipeInfo);
Main.recipe[i] = CurrentCompound.CurrentRecipe;
}
else
Expand Down Expand Up @@ -175,24 +180,27 @@ public static void RecursiveSearch(Dictionary<int, int> inventory)
for (int n = 0; n < Recipe.maxRecipes && Main.recipe[n].createItem.type != ItemID.None; n++)
{
Recipe recipe = CurrentCompound?.RecipeId == n ? CurrentCompound.OverridenRecipe : Main.recipe[n];
Dictionary<int, int> usedItems = FindIngredientsForRecipe(inventory, craftingSource, recipe);
if (usedItems != null)
RecipeInfo recipeInfo = FindIngredientsForRecipe(inventory, craftingSource, recipe);
if (recipeInfo != null)
{
RecipeCache.Add(recipe, usedItems);
if (recipeInfo.RecipeUsed.Count > 1)
RecipeCache.Add(recipe, recipeInfo);
Main.availableRecipe[Main.numAvailableRecipes++] = n;
}
}
}

public static Dictionary<int, int> FindIngredientsForRecipe(Dictionary<int, int> dictionary,
public static RecipeInfo FindIngredientsForRecipe(Dictionary<int, int> dictionary,
CraftingSource craftingSource, Recipe recipe)
{
Dictionary<int, int> inventoryToUse = new Dictionary<int, int>(dictionary);
Dictionary<int, int> inventoryOnceUsed = inventoryToUse;
Dictionary<int, int> trueInventoryOnceUsed = inventoryToUse;
Dictionary<Recipe, int> recipeUsed = new Dictionary<Recipe, int>();
List<int> craftedItems = new List<int>();

if (AmountOfDoableRecipe(ref inventoryOnceUsed, craftingSource, recipe.createItem.stack, recipe,
craftedItems, 0) == 0) return null;
if (AmountOfDoableRecipe(ref inventoryOnceUsed, ref trueInventoryOnceUsed, ref recipeUsed, craftingSource,
recipe.createItem.stack, recipe.createItem.stack, recipe, craftedItems, 0) == 0) return null;

Dictionary<int, int> usedItems = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> keyValuePair in inventoryOnceUsed)
Expand All @@ -204,16 +212,33 @@ public static Dictionary<int, int> FindIngredientsForRecipe(Dictionary<int, int>
usedItems.Add(keyValuePair.Key, amount);
}

return usedItems;
Dictionary<int, int> trueUsedItems = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> keyValuePair in trueInventoryOnceUsed)
{
if (!inventoryToUse.TryGetValue(keyValuePair.Key, out int amount))
amount = 0;
amount -= keyValuePair.Value;
if (amount != 0)
trueUsedItems.Add(keyValuePair.Key, amount);
}

return new RecipeInfo(usedItems, trueUsedItems, recipeUsed);
}

public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse, CraftingSource craftingSource,
int amount, Recipe recipe, List<int> craftedItems, int depth)
//Every "true" variable is the same as the normal one except when alchemy table is used,
//saving ingredients while not showing it to the player.
public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse,
ref Dictionary<int, int> trueInventoryToUse, ref Dictionary<Recipe, int> recipeUsed,
CraftingSource craftingSource, int amount, int trueAmount, Recipe recipe, List<int> craftedItems, int depth)
{
if (!IsAvailable(recipe, craftingSource)) return 0;

Dictionary<int, int> inventoryOnceUsed =
inventoryToUse.ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value);
Dictionary<int, int> trueInventoryOnceUsed =
trueInventoryToUse.ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value);
Dictionary<Recipe, int> currentRecipeUsed =
recipeUsed.ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value);
List<int> craftedItemsOnceUsed = craftedItems.ToList();
if (!craftedItemsOnceUsed.Contains(recipe.createItem.type))
craftedItemsOnceUsed.Add(recipe.createItem.type);
Expand All @@ -223,12 +248,18 @@ public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse,
List<int> recipeAcceptedGroups = (List<int>) getAcceptedGroups.Invoke(null, new object[] {recipe});

int timeCraft = (amount + recipe.createItem.stack - 1) / recipe.createItem.stack;
int trueTimeCraft = (trueAmount + recipe.createItem.stack - 1) / recipe.createItem.stack;
for (int numIngredient = 0; numIngredient < Recipe.maxRequirements; numIngredient++)
{
Item ingredient = recipe.requiredItem[numIngredient];
if (ingredient.type == ItemID.None) break;

int ingredientsNeeded = timeCraft * ingredient.stack;
int trueIngredientsNeeded = trueTimeCraft * ingredient.stack;
if (recipe.alchemy && craftingSource.AlchemyTable)
for (int i = 0; i < trueTimeCraft; i++)
if(Main.rand.Next(3) == 0)
trueIngredientsNeeded -= ingredient.stack;

#region UseIngredients

Expand Down Expand Up @@ -257,6 +288,10 @@ public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse,
inventoryOnceUsed[validItem] -= usedAmount;
ingredientsNeeded -= usedAmount;

usedAmount = Math.Min(trueIngredientsNeeded, availableAmount);
trueInventoryOnceUsed[validItem] -= usedAmount;
trueIngredientsNeeded -= usedAmount;

if (ingredientsNeeded == 0)
break;
}
Expand All @@ -274,8 +309,10 @@ public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse,
RecipeByResult.TryGetValue(validItem, out List<Recipe> usableRecipes))
foreach (Recipe ingredientRecipe in usableRecipes)
{
ingredientsNeeded -= AmountOfDoableRecipe(ref inventoryOnceUsed, craftingSource,
ingredientsNeeded, ingredientRecipe, craftedItemsOnceUsed, depth + 1);
ingredientsNeeded -= AmountOfDoableRecipe(ref inventoryOnceUsed,
ref trueInventoryOnceUsed, ref currentRecipeUsed, craftingSource,
ingredientsNeeded, trueIngredientsNeeded, ingredientRecipe,
craftedItemsOnceUsed, depth + 1);
if (ingredientsNeeded <= 0)
break;
}
Expand All @@ -300,7 +337,9 @@ public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse,
}
else if (amount > timeCraft * recipe.createItem.stack)
{
return AmountOfDoableRecipe(ref inventoryToUse, craftingSource, timeCraft * recipe.createItem.stack,
trueTimeCraft = Math.Min(timeCraft, trueTimeCraft);
return AmountOfDoableRecipe(ref inventoryToUse, ref trueInventoryToUse, ref currentRecipeUsed,
craftingSource, timeCraft * recipe.createItem.stack, trueTimeCraft * recipe.createItem.stack,
recipe, craftedItems, depth);
}
else
Expand All @@ -313,12 +352,29 @@ public static int AmountOfDoableRecipe(ref Dictionary<int, int> inventoryToUse,
inventoryOnceUsed.Add(recipe.createItem.type, timeCraft * recipe.createItem.stack - amount);
}

if (trueAmount < trueTimeCraft * recipe.createItem.stack)
{
if (trueInventoryOnceUsed.ContainsKey(recipe.createItem.type))
trueInventoryOnceUsed[recipe.createItem.type] +=
trueTimeCraft * recipe.createItem.stack - trueAmount;
else
trueInventoryOnceUsed.Add(recipe.createItem.type,
trueTimeCraft * recipe.createItem.stack - trueAmount);
}

if (currentRecipeUsed.ContainsKey(recipe))
currentRecipeUsed[recipe] += trueTimeCraft;
else
currentRecipeUsed.Add(recipe, trueTimeCraft);

inventoryToUse = inventoryOnceUsed;
trueInventoryToUse = trueInventoryOnceUsed;
recipeUsed = currentRecipeUsed;
return amount;
}
}

private static bool IsAvailable(Recipe recipe, CraftingSource craftingSource)
public static bool IsAvailable(Recipe recipe, CraftingSource craftingSource)
{
if (!RecipeHooks.RecipeAvailable(recipe))
return false;
Expand Down
2 changes: 1 addition & 1 deletion build.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
displayName = Recursive Craft
author = Gaelyte
version = 1.1
version = 1.2
homepage = https://github.com/Ishigh1/RecursiveCraft
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 1.2
* Fixed an issue with recipes needing more than 15 ingredients
* Fixed an issue with OnCraft not being called
* Fixed an issue where intermediate alchemy bonus wasn't well applied

# 1.1
* Reworked the code to make implementations of mods like Magic Storage easier (they are not compatible yet)
* Allowed items needing themselves in the craftings
Expand Down

0 comments on commit 33f79fe

Please sign in to comment.