diff --git a/src/main/java/WayofTime/bloodmagic/item/routing/ItemRouterFilter.java b/src/main/java/WayofTime/bloodmagic/item/routing/ItemRouterFilter.java index 70e55aec4a..aa8214e68f 100644 --- a/src/main/java/WayofTime/bloodmagic/item/routing/ItemRouterFilter.java +++ b/src/main/java/WayofTime/bloodmagic/item/routing/ItemRouterFilter.java @@ -58,11 +58,11 @@ public void addInformation(ItemStack stack, World world, List tooltip, I @Override public IItemFilter getInputItemFilter(ItemStack filterStack, TileEntity tile, IItemHandler handler) { - IItemFilter testFilter = new TestItemFilter(); + IItemFilter testFilter = new PreciseItemFilter(); switch (filterStack.getMetadata()) { case 0: - testFilter = new TestItemFilter(); + testFilter = new PreciseItemFilter(); break; case 1: testFilter = new IgnoreNBTItemFilter(); @@ -101,7 +101,7 @@ public IItemFilter getOutputItemFilter(ItemStack filterStack, TileEntity tile, I switch (filterStack.getMetadata()) { case 0: - testFilter = new TestItemFilter(); + testFilter = new PreciseItemFilter(); break; case 1: testFilter = new IgnoreNBTItemFilter(); diff --git a/src/main/java/WayofTime/bloodmagic/routing/DefaultItemFilter.java b/src/main/java/WayofTime/bloodmagic/routing/DefaultItemFilter.java index c33f19c9de..dac23bc92e 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/DefaultItemFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/DefaultItemFilter.java @@ -36,38 +36,6 @@ public void initializeFilter(List filteredList, TileEntity tile, IIte this.itemHandler = itemHandler; } - /** - * This method is only called when the output inventory this filter is - * managing receives an ItemStack. Should only really be called by the Input - * filter via it's transfer method. - * - * @param inputStack - The stack to transfer - * @return - The remainder of the stack after it has been absorbed into the - * inventory. - */ - @Override - public ItemStack transferStackThroughOutputFilter(ItemStack inputStack) { - int allowedAmount = inputStack.getCount(); //This is done to make the migration to a maximum amount transfered a lot easier - - if (allowedAmount <= 0) { - return inputStack; - } - - ItemStack testStack = inputStack.copy(); - testStack.setCount(allowedAmount); - ItemStack remainderStack = Utils.insertStackIntoTile(testStack, itemHandler); - - int changeAmount = allowedAmount - (remainderStack.isEmpty() ? 0 : remainderStack.getCount()); - testStack = inputStack.copy(); - testStack.shrink(changeAmount); - - World world = accessedTile.getWorld(); - BlockPos pos = accessedTile.getPos(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); - - return testStack; - } - /** * This method is only called on an input filter to transfer ItemStacks from * the input inventory to the output inventory. @@ -75,43 +43,43 @@ public ItemStack transferStackThroughOutputFilter(ItemStack inputStack) { @Override public int transferThroughInputFilter(IItemFilter outputFilter, int maxTransfer) { for (int slot = 0; slot < itemHandler.getSlots(); slot++) { - ItemStack inputStack = itemHandler.getStackInSlot(slot); - if (inputStack.isEmpty() || itemHandler.extractItem(slot, inputStack.getCount(), true).isEmpty())//(accessedInventory instanceof ISidedInventory && !((ISidedInventory) accessedInventory).canExtractItem(slot, inputStack, accessedSide))) - { + int taken = outputFilter.offerStack(itemHandler, slot, maxTransfer); + if (taken == 0) { continue; } - int allowedAmount = Math.min(itemHandler.extractItem(slot, inputStack.getCount(), true).getCount(), maxTransfer); - - ItemStack testStack = inputStack.copy(); - testStack.setCount(allowedAmount); - ItemStack remainderStack = outputFilter.transferStackThroughOutputFilter(testStack); - int changeAmount = allowedAmount - (remainderStack.isEmpty() ? 0 : remainderStack.getCount()); - - if (!remainderStack.isEmpty() && remainderStack.getCount() == allowedAmount) { - //Nothing has changed. Moving on! - continue; - } - - itemHandler.extractItem(slot, changeAmount, false); - World world = accessedTile.getWorld(); BlockPos pos = accessedTile.getPos(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); - return changeAmount; + return taken; } - return 0; } @Override - public boolean doesStackMatchFilter(ItemStack testStack) { - return true; + public int offerStack(IItemHandler inv, int slot, int maxTransfer) { + if (inv.getStackInSlot(slot).isEmpty()) { + return 0; + } + + ItemStack extracted = inv.extractItem(slot, maxTransfer, true); + if (extracted.isEmpty()) { + return 0; + } + ItemStack remainderStack = Utils.insertStackIntoTile(extracted, itemHandler); + int taken = extracted.getCount() - remainderStack.getCount(); + inv.extractItem(slot, taken, false); + + World world = accessedTile.getWorld(); + BlockPos pos = accessedTile.getPos(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + + return taken; } @Override - public boolean doStacksMatch(ItemStack filterStack, ItemStack testStack) { - return true; + public boolean canSkip() { + return false; } } diff --git a/src/main/java/WayofTime/bloodmagic/routing/IItemFilter.java b/src/main/java/WayofTime/bloodmagic/routing/IItemFilter.java index 443b0d69c1..001a05349f 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/IItemFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/IItemFilter.java @@ -10,23 +10,30 @@ public interface IItemFilter extends IRoutingFilter { void initializeFilter(List filteredList, TileEntity tile, IItemHandler itemHandler, boolean isFilterOutput); /** - * This method is only called when the output inventory this filter is - * managing receives an ItemStack. Should only really be called by the Input - * filter via it's transfer method. - * - * @param inputStack - The stack to filter - * @return - The remainder of the stack after it has been absorbed into the - * inventory. + * Tries to transfer items from this filter to outputFilter. + * Potentially modifies outputFilter and this filter. + * @param outputFilter the filter to transfer items to + * @param maxTransfer the max amount of items to transfer + * @return the amount of items actually transferred. */ - ItemStack transferStackThroughOutputFilter(ItemStack inputStack); + int transferThroughInputFilter(IItemFilter outputFilter, int maxTransfer); /** - * This method is only called on an input filter to transfer ItemStacks from - * the input inventory to the output inventory. + * Offers an inventory slot to this output filter. The output filter will + * try to extract the stack and return how many items it actually extracted. + * @param inv The inventory that has the offered ItemStack. + * inv may be modified by calling inv.extractItem(slot, ..., false) + * @param slot The slot of inv to check. + * @param maxTransfer The max amount of items that can be taken. + * @return The number of items that were actually extracted and taken. */ - int transferThroughInputFilter(IItemFilter outputFilter, int maxTransfer); - - boolean doesStackMatchFilter(ItemStack testStack); + int offerStack(IItemHandler inv, int slot, int maxTransfer); - boolean doStacksMatch(ItemStack filterStack, ItemStack testStack); + /** + * Returns true if this is an input filter that can accept no more items + * or if this is an output filter that can output no items. + * Filters may return false even if they have no work. + * @return true if this filter can be skipped + */ + boolean canSkip(); } diff --git a/src/main/java/WayofTime/bloodmagic/routing/IgnoreNBTItemFilter.java b/src/main/java/WayofTime/bloodmagic/routing/IgnoreNBTItemFilter.java index b7ef367d7b..2e865242da 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/IgnoreNBTItemFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/IgnoreNBTItemFilter.java @@ -2,7 +2,7 @@ import net.minecraft.item.ItemStack; -public class IgnoreNBTItemFilter extends TestItemFilter { +public class IgnoreNBTItemFilter extends PreciseItemFilter { @Override public boolean doesStackMatchFilter(ItemStack testStack) { for (ItemStack filterStack : requestList) { diff --git a/src/main/java/WayofTime/bloodmagic/routing/ModIdItemFilter.java b/src/main/java/WayofTime/bloodmagic/routing/ModIdItemFilter.java index 36531585a4..4543a4757d 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/ModIdItemFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/ModIdItemFilter.java @@ -2,7 +2,7 @@ import net.minecraft.item.ItemStack; -public class ModIdItemFilter extends TestItemFilter { +public class ModIdItemFilter extends PreciseItemFilter { @Override public boolean doStacksMatch(ItemStack filterStack, ItemStack testStack) { diff --git a/src/main/java/WayofTime/bloodmagic/routing/OreDictItemFilter.java b/src/main/java/WayofTime/bloodmagic/routing/OreDictItemFilter.java index aa209492e1..c4c6f7bc9d 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/OreDictItemFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/OreDictItemFilter.java @@ -3,7 +3,7 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.oredict.OreDictionary; -public class OreDictItemFilter extends TestItemFilter { +public class OreDictItemFilter extends PreciseItemFilter { @Override public boolean doesStackMatchFilter(ItemStack testStack) { for (ItemStack filterStack : requestList) { diff --git a/src/main/java/WayofTime/bloodmagic/routing/TestItemFilter.java b/src/main/java/WayofTime/bloodmagic/routing/PreciseItemFilter.java similarity index 59% rename from src/main/java/WayofTime/bloodmagic/routing/TestItemFilter.java rename to src/main/java/WayofTime/bloodmagic/routing/PreciseItemFilter.java index 2e45865ddc..02fedeb0fd 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/TestItemFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/PreciseItemFilter.java @@ -6,6 +6,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; import java.util.Iterator; import java.util.List; @@ -17,7 +18,7 @@ * * @author WayofTime */ -public class TestItemFilter implements IItemFilter { +public class PreciseItemFilter implements IItemFilter { /* * This list acts as the way the filter keeps track of its contents. For the * case of an output filter, it holds a list of ItemStacks that needs to be @@ -66,8 +67,19 @@ public void initializeFilter(List filteredList, TileEntity tile, IIte } } else { requestList = filteredList; - for (ItemStack filterStack : requestList) { - filterStack.setCount(filterStack.getCount() * -1); //Invert the stack size so that + + int available[] = new int[requestList.size()]; + for (int i = 0; i < requestList.size(); i++) { + ItemStack stack = requestList.get(i); + // Invert the stack size so that after adding the items in the + // inventory, available[...] will contain the amount we can + // remove. + available[i] = -stack.getCount(); + // Stacks with size <= 0 are treated as empty, causing many + // comparisons to treat them like air and disregard the actual + // item they contain. To prevent incorrect comparisons, we make + // sure the stacks we compare with are non-empty + stack.setCount(1); } for (int slot = 0; slot < itemHandler.getSlots(); slot++) { @@ -76,127 +88,106 @@ public void initializeFilter(List filteredList, TileEntity tile, IIte continue; } - int stackSize = checkedStack.getCount(); - - for (ItemStack filterStack : filteredList) { - if (doStacksMatch(filterStack, checkedStack)) { - filterStack.grow(stackSize); + for (int i = 0; i < requestList.size(); i++) { + if (doStacksMatch(requestList.get(i), checkedStack)) { + available[i] += checkedStack.getCount(); } } } - } - requestList.removeIf(ItemStack::isEmpty); - } - - /** - * This method is only called when the output inventory this filter is - * managing receives an ItemStack. Should only really be called by the Input - * filter via it's transfer method. - * - * @param inputStack - The stack to transfer - * @return - The remainder of the stack after it has been absorbed into the - * inventory. - */ - @Override - public ItemStack transferStackThroughOutputFilter(ItemStack inputStack) { - int allowedAmount = 0; - for (ItemStack filterStack : requestList) { - if (doStacksMatch(filterStack, inputStack)) { - allowedAmount = Math.min(filterStack.getCount(), inputStack.getCount()); - break; + for (int i = 0; i < requestList.size(); i++) { + requestList.get(i).setCount(available[i]); } } - if (allowedAmount <= 0) { - return inputStack; - } - - ItemStack testStack = inputStack.copy(); - testStack.setCount(allowedAmount); - ItemStack remainderStack = Utils.insertStackIntoTile(testStack, itemHandler); - - int changeAmount = allowedAmount - (remainderStack.isEmpty() ? 0 : remainderStack.getCount()); - testStack = inputStack.copy(); - testStack.shrink(changeAmount); - - Iterator itr = requestList.iterator(); - while (itr.hasNext()) { - ItemStack filterStack = itr.next(); - if (doStacksMatch(filterStack, inputStack)) { - filterStack.shrink(changeAmount); - if (filterStack.isEmpty()) { - itr.remove(); - } - } - } - - World world = accessedTile.getWorld(); - BlockPos pos = accessedTile.getPos(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); - - return testStack; + requestList.removeIf(ItemStack::isEmpty); } - /** - * This method is only called on an input filter to transfer ItemStacks from - * the input inventory to the output inventory. - */ @Override public int transferThroughInputFilter(IItemFilter outputFilter, int maxTransfer) { for (int slot = 0; slot < itemHandler.getSlots(); slot++) { ItemStack inputStack = itemHandler.getStackInSlot(slot); - if (inputStack.isEmpty() || itemHandler.extractItem(slot, inputStack.getCount(), true).isEmpty())//(accessedInventory instanceof ISidedInventory && !((ISidedInventory) accessedInventory).canExtractItem(slot, inputStack, accessedSide))) - { + if (inputStack.isEmpty()) { continue; } - int allowedAmount = 0; - for (ItemStack filterStack : requestList) { + Iterator itr = requestList.iterator(); + ItemStack match = null; + while (itr.hasNext()) { + ItemStack filterStack = itr.next(); if (doStacksMatch(filterStack, inputStack)) { - allowedAmount = Math.min(maxTransfer, Math.min(filterStack.getCount(), itemHandler.extractItem(slot, inputStack.getCount(), true).getCount())); + match = filterStack; break; } } - if (allowedAmount <= 0) { + if (match == null) { continue; } - ItemStack testStack = inputStack.copy(); - testStack.setCount(allowedAmount); - ItemStack remainderStack = outputFilter.transferStackThroughOutputFilter(testStack); - int changeAmount = allowedAmount - (remainderStack.isEmpty() ? 0 : remainderStack.getCount()); - - if (!remainderStack.isEmpty() && remainderStack.getCount() == allowedAmount) { - //Nothing has changed. Moving on! + int allowedAmount = Math.min(maxTransfer, match.getCount()); + int taken = outputFilter.offerStack(itemHandler, slot, allowedAmount); + if (taken == 0) { continue; } - itemHandler.extractItem(slot, changeAmount, false); - - Iterator itr = requestList.iterator(); - while (itr.hasNext()) { - ItemStack filterStack = itr.next(); - if (doStacksMatch(filterStack, inputStack)) { - filterStack.shrink(changeAmount); - if (filterStack.isEmpty()) { - itr.remove(); - } - } + match.shrink(taken); + if (match.isEmpty()) { + itr.remove(); } World world = accessedTile.getWorld(); BlockPos pos = accessedTile.getPos(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); - return changeAmount; + return taken; } - return 0; } @Override + public int offerStack(IItemHandler inv, int slot, int maxTransfer) { + ItemStack invStack = inv.getStackInSlot(slot); + ItemStack match = null; + Iterator itr = requestList.iterator(); + while (itr.hasNext()) { + ItemStack filterStack = itr.next(); + if (doStacksMatch(filterStack, invStack)) { + match = filterStack; + break; + } + } + + if (match == null) { + return 0; + } + + int allowed = Math.min(maxTransfer, match.getCount()); + ItemStack extracted = inv.extractItem(slot, allowed, true); + ItemStack remainderStack = Utils.insertStackIntoTile(extracted, itemHandler); + int taken = extracted.getCount() - remainderStack.getCount(); + inv.extractItem(slot, taken, false); + + match.shrink(taken); + if (match.isEmpty()) { + itr.remove(); + } + + World world = accessedTile.getWorld(); + BlockPos pos = accessedTile.getPos(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + + return taken; + } + + @Override + public boolean canSkip() { + return requestList.isEmpty(); + } + + /** + * @return True iff testStack matches this filter's conditions. + */ public boolean doesStackMatchFilter(ItemStack testStack) { for (ItemStack filterStack : requestList) { if (doStacksMatch(filterStack, testStack)) { @@ -207,8 +198,13 @@ public boolean doesStackMatchFilter(ItemStack testStack) { return false; } - @Override + /** + * @param filterStack + * @param testStack + * @return True iff filterStack and testStack are equivalent using + * this filter's conditions. + */ public boolean doStacksMatch(ItemStack filterStack, ItemStack testStack) { - return Utils.canCombine(filterStack, testStack); + return ItemHandlerHelper.canItemStacksStack(filterStack, testStack); } } diff --git a/src/main/java/WayofTime/bloodmagic/routing/RoutingFluidFilter.java b/src/main/java/WayofTime/bloodmagic/routing/RoutingFluidFilter.java index 9f4b47a744..b57bad4aa3 100644 --- a/src/main/java/WayofTime/bloodmagic/routing/RoutingFluidFilter.java +++ b/src/main/java/WayofTime/bloodmagic/routing/RoutingFluidFilter.java @@ -89,7 +89,8 @@ public FluidStack transferStackThroughOutputFilter(FluidStack fluidStack) { } FluidStack copyStack = fluidStack.copy(); - int filledAmount = fluidHandler.fill(fluidStack, true); + copyStack.amount = allowedAmount; + int filledAmount = fluidHandler.fill(copyStack, true); copyStack.amount = fluidStack.amount - filledAmount; Iterator itr = requestList.iterator(); @@ -130,7 +131,6 @@ public int transferThroughInputFilter(IFluidFilter outputFilter, int maxTransfer drainStack.amount = drained; fluidHandler.drain(drainStack, true); - maxTransfer -= drained; } Iterator itr = requestList.iterator(); @@ -148,7 +148,7 @@ public int transferThroughInputFilter(IFluidFilter outputFilter, int maxTransfer BlockPos pos = accessedTile.getPos(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); - return maxTransfer; + return drained; } } diff --git a/src/main/java/WayofTime/bloodmagic/tile/routing/TileMasterRoutingNode.java b/src/main/java/WayofTime/bloodmagic/tile/routing/TileMasterRoutingNode.java index afbb3410c1..42c97df893 100644 --- a/src/main/java/WayofTime/bloodmagic/tile/routing/TileMasterRoutingNode.java +++ b/src/main/java/WayofTime/bloodmagic/tile/routing/TileMasterRoutingNode.java @@ -32,10 +32,7 @@ public TileMasterRoutingNode() { @Override public void update() { if (!getWorld().isRemote) { -// currentInput = getWorld().isBlockIndirectlyGettingPowered(pos); currentInput = getWorld().getStrongPower(pos); - -// System.out.println(currentInput); } if (getWorld().isRemote || getWorld().getTotalWorldTime() % tickRate != 0) //Temporary tick rate solver @@ -58,7 +55,7 @@ public void update() { } IItemFilter filter = outputNode.getOutputFilterForSide(facing); - if (filter != null) { + if (filter != null && !filter.canSkip()) { int priority = outputNode.getPriority(facing); if (outputMap.containsKey(priority)) { outputMap.get(priority).add(filter); @@ -110,7 +107,7 @@ public void update() { } IItemFilter filter = inputNode.getInputFilterForSide(facing); - if (filter != null) { + if (filter != null && !filter.canSkip()) { int priority = inputNode.getPriority(facing); if (inputMap.containsKey(priority)) { inputMap.get(priority).add(filter);