package edx.mechanical.mech.gear import codechicken.lib.vec.Rotation import codechicken.multipart.TileMultipart import edx.core.interfaces.TNodeMechanical import edx.mechanical.mech.gearshaft.{NodeGearShaft, PartGearShaft} import edx.mechanical.mech.grid.NodeMechanical import net.minecraft.tileentity.TileEntity import net.minecraftforge.common.util.ForgeDirection import resonantengine.api.graph.INodeProvider import resonantengine.lib.transform.vector.Vector3 import resonantengine.lib.wrapper.ForgeDirectionWrapper._ /** * Node for the gear * * @author Calclavia, Edited by: Darkguardsman */ class NodeGear(parent: PartGear) extends NodeMechanical(parent: PartGear) { override def angleDisplacement = if (gear.getMultiBlock.isConstructed) Math.PI / 36 else Math.PI / 12 override def inertia: Double = { gear.tier match { case 0 => 50 case 1 => 20 case 2 => 15 } } protected def gear = getParent.asInstanceOf[PartGear] override def friction: Double = { gear.tier match { case 0 => 1 case 1 => 1.5 case 2 => 1.3 } } override def reconstruct() { if (!parent.getMultiBlock.isPrimary) { parent.getMultiBlock.getPrimary.mechanicalNode.reconstruct() } super.reconstruct() } override def rebuild() { if (!gear.getMultiBlock.isPrimary || world == null) { return } //Check behind val tileBehind = new Vector3(gear.tile).add(gear.placementSide).getTileEntity(world) if (tileBehind.isInstanceOf[INodeProvider]) { val other = tileBehind.asInstanceOf[INodeProvider].getNode(classOf[NodeMechanical], gear.placementSide.getOpposite) if (other != null && other != this && !other.getParent.isInstanceOf[PartGearShaft] && other.canConnect(this, gear.placementSide.getOpposite)) { connect(other, gear.placementSide) } } //Check internal for (i <- 0 until 6) { val toDir = ForgeDirection.getOrientation(i) var tile: TileEntity = gear.tile if (gear.getMultiBlock.isConstructed && toDir != gear.placementSide && toDir != gear.placementSide.getOpposite) { tile = new Vector3(gear.tile).add(toDir).getTileEntity(world) } if (tile.isInstanceOf[INodeProvider]) { val other = tile.asInstanceOf[INodeProvider].getNode(classOf[NodeMechanical], if (toDir == gear.placementSide.getOpposite) ForgeDirection.UNKNOWN else toDir) if (other != this && toDir != gear.placementSide && other != null && canConnect(other, toDir) && other.canConnect(this, toDir.getOpposite)) { connect(other, toDir) } } } //TODO: Change this to the radius of the gear val checkDisplacement = if (gear.getMultiBlock.isPrimary && gear.getMultiBlock.isConstructed) 2 else 1 //Check the sides of the gear for any other gear connections for (i <- 0 until 4) { val toDir = ForgeDirection.getOrientation(Rotation.rotateSide(gear.placementSide.ordinal, i)) val checkTile = (new Vector3(gear.tile) + (new Vector3(toDir) * checkDisplacement)).getTileEntity(world) if (!directionMap.containsValue(toDir) && checkTile.isInstanceOf[INodeProvider]) { val other = checkTile.asInstanceOf[INodeProvider].getNode(classOf[NodeMechanical], gear.placementSide) if (other != null && other != this && canConnect(other, toDir) && other.canConnect(this, toDir.getOpposite) && !other.isInstanceOf[NodeGearShaft]) { connect(other, toDir) } } } } /** * 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 <: NodeMechanical](other: B, from: ForgeDirection): Boolean = { if (!gear.getMultiBlock.isPrimary) { return false } if (other.isInstanceOf[NodeMechanical]) { val otherParent = other.getParent if (from == gear.placementSide) { //This object is coming from the back of the gear //Check if it's a gear that's connected back-to-back if (otherParent.isInstanceOf[PartGear]) { val otherGearPart = otherParent.asInstanceOf[PartGear] if (otherGearPart.placementSide == parent.placementSide.getOpposite) { //Check if it is the center of another gear (if it is a multiblock) return otherGearPart.getMultiBlock.isPrimary } } //It's not a gear. It might be be another tile node val sourceTile = toVectorWorld.add(from).getTileEntity(world) if (sourceTile.isInstanceOf[INodeProvider]) { //Found a potential node. Check if it is actually adjacent to the gear. val sourceInstance = sourceTile.asInstanceOf[INodeProvider].getNode(classOf[NodeMechanical], from) return sourceInstance == other } } else if (from == gear.placementSide.getOpposite) { //This object is from the front of the gear //Check if it's a gear internally if (otherParent.isInstanceOf[PartGear]) { //Check internal gears if (otherParent.asInstanceOf[PartGear].tile == parent.tile && !parent.getMultiBlock.isConstructed) { return true // otherParent.asInstanceOf[PartGear].placementSide != parent.placementSide.getOpposite } if (otherParent.asInstanceOf[PartGear].placementSide != gear.placementSide) { val part = gear.tile.partMap(otherParent.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 = otherParent.asInstanceOf[PartGear].tile.partMap(gear.placementSide.ordinal) if (checkPart.isInstanceOf[PartGear]) { val requiredDirection = checkPart.asInstanceOf[PartGear].getPosition.subtract(toVectorWorld).toForgeDirection return checkPart.asInstanceOf[PartGear].isCenterMultiBlock && otherParent.asInstanceOf[PartGear].placementSide == requiredDirection } } } } } //Check if it's a shaft if (otherParent.isInstanceOf[PartGearShaft]) { //We are connecting to a shaft. val shaft = otherParent.asInstanceOf[PartGearShaft] /*shaft.tile.partMap(from.getOpposite.ordinal) != gear && */ return 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 (from != ForgeDirection.UNKNOWN) { //This object is from the sides of the gear. It can either be a gear within this block or outside if (other.isInstanceOf[NodeGear]) { val otherParent = other.parent.asInstanceOf[PartGear] //Check inside this block if (otherParent.tile == parent.tile) { return otherParent.placementSide != parent.placementSide && otherParent != parent.placementSide.getOpposite } //Check for gear outside this block placed on the same plane val otherTile = other.toVectorWorld.getTileEntity if (otherTile.isInstanceOf[TileMultipart]) { if (otherTile.asInstanceOf[TileMultipart].partMap(gear.placementSide.ordinal()) == other.parent) { //We found another gear, but check if we are connecting to the center spaces of the gear //If this is a multiblock, "otherTile" would be the center of that gear, not the adjacent val adjacentTile = toVectorWorld.add(from).getTileEntity if (adjacentTile.isInstanceOf[TileMultipart]) { val adjacentPart = adjacentTile.asInstanceOf[TileMultipart].partMap(gear.placementSide.ordinal) return adjacentPart.asInstanceOf[PartGear].isCenterMultiBlock } } } } } } return false } override def inverseRotation(other: TNodeMechanical): Boolean = { if (other.isInstanceOf[NodeGearShaft]) { return parent.placementSide.offset < Vector3.zero } return !other.isInstanceOf[NodeGearShaft] } override def radius(other: TNodeMechanical): Double = { val deltaPos = other.asInstanceOf[NodeMechanical].toVectorWorld - toVectorWorld val caseX = gear.placementSide.offsetX != 0 && deltaPos.y == 0 && deltaPos.z == 0 val caseY = gear.placementSide.offsetY != 0 && deltaPos.x == 0 && deltaPos.z == 0 val caseZ = gear.placementSide.offsetZ != 0 && deltaPos.x == 0 && deltaPos.y == 0 if (caseX || caseY || caseZ) return super.radius(other) if (gear.getMultiBlock.isConstructed) 1.5 else super.radius(other) } }