package mekanism.common.multipart;
import java.util.Collection;
import mekanism.api.transmitters.TransmissionType;
import mekanism.api.util.CapabilityUtils;
import mekanism.common.FluidNetwork;
import mekanism.common.Tier;
import mekanism.common.Tier.BaseTier;
import mekanism.common.Tier.PipeTier;
import mekanism.common.base.FluidHandlerWrapper;
import mekanism.common.base.IFluidHandlerWrapper;
import mekanism.common.capabilities.CapabilityWrapperManager;
import mekanism.common.util.PipeUtils;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
public class PartMechanicalPipe extends PartTransmitter<IFluidHandler, FluidNetwork> implements IFluidHandlerWrapper
{
public Tier.PipeTier tier;
public float currentScale;
public FluidTank buffer = new FluidTank(Fluid.BUCKET_VOLUME);
public FluidStack lastWrite;
public PartMechanicalPipe(Tier.PipeTier pipeTier)
{
super();
tier = pipeTier;
buffer.setCapacity(getCapacity());
}
@Override
public void update()
{
if(!getWorld().isRemote)
{
updateShare();
IFluidHandler[] connectedAcceptors = PipeUtils.getConnectedAcceptors(getPos(), getWorld());
for(EnumFacing side : getConnections(ConnectionType.PULL))
{
if(connectedAcceptors[side.ordinal()] != null)
{
IFluidHandler container = connectedAcceptors[side.ordinal()];
if(container != null)
{
FluidStack received = container.drain(getPullAmount(), false);
if(received != null && received.amount != 0)
{
container.drain(takeFluid(received, true), true);
}
}
}
}
}
super.update();
}
@Override
public void updateShare()
{
if(getTransmitter().hasTransmitterNetwork() && getTransmitter().getTransmitterNetworkSize() > 0)
{
FluidStack last = getSaveShare();
if((last != null && !(lastWrite != null && lastWrite.amount == last.amount && lastWrite.getFluid() == last.getFluid())) || (last == null && lastWrite != null))
{
lastWrite = last;
markDirty();
}
}
}
private FluidStack getSaveShare()
{
if(getTransmitter().hasTransmitterNetwork() && getTransmitter().getTransmitterNetwork().buffer != null)
{
int remain = getTransmitter().getTransmitterNetwork().buffer.amount%getTransmitter().getTransmitterNetwork().transmitters.size();
int toSave = getTransmitter().getTransmitterNetwork().buffer.amount/getTransmitter().getTransmitterNetwork().transmitters.size();
if(getTransmitter().getTransmitterNetwork().transmitters.iterator().next().equals(getTransmitter()))
{
toSave += remain;
}
return PipeUtils.copy(getTransmitter().getTransmitterNetwork().buffer, toSave);
}
return null;
}
@Override
public void onUnloaded()
{
if(!getWorld().isRemote && getTransmitter().hasTransmitterNetwork())
{
if(lastWrite != null && getTransmitter().getTransmitterNetwork().buffer != null)
{
getTransmitter().getTransmitterNetwork().buffer.amount -= lastWrite.amount;
if(getTransmitter().getTransmitterNetwork().buffer.amount <= 0)
{
getTransmitter().getTransmitterNetwork().buffer = null;
}
}
}
super.onUnloaded();
}
@Override
public void readFromNBT(NBTTagCompound nbtTags)
{
super.readFromNBT(nbtTags);
if(nbtTags.hasKey("tier")) tier = Tier.PipeTier.values()[nbtTags.getInteger("tier")];
buffer.setCapacity(getCapacity());
if(nbtTags.hasKey("cacheFluid"))
{
buffer.setFluid(FluidStack.loadFluidStackFromNBT(nbtTags.getCompoundTag("cacheFluid")));
}
else {
buffer.setFluid(null);
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbtTags)
{
super.writeToNBT(nbtTags);
if(lastWrite != null && lastWrite.amount > 0)
{
nbtTags.setTag("cacheFluid", lastWrite.writeToNBT(new NBTTagCompound()));
}
else {
nbtTags.removeTag("cacheFluid");
}
nbtTags.setInteger("tier", tier.ordinal());
return nbtTags;
}
@Override
public ResourceLocation getType()
{
return new ResourceLocation("mekanism:mechanical_pipe_" + tier.name().toLowerCase());
}
@Override
public TransmissionType getTransmissionType()
{
return TransmissionType.FLUID;
}
@Override
public TransmitterType getTransmitterType()
{
return tier.type;
}
@Override
public boolean isValidAcceptor(TileEntity acceptor, EnumFacing side)
{
return PipeUtils.isValidAcceptorOnSide(acceptor, side);
}
@Override
public FluidNetwork createNewNetwork()
{
return new FluidNetwork();
}
@Override
public FluidNetwork createNetworkByMerging(Collection<FluidNetwork> networks)
{
return new FluidNetwork(networks);
}
@Override
public int getCapacity()
{
return tier.pipeCapacity;
}
@Override
public FluidStack getBuffer()
{
return buffer == null ? null : buffer.getFluid();
}
@Override
public void takeShare()
{
if(getTransmitter().hasTransmitterNetwork() && getTransmitter().getTransmitterNetwork().buffer != null && lastWrite != null)
{
getTransmitter().getTransmitterNetwork().buffer.amount -= lastWrite.amount;
buffer.setFluid(lastWrite);
}
}
@Override
public int fill(EnumFacing from, FluidStack resource, boolean doFill)
{
if(getConnectionType(from) == ConnectionType.NORMAL)
{
return takeFluid(resource, doFill);
}
return 0;
}
@Override
public FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain)
{
return null;
}
@Override
public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain)
{
return null;
}
@Override
public boolean canFill(EnumFacing from, Fluid fluid)
{
return getConnectionType(from) == ConnectionType.NORMAL;
}
@Override
public boolean canDrain(EnumFacing from, Fluid fluid)
{
return false;
}
@Override
public FluidTankInfo[] getTankInfo(EnumFacing from)
{
if(from != null && getConnectionType(from) != ConnectionType.NONE)
{
return new FluidTankInfo[] {buffer.getInfo()};
}
return new FluidTankInfo[0];
}
public int getPullAmount()
{
return tier.pipePullAmount;
}
@Override
public IFluidHandler getCachedAcceptor(EnumFacing side)
{
TileEntity tile = getCachedTile(side);
if(CapabilityUtils.hasCapability(tile, CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side.getOpposite()))
{
return CapabilityUtils.getCapability(tile, CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side.getOpposite());
}
return null;
}
public int takeFluid(FluidStack fluid, boolean doEmit)
{
if(getTransmitter().hasTransmitterNetwork())
{
return getTransmitter().getTransmitterNetwork().emit(fluid, doEmit);
}
else {
return buffer.fill(fluid, doEmit);
}
}
@Override
public boolean upgrade(int tierOrdinal)
{
if(tier.ordinal() < BaseTier.ULTIMATE.ordinal() && tierOrdinal == tier.ordinal()+1)
{
tier = PipeTier.values()[tier.ordinal()+1];
markDirtyTransmitters();
sendDesc = true;
return true;
}
return false;
}
@Override
public void readUpdatePacket(PacketBuffer packet)
{
tier = PipeTier.values()[packet.readInt()];
super.readUpdatePacket(packet);
}
@Override
public void writeUpdatePacket(PacketBuffer packet)
{
packet.writeInt(tier.ordinal());
super.writeUpdatePacket(packet);
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing side)
{
return capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY || super.hasCapability(capability, side);
}
public CapabilityWrapperManager manager = new CapabilityWrapperManager(IFluidHandlerWrapper.class, FluidHandlerWrapper.class);
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing side)
{
if(capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
{
return (T)manager.getWrapper(this, side);
}
return super.getCapability(capability, side);
}
}