Started reworking MechanicalNode
This commit is contained in:
parent
eb39dcf90d
commit
47a4ea6ef1
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
@ -24,9 +23,9 @@ class GearNode(parent: PartGear) extends MechanicalNode(parent: PartGear)
|
|||
return this.getParent.asInstanceOf[PartGear]
|
||||
}
|
||||
|
||||
override def onUpdate
|
||||
override def update(deltaTime: Double)
|
||||
{
|
||||
super.onUpdate
|
||||
super.update(deltaTime)
|
||||
if (!gear.getMultiBlock.isPrimary)
|
||||
{
|
||||
torque = 0
|
||||
|
|
Loading…
Reference in a new issue