Patched some sync blocks preventing mechanical concurrent modification

This commit is contained in:
Calclavia 2014-06-20 16:58:16 -07:00
parent 38aa020db3
commit 0daba1a577
3 changed files with 695 additions and 654 deletions

View file

@ -17,382 +17,413 @@ import universalelectricity.api.vector.IVectorWorld;
import universalelectricity.api.vector.Vector3; import universalelectricity.api.vector.Vector3;
import codechicken.multipart.TMultiPart; import codechicken.multipart.TMultiPart;
/** A mechanical node for mechanical energy. /**
* * A mechanical node for mechanical energy.
* @author Calclavia, Darkguardsman */ *
* @author Calclavia, Darkguardsman
*/
public class MechanicalNode implements IMechanicalNode, ISaveObj, IVectorWorld public class MechanicalNode implements IMechanicalNode, ISaveObj, IVectorWorld
{ {
/** Is debug enabled for the node */ /**
public boolean doDebug = false; * Is debug enabled for the node
/** Used to note that you should trigger a packet update for rotation */ */
public boolean markRotationUpdate = false; public boolean doDebug = false;
public boolean markTorqueUpdate = false; /**
/** Which section of debug is enabled */ * Used to note that you should trigger a packet update for rotation
public int debugCue = 0, maxDebugCue = 1, minDebugCue = 0; */
public static final int UPDATE_DEBUG = 0, CONNECTION_DEBUG = 1; public boolean markRotationUpdate = false;
/** Rotational Force */ public boolean markTorqueUpdate = false;
public double torque = 0, prevTorque; /**
/** Rotational speed */ * Which section of debug is enabled
public double prevAngularVelocity, angularVelocity = 0; */
/** Rotational acceleration */ public int debugCue = 0, maxDebugCue = 1, minDebugCue = 0;
public float acceleration = 2f; public static final int UPDATE_DEBUG = 0, CONNECTION_DEBUG = 1;
/**
* Rotational Force
*/
public double torque = 0, prevTorque;
/**
* Rotational speed
*/
public double prevAngularVelocity, angularVelocity = 0;
/**
* Rotational acceleration
*/
public float acceleration = 2f;
/** The current rotation of the mechanical node. */ /**
public double renderAngle = 0, prev_angle = 0; * The current rotation of the mechanical node.
/** Limits the max distance an object can rotate in a single update */ */
protected double maxDeltaAngle = Math.toRadians(180); public double renderAngle = 0, prev_angle = 0;
/**
* Limits the max distance an object can rotate in a single update
*/
protected double maxDeltaAngle = Math.toRadians(180);
protected double load = 2; protected double load = 2;
protected byte connectionMap = Byte.parseByte("111111", 2); protected byte connectionMap = Byte.parseByte("111111", 2);
private double power = 0; private double power = 0;
private INodeProvider parent; private INodeProvider parent;
private long ticks = 0; private long ticks = 0;
private final AbstractMap<MechanicalNode, ForgeDirection> connections = new WeakHashMap<MechanicalNode, ForgeDirection>(); private final AbstractMap<MechanicalNode, ForgeDirection> connections = new WeakHashMap<MechanicalNode, ForgeDirection>();
public MechanicalNode(INodeProvider parent) public MechanicalNode(INodeProvider parent)
{ {
this.setParent(parent); this.setParent(parent);
} }
@Override @Override
public MechanicalNode setLoad(double load) public MechanicalNode setLoad(double load)
{ {
this.load = load; this.load = load;
return this; return this;
} }
public MechanicalNode setConnection(byte connectionMap) public MechanicalNode setConnection(byte connectionMap)
{ {
this.connectionMap = connectionMap; this.connectionMap = connectionMap;
return this; return this;
} }
@Override @Override
public double getRadius() public double getRadius()
{ {
return 0.5; return 0.5;
} }
public void update() public void update()
{ {
update(0.05f); update(0.05f);
} }
@Override @Override
public void update(float deltaTime) public void update(float deltaTime)
{ {
ticks++; ticks++;
if (ticks >= Long.MAX_VALUE) if (ticks >= Long.MAX_VALUE)
{ {
ticks = 1; ticks = 1;
} }
//temp, TODO find a better way to trigger this //temp, TODO find a better way to trigger this
if (ticks % 100 == 0) if (ticks % 100 == 0)
{ {
this.recache(); this.recache();
} }
//----------------------------------- //-----------------------------------
// Render Update // Render Update
//----------------------------------- //-----------------------------------
if (angularVelocity >= 0) if (angularVelocity >= 0)
{ {
renderAngle += Math.min(angularVelocity, this.maxDeltaAngle) * deltaTime; renderAngle += Math.min(angularVelocity, this.maxDeltaAngle) * deltaTime;
} }
else else
{ {
renderAngle += Math.max(angularVelocity, -this.maxDeltaAngle) * deltaTime; renderAngle += Math.max(angularVelocity, -this.maxDeltaAngle) * deltaTime;
} }
if (renderAngle % (Math.PI * 2) != renderAngle) if (renderAngle % (Math.PI * 2) != renderAngle)
{ {
revolve(); revolve();
renderAngle = renderAngle % (Math.PI * 2); renderAngle = renderAngle % (Math.PI * 2);
} }
//----------------------------------- //-----------------------------------
// Server side Update // Server side Update
//----------------------------------- //-----------------------------------
if (world() != null && !world().isRemote) if (world() != null && !world().isRemote)
{ {
final double acceleration = this.acceleration * deltaTime; final double acceleration = this.acceleration * deltaTime;
if (Math.abs(prevAngularVelocity - angularVelocity) > 0.01f) if (Math.abs(prevAngularVelocity - angularVelocity) > 0.01f)
{ {
prevAngularVelocity = angularVelocity; prevAngularVelocity = angularVelocity;
markRotationUpdate = true; markRotationUpdate = true;
} }
if (Math.abs(prevTorque - torque) > 0.01f) if (Math.abs(prevTorque - torque) > 0.01f)
{ {
prevTorque = torque; prevTorque = torque;
markTorqueUpdate = true; markTorqueUpdate = true;
} }
//----------------------------------- //-----------------------------------
// Loss calculations // Loss calculations
//----------------------------------- //-----------------------------------
double torqueLoss = Math.min(Math.abs(getTorque()), (Math.abs(getTorque() * getTorqueLoad()) + getTorqueLoad() / 10) * deltaTime); double torqueLoss = Math.min(Math.abs(getTorque()), (Math.abs(getTorque() * getTorqueLoad()) + getTorqueLoad() / 10) * deltaTime);
torque += torque > 0 ? -torqueLoss : torqueLoss; torque += torque > 0 ? -torqueLoss : torqueLoss;
double velocityLoss = Math.min(Math.abs(getAngularSpeed()), (Math.abs(getAngularSpeed() * getAngularVelocityLoad()) + getAngularVelocityLoad() / 10) * deltaTime); double velocityLoss = Math.min(Math.abs(getAngularSpeed()), (Math.abs(getAngularSpeed() * getAngularVelocityLoad()) + getAngularVelocityLoad() / 10) * deltaTime);
angularVelocity += angularVelocity > 0 ? -velocityLoss : velocityLoss; angularVelocity += angularVelocity > 0 ? -velocityLoss : velocityLoss;
if (getEnergy() <= 0) if (getEnergy() <= 0)
{ {
angularVelocity = torque = 0; angularVelocity = torque = 0;
} }
power = getEnergy() / deltaTime; power = getEnergy() / deltaTime;
//----------------------------------- //-----------------------------------
// Connection application of force and speed // Connection application of force and speed
//----------------------------------- //-----------------------------------
synchronized (getConnections()) synchronized (getConnections())
{ {
Iterator<Entry<MechanicalNode, ForgeDirection>> it = getConnections().entrySet().iterator(); Iterator<Entry<MechanicalNode, ForgeDirection>> it = getConnections().entrySet().iterator();
while (it.hasNext()) while (it.hasNext())
{ {
Entry<MechanicalNode, ForgeDirection> entry = it.next(); Entry<MechanicalNode, ForgeDirection> entry = it.next();
ForgeDirection dir = entry.getValue(); ForgeDirection dir = entry.getValue();
MechanicalNode adjacentMech = entry.getKey(); MechanicalNode adjacentMech = entry.getKey();
/** Calculate angular velocity and torque. */ /** Calculate angular velocity and torque. */
float ratio = adjacentMech.getRatio(dir.getOpposite(), this) / getRatio(dir, adjacentMech); float ratio = adjacentMech.getRatio(dir.getOpposite(), this) / getRatio(dir, adjacentMech);
boolean inverseRotation = inverseRotation(dir, adjacentMech) && adjacentMech.inverseRotation(dir.getOpposite(), this); boolean inverseRotation = inverseRotation(dir, adjacentMech) && adjacentMech.inverseRotation(dir.getOpposite(), this);
int inversion = inverseRotation ? -1 : 1; int inversion = inverseRotation ? -1 : 1;
double targetTorque = inversion * adjacentMech.getTorque() / ratio; double targetTorque = inversion * adjacentMech.getTorque() / ratio;
double applyTorque = targetTorque * acceleration; double applyTorque = targetTorque * acceleration;
if (Math.abs(torque + applyTorque) < Math.abs(targetTorque)) if (Math.abs(torque + applyTorque) < Math.abs(targetTorque))
{ {
torque += applyTorque; torque += applyTorque;
} }
else if (Math.abs(torque - applyTorque) > Math.abs(targetTorque)) else if (Math.abs(torque - applyTorque) > Math.abs(targetTorque))
{ {
torque -= applyTorque; torque -= applyTorque;
} }
double targetVelocity = inversion * adjacentMech.getAngularSpeed() * ratio; double targetVelocity = inversion * adjacentMech.getAngularSpeed() * ratio;
double applyVelocity = targetVelocity * acceleration; double applyVelocity = targetVelocity * acceleration;
if (Math.abs(angularVelocity + applyVelocity) < Math.abs(targetVelocity)) if (Math.abs(angularVelocity + applyVelocity) < Math.abs(targetVelocity))
{ {
angularVelocity += applyVelocity; angularVelocity += applyVelocity;
} }
else if (Math.abs(angularVelocity - applyVelocity) > Math.abs(targetVelocity)) else if (Math.abs(angularVelocity - applyVelocity) > Math.abs(targetVelocity))
{ {
angularVelocity -= applyVelocity; angularVelocity -= applyVelocity;
} }
/** Set all current rotations */ /** Set all current rotations */
// adjacentMech.angle = Math.abs(angle) * (adjacentMech.angle >= 0 ? 1 : -1); // adjacentMech.angle = Math.abs(angle) * (adjacentMech.angle >= 0 ? 1 : -1);
} }
} }
} }
onUpdate(); onUpdate();
prev_angle = renderAngle; prev_angle = renderAngle;
} }
protected void onUpdate() protected void onUpdate()
{ {
} }
/** Called when one revolution is made. */ /**
protected void revolve() * Called when one revolution is made.
{ */
protected void revolve()
{
} }
@Override @Override
public void apply(Object source, double torque, double angularVelocity) public void apply(Object source, double torque, double angularVelocity)
{ {
this.torque += torque; this.torque += torque;
this.angularVelocity += angularVelocity; this.angularVelocity += angularVelocity;
} }
@Override @Override
public double getTorque() public double getTorque()
{ {
return angularVelocity != 0 ? torque : 0; return angularVelocity != 0 ? torque : 0;
} }
@Override @Override
public double getAngularSpeed() public double getAngularSpeed()
{ {
return torque != 0 ? angularVelocity : 0; return torque != 0 ? angularVelocity : 0;
} }
@Override @Override
public float getRatio(ForgeDirection dir, IMechanicalNode with) public float getRatio(ForgeDirection dir, IMechanicalNode with)
{ {
return 0.5f; return 0.5f;
} }
@Override @Override
public boolean inverseRotation(ForgeDirection dir, IMechanicalNode with) public boolean inverseRotation(ForgeDirection dir, IMechanicalNode with)
{ {
return true; return true;
} }
/** The energy percentage loss due to resistance in seconds. */ /**
public double getTorqueLoad() * The energy percentage loss due to resistance in seconds.
{ */
return load; public double getTorqueLoad()
} {
return load;
}
public double getAngularVelocityLoad() public double getAngularVelocityLoad()
{ {
return load; return load;
} }
/** Checks to see if a connection is allowed from side and from a source */ /**
public boolean canConnect(ForgeDirection from, Object source) * Checks to see if a connection is allowed from side and from a source
{ */
if (source instanceof MechanicalNode) public boolean canConnect(ForgeDirection from, Object source)
{ {
boolean flag = (connectionMap & (1 << from.ordinal())) != 0; if (source instanceof MechanicalNode)
return flag; {
} boolean flag = (connectionMap & (1 << from.ordinal())) != 0;
return false; return flag;
} }
return false;
}
@Override @Override
public double getEnergy() public double getEnergy()
{ {
return getTorque() * getAngularSpeed(); return getTorque() * getAngularSpeed();
} }
@Override @Override
public double getPower() public double getPower()
{ {
return power; return power;
} }
@Override @Override
public void load(NBTTagCompound nbt) public void load(NBTTagCompound nbt)
{ {
torque = nbt.getDouble("torque"); torque = nbt.getDouble("torque");
angularVelocity = nbt.getDouble("angularVelocity"); angularVelocity = nbt.getDouble("angularVelocity");
} }
@Override @Override
public void save(NBTTagCompound nbt) public void save(NBTTagCompound nbt)
{ {
nbt.setDouble("torque", torque); nbt.setDouble("torque", torque);
nbt.setDouble("angularVelocity", angularVelocity); nbt.setDouble("angularVelocity", angularVelocity);
} }
@Override @Override
public void reconstruct() public void reconstruct()
{ {
recache(); recache();
} }
@Override @Override
public void deconstruct() public void deconstruct()
{ {
for (Entry<MechanicalNode, ForgeDirection> entry : getConnections().entrySet()) for (Entry<MechanicalNode, ForgeDirection> entry : getConnections().entrySet())
{ {
entry.getKey().getConnections().remove(this); entry.getKey().getConnections().remove(this);
entry.getKey().recache(); entry.getKey().recache();
} }
getConnections().clear(); getConnections().clear();
} }
@Override @Override
public void recache() public void recache()
{ {
getConnections().clear(); synchronized (this)
{
getConnections().clear();
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
{ {
TileEntity tile = position().translate(dir).getTileEntity(world()); TileEntity tile = position().translate(dir).getTileEntity(world());
if (tile instanceof INodeProvider) if (tile instanceof INodeProvider)
{ {
INode node = ((INodeProvider) tile).getNode(MechanicalNode.class, dir.getOpposite()); INode node = ((INodeProvider) tile).getNode(MechanicalNode.class, dir.getOpposite());
if (node instanceof MechanicalNode) if (node instanceof MechanicalNode)
{ {
MechanicalNode check = (MechanicalNode) node; MechanicalNode check = (MechanicalNode) node;
boolean canConnect = canConnect(dir, check); boolean canConnect = canConnect(dir, check);
boolean canOtherConnect = check.canConnect(dir.getOpposite(), this); boolean canOtherConnect = check.canConnect(dir.getOpposite(), this);
if (canConnect && canOtherConnect) if (canConnect && canOtherConnect)
{ {
getConnections().put(check, dir); getConnections().put(check, dir);
} }
} }
} }
} }
} }
}
/** Gets the node provider for this node */ /**
public INodeProvider getParent() * Gets the node provider for this node
{ */
return parent; public INodeProvider getParent()
} {
return parent;
}
/** Sets the node provider for the node */ /**
public void setParent(INodeProvider parent) * Sets the node provider for the node
{ */
this.parent = parent; public void setParent(INodeProvider parent)
} {
this.parent = parent;
}
@Override @Override
public String toString() public String toString()
{ {
return this.getClass().getSimpleName() + this.hashCode(); return this.getClass().getSimpleName() + this.hashCode();
} }
public AbstractMap<MechanicalNode, ForgeDirection> getConnections() public AbstractMap<MechanicalNode, ForgeDirection> getConnections()
{ {
return connections; return connections;
} }
@Override @Override
public World world() public World world()
{ {
return getParent() instanceof TMultiPart ? ((TMultiPart) getParent()).world() : getParent() instanceof TileEntity ? ((TileEntity) getParent()).getWorldObj() : null; return getParent() instanceof TMultiPart ? ((TMultiPart) getParent()).world() : getParent() instanceof TileEntity ? ((TileEntity) getParent()).getWorldObj() : null;
} }
public Vector3 position() public Vector3 position()
{ {
return new Vector3(x(), y(), z()); return new Vector3(x(), y(), z());
} }
@Override @Override
public double z() public double z()
{ {
if(this.getParent() instanceof TileEntity) if (this.getParent() instanceof TileEntity)
{ {
return ((TileEntity)this.getParent()).zCoord; return ((TileEntity) this.getParent()).zCoord;
} }
return this.getParent() instanceof TMultiPart && ((TMultiPart) this.getParent()).tile() != null ? ((TMultiPart) this.getParent()).z() : 0; return this.getParent() instanceof TMultiPart && ((TMultiPart) this.getParent()).tile() != null ? ((TMultiPart) this.getParent()).z() : 0;
} }
@Override @Override
public double x() public double x()
{ {
if(this.getParent() instanceof TileEntity) if (this.getParent() instanceof TileEntity)
{ {
return ((TileEntity)this.getParent()).xCoord; return ((TileEntity) this.getParent()).xCoord;
} }
return this.getParent() instanceof TMultiPart && ((TMultiPart) this.getParent()).tile() != null ? ((TMultiPart) this.getParent()).x() : 0; return this.getParent() instanceof TMultiPart && ((TMultiPart) this.getParent()).tile() != null ? ((TMultiPart) this.getParent()).x() : 0;
} }
@Override @Override
public double y() public double y()
{ {
if(this.getParent() instanceof TileEntity) if (this.getParent() instanceof TileEntity)
{ {
return ((TileEntity)this.getParent()).yCoord; return ((TileEntity) this.getParent()).yCoord;
} }
return this.getParent() instanceof TMultiPart && ((TMultiPart) this.getParent()).tile() != null ? ((TMultiPart) this.getParent()).y() : 0; return this.getParent() instanceof TMultiPart && ((TMultiPart) this.getParent()).tile() != null ? ((TMultiPart) this.getParent()).y() : 0;
} }
} }

View file

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

View file

@ -14,113 +14,116 @@ import universalelectricity.api.vector.Vector3;
public class GearShaftNode extends MechanicalNode public class GearShaftNode extends MechanicalNode
{ {
public GearShaftNode(PartGearShaft parent) public GearShaftNode(PartGearShaft parent)
{ {
super(parent); super(parent);
} }
@Override @Override
public double getTorqueLoad() public double getTorqueLoad()
{ {
// Decelerate the gear based on tier. // Decelerate the gear based on tier.
switch (shaft().tier) switch (shaft().tier)
{ {
default: default:
return 0.03; return 0.03;
case 1: case 1:
return 0.02; return 0.02;
case 2: case 2:
return 0.01; return 0.01;
} }
} }
@Override @Override
public double getAngularVelocityLoad() public double getAngularVelocityLoad()
{ {
return 0; return 0;
} }
@Override @Override
public void recache() public void recache()
{ {
getConnections().clear(); synchronized (this)
List<ForgeDirection> dirs = new ArrayList<ForgeDirection>(); {
dirs.add(shaft().placementSide); getConnections().clear();
dirs.add(shaft().placementSide.getOpposite()); List<ForgeDirection> dirs = new ArrayList<ForgeDirection>();
/** Check for internal connections, the FRONT and BACK. */ dirs.add(shaft().placementSide);
Iterator<ForgeDirection> it = dirs.iterator(); dirs.add(shaft().placementSide.getOpposite());
while (it.hasNext()) /** Check for internal connections, the FRONT and BACK. */
{ Iterator<ForgeDirection> it = dirs.iterator();
ForgeDirection checkDir = it.next(); while (it.hasNext())
if (checkDir == shaft().placementSide || checkDir == shaft().placementSide.getOpposite()) {
{ ForgeDirection checkDir = it.next();
if (shaft().tile() instanceof INodeProvider) if (checkDir == shaft().placementSide || checkDir == shaft().placementSide.getOpposite())
{ {
MechanicalNode instance = (MechanicalNode) ((INodeProvider) shaft().tile()).getNode(MechanicalNode.class, checkDir); if (shaft().tile() instanceof INodeProvider)
{
MechanicalNode instance = (MechanicalNode) ((INodeProvider) shaft().tile()).getNode(MechanicalNode.class, checkDir);
if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this)) if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this))
{ {
getConnections().put(instance, checkDir); getConnections().put(instance, checkDir);
it.remove(); it.remove();
} }
} }
} }
} }
/** Look for connections outside this block space, the relative FRONT and BACK */ /** Look for connections outside this block space, the relative FRONT and BACK */
if (!dirs.isEmpty()) if (!dirs.isEmpty())
for (ForgeDirection checkDir : dirs) for (ForgeDirection checkDir : dirs)
{ {
if (!getConnections().containsValue(checkDir) && (checkDir == shaft().placementSide || checkDir == shaft().placementSide.getOpposite())) if (!getConnections().containsValue(checkDir) && (checkDir == shaft().placementSide || checkDir == shaft().placementSide.getOpposite()))
{ {
TileEntity checkTile = new Vector3(shaft().tile()).translate(checkDir).getTileEntity(world()); TileEntity checkTile = new Vector3(shaft().tile()).translate(checkDir).getTileEntity(world());
if (checkTile instanceof INodeProvider) if (checkTile instanceof INodeProvider)
{ {
MechanicalNode instance = (MechanicalNode) ((INodeProvider) checkTile).getNode(MechanicalNode.class, checkDir.getOpposite()); MechanicalNode instance = (MechanicalNode) ((INodeProvider) checkTile).getNode(MechanicalNode.class, checkDir.getOpposite());
// Only connect to shafts outside of this block space. // Only connect to shafts outside of this block space.
if (instance != null && instance != this && instance.getParent() instanceof PartGearShaft && instance.canConnect(checkDir.getOpposite(), this)) if (instance != null && instance != this && instance.getParent() instanceof PartGearShaft && instance.canConnect(checkDir.getOpposite(), this))
{ {
getConnections().put(instance, checkDir); getConnections().put(instance, checkDir);
} }
} }
} }
} }
} }
}
@Override @Override
public boolean canConnect(ForgeDirection from, Object source) public boolean canConnect(ForgeDirection from, Object source)
{ {
if (source instanceof MechanicalNode) if (source instanceof MechanicalNode)
{ {
if (((MechanicalNode) source).getParent() instanceof PartGear) if (((MechanicalNode) source).getParent() instanceof PartGear)
{ {
PartGear gear = (PartGear) ((MechanicalNode) source).getParent(); PartGear gear = (PartGear) ((MechanicalNode) source).getParent();
if (!(Math.abs(gear.placementSide.offsetX) == Math.abs(shaft().placementSide.offsetX) && Math.abs(gear.placementSide.offsetY) == Math.abs(shaft().placementSide.offsetY) && Math.abs(gear.placementSide.offsetZ) == Math.abs(shaft().placementSide.offsetZ))) if (!(Math.abs(gear.placementSide.offsetX) == Math.abs(shaft().placementSide.offsetX) && Math.abs(gear.placementSide.offsetY) == Math.abs(shaft().placementSide.offsetY) && Math.abs(gear.placementSide.offsetZ) == Math.abs(shaft().placementSide.offsetZ)))
{ {
return false; return false;
} }
} }
} }
return from == shaft().placementSide || from == shaft().placementSide.getOpposite(); return from == shaft().placementSide || from == shaft().placementSide.getOpposite();
} }
@Override @Override
public boolean inverseRotation(ForgeDirection dir, IMechanicalNode with) public boolean inverseRotation(ForgeDirection dir, IMechanicalNode with)
{ {
if (shaft().placementSide.offsetY != 0 || shaft().placementSide.offsetZ != 0) if (shaft().placementSide.offsetY != 0 || shaft().placementSide.offsetZ != 0)
{ {
return dir == shaft().placementSide.getOpposite(); return dir == shaft().placementSide.getOpposite();
} }
return dir == shaft().placementSide; return dir == shaft().placementSide;
} }
public PartGearShaft shaft() public PartGearShaft shaft()
{ {
return (PartGearShaft) this.getParent(); return (PartGearShaft) this.getParent();
} }
} }