diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java index 1c02526a..9e6f6088 100644 --- a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java +++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java @@ -1,5 +1,7 @@ package gregtech.common.tileentities.machines.basic; +import cpw.mods.fml.common.registry.GameRegistry; + import gregtech.api.enums.Textures; import gregtech.api.gui.GT_Container_BasicTank; import gregtech.api.gui.GT_GUIContainer_BasicTank; @@ -9,6 +11,7 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.metatileentity.BaseTileEntity; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch; import gregtech.api.objects.GT_RenderedTexture; +import gregtech.api.util.GT_Log; import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_Utility; import net.minecraft.block.Block; @@ -21,25 +24,43 @@ import net.minecraft.world.ChunkPosition; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidBlock; +import net.minecraftforge.fluids.IFluidHandler; -import java.util.ArrayList; +import java.util.ArrayDeque; import java.util.Iterator; +import java.util.HashSet; +import java.util.Set; +import static gregtech.api.enums.GT_Values.D1; import static gregtech.api.enums.GT_Values.V; +import static gregtech.api.util.GT_Utility.getFakePlayer; public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_Hatch { - private static final ItemStack MINING_PIPE = GT_ModHandler.getIC2Item("miningPipe", 0); + private static final ItemStack MINING_PIPE = GT_ModHandler.getIC2Item("miningPipe", 0); private static final Block MINING_PIPE_BLOCK = GT_Utility.getBlockFromStack(MINING_PIPE); private static final Block MINING_PIPE_TIP_BLOCK = GT_Utility.getBlockFromStack(GT_ModHandler.getIC2Item("miningPipeTip", 0)); - public ArrayList mPumpList = new ArrayList(); + public static int getMaxDistanceForTier(byte aTier) { + return (10 * ((int) Math.pow(1.6D, aTier))); + } + + public static long getEuUsagePerTier(byte aTier) { + return (16 * ((long) Math.pow(4, aTier))); + } + + public ArrayDeque mPumpList = new ArrayDeque(); + public boolean wasPumping = false; public int mPumpTimer = 0; public int mPumpCountBelow = 0; - public Block mPumpedBlock1 = null; - public Block mPumpedBlock2 = null; + public Block mPrimaryPumpedBlock = null; + public Block mSecondaryPumpedBlock = null; public GT_MetaTileEntity_Pump(int aID, String aName, String aNameRegional, int aTier) { - super(aID, aName, aNameRegional, aTier, 3, new String[]{"The best way to empty Oceans!", "Pumping Area: " + ((10 * ((int) Math.pow(1.6, aTier))) * 2 + 1) + "x" + ((10 * ((int) Math.pow(1.6, aTier))) * 2 + 1)}); + + super(aID, aName, aNameRegional, aTier, 3, + new String[]{"The best way to empty Oceans!", + "Pumping Area: " + (GT_MetaTileEntity_Pump.getMaxDistanceForTier((byte)aTier) * 2 + 1) + "x" + + (GT_MetaTileEntity_Pump.getMaxDistanceForTier((byte)aTier) * 2 + 1)}); } public GT_MetaTileEntity_Pump(String aName, int aTier, String aDescription, ITexture[][][] aTextures) { @@ -56,15 +77,26 @@ public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_Hatch { } public void saveNBTData(NBTTagCompound aNBT) { + boolean wasPumping = this.wasPumping || !this.mPumpList.isEmpty(); + if (D1) { + GT_Log.out.println("PUMP: NBT:Save - WasPumping - " + wasPumping + " blocks (" + this.mPrimaryPumpedBlock + ", " + this.mSecondaryPumpedBlock + ")"); + } super.saveNBTData(aNBT); - aNBT.setString("mPumpedBlock1", this.mPumpedBlock1 == null ? "" : this.mPumpedBlock1.getUnlocalizedName()); - aNBT.setString("mPumpedBlock2", this.mPumpedBlock2 == null ? "" : this.mPumpedBlock2.getUnlocalizedName()); + aNBT.setString("mPumpedBlock1", this.mPrimaryPumpedBlock == null ? "" : Block.blockRegistry.getNameForObject(this.mPrimaryPumpedBlock)); + aNBT.setString("mPumpedBlock2", this.mSecondaryPumpedBlock == null ? "" : Block.blockRegistry.getNameForObject(this.mSecondaryPumpedBlock)); + aNBT.setBoolean("wasPumping", wasPumping); } public void loadNBTData(NBTTagCompound aNBT) { super.loadNBTData(aNBT); - this.mPumpedBlock1 = Block.getBlockFromName(aNBT.getString("mPumpedBlock1")); - this.mPumpedBlock2 = Block.getBlockFromName(aNBT.getString("mPumpedBlock2")); + this.wasPumping = aNBT.getBoolean("wasPumping"); + this.mPrimaryPumpedBlock = Block.getBlockFromName(aNBT.getString("mPumpedBlock1")); + this.mSecondaryPumpedBlock = Block.getBlockFromName(aNBT.getString("mPumpedBlock2")); + + if (D1) { + GT_Log.out.println("PUMP: NBT:Load - WasPumping - " + this.wasPumping + "(" + aNBT.getString("mPumpedBlock1") + ") " + this.mPrimaryPumpedBlock); + } + } @Override @@ -122,51 +154,97 @@ public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_Hatch { } this.doTickProfilingInThisTick = true; this.mPumpCountBelow = 0; + IGregTechTileEntity tTileEntity; - for (int i = 1; (i < 21) && ((tTileEntity = getBaseMetaTileEntity().getIGregTechTileEntityAtSideAndDistance((byte) 0, i)) != null) - && ((tTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_Pump)); i++) { + for (int i = 1 ; + (i < 21) && ((tTileEntity = getBaseMetaTileEntity().getIGregTechTileEntityAtSideAndDistance((byte) 0, i)) != null) + && ((tTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_Pump)) ; i++) + { + // Apparently someone might stack 21 pumps on top of each other, so let's check for that getBaseMetaTileEntity().setActive(tTileEntity.isActive()); this.mPumpCountBelow += 1; + // The more pumps we have stacked, the faster the ones below go ((GT_MetaTileEntity_Pump) tTileEntity.getMetaTileEntity()).mPumpTimer -= 1; } if (this.mPumpCountBelow <= 0) { - if ((getBaseMetaTileEntity().isAllowedToWork()) && (getBaseMetaTileEntity().isUniversalEnergyStored(16 * ((int) Math.pow(4, this.mTier)))) + // Only the bottom most pump does anything + if ((getBaseMetaTileEntity().isAllowedToWork()) && (getBaseMetaTileEntity().isUniversalEnergyStored(this.getEuUsagePerAction())) && ((this.mFluid == null) || (this.mFluid.amount + 1000 <= getCapacity()))) { boolean tMovedOneDown = false; if ((this.mPumpList.isEmpty()) && (getBaseMetaTileEntity().getTimer() % 100L == 0L)) { - tMovedOneDown = moveOneDown(); - } - if ((GT_Utility.isBlockInvalid(this.mPumpedBlock1)) || (GT_Utility.isBlockInvalid(this.mPumpedBlock2))) { - getFluidAt(getBaseMetaTileEntity().getXCoord(), getYOfPumpHead() - 1, getBaseMetaTileEntity().getZCoord()); - if ((GT_Utility.isBlockInvalid(this.mPumpedBlock1)) || (GT_Utility.isBlockInvalid(this.mPumpedBlock2))) { - getFluidAt(getBaseMetaTileEntity().getXCoord(), getYOfPumpHead(), getBaseMetaTileEntity().getZCoord() + 1); - } - if ((GT_Utility.isBlockInvalid(this.mPumpedBlock1)) || (GT_Utility.isBlockInvalid(this.mPumpedBlock2))) { - getFluidAt(getBaseMetaTileEntity().getXCoord(), getYOfPumpHead(), getBaseMetaTileEntity().getZCoord() - 1); - } - if ((GT_Utility.isBlockInvalid(this.mPumpedBlock1)) || (GT_Utility.isBlockInvalid(this.mPumpedBlock2))) { - getFluidAt(getBaseMetaTileEntity().getXCoord() + 1, getYOfPumpHead(), getBaseMetaTileEntity().getZCoord()); - } - if ((GT_Utility.isBlockInvalid(this.mPumpedBlock1)) || (GT_Utility.isBlockInvalid(this.mPumpedBlock2))) { - getFluidAt(getBaseMetaTileEntity().getXCoord() - 1, getYOfPumpHead(), getBaseMetaTileEntity().getZCoord()); - } - } else if (getYOfPumpHead() < getBaseMetaTileEntity().getYCoord()) { - if ((tMovedOneDown) || ((this.mPumpList.isEmpty()) && (getBaseMetaTileEntity().getTimer() % 200L == 100L)) || (getBaseMetaTileEntity().getTimer() % 72000L == 100L)) { - this.mPumpList.clear(); - int y = getBaseMetaTileEntity().getYCoord() - 1; - for (int yHead = getYOfPumpHead(); (this.mPumpList.isEmpty()) && (y >= yHead); y--) { - scanForFluid(getBaseMetaTileEntity().getXCoord(), y, getBaseMetaTileEntity().getZCoord(), this.mPumpList, getBaseMetaTileEntity().getXCoord(), getBaseMetaTileEntity().getZCoord(), 10 * ((int) Math.pow(1.6, this.mTier))); + if (!this.wasPumping){ + tMovedOneDown = moveOneDown(); + if (D1) { + GT_Log.out.println("PUMP: Moved down"); } + } else if (D1) { + GT_Log.out.println("PUMP: Was pumping, didn't move down"); + } + } + int x = getBaseMetaTileEntity().getXCoord(), z = getBaseMetaTileEntity().getZCoord(); + + if (!this.hasValidFluid()) { + // We don't have a valid block, let's try to find one + int y = getYOfPumpHead(); + + if (D1 && this.mPrimaryPumpedBlock != null) { + GT_Log.out.println("PUMP: Had an invalid pump block. Trying to find a fluid at Y: " + y + + " Previous blocks 1: " + this.mPrimaryPumpedBlock + " 2: " + this.mSecondaryPumpedBlock); + } + // First look down + checkForFluidToPump(x, y - 1, z ); + + // Then look all around + checkForFluidToPump(x, y, z + 1); + checkForFluidToPump(x, y, z - 1); + checkForFluidToPump(x + 1, y, z ); + checkForFluidToPump(x - 1, y, z ); + this.clearQueue(false); + + if(this.hasValidFluid()) { + // Don't move down and rebuild the queue if we now have a valid fluid + this.wasPumping = true; + } + + } else if (getYOfPumpHead() < getBaseMetaTileEntity().getYCoord()) { + // We didn't just look for a block, and the pump head is below the pump + if ((tMovedOneDown) || this.wasPumping || + ((this.mPumpList.isEmpty()) && (getBaseMetaTileEntity().getTimer() % 200L == 100L)) || + (getBaseMetaTileEntity().getTimer() % 72000L == 100L)) + { + // Rebuild the list to pump if any of the following conditions are true: + // 1) We just moved down + // 2) We were previously pumping (and possibly just reloaded) + // 3) We have an empty queue and enough time has passed + // 4) A long while has has passed + if (D1) { + GT_Log.out.println("PUMP: Rebuilding pump list - Size " + + this.mPumpList.size() + " WasPumping: " + this.wasPumping + " Timer " + getBaseMetaTileEntity().getTimer()); + } + int yPump = getBaseMetaTileEntity().getYCoord() - 1, yHead = getYOfPumpHead(); + + this.rebuildPumpQueue(x, yPump, z, yHead); + + if (D1) { + GT_Log.out.println("PUMP: Rebuilt pump list - Size " + this.mPumpList.size()); + } + } if ((!tMovedOneDown) && (this.mPumpTimer <= 0)) { - while ((!this.mPumpList.isEmpty()) - && (!consumeFluid(((ChunkPosition) this.mPumpList.get(this.mPumpList.size() - 1)).chunkPosX, - ((ChunkPosition) this.mPumpList.get(this.mPumpList.size() - 1)).chunkPosY, - ((ChunkPosition) this.mPumpList.remove(this.mPumpList.size() - 1)).chunkPosZ))) { - //Should this be empty? + while ((!this.mPumpList.isEmpty())) { + ChunkPosition pos = this.mPumpList.pollLast(); + if (consumeFluid(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ)) { + // Keep trying until we consume something, or the list is empty + break; + } } - this.mPumpTimer = 160 / ((int) Math.pow(2, this.mTier)); + this.mPumpTimer = GT_Utility.safeInt(160 / (long)Math.pow(2, this.mTier) ); + this.mPumpTimer = mPumpTimer==0 ? 1 : mPumpTimer; } + } else { + // We somehow have a valid fluid, but the head of the pump isn't below the pump. Perhaps someone broke some pipes + // -- Clear the queue and we should try to move down until we can find a valid fluid + this.clearQueue(false); } } getBaseMetaTileEntity().setActive(!this.mPumpList.isEmpty()); @@ -174,160 +252,216 @@ public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_Hatch { } } + private int getMaxPumpableDistance() { + return GT_MetaTileEntity_Pump.getMaxDistanceForTier(this.mTier); + } + + private long getEuUsagePerAction() { + return GT_MetaTileEntity_Pump.getEuUsagePerTier(this.mTier); + } + + private boolean hasValidFluid() { + return (!GT_Utility.isBlockInvalid(this.mPrimaryPumpedBlock) && !GT_Utility.isBlockInvalid(this.mSecondaryPumpedBlock)); + } + private boolean moveOneDown() { - if ((this.mInventory[0] == null) || (this.mInventory[0].stackSize < 1) - || (!GT_Utility.areStacksEqual(this.mInventory[0], MINING_PIPE))) { + if ((this.mInventory[0] == null) || (this.mInventory[0].stackSize < 1) || (!GT_Utility.areStacksEqual(this.mInventory[0], MINING_PIPE))) { + // No mining pipes return false; } + int yHead = getYOfPumpHead(); - if (yHead <= 0) { + if (yHead <= 1) { + // Let's not punch through bedrock return false; } - if ((!consumeFluid(getBaseMetaTileEntity().getXCoord(), yHead - 1, getBaseMetaTileEntity().getZCoord())) && (!getBaseMetaTileEntity().getBlock(getBaseMetaTileEntity().getXCoord(), yHead - 1, getBaseMetaTileEntity().getZCoord()).isAir(getBaseMetaTileEntity().getWorld(), getBaseMetaTileEntity().getXCoord(), yHead - 1, getBaseMetaTileEntity().getZCoord()))) { + + int x = getBaseMetaTileEntity().getXCoord(), z = getBaseMetaTileEntity().getZCoord(); + + if ((!consumeFluid(x, yHead - 1, z)) && (!getBaseMetaTileEntity().getBlock(x, yHead - 1, z).isAir(getBaseMetaTileEntity().getWorld(), x, yHead - 1, z))) { + // Either we didn't consume a fluid, or it's a non Air block return false; } - if (!GT_Utility.setBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), getBaseMetaTileEntity().getXCoord(), yHead - 1, getBaseMetaTileEntity().getZCoord(), MINING_PIPE_TIP_BLOCK, 0, false)) { + + // Try to set the block below us to a a tip + if (!GT_Utility.setBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), x, yHead - 1, z, MINING_PIPE_TIP_BLOCK, 0, false)) { return false; } + // And change the previous block to a pipe -- as long as it isn't the pump itself! if (yHead != getBaseMetaTileEntity().getYCoord()) { - getBaseMetaTileEntity().getWorld().setBlock(getBaseMetaTileEntity().getXCoord(), yHead, getBaseMetaTileEntity().getZCoord(), MINING_PIPE_BLOCK); + getBaseMetaTileEntity().getWorld().setBlock(x, yHead, z, MINING_PIPE_BLOCK); } getBaseMetaTileEntity().decrStackSize(0, 1); return true; } private int getYOfPumpHead() { - int y = getBaseMetaTileEntity().getYCoord() - 1; - while (getBaseMetaTileEntity().getBlock(getBaseMetaTileEntity().getXCoord(), y, getBaseMetaTileEntity().getZCoord()) == MINING_PIPE_BLOCK) { - y--; - } - if (y == getBaseMetaTileEntity().getYCoord() - 1) { - if (getBaseMetaTileEntity().getBlock(getBaseMetaTileEntity().getXCoord(), y, getBaseMetaTileEntity().getZCoord()) != MINING_PIPE_TIP_BLOCK) { - return y + 1; + // Let's play find the pump head! + + // TODO: Handle pipe|pipe|head|pipe|pipe + int y = getBaseMetaTileEntity().getYCoord() - 1, x = getBaseMetaTileEntity().getXCoord(), z = getBaseMetaTileEntity().getZCoord(); + + while(y > 0) { + Block curBlock = getBaseMetaTileEntity().getBlock(x, y, z); + if(curBlock == MINING_PIPE_BLOCK) { + y--; + } else if (curBlock == MINING_PIPE_TIP_BLOCK) { + Block nextBlock = getBaseMetaTileEntity().getBlock(x, y - 1 , z); + if (nextBlock == MINING_PIPE_BLOCK || nextBlock == MINING_PIPE_TIP_BLOCK) { + // We're running into an existing set of pipes -- Turn this block into a pipe and keep going + this.clearQueue(true); + getBaseMetaTileEntity().getWorld().setBlock(x, y, z, MINING_PIPE_BLOCK); + } + y--; + + } else { + break; } - } else if (getBaseMetaTileEntity().getBlock(getBaseMetaTileEntity().getXCoord(), y, getBaseMetaTileEntity().getZCoord()) != MINING_PIPE_TIP_BLOCK - && this.mInventory[0] != null && this.mInventory[0].stackSize > 0 && GT_Utility.areStacksEqual(this.mInventory[0], MINING_PIPE)) { - getBaseMetaTileEntity().getWorld().setBlock(getBaseMetaTileEntity().getXCoord(), y, getBaseMetaTileEntity().getZCoord(), MINING_PIPE_BLOCK); - getBaseMetaTileEntity().decrStackSize(0, 1); + } + + + if (getBaseMetaTileEntity().getBlock(x, y, z) != MINING_PIPE_TIP_BLOCK) { + if (y != getBaseMetaTileEntity().getYCoord() - 1 && getBaseMetaTileEntity().getBlock(x, y + 1, z) == MINING_PIPE_BLOCK) { + // We're below the pump at the bottom of the pipes, we haven't found a tip; make the previous pipe a tip! + this.clearQueue(true); + getBaseMetaTileEntity().getWorld().setBlock(x, y + 1, z, MINING_PIPE_TIP_BLOCK); + } + + return y + 1; } return y; } - private void scanForFluid(int aX, int aY, int aZ, ArrayList aList, int mX, int mZ, int mDist) { - doTickProfilingInThisTick = false; - ArrayList tList1 = new ArrayList(); - ArrayList tList2 = new ArrayList(); - tList1.add(new ChunkPosition(aX, aY, aZ)); - while (!tList1.isEmpty()) { - Iterator i$ = tList1.iterator(); - do { - if (!i$.hasNext()) - break; - ChunkPosition tPos = (ChunkPosition) i$.next(); - if (tPos.chunkPosX < mX + mDist) - addToFirstListIfFluidAndNotAlreadyAddedToAnyOfTheLists(tPos.chunkPosX + 1, tPos.chunkPosY, tPos.chunkPosZ, tList2, aList); - if (tPos.chunkPosX > mX - mDist) - addToFirstListIfFluidAndNotAlreadyAddedToAnyOfTheLists(tPos.chunkPosX - 1, tPos.chunkPosY, tPos.chunkPosZ, tList2, aList); - if (tPos.chunkPosZ < mZ + mDist) - addToFirstListIfFluidAndNotAlreadyAddedToAnyOfTheLists(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ + 1, tList2, aList); - if (tPos.chunkPosZ > mZ - mDist) - addToFirstListIfFluidAndNotAlreadyAddedToAnyOfTheLists(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ - 1, tList2, aList); - addToFirstListIfFluidAndNotAlreadyAddedToAnyOfTheLists(tPos.chunkPosX, tPos.chunkPosY + 1, tPos.chunkPosZ, tList2, aList); - ChunkPosition tCoordinate = new ChunkPosition(aX, aY + 1, aZ); - if (tPos.chunkPosX == mX && tPos.chunkPosZ == mZ && tPos.chunkPosY < getBaseMetaTileEntity().getYCoord() && !aList.contains(tCoordinate) && !tList2.contains(tCoordinate)) - tList2.add(tCoordinate); - } while (true); - aList.addAll(tList2); - tList1 = tList2; - tList2 = new ArrayList(); + private void clearQueue(boolean checkPumping) { + if(checkPumping) { + this.wasPumping = !this.mPumpList.isEmpty(); + } else { + this.wasPumping = false; } - for (int y = getBaseMetaTileEntity().getYCoord(); y >= aY; y--) - aList.remove(new ChunkPosition(aX, y, aZ)); + this.mPumpList.clear(); } - private boolean addToFirstListIfFluidAndNotAlreadyAddedToAnyOfTheLists(int aX, int aY, int aZ, ArrayList aList1, - ArrayList aList2) { + private void rebuildPumpQueue(int aX, int yStart, int aZ, int yEnd) { + int mDist = this.getMaxPumpableDistance(); + doTickProfilingInThisTick = false; + ArrayDeque fluidsToSearch = new ArrayDeque(); + ArrayDeque fluidsFound = new ArrayDeque(); + Set checked = new HashSet(); + this.clearQueue(false); + + for (int aY = yStart ; this.mPumpList.isEmpty() && aY >= yEnd ; aY--) { + // Start at the top (presumably the block below the pump), and work our way down to the end (presumably the location of the pump Head) + // and build up a queue of fluids to pump + fluidsToSearch.add(new ChunkPosition(aX, aY, aZ)); + + while (!fluidsToSearch.isEmpty()) { + Iterator i$ = fluidsToSearch.iterator(); + while(i$.hasNext()) { + ChunkPosition tPos = i$.next(); + + // Look all around + if (tPos.chunkPosX < aX + mDist) queueFluid(tPos.chunkPosX + 1, tPos.chunkPosY, tPos.chunkPosZ, fluidsFound, checked); + if (tPos.chunkPosX > aX - mDist) queueFluid(tPos.chunkPosX - 1, tPos.chunkPosY, tPos.chunkPosZ, fluidsFound, checked); + if (tPos.chunkPosZ < aZ + mDist) queueFluid(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ + 1, fluidsFound, checked); + if (tPos.chunkPosZ > aZ - mDist) queueFluid(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ - 1, fluidsFound, checked); + + // And then look up + queueFluid(tPos.chunkPosX, tPos.chunkPosY + 1, tPos.chunkPosZ, this.mPumpList, checked); + } + this.mPumpList.addAll(fluidsFound); + fluidsToSearch = fluidsFound; + fluidsFound = new ArrayDeque(); + } + + // Make sure we don't have the pipe location in the queue + this.mPumpList.remove(new ChunkPosition(aX, aY, aZ)); + } + } + + private boolean queueFluid(int aX, int aY, int aZ, ArrayDeque fluidsFound, Set checked) { + // If we haven't already looked at this coordinate set, and it's not already in the list of fluids found, see if there is + // a valid fluid and add it to the fluids found ChunkPosition tCoordinate = new ChunkPosition(aX, aY, aZ); - if ((!aList1.contains(tCoordinate)) && (!aList2.contains(tCoordinate))) { + if (checked.add(tCoordinate) && !fluidsFound.contains(tCoordinate)) { Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ); - if ((this.mPumpedBlock1 == aBlock) || (this.mPumpedBlock2 == aBlock)) { - aList1.add(tCoordinate); + if ((this.mPrimaryPumpedBlock == aBlock) || (this.mSecondaryPumpedBlock == aBlock)) { + fluidsFound.addFirst(tCoordinate); return true; } } return false; } - private void getFluidAt(int aX, int aY, int aZ) { + private void checkForFluidToPump(int aX, int aY, int aZ) { + // If we don't currently have a valid fluid to pump, try pumping the fluid at the given coordinates + if(this.hasValidFluid()) + return; + Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ); if (GT_Utility.isBlockValid(aBlock)) { if ((aBlock == Blocks.water) || (aBlock == Blocks.flowing_water)) { - this.mPumpedBlock1 = Blocks.water; - this.mPumpedBlock2 = Blocks.flowing_water; + this.mPrimaryPumpedBlock = Blocks.water; + this.mSecondaryPumpedBlock = Blocks.flowing_water; return; } if ((aBlock == Blocks.lava) || (aBlock == Blocks.flowing_lava)) { - this.mPumpedBlock1 = Blocks.lava; - this.mPumpedBlock2 = Blocks.flowing_lava; + this.mPrimaryPumpedBlock = Blocks.lava; + this.mSecondaryPumpedBlock = Blocks.flowing_lava; return; } if ((aBlock instanceof IFluidBlock)) { - this.mPumpedBlock1 = aBlock; - this.mPumpedBlock2 = aBlock; + this.mPrimaryPumpedBlock = aBlock; + this.mSecondaryPumpedBlock = aBlock; return; } } - this.mPumpedBlock1 = null; - this.mPumpedBlock2 = null; + this.mPrimaryPumpedBlock = null; + this.mSecondaryPumpedBlock = null; } private boolean consumeFluid(int aX, int aY, int aZ) { - if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), aX, aY, aZ, true)) return false; + // Try to consume a fluid at a location + // Returns true if something was consumed, otherwise false + if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), aX, aY, aZ, true)) return false; + Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ); - int aMeta = getBaseMetaTileEntity().getMetaID(aX, aY, aZ); - if ((GT_Utility.isBlockValid(aBlock)) && ((this.mPumpedBlock1 == aBlock) || (this.mPumpedBlock2 == aBlock))) { - if ((aBlock == Blocks.water) || (aBlock == Blocks.flowing_water)) { - if (aMeta == 0) { - if (this.mFluid == null) { - getBaseMetaTileEntity().decreaseStoredEnergyUnits(16 * ((int) Math.pow(4, this.mTier)), true); - this.mFluid = GT_ModHandler.getWater(1000L); - } else if (GT_ModHandler.isWater(this.mFluid)) { - getBaseMetaTileEntity().decreaseStoredEnergyUnits(16 * ((int) Math.pow(4, this.mTier)), true); - this.mFluid.amount += 1000; - } else { - return false; - } - } else { - getBaseMetaTileEntity().decreaseStoredEnergyUnits(4 * ((int) Math.pow(4, this.mTier)), true); + + if ((GT_Utility.isBlockValid(aBlock)) && ((this.mPrimaryPumpedBlock == aBlock) || (this.mSecondaryPumpedBlock == aBlock))) { + boolean isWaterOrLava = ((this.mPrimaryPumpedBlock == Blocks.water || this.mPrimaryPumpedBlock == Blocks.lava)); + + if (isWaterOrLava && getBaseMetaTileEntity().getMetaID(aX, aY, aZ) != 0) { + // Water/Lava that isn't a source block - do nothing here, but set the block to air and consume energy below + if (D1) { + GT_Log.out.println("PUMP: Water/Lava - Not a source block"); } - } - if ((aBlock == Blocks.lava) || (aBlock == Blocks.flowing_lava)) { - if (aMeta == 0) { - if (this.mFluid == null) { - getBaseMetaTileEntity().decreaseStoredEnergyUnits(16 * ((int) Math.pow(4, this.mTier)), true); - this.mFluid = GT_ModHandler.getLava(1000L); - } else if (GT_ModHandler.isLava(this.mFluid)) { - getBaseMetaTileEntity().decreaseStoredEnergyUnits(16 * ((int) Math.pow(4, this.mTier)), true); - this.mFluid.amount += 1000; - } else { - return false; - } - } else { - getBaseMetaTileEntity().decreaseStoredEnergyUnits(4 * ((int) Math.pow(4, this.mTier)), true); - } - } - if ((aBlock instanceof IFluidBlock)) { - if (this.mFluid == null) { + } else if (this.mFluid == null) { + // The pump has no internal fluid + if (this.mPrimaryPumpedBlock == Blocks.water) + this.mFluid = GT_ModHandler.getWater(1000L); + else if (this.mPrimaryPumpedBlock == Blocks.lava) + this.mFluid = GT_ModHandler.getLava(1000L); + else { + // Not water or lava; try to drain and set to air this.mFluid = ((IFluidBlock) aBlock).drain(getBaseMetaTileEntity().getWorld(), aX, aY, aZ, true); - getBaseMetaTileEntity().decreaseStoredEnergyUnits(this.mFluid == null ? 1000 : this.mFluid.amount, true); - } else if (this.mFluid.isFluidEqual(((IFluidBlock) aBlock).drain(getBaseMetaTileEntity().getWorld(), aX, aY, aZ, false))) { - this.getBaseMetaTileEntity().getWorld().setBlockToAir(aX, aY, aZ); - this.mFluid.amount += 1000; - getBaseMetaTileEntity().decreaseStoredEnergyUnits(16 * ((int) Math.pow(4, this.mTier)), true); - } else { - return false; } + } else if (GT_ModHandler.isWater(this.mFluid) || GT_ModHandler.isLava(this.mFluid) || + this.mFluid.isFluidEqual(((IFluidBlock) aBlock).drain(getBaseMetaTileEntity().getWorld(), aX, aY, aZ, false))) + { + if (!isWaterOrLava) { + // Only set Block to Air for non lava/water fluids + this.getBaseMetaTileEntity().getWorld().setBlockToAir(aX, aY, aZ); + } + this.mFluid.amount += 1000; + + } else { + if (D1) { + GT_Log.out.println("PUMP: Couldn't consume " + aBlock); + } + // We didn't do anything + return false; } + + getBaseMetaTileEntity().decreaseStoredEnergyUnits(this.getEuUsagePerAction(), true); getBaseMetaTileEntity().getWorld().setBlock(aX, aY, aZ, Blocks.air, 0, 2); return true; } @@ -435,7 +569,7 @@ public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_Hatch { @Override public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, byte aSide, byte aFacing, byte aColorIndex, boolean aActive, boolean aRedstone) { - return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[mTier][aColorIndex + 1], (aSide == 0 || aSide == 1) ? null : new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_ADV_PUMP)}; + return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[mTier][aColorIndex + 1], (aSide == 0 || aSide == 1) ? new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) : new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_ADV_PUMP)}; } @Override @@ -453,9 +587,9 @@ public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_Hatch { private FakePlayer mFakePlayer = null; protected FakePlayer getFakePlayer(IGregTechTileEntity aBaseTile) { - if (mFakePlayer == null) mFakePlayer = GT_Utility.getFakePlayer(aBaseTile); - mFakePlayer.setWorld(aBaseTile.getWorld()); - mFakePlayer.setPosition(aBaseTile.getXCoord(), aBaseTile.getYCoord(), aBaseTile.getZCoord()); - return mFakePlayer; + if (mFakePlayer == null) mFakePlayer = GT_Utility.getFakePlayer(aBaseTile); + mFakePlayer.setWorld(aBaseTile.getWorld()); + mFakePlayer.setPosition(aBaseTile.getXCoord(), aBaseTile.getYCoord(), aBaseTile.getZCoord()); + return mFakePlayer; } }