diff --git a/src/main/java/WayofTime/bloodmagic/compress/AdvancedCompressionHandler.java b/src/main/java/WayofTime/bloodmagic/compress/AdvancedCompressionHandler.java index b5d78913..e2dc02d1 100644 --- a/src/main/java/WayofTime/bloodmagic/compress/AdvancedCompressionHandler.java +++ b/src/main/java/WayofTime/bloodmagic/compress/AdvancedCompressionHandler.java @@ -1,86 +1,12 @@ package WayofTime.bloodmagic.compress; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Container; -import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.CraftingManager; -import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.Tuple; import net.minecraft.world.World; public class AdvancedCompressionHandler extends CompressionHandler { - private static InventoryCrafting[] inventoryCrafting = { - new InventoryCrafting(new Container() { - public boolean canInteractWith(EntityPlayer player) { - return false; - } - }, - 3, 3), - new InventoryCrafting(new Container() { - public boolean canInteractWith(EntityPlayer player) { - return false; - } - }, - 2, 2), - new InventoryCrafting(new Container() { - public boolean canInteractWith(EntityPlayer player) { - return false; - } - }, - 1, 1) - - }; - - private static ItemStack reversibleCheck; - - public static boolean isResultStackReversible(ItemStack stack, World world) { - if (stack.isEmpty()) { - return false; - } - - inventoryCrafting[2].setInventorySlotContents(0, stack); - ItemStack returnStack = getNNRecipeOutput(inventoryCrafting[2], world); - - return !returnStack.isEmpty() && CompressionRegistry.areItemStacksEqual(reversibleCheck, returnStack); - } - - public static ItemStack getRecipe(ItemStack stack, World world, int gridSize) { - StorageBlockCraftingManager craftingManagerSB = StorageBlockCraftingManager.getInstance(); - InventoryCrafting inventory = inventoryCrafting[3 - gridSize]; - for (int i = 0; i < inventory.getSizeInventory(); i++) { - inventory.setInventorySlotContents(i, stack); - } - ItemStack notEmptyRecipe = craftingManagerSB.findMatchingRecipe(inventory, world); - if (!notEmptyRecipe.isEmpty()) { - return notEmptyRecipe; - } - ItemStack result = getNNRecipeOutput(inventory, world); - - if (isResultStackReversible(result, world)) { - craftingManagerSB.addRecipe(CraftingManager.findMatchingRecipe(inventory, world)); - return result; - } - return ItemStack.EMPTY; - } - - public static ItemStack getNNRecipeOutput(InventoryCrafting inventory, World world) { - IRecipe checkForNull = CraftingManager.findMatchingRecipe(inventory, world); - if (checkForNull != null) { - return checkForNull.getRecipeOutput(); - } - return ItemStack.EMPTY; - } - - public static ItemStack get22Recipe(ItemStack stack, World world) { - return getRecipe(stack, world, 2); - } - - public static ItemStack get33Recipe(ItemStack stack, World world) { - return getRecipe(stack, world, 3); - } - public ItemStack compressInventory(ItemStack[] inv, World world) { for (ItemStack invStack : inv) { if (invStack.isEmpty()) { @@ -88,12 +14,26 @@ public class AdvancedCompressionHandler extends CompressionHandler { } for (int i = 3; i >= 2; i--) { - reversibleCheck = invStack; - ItemStack stack = getRecipe(invStack, world, i); + ItemStack invStackCopy = invStack.copy(); + invStackCopy.setCount(1); + Tuple stackTuple = CompressionRegistry.compressionMap.get(invStackCopy); + ItemStack stack; + if (stackTuple == null) { + StorageBlockCraftingManager.reversibleCheck = invStack; + stack = StorageBlockCraftingManager.getRecipe(invStack, world, i); + if (stack.isEmpty()) + continue; + CompressionRegistry.compressionMap.put(invStackCopy, new Tuple<>(stack, i * i)); + } else { + stack = stackTuple.getFirst(); + if (stackTuple.getSecond() != i * i) + return ItemStack.EMPTY; + } + if (!stack.isEmpty()) { int needed = (i == 2 ? 4 : 9); - int remaining = iterateThroughInventory(invStack, invStack.getMaxStackSize() - needed, inv, needed, true); // if more than needed gets consumed at any point, the simulate test was needed after all + int remaining = iterateThroughInventory(invStack, CompressionRegistry.getItemThreshold(invStack, needed), inv, needed, true); if (remaining <= 0) return stack; } diff --git a/src/main/java/WayofTime/bloodmagic/compress/CompressionHandler.java b/src/main/java/WayofTime/bloodmagic/compress/CompressionHandler.java index 2cd74d14..715a7b19 100644 --- a/src/main/java/WayofTime/bloodmagic/compress/CompressionHandler.java +++ b/src/main/java/WayofTime/bloodmagic/compress/CompressionHandler.java @@ -3,6 +3,9 @@ package WayofTime.bloodmagic.compress; import net.minecraft.item.ItemStack; import net.minecraft.world.World; +import java.util.HashSet; +import java.util.Set; + public abstract class CompressionHandler { /** * Called to look at the inventory and syphons the required stack. Returns @@ -14,7 +17,9 @@ public abstract class CompressionHandler { public abstract ItemStack compressInventory(ItemStack[] inv, World world); public int iterateThroughInventory(ItemStack required, int kept, ItemStack[] inv, int needed, boolean doDrain) { + int oldNeeded = needed; int i = -1; + Set consumeSet = new HashSet<>(); for (ItemStack invStack : inv) { i++; @@ -31,26 +36,32 @@ public abstract class CompressionHandler { used += stackSize - remainingFromStack; } - kept -= used; // 0 + kept -= used; if (kept <= 0 && needed > 0) { int remainingFromStack = Math.max(stackSize - used - needed, 0); - if (doDrain) { + needed -= (stackSize - used - remainingFromStack); + if (needed != 0 && needed < oldNeeded) { + consumeSet.add(i); + } + + if (doDrain && (!(needed < oldNeeded) || needed == 0)) { invStack.setCount(remainingFromStack + used); + for (Integer j : consumeSet) { + inv[j].setCount(0); + inv[j] = ItemStack.EMPTY; + } + consumeSet.clear(); if (invStack.isEmpty()) { inv[i] = ItemStack.EMPTY; } } - - needed -= (stackSize - used - remainingFromStack); } - if (needed <= 0) { return 0; } } } - return needed; diff --git a/src/main/java/WayofTime/bloodmagic/compress/CompressionRegistry.java b/src/main/java/WayofTime/bloodmagic/compress/CompressionRegistry.java index 8c10fa3a..fb1de055 100644 --- a/src/main/java/WayofTime/bloodmagic/compress/CompressionRegistry.java +++ b/src/main/java/WayofTime/bloodmagic/compress/CompressionRegistry.java @@ -3,6 +3,7 @@ package WayofTime.bloodmagic.compress; import WayofTime.bloodmagic.util.Utils; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Tuple; import net.minecraft.world.World; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -18,8 +19,9 @@ import java.util.Map; * form. */ public class CompressionRegistry { - public static List compressionRegistry = new ArrayList<>(); + private static List compressionRegistry = new ArrayList<>(); public static Map thresholdMap = new HashMap<>(); + static Map> compressionMap = new HashMap<>(); public static void registerHandler(CompressionHandler handler) { compressionRegistry.add(handler); @@ -77,10 +79,24 @@ public class CompressionRegistry { return Pair.of(ItemStack.EMPTY, false); } - public static int getItemThreshold(ItemStack stack) { - return stack.getItem().getItemStackLimit(stack); //this should work according to the guide, leaving behind a full stack of the source item (unless otherwise specified with a BaseCompressionHandler recipe) + + public static int getItemThreshold(ItemStack stack, int needed) { + Integer threshold = thresholdMap.get(stack); + if (threshold != null) + return threshold; + else + return stack.getMaxStackSize() - needed; } + public static int getItemThreshold(ItemStack stack) { + Integer threshold = thresholdMap.get(stack); + if (threshold != null) + return threshold; + else + return stack.getMaxStackSize(); + } + + public static boolean areItemStacksEqual(ItemStack stack, ItemStack compressedStack) { return stack.isItemEqual(compressedStack) && (stack.getTagCompound() == null ? !compressedStack.hasTagCompound() : stack.getTagCompound().equals(compressedStack.getTagCompound())); } diff --git a/src/main/java/WayofTime/bloodmagic/compress/StorageBlockCraftingManager.java b/src/main/java/WayofTime/bloodmagic/compress/StorageBlockCraftingManager.java index cfe039c1..71b6120e 100644 --- a/src/main/java/WayofTime/bloodmagic/compress/StorageBlockCraftingManager.java +++ b/src/main/java/WayofTime/bloodmagic/compress/StorageBlockCraftingManager.java @@ -6,15 +6,89 @@ import net.minecraft.inventory.Container; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.world.World; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; public class StorageBlockCraftingManager { private static final StorageBlockCraftingManager instance = new StorageBlockCraftingManager(); - private List recipes = new LinkedList<>(); + private static InventoryCrafting[] inventoryCrafting = { + new InventoryCrafting(new Container() { + public boolean canInteractWith(EntityPlayer player) { + return false; + } + }, + 3, 3), + new InventoryCrafting(new Container() { + public boolean canInteractWith(EntityPlayer player) { + return false; + } + }, + 2, 2), + new InventoryCrafting(new Container() { + public boolean canInteractWith(EntityPlayer player) { + return false; + } + }, + 1, 1) + + }; + static ItemStack reversibleCheck; + private HashSet recipes = new HashSet<>(); // TODO: Clear when recipes are reloaded in 1.14 + private Set blacklist = new HashSet<>(); + + public static boolean isResultStackReversible(ItemStack stack, World world) { + if (stack.isEmpty()) { + return false; + } + + inventoryCrafting[2].setInventorySlotContents(0, stack); + ItemStack returnStack = getNNRecipeOutput(inventoryCrafting[2], world); + + return !returnStack.isEmpty() && CompressionRegistry.areItemStacksEqual(reversibleCheck, returnStack); + } + + public static ItemStack getRecipe(ItemStack stack, World world, int gridSize) { + StorageBlockCraftingManager craftingManagerSB = getInstance(); + if (craftingManagerSB.blacklist.contains(stack)) { + return ItemStack.EMPTY; + } + InventoryCrafting inventory = inventoryCrafting[3 - gridSize]; + for (int i = 0; i < inventory.getSizeInventory(); i++) { + inventory.setInventorySlotContents(i, stack); + } + ItemStack notEmptyRecipe = craftingManagerSB.findMatchingRecipe(inventory, world); + if (!notEmptyRecipe.isEmpty()) { + return notEmptyRecipe; + } + ItemStack result = getNNRecipeOutput(inventory, world); + + if (isResultStackReversible(result, world)) { + craftingManagerSB.addRecipe(CraftingManager.findMatchingRecipe(inventory, world)); + return result; + } + craftingManagerSB.blacklist.add(stack); + return ItemStack.EMPTY; + } + + public static ItemStack getNNRecipeOutput(InventoryCrafting inventory, World world) { + IRecipe checkForNull = CraftingManager.findMatchingRecipe(inventory, world); + if (checkForNull != null) { + return checkForNull.getRecipeOutput(); + } + return ItemStack.EMPTY; + } + + public static ItemStack get22Recipe(ItemStack stack, World world) { + return getRecipe(stack, world, 2); + } + + public static ItemStack get33Recipe(ItemStack stack, World world) { + return getRecipe(stack, world, 3); + } public void addRecipe(IRecipe recipe) { this.recipes.add(recipe); @@ -32,7 +106,7 @@ public class StorageBlockCraftingManager { return this.findMatchingRecipe(craftingInventory, world, this.recipes); } - private ItemStack findMatchingRecipe(InventoryCrafting craftingInventory, World world, List list) { + private ItemStack findMatchingRecipe(InventoryCrafting craftingInventory, World world, HashSet list) { int i = 0; ItemStack itemstack = ItemStack.EMPTY; ItemStack itemstack1 = ItemStack.EMPTY; @@ -67,11 +141,10 @@ public class StorageBlockCraftingManager { return new ItemStack(itemstack.getItem(), 1, i1); } else { - for (j = 0; j < list.size(); ++j) { - IRecipe irecipe = list.get(j); + for (IRecipe iRecipe : list) { - if (irecipe.matches(craftingInventory, world)) { - return irecipe.getCraftingResult(craftingInventory); + if (iRecipe.matches(craftingInventory, world)) { + return iRecipe.getCraftingResult(craftingInventory); } } @@ -83,62 +156,5 @@ public class StorageBlockCraftingManager { return instance; } - private static boolean isResultStackReversible(ItemStack stack, int gridSize, World world, List list) { - if (stack.isEmpty()) { - return false; - } - InventoryCrafting inventory = new InventoryCrafting(new Container() { - public boolean canInteractWith(EntityPlayer player) { - return false; - } - }, 2, 2); - inventory.setInventorySlotContents(0, stack); - - ItemStack returnStack = StorageBlockCraftingManager.getInstance().findMatchingRecipe(inventory, world, list); - if (returnStack.isEmpty()) { - return false; - } - - ItemStack compressedStack = ItemStack.EMPTY; - switch (gridSize) { - case 2: - compressedStack = get22Recipe(returnStack, world, list); - break; - case 3: - compressedStack = get33Recipe(returnStack, world, list); - break; - } - - return !compressedStack.isEmpty() && CompressionRegistry.areItemStacksEqual(stack, compressedStack); - } - - private static ItemStack getRecipe(ItemStack stack, World world, int gridSize, List list) { - InventoryCrafting inventory = new InventoryCrafting(new Container() { - public boolean canInteractWith(EntityPlayer player) { - return false; - } - }, gridSize, gridSize); - for (int i = 0; i < inventory.getSizeInventory(); i++) { - inventory.setInventorySlotContents(i, stack); - } - - return StorageBlockCraftingManager.getInstance().findMatchingRecipe(inventory, world, list); - } - - private static boolean has22Recipe(ItemStack stack, World world, List list) { - return !get22Recipe(stack, world, list).isEmpty(); - } - - private static ItemStack get22Recipe(ItemStack stack, World world, List list) { - return getRecipe(stack, world, 2, list); - } - - private static boolean has33Recipe(ItemStack stack, World world, List list) { - return !get33Recipe(stack, world, list).isEmpty(); - } - - private static ItemStack get33Recipe(ItemStack stack, World world, List list) { - return getRecipe(stack, world, 3, list); - } }