mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-11 16:07:38 +00:00
Autocrafting Improvement (#655)
This commit is contained in:
1 parent
e23e542aac
commit
77fa3bafd6
10 files changed
+332
-189
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ public class BookmarkItem {
|
||||
|
||||
for (Map.Entry<ItemStack, String> entry : BookmarkItem.fuzzyPermutations.entrySet()) {
|
||||
if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, entry.getKey())) {
|
||||
BookmarkItem.fuzzyPermutations.put(stack, entry.getValue());
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<IngredientDistribution> 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<IngredientDistribution> 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<DistributedIngred> 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<ItemStack> containerItem = StackInfo.getContainerItem(pstack);
|
||||
if (containerItem != null && containerItem.isPresent()) {
|
||||
istack.isContainerItem = pstack.getItem() == containerItem.get().getItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
|
||||
public class RecipeHandlerRef {
|
||||
|
||||
private static final LRUCache<Class<?>, Boolean> transferAlghoritmCache = new LRUCache<>(200);
|
||||
private static final LRUCache<RecipeId, RecipeHandlerRef> 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) {
|
||||
|
||||
@@ -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<BookmarkItem, BookmarkItem> preferredItems = new HashMap<>();
|
||||
public final Map<BookmarkItem, Long> requiredAmount = new HashMap<>();
|
||||
public final Map<BookmarkItem, ItemStack> requiredContainerItem = new HashMap<>();
|
||||
public final List<ItemStack> containerItems = new ArrayList<>();
|
||||
private final List<ItemStack> containerItemsBlacklist = new ArrayList<>();
|
||||
|
||||
private RecipeChainMath(List<BookmarkItem> recipeItems, Set<RecipeId> collapsedRecipes) {
|
||||
final Map<RecipeId, Integer> 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<ItemStack> 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<BookmarkItem> 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<RecipeId> 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<RecipeId> 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<ItemStack> 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<ItemStack> 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)) {
|
||||
|
||||
@@ -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<BookmarkItem> initialItems;
|
||||
protected final Map<RecipeId, Long> 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<ItemStack> outputs = new ArrayList<>();
|
||||
final List<ItemStack> 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<ItemStack> 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;
|
||||
|
||||
Reference in new issue
Block a user