From 47a4ea6ef1870c97711fae04235e4a3bbd55ad29 Mon Sep 17 00:00:00 2001 From: Calclavia Date: Thu, 6 Nov 2014 14:05:42 +0800 Subject: [PATCH] Started reworking MechanicalNode --- .../mechanical/mech/DebugFrameMechanical.java | 6 +- .../mechanical/mech/MechanicalNode.java | 336 ----------------- .../mechanical/mech/MechanicalNode.scala | 221 +++++++++++ .../mechanical/mech/PartMechanical.scala | 9 +- .../mechanical/mech/gear/GearNode.scala | 349 +++++++++--------- 5 files changed, 403 insertions(+), 518 deletions(-) delete mode 100644 src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.java create mode 100644 src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.scala diff --git a/src/main/scala/resonantinduction/mechanical/mech/DebugFrameMechanical.java b/src/main/scala/resonantinduction/mechanical/mech/DebugFrameMechanical.java index 634cc39d6..2929dbc76 100644 --- a/src/main/scala/resonantinduction/mechanical/mech/DebugFrameMechanical.java +++ b/src/main/scala/resonantinduction/mechanical/mech/DebugFrameMechanical.java @@ -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); diff --git a/src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.java b/src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.java deleted file mode 100644 index 44a88df28..000000000 --- a/src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.java +++ /dev/null @@ -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 implements TMultipartNode, 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> it = directionMap().entrySet().iterator(); - - while (it.hasNext()) - { - MechanicalNode adjacentMech = null; - Entry 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 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; - } -} diff --git a/src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.scala b/src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.scala new file mode 100644 index 000000000..5508c6f09 --- /dev/null +++ b/src/main/scala/resonantinduction/mechanical/mech/MechanicalNode.scala @@ -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 + } +} \ No newline at end of file diff --git a/src/main/scala/resonantinduction/mechanical/mech/PartMechanical.scala b/src/main/scala/resonantinduction/mechanical/mech/PartMechanical.scala index 4fa88228d..0e4bdf9b5 100644 --- a/src/main/scala/resonantinduction/mechanical/mech/PartMechanical.scala +++ b/src/main/scala/resonantinduction/mechanical/mech/PartMechanical.scala @@ -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 = diff --git a/src/main/scala/resonantinduction/mechanical/mech/gear/GearNode.scala b/src/main/scala/resonantinduction/mechanical/mech/gear/GearNode.scala index 942fb2633..8c232b6a5 100644 --- a/src/main/scala/resonantinduction/mechanical/mech/gear/GearNode.scala +++ b/src/main/scala/resonantinduction/mechanical/mech/gear/GearNode.scala @@ -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`) + } } \ No newline at end of file