diff --git a/src/main/java/codechicken/nei/NEIClientConfig.java b/src/main/java/codechicken/nei/NEIClientConfig.java index e7ed989f..ce65699e 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -746,8 +746,7 @@ public class NEIClientConfig { API.addHashBind("gui.remove_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH); API.addKeyBind("gui.bookmark_pull_items", Keyboard.KEY_V); API.addKeyBind("gui.overlay", Keyboard.KEY_S); - API.addHashBind("gui.craft_all", Keyboard.KEY_C + NEIClientUtils.SHIFT_HASH); - API.addHashBind("gui.craft_missing", Keyboard.KEY_C + NEIClientUtils.SHIFT_HASH + NEIKeyboardUtils.CTRL_HASH); + API.addKeyBind("gui.craft_items", Keyboard.KEY_C); API.addHashBind("gui.hide_bookmarks", Keyboard.KEY_B); API.addKeyBind("gui.getprevioussearch", Keyboard.KEY_UP); API.addKeyBind("gui.getnextsearch", Keyboard.KEY_DOWN); diff --git a/src/main/java/codechicken/nei/NEIServerUtils.java b/src/main/java/codechicken/nei/NEIServerUtils.java index adff7e14..68a4d19d 100644 --- a/src/main/java/codechicken/nei/NEIServerUtils.java +++ b/src/main/java/codechicken/nei/NEIServerUtils.java @@ -199,17 +199,25 @@ public class NEIServerUtils { if (NEIServerUtils.areStacksSameTypeCrafting(stack2, stack1)) { if (NBTHelper.matchTag(stack1.getTagCompound(), stack2.getTagCompound())) return true; - - return (isItemTool(stack1) || stack1.getMaxStackSize() == 1 && stack2.getMaxStackSize() == 1) + if (isItemTool(stack1) + && (stack1.stackTagCompound == null || stack1.stackTagCompound.hasKey("GT.ToolStats")) + && (stack2.stackTagCompound == null || stack2.stackTagCompound.hasKey("GT.ToolStats"))) + return true; + return stack1.getMaxStackSize() == 1 && stack2.getMaxStackSize() == 1 && (stack1.stackTagCompound == null ^ stack2.stackTagCompound == null); } return false; } + /** + * GT Items don't have any NBT set for the recipe, so if either of the stacks has a NULL nbt, and the other doesn't, + * pretend they stack + * + * @param ItemStack stack + * @return + */ public static boolean isItemTool(ItemStack stack) { - // GT Items don't have any NBT set for the recipe, so if either of the stacks has a NULL nbt, and the other - // doesn't, pretend they stack return NEIServerUtils.gtMetaBaseItem != null && NEIServerUtils.gtMetaBaseItem.isInstance(stack.getItem()); } diff --git a/src/main/java/codechicken/nei/api/ShortcutInputHandler.java b/src/main/java/codechicken/nei/api/ShortcutInputHandler.java index c030a611..68e936e5 100644 --- a/src/main/java/codechicken/nei/api/ShortcutInputHandler.java +++ b/src/main/java/codechicken/nei/api/ShortcutInputHandler.java @@ -66,24 +66,20 @@ public abstract class ShortcutInputHandler { return ItemPanels.bookmarkPanel.pullBookmarkItems(groupId, NEIClientUtils.shiftKey()); } - if (NEIClientConfig.autocraftingEnabled() + if (NEIClientConfig.autocraftingEnabled() && NEIClientConfig.isKeyHashDown("gui.craft_items") + && NEIClientUtils.shiftKey() && ItemPanels.bookmarkPanel.getGrid().isCraftingMode(groupId)) { - final boolean ignoreInventory = NEIClientConfig.isKeyHashDown("gui.craft_all"); + final RecipeChainMath math = ItemPanels.bookmarkPanel.getGrid().createRecipeChainMath(groupId); - if (ignoreInventory || NEIClientConfig.isKeyHashDown("gui.craft_missing")) { - final RecipeChainMath math = ItemPanels.bookmarkPanel.getGrid().createRecipeChainMath(groupId); + if (math != null) { - if (math != null) { - - if (ignoreInventory) { - autocraftingIgnoreInventory(math); - } - - AutoCraftingManager.runProcessing(math); - return true; + if (!NEIClientUtils.controlKey()) { + autocraftingIgnoreInventory(math); } - } + AutoCraftingManager.runProcessing(math); + return true; + } } } @@ -121,12 +117,9 @@ public abstract class ShortcutInputHandler { return pullRecipeItems(stackover, NEIClientUtils.shiftKey()); } - if (NEIClientConfig.autocraftingEnabled() && NEIClientConfig.isKeyHashDown("gui.craft_missing")) { - return runAutoCrafting(stackover, false); - } - - if (NEIClientConfig.autocraftingEnabled() && NEIClientConfig.isKeyHashDown("gui.craft_all")) { - return runAutoCrafting(stackover, true); + if (NEIClientConfig.autocraftingEnabled() && NEIClientConfig.isKeyHashDown("gui.craft_items") + && NEIClientUtils.shiftKey()) { + return runAutoCrafting(stackover, !NEIClientUtils.controlKey()); } return false; @@ -358,10 +351,11 @@ public abstract class ShortcutInputHandler { if (NEIClientConfig.autocraftingEnabled() && ItemPanels.bookmarkPanel.getGrid().isCraftingMode(groupId)) { hotkeys.put( - NEIClientConfig.getKeyName("gui.craft_missing"), + NEIClientConfig + .getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH), NEIClientUtils.translate("bookmark.group.craft_missing")); hotkeys.put( - NEIClientConfig.getKeyName("gui.craft_all"), + NEIClientConfig.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH), NEIClientUtils.translate("bookmark.group.craft_all")); } } @@ -459,10 +453,12 @@ public abstract class ShortcutInputHandler { if (NEIClientConfig.autocraftingEnabled()) { hotkeys.put( - NEIClientConfig.getKeyName("gui.craft_missing"), + NEIClientConfig.getKeyName( + "gui.craft_items", + NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH), NEIClientUtils.translate("itempanel.craft_missing")); hotkeys.put( - NEIClientConfig.getKeyName("gui.craft_all"), + NEIClientConfig.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH), NEIClientUtils.translate("itempanel.craft_all")); } } diff --git a/src/main/java/codechicken/nei/bookmark/BookmarkItem.java b/src/main/java/codechicken/nei/bookmark/BookmarkItem.java index 945d98a7..adc56de2 100644 --- a/src/main/java/codechicken/nei/bookmark/BookmarkItem.java +++ b/src/main/java/codechicken/nei/bookmark/BookmarkItem.java @@ -132,6 +132,7 @@ public class BookmarkItem { for (Map.Entry entry : BookmarkItem.fuzzyPermutations.entrySet()) { if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, entry.getKey())) { + BookmarkItem.fuzzyPermutations.put(stack, entry.getValue()); return entry.getValue(); } } diff --git a/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java b/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java index 3bc635f0..445ff145 100644 --- a/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java +++ b/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java @@ -142,9 +142,7 @@ public class RecipeChainDetails { if (collapsedRecipes.isEmpty()) { for (BookmarkItem item : math.recipeResults) { - if (sortingChainItems.containsKey(item)) { - generateResult(math, item, sortingChainItems.get(item)); - } + generateResult(math, item, sortingChainItems.get(item)); } for (BookmarkItem item : math.recipeIngredients) { diff --git a/src/main/java/codechicken/nei/recipe/DefaultOverlayHandler.java b/src/main/java/codechicken/nei/recipe/DefaultOverlayHandler.java index 9e45b390..dd08c4ca 100644 --- a/src/main/java/codechicken/nei/recipe/DefaultOverlayHandler.java +++ b/src/main/java/codechicken/nei/recipe/DefaultOverlayHandler.java @@ -6,9 +6,11 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Slot; import net.minecraft.inventory.SlotCrafting; @@ -33,6 +35,7 @@ public class DefaultOverlayHandler implements IOverlayHandler { public int distributed; public int numSlots; public int recipeAmount; + public boolean isContainerItem = false; } public static class IngredientDistribution { @@ -137,67 +140,103 @@ public class DefaultOverlayHandler implements IOverlayHandler { } } - return true; + return dropOffMouseStack(thePlayer, gui); } private void moveIngredients(GuiContainer gui, List assignedIngredients, int multiplier) { - for (IngredientDistribution distrib : assignedIngredients) { - if (distrib.slots.length == 0) continue; + final EntityClientPlayerMP thePlayer = NEIClientUtils.mc().thePlayer; - ItemStack pstack = distrib.permutation; - int transferCap = multiplier * pstack.stackSize; - int transferred = 0; + for (Slot slot : gui.inventorySlots.inventorySlots) { + if (slot instanceof SlotCrafting || !slot.getHasStack() + || !canMoveFrom(slot, gui) + || !slot.canTakeStack(thePlayer)) + continue; + ItemStack stack = slot.getStack(); + int slotTransferCap = stack.getMaxStackSize(); - int destSlotIndex = 0; - Slot dest = distrib.slots[0]; - int slotTransferred = 0; - int slotTransferCap = pstack.getMaxStackSize(); + for (IngredientDistribution distrib : assignedIngredients) { + if (distrib.slots.length == 0 || !slot.getHasStack() || !canStack(distrib.permutation, stack)) continue; + int transferCap = Math.min(slotTransferCap, multiplier * distrib.permutation.stackSize); + int stackSize = slot.getStack().stackSize; + boolean pickup = false; - for (Slot slot : gui.inventorySlots.inventorySlots) { - if (!slot.getHasStack() || !canMoveFrom(slot, gui)) continue; + for (Slot dest : distrib.slots) { + int amount = Math + .min(transferCap - (dest.getHasStack() ? dest.getStack().stackSize : 0), stackSize); - ItemStack stack = slot.getStack(); - if (!canStack(pstack, stack)) continue; + if (stackSize <= amount) { - int amount = Math.min(transferCap - transferred, stack.stackSize); - FastTransferManager.clickSlot(gui, slot.slotNumber); - for (int c = 0; c < amount; c++) { - FastTransferManager.clickSlot(gui, dest.slotNumber, 1); - transferred++; - slotTransferred++; - if (slotTransferred >= slotTransferCap) { - destSlotIndex++; - if (destSlotIndex == distrib.slots.length) { - dest = null; - break; + if (!pickup) { + FastTransferManager.clickSlot(gui, slot.slotNumber); + } + + FastTransferManager.clickSlot(gui, dest.slotNumber); + break; + } else { + + for (int c = 0; c < amount; c++) { + + if (pickup != (pickup = true)) { + FastTransferManager.clickSlot(gui, slot.slotNumber); + } + + FastTransferManager.clickSlot(gui, dest.slotNumber, 1); + stackSize--; } - dest = distrib.slots[destSlotIndex]; - slotTransferred = 0; } + } - FastTransferManager.clickSlot(gui, slot.slotNumber); - if (transferred >= transferCap || dest == null) break; + + if (thePlayer.inventory.getItemStack() != null) { + FastTransferManager.clickSlot(gui, slot.slotNumber); + } + } + + } + } + + protected boolean dropOffMouseStack(EntityPlayer entityPlayer, GuiContainer gui) { + + if (entityPlayer.inventory.getItemStack() == null) { + return true; + } + + for (int i = 0; i < gui.inventorySlots.inventorySlots.size(); i++) { + Slot slot = gui.inventorySlots.inventorySlots.get(i); + + if (slot.inventory == entityPlayer.inventory) { + ItemStack mouseItem = entityPlayer.inventory.getItemStack(); + ItemStack slotStack = slot.getStack(); + + if (slotStack == null || NEIClientUtils.areStacksSameType(mouseItem, slotStack)) { + FastTransferManager.clickSlot(gui, i, 0, 0); + } + + if (entityPlayer.inventory.getItemStack() == null) { + return true; + } + } } + + return entityPlayer.inventory.getItemStack() == null; } private int calculateRecipeQuantity(List assignedIngredients) { int quantity = Integer.MAX_VALUE; for (IngredientDistribution distrib : assignedIngredients) { - DistributedIngred istack = distrib.distrib; + final DistributedIngred istack = distrib.distrib; if (istack.numSlots == 0) return 0; final int maxStackSize = istack.stack.getMaxStackSize(); - int allSlots = istack.invAmount; - if (allSlots / istack.numSlots > maxStackSize) allSlots = istack.numSlots * maxStackSize; - - final int newQuantity = allSlots / istack.distributed; - if (maxStackSize == 1) { + if (maxStackSize == 1 && istack.isContainerItem) { // If non-stackable, fill up as much as possible of the other ingredients continue; } - quantity = Math.min(quantity, newQuantity); + + final int allSlots = Math.min(istack.invAmount, istack.numSlots * maxStackSize); + quantity = Math.min(quantity, allSlots / istack.distributed); } if (quantity == Integer.MAX_VALUE) { @@ -292,9 +331,20 @@ public class DefaultOverlayHandler implements IOverlayHandler { private void findInventoryQuantities(GuiContainer gui, List ingredStacks) { for (Slot slot : gui.inventorySlots.inventorySlots) /* work out how much we have to go round */ { if (slot.getHasStack() && canMoveFrom(slot, gui)) { - ItemStack pstack = slot.getStack(); - DistributedIngred istack = findIngred(ingredStacks, pstack); - if (istack != null) istack.invAmount += pstack.stackSize; + final ItemStack pstack = slot.getStack(); + final DistributedIngred istack = findIngred(ingredStacks, pstack); + + if (istack != null) { + istack.invAmount += pstack.stackSize; + + if (!istack.isContainerItem && pstack.getMaxStackSize() == 1 + && pstack.getItem().hasContainerItem(pstack)) { + final Optional containerItem = StackInfo.getContainerItem(pstack); + if (containerItem != null && containerItem.isPresent()) { + istack.isContainerItem = pstack.getItem() == containerItem.get().getItem(); + } + } + } } } } diff --git a/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java b/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java index 3255f7a0..5d967afd 100644 --- a/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java +++ b/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java @@ -14,6 +14,7 @@ import codechicken.nei.recipe.Recipe.RecipeId; public class RecipeHandlerRef { + private static final LRUCache, Boolean> transferAlghoritmCache = new LRUCache<>(200); private static final LRUCache recipeRefCache = new LRUCache<>(200); public final IRecipeHandler handler; public final int recipeIndex; @@ -139,20 +140,36 @@ public class RecipeHandlerRef { public boolean allowedTransferAlghoritm(GuiContainer gui) { final IOverlayHandler overlayHandler = getOverlayHandler(gui); - if (overlayHandler != null) { - try { - return !overlayHandler.getClass() - .getDeclaredMethod( - "transferRecipe", - GuiContainer.class, - IRecipeHandler.class, - int.class, - int.class) - .isDefault(); - } catch (NoSuchMethodException e) {} + if (overlayHandler == null) { + return false; } - return false; + return transferAlghoritmCache.computeIfAbsent(overlayHandler.getClass(), clazz -> { + + try { + + if (overlayHandler instanceof DefaultOverlayHandler) { + final Class overlayRecipeClazz = overlayHandler.getClass() + .getMethod( + "overlayRecipe", + GuiContainer.class, + IRecipeHandler.class, + int.class, + boolean.class) + .getDeclaringClass(); + + if (overlayRecipeClazz.equals(DefaultOverlayHandler.class)) { + return true; + } + } + + return !overlayHandler.getClass() + .getMethod("transferRecipe", GuiContainer.class, IRecipeHandler.class, int.class, int.class) + .isDefault(); + } catch (NoSuchMethodException e) {} + + return false; + }); } public IRecipeOverlayRenderer getRecipeOverlayRenderer(GuiContainer gui) { diff --git a/src/main/java/codechicken/nei/recipe/chain/RecipeChainMath.java b/src/main/java/codechicken/nei/recipe/chain/RecipeChainMath.java index 6ba1eff1..c0183495 100644 --- a/src/main/java/codechicken/nei/recipe/chain/RecipeChainMath.java +++ b/src/main/java/codechicken/nei/recipe/chain/RecipeChainMath.java @@ -10,10 +10,10 @@ import java.util.Optional; import java.util.Set; import net.minecraft.init.Blocks; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import codechicken.nei.ItemStackAmount; +import codechicken.nei.NEIClientUtils; import codechicken.nei.bookmark.BookmarkItem; import codechicken.nei.recipe.Recipe; import codechicken.nei.recipe.Recipe.RecipeId; @@ -34,7 +34,8 @@ public class RecipeChainMath { public final Map preferredItems = new HashMap<>(); public final Map requiredAmount = new HashMap<>(); - public final Map requiredContainerItem = new HashMap<>(); + public final List containerItems = new ArrayList<>(); + private final List containerItemsBlacklist = new ArrayList<>(); private RecipeChainMath(List recipeItems, Set collapsedRecipes) { final Map recipeState = new HashMap<>(); @@ -51,17 +52,7 @@ public class RecipeChainMath { if (recipeState.getOrDefault(item.recipeId, 0) != 3) { this.initialItems.add(item.copy()); } else if (item.isIngredient) { - final Optional containerItem = StackInfo.getContainerItem(item.getItemStack(1)); this.recipeIngredients.add(item.copyWithAmount(0)); - - if (containerItem != null && containerItem.isPresent()) { - final ItemStack stack = containerItem.get(); - - if (Item.getIdFromItem(item.itemStack.getItem()) != Item.getIdFromItem(stack.getItem())) { - this.recipeResults.add(BookmarkItem.of(-2, stack, 1, item.recipeId, false).copyWithAmount(0)); - } - } - } else { this.recipeResults.add(item.copyWithAmount(0)); multipliers.put( @@ -165,8 +156,7 @@ public class RecipeChainMath { final List rootIngredients = new ArrayList<>(); for (BookmarkItem item : this.recipeResults) { - if (item.groupId != -2 && this.outputRecipes.containsKey(item.recipeId) - && !ROOT_RECIPE_ID.equals(item.recipeId)) { + if (this.outputRecipes.containsKey(item.recipeId) && !ROOT_RECIPE_ID.equals(item.recipeId)) { final long amount = item.factor * this.outputRecipes.get(item.recipeId); rootIngredients.add( BookmarkItem.of( @@ -260,23 +250,36 @@ public class RecipeChainMath { this.preferredItems.clear(); this.requiredAmount.clear(); - this.requiredContainerItem.clear(); + this.containerItems.clear(); + this.containerItemsBlacklist.clear(); for (RecipeId recipeId : this.outputRecipes.keySet()) { collectPreferredItems(recipeId, this.preferredItems, new HashSet<>()); } - } public RecipeChainMath refresh() { resetCalculation(); + if (this.outputRecipes.containsKey(ROOT_RECIPE_ID)) { + for (BookmarkItem ingrItem : this.recipeIngredients) { + if (ROOT_RECIPE_ID.equals(ingrItem.recipeId) + && ingrItem.itemStack.getItem().hasContainerItem(ingrItem.itemStack)) { + this.containerItemsBlacklist.add(ingrItem.itemStack); + } + } + } + for (BookmarkItem prefItem : this.recipeResults) { if (prefItem.factor > 0 && this.outputRecipes.containsKey(prefItem.recipeId)) { final long prefAmount = prefItem.factor * this.outputRecipes.get(prefItem.recipeId); + if (prefItem.itemStack.getItem().hasContainerItem(prefItem.itemStack)) { + this.containerItemsBlacklist.add(prefItem.itemStack); + } + this.preferredItems.put(prefItem, prefItem); - calculateSuitableRecipe(prefItem, prepareAmount(prefItem, prefAmount), new ArrayList<>()); + calculateSuitableRecipe(prefItem, prefAmount, new ArrayList<>()); this.preferredItems.remove(prefItem); } } @@ -295,7 +298,7 @@ public class RecipeChainMath { private void prepareIngredients(RecipeId recipeId, long stepShift, List visited) { for (BookmarkItem item : this.recipeIngredients) { if (item.factor > 0 && recipeId.equals(item.recipeId)) { - calculateSuitableRecipe(item, prepareAmount(item, item.factor * stepShift), visited); + calculateSuitableRecipe(item, item.factor * stepShift, visited); } } } @@ -303,18 +306,41 @@ public class RecipeChainMath { private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List visited) { final BookmarkItem prefItem = this.preferredItems.get(ingrItem); + // calculate existing containers + if (ingrAmount > 0) { + for (ItemStack stack : ingrItem.permutations.values()) { + if (hasContainerItem(stack)) { + final long stackSize = ingrItem.getStackSize(ingrAmount); + final long shiftSize = shiftContainerItems(stack, stackSize); + if (stackSize != shiftSize && (ingrAmount = shiftSize * ingrItem.fluidCellAmount) == 0) { + break; + } + } + } + } + + // calculate existing initial items + if (ingrAmount > 0) { + for (BookmarkItem item : this.initialItems) { + if (item.containsItems(ingrItem) + && (ingrAmount = addRequiredAmount(item, ingrAmount, item.amount)) == 0) { + break; + } + } + } + + // shift amount if (prefItem == null) { - addRequiredAmount(ingrItem, ingrAmount); + addRequiredAmount(ingrItem, ingrAmount, Long.MAX_VALUE); } else if (visited.contains(prefItem.recipeId)) { - addRequiredAmount(prefItem, ingrAmount); + addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE); } else { - addRequiredAmount(prefItem, ingrAmount); + addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE); final long shift = (long) Math .ceil((this.requiredAmount.get(prefItem) - prefItem.amount) / (double) prefItem.factor); if (shift > 0) { addShift(prefItem.recipeId, shift); - visited.add(prefItem.recipeId); prepareIngredients(prefItem.recipeId, shift, visited); visited.remove(prefItem.recipeId); @@ -323,79 +349,85 @@ public class RecipeChainMath { } - private void addRequiredAmount(BookmarkItem prefItem, long ingrAmount) { - long amount = this.requiredAmount.getOrDefault(prefItem, 0L); + private long addRequiredAmount(BookmarkItem prefItem, long ingrAmount, long maxAmount) { + long shiftAmount = this.requiredAmount.getOrDefault(prefItem, 0L); + + if (hasContainerItem(prefItem.itemStack)) { + ItemStack itemStack = prefItem.itemStack; + + while (ingrAmount > 0 && shiftAmount < maxAmount) { + itemStack = itemStack.copy(); + itemStack.stackSize = 1; + + this.containerItems.add(itemStack); + ingrAmount = shiftContainerItems(itemStack, prefItem.getStackSize(ingrAmount)) + * prefItem.fluidCellAmount; + + shiftAmount += prefItem.fluidCellAmount; + } - if (prefItem.itemStack.getItem().hasContainerItem(prefItem.itemStack)) { - amount += calculateContainerItemCount(prefItem, ingrAmount); } else { - amount += ingrAmount; + long initAmount = Math.min(ingrAmount, maxAmount - shiftAmount); + + shiftAmount += initAmount; + ingrAmount -= initAmount; } - this.requiredAmount.put(prefItem, amount); - } - - private long calculateContainerItemCount(BookmarkItem item, long amount) { - final int itemId = Item.getIdFromItem(item.itemStack.getItem()); - ItemStack aStack = this.requiredContainerItem.get(item); - long result = 0; - - for (int i = 0; i < amount; i++) { - - if (aStack == null) { - aStack = item.getItemStack(1); - result++; - } - - final Optional containerItem = StackInfo.getContainerItem(aStack); - - if (containerItem != null && containerItem.isPresent()) { - aStack = containerItem.get(); - - if (itemId != Item.getIdFromItem(aStack.getItem())) { - aStack = null; - } - } else { - aStack = null; - } - - } - - this.requiredContainerItem.put(item, aStack); - - return result; - } - - private long prepareAmount(BookmarkItem ingrItem, long ingrAmount) { - if (ingrAmount == 0) return 0; - - for (BookmarkItem item : this.initialItems) { - if (item.containsItems(ingrItem)) { - long amount = this.requiredAmount.getOrDefault(item, 0L); - - if (item.itemStack.getItem().hasContainerItem(item.itemStack) - && ((item.amount - amount) > 0 || this.requiredContainerItem.get(item) != null)) { - ingrAmount = calculateContainerItemCount(item, ingrAmount); - } - - long initAmount = Math.min(ingrAmount, item.amount - amount); - - if (initAmount > 0) { - this.requiredAmount.put(item, this.requiredAmount.getOrDefault(item, 0L) + initAmount); - ingrAmount -= initAmount; - - if ((item.amount - amount - initAmount) < 0) { - this.requiredContainerItem.put(item, null); - } - - if (ingrAmount == 0) break; - } - } - } + this.requiredAmount.put(prefItem, shiftAmount); return ingrAmount; } + private long shiftContainerItems(ItemStack aStack, long steps) { + + for (int i = 0; i < this.containerItems.size() && steps > 0; i++) { + ItemStack bStack = this.containerItems.get(i); + + if (bStack != null && NEIClientUtils.areStacksSameTypeCraftingWithNBT(aStack, bStack)) { + + while (bStack != null && steps > 0) { + final Optional containerItem = StackInfo.getContainerItem(bStack); + + steps--; + + if (containerItem != null && containerItem.isPresent()) { + bStack = containerItem.get(); + + if (aStack.getItem() != bStack.getItem()) { + this.containerItems.add(bStack); + bStack = null; + } + } else { + bStack = null; + } + } + + this.containerItems.set(i, bStack); + } + + } + + this.containerItems.removeIf(stack -> stack == null); + + return steps; + } + + private boolean hasContainerItem(ItemStack aStack) { + + if (aStack.getItem().hasContainerItem(aStack)) { + + for (ItemStack bStack : this.containerItemsBlacklist) { + if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(aStack, bStack)) { + return false; + } + } + + return true; + } + + return false; + } + private void addShift(RecipeId recipeId, long shift) { for (BookmarkItem item : this.recipeIngredients) { if (recipeId.equals(item.recipeId)) { diff --git a/src/main/java/codechicken/nei/recipe/chain/RecipeChainTooltipLineHandler.java b/src/main/java/codechicken/nei/recipe/chain/RecipeChainTooltipLineHandler.java index 377bd8ad..8831f183 100644 --- a/src/main/java/codechicken/nei/recipe/chain/RecipeChainTooltipLineHandler.java +++ b/src/main/java/codechicken/nei/recipe/chain/RecipeChainTooltipLineHandler.java @@ -2,10 +2,15 @@ package codechicken.nei.recipe.chain; import java.awt.Dimension; import java.util.ArrayList; -import java.util.Arrays; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.inventory.SlotCrafting; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; @@ -17,6 +22,7 @@ import codechicken.nei.ItemsTooltipLineHandler; import codechicken.nei.NEIClientConfig; import codechicken.nei.NEIClientUtils; import codechicken.nei.bookmark.BookmarkItem; +import codechicken.nei.recipe.Recipe.RecipeId; import codechicken.nei.recipe.StackInfo; public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { @@ -25,12 +31,14 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { public final boolean crafting; protected final RecipeChainMath math; protected final List initialItems; + protected final Map outputRecipes; protected ItemsTooltipLineHandler available; protected ItemsTooltipLineHandler inputs; protected ItemsTooltipLineHandler outputs; protected ItemsTooltipLineHandler remainder; protected boolean lastShiftKey = false; + protected boolean lastControlKey = false; protected Dimension size = new Dimension(); @@ -39,6 +47,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { this.crafting = crafting; this.math = math; this.initialItems = new ArrayList<>(this.math.initialItems); + this.outputRecipes = new HashMap<>(this.math.outputRecipes); } private void onUpdate() { @@ -47,22 +56,52 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { final List outputs = new ArrayList<>(); final List remainder = new ArrayList<>(); final ItemStackAmount inventory = new ItemStackAmount(); + final GuiContainer currentGui = NEIClientUtils.getGuiContainer(); + final EntityClientPlayerMP thePlayer = currentGui.mc.thePlayer; - if (lastShiftKey) { - inventory.addAll(Arrays.asList(NEIClientUtils.mc().thePlayer.inventory.mainInventory)); + if (this.lastShiftKey) { + for (Slot slot : currentGui.inventorySlots.inventorySlots) { + if (slot.getHasStack() && !(slot instanceof SlotCrafting) && slot.canTakeStack(thePlayer)) { + inventory.add(slot.getStack()); + } + } } if (!this.math.outputRecipes.isEmpty()) { this.math.initialItems.clear(); + this.math.outputRecipes.clear(); + this.math.outputRecipes.putAll(this.outputRecipes); - if (lastShiftKey) { - for (ItemStack stack : inventory.values()) { - final long invStackSize = inventory.get(stack); + if (this.lastShiftKey) { - if (invStackSize > 0) { - this.math.initialItems.add(BookmarkItem.of(-1, stack.copy())); + if (!this.lastControlKey) { + final List items = inventory.values(); + for (BookmarkItem item : math.recipeResults) { + if (item.factor > 0 && this.math.outputRecipes.containsKey(item.recipeId)) { + long amount = 0; + + for (ItemStack stack : items) { + if (stack != null + && NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, item.itemStack)) { + amount += StackInfo.getAmount(stack); + } + } + + if (amount >= item.amount) { + final long itemAmount = item.factor * this.math.outputRecipes.get(item.recipeId); + amount += itemAmount - amount % itemAmount; + this.math.outputRecipes.put( + item.recipeId, + Math.max(this.math.outputRecipes.get(item.recipeId), amount / item.factor)); + } + } } } + + for (ItemStack stack : inventory.values()) { + this.math.initialItems.add(BookmarkItem.of(-1, stack.copy())); + } + } else { this.math.initialItems.addAll(initialItems); } @@ -73,7 +112,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { final long amount = math.requiredAmount.getOrDefault(item, 0L); if (amount > 0) { - if (lastShiftKey) { + if (this.lastShiftKey) { available.add(item.getItemStack(amount)); } else { inputs.add(item.getItemStack(amount)); @@ -95,23 +134,23 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L); if (amount > 0) { - if (math.outputRecipes.containsKey(item.recipeId) && item.groupId != -2) { + if (math.outputRecipes.containsKey(item.recipeId)) { outputs.add(item.getItemStack(amount)); - } else if (lastShiftKey) { + } else if (this.lastShiftKey) { remainder.add(item.getItemStack(amount)); } } } - if (lastShiftKey) { - for (ItemStack stack : math.requiredContainerItem.values()) { + if (this.lastShiftKey) { + for (ItemStack stack : math.containerItems) { if (stack != null) { remainder.add(stack.copy()); } } } - } else if (lastShiftKey) { + } else if (this.lastShiftKey) { for (BookmarkItem item : this.math.initialItems) { if (inventory.contains(item.itemStack)) { @@ -143,7 +182,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { .thenComparing(ItemSorter.instance)); this.inputs = new ItemsTooltipLineHandler( - lastShiftKey ? NEIClientUtils.translate("bookmark.crafting_chain.missing") + this.lastShiftKey ? NEIClientUtils.translate("bookmark.crafting_chain.missing") : NEIClientUtils.translate("bookmark.crafting_chain.input"), inputs, true, @@ -167,7 +206,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { true, Integer.MAX_VALUE); - if (lastShiftKey) { + if (this.lastShiftKey) { this.inputs.setLabelColor(EnumChatFormatting.RED); this.available.setLabelColor(EnumChatFormatting.GREEN); } @@ -197,7 +236,11 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler { @Override public Dimension getSize() { - if (this.lastShiftKey != (this.lastShiftKey = NEIClientUtils.shiftKey()) || this.outputs == null) { + boolean update = this.outputs == null; + update = this.lastShiftKey != (this.lastShiftKey = NEIClientUtils.shiftKey()) || update; + update = this.lastControlKey != (this.lastControlKey = NEIClientUtils.controlKey()) || update; + + if (update) { onUpdate(); } return this.size; diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index 055791fd..71dacc30 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -172,8 +172,7 @@ nei.options.keys.gui.getprevioussearch=Previous Search nei.options.keys.gui.getnextsearch=Next Search nei.options.keys.gui.next_tooltip=Next Tooltip nei.options.keys.gui.copy_name=Copy Item Name -nei.options.keys.gui.craft_missing=Craft Missing Items -nei.options.keys.gui.craft_all=Craft Items +nei.options.keys.gui.craft_items=Craft Items nei.options.keys.gui.copy_oredict=Copy Item OreDictionary nei.options.keys.gui.itemzoom_toggle=Toggle Item Zoom nei.options.keys.gui.itemzoom_hold=Hold to Display Item Zoom