Separated Gear's node class from PartGear to make the code cleaner

This commit is contained in:
Robert S 2014-05-24 14:50:29 -04:00
parent 9b67a2d66d
commit 9d21e4ee98
3 changed files with 397 additions and 269 deletions

View file

@ -0,0 +1,290 @@
package resonantinduction.mechanical.gear;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
import resonant.api.IMechanicalNode;
import resonant.api.grid.INodeProvider;
import resonantinduction.mechanical.energy.grid.MechanicalNode;
import codechicken.lib.vec.Rotation;
import codechicken.multipart.TMultiPart;
import codechicken.multipart.TileMultipart;
/** Node for the gear
*
* @author Calclavia, Edited by: Darkguardsman */
public class GearNode extends MechanicalNode
{
public GearNode(PartGear parent)
{
super(parent);
}
protected PartGear gear()
{
return (PartGear) this.parent;
}
@Override
public void onUpdate()
{
if (!gear().getMultiBlock().isPrimary())
{
torque = 0;
angularVelocity = 0;
}
else
{
if (gear().tier == 10)
{
torque = 100;
angularVelocity = 100;
}
}
}
@Override
public double getTorqueLoad()
{
// Decelerate the gear based on tier.
switch (gear().tier)
{
default:
return 0.3;
case 1:
return 0.2;
case 2:
return 0.1;
case 10:
return 0;
}
}
@Override
public double getAngularVelocityLoad()
{
// Decelerate the gear based on tier.
switch (gear().tier)
{
default:
return 0.03;
case 1:
return 0.02;
case 2:
return 0.01;
case 10:
return 0;
}
}
@Override
public void doRecache()
{
connections.clear();
/** Only call refresh if this is the main block of a multiblock gear or a single gear block. */
if (!gear().getMultiBlock().isPrimary() || world() == null)
{
return;
}
/** Look for gears that are back-to-back with this gear. Equate torque. */
TileEntity tileBehind = new universalelectricity.api.vector.Vector3(gear().tile()).translate(gear().placementSide).getTileEntity(world());
if (tileBehind instanceof INodeProvider)
{
MechanicalNode instance = (MechanicalNode) ((INodeProvider) tileBehind).getNode(MechanicalNode.class, gear().placementSide.getOpposite());
if (instance != null && instance != this && !(instance.parent instanceof PartGearShaft) && instance.canConnect(gear().placementSide.getOpposite(), this))
{
connections.put(instance, gear().placementSide);
}
}
/** Look for gears that are internal and adjacent to this gear. (The 4 sides + the internal
* center) */
for (int i = 0; i < 6; i++)
{
ForgeDirection checkDir = ForgeDirection.getOrientation(i);
TileEntity tile = gear().tile();
if (gear().getMultiBlock().isConstructed() && checkDir != gear().placementSide && checkDir != gear().placementSide.getOpposite())
{
tile = new universalelectricity.api.vector.Vector3(gear().tile()).translate(checkDir).getTileEntity(world());
}
if (tile instanceof INodeProvider)
{
/** If we're checking for the block that is opposite to the gear's placement side
* (the center), then we try to look for a gear shaft in the center. */
MechanicalNode instance = (MechanicalNode) ((INodeProvider) tile).getNode(MechanicalNode.class, checkDir == gear().placementSide.getOpposite() ? ForgeDirection.UNKNOWN : checkDir);
if (!connections.containsValue(checkDir) && instance != this && checkDir != gear().placementSide && instance != null && instance.canConnect(checkDir.getOpposite(), this))
{
connections.put(instance, checkDir);
}
}
}
int displaceCheck = 1;
if (gear().getMultiBlock().isPrimary() && gear().getMultiBlock().isConstructed())
{
displaceCheck = 2;
}
/** Look for gears outside this block space, the relative UP, DOWN, LEFT, RIGHT */
for (int i = 0; i < 4; i++)
{
ForgeDirection checkDir = ForgeDirection.getOrientation(Rotation.rotateSide(gear().placementSide.ordinal(), i));
TileEntity checkTile = new universalelectricity.api.vector.Vector3(gear().tile()).translate(checkDir, displaceCheck).getTileEntity(world());
if (!connections.containsValue(checkDir) && checkTile instanceof INodeProvider)
{
MechanicalNode instance = (MechanicalNode) ((INodeProvider) checkTile).getNode(MechanicalNode.class, gear().placementSide);
if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this) && !(instance.parent instanceof PartGearShaft))
{
connections.put(instance, checkDir);
}
}
}
}
/** Can this gear be connected BY the source?
*
* @param from - Direction source is coming from.
* @param with - The source of the connection.
* @return True is so. */
@Override
public boolean canConnect(ForgeDirection from, Object with)
{
if (!gear().getMultiBlock().isPrimary())
{
return false;
}
if (with instanceof MechanicalNode)
{
INodeProvider parent = ((MechanicalNode) with).parent;
/** Check for flat connections (gear face on gear face) to make sure it's actually on
* this gear block. */
if (from == gear().placementSide.getOpposite())
{
if (parent instanceof PartGear || parent instanceof PartGearShaft)
{
if (parent instanceof PartGearShaft)
{
PartGearShaft shaft = (PartGearShaft) parent;
return shaft.tile().partMap(from.getOpposite().ordinal()) == gear() && Math.abs(shaft.placementSide.offsetX) == Math.abs(gear().placementSide.offsetX) && Math.abs(shaft.placementSide.offsetY) == Math.abs(gear().placementSide.offsetY) && Math.abs(shaft.placementSide.offsetZ) == Math.abs(gear().placementSide.offsetZ);
}
else if (parent instanceof PartGear)
{
if (((PartGear) parent).tile() == gear().tile() && !gear().getMultiBlock().isConstructed())
{
return true;
}
if (((PartGear) parent).placementSide != gear().placementSide)
{
TMultiPart part = gear().tile().partMap(((PartGear) parent).placementSide.ordinal());
if (part instanceof PartGear)
{
/** Case when we connect gears via edges internally. Large gear
* attempt to connect to small gear. */
PartGear sourceGear = (PartGear) part;
if (sourceGear.isCenterMultiBlock() && !sourceGear.getMultiBlock().isPrimary())
{
// For large gear to small gear on edge connection.
return true;
}
}
else
{
/** Small gear attempting to connect to large gear. */
if (gear().getMultiBlock().isConstructed())
{
TMultiPart checkPart = ((PartGear) parent).tile().partMap(gear().placementSide.ordinal());
if (checkPart instanceof PartGear)
{
ForgeDirection requiredDirection = ((PartGear) checkPart).getPosition().subtract(position()).toForgeDirection();
return ((PartGear) checkPart).isCenterMultiBlock() && ((PartGear) parent).placementSide == requiredDirection;
}
}
}
}
}
}
/** Face to face stick connection. */
TileEntity sourceTile = position().translate(from.getOpposite()).getTileEntity(world());
if (sourceTile instanceof INodeProvider)
{
MechanicalNode sourceInstance = (MechanicalNode) ((INodeProvider) sourceTile).getNode(MechanicalNode.class, from);
return sourceInstance == with;
}
}
else if (from == gear().placementSide)
{
/** Face to face stick connection. */
TileEntity sourceTile = position().translate(from).getTileEntity(world());
if (sourceTile instanceof INodeProvider)
{
MechanicalNode sourceInstance = (MechanicalNode) ((INodeProvider) sourceTile).getNode(MechanicalNode.class, from.getOpposite());
return sourceInstance == with;
}
}
else
{
TileEntity destinationTile = ((MechanicalNode) with).position().translate(from.getOpposite()).getTileEntity(world());
if (destinationTile instanceof INodeProvider && destinationTile instanceof TileMultipart)
{
TMultiPart destinationPart = ((TileMultipart) destinationTile).partMap(gear().placementSide.ordinal());
if (destinationPart instanceof PartGear)
{
if (gear() != destinationPart)
{
return ((PartGear) destinationPart).isCenterMultiBlock();
}
else
{
return true;
}
}
else
{
return true;
}
}
}
}
return false;
}
@Override
public float getRatio(ForgeDirection dir, IMechanicalNode with)
{
universalelectricity.api.vector.Vector3 deltaPos = with.position().subtract(position());
boolean caseX = gear().placementSide.offsetX != 0 && deltaPos.y == 0 && deltaPos.z == 0;
boolean caseY = gear().placementSide.offsetY != 0 && deltaPos.x == 0 && deltaPos.z == 0;
boolean caseZ = gear().placementSide.offsetZ != 0 && deltaPos.x == 0 && deltaPos.y == 0;
if (caseX || caseY || caseZ)
{
return super.getRatio(dir, with);
}
return gear().getMultiBlock().isConstructed() ? 1.5f : super.getRatio(dir, with);
}
}

View file

@ -59,272 +59,8 @@ public class PartGear extends PartMechanical implements IMultiBlockStructure<Par
public PartGear()
{
super();
node = new MechanicalNode(this)
{
@Override
public void onUpdate()
{
if (!getMultiBlock().isPrimary())
{
torque = 0;
angularVelocity = 0;
}
else
{
if (tier == 10)
{
torque = 100;
angularVelocity = 100;
}
}
}
@Override
public double getTorqueLoad()
{
// Decelerate the gear based on tier.
switch (tier)
{
default:
return 0.3;
case 1:
return 0.2;
case 2:
return 0.1;
case 10:
return 0;
}
}
@Override
public double getAngularVelocityLoad()
{
// Decelerate the gear based on tier.
switch (tier)
{
default:
return 0.03;
case 1:
return 0.02;
case 2:
return 0.01;
case 10:
return 0;
}
}
@Override
public void doRecache()
{
connections.clear();
/** Only call refresh if this is the main block of a multiblock gear or a single gear
* block. */
if (!getMultiBlock().isPrimary() || world() == null)
{
return;
}
/** Look for gears that are back-to-back with this gear. Equate torque. */
TileEntity tileBehind = new universalelectricity.api.vector.Vector3(tile()).translate(placementSide).getTileEntity(world());
if (tileBehind instanceof INodeProvider)
{
MechanicalNode instance = (MechanicalNode) ((INodeProvider) tileBehind).getNode(MechanicalNode.class, placementSide.getOpposite());
if (instance != null && instance != this && !(instance.parent instanceof PartGearShaft) && instance.canConnect(placementSide.getOpposite(), this))
{
connections.put(instance, placementSide);
}
}
/** Look for gears that are internal and adjacent to this gear. (The 4 sides + the
* internal center) */
for (int i = 0; i < 6; i++)
{
ForgeDirection checkDir = ForgeDirection.getOrientation(i);
TileEntity tile = tile();
if (getMultiBlock().isConstructed() && checkDir != placementSide && checkDir != placementSide.getOpposite())
{
tile = new universalelectricity.api.vector.Vector3(tile()).translate(checkDir).getTileEntity(world());
}
if (tile instanceof INodeProvider)
{
/** If we're checking for the block that is opposite to the gear's placement
* side (the center), then we try to look for a gear shaft in the center. */
MechanicalNode instance = (MechanicalNode) ((INodeProvider) tile).getNode(MechanicalNode.class, checkDir == placementSide.getOpposite() ? ForgeDirection.UNKNOWN : checkDir);
if (!connections.containsValue(checkDir) && instance != this && checkDir != placementSide && instance != null && instance.canConnect(checkDir.getOpposite(), this))
{
connections.put(instance, checkDir);
}
}
}
int displaceCheck = 1;
if (getMultiBlock().isPrimary() && getMultiBlock().isConstructed())
{
displaceCheck = 2;
}
/** Look for gears outside this block space, the relative UP, DOWN, LEFT, RIGHT */
for (int i = 0; i < 4; i++)
{
ForgeDirection checkDir = ForgeDirection.getOrientation(Rotation.rotateSide(PartGear.this.placementSide.ordinal(), i));
TileEntity checkTile = new universalelectricity.api.vector.Vector3(tile()).translate(checkDir, displaceCheck).getTileEntity(world());
if (!connections.containsValue(checkDir) && checkTile instanceof INodeProvider)
{
MechanicalNode instance = (MechanicalNode) ((INodeProvider) checkTile).getNode(MechanicalNode.class, placementSide);
if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this) && !(instance.parent instanceof PartGearShaft))
{
connections.put(instance, checkDir);
}
}
}
}
/** Can this gear be connected BY the source?
*
* @param from - Direction source is coming from.
* @param with - The source of the connection.
* @return True is so. */
@Override
public boolean canConnect(ForgeDirection from, Object with)
{
if (!getMultiBlock().isPrimary())
{
return false;
}
if (with instanceof MechanicalNode)
{
INodeProvider parent = ((MechanicalNode) with).parent;
/** Check for flat connections (gear face on gear face) to make sure it's
* actually on this gear block. */
if (from == placementSide.getOpposite())
{
if (parent instanceof PartGear || parent instanceof PartGearShaft)
{
if (parent instanceof PartGearShaft)
{
PartGearShaft shaft = (PartGearShaft) parent;
return shaft.tile().partMap(from.getOpposite().ordinal()) == PartGear.this && Math.abs(shaft.placementSide.offsetX) == Math.abs(placementSide.offsetX) && Math.abs(shaft.placementSide.offsetY) == Math.abs(placementSide.offsetY) && Math.abs(shaft.placementSide.offsetZ) == Math.abs(placementSide.offsetZ);
}
else if (parent instanceof PartGear)
{
if (((PartGear) parent).tile() == tile() && !getMultiBlock().isConstructed())
{
return true;
}
if (((PartGear) parent).placementSide != placementSide)
{
TMultiPart part = tile().partMap(((PartGear) parent).placementSide.ordinal());
if (part instanceof PartGear)
{
/** Case when we connect gears via edges internally. Large
* gear attempt to connect to small gear. */
PartGear sourceGear = (PartGear) part;
if (sourceGear.isCenterMultiBlock() && !sourceGear.getMultiBlock().isPrimary())
{
// For large gear to small gear on edge connection.
return true;
}
}
else
{
/** Small gear attempting to connect to large gear. */
if (getMultiBlock().isConstructed())
{
TMultiPart checkPart = ((PartGear) parent).tile().partMap(placementSide.ordinal());
if (checkPart instanceof PartGear)
{
ForgeDirection requiredDirection = ((PartGear) checkPart).getPosition().subtract(position()).toForgeDirection();
return ((PartGear) checkPart).isCenterMultiBlock() && ((PartGear) parent).placementSide == requiredDirection;
}
}
}
}
}
}
/** Face to face stick connection. */
TileEntity sourceTile = position().translate(from.getOpposite()).getTileEntity(world());
if (sourceTile instanceof INodeProvider)
{
MechanicalNode sourceInstance = (MechanicalNode) ((INodeProvider) sourceTile).getNode(MechanicalNode.class, from);
return sourceInstance == with;
}
}
else if (from == placementSide)
{
/** Face to face stick connection. */
TileEntity sourceTile = position().translate(from).getTileEntity(world());
if (sourceTile instanceof INodeProvider)
{
MechanicalNode sourceInstance = (MechanicalNode) ((INodeProvider) sourceTile).getNode(MechanicalNode.class, from.getOpposite());
return sourceInstance == with;
}
}
else
{
TileEntity destinationTile = ((MechanicalNode) with).position().translate(from.getOpposite()).getTileEntity(world());
if (destinationTile instanceof INodeProvider && destinationTile instanceof TileMultipart)
{
TMultiPart destinationPart = ((TileMultipart) destinationTile).partMap(placementSide.ordinal());
if (destinationPart instanceof PartGear)
{
if (PartGear.this != destinationPart)
{
return ((PartGear) destinationPart).isCenterMultiBlock();
}
else
{
return true;
}
}
else
{
return true;
}
}
}
}
return false;
}
@Override
public float getRatio(ForgeDirection dir, IMechanicalNode with)
{
universalelectricity.api.vector.Vector3 deltaPos = with.position().subtract(position());
boolean caseX = placementSide.offsetX != 0 && deltaPos.y == 0 && deltaPos.z == 0;
boolean caseY = placementSide.offsetY != 0 && deltaPos.x == 0 && deltaPos.z == 0;
boolean caseZ = placementSide.offsetZ != 0 && deltaPos.x == 0 && deltaPos.y == 0;
if (caseX || caseY || caseZ)
{
return super.getRatio(dir, with);
}
return getMultiBlock().isConstructed() ? 1.5f : super.getRatio(dir, with);
}
};
node = new MechanicalNode(this);
}
@Override

View file

@ -5,8 +5,11 @@ import java.util.Set;
import java.util.WeakHashMap;
import universalelectricity.api.net.IUpdate;
import universalelectricity.core.net.ConnectionPathfinder;
/** Network type only used by gear related mechanical machines
/** Network type only used by gear related mechanical machines. Any node that uses this network needs
* to call onAdded() and onRemoved(). This way the network knows when to handle remapping of all
* connections.
*
* @author Darkguardsman */
public class GearNetwork implements IUpdate
@ -15,6 +18,7 @@ public class GearNetwork implements IUpdate
private final Set<NodeGear> nodes = Collections.newSetFromMap(new WeakHashMap<NodeGear, Boolean>());
private final Set<NodeGenerator> generators = Collections.newSetFromMap(new WeakHashMap<NodeGenerator, Boolean>());
private boolean doRemap = false;
private boolean isDead = false;
/** Called by a gear when its added to the world */
public void onAdded(NodeGear gear)
@ -60,13 +64,111 @@ public class GearNetwork implements IUpdate
@Override
public boolean canUpdate()
{
return true;
return !isDead;
}
@Override
public boolean continueUpdate()
{
return true;
return canUpdate();
}
/** Called to merge this network with another network. Creates a new network in the process and
* empties the old networks */
public GearNetwork merge(GearNetwork network)
{
if (network != null && network.getClass().isAssignableFrom(getClass()) && network != this)
{
synchronized (this)
{
GearNetwork newNetwork = new GearNetwork();
//Add all nodes to new network from old ones
newNetwork.nodes.addAll(nodes);
newNetwork.nodes.addAll(network.nodes);
//Add all generator nodes
newNetwork.generators.addAll(generators);
newNetwork.generators.addAll(network.generators);
//Destroy the old networks
network.deconstruct();
deconstruct();
newNetwork.doRemap = true;
return newNetwork;
}
}
return null;
}
public void split(NodeGear splitPoint)
{
/** Loop through the connected blocks and attempt to see if there are connections between the
* two points elsewhere. */
Object[] connectedBlocks = getConnectionsFor(splitPoint);
removeConnector(splitPoint);
for (int i = 0; i < connectedBlocks.length; i++)
{
Object connectedA = connectedBlocks[i];
if (connectedA != null && isValidConnector(connectedA))
{
for (int ii = 0; ii < connectedBlocks.length; ii++)
{
final Object connectedB = connectedBlocks[ii];
if (connectedB != null && connectedA != connectedB && isValidConnector(connectedB))
{
ConnectionPathfinder<C> finder = new ConnectionPathfinder<C>(getConnectorClass(), (C) connectedB, splitPoint);
finder.findNodes((C) connectedA);
if (finder.results.size() <= 0)
{
try
{
/** The connections A and B are not connected anymore. Give them both
* a new common network. */
N newNetwork = newInstance();
for (C node : finder.closedSet)
{
if (node != splitPoint)
{
newNetwork.addConnector(node);
removeConnector(node);
onSplit(newNetwork);
}
}
newNetwork.reconstruct();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}
}
reconstruct();
}
/** Called to rebuild the network */
protected void reconstruct()
{
}
/** Called to destroy or rather clean up the network. Make sure to do your cleanup in this
* method. */
protected void deconstruct()
{
this.nodes.clear();
this.generators.clear();
this.isDead = true;
}
}