From a42f273420ec6053b2395e3ece61b979449ed4a1 Mon Sep 17 00:00:00 2001 From: Calclavia Date: Thu, 6 Mar 2014 16:33:54 +0800 Subject: [PATCH] Added PressureNode for fluid network --- .../mechanical/energy/network/EnergyNode.java | 9 +- .../energy/network/MechanicalNode.java | 9 +- .../resonantinduction/core/grid/Node.java | 10 +- .../grid/fluid/IPressureNodeProvider.java | 10 + .../core/grid/fluid/PressureNode.java | 243 ++++++++++++++++++ 5 files changed, 274 insertions(+), 7 deletions(-) create mode 100644 src/main/java/resonantinduction/core/grid/fluid/IPressureNodeProvider.java create mode 100644 src/main/java/resonantinduction/core/grid/fluid/PressureNode.java diff --git a/mechanical/src/main/java/resonantinduction/mechanical/energy/network/EnergyNode.java b/mechanical/src/main/java/resonantinduction/mechanical/energy/network/EnergyNode.java index c24d5e239..cf4cad342 100644 --- a/mechanical/src/main/java/resonantinduction/mechanical/energy/network/EnergyNode.java +++ b/mechanical/src/main/java/resonantinduction/mechanical/energy/network/EnergyNode.java @@ -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

extends Node { + public EnergyNode(P parent) + { + super(parent); + } + /** * @return Gets the power of this node. Note that power by definition is energy per second. */ diff --git a/mechanical/src/main/java/resonantinduction/mechanical/energy/network/MechanicalNode.java b/mechanical/src/main/java/resonantinduction/mechanical/energy/network/MechanicalNode.java index 4961d0111..67a1beb00 100644 --- a/mechanical/src/main/java/resonantinduction/mechanical/energy/network/MechanicalNode.java +++ b/mechanical/src/main/java/resonantinduction/mechanical/energy/network/MechanicalNode.java @@ -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 { - 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(this, MechanicalNode.class); } diff --git a/src/main/java/resonantinduction/core/grid/Node.java b/src/main/java/resonantinduction/core/grid/Node.java index 1be368c63..e4a65cc8f 100644 --- a/src/main/java/resonantinduction/core/grid/Node.java +++ b/src/main/java/resonantinduction/core/grid/Node.java @@ -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 +public abstract class Node

{ + public final P parent; + protected final AbstractMap connections = new WeakHashMap(); public G grid = null; + public Node(P parent) + { + this.parent = parent; + } + public final G getGrid() { if (grid == null) diff --git a/src/main/java/resonantinduction/core/grid/fluid/IPressureNodeProvider.java b/src/main/java/resonantinduction/core/grid/fluid/IPressureNodeProvider.java new file mode 100644 index 000000000..fbce10e03 --- /dev/null +++ b/src/main/java/resonantinduction/core/grid/fluid/IPressureNodeProvider.java @@ -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, IFluidHandler +{ + FluidTank getPressureTank(); +} diff --git a/src/main/java/resonantinduction/core/grid/fluid/PressureNode.java b/src/main/java/resonantinduction/core/grid/fluid/PressureNode.java new file mode 100644 index 000000000..700c3a586 --- /dev/null +++ b/src/main/java/resonantinduction/core/grid/fluid/PressureNode.java @@ -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 +{ + 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> it = getConnections().entrySet().iterator(); + + while (it.hasNext()) + { + Entry 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> it = getConnections().entrySet().iterator(); + + while (it.hasNext()) + { + Entry 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(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); + } + +}