package appeng.parts.p2p; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Stack; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidHandler; import appeng.api.config.TunnelType; import appeng.me.GridAccessException; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class PartP2PLiquids extends PartP2PTunnel implements IFluidHandler { private final static FluidTankInfo[] activeTank = new FluidTankInfo[] { new FluidTankInfo( null, 10000 ) }; private final static FluidTankInfo[] inactiveTank = new FluidTankInfo[] { new FluidTankInfo( null, 0 ) }; public TunnelType getTunnelType() { return TunnelType.FLUID; } public PartP2PLiquids(ItemStack is) { super( is ); } private FluidTankInfo[] getTank() { if ( output ) { PartP2PLiquids tun = getInput(); if ( tun != null ) return activeTank; } else { try { if ( !getOutputs().isEmpty() ) return activeTank; } catch (GridAccessException e) { // :( } } return inactiveTank; } IFluidHandler cachedTank; public float getPowerDrainPerTick() { return 2.0f; }; private int tmpUsed; @Override public void writeToNBT(NBTTagCompound tag) { super.writeToNBT( tag ); } @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT( tag ); } @SideOnly(Side.CLIENT) public IIcon getTypeTexture() { return Blocks.lapis_block.getBlockTextureFromSide( 0 ); } List getOutputs(Fluid input) { List outs = new LinkedList(); try { for (PartP2PLiquids l : getOutputs()) { IFluidHandler targ = l.getTarget(); if ( targ != null ) { if ( targ.canFill( l.side.getOpposite(), input ) ) outs.add( l ); } } } catch (GridAccessException e) { // :P } return outs; } @Override public void onNeighborChanged() { cachedTank = null; if ( output ) { PartP2PLiquids in = getInput(); if ( in != null ) in.onTunnelNetworkChange(); } }; @Override public void onTunnelNetworkChange() { cachedTank = null; } IFluidHandler getTarget() { if ( !proxy.isActive() ) return null; if ( cachedTank != null ) return cachedTank; TileEntity te = tile.getWorldObj().getTileEntity( tile.xCoord + side.offsetX, tile.yCoord + side.offsetY, tile.zCoord + side.offsetZ ); if ( te instanceof IFluidHandler ) return cachedTank = (IFluidHandler) te; return null; } static final ThreadLocal> depth = new ThreadLocal>(); private Stack getDepth() { Stack s = depth.get(); if ( s == null ) depth.set( s = new Stack() ); return s; } @Override public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { Stack stack = getDepth(); for (PartP2PLiquids t : stack) if ( t == this ) return 0; stack.push( this ); List list = getOutputs( resource.getFluid() ); int requestTotal = 0; Iterator i = list.iterator(); while (i.hasNext()) { PartP2PLiquids l = i.next(); IFluidHandler tank = l.getTarget(); if ( tank != null ) l.tmpUsed = tank.fill( l.side.getOpposite(), resource.copy(), false ); else l.tmpUsed = 0; if ( l.tmpUsed <= 0 ) i.remove(); else requestTotal += l.tmpUsed; } if ( requestTotal <= 0 ) { if ( stack.pop() != this ) throw new RuntimeException( "Invalid Recursion detected." ); return 0; } if ( !doFill ) { if ( stack.pop() != this ) throw new RuntimeException( "Invalid Recursion detected." ); return Math.min( resource.amount, requestTotal ); } int avilable = resource.amount; int used = 0; i = list.iterator(); while (i.hasNext()) { PartP2PLiquids l = i.next(); FluidStack insert = resource.copy(); insert.amount = (int) Math.ceil( insert.amount * ((double) l.tmpUsed / (double) requestTotal) ); if ( insert.amount > avilable ) insert.amount = avilable; IFluidHandler tank = l.getTarget(); if ( tank != null ) l.tmpUsed = tank.fill( l.side.getOpposite(), insert.copy(), true ); else l.tmpUsed = 0; avilable -= insert.amount; used += insert.amount; } if ( stack.pop() != this ) throw new RuntimeException( "Invalid Recursion detected." ); return used; } @Override public boolean canFill(ForgeDirection from, Fluid fluid) { return !output && from.equals( side ) && !getOutputs( fluid ).isEmpty(); } @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { return null; } @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { return null; } @Override public boolean canDrain(ForgeDirection from, Fluid fluid) { return false; } @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { if ( from.equals( side ) ) return getTank(); return new FluidTankInfo[0]; } }