package pneumaticCraft.common.tileentity; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Stack; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.ChunkPosition; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidHandler; import org.apache.commons.lang3.tuple.Pair; import pneumaticCraft.api.tileentity.IAirHandler; import pneumaticCraft.common.ai.ChunkPositionSorter; import pneumaticCraft.common.block.Blockss; import pneumaticCraft.common.item.ItemMachineUpgrade; import pneumaticCraft.common.item.Itemss; import pneumaticCraft.common.network.DescSynced; import pneumaticCraft.common.network.GuiSynced; import pneumaticCraft.common.util.IOHelper; import pneumaticCraft.common.util.PneumaticCraftUtils; import pneumaticCraft.lib.PneumaticValues; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class TileEntityGasLift extends TileEntityPneumaticBase implements IMinWorkingPressure, IRedstoneControlled, IFluidHandler, IInventory{ @GuiSynced private final FluidTank tank = new FluidTank(PneumaticValues.NORMAL_TANK_CAPACITY); private final ItemStack[] inventory = new ItemStack[5]; @GuiSynced public int currentDepth; @GuiSynced public int redstoneMode, status, mode; @DescSynced public boolean[] sidesConnected = new boolean[6]; private int workTimer; private int ticker; private List<ChunkPosition> pumpingLake; private static final int MAX_PUMP_RANGE = 15; public TileEntityGasLift(){ super(5, 7, 3000); setUpgradeSlots(0, 1, 2, 3); } @Override public boolean isConnectedTo(ForgeDirection d){ return d != ForgeDirection.DOWN; } @Override public void onNeighborTileUpdate(){ super.onNeighborTileUpdate(); List<Pair<ForgeDirection, IAirHandler>> connections = getConnectedPneumatics(); for(int i = 0; i < sidesConnected.length; i++) sidesConnected[i] = false; for(Pair<ForgeDirection, IAirHandler> entry : connections) { sidesConnected[entry.getKey().ordinal()] = true; } } @Override public void updateEntity(){ super.updateEntity(); if(!worldObj.isRemote) { ticker++; if(currentDepth > 0) { int curCheckingPipe = ticker % currentDepth; if(curCheckingPipe > 0 && !isPipe(xCoord, yCoord - curCheckingPipe, zCoord)) currentDepth = curCheckingPipe - 1; } if(ticker % 400 == 0) pumpingLake = null; if(redstoneAllows() && getPressure(ForgeDirection.UNKNOWN) >= getMinWorkingPressure()) { workTimer += this.getSpeedMultiplierFromUpgrades(); while(workTimer > 20) { workTimer -= 20; status = 0; if(mode == 2) { if(currentDepth > 0) { status = 3; if(isPipe(xCoord, yCoord - currentDepth, zCoord)) { if(IOHelper.insert(this, new ItemStack(Blockss.pressureTube), 0, false) == null) { worldObj.func_147480_a(xCoord, yCoord - currentDepth, zCoord, false); addAir(-100, ForgeDirection.UNKNOWN); currentDepth--; } else { status = 0; } } else { currentDepth--; } } } else { if(!suckLiquid()) { if(yCoord - currentDepth >= 0 && !isUnbreakable(xCoord, yCoord - currentDepth - 1, zCoord)) { status = 2; currentDepth++; if(!isPipe(xCoord, yCoord - currentDepth, zCoord)) { if(inventory[4] != null) { decrStackSize(4, 1); worldObj.func_147480_a(xCoord, yCoord - currentDepth, zCoord, false); worldObj.setBlock(xCoord, yCoord - currentDepth, zCoord, Blockss.pressureTube); addAir(-100, ForgeDirection.UNKNOWN); } else { status = 0; currentDepth--; break; } } } else { break; } } } } } else { status = 0; } if(getUpgrades(ItemMachineUpgrade.UPGRADE_DISPENSER_DAMAGE) > 0) { autoExportLiquid(); } } } private boolean isPipe(int x, int y, int z){ return worldObj.getBlock(x, y, z) == Blockss.pressureTube; } private boolean isUnbreakable(int x, int y, int z){ return worldObj.getBlock(x, y, z).getBlockHardness(worldObj, x, y, z) < 0; } public boolean suckLiquid(){ Block block = worldObj.getBlock(xCoord, yCoord - currentDepth - 1, zCoord); Fluid fluid = FluidRegistry.lookupFluidForBlock(block); if(fluid != null) { if(fill(ForgeDirection.UNKNOWN, new FluidStack(fluid, 1000), false) == 1000) { if(pumpingLake == null) { pumpingLake = new ArrayList<ChunkPosition>(); Stack<ChunkPosition> pendingPositions = new Stack<ChunkPosition>(); ChunkPosition thisPos = new ChunkPosition(xCoord, yCoord - currentDepth - 1, zCoord); pendingPositions.add(thisPos); pumpingLake.add(thisPos); while(!pendingPositions.empty()) { ChunkPosition checkingPos = pendingPositions.pop(); for(ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { if(d == ForgeDirection.DOWN) continue; ChunkPosition newPos = new ChunkPosition(checkingPos.chunkPosX + d.offsetX, checkingPos.chunkPosY + d.offsetY, checkingPos.chunkPosZ + d.offsetZ); if(PneumaticCraftUtils.distBetween(newPos, xCoord + 0.5, yCoord - currentDepth - 1, zCoord + 0.5) <= MAX_PUMP_RANGE && worldObj.getBlock(newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ) == block && !pumpingLake.contains(newPos)) { pendingPositions.add(newPos); pumpingLake.add(newPos); } } } Collections.sort(pumpingLake, new ChunkPositionSorter(xCoord + 0.5, yCoord - currentDepth - 1, zCoord + 0.5)); Collections.reverse(pumpingLake); } ChunkPosition curPos = null; boolean foundSource = false; while(pumpingLake.size() > 0) { curPos = pumpingLake.get(0); if(worldObj.getBlock(curPos.chunkPosX, curPos.chunkPosY, curPos.chunkPosZ) == block && worldObj.getBlockMetadata(curPos.chunkPosX, curPos.chunkPosY, curPos.chunkPosZ) == 0) { foundSource = true; break; } pumpingLake.remove(0); } if(pumpingLake.size() == 0) { pumpingLake = null; } else if(foundSource) { worldObj.setBlockToAir(curPos.chunkPosX, curPos.chunkPosY, curPos.chunkPosZ); fill(ForgeDirection.UNKNOWN, new FluidStack(fluid, 1000), true); addAir(-100, ForgeDirection.UNKNOWN); status = 1; } } return true; } else { pumpingLake = null; return false; } } @Override public void handleGUIButtonPress(int buttonID, EntityPlayer player){ if(buttonID == 0) { redstoneMode++; if(redstoneMode > 2) redstoneMode = 0; } else if(buttonID > 0 && buttonID < 4) { mode = buttonID - 1; } } @Override public int getRedstoneMode(){ return redstoneMode; } @Override public float getMinWorkingPressure(){ return 0.5F + currentDepth * 0.05F; } @Override public void writeToNBT(NBTTagCompound tag){ super.writeToNBT(tag); writeInventoryToNBT(tag, inventory); tag.setByte("redstoneMode", (byte)redstoneMode); tag.setByte("mode", (byte)mode); NBTTagCompound tankTag = new NBTTagCompound(); tank.writeToNBT(tankTag); tag.setTag("tank", tankTag); tag.setInteger("currentDepth", currentDepth); } @Override public void readFromNBT(NBTTagCompound tag){ super.readFromNBT(tag); readInventoryFromNBT(tag, inventory); redstoneMode = tag.getByte("redstoneMode"); mode = tag.getByte("mode"); tank.readFromNBT(tag.getCompoundTag("tank")); currentDepth = tag.getInteger("currentDepth"); } @Override public int fill(ForgeDirection from, FluidStack resource, boolean doFill){ return tank.fill(resource, doFill); } @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain){ return tank.getFluid() != null && tank.getFluid().isFluidEqual(resource) ? drain(ForgeDirection.UNKNOWN, resource.amount, doDrain) : null; } @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain){ return mode == 0 ? tank.drain(maxDrain, doDrain) : tank.drain(Math.min(tank.getFluidAmount() - 1000, maxDrain), doDrain); } @Override public boolean canFill(ForgeDirection from, Fluid fluid){ return false; } @Override public boolean canDrain(ForgeDirection from, Fluid fluid){ return true; } @Override public FluidTankInfo[] getTankInfo(ForgeDirection from){ return new FluidTankInfo[]{new FluidTankInfo(tank)}; } @SideOnly(Side.CLIENT) public FluidTank getTank(){ return tank; } /** * Returns the name of the inventory. */ @Override public String getInventoryName(){ return Blockss.gasLift.getUnlocalizedName(); } /** * Returns the number of slots in the inventory. */ @Override public int getSizeInventory(){ return inventory.length; } /** * Returns the stack in slot i */ @Override public ItemStack getStackInSlot(int par1){ return inventory[par1]; } @Override public ItemStack decrStackSize(int slot, int amount){ ItemStack itemStack = getStackInSlot(slot); if(itemStack != null) { if(itemStack.stackSize <= amount) { setInventorySlotContents(slot, null); } else { itemStack = itemStack.splitStack(amount); if(itemStack.stackSize == 0) { setInventorySlotContents(slot, null); } } } return itemStack; } @Override public ItemStack getStackInSlotOnClosing(int slot){ ItemStack itemStack = getStackInSlot(slot); if(itemStack != null) { setInventorySlotContents(slot, null); } return itemStack; } @Override public void setInventorySlotContents(int slot, ItemStack itemStack){ inventory[slot] = itemStack; if(itemStack != null && itemStack.stackSize > getInventoryStackLimit()) { itemStack.stackSize = getInventoryStackLimit(); } } @Override public boolean isItemValidForSlot(int par1, ItemStack stack){ return stack != null && (par1 < 4 && stack.getItem() == Itemss.machineUpgrade || par1 == 4 && stack.isItemEqual(new ItemStack(Blockss.pressureTube))); } @Override public boolean hasCustomInventoryName(){ return false; } @Override public int getInventoryStackLimit(){ return 64; } @Override public boolean isUseableByPlayer(EntityPlayer p_70300_1_){ return isGuiUseableByPlayer(p_70300_1_); } @Override public void openInventory(){} @Override public void closeInventory(){} }