Mekanism-tilera-Edition/src/main/java/mekanism/common/FluidNetwork.java
2015-11-26 14:40:46 -07:00

356 lines
7 KiB
Java

package mekanism.common;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.Event;
import mekanism.api.Coord4D;
import mekanism.api.transmitters.DynamicNetwork;
import mekanism.api.transmitters.IGridTransmitter;
import mekanism.common.util.LangUtils;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidHandler;
import java.util.*;
public class FluidNetwork extends DynamicNetwork<IFluidHandler, FluidNetwork>
{
public int transferDelay = 0;
public boolean didTransfer;
public boolean prevTransfer;
public float fluidScale;
public Fluid refFluid;
public FluidStack buffer;
public int prevStored;
public int prevTransferAmount = 0;
public FluidNetwork() {}
public FluidNetwork(Collection<FluidNetwork> networks)
{
for(FluidNetwork net : networks)
{
if(net != null)
{
if(net.buffer != null)
{
if(buffer == null)
{
buffer = net.buffer.copy();
}
else {
if(buffer.getFluid() == net.buffer.getFluid())
{
buffer.amount += net.buffer.amount;
}
else if(net.buffer.amount > buffer.amount)
{
buffer = net.buffer.copy();
}
}
net.buffer = null;
}
adoptTransmittersAndAcceptorsFrom(net);
net.deregister();
}
}
fluidScale = getScale();
register();
}
@Override
public void absorbBuffer(IGridTransmitter<IFluidHandler, FluidNetwork> transmitter)
{
Object b = transmitter.getBuffer();
if(!(b instanceof FluidStack) || ((FluidStack)b).getFluid() == null || ((FluidStack)b).amount == 0)
{
return;
}
FluidStack fluid = (FluidStack)b;
if(buffer == null || buffer.getFluid() == null || buffer.amount == 0)
{
buffer = fluid.copy();
fluid.amount = 0;
return;
}
//TODO better multiple buffer impl
if(buffer.isFluidEqual(fluid))
{
buffer.amount += fluid.amount;
}
fluid.amount = 0;
}
@Override
public void clampBuffer()
{
if(buffer != null && buffer.amount > getCapacity())
{
buffer.amount = capacity;
}
}
@Override
protected void updateMeanCapacity()
{
int numCables = transmitters.size();
double sum = 0;
for(IGridTransmitter<IFluidHandler, FluidNetwork> pipe : transmitters)
{
sum += pipe.getCapacity();
}
meanCapacity = sum / (double)numCables;
}
public int getFluidNeeded()
{
return getCapacity()-(buffer != null ? buffer.amount : 0);
}
public int tickEmit(FluidStack fluidToSend, boolean doTransfer)
{
List<IFluidHandler> availableAcceptors = new ArrayList<>();
availableAcceptors.addAll(getAcceptors(fluidToSend));
Collections.shuffle(availableAcceptors);
int fluidSent = 0;
if(!availableAcceptors.isEmpty())
{
int divider = availableAcceptors.size();
int remaining = fluidToSend.amount % divider;
int sending = (fluidToSend.amount-remaining)/divider;
for(IFluidHandler acceptor : availableAcceptors)
{
int currentSending = sending;
EnumSet<ForgeDirection> sides = acceptorDirections.get(Coord4D.get((TileEntity)acceptor));
if(remaining > 0)
{
currentSending++;
remaining--;
}
for(ForgeDirection side : sides)
{
int prev = fluidSent;
if(acceptor != null && fluidToSend != null)
{
fluidSent += acceptor.fill(side, new FluidStack(fluidToSend.getFluidID(), currentSending), doTransfer);
}
if(fluidSent > prev)
{
break;
}
}
}
}
if(doTransfer && fluidSent > 0 && FMLCommonHandler.instance().getEffectiveSide().isServer())
{
didTransfer = true;
transferDelay = 2;
}
return fluidSent;
}
public int emit(FluidStack fluidToSend, boolean doTransfer)
{
if(fluidToSend == null || (buffer != null && buffer.getFluid() != fluidToSend.getFluid()))
{
return 0;
}
int toUse = Math.min(getFluidNeeded(), fluidToSend.amount);
if(doTransfer)
{
if(buffer == null)
{
buffer = fluidToSend.copy();
buffer.amount = toUse;
}
else {
buffer.amount += toUse;
}
}
return toUse;
}
@Override
public void onUpdate()
{
super.onUpdate();
if(FMLCommonHandler.instance().getEffectiveSide().isServer())
{
prevTransferAmount = 0;
if(transferDelay == 0)
{
didTransfer = false;
}
else {
transferDelay--;
}
int stored = buffer != null ? buffer.amount : 0;
if(stored != prevStored)
{
needsUpdate = true;
}
prevStored = stored;
if(didTransfer != prevTransfer || needsUpdate)
{
MinecraftForge.EVENT_BUS.post(new FluidTransferEvent(this, buffer, didTransfer));
needsUpdate = false;
}
prevTransfer = didTransfer;
if(buffer != null)
{
prevTransferAmount = tickEmit(buffer, true);
if(buffer != null)
{
buffer.amount -= prevTransferAmount;
if(buffer.amount <= 0)
{
buffer = null;
}
}
}
}
}
@Override
public void clientTick()
{
super.clientTick();
fluidScale = Math.max(fluidScale, getScale());
if(didTransfer && fluidScale < 1)
{
fluidScale = Math.max(getScale(), Math.min(1, fluidScale+0.02F));
}
else if(!didTransfer && fluidScale > 0)
{
fluidScale = getScale();
if(fluidScale == 0)
{
buffer = null;
}
}
}
@Override
public Set<IFluidHandler> getAcceptors(Object data)
{
FluidStack fluidToSend = (FluidStack)data;
Set<IFluidHandler> toReturn = new HashSet<>();
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{
return toReturn;
}
for(Coord4D coord : possibleAcceptors.keySet())
{
EnumSet<ForgeDirection> sides = acceptorDirections.get(coord);
TileEntity tile = coord.getTileEntity(getWorld());
if(sides == null || sides.isEmpty())
{
continue;
}
IFluidHandler acceptor = (IFluidHandler)tile;
for(ForgeDirection side : sides)
{
if(acceptor != null && acceptor.canFill(side, fluidToSend.getFluid()))
{
toReturn.add(acceptor);
break;
}
}
}
return toReturn;
}
public static class FluidTransferEvent extends Event
{
public final FluidNetwork fluidNetwork;
public final FluidStack fluidType;
public final boolean didTransfer;
public FluidTransferEvent(FluidNetwork network, FluidStack type, boolean did)
{
fluidNetwork = network;
fluidType = type;
didTransfer = did;
}
}
public float getScale()
{
return Math.min(1, (buffer == null || getCapacity() == 0 ? 0 : (float)buffer.amount/getCapacity()));
}
@Override
public String toString()
{
return "[FluidNetwork] " + transmitters.size() + " transmitters, " + possibleAcceptors.size() + " acceptors.";
}
@Override
public String getNeededInfo()
{
return (float)getFluidNeeded()/1000F + " buckets";
}
@Override
public String getStoredInfo()
{
return buffer != null ? LangUtils.localizeFluidStack(buffer) + " (" + buffer.amount + " mB)" : "None";
}
@Override
public String getFlowInfo()
{
return Integer.toString(prevTransferAmount) + " mB/t";
}
}