Added PressureNode for fluid network

This commit is contained in:
Calclavia 2014-03-06 16:33:54 +08:00
parent 1016210e59
commit a42f273420
5 changed files with 274 additions and 7 deletions

View file

@ -1,9 +1,16 @@
package resonantinduction.mechanical.energy.network;
import resonantinduction.core.grid.Grid;
import resonantinduction.core.grid.INodeProvider;
import resonantinduction.core.grid.Node;
public abstract class EnergyNode extends Node
public abstract class EnergyNode<P extends INodeProvider, G extends Grid, N> extends Node<P, G, N>
{
public EnergyNode(P parent)
{
super(parent);
}
/**
* @return Gets the power of this node. Note that power by definition is energy per second.
*/

View file

@ -9,6 +9,7 @@ import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
import resonantinduction.core.ResonantInduction;
import resonantinduction.core.grid.Grid;
import resonantinduction.core.grid.INodeProvider;
import resonantinduction.core.grid.TickingGrid;
import universalelectricity.api.vector.Vector3;
import codechicken.multipart.TMultiPart;
@ -29,10 +30,8 @@ import codechicken.multipart.TMultiPart;
*
* @author Calclavia
*/
public class MechanicalNode extends EnergyNode
public class MechanicalNode extends EnergyNode<IMechanicalNodeProvider, TickingGrid, MechanicalNode>
{
public final IMechanicalNodeProvider parent;
public double torque = 0;
public double prevAngularVelocity, angularVelocity = 0;
public float acceleration = 2f;
@ -49,7 +48,7 @@ public class MechanicalNode extends EnergyNode
public MechanicalNode(IMechanicalNodeProvider parent)
{
this.parent = parent;
super(parent);
}
public MechanicalNode setLoad(double load)
@ -243,7 +242,7 @@ public class MechanicalNode extends EnergyNode
}
@Override
public Grid newGrid()
public TickingGrid newGrid()
{
return new TickingGrid<MechanicalNode>(this, MechanicalNode.class);
}

View file

@ -3,15 +3,23 @@ package resonantinduction.core.grid;
import java.util.AbstractMap;
import java.util.WeakHashMap;
import resonantinduction.mechanical.energy.network.IMechanicalNodeProvider;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.ForgeDirection;
public abstract class Node<G extends Grid, N>
public abstract class Node<P extends INodeProvider, G extends Grid, N>
{
public final P parent;
protected final AbstractMap<N, ForgeDirection> connections = new WeakHashMap<N, ForgeDirection>();
public G grid = null;
public Node(P parent)
{
this.parent = parent;
}
public final G getGrid()
{
if (grid == null)

View file

@ -0,0 +1,10 @@
package resonantinduction.core.grid.fluid;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.IFluidHandler;
import resonantinduction.core.grid.INodeProvider;
public interface IPressureNodeProvider extends INodeProvider<PressureNode>, IFluidHandler
{
FluidTank getPressureTank();
}

View file

@ -0,0 +1,243 @@
package resonantinduction.core.grid.fluid;
import java.util.Iterator;
import java.util.Map.Entry;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.IFluidHandler;
import resonantinduction.api.mechanical.fluid.IPressure;
import resonantinduction.core.grid.Grid;
import resonantinduction.core.grid.Node;
import resonantinduction.core.grid.TickingGrid;
import resonantinduction.mechanical.energy.network.IMechanicalNodeProvider;
import universalelectricity.api.vector.Vector3;
import codechicken.multipart.TMultiPart;
public class PressureNode extends Node<IPressureNodeProvider, TickingGrid, Object>
{
protected byte connectionMap = Byte.parseByte("111111", 2);
protected int pressure = 0;
public PressureNode(IPressureNodeProvider parent)
{
super(parent);
}
public PressureNode setConnection(byte connectionMap)
{
this.connectionMap = connectionMap;
return this;
}
@Override
public void update(float deltaTime)
{
updatePressure();
distribute();
}
protected void updatePressure()
{
int totalPressure = 0;
int findCount = 0;
int minPressure = 0;
int maxPressure = 0;
Iterator<Entry<Object, ForgeDirection>> it = getConnections().entrySet().iterator();
while (it.hasNext())
{
Entry<Object, ForgeDirection> entry = it.next();
Object obj = entry.getKey();
if (obj instanceof IPressure)
{
int pressure = ((IPressure) obj).getPressure(entry.getValue().getOpposite());
minPressure = Math.min(pressure, minPressure);
maxPressure = Math.max(pressure, maxPressure);
totalPressure += pressure;
findCount++;
}
}
if (findCount == 0)
{
pressure = 0;
}
else
{
/**
* Create pressure loss.
*/
if (minPressure < 0)
minPressure += 1;
if (maxPressure > 0)
maxPressure -= 1;
pressure = Math.max(minPressure, Math.min(maxPressure, totalPressure / findCount + Integer.signum(totalPressure)));
}
}
public void distribute()
{
Iterator<Entry<Object, ForgeDirection>> it = getConnections().entrySet().iterator();
while (it.hasNext())
{
Entry<?, ForgeDirection> entry = it.next();
Object obj = entry.getKey();
ForgeDirection dir = entry.getValue();
if (obj instanceof PressureNode)
{
PressureNode otherPipe = (PressureNode) obj;
/**
* Move fluid from higher pressure to lower. In this case, move from tankA to tankB.
*/
int pressureA = getPressure(dir);
int pressureB = otherPipe.getPressure(dir.getOpposite());
if (pressureA >= pressureB)
{
FluidTank tankA = parent.getPressureTank();
FluidStack fluidA = tankA.getFluid();
if (tankA != null && fluidA != null)
{
int amountA = fluidA.amount;
if (amountA > 0)
{
FluidTank tankB = otherPipe.parent.getPressureTank();
if (tankB != null)
{
int amountB = tankB.getFluidAmount();
int quantity = Math.max(pressureA > pressureB ? (pressureA - pressureB) * getMaxFlowRate() : 0, Math.min((amountA - amountB) / 2, getMaxFlowRate()));
quantity = Math.min(Math.min(quantity, tankB.getCapacity() - amountB), amountA);
if (quantity > 0)
{
FluidStack drainStack = parent.drain(dir.getOpposite(), quantity, false);
if (drainStack != null && drainStack.amount > 0)
parent.drain(dir.getOpposite(), otherPipe.parent.fill(dir, drainStack, true), true);
}
}
}
}
}
}
else if (obj instanceof IFluidHandler)
{
IFluidHandler fluidHandler = (IFluidHandler) obj;
int pressure = getPressure(dir);
int tankPressure = fluidHandler instanceof IPressure ? ((IPressure) fluidHandler).getPressure(dir.getOpposite()) : 0;
FluidTank sourceTank = parent.getPressureTank();
int transferAmount = (Math.max(pressure, tankPressure) - Math.min(pressure, tankPressure)) * getMaxFlowRate();
if (pressure > tankPressure)
{
if (sourceTank.getFluidAmount() > 0 && transferAmount > 0)
{
FluidStack drainStack = parent.drain(dir.getOpposite(), transferAmount, false);
parent.drain(dir.getOpposite(), fluidHandler.fill(dir.getOpposite(), drainStack, true), true);
}
}
else if (pressure < tankPressure)
{
if (transferAmount > 0)
{
FluidStack drainStack = fluidHandler.drain(dir.getOpposite(), transferAmount, false);
if (drainStack != null)
{
fluidHandler.drain(dir.getOpposite(), parent.fill(dir.getOpposite(), drainStack, true), true);
}
}
}
}
}
}
private int getMaxFlowRate()
{
return 10;
}
protected int getPressure(ForgeDirection dir)
{
return pressure;
}
/**
* Recache the connections. This is the default connection implementation.
*/
public void recache()
{
synchronized (connections)
{
connections.clear();
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity tile = position().translate(dir).getTileEntity(world());
if (tile instanceof IMechanicalNodeProvider)
{
PressureNode check = ((IPressureNodeProvider) tile).getNode(dir.getOpposite());
if (check != null && canConnect(dir, check) && check.canConnect(dir.getOpposite(), this))
{
connections.put(check, dir);
}
}
}
}
}
public World world()
{
return parent instanceof TMultiPart ? ((TMultiPart) parent).world() : parent instanceof TileEntity ? ((TileEntity) parent).getWorldObj() : null;
}
public Vector3 position()
{
return parent instanceof TMultiPart ? new Vector3(((TMultiPart) parent).x(), ((TMultiPart) parent).y(), ((TMultiPart) parent).z()) : parent instanceof TileEntity ? new Vector3((TileEntity) parent) : null;
}
public boolean canConnect(ForgeDirection from, Object source)
{
return (source instanceof PressureNode) && (connectionMap & (1 << from.ordinal())) != 0;
}
@Override
public TickingGrid newGrid()
{
return new TickingGrid<PressureNode>(this, PressureNode.class);
}
@Override
public void load(NBTTagCompound nbt)
{
super.load(nbt);
pressure = nbt.getInteger("pressure");
}
@Override
public void save(NBTTagCompound nbt)
{
super.save(nbt);
nbt.setInteger("pressure", pressure);
}
}