Started reworking MechanicalNode

This commit is contained in:
Calclavia 2014-11-06 14:05:42 +08:00
parent eb39dcf90d
commit 47a4ea6ef1
5 changed files with 403 additions and 518 deletions

View file

@ -131,7 +131,7 @@ public class DebugFrameMechanical extends FrameNodeDebug
@Override
public String buildLabel()
{
return super.buildLabel() + DebugFrameMechanical.this.getNode().angularVelocity;
return super.buildLabel() + DebugFrameMechanical.this.getNode().angularVelocity();
}
};
topPanel.add(velLabel);
@ -141,7 +141,7 @@ public class DebugFrameMechanical extends FrameNodeDebug
@Override
public String buildLabel()
{
return super.buildLabel() + DebugFrameMechanical.this.getNode().renderAngle;
return super.buildLabel() + DebugFrameMechanical.this.getNode().renderAngle();
}
};
topPanel.add(angleLabel);
@ -151,7 +151,7 @@ public class DebugFrameMechanical extends FrameNodeDebug
@Override
public String buildLabel()
{
return super.buildLabel() + DebugFrameMechanical.this.getNode().torque;
return super.buildLabel() + DebugFrameMechanical.this.getNode().torque();
}
};
topPanel.add(torqueLabel);

View file

@ -1,336 +0,0 @@
package resonantinduction.mechanical.mech;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
import resonant.api.grid.INode;
import resonant.api.grid.INodeProvider;
import resonant.api.grid.IUpdate;
import resonant.lib.grid.node.NodeConnector;
import resonant.lib.transform.vector.IVectorWorld;
import resonant.lib.utility.nbt.ISaveObj;
import resonantinduction.core.interfaces.IMechanicalNode;
import resonantinduction.core.prefab.node.TMultipartNode;
import java.util.Iterator;
import java.util.Map.Entry;
/**
* Prefab node for the mechanical system used by almost ever mechanical object in Resonant Induction. Handles connections to other tiles, and shares power with them
*
* @author Calclavia, Darkguardsman
*/
//Don't convert to scala as this will find its way into RE later - From Darkguardsman
public class MechanicalNode extends NodeConnector<MechanicalNode> implements TMultipartNode<MechanicalNode>, IMechanicalNode, ISaveObj, IVectorWorld, IUpdate
{
/**
* Marks that the rotation has changed and should be updated client side
*/
public boolean markRotationUpdate = false;
/**
* Makrs that the torque value has changed and should be updated client side
*/
public boolean markTorqueUpdate = false;
/**
* Allows the node to share its power with other nodes
*/
public boolean sharePower = true;
public double torque = 0, prevTorque;
public double prevAngularVelocity, angularVelocity = 0;
/**
* Current angle of rotation, mainly used for rendering
*/
public double renderAngle = 0;
/**
* Angle of rotation of last update
*/
public double prev_angle = 0;
public float acceleration = 2f;
protected double maxDeltaAngle = Math.toRadians(120);
protected double load = 2;
private double power = 0;
/**
* Current update tick #
*/
private long ticks = 0;
public MechanicalNode(INodeProvider parent)
{
super(parent);
}
@Override
public double getRadius(ForgeDirection dir, IMechanicalNode with)
{
return 0.5;
}
@Override
public double getAngularSpeed(ForgeDirection side)
{
return angularVelocity;
}
@Override
public double getForce(ForgeDirection side)
{
return torque;
}
@Override
public boolean inverseRotation(ForgeDirection side)
{
return false;
}
final public void update()
{
update(0.05f);
}
@Override
final public void update(double deltaTime)
{
ticks++;
if (ticks >= Long.MAX_VALUE)
{
ticks = 0;
}
//-----------------------------------
// Render Update
//-----------------------------------
// Updates rotation angle and prevents it from rotating too fast
if (angularVelocity >= 0)
{
renderAngle += Math.min(angularVelocity, this.maxDeltaAngle) * deltaTime;
}
else
{
renderAngle += Math.max(angularVelocity, -this.maxDeltaAngle) * deltaTime;
}
// Cap rotation angle to prevent render issues
if (renderAngle >= Math.PI * 2)
{
revolve();
renderAngle = renderAngle % (Math.PI * 2);
}
//-----------------------------------
// Server side Update
//-----------------------------------
if (world() != null && !world().isRemote)
{
final double acceleration = this.acceleration * deltaTime;
if (Math.abs(prevAngularVelocity - angularVelocity) > 0.01f)
{
prevAngularVelocity = angularVelocity;
markRotationUpdate = true;
}
if (Math.abs(prevTorque - torque) > 0.01f)
{
prevTorque = torque;
markTorqueUpdate = true;
}
//-----------------------------------
// Loss calculations
//-----------------------------------
double torqueLoss = Math.min(Math.abs(getTorque()), (Math.abs(getTorque() * getTorqueLoad()) + getTorqueLoad() / 10) * deltaTime);
torque += torque > 0 ? -torqueLoss : torqueLoss;
double velocityLoss = Math.min(Math.abs(getAngularSpeed()), (Math.abs(getAngularSpeed() * getAngularVelocityLoad()) + getAngularVelocityLoad() / 10) * deltaTime);
angularVelocity += angularVelocity > 0 ? -velocityLoss : velocityLoss;
if (getEnergy() <= 0)
{
angularVelocity = torque = 0;
}
power = getEnergy() / deltaTime;
if (sharePower)
{
// Power sharing calculations
Iterator<Entry<MechanicalNode, ForgeDirection>> it = directionMap().entrySet().iterator();
while (it.hasNext())
{
MechanicalNode adjacentMech = null;
Entry<MechanicalNode, ForgeDirection> entry = it.next();
ForgeDirection dir = entry.getValue();
//TODO: Will never happen that it isn't a mech node.
// Get mech node
if (entry.getKey() instanceof MechanicalNode)
{
adjacentMech = (MechanicalNode) entry.getKey();
}
else if (entry.getKey() instanceof INodeProvider)
{
INode node = ((INodeProvider) entry.getKey()).getNode(MechanicalNode.class, dir.getOpposite());
if (node instanceof MechanicalNode)
{
adjacentMech = (MechanicalNode) node;
}
}
else
{
it.remove();
}
// If node is not null apply power
if (adjacentMech != null)
{
/** Calculate angular velocity and torque. */
double ratio = adjacentMech.getRadius(dir.getOpposite(), this) / getRadius(dir, adjacentMech);
boolean inverseRotation = inverseRotation(dir) && adjacentMech.inverseRotation(dir.getOpposite());
int inversion = inverseRotation ? -1 : 1;
double targetTorque = inversion * adjacentMech.getTorque() / ratio;
double applyTorque = targetTorque * acceleration;
if (Math.abs(torque + applyTorque) < Math.abs(targetTorque))
{
torque += applyTorque;
}
else if (Math.abs(torque - applyTorque) > Math.abs(targetTorque))
{
torque -= applyTorque;
}
double targetVelocity = inversion * adjacentMech.getAngularSpeed() * ratio;
double applyVelocity = targetVelocity * acceleration;
if (Math.abs(angularVelocity + applyVelocity) < Math.abs(targetVelocity))
{
angularVelocity += applyVelocity;
}
else if (Math.abs(angularVelocity - applyVelocity) > Math.abs(targetVelocity))
{
angularVelocity -= applyVelocity;
}
/** Set all current rotations */
// adjacentMech.angle = Math.abs(angle) * (adjacentMech.angle >= 0 ? 1 : -1);
}
}
}
}
onUpdate();
prev_angle = renderAngle;
}
@Override
public boolean canUpdate()
{
return true;
}
@Override
public boolean continueUpdate()
{
return true;
}
protected void onUpdate()
{
}
/**
* Called when one revolution is made.
*/
protected void revolve()
{
}
@Override
public void apply(Object source, double torque, double angularVelocity)
{
this.torque += torque;
this.angularVelocity += angularVelocity;
}
private double getTorque()
{
return angularVelocity != 0 ? torque : 0;
}
private double getAngularSpeed()
{
return torque != 0 ? angularVelocity : 0;
}
/**
* The energy percentage loss due to resistance in seconds.
*/
public double getTorqueLoad()
{
return load;
}
public double getAngularVelocityLoad()
{
return load;
}
public double getEnergy()
{
return getTorque() * getAngularSpeed();
}
public double getPower()
{
return power;
}
@Override
public void load(NBTTagCompound nbt)
{
torque = nbt.getDouble("torque");
angularVelocity = nbt.getDouble("angularVelocity");
}
@Override
public void save(NBTTagCompound nbt)
{
nbt.setDouble("torque", torque);
nbt.setDouble("angularVelocity", angularVelocity);
}
@Override
public <B extends MechanicalNode> boolean canConnect(B other, ForgeDirection from)
{
if (canConnect(from))
{
if (other instanceof INodeProvider)
{
return ((INodeProvider) other).getNode(MechanicalNode.class, from.getOpposite()) instanceof MechanicalNode;
}
return other instanceof MechanicalNode;
}
return false;
}
@Override
public boolean isValidConnection(Object object)
{
return true;
}
}

View file

@ -0,0 +1,221 @@
package resonantinduction.mechanical.mech
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection
import resonant.api.grid.{INodeProvider, IUpdate}
import resonant.lib.grid.node.NodeConnector
import resonant.lib.transform.vector.IVectorWorld
import resonant.lib.utility.nbt.ISaveObj
import resonantinduction.core.interfaces.IMechanicalNode
import resonantinduction.core.prefab.node.TMultipartNode
import scala.collection.convert.wrapAll._
/**
* Prefab node for the mechanical system used by almost ever mechanical object in Resonant Induction. Handles connections to other tiles, and shares power with them
*
* @author Calclavia, Darkguardsman
*/
class MechanicalNode(parent: INodeProvider) extends NodeConnector[MechanicalNode](parent) with TMultipartNode[MechanicalNode] with IMechanicalNode with ISaveObj with IVectorWorld with IUpdate
{
/**
* Marks that the rotation has changed and should be updated client side
*/
var markRotationUpdate: Boolean = false
/**
* Makrs that the torque value has changed and should be updated client side
*/
var markTorqueUpdate: Boolean = false
/**
* Allows the node to share its power with other nodes
*/
var sharePower: Boolean = true
var torque: Double = 0
var prevTorque: Double = .0
var prevAngularVelocity: Double = .0
var angularVelocity: Double = 0
/**
* Current angle of rotation, mainly used for rendering
*/
var renderAngle: Double = 0
/**
* Angle of rotation of last update
*/
var prev_angle: Double = 0
var acceleration: Float = 2f
protected var maxDeltaAngle: Double = Math.toRadians(120)
protected var load: Double = 2
private var power: Double = 0
override def getRadius(dir: ForgeDirection, `with`: IMechanicalNode): Double = 0.5
override def getAngularSpeed(side: ForgeDirection): Double = angularVelocity
override def getForce(side: ForgeDirection): Double = torque
override def inverseRotation(side: ForgeDirection): Boolean = false
override def update(deltaTime: Double)
{
if (angularVelocity >= 0)
{
renderAngle += Math.min(angularVelocity, this.maxDeltaAngle) * deltaTime
}
else
{
renderAngle += Math.max(angularVelocity, -this.maxDeltaAngle) * deltaTime
}
if (renderAngle >= Math.PI * 2)
{
revolve
renderAngle = renderAngle % (Math.PI * 2)
}
if (world != null && !world.isRemote)
{
val acceleration: Double = this.acceleration * deltaTime
if (Math.abs(prevAngularVelocity - angularVelocity) > 0.01f)
{
prevAngularVelocity = angularVelocity
markRotationUpdate = true
}
if (Math.abs(prevTorque - torque) > 0.01f)
{
prevTorque = torque
markTorqueUpdate = true
}
val torqueLoss: Double = Math.min(Math.abs(getTorque), (Math.abs(getTorque * getTorqueLoad) + getTorqueLoad / 10) * deltaTime)
torque += (if (torque > 0) -torqueLoss else torqueLoss)
val velocityLoss: Double = Math.min(Math.abs(getAngularSpeed), (Math.abs(getAngularSpeed * getAngularVelocityLoad) + getAngularVelocityLoad / 10) * deltaTime)
angularVelocity += (if (angularVelocity > 0) -velocityLoss else velocityLoss)
if (getEnergy <= 0)
{
angularVelocity = ({torque = 0; torque })
}
power = getEnergy / deltaTime
if (sharePower)
{
directionMap.foreach
{
case (adjacentMech: MechanicalNode, dir: ForgeDirection) =>
{
if (adjacentMech != null)
{
val ratio: Double = adjacentMech.getRadius(dir.getOpposite, this) / getRadius(dir, adjacentMech)
val inverseRotation: Boolean = this.inverseRotation(dir) && adjacentMech.inverseRotation(dir.getOpposite)
val inversion: Int = if (inverseRotation) -1 else 1
val targetTorque: Double = inversion * adjacentMech.getTorque / ratio
val applyTorque: Double = targetTorque * acceleration
if (Math.abs(torque + applyTorque) < Math.abs(targetTorque))
{
torque += applyTorque
}
else if (Math.abs(torque - applyTorque) > Math.abs(targetTorque))
{
torque -= applyTorque
}
val targetVelocity: Double = inversion * adjacentMech.getAngularSpeed * ratio
val applyVelocity: Double = targetVelocity * acceleration
if (Math.abs(angularVelocity + applyVelocity) < Math.abs(targetVelocity))
{
angularVelocity += applyVelocity
}
else if (Math.abs(angularVelocity - applyVelocity) > Math.abs(targetVelocity))
{
angularVelocity -= applyVelocity
}
}
}
}
}
}
prev_angle = renderAngle
}
override def canUpdate: Boolean = true
override def continueUpdate: Boolean = true
/**
* Called when one revolution is made.
*/
protected def revolve
{
}
override def apply(source: AnyRef, torque: Double, angularVelocity: Double)
{
this.torque += torque
this.angularVelocity += angularVelocity
}
private def getTorque: Double =
{
return if (angularVelocity != 0) torque else 0
}
private def getAngularSpeed: Double =
{
return if (torque != 0) angularVelocity else 0
}
/**
* The energy percentage loss due to resistance in seconds.
*/
def getTorqueLoad: Double =
{
return load
}
def getAngularVelocityLoad: Double =
{
return load
}
def getEnergy: Double =
{
return getTorque * getAngularSpeed
}
def getPower: Double =
{
return power
}
def load(nbt: NBTTagCompound)
{
torque = nbt.getDouble("torque")
angularVelocity = nbt.getDouble("angularVelocity")
}
def save(nbt: NBTTagCompound)
{
nbt.setDouble("torque", torque)
nbt.setDouble("angularVelocity", angularVelocity)
}
/**
* Can this node connect with another node?
* @param other - Most likely a node, but it can also be another object
* @param from - Direction of connection
* @return True connection is allowed
*/
override def canConnect[B <: MechanicalNode](other: B, from: ForgeDirection): Boolean =
{
if (canConnect(from))
{
if (other.isInstanceOf[INodeProvider])
{
return (other.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], from.getOpposite).isInstanceOf[MechanicalNode]
}
return other.isInstanceOf[MechanicalNode]
}
return false
}
override def isValidConnection(`object`: AnyRef): Boolean =
{
return true
}
}

View file

@ -52,18 +52,19 @@ abstract class PartMechanical extends PartAbstract with JNormalOcclusion with TF
}
}
override def update
override def update()
{
this.mechanicalNode.update
if (!world.isRemote)
{
checkClientUpdate
checkClientUpdate()
}
if (frame != null)
{
frame.update
}
super.update
super.update()
}
override def activate(player: EntityPlayer, hit: MovingObjectPosition, itemStack: ItemStack): Boolean =

View file

@ -4,12 +4,11 @@ import codechicken.lib.vec.Rotation
import codechicken.multipart.{TMultiPart, TileMultipart}
import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.util.ForgeDirection
import resonant.lib.grid.electric.DCNode
import resonant.api.grid.INodeProvider
import resonant.lib.transform.vector.{IVectorWorld, Vector3, VectorWorld}
import resonantinduction.core.interfaces.IMechanicalNode
import resonantinduction.mechanical.mech.MechanicalNode
import resonantinduction.mechanical.mech.gearshaft.PartGearShaft
import resonant.api.grid.INodeProvider
import resonant.lib.transform.vector.{IVectorWorld, Vector3, VectorWorld}
/**
* Node for the gear
@ -19,205 +18,205 @@ import resonant.lib.transform.vector.{IVectorWorld, Vector3, VectorWorld}
class GearNode(parent: PartGear) extends MechanicalNode(parent: PartGear)
{
protected def gear: PartGear =
{
return this.getParent.asInstanceOf[PartGear]
}
protected def gear: PartGear =
{
return this.getParent.asInstanceOf[PartGear]
}
override def onUpdate
override def update(deltaTime: Double)
{
super.update(deltaTime)
if (!gear.getMultiBlock.isPrimary)
{
super.onUpdate
if (!gear.getMultiBlock.isPrimary)
{
torque = 0
angularVelocity = 0
}
else if (gear.tier == 10)
{
torque = 100
angularVelocity = 100
}
torque = 0
angularVelocity = 0
}
override def getTorqueLoad: Double =
else if (gear.tier == 10)
{
if (gear.tier == 1) return 0.2
if (gear.tier == 2) return 0.1
if (gear.tier == 0) return 0
return 0.3
torque = 100
angularVelocity = 100
}
}
override def getAngularVelocityLoad: Double =
override def getTorqueLoad: Double =
{
if (gear.tier == 1) return 0.2
if (gear.tier == 2) return 0.1
if (gear.tier == 0) return 0
return 0.3
}
override def getAngularVelocityLoad: Double =
{
if (gear.tier == 1) return 0.2
if (gear.tier == 2) return 0.1
if (gear.tier == 0) return 0
return 0.3
}
override def reconstruct()
{
connections.clear
if (!gear.getMultiBlock.isPrimary || world == null)
{
if (gear.tier == 1) return 0.2
if (gear.tier == 2) return 0.1
if (gear.tier == 0) return 0
return 0.3
return
}
override def reconstruct()
val tileBehind: TileEntity = new Vector3(gear.tile).add(gear.placementSide).getTileEntity(world)
if (tileBehind.isInstanceOf[INodeProvider])
{
connections.clear
if (!gear.getMultiBlock.isPrimary || world == null)
{
return
}
val tileBehind: TileEntity = new Vector3(gear.tile).add(gear.placementSide).getTileEntity(world)
if (tileBehind.isInstanceOf[INodeProvider])
{
val instance: MechanicalNode = (tileBehind.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], gear.placementSide.getOpposite).asInstanceOf[MechanicalNode]
if (instance != null && instance != this && !(instance.getParent.isInstanceOf[PartGearShaft]) && instance.canConnect(this,gear.placementSide.getOpposite))
{
connect(instance, gear.placementSide)
}
}
for (i <- 0 until 6)
{
val checkDir: ForgeDirection = ForgeDirection.getOrientation(i)
var tile: TileEntity = gear.tile
if (gear.getMultiBlock.isConstructed && checkDir != gear.placementSide && checkDir != gear.placementSide.getOpposite)
{
tile = new Vector3(gear.tile).add(checkDir).getTileEntity(world)
}
if (tile.isInstanceOf[INodeProvider])
{
val instance: MechanicalNode = (tile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], if (checkDir == gear.placementSide.getOpposite) ForgeDirection.UNKNOWN else checkDir).asInstanceOf[MechanicalNode]
if (!directionMap.containsValue(checkDir) && instance != this && checkDir != gear.placementSide && instance != null && instance.canConnect(this,checkDir.getOpposite))
{
connect(instance, checkDir)
}
}
}
var displaceCheck: Int = 1
if (gear.getMultiBlock.isPrimary && gear.getMultiBlock.isConstructed)
{
displaceCheck = 2
}
for (i <- 0 until 4)
{
val checkDir: ForgeDirection = ForgeDirection.getOrientation(Rotation.rotateSide(gear.placementSide.ordinal, i))
val checkTile: TileEntity = new Vector3(gear.tile).add(checkDir).getTileEntity(world)
if (!directionMap.containsValue(checkDir) && checkTile.isInstanceOf[INodeProvider])
{
val instance: MechanicalNode = (checkTile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], gear.placementSide).asInstanceOf[MechanicalNode]
if (instance != null && instance != this && instance.canConnect(this,checkDir.getOpposite) && !(instance.getParent.isInstanceOf[PartGearShaft]))
{
connect(instance, checkDir)
}
}
}
val instance: MechanicalNode = (tileBehind.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], gear.placementSide.getOpposite).asInstanceOf[MechanicalNode]
if (instance != null && instance != this && !(instance.getParent.isInstanceOf[PartGearShaft]) && instance.canConnect(this, gear.placementSide.getOpposite))
{
connect(instance, gear.placementSide)
}
}
/**
* Can this gear be connected BY the source?
*
* @param from - Direction source is coming from.
* @param other - The source of the connection.
* @return True is so.
*/
override def canConnect[B](other: B, from: ForgeDirection): Boolean =
for (i <- 0 until 6)
{
if (!gear.getMultiBlock.isPrimary)
val checkDir: ForgeDirection = ForgeDirection.getOrientation(i)
var tile: TileEntity = gear.tile
if (gear.getMultiBlock.isConstructed && checkDir != gear.placementSide && checkDir != gear.placementSide.getOpposite)
{
tile = new Vector3(gear.tile).add(checkDir).getTileEntity(world)
}
if (tile.isInstanceOf[INodeProvider])
{
val instance: MechanicalNode = (tile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], if (checkDir == gear.placementSide.getOpposite) ForgeDirection.UNKNOWN else checkDir).asInstanceOf[MechanicalNode]
if (!directionMap.containsValue(checkDir) && instance != this && checkDir != gear.placementSide && instance != null && instance.canConnect(this, checkDir.getOpposite))
{
return false
connect(instance, checkDir)
}
if (other.isInstanceOf[MechanicalNode])
}
}
var displaceCheck: Int = 1
if (gear.getMultiBlock.isPrimary && gear.getMultiBlock.isConstructed)
{
displaceCheck = 2
}
for (i <- 0 until 4)
{
val checkDir: ForgeDirection = ForgeDirection.getOrientation(Rotation.rotateSide(gear.placementSide.ordinal, i))
val checkTile: TileEntity = new Vector3(gear.tile).add(checkDir).getTileEntity(world)
if (!directionMap.containsValue(checkDir) && checkTile.isInstanceOf[INodeProvider])
{
val instance: MechanicalNode = (checkTile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], gear.placementSide).asInstanceOf[MechanicalNode]
if (instance != null && instance != this && instance.canConnect(this, checkDir.getOpposite) && !(instance.getParent.isInstanceOf[PartGearShaft]))
{
val parent: INodeProvider = (other.asInstanceOf[MechanicalNode]).getParent
if (from == gear.placementSide.getOpposite)
connect(instance, checkDir)
}
}
}
}
/**
* Can this gear be connected BY the source?
*
* @param from - Direction source is coming from.
* @param other - The source of the connection.
* @return True is so.
*/
override def canConnect[B](other: B, from: ForgeDirection): Boolean =
{
if (!gear.getMultiBlock.isPrimary)
{
return false
}
if (other.isInstanceOf[MechanicalNode])
{
val parent: INodeProvider = (other.asInstanceOf[MechanicalNode]).getParent
if (from == gear.placementSide.getOpposite)
{
if (parent.isInstanceOf[PartGear] || parent.isInstanceOf[PartGearShaft])
{
if (parent.isInstanceOf[PartGearShaft])
{
val shaft: PartGearShaft = parent.asInstanceOf[PartGearShaft]
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.isInstanceOf[PartGear])
{
if ((parent.asInstanceOf[PartGear]).tile == gear.tile && !gear.getMultiBlock.isConstructed)
{
if (parent.isInstanceOf[PartGear] || parent.isInstanceOf[PartGearShaft])
{
if (parent.isInstanceOf[PartGearShaft])
{
val shaft: PartGearShaft = parent.asInstanceOf[PartGearShaft]
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.isInstanceOf[PartGear])
{
if ((parent.asInstanceOf[PartGear]).tile == gear.tile && !gear.getMultiBlock.isConstructed)
{
return true
}
if ((parent.asInstanceOf[PartGear]).placementSide ne gear.placementSide)
{
val part: TMultiPart = gear.tile.partMap((parent.asInstanceOf[PartGear]).placementSide.ordinal)
if (part.isInstanceOf[PartGear])
{
val sourceGear: PartGear = part.asInstanceOf[PartGear]
if (sourceGear.isCenterMultiBlock && !sourceGear.getMultiBlock.isPrimary)
{
return true
}
}
else
{
if (gear.getMultiBlock.isConstructed)
{
val checkPart: TMultiPart = (parent.asInstanceOf[PartGear]).tile.partMap(gear.placementSide.ordinal)
if (checkPart.isInstanceOf[PartGear])
{
val requiredDirection: ForgeDirection = (checkPart.asInstanceOf[PartGear]).getPosition.subtract(position).toForgeDirection
return (checkPart.asInstanceOf[PartGear]).isCenterMultiBlock && (parent.asInstanceOf[PartGear]).placementSide == requiredDirection
}
}
}
}
}
}
val sourceTile: TileEntity = position.add(from.getOpposite).getTileEntity(world)
if (sourceTile.isInstanceOf[INodeProvider])
{
val sourceInstance: MechanicalNode = (sourceTile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], from).asInstanceOf[MechanicalNode]
return sourceInstance == other
}
return true
}
else if (from == gear.placementSide)
if ((parent.asInstanceOf[PartGear]).placementSide ne gear.placementSide)
{
val sourceTile: TileEntity = position.add(from).getTileEntity(world)
if (sourceTile.isInstanceOf[INodeProvider])
val part: TMultiPart = gear.tile.partMap((parent.asInstanceOf[PartGear]).placementSide.ordinal)
if (part.isInstanceOf[PartGear])
{
val sourceGear: PartGear = part.asInstanceOf[PartGear]
if (sourceGear.isCenterMultiBlock && !sourceGear.getMultiBlock.isPrimary)
{
val sourceInstance: MechanicalNode = (sourceTile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], from.getOpposite).asInstanceOf[MechanicalNode]
return sourceInstance == other
return true
}
}
else
{
if (gear.getMultiBlock.isConstructed)
{
val checkPart: TMultiPart = (parent.asInstanceOf[PartGear]).tile.partMap(gear.placementSide.ordinal)
if (checkPart.isInstanceOf[PartGear])
{
val requiredDirection: ForgeDirection = (checkPart.asInstanceOf[PartGear]).getPosition.subtract(position).toForgeDirection
return (checkPart.asInstanceOf[PartGear]).isCenterMultiBlock && (parent.asInstanceOf[PartGear]).placementSide == requiredDirection
}
}
}
}
}
}
val sourceTile: TileEntity = position.add(from.getOpposite).getTileEntity(world)
if (sourceTile.isInstanceOf[INodeProvider])
{
val sourceInstance: MechanicalNode = (sourceTile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], from).asInstanceOf[MechanicalNode]
return sourceInstance == other
}
}
else if (from == gear.placementSide)
{
val sourceTile: TileEntity = position.add(from).getTileEntity(world)
if (sourceTile.isInstanceOf[INodeProvider])
{
val sourceInstance: MechanicalNode = (sourceTile.asInstanceOf[INodeProvider]).getNode(classOf[MechanicalNode], from.getOpposite).asInstanceOf[MechanicalNode]
return sourceInstance == other
}
}
else
{
val destinationTile: TileEntity = (other.asInstanceOf[MechanicalNode]).position.add(from.getOpposite).getTileEntity(world)
if (destinationTile.isInstanceOf[INodeProvider] && destinationTile.isInstanceOf[TileMultipart])
{
val destinationPart: TMultiPart = (destinationTile.asInstanceOf[TileMultipart]).partMap(gear.placementSide.ordinal)
if (destinationPart.isInstanceOf[PartGear])
{
if (gear ne destinationPart)
{
return (destinationPart.asInstanceOf[PartGear]).isCenterMultiBlock
}
else
{
val destinationTile: TileEntity = (other.asInstanceOf[MechanicalNode]).position.add(from.getOpposite).getTileEntity(world)
if (destinationTile.isInstanceOf[INodeProvider] && destinationTile.isInstanceOf[TileMultipart])
{
val destinationPart: TMultiPart = (destinationTile.asInstanceOf[TileMultipart]).partMap(gear.placementSide.ordinal)
if (destinationPart.isInstanceOf[PartGear])
{
if (gear ne destinationPart)
{
return (destinationPart.asInstanceOf[PartGear]).isCenterMultiBlock
}
else
{
return true
}
}
else
{
return true
}
}
return true
}
}
else
{
return true
}
}
return false
}
}
return false
}
override def getRadius(dir: ForgeDirection, `with`: IMechanicalNode): Double =
{
val deltaPos: Vector3 = new VectorWorld(`with`.asInstanceOf[IVectorWorld]).subtract(position)
val caseX: Boolean = gear.placementSide.offsetX != 0 && deltaPos.y == 0 && deltaPos.z == 0
val caseY: Boolean = gear.placementSide.offsetY != 0 && deltaPos.x == 0 && deltaPos.z == 0
val caseZ: Boolean = gear.placementSide.offsetZ != 0 && deltaPos.x == 0 && deltaPos.y == 0
if (caseX || caseY || caseZ)
{
val deltaPos: Vector3 = new VectorWorld(`with`.asInstanceOf[IVectorWorld]).subtract(position)
val caseX: Boolean = gear.placementSide.offsetX != 0 && deltaPos.y == 0 && deltaPos.z == 0
val caseY: Boolean = gear.placementSide.offsetY != 0 && deltaPos.x == 0 && deltaPos.z == 0
val caseZ: Boolean = gear.placementSide.offsetZ != 0 && deltaPos.x == 0 && deltaPos.y == 0
if (caseX || caseY || caseZ)
{
return super.getRadius(dir, `with`)
}
return if (gear.getMultiBlock.isConstructed) 1.5f else super.getRadius(dir, `with`)
return super.getRadius(dir, `with`)
}
return if (gear.getMultiBlock.isConstructed) 1.5f else super.getRadius(dir, `with`)
}
}