Massive Fluid Network changes

Got started on this and didn't stop to better document the changes.
First the man changes are to div out the network code to be more usable
in other way than fluids. As well to make a new network class for the
tanks which are now becoming a more like the pipes. I will later as well
make a mechanical network and a data network for later use.

On top of that there are some helper class that i didn't upload before i
started work. There is nothing too them as they were in the start of
development.
This commit is contained in:
Robert Seifert 2013-06-03 02:22:29 -04:00
parent 04a81b09a3
commit 3de7ab0ca5
24 changed files with 1124 additions and 848 deletions

View file

@ -1,52 +0,0 @@
package dark.library.helpers;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
public class DebugToPlayer
{
/**
* Sends a message to the closest player
*
* @param range - range
* @param msg - display message under 200 chars
*/
public static void SendToClosest(World world, int x, int y, int z, int range, String msg)
{
EntityPlayer player = world.getClosestPlayer(x, y, z, range);
if (player != null)
{
msg = trimForDisplay(msg);
player.sendChatToPlayer("Debug: " + msg);
}
}
/**
* Sends a debug message to the player using the tileEntity as the center
*
* @param r - range
* @param msg - display message under 200 chars
*/
public static void SendToClosest(TileEntity ent, int r, String msg)
{
if (ent != null)
{
DebugToPlayer.SendToClosest(ent.worldObj, ent.xCoord, ent.yCoord, ent.zCoord, r, msg);
}
}
/**
* cleans up the display text and adds the [Debug] prefix too the text
*
* @param msg - display string under 200 chars
* @return
*/
public static String trimForDisplay(String msg)
{
// TODO trim the length to under 255 to prevent crashing
msg = msg.trim();
msg = "[Debug] " + msg;
return msg;
}
}

View file

@ -0,0 +1,47 @@
package dark.library.helpers;
import java.util.Iterator;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import universalelectricity.core.vector.Vector3;
public class PlayerMsgHelper
{
public static void msgAllPlayersInRange(World world, Vector3 loc, double range, String sender, String... msgs)
{
if (world != null && loc != null && msgs != null)
{
String sendMsg = sender + ">>>";
for (int i = 0; i < msgs.length; i++)
{
sendMsg += msgs[i] + ">>>";
}
sendMsg = sendMsg.substring(0, sendMsg.length() > 255 ? 255 : sendMsg.length());
List<EntityPlayer> list = getPlayersInRange(world, loc, range, false);
for (EntityPlayer player : list)
{
player.sendChatToPlayer(sendMsg);
}
}
}
public static List<EntityPlayer> getPlayersInRange(World world, Vector3 loc, double range, boolean canSee)
{
AxisAlignedBB bound = AxisAlignedBB.getBoundingBox(loc.x - range, loc.y - range, loc.z - range, loc.x + range, loc.y + range, loc.z + range);
List<EntityPlayer> list = world.getEntitiesWithinAABB(EntityPlayer.class, bound);
Iterator<EntityPlayer> it = list.iterator();
while (it.hasNext() && canSee)
{
EntityPlayer player = it.next();
if (world.rayTraceBlocks(loc.toVec3(), new Vector3(player).add(new Vector3(0, player.getEyeHeight(), 0)).toVec3()) != null)
{
it.remove();
}
}
return list;
}
}

View file

@ -0,0 +1,6 @@
package dark.library.math;
public class LinearAlg
{
}

View file

@ -0,0 +1,42 @@
package dark.library.math;
import universalelectricity.core.vector.Vector3;
public class OrbitHelper
{
/**
* Get the offset of the center of the circle and object will be if move around the edge of the
* circle so far
*
* @param radus distance of the circle
* @param pos in the circle
* @return change from center of the circle
*/
public Vector3 getRadianPos(float radus, int pos, float spacing)
{
return null;
}
/**
* Gets the spacing in order to to have x number of the same width object orbit a point
*
* @param radus of the circle
* @param width of the object including spacing
* @param number of objects
* @return spacing in radians of the circle
*/
public float getObjectSpacing(double radus, double width, double number)
{
return 0;
}
public Vector3 getCirclePos(int objects, double width, double radius)
{
if (radius < (width + (width / 2)) * objects)
{
radius = (width + width / 2) * objects;
}
float spacing = this.getObjectSpacing(radius, width, objects);
return null;
}
}

View file

@ -186,7 +186,7 @@ public abstract class TileEntityTerminal extends TileEntityRunnableMachine imple
}
catch (Exception e)
{
FMLLog.severe("ICBM: Failed to receive packet for terminal.");
FMLLog.severe("DarkLib>>>TerminalInstance>>>PacketReadError>>>ForTile>>>"+this.toString());
e.printStackTrace();
}
}

View file

@ -22,7 +22,7 @@ public class FluidRestrictionHandler
@ForgeSubscribe
public void onLiquidRegistered(LiquidRegisterEvent event)
{
if (event.Name != null)
if (event != null && event.Name != null)
{
if (event.Name.equalsIgnoreCase("Fuel") && !restrictedStacks.containsKey(ColorCode.YELLOW))
{
@ -46,14 +46,16 @@ public class FluidRestrictionHandler
{
return restrictedStacks.containsKey(ColorCode.get(meta));
}
public static boolean hasRestrictedStack(LiquidStack stack)
{
if(stack == null)
if (stack == null)
{
return false;
}
return restrictedStacks.inverse().containsKey(stack);
}
/**
* gets the liquid stack that is restricted to this color
*

View file

@ -0,0 +1,18 @@
package hydraulic.api;
import net.minecraftforge.liquids.ITankContainer;
import net.minecraftforge.liquids.LiquidStack;
import net.minecraftforge.liquids.LiquidTank;
public interface INetworkFluidPart extends IColorCoded, ITankContainer, INetworkPart
{
/**
* Gets the part's main tank for shared storage
*/
public LiquidTank getTank();
/**
* Sets the content of the part's main tank
*/
public void setTankContent(LiquidStack stack);
}

View file

@ -0,0 +1,27 @@
package hydraulic.api;
import hydraulic.network.TileNetwork;
import net.minecraft.tileentity.TileEntity;
public interface INetworkPart extends ITileConnector
{
/**
* Array of connections this tile has to other tiles
*/
public TileEntity[] getNetworkConnections();
/**
* Update the connection this tile has to other tiles
*/
public void updateNetworkConnections();
/**
* Gets the networkPart's primary network
*/
public TileNetwork getTileNetwork();
/**
* Sets the networkPart's primary network
*/
public void setTileNetwork(TileNetwork fluidNetwok);
}

View file

@ -1,10 +1,6 @@
package hydraulic.fluidnetwork;
package hydraulic.api;
import hydraulic.api.IColorCoded;
import hydraulic.api.IPipeConnection;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.liquids.ILiquidTank;
import net.minecraftforge.liquids.ITankContainer;
import net.minecraftforge.liquids.LiquidStack;
/**
@ -12,34 +8,30 @@ import net.minecraftforge.liquids.LiquidStack;
* that doesn't change the over all network pressure. So pipes, gauges, tubes, buffers, decor
* blocks.
*/
public interface IFluidNetworkPart extends IPipeConnection, IColorCoded, ITankContainer, INetworkPath
public interface INetworkPipe extends INetworkFluidPart
{
/**
* gets the devices pressure from a given side for input
* Gets the parts max pressure limit it can handle
*
* Note this is not recommended max limit by rather actual breaking point of the part
*/
public double getMaxPressure(ForgeDirection side);
/**
* The max amount of liquid that can flow per request
* Max flow rate of liquid flow this part from the side for the liquid type that his part will
* allow
*
* @return limit in bucket parts(1/1000 of a bucket)
*/
public int getMaxFlowRate(LiquidStack stack, ForgeDirection side);
/**
* Called when the pressure on the machine reachs max
* Called when the pressure on the machine goes beyond max limits. Suggest doing random chance
* of damage or break too simulate real chances of pipe going beyond designed limits
*
* @param damageAllowed - can this tileEntity cause grief damage
* @return true if the device over pressured and destroyed itself
*/
public boolean onOverPressure(Boolean damageAllowed);
/**
* size of the pipes liquid storage ability
*/
public int getTankSize();
public ILiquidTank getTank();
public void setTankContent(LiquidStack stack);
}

View file

@ -1,18 +0,0 @@
package hydraulic.api;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
public interface IPipeConnection
{
/**
* This method should only be used by pipe like objects to find if they can connect to this
* object
*
* @param entity - the pipe connecting to this object as a TileEntity instance
* @param dir - side connecting too
*
* @return true if it can connect
*/
public boolean canPipeConnect(TileEntity entity, ForgeDirection dir);
}

View file

@ -6,7 +6,7 @@ package hydraulic.api;
* net.minecraftforge.liquids too make your machine work with other fluid mods that don't use
* pressure
*/
public interface IPsiReciever extends IPipeConnection
public interface IPsiReciever extends ITileConnector
{
/**
* the load that this machine is handling, working, or moving

View file

@ -0,0 +1,12 @@
package hydraulic.api;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
public interface ITileConnector
{
/**
* Can this tile connect on the given side
*/
public boolean canTileConnect(TileEntity entity, ForgeDirection dir);
}

View file

@ -1,700 +0,0 @@
package hydraulic.fluidnetwork;
import hydraulic.api.ColorCode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.liquids.ILiquidTank;
import net.minecraftforge.liquids.ITankContainer;
import net.minecraftforge.liquids.LiquidContainerRegistry;
import net.minecraftforge.liquids.LiquidDictionary;
import net.minecraftforge.liquids.LiquidStack;
import net.minecraftforge.liquids.LiquidTank;
import universalelectricity.core.path.Pathfinder;
import universalelectricity.core.vector.Vector3;
import cpw.mods.fml.common.FMLLog;
import dark.library.helpers.ConnectionHelper;
/**
* Side note: the network should act like this when done {@link http
* ://www.e4training.com/hydraulic_calculators/B1.htm} as well as stay compatible with the forge
* Liquids
*
* @author Rseifert
*
*/
public class HydraulicNetwork
{
/* BLOCK THAT ACT AS FLUID CONVEYORS ** */
public final List<IFluidNetworkPart> fluidParts = new ArrayList<IFluidNetworkPart>();
/* MACHINES THAT USE THE FORGE LIQUID API TO RECEIVE LIQUID ** */
public final List<ITankContainer> fluidTanks = new ArrayList<ITankContainer>();
/* MACHINES THAT USE THE PRESSURE SYSTEM TO DO WORK ** */
private final HashMap<TileEntity, FluidPressurePack> pressureProducers = new HashMap<TileEntity, FluidPressurePack>();
private final HashMap<TileEntity, FluidPressurePack> pressureLoads = new HashMap<TileEntity, FluidPressurePack>();
public ColorCode color = ColorCode.NONE;
/* PRESSURE OF THE NETWORK AS A TOTAL. ZERO AS IN NO PRODUCTION */
public double pressureProduced = 0;
/* PRESSURE OF THE NETWORK'S LOAD AS A TOTAL. ZERO AS IN NO LOAD */
public double pressureLoad = 0;
/* IS IT PROCESSING AN ADD LIQUID EVENT */
private boolean processingRequest = false;
/* COMBINED TEMP STORAGE FOR ALL PIPES IN THE NETWORK */
private LiquidTank combinedStorage = new LiquidTank(LiquidContainerRegistry.BUCKET_VOLUME);
public HydraulicNetwork(ColorCode color, IFluidNetworkPart... parts)
{
this.fluidParts.addAll(Arrays.asList(parts));
this.color = color;
}
/**
* sets this tileEntity to produce a pressure and flow rate in the network
*/
public void startProducingPressure(TileEntity tileEntity, FluidPressurePack fluidPack)
{
if (tileEntity != null && fluidPack.liquidStack != null)
{
if ((this.combinedStorage.getLiquid() == null || fluidPack.liquidStack.isLiquidEqual(this.combinedStorage.getLiquid())) && fluidPack.liquidStack.amount > 0)
{
this.pressureProducers.put(tileEntity, fluidPack);
}
}
}
/**
* sets this tileEntity to produce a pressure and flow rate in the network
*/
public void startProducingPressure(TileEntity tileEntity, LiquidStack stack, double pressure)
{
this.startProducingPressure(tileEntity, new FluidPressurePack(stack, pressure));
}
/**
* is this tile entity producing a pressure
*/
public boolean isProducingPressure(TileEntity tileEntity)
{
return this.pressureProducers.containsKey(tileEntity);
}
/**
* Sets this tile entity to stop producing pressure and flow in this network
*/
public void removeSource(TileEntity tileEntity)
{
this.pressureProducers.remove(tileEntity);
}
/**
* Sets this tile entity to act as a load on the system
*/
public void addLoad(TileEntity tileEntity, FluidPressurePack fluidPack)
{
if (tileEntity != null && fluidPack.liquidStack != null && fluidPack.liquidStack.amount > 0)
{
this.pressureLoads.put(tileEntity, fluidPack);
}
}
/**
* Sets this tile entity to act as a load on the system
*/
public void addLoad(TileEntity tileEntity, LiquidStack stack, double pressure)
{
this.addLoad(tileEntity, new FluidPressurePack(stack, pressure));
}
/**
* is this tileEntity a load in the network
*/
public boolean isLoad(TileEntity tileEntity)
{
return this.pressureLoads.containsKey(tileEntity);
}
/**
* removes this tileEntity from being a load on the network
*/
public void removeLoad(TileEntity tileEntity)
{
this.pressureLoads.remove(tileEntity);
}
/**
* Removes a tileEntity from any of the valid lists
*/
public void removeEntity(TileEntity ent)
{
if (fluidTanks.contains(ent))
{
fluidTanks.remove(ent);
}
this.removeLoad(ent);
this.removeSource(ent);
}
/**
* Adds a tileEntity to the list if its valid
*/
public void addEntity(ITankContainer ent)
{
if (ent == null)
{
return;
}
else if (ent instanceof IFluidNetworkPart)
{
this.addNetworkPart((IFluidNetworkPart) ent);
}
else if (!fluidTanks.contains(ent))
{
fluidTanks.add(ent);
}
}
public void addNetworkPart(IFluidNetworkPart newConductor)
{
this.cleanConductors();
if (newConductor.getColor() == this.color && !fluidParts.contains(newConductor))
{
fluidParts.add(newConductor);
newConductor.setNetwork(this);
}
}
/**
* Checks too see if the tileEntity is part of or connected too the network
*/
public boolean isConnected(TileEntity tileEntity)
{
if (this.fluidParts.contains(tileEntity))
{
return true;
}
else if (this.fluidTanks.contains(tileEntity))
{
return true;
}
else
{
return false;
}
}
/**
* @param ignoreTiles The TileEntities to ignore during this calculation. Null will make it not
* ignore any.
* @return The electricity produced in this electricity network
*/
public double getPressureProduced(TileEntity... ignoreTiles)
{
// TODO pressure is not added as a sum but rather as a collective sum of the largest
// pressures. IF the pressure is to small it will be ignored and stop producing pressure.
int totalPressure = 0;
Iterator it = this.pressureProducers.entrySet().iterator();
loop:
while (it.hasNext())
{
Map.Entry pairs = (Map.Entry) it.next();
if (pairs != null)
{
TileEntity tileEntity = (TileEntity) pairs.getKey();
if (tileEntity == null)
{
it.remove();
continue;
}
if (tileEntity.isInvalid())
{
it.remove();
continue;
}
if (tileEntity.worldObj.getBlockTileEntity(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord) != tileEntity)
{
it.remove();
continue;
}
if (ignoreTiles != null)
{
for (TileEntity ignoreTile : ignoreTiles)
{
if (tileEntity == ignoreTile)
{
continue loop;
}
}
}
FluidPressurePack pack = (FluidPressurePack) pairs.getValue();
if (pairs.getKey() != null && pairs.getValue() != null && pack != null)
{
totalPressure += pack.pressure;
}
}
}
return totalPressure;
}
/**
* Adds FLuid to this network from one of the connected Pipes
*
* @param source - Were this liquid came from
* @param stack - LiquidStack to be sent
* @param doFill - actually fill the tank or just check numbers
* @return the amount of liquid consumed from the init stack
*/
public int addFluidToNetwork(TileEntity source, LiquidStack stack, boolean doFill)
{
return this.addFluidToNetwork(source, stack, doFill, false);
}
/**
* Adds FLuid to this network from one of the connected Pipes
*
* @param source - Were this liquid came from
* @param stack - LiquidStack to be sent
* @param doFill - actually fill the tank or just check numbers
* @param allowStore - allows the network to store this liquid in the pipes
* @return the amount of liquid consumed from the init stack
*/
public int addFluidToNetwork(TileEntity source, LiquidStack stack, boolean doFill, boolean allowStore)
{
int used = 0;
LiquidStack prevCombined = this.combinedStorage.getLiquid();
if (!this.processingRequest && stack != null && color.isValidLiquid(stack))
{
if (this.combinedStorage.getLiquid() != null && !stack.isLiquidEqual(this.combinedStorage.getLiquid()))
{
// TODO cause mixing
}
if (stack.amount > this.getMaxFlow(stack))
{
stack = new LiquidStack(stack.itemID, this.getMaxFlow(stack), stack.itemMeta);
}
/* Main fill target to try to fill with the stack */
ITankContainer primaryFill = null;
int volume = Integer.MAX_VALUE;
ForgeDirection fillDir = ForgeDirection.UNKNOWN;
/* Secondary fill target if the main target is not found */
ITankContainer secondayFill = null;
int mostFill = 0;
ForgeDirection otherFillDir = ForgeDirection.UNKNOWN;
boolean found = false;
/* FIND THE FILL TARGET FROM THE LIST OF FLUID RECIEVERS */
for (ITankContainer tankContainer : fluidTanks)
{
if (tankContainer instanceof TileEntity && tankContainer != source && !(tankContainer instanceof IFluidNetworkPart))
{
TileEntity[] connectedTiles = ConnectionHelper.getSurroundingTileEntities((TileEntity) tankContainer);
for (int i = 0; i < 6; i++)
{
if (connectedTiles[i] instanceof IFluidNetworkPart && ((IFluidNetworkPart) connectedTiles[i]).getNetwork() == this)
{
ForgeDirection dir = ForgeDirection.getOrientation(i).getOpposite();
ILiquidTank targetTank = tankContainer.getTank(dir, stack);
int fill = tankContainer.fill(dir, stack, false);
/* USE GET TANK FROM SIDE METHOD FIRST */
if (targetTank != null)
{
LiquidStack stackStored = targetTank.getLiquid();
if (stackStored == null)
{
primaryFill = tankContainer;
found = true;
fillDir = dir;
break;
}
else if (stackStored.amount < targetTank.getCapacity() && stackStored.amount < volume)
{
primaryFill = tankContainer;
volume = stackStored.amount;
}
}/* USE FILL METHOD IF GET TANK == NULL */
else if (fill > 0 && fill > mostFill)
{
secondayFill = tankContainer;
mostFill = fill;
otherFillDir = dir;
}
}
}
}
if (found)
{
break;
}
}// End of tank finder
boolean filledMain = false;
if (primaryFill != null)
{
used = primaryFill.fill(fillDir, stack, doFill);
//System.out.println("Primary Target " + used + doFill);
}
else if (secondayFill != null)
{
used = secondayFill.fill(fillDir, stack, doFill);
//System.out.println("Seconday Target " + used + doFill);
}
else if (allowStore && (this.combinedStorage.getLiquid() == null || this.combinedStorage.getLiquid().amount < this.combinedStorage.getCapacity()))
{
used = this.combinedStorage.fill(stack, doFill);
//System.out.println("Network Target filled for " + used + doFill);
filledMain = true;
}
/* IF THE COMBINED STORAGE OF THE PIPES HAS LIQUID MOVE IT FIRST */
if (!filledMain && used > 0 && this.combinedStorage.getLiquid() != null && this.combinedStorage.getLiquid().amount > 0)
{
LiquidStack drainStack = new LiquidStack(0, 0, 0);
if (this.combinedStorage.getLiquid().amount >= used)
{
drainStack = this.combinedStorage.drain(used, doFill);
used = 0;
}
else
{
int pUsed = used;
used = Math.min(used, Math.max(used - this.combinedStorage.getLiquid().amount, 0));
drainStack = this.combinedStorage.drain(pUsed - used, doFill);
}
//System.out.println("Pulling " + (drainStack != null ? drainStack.amount : 0) + " from combined leaving " + (this.combinedStorage.getLiquid() != null ? this.combinedStorage.getLiquid().amount : 0));
}
if (prevCombined != null && this.combinedStorage.getLiquid() != null && prevCombined.amount != this.combinedStorage.getLiquid().amount)
{
this.moveAndSumVolume(false);
}
}
this.processingRequest = false;
return used;
}
/**
* gets the flow rate of the network by getting the pipe with the lowest flow rate.
*
* @return units of liquid per tick, default 20B/s
*/
public int getMaxFlow(LiquidStack stack)
{
int flow = 1000;
for (IFluidNetworkPart conductor : this.fluidParts)
{
// TODO change the direction to actual look for connected only directions and pipes
// along
// the path to the target
int cFlow = conductor.getMaxFlowRate(stack, ForgeDirection.UNKNOWN);
if (cFlow < flow)
{
flow = cFlow;
}
}
return flow;
}
public void cleanConductors()
{
for (int i = 0; i < fluidParts.size(); i++)
{
if (fluidParts.get(i) == null)
{
fluidParts.remove(i);
}
else if (((TileEntity) fluidParts.get(i)).isInvalid())
{
fluidParts.remove(i);
}
}
}
public void setNetwork()
{
this.cleanConductors();
for (IFluidNetworkPart conductor : this.fluidParts)
{
conductor.setNetwork(this);
}
}
public void onPresureChange()
{
this.cleanConductors();
for (int i = 0; i < fluidParts.size(); i++)
{
// TODO change to actual check connected sides only && get true value from settings file
IFluidNetworkPart part = fluidParts.get(i);
if (part.getMaxPressure(ForgeDirection.UNKNOWN) < this.pressureProduced && part.onOverPressure(true))
{
this.fluidParts.remove(part);
this.cleanConductors();
}
}
}
public void cleanUpConductors()
{
Iterator it = this.fluidParts.iterator();
int capacity = 0;
while (it.hasNext())
{
IFluidNetworkPart conductor = (IFluidNetworkPart) it.next();
if (conductor == null)
{
it.remove();
}
else if (((TileEntity) conductor).isInvalid())
{
it.remove();
}
else if (conductor.getColor() != this.color)
{
it.remove();
}
else
{
conductor.setNetwork(this);
capacity += LiquidContainerRegistry.BUCKET_VOLUME;
}
}
this.combinedStorage.setCapacity(capacity);
}
/**
* This function is called to refresh all conductors in this network
*/
public void refreshConductors()
{
this.cleanUpConductors();
try
{
Iterator<IFluidNetworkPart> it = this.fluidParts.iterator();
while (it.hasNext())
{
IFluidNetworkPart conductor = it.next();
conductor.updateAdjacentConnections();
}
}
catch (Exception e)
{
FMLLog.severe("Universal Electricity: Failed to refresh conductor.");
e.printStackTrace();
}
}
public List<IFluidNetworkPart> getFluidNetworkParts()
{
return this.fluidParts;
}
public void mergeNetworks(HydraulicNetwork network)
{
if (network != null && network != this && network.color == this.color)
{
if (this.combinedStorage.getLiquid() != null && network.combinedStorage.getLiquid() != null && !this.combinedStorage.getLiquid().isLiquidEqual(network.combinedStorage.getLiquid()))
{
this.causingMixing(this.combinedStorage.getLiquid(), network.combinedStorage.getLiquid());
}
else
{
this.moveAndSumVolume(false);
network.moveAndSumVolume(false);
LiquidStack stack = new LiquidStack(0, 0, 0);
if (this.combinedStorage.getLiquid() != null && network.combinedStorage.getLiquid() != null && this.combinedStorage.getLiquid().isLiquidEqual(network.combinedStorage.getLiquid()))
{
stack = this.combinedStorage.getLiquid();
stack.amount += network.combinedStorage.getLiquid().amount;
}
else if (this.combinedStorage.getLiquid() == null && network.combinedStorage.getLiquid() != null)
{
stack = network.combinedStorage.getLiquid();
}
else if (this.combinedStorage.getLiquid() != null && network.combinedStorage.getLiquid() == null)
{
stack = this.combinedStorage.getLiquid();
}
HydraulicNetwork newNetwork = new HydraulicNetwork(this.color);
newNetwork.getFluidNetworkParts().addAll(this.getFluidNetworkParts());
newNetwork.getFluidNetworkParts().addAll(network.getFluidNetworkParts());
newNetwork.cleanUpConductors();
newNetwork.moveAndSumVolume(true);
}
}
}
public void causingMixing(LiquidStack stack, LiquidStack stack2)
{
// TODO cause mixing of liquids based on types and volume. Also apply damage to pipes/parts
// as needed
}
public void splitNetwork(World world, IFluidNetworkPart splitPoint)
{
if (splitPoint instanceof TileEntity)
{
this.getFluidNetworkParts().remove(splitPoint);
this.moveAndSumVolume(false);
/**
* Loop through the connected blocks and attempt to see if there are connections between
* the two points elsewhere.
*/
TileEntity[] connectedBlocks = splitPoint.getAdjacentConnections();
for (int i = 0; i < connectedBlocks.length; i++)
{
TileEntity connectedBlockA = connectedBlocks[i];
if (connectedBlockA instanceof IFluidNetworkPart)
{
for (int pipeCount = 0; pipeCount < connectedBlocks.length; pipeCount++)
{
final TileEntity connectedBlockB = connectedBlocks[pipeCount];
if (connectedBlockA != connectedBlockB && connectedBlockB instanceof IFluidNetworkPart)
{
Pathfinder finder = new PathfinderCheckerPipes(world, (IFluidNetworkPart) connectedBlockB, splitPoint);
finder.init(new Vector3(connectedBlockA));
if (finder.results.size() > 0)
{
/* STILL CONNECTED SOMEWHERE ELSE */
for (Vector3 node : finder.closedSet)
{
TileEntity entity = node.getTileEntity(world);
if (entity instanceof IFluidNetworkPart)
{
if (node != splitPoint)
{
((IFluidNetworkPart) entity).setNetwork(this);
}
}
}
}
else
{
/* NO LONGER CONNECTED ELSE WHERE SO SPLIT AND REFRESH */
HydraulicNetwork newNetwork = new HydraulicNetwork(this.color);
int parts = 0;
for (Vector3 node : finder.closedSet)
{
TileEntity entity = node.getTileEntity(world);
if (entity instanceof IFluidNetworkPart)
{
if (node != splitPoint)
{
newNetwork.getFluidNetworkParts().add((IFluidNetworkPart) entity);
parts++;
}
}
}
newNetwork.cleanUpConductors();
newNetwork.moveAndSumVolume(true);
}
}
}
}
}
}
}
/**
* Moves the volume stored in the network to the parts or sums up the volume from the parts and
* loads it to the network. Assumes that all liquidStacks stored are equal
*
* @param load - loads the volume from the parts before leveling out the volumes
*/
public void moveAndSumVolume(boolean load)
{
int volume = 0;
int itemID = 0;
int itemMeta = 0;
if (load)
{
for (IFluidNetworkPart part : this.fluidParts)
{
if (part.getTank() != null && part.getTank().getLiquid() != null)
{
if (itemID == 0)
{
itemID = part.getTank().getLiquid().itemID;
itemMeta = part.getTank().getLiquid().itemMeta;
}
volume += part.getTank().getLiquid().amount;
}
}
this.combinedStorage.setLiquid(new LiquidStack(itemID, volume, itemMeta));
}
if (this.combinedStorage.getLiquid() != null && this.fluidParts.size() > 0)
{
volume = this.combinedStorage.getLiquid().amount / this.fluidParts.size();
itemID = this.combinedStorage.getLiquid().itemID;
itemMeta = this.combinedStorage.getLiquid().itemMeta;
for (IFluidNetworkPart part : this.fluidParts)
{
part.setTankContent(null);
part.setTankContent(new LiquidStack(itemID, volume, itemMeta));
}
}
}
@Override
public String toString()
{
return "HydraulicNetwork[" + this.hashCode() + "|parts:" + this.fluidParts.size() + "]";
}
public String getStorageFluid()
{
if (!combinedStorage.containsValidLiquid())
{
return "Zero";
}
return String.format("%d/%d %S Stored", combinedStorage.getLiquid().amount / LiquidContainerRegistry.BUCKET_VOLUME, combinedStorage.getCapacity() / LiquidContainerRegistry.BUCKET_VOLUME, LiquidDictionary.findLiquidName(this.combinedStorage.getLiquid()));
}
public ILiquidTank getTank()
{
if (this.combinedStorage == null)
{
this.combinedStorage = new LiquidTank(0);
}
return this.combinedStorage;
}
}

View file

@ -1,31 +0,0 @@
package hydraulic.fluidnetwork;
import net.minecraft.tileentity.TileEntity;
public interface INetworkPath
{
/**
* Gets a list of all the connected TileEntities that this conductor is connected to. The
* array's length should be always the 6 adjacent wires.
*
* @return
*/
public TileEntity[] getAdjacentConnections();
/**
* Instantly refreshes all connected blocks around the conductor, recalculating the connected
* blocks.
*/
public void updateAdjacentConnections();
/**
* The Fluid network that this machine is part of
*/
public HydraulicNetwork getNetwork();
/**
* sets the machines network
*/
public void setNetwork(HydraulicNetwork network);
}

View file

@ -13,7 +13,7 @@ import universalelectricity.core.vector.VectorHelper;
*
* @author DarkGuardsman
*/
public class FillDrainHelper
public class TankHelper
{
/**
* Fills all ITankContainers around the point
@ -29,7 +29,7 @@ public class FillDrainHelper
int fill = 0;
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS)
{
fill += FillDrainHelper.fillDirection(world, center, stack, direction);
fill += TankHelper.fillDirection(world, center, stack, direction);
}
return fill;
}

View file

@ -0,0 +1,15 @@
package hydraulic.network;
/**
* Side note: the network should act like this when done {@link http
* ://www.e4training.com/hydraulic_calculators/B1.htm} as well as stay compatible with the forge
* Liquids
*
* @author Rseifert
*
*/
public class ContainerNetwork
{
}

View file

@ -0,0 +1,295 @@
package hydraulic.network;
import hydraulic.api.ColorCode;
import hydraulic.api.INetworkFluidPart;
import hydraulic.api.INetworkPart;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.liquids.ILiquidTank;
import net.minecraftforge.liquids.ITankContainer;
import net.minecraftforge.liquids.LiquidContainerRegistry;
import net.minecraftforge.liquids.LiquidDictionary;
import net.minecraftforge.liquids.LiquidStack;
import net.minecraftforge.liquids.LiquidTank;
import universalelectricity.core.path.Pathfinder;
import universalelectricity.core.vector.Vector3;
import cpw.mods.fml.common.FMLLog;
public class FluidNetwork extends TileNetwork
{
/* MACHINES THAT USE THE FORGE LIQUID API TO RECEIVE LIQUID ** */
public final List<ITankContainer> fluidTanks = new ArrayList<ITankContainer>();
/* COMBINED TEMP STORAGE FOR ALL PIPES IN THE NETWORK */
public LiquidTank combinedStorage = new LiquidTank(LiquidContainerRegistry.BUCKET_VOLUME);
public ColorCode color = ColorCode.NONE;
public FluidNetwork(ColorCode color, INetworkPart... parts)
{
super(parts);
this.color = color;
}
/**
* Moves the volume stored in the network to the parts or sums up the volume from the parts and
* loads it to the network. Assumes that all liquidStacks stored are equal
*
* @param sumParts - loads the volume from the parts before leveling out the volumes
*/
public void balanceColletiveTank(boolean sumParts)
{
int volume = 0, itemID = 0, itemMeta = 0;
if (sumParts)
{
for (INetworkPart par : this.networkMember)
{
if (par instanceof INetworkFluidPart)
{
INetworkFluidPart part = ((INetworkFluidPart) par);
if (part.getTank() != null && part.getTank().getLiquid() != null)
{
if (itemID == 0)
{
itemID = part.getTank().getLiquid().itemID;
itemMeta = part.getTank().getLiquid().itemMeta;
}
volume += part.getTank().getLiquid().amount;
}
}
}
this.combinedStorage.setLiquid(new LiquidStack(itemID, volume, itemMeta));
}
if (this.combinedStorage.getLiquid() != null && this.networkMember.size() > 0)
{
volume = this.combinedStorage.getLiquid().amount / this.networkMember.size();
itemID = this.combinedStorage.getLiquid().itemID;
itemMeta = this.combinedStorage.getLiquid().itemMeta;
for (INetworkPart par : this.networkMember)
{
if (par instanceof INetworkFluidPart)
{
INetworkFluidPart part = ((INetworkFluidPart) par);
part.setTankContent(null);
part.setTankContent(new LiquidStack(itemID, volume, itemMeta));
}
}
}
}
@Override
public void removeEntity(TileEntity ent)
{
super.removeEntity(ent);
this.fluidTanks.remove(ent);
}
@Override
public boolean addEntity(TileEntity ent, boolean member)
{
if (!(super.addEntity(ent, member)) && ent instanceof ITankContainer && !fluidTanks.contains(ent))
{
fluidTanks.add((ITankContainer) ent);
return true;
}
return false;
}
/**
* Checks too see if the tileEntity is part of or connected too the network
*/
public boolean isConnected(TileEntity tileEntity)
{
return this.fluidTanks.contains(tileEntity);
}
public boolean isPartOfNetwork(TileEntity ent)
{
return super.isPartOfNetwork(ent) || this.fluidTanks.contains(ent);
}
public void causingMixing(LiquidStack stack, LiquidStack stack2)
{
// TODO cause mixing of liquids based on types and volume. Also apply damage to pipes/parts
// as needed
}
public void splitNetwork(World world, INetworkPart splitPoint)
{
if (splitPoint instanceof TileEntity)
{
this.getNetworkMemebers().remove(splitPoint);
this.balanceColletiveTank(false);
/**
* Loop through the connected blocks and attempt to see if there are connections between
* the two points elsewhere.
*/
TileEntity[] connectedBlocks = splitPoint.getNetworkConnections();
for (int i = 0; i < connectedBlocks.length; i++)
{
TileEntity connectedBlockA = connectedBlocks[i];
if (connectedBlockA instanceof INetworkPart)
{
for (int pipeCount = 0; pipeCount < connectedBlocks.length; pipeCount++)
{
final TileEntity connectedBlockB = connectedBlocks[pipeCount];
if (connectedBlockA != connectedBlockB && connectedBlockB instanceof INetworkPart)
{
Pathfinder finder = new PathfinderCheckerPipes(world, (INetworkPart) connectedBlockB, splitPoint);
finder.init(new Vector3(connectedBlockA));
if (finder.results.size() > 0)
{
/* STILL CONNECTED SOMEWHERE ELSE */
for (Vector3 node : finder.closedSet)
{
TileEntity entity = node.getTileEntity(world);
if (entity instanceof INetworkPart)
{
if (node != splitPoint)
{
((INetworkPart) entity).setTileNetwork(this);
}
}
}
}
else
{
/* NO LONGER CONNECTED ELSE WHERE SO SPLIT AND REFRESH */
PipeNetwork newNetwork = new PipeNetwork(this.color);
int parts = 0;
for (Vector3 node : finder.closedSet)
{
TileEntity entity = node.getTileEntity(world);
if (entity instanceof INetworkPart)
{
if (node != splitPoint)
{
newNetwork.getNetworkMemebers().add((INetworkPart) entity);
parts++;
}
}
}
newNetwork.cleanUpConductors();
newNetwork.balanceColletiveTank(true);
}
}
}
}
}
}
}
@Override
public boolean preMergeProcessing(TileNetwork net)
{
if (net instanceof FluidNetwork && ((FluidNetwork)net).color == this.color)
{
FluidNetwork network = (FluidNetwork) net;
if (this.combinedStorage.getLiquid() != null && network.combinedStorage.getLiquid() != null && !this.combinedStorage.getLiquid().isLiquidEqual(network.combinedStorage.getLiquid()))
{
this.causingMixing(this.combinedStorage.getLiquid(), network.combinedStorage.getLiquid());
}
else
{
this.balanceColletiveTank(false);
network.balanceColletiveTank(false);
LiquidStack stack = new LiquidStack(0, 0, 0);
if (this.combinedStorage.getLiquid() != null && network.combinedStorage.getLiquid() != null && this.combinedStorage.getLiquid().isLiquidEqual(network.combinedStorage.getLiquid()))
{
stack = this.combinedStorage.getLiquid();
stack.amount += network.combinedStorage.getLiquid().amount;
}
else if (this.combinedStorage.getLiquid() == null && network.combinedStorage.getLiquid() != null)
{
stack = network.combinedStorage.getLiquid();
}
else if (this.combinedStorage.getLiquid() != null && network.combinedStorage.getLiquid() == null)
{
stack = this.combinedStorage.getLiquid();
}
}
return true;
}
return false;
}
@Override
public void postMergeProcessing(TileNetwork network)
{
FluidNetwork newNetwork = new FluidNetwork(this.color);
newNetwork.getNetworkMemebers().addAll(this.getNetworkMemebers());
newNetwork.getNetworkMemebers().addAll(network.getNetworkMemebers());
newNetwork.cleanUpConductors();
newNetwork.balanceColletiveTank(true);
}
public void refresh()
{
this.cleanUpConductors();
int capacity = 0;
try
{
Iterator<INetworkPart> it = this.networkMember.iterator();
while (it.hasNext())
{
INetworkPart conductor = it.next();
conductor.updateNetworkConnections();
capacity += LiquidContainerRegistry.BUCKET_VOLUME;
}
this.combinedStorage.setCapacity(capacity);
}
catch (Exception e)
{
FMLLog.severe("FluidNetwork>>>Refresh>>>Critical Error.");
e.printStackTrace();
}
}
public boolean isValidMember(INetworkPart part)
{
return super.isValidMember(part) && part instanceof INetworkFluidPart && ((INetworkFluidPart) part).getColor() == this.color;
}
@Override
public String toString()
{
return "FluidNetwork[" + this.hashCode() + "|parts:" + this.networkMember.size() + "]";
}
public String getNetworkFluid()
{
if (!combinedStorage.containsValidLiquid())
{
return "Zero";
}
return String.format("%d/%d %S Stored", combinedStorage.getLiquid().amount / LiquidContainerRegistry.BUCKET_VOLUME, combinedStorage.getCapacity() / LiquidContainerRegistry.BUCKET_VOLUME, LiquidDictionary.findLiquidName(this.combinedStorage.getLiquid()));
}
public ILiquidTank getNetworkTank()
{
if (this.combinedStorage == null)
{
this.combinedStorage = new LiquidTank(0);
}
return this.combinedStorage;
}
}

View file

@ -1,4 +1,4 @@
package hydraulic.fluidnetwork;
package hydraulic.network;
import net.minecraftforge.liquids.LiquidStack;

View file

@ -1,7 +1,7 @@
package hydraulic.fluidnetwork;
package hydraulic.network;
import hydraulic.api.IDrain;
import hydraulic.api.INetworkPart;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.liquids.ITankContainer;
@ -21,18 +21,18 @@ public class HydraulicNetworkHelper
ForgeDirection direction = ForgeDirection.getOrientation(i);
TileEntity checkTile = VectorHelper.getConnectorFromSide(tileEntity.worldObj, new Vector3(tileEntity), direction);
if (checkTile instanceof IFluidNetworkPart)
if (checkTile instanceof INetworkPart)
{
HydraulicNetwork network = ((IFluidNetworkPart) checkTile).getNetwork();
TileNetwork network = ((INetworkPart) checkTile).getTileNetwork();
if (network != null)
if (network != null && network instanceof FluidNetwork)
{
network.removeEntity(tileEntity);
for(ITankContainer tank : network.fluidTanks)
for (ITankContainer tank : ((FluidNetwork) network).fluidTanks)
{
if(tank instanceof IDrain)
if (tank instanceof IDrain)
{
((IDrain)tank).stopRequesting(tileEntity);
((IDrain) tank).stopRequesting(tileEntity);
}
}
}

View file

@ -1,4 +1,7 @@
package hydraulic.fluidnetwork;
package hydraulic.network;
import hydraulic.api.INetworkPart;
import hydraulic.api.INetworkPipe;
import java.util.Arrays;
import java.util.HashSet;
@ -16,7 +19,7 @@ import universalelectricity.core.vector.Vector3;
*/
public class PathfinderCheckerPipes extends Pathfinder
{
public PathfinderCheckerPipes(final World world, final IFluidNetworkPart targetConnector, final IFluidNetworkPart... ignoreConnector)
public PathfinderCheckerPipes(final World world, final INetworkPart connectedBlockB, final INetworkPart splitPoint)
{
super(new IPathCallBack()
{
@ -31,9 +34,9 @@ public class PathfinderCheckerPipes extends Pathfinder
Vector3 position = currentNode.clone().modifyPositionFromSide(direction);
TileEntity connectedBlock = position.getTileEntity(world);
if (connectedBlock instanceof IFluidNetworkPart && !Arrays.asList(ignoreConnector).contains(connectedBlock))
if (connectedBlock instanceof INetworkPipe && !Arrays.asList(splitPoint).contains(connectedBlock))
{
if (((IFluidNetworkPart) connectedBlock).canPipeConnect(connectedBlock, direction.getOpposite()))
if (((INetworkPipe) connectedBlock).canTileConnect(connectedBlock, direction.getOpposite()))
{
neighbors.add(position);
}
@ -46,7 +49,7 @@ public class PathfinderCheckerPipes extends Pathfinder
@Override
public boolean onSearch(Pathfinder finder, Vector3 node)
{
if (node.getTileEntity(world) == targetConnector)
if (node.getTileEntity(world) == connectedBlockB)
{
finder.results.add(node);
return true;

View file

@ -0,0 +1,360 @@
package hydraulic.network;
import hydraulic.api.ColorCode;
import hydraulic.api.INetworkPart;
import hydraulic.api.INetworkPipe;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.liquids.ILiquidTank;
import net.minecraftforge.liquids.ITankContainer;
import net.minecraftforge.liquids.LiquidStack;
import dark.library.helpers.ConnectionHelper;
/**
* Side note: the network should act like this when done {@link http
* ://www.e4training.com/hydraulic_calculators/B1.htm} as well as stay compatible with the forge
* Liquids
*
* @author Rseifert
*
*/
public class PipeNetwork extends FluidNetwork
{
/* MACHINES THAT USE THE PRESSURE SYSTEM TO DO WORK ** */
private final HashMap<TileEntity, FluidPressurePack> pressureProducers = new HashMap<TileEntity, FluidPressurePack>();
private final HashMap<TileEntity, FluidPressurePack> pressureLoads = new HashMap<TileEntity, FluidPressurePack>();
/* PRESSURE OF THE NETWORK AS A TOTAL. ZERO AS IN NO PRESSURE */
public double pressureProduced = 0, pressureLoad = 0;
/* IS IT PROCESSING AN ADD LIQUID EVENT */
private boolean processingRequest = false;
public PipeNetwork(ColorCode color, INetworkPart... parts)
{
super(color, parts);
}
public boolean isPartOfNetwork(TileEntity ent)
{
return super.isPartOfNetwork(ent) || this.pressureLoads.containsKey(ent) || this.pressureProducers.containsKey(ent);
}
/**
* sets this tileEntity to produce a pressure and flow rate in the network
*/
public void startProducingPressure(TileEntity tileEntity, FluidPressurePack fluidPack)
{
if (tileEntity != null && fluidPack.liquidStack != null)
{
if ((this.combinedStorage.getLiquid() == null || fluidPack.liquidStack.isLiquidEqual(this.combinedStorage.getLiquid())) && fluidPack.liquidStack.amount > 0)
{
this.pressureProducers.put(tileEntity, fluidPack);
}
}
}
/**
* sets this tileEntity to produce a pressure and flow rate in the network
*/
public void startProducingPressure(TileEntity tileEntity, LiquidStack stack, double pressure)
{
this.startProducingPressure(tileEntity, new FluidPressurePack(stack, pressure));
}
/**
* is this tile entity producing a pressure
*/
public boolean isProducingPressure(TileEntity tileEntity)
{
return this.pressureProducers.containsKey(tileEntity);
}
/**
* Sets this tile entity to act as a load on the system
*/
public void addLoad(TileEntity tileEntity, FluidPressurePack fluidPack)
{
if (tileEntity != null && fluidPack.liquidStack != null && fluidPack.liquidStack.amount > 0)
{
this.pressureLoads.put(tileEntity, fluidPack);
}
}
/**
* Sets this tile entity to act as a load on the system
*/
public void addLoad(TileEntity tileEntity, LiquidStack stack, double pressure)
{
this.addLoad(tileEntity, new FluidPressurePack(stack, pressure));
}
/**
* is this tileEntity a load in the network
*/
public boolean isLoad(TileEntity tileEntity)
{
return this.pressureLoads.containsKey(tileEntity);
}
/**
* @param ignoreTiles The TileEntities to ignore during this calculation. Null will make it not
* ignore any.
* @return The electricity produced in this electricity network
*/
public double getPressureProduced(TileEntity... ignoreTiles)
{
// TODO pressure is not added as a sum but rather as a collective sum of the largest
// pressures. IF the pressure is to small it will be ignored and stop producing pressure.
int totalPressure = 0;
Iterator it = this.pressureProducers.entrySet().iterator();
loop:
while (it.hasNext())
{
Map.Entry pairs = (Map.Entry) it.next();
if (pairs != null)
{
TileEntity tileEntity = (TileEntity) pairs.getKey();
if (tileEntity == null)
{
it.remove();
continue;
}
if (tileEntity.isInvalid())
{
it.remove();
continue;
}
if (tileEntity.worldObj.getBlockTileEntity(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord) != tileEntity)
{
it.remove();
continue;
}
if (ignoreTiles != null)
{
for (TileEntity ignoreTile : ignoreTiles)
{
if (tileEntity == ignoreTile)
{
continue loop;
}
}
}
FluidPressurePack pack = (FluidPressurePack) pairs.getValue();
if (pairs.getKey() != null && pairs.getValue() != null && pack != null)
{
totalPressure += pack.pressure;
}
}
}
return totalPressure;
}
@Override
public void removeEntity(TileEntity ent)
{
super.removeEntity(ent);
this.pressureLoads.remove(ent);
this.pressureProducers.remove(ent);
}
/**
* Adds FLuid to this network from one of the connected Pipes
*
* @param source - Were this liquid came from
* @param stack - LiquidStack to be sent
* @param doFill - actually fill the tank or just check numbers
* @return the amount of liquid consumed from the init stack
*/
public int addFluidToNetwork(TileEntity source, LiquidStack stack, boolean doFill)
{
return this.addFluidToNetwork(source, stack, doFill, false);
}
/**
* Adds FLuid to this network from one of the connected Pipes
*
* @param source - Were this liquid came from
* @param stack - LiquidStack to be sent
* @param doFill - actually fill the tank or just check numbers
* @param allowStore - allows the network to store this liquid in the pipes
* @return the amount of liquid consumed from the init stack
*/
public int addFluidToNetwork(TileEntity source, LiquidStack stack, boolean doFill, boolean allowStore)
{
int used = 0;
LiquidStack prevCombined = this.combinedStorage.getLiquid();
if (!this.processingRequest && stack != null && color.isValidLiquid(stack))
{
if (this.combinedStorage.getLiquid() != null && !stack.isLiquidEqual(this.combinedStorage.getLiquid()))
{
// TODO cause mixing
}
if (stack.amount > this.getMaxFlow(stack))
{
stack = new LiquidStack(stack.itemID, this.getMaxFlow(stack), stack.itemMeta);
}
/* Main fill target to try to fill with the stack */
ITankContainer primaryFill = null;
int volume = Integer.MAX_VALUE;
ForgeDirection fillDir = ForgeDirection.UNKNOWN;
/* Secondary fill target if the main target is not found */
ITankContainer secondayFill = null;
int mostFill = 0;
ForgeDirection otherFillDir = ForgeDirection.UNKNOWN;
boolean found = false;
/* FIND THE FILL TARGET FROM THE LIST OF FLUID RECIEVERS */
for (ITankContainer tankContainer : fluidTanks)
{
if (tankContainer instanceof TileEntity && tankContainer != source && !(tankContainer instanceof INetworkPipe))
{
TileEntity[] connectedTiles = ConnectionHelper.getSurroundingTileEntities((TileEntity) tankContainer);
for (int i = 0; i < 6; i++)
{
if (connectedTiles[i] instanceof INetworkPipe && ((INetworkPipe) connectedTiles[i]).getTileNetwork() == this)
{
ForgeDirection dir = ForgeDirection.getOrientation(i).getOpposite();
ILiquidTank targetTank = tankContainer.getTank(dir, stack);
int fill = tankContainer.fill(dir, stack, false);
/* USE GET TANK FROM SIDE METHOD FIRST */
if (targetTank != null)
{
LiquidStack stackStored = targetTank.getLiquid();
if (stackStored == null)
{
primaryFill = tankContainer;
found = true;
fillDir = dir;
break;
}
else if (stackStored.amount < targetTank.getCapacity() && stackStored.amount < volume)
{
primaryFill = tankContainer;
volume = stackStored.amount;
}
}/* USE FILL METHOD IF GET TANK == NULL */
else if (fill > 0 && fill > mostFill)
{
secondayFill = tankContainer;
mostFill = fill;
otherFillDir = dir;
}
}
}
}
if (found)
{
break;
}
}// End of tank finder
boolean filledMain = false;
if (primaryFill != null)
{
used = primaryFill.fill(fillDir, stack, doFill);
// System.out.println("Primary Target " + used + doFill);
}
else if (secondayFill != null)
{
used = secondayFill.fill(fillDir, stack, doFill);
// System.out.println("Seconday Target " + used + doFill);
}
else if (allowStore && (this.combinedStorage.getLiquid() == null || this.combinedStorage.getLiquid().amount < this.combinedStorage.getCapacity()))
{
used = this.combinedStorage.fill(stack, doFill);
// System.out.println("Network Target filled for " + used + doFill);
filledMain = true;
}
/* IF THE COMBINED STORAGE OF THE PIPES HAS LIQUID MOVE IT FIRST */
if (!filledMain && used > 0 && this.combinedStorage.getLiquid() != null && this.combinedStorage.getLiquid().amount > 0)
{
LiquidStack drainStack = new LiquidStack(0, 0, 0);
if (this.combinedStorage.getLiquid().amount >= used)
{
drainStack = this.combinedStorage.drain(used, doFill);
used = 0;
}
else
{
int pUsed = used;
used = Math.min(used, Math.max(used - this.combinedStorage.getLiquid().amount, 0));
drainStack = this.combinedStorage.drain(pUsed - used, doFill);
}
// System.out.println("Pulling " + (drainStack != null ? drainStack.amount : 0) +
// " from combined leaving " + (this.combinedStorage.getLiquid() != null ?
// this.combinedStorage.getLiquid().amount : 0));
}
if (prevCombined != null && this.combinedStorage.getLiquid() != null && prevCombined.amount != this.combinedStorage.getLiquid().amount)
{
this.balanceColletiveTank(false);
}
}
this.processingRequest = false;
return used;
}
/**
* gets the flow rate of the network by getting the pipe with the lowest flow rate.
*
* @return units of liquid per tick, default 20B/s
*/
public int getMaxFlow(LiquidStack stack)
{
int flow = 1000;
for (INetworkPart conductor : this.networkMember)
{
if (conductor instanceof INetworkPipe)
{
int cFlow = ((INetworkPipe) conductor).getMaxFlowRate(stack, ForgeDirection.UNKNOWN);
if (cFlow < flow)
{
flow = cFlow;
}
}
}
return flow;
}
public void onPresureChange()
{
this.cleanUpConductors();
for (int i = 0; i < networkMember.size(); i++)
{
if (networkMember.get(i) instanceof INetworkPipe)
{
INetworkPipe part = (INetworkPipe) networkMember.get(i);
if (part.getMaxPressure(ForgeDirection.UNKNOWN) < this.pressureProduced && part.onOverPressure(true))
{
this.networkMember.remove(part);
this.cleanUpConductors();
}
}
}
}
}

View file

@ -0,0 +1,254 @@
package hydraulic.network;
import hydraulic.api.INetworkPart;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import universalelectricity.core.path.Pathfinder;
import universalelectricity.core.vector.Vector3;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import cpw.mods.fml.common.FMLLog;
public class TileNetwork
{
/* BLOCK THAT ACT AS FLUID CONVEYORS ** */
public final List<INetworkPart> networkMember = new ArrayList<INetworkPart>();
public TileNetwork(INetworkPart... parts)
{
this.networkMember.addAll(Arrays.asList(parts));
}
/**
* Adds a TileEntity to the network
*
* @param ent - tileEntity instance
* @param member - add to network member list
* @return
*/
public boolean addEntity(TileEntity ent, boolean member)
{
if (ent == null || this.isPartOfNetwork(ent))
{
return false;
}
else if (ent instanceof INetworkPart && member)
{
return this.addNetworkPart((INetworkPart) ent);
}
return false;
}
public boolean isPartOfNetwork(TileEntity ent)
{
return this.networkMember.contains(ent);
}
/**
* Adds a new part to the network member list
*/
public boolean addNetworkPart(INetworkPart part)
{
if (!networkMember.contains(part) && this.isValidMember(part))
{
networkMember.add(part);
part.setTileNetwork(this);
this.cleanUpConductors();
return true;
}
return false;
}
/**
* Removes a tileEntity from any of the valid lists
*/
public void removeEntity(TileEntity ent)
{
this.networkMember.remove(ent);
}
/**
* Cleans the list of networkMembers and remove those that no longer belong
*/
public void cleanUpConductors()
{
Iterator<INetworkPart> it = this.networkMember.iterator();
while (it.hasNext())
{
INetworkPart part = it.next();
if (!this.isValidMember(part))
{
it.remove();
}
else
{
part.setTileNetwork(this);
}
}
}
/**
* Is this part a valid member of the network
*/
public boolean isValidMember(INetworkPart part)
{
return part != null && part instanceof TileEntity && !((TileEntity) part).isInvalid();
}
/**
* Refreshes the network... mainly the network member list
*/
public void refresh()
{
this.cleanUpConductors();
try
{
Iterator<INetworkPart> it = this.networkMember.iterator();
while (it.hasNext())
{
INetworkPart conductor = it.next();
conductor.updateNetworkConnections();
}
}
catch (Exception e)
{
FMLLog.severe("TileNetwork>>>Refresh>>>Critical Error.");
e.printStackTrace();
}
}
/**
* Gets the list of network members
*/
public List<INetworkPart> getNetworkMemebers()
{
return this.networkMember;
}
/**
* Combines two networks together into one
*
* @param network
*/
public void merge(TileNetwork network)
{
if (network != null && network != this && network.getClass().equals(this.getClass()))
{
if (this.preMergeProcessing(network))
{
this.postMergeProcessing(network);
}
}
}
/**
* Processing that needs too be done before the network merges
*
* @return false if the merge needs to be canceled
*/
public boolean preMergeProcessing(TileNetwork network)
{
return true;
}
/**
* Finalizing the merge of two networks by creating the new network and importing all network
* parts
*/
public void postMergeProcessing(TileNetwork network)
{
TileNetwork newNetwork = new TileNetwork();
newNetwork.getNetworkMemebers().addAll(this.getNetworkMemebers());
newNetwork.getNetworkMemebers().addAll(network.getNetworkMemebers());
newNetwork.cleanUpConductors();
// newNetwork.balanceColletiveTank(true);
}
/**
* Called when a peace of the network is remove from the network. Will split the network if it
* can no longer find a valid connection too all parts
*/
public void splitNetwork(World world, INetworkPart splitPoint)
{
if (splitPoint instanceof TileEntity)
{
this.getNetworkMemebers().remove(splitPoint);
/**
* Loop through the connected blocks and attempt to see if there are connections between
* the two points elsewhere.
*/
TileEntity[] connectedBlocks = splitPoint.getNetworkConnections();
for (int i = 0; i < connectedBlocks.length; i++)
{
TileEntity connectedBlockA = connectedBlocks[i];
if (connectedBlockA instanceof INetworkPart)
{
for (int pipeCount = 0; pipeCount < connectedBlocks.length; pipeCount++)
{
final TileEntity connectedBlockB = connectedBlocks[pipeCount];
if (connectedBlockA != connectedBlockB && connectedBlockB instanceof INetworkPart)
{
Pathfinder finder = new PathfinderCheckerPipes(world, (INetworkPart) connectedBlockB, splitPoint);
finder.init(new Vector3(connectedBlockA));
if (finder.results.size() > 0)
{
/* STILL CONNECTED SOMEWHERE ELSE */
for (Vector3 node : finder.closedSet)
{
TileEntity entity = node.getTileEntity(world);
if (entity instanceof INetworkPart)
{
if (node != splitPoint)
{
((INetworkPart) entity).setTileNetwork(this);
}
}
}
}
else
{
/* NO LONGER CONNECTED ELSE WHERE SO SPLIT AND REFRESH */
TileNetwork newNetwork = new TileNetwork();
int parts = 0;
for (Vector3 node : finder.closedSet)
{
TileEntity entity = node.getTileEntity(world);
if (entity instanceof INetworkPart)
{
if (node != splitPoint)
{
newNetwork.getNetworkMemebers().add((INetworkPart) entity);
parts++;
}
}
}
newNetwork.cleanUpConductors();
}
}
}
}
}
}
}
@Override
public String toString()
{
return "TileNetwork[" + this.hashCode() + "|parts:" + this.networkMember.size() + "]";
}
}

View file

@ -1,8 +1,8 @@
package hydraulic.prefab.tile;
import hydraulic.api.IPipeConnection;
import hydraulic.api.ITileConnector;
import hydraulic.api.IReadOut;
import hydraulic.fluidnetwork.HydraulicNetworkHelper;
import hydraulic.network.HydraulicNetworkHelper;
import java.util.Random;
@ -12,7 +12,7 @@ import net.minecraftforge.liquids.ITankContainer;
import net.minecraftforge.liquids.LiquidStack;
import universalelectricity.prefab.tile.TileEntityAdvanced;
public abstract class TileEntityFluidDevice extends TileEntityAdvanced implements IReadOut, IPipeConnection
public abstract class TileEntityFluidDevice extends TileEntityAdvanced implements IReadOut, ITileConnector
{
public Random random = new Random();

View file

@ -34,9 +34,13 @@ public abstract class TileEntityFluidStorage extends TileEntityFluidDevice imple
}
@Override
public boolean canPipeConnect(TileEntity entity, ForgeDirection dir)
public boolean canTileConnect(TileEntity entity, ForgeDirection dir)
{
return true;
if (entity instanceof ITankContainer)
{
return true;
}
return false;
}
@Override