Finished new node grid

This commit is contained in:
Calclavia 2014-03-05 19:37:24 +08:00
parent f90c513986
commit 61aec43d44
12 changed files with 192 additions and 171 deletions

View file

@ -47,18 +47,6 @@ public class BlockConveyorBelt extends BlockTile
} }
} }
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, int par5)
{
TileEntity t = world.getBlockTileEntity(x, y, z);
if (t != null && t instanceof TileConveyorBelt)
{
TileConveyorBelt tileEntity = (TileConveyorBelt) t;
tileEntity.mechanicalNode.reconstruct();
}
}
@Override @Override
public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z)
{ {

View file

@ -1,30 +0,0 @@
package resonantinduction.mechanical.energy.network;
import resonantinduction.core.grid.NodeGrid;
import universalelectricity.core.net.NetworkTickHandler;
/**
* A mechanical network for translate speed and force using mechanical rotations.
*
* Useful Formula:
*
* Power is the work per unit time.
* Power (W) = Torque (Strength of the rotation, Newton Meters) x Speed (Angular Velocity, RADIAN
* PER SECOND).
* *OR*
* Power = Torque / Time
*
* Torque = r (Radius) * F (Force) * sin0 (Direction/Angle of the force applied. 90 degrees if
* optimal.)
*
* @author Calclavia
*/
public class MechanicalNetwork extends NodeGrid<MechanicalNode>
{
public MechanicalNetwork(MechanicalNode node)
{
super(MechanicalNode.class);
add(node);
NetworkTickHandler.addNetwork(this);
}
}

View file

@ -1,22 +1,35 @@
package resonantinduction.mechanical.energy.network; package resonantinduction.mechanical.energy.network;
import java.util.AbstractMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.WeakHashMap;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.ForgeDirection;
import resonantinduction.core.grid.IGrid; import resonantinduction.core.grid.Grid;
import resonantinduction.core.grid.TickingGrid;
import universalelectricity.api.vector.Vector3; import universalelectricity.api.vector.Vector3;
import codechicken.multipart.TMultiPart; import codechicken.multipart.TMultiPart;
/**
* A mechanical node for mechanical energy.
*
* Useful Formula:
*
* Power is the work per unit time.
* Power (W) = Torque (Strength of the rotation, Newton Meters) x Speed (Angular Velocity, RADIAN
* PER SECOND).
* *OR*
* Power = Torque / Time
*
* Torque = r (Radius) * F (Force) * sin0 (Direction/Angle of the force applied. 90 degrees if
* optimal.)
*
* @author Calclavia
*/
public class MechanicalNode extends EnergyNode public class MechanicalNode extends EnergyNode
{ {
protected final AbstractMap<MechanicalNode, ForgeDirection> connections = new WeakHashMap<MechanicalNode, ForgeDirection>();
public final IMechanicalNodeProvider parent; public final IMechanicalNodeProvider parent;
public double torque = 0; public double torque = 0;
@ -54,7 +67,7 @@ public class MechanicalNode extends EnergyNode
public void update(float deltaTime) public void update(float deltaTime)
{ {
power = getEnergy() / deltaTime; power = getEnergy() / deltaTime;
prevAngularVelocity = angularVelocity; prevAngularVelocity = angularVelocity;
onUpdate(); onUpdate();
@ -71,7 +84,7 @@ public class MechanicalNode extends EnergyNode
if (world() != null && !world().isRemote) if (world() != null && !world().isRemote)
{ {
double acceleration = this.acceleration * deltaTime; double acceleration = this.acceleration * deltaTime;
System.out.println("UPDATED");
/** /**
* Loss energy * Loss energy
*/ */
@ -190,12 +203,6 @@ System.out.println("UPDATED");
} }
} }
@Override
public AbstractMap<MechanicalNode, ForgeDirection> getConnections()
{
return connections;
}
public World world() public World world()
{ {
return parent instanceof TMultiPart ? ((TMultiPart) parent).world() : parent instanceof TileEntity ? ((TileEntity) parent).getWorldObj() : null; return parent instanceof TMultiPart ? ((TMultiPart) parent).world() : parent instanceof TileEntity ? ((TileEntity) parent).getWorldObj() : null;
@ -224,9 +231,9 @@ System.out.println("UPDATED");
} }
@Override @Override
public IGrid newGrid() public Grid newGrid()
{ {
return new MechanicalNetwork(this); return new TickingGrid<MechanicalNode>(this);
} }
@Override @Override

View file

@ -79,22 +79,10 @@ public abstract class PartMechanical extends JCuboidPart implements JNormalOcclu
node.reconstruct(); node.reconstruct();
} }
@Override
public void onNeighborChanged()
{
node.reconstruct();
}
@Override
public void onPartChanged(TMultiPart part)
{
node.reconstruct();
}
@Override @Override
public void onWorldSeparate() public void onWorldSeparate()
{ {
node.split(); node.deconstruct();
} }
/** Packet Code. */ /** Packet Code. */

View file

@ -57,7 +57,7 @@ public class TileMechanicalTurbine extends TileTurbine implements IMechanicalNod
@Override @Override
public void invalidate() public void invalidate()
{ {
node.split(); node.deconstruct();
super.invalidate(); super.invalidate();
} }

View file

@ -16,7 +16,7 @@ import universalelectricity.core.net.ConnectionPathfinder;
* *
* @param <N> - The node type. * @param <N> - The node type.
*/ */
public abstract class Grid<N> implements IGrid<N> public abstract class Grid<N>
{ {
/** /**
* A set of connectors (e.g conductors). * A set of connectors (e.g conductors).
@ -29,7 +29,6 @@ public abstract class Grid<N> implements IGrid<N>
nodeType = type; nodeType = type;
} }
@Override
public void add(N node) public void add(N node)
{ {
synchronized (nodes) synchronized (nodes)
@ -38,7 +37,6 @@ public abstract class Grid<N> implements IGrid<N>
} }
} }
@Override
public void remove(N node) public void remove(N node)
{ {
synchronized (nodes) synchronized (nodes)
@ -47,21 +45,20 @@ public abstract class Grid<N> implements IGrid<N>
} }
} }
@Override
public Set<N> getNodes() public Set<N> getNodes()
{ {
return nodes; return nodes;
} }
/** /**
* A simple reconstruct class to rebuild the grid. * A simple reconstruct class to rebuild the grid. The set "nodes" is copied due to the fact
* that this method will allow the modification of nodes while looping.
*/ */
@Override
public void reconstruct() public void reconstruct()
{ {
synchronized (nodes) synchronized (nodes)
{ {
Iterator<N> it = nodes.iterator(); Iterator<N> it = new HashSet<N>(nodes).iterator();
while (it.hasNext()) while (it.hasNext())
{ {
@ -84,6 +81,19 @@ public abstract class Grid<N> implements IGrid<N>
return nodeType.isAssignableFrom(node.getClass()); return nodeType.isAssignableFrom(node.getClass());
} }
protected void reconstructNode(N node)
{
}
public void deconstruct()
{
synchronized (nodes)
{
nodes.clear();
}
}
/** /**
* Gets the first connector in the set. * Gets the first connector in the set.
* *
@ -91,22 +101,19 @@ public abstract class Grid<N> implements IGrid<N>
*/ */
public N getFirstNode() public N getFirstNode()
{ {
for (N node : getNodes()) synchronized (nodes)
{ {
return node; for (N node : nodes)
{
return node;
}
} }
return null; return null;
} }
protected void reconstructNode(N node)
{
}
@Override @Override
public String toString() public String toString()
{ {
return getClass().getSimpleName() + "[" + hashCode() + ", Connectors: " + nodes.size() + "]"; return getClass().getSimpleName() + "[" + hashCode() + ", Nodes: " + nodes.size() + "]";
} }
} }

View file

@ -1,14 +0,0 @@
package resonantinduction.core.grid;
import java.util.Set;
public interface IGrid<N>
{
public void add(N node);
public void remove(N node);
public Set<N> getNodes();
public void reconstruct();
}

View file

@ -1,29 +0,0 @@
package resonantinduction.core.grid;
import java.util.AbstractMap;
import net.minecraftforge.common.ForgeDirection;
public interface INode<G extends IGrid>
{
/**
* Updates the node. This may be called on a different thread.
*
* @param deltaTime - The time in seconds that has passed between the successive updates.
*/
void update(float deltaTime);
/**
* @return A map consisting of the connected object and a ForgeDirection.
*/
AbstractMap<?, ForgeDirection> getConnections();
G getGrid();
void setGrid(G grid);
/**
* Called whenever the node changes to update its cached connections and network.
*/
void reconstruct();
}

View file

@ -2,7 +2,7 @@ package resonantinduction.core.grid;
import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.ForgeDirection;
public interface INodeProvider<N extends INode> public interface INodeProvider<N extends Node>
{ {
public N getNode(ForgeDirection from); public N getNode(ForgeDirection from);
} }

View file

@ -1,13 +1,17 @@
package resonantinduction.core.grid; package resonantinduction.core.grid;
import resonantinduction.mechanical.energy.network.PartMechanical; import java.util.AbstractMap;
import net.minecraft.nbt.NBTTagCompound; import java.util.WeakHashMap;
public abstract class Node<G extends IGrid> implements INode<G> import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.ForgeDirection;
public abstract class Node<G extends Grid, N>
{ {
protected final AbstractMap<N, ForgeDirection> connections = new WeakHashMap<N, ForgeDirection>();
public G grid = null; public G grid = null;
@Override
public final G getGrid() public final G getGrid()
{ {
if (grid == null) if (grid == null)
@ -18,37 +22,90 @@ public abstract class Node<G extends IGrid> implements INode<G>
protected abstract G newGrid(); protected abstract G newGrid();
@Override
public final void setGrid(G grid) public final void setGrid(G grid)
{ {
this.grid = grid; this.grid = grid;
} }
@Override public void update(float deltaTime)
{
}
/**
* This constructs the node. It should be called whenever the connections of the node are
* updated OR when the node is first initiated and can access its connections.
*/
public void reconstruct() public void reconstruct()
{ {
recache(); synchronized (connections)
getGrid().reconstruct(); {
recache();
getGrid().add(this);
getGrid().reconstruct();
}
} }
// TODO: Fix this. /**
public void split() * This destroys the node, removing it from the grid and also destroying all references to it.
*/
public void deconstruct()
{ {
synchronized (connections)
{
/**
* Remove self from all connections.
*/
for (N connection : connections.keySet())
{
if (getGrid().isValidNode(connection))
{
((Node) connection).getConnections().remove(this);
}
}
getGrid().remove(this);
getGrid().deconstruct();
}
} }
/**
* Called for a node to recache all its connections.
*/
public void recache() public void recache()
{ {
} }
/**
* Returns all the connections in this node.
*
* @return
*/
public AbstractMap<N, ForgeDirection> getConnections()
{
return connections;
}
/**
* Must be called to load the node's data.
*/
public void load(NBTTagCompound nbt) public void load(NBTTagCompound nbt)
{ {
} }
/**
* Must be called to save the node's data.
*/
public void save(NBTTagCompound nbt) public void save(NBTTagCompound nbt)
{ {
} }
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + hashCode() + ", Connections: " + connections.size() + ", Grid:" + getGrid() + "]";
}
} }

View file

@ -1,57 +1,39 @@
package resonantinduction.core.grid; package resonantinduction.core.grid;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.ForgeDirection;
import resonantinduction.mechanical.energy.network.MechanicalNode; import resonantinduction.mechanical.energy.network.MechanicalNode;
import universalelectricity.api.net.IConnectable;
import universalelectricity.api.net.IUpdate; import universalelectricity.api.net.IUpdate;
public class NodeGrid<N extends INode> extends Grid<N> implements IUpdate public abstract class NodeGrid<N extends Node> extends Grid<N>
{ {
public NodeGrid(Class<? extends N> type) public NodeGrid(Class<? extends N> type)
{ {
super(type); super(type);
} }
/**
* An grid update called only server side.
*/
@Override
public void update()
{
synchronized (nodes)
{
for (INode node : nodes)
{
node.update(1 / 20f);
}
}
}
@Override
public boolean canUpdate()
{
return nodes.size() > 0;
}
@Override
public boolean continueUpdate()
{
return canUpdate();
}
@Override @Override
protected void reconstructNode(N node) protected void reconstructNode(N node)
{ {
node.recache();
node.setGrid(this); node.setGrid(this);
AbstractMap<Object, ForgeDirection> connections = node.getConnections(); AbstractMap<Object, ForgeDirection> connections = node.getConnections();
for (Object connection : connections.keySet()) for (Object connection : connections.keySet())
{ {
if (isValidNode(connection) && connection instanceof INode) if (isValidNode(connection) && connection instanceof Node)
{ {
INode connectedNode = (INode) connection; Node connectedNode = (Node) connection;
if (connectedNode.getGrid() != this) if (connectedNode.getGrid() != this)
{ {
@ -63,4 +45,22 @@ public class NodeGrid<N extends INode> extends Grid<N> implements IUpdate
} }
} }
} }
@Override
public void deconstruct()
{
synchronized (nodes)
{
Iterator<N> it = new HashSet<N>(nodes).iterator();
while (it.hasNext())
{
N node = it.next();
node.setGrid(null);
node.reconstruct();
}
nodes.clear();
}
}
} }

View file

@ -0,0 +1,47 @@
package resonantinduction.core.grid;
import resonantinduction.mechanical.energy.network.MechanicalNode;
import universalelectricity.api.net.IUpdate;
import universalelectricity.core.net.NetworkTickHandler;
public class TickingGrid<N extends Node> extends NodeGrid<N> implements IUpdate
{
public TickingGrid(N node, Class type)
{
super(type);
add(node);
NetworkTickHandler.addNetwork(this);
}
public TickingGrid(N node)
{
this(node, node.getClass());
}
/**
* An grid update called only server side.
*/
@Override
public void update()
{
synchronized (nodes)
{
for (Node node : nodes)
{
node.update(1 / 20f);
}
}
}
@Override
public boolean canUpdate()
{
return nodes.size() > 0;
}
@Override
public boolean continueUpdate()
{
return canUpdate();
}
}