From 6869f2cb308e1e814f951f4fecaa9b28bc032d6b Mon Sep 17 00:00:00 2001 From: Alex Ponebshek Date: Mon, 28 Mar 2016 20:53:09 -0500 Subject: [PATCH 1/5] Auto workbench will track how many unique ingredients are not present and will keep input slots reserved for them --- .../core/block/TileEntityAutoCrafting.java | 74 +++++++++++++++++-- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java index 9c107f1..fa5e151 100644 --- a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java +++ b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java @@ -12,6 +12,7 @@ import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ISidedInventory; 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; @@ -22,8 +23,7 @@ import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayerFactory; -import java.util.List; -import java.util.Locale; +import java.util.*; public class TileEntityAutoCrafting extends TileEntity implements ISidedInventory, IGuiTile { @@ -75,6 +75,9 @@ public static enum Mode { private int lastUpdate = 0; private ItemStack[] inventory = new ItemStack[26]; + private boolean inputRestricted = false; + List inputsNeeded = new ArrayList(9); + public final int[] SLOTS = InventoryUtils.createSlotArray(10, inventory.length); private boolean poweredNow = false; @@ -138,9 +141,16 @@ private boolean isReplaceableInCraftingGridSlot(int slot, ItemStack stack) { return result; } - private boolean tryCrafting() { + /** + * Combines the test for whether we can craft (pulled out of tryCrafting) with code to prepare the data for input + * restriction checking, ie, do we need to restrict any inputs to ensure we maintain room for all ingredients? + * + * @return refs if we will be ready to craft something *now*, otherwise null + */ + private StackReference[] verifyCraftability() { if (currentRecipe == null || getStackInSlot(9) == null) { - return false; + inputRestricted = false; // no input restrictions if there's no recipe to defend! + return null; } boolean[] found = new boolean[9]; @@ -168,12 +178,48 @@ private boolean tryCrafting() { } } - for (boolean b : found) { - if (!b) { - return false; + inputsNeeded.clear(); + List inputsCounted = new ArrayList(9); + + for (int gridSlot = 0; gridSlot < 9; gridSlot++) { + if (! found[gridSlot]) { + ItemStack test = ItemStack.copyItemStack(getStackInSlot(gridSlot)); + test.stackSize = 1; + + alreadyReserved: { // make sure it's a *unique* missing ingredient + for (ItemStack x : inputsCounted) { + if (ItemStack.areItemStacksEqual(x, test)) + break alreadyReserved; + } + + inputsNeeded.add(gridSlot); + inputsCounted.add(test); + } } } + if (inputsNeeded.size() == 0) { + inputRestricted = false; // no restrictions if we already have all needed inputs + return refs; + } else { + // we can't craft, so we'll go ahead and check what's needed and how many empty slots we have for inputs + int inputSlotsEmpty = 0; + + for (int invSlot = 10; invSlot < 18; invSlot++) { + ItemStack stack = ItemStack.copyItemStack(getStackInSlot(invSlot)); + if (stack == null || stack.stackSize <= 0) + inputSlotsEmpty ++; + } + + inputRestricted = (inputSlotsEmpty <= inputsNeeded.size()); + return null; + } + } + + private boolean tryCrafting() { + StackReference[] refs = verifyCraftability(); + if (refs == null) return false; + // replace all ingredients with found stacks for (int i = 0; i < 9; i++) { if (craftingGrid.getStackInSlot(i) != null) { @@ -214,6 +260,7 @@ private boolean tryCrafting() { // restore original items from ghost slots InventoryUtils.setContents(craftingGrid, this); + verifyCraftability(); // crafting will have changed contents, so re-run verify to ensure correct input blocking return craftingCompleted; } @@ -257,6 +304,7 @@ public void updateEntity() { lastUpdate = 0; if (lastCraftingSuccess || inventoryChanged) { + if (inventoryChanged) verifyCraftability(); inventoryChanged = false; if (mode == Mode.ALWAYS || (mode == Mode.POWERED && poweredNow) || (mode == Mode.UNPOWERED && !poweredNow)) { @@ -346,7 +394,17 @@ public int[] getAccessibleSlotsFromSide(int side) { @Override public boolean canInsertItem(int slotIndex, ItemStack stack, int side) { - return slotIndex >= 10 && slotIndex < 18; + if (inventoryChanged) verifyCraftability(); + + if (slotIndex < 10 || slotIndex >= 18) return false; // not valid insert slot + if (! inputRestricted) return true; // plenty of space + if (getStackInSlot(slotIndex) != null) return true; // slot not empty, allow normal item stacking behavior + + for (int testSlot : inputsNeeded) + if (isReplaceableInCraftingGridSlot(testSlot, stack)) + return true; + + return false; } @Override From 24ce4be99135fcd5eca539599b26d6b09757656e Mon Sep 17 00:00:00 2001 From: Alex Ponebshek Date: Thu, 31 Mar 2016 11:18:54 -0500 Subject: [PATCH 2/5] make gradlew executable --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 5000659bdb9e7c919b5868e934a118dd9ba49a64 Mon Sep 17 00:00:00 2001 From: Alex Ponebshek Date: Thu, 31 Mar 2016 14:13:12 -0500 Subject: [PATCH 3/5] Don't reserve a slot for ingredients that already have a slot, even if there aren't enough --- .../core/block/TileEntityAutoCrafting.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java index fa5e151..cb276fd 100644 --- a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java +++ b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java @@ -182,17 +182,20 @@ private StackReference[] verifyCraftability() { List inputsCounted = new ArrayList(9); for (int gridSlot = 0; gridSlot < 9; gridSlot++) { - if (! found[gridSlot]) { - ItemStack test = ItemStack.copyItemStack(getStackInSlot(gridSlot)); + ItemStack test = ItemStack.copyItemStack(getStackInSlot(gridSlot)); + if (test != null) { test.stackSize = 1; - alreadyReserved: { // make sure it's a *unique* missing ingredient + alreadyReserved: { // make sure it's a *unique* ingredient for (ItemStack x : inputsCounted) { if (ItemStack.areItemStacksEqual(x, test)) break alreadyReserved; } - inputsNeeded.add(gridSlot); + if (! found[gridSlot]) { + inputsNeeded.add(gridSlot); + } + inputsCounted.add(test); } } From 8c9c216b2e9547fddd66ff6fe9136f23a2e6fa11 Mon Sep 17 00:00:00 2001 From: Alex Ponebshek Date: Thu, 31 Mar 2016 17:56:17 -0500 Subject: [PATCH 4/5] Respect leaveContainerItem and keep reusable crafting items in the input slots if they would stay in a normal crafting grid --- .../core/block/TileEntityAutoCrafting.java | 36 +++++++++++++------ .../core/util/InventoryUtils.java | 2 -- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java index cb276fd..3f507a7 100644 --- a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java +++ b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java @@ -241,18 +241,32 @@ private boolean tryCrafting() { FMLCommonHandler.instance().firePlayerCraftingEvent(fakePlayer, result, craftingGrid); result.onCrafting(worldObj, fakePlayer, result.stackSize); - for (StackReference ref : refs) { - if (ref != null) { - ItemStack stack = ref.decreaseStackSize(1); - if (stack != null && stack.getItem() != null && stack.getItem().hasContainerItem(stack)) { - ItemStack container = stack.getItem().getContainerItem(stack); - if (container.isItemStackDamageable() && container.getItemDamage() > container.getMaxDamage()) { + for (int i=0; i<9; i++) { + StackReference ref = refs[i]; if (ref == null) continue; + ItemStack stack = ref.decreaseStackSize(1); if (stack == null) continue; + Item stackItem = stack.getItem(); if (stackItem == null) continue; + ItemStack container = stackItem.getContainerItem(stack); if (container == null) continue; + if (container.isItemStackDamageable() && container.getItemDamage() > container.getMaxDamage()) + continue; + + // attempt to let the ingredient remain in its slot? + if (! stackItem.doesContainerItemLeaveCraftingGrid(stack)) { + ItemStack actualStack = getStackInSlot(ref.slot); + + if (actualStack == null || actualStack.stackSize == 0) { // slot is now empty, so just put container stack there + setInventorySlotContents(ref.slot, container); + container = null; + } else { + // if we can't put it back in the same slot, try to shove it somewhere in inputs + if (container != null && InventoryUtils.addItemToInventory(this, container.copy(), 10, 18)) container = null; - } - if (container != null && !InventoryUtils.addItemToInventory(this, container, 18, 26)) { - InventoryUtils.dropItem(worldObj, xCoord + 0.5, yCoord + 1, zCoord + 0.5, container); - // XXX: try other inventories - } + } + } + + if (container != null) { + if (!InventoryUtils.addItemToInventory(this, container.copy(), 18, 26)) { + InventoryUtils.dropItem(worldObj, xCoord + 0.5, yCoord + 1, zCoord + 0.5, container); + // XXX: try other inventories? } } } diff --git a/src/main/java/net/lepko/easycrafting/core/util/InventoryUtils.java b/src/main/java/net/lepko/easycrafting/core/util/InventoryUtils.java index 43a63b2..c23f017 100644 --- a/src/main/java/net/lepko/easycrafting/core/util/InventoryUtils.java +++ b/src/main/java/net/lepko/easycrafting/core/util/InventoryUtils.java @@ -260,8 +260,6 @@ public static ItemStack decreaseStackSize(IInventory inv, int slotIndex, int amo ItemStack is = stack.splitStack(amount); if (stack.stackSize == 0) { inv.setInventorySlotContents(slotIndex, null); - } else { - inv.markDirty(); } inv.markDirty(); return is; From 423a3ab03b8b88c4f404e00a527e94a15a17b66f Mon Sep 17 00:00:00 2001 From: Alex Ponebshek Date: Thu, 31 Mar 2016 19:48:13 -0500 Subject: [PATCH 5/5] Fixed oopsie introduced by 5000659bdb9e7c919b5868e934a118dd9ba49a64 which caused crashes when an auto workbench had some but not enough of an ingredient --- .../easycrafting/core/block/TileEntityAutoCrafting.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java index 3f507a7..1010993 100644 --- a/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java +++ b/src/main/java/net/lepko/easycrafting/core/block/TileEntityAutoCrafting.java @@ -180,12 +180,15 @@ private StackReference[] verifyCraftability() { inputsNeeded.clear(); List inputsCounted = new ArrayList(9); + boolean canCraft = true; for (int gridSlot = 0; gridSlot < 9; gridSlot++) { ItemStack test = ItemStack.copyItemStack(getStackInSlot(gridSlot)); if (test != null) { test.stackSize = 1; + canCraft = canCraft && found[gridSlot]; + alreadyReserved: { // make sure it's a *unique* ingredient for (ItemStack x : inputsCounted) { if (ItemStack.areItemStacksEqual(x, test)) @@ -201,7 +204,7 @@ private StackReference[] verifyCraftability() { } } - if (inputsNeeded.size() == 0) { + if (canCraft) { inputRestricted = false; // no restrictions if we already have all needed inputs return refs; } else {