electrodynamics/src/main/scala/edx/electrical/wire/flat/PartFlatWire.scala

873 lines
22 KiB
Scala
Raw Normal View History

2015-01-14 12:06:03 +01:00
package edx.electrical.wire.flat
import java.lang.{Iterable => JIterable}
import codechicken.lib.data.{MCDataInput, MCDataOutput}
import codechicken.lib.raytracer.IndexedCuboid6
import codechicken.lib.render.{CCRenderState, TextureUtils}
import codechicken.lib.vec.{BlockCoord, Cuboid6, Rotation, Vector3}
import codechicken.multipart._
import cpw.mods.fml.relauncher.{Side, SideOnly}
2015-01-14 12:06:03 +01:00
import edx.core.prefab.node.TMultipartNode
import edx.core.prefab.part.ChickenBonesWrapper._
import edx.core.prefab.part.connector.{PartAbstract, TColorable}
import edx.core.util.MultipartUtil
import edx.electrical.wire.base.TWire
import net.minecraft.client.renderer.RenderBlocks
import net.minecraft.entity.player.EntityPlayer
2014-10-12 09:09:59 +02:00
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.{IIcon, MovingObjectPosition}
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
2014-12-09 23:46:07 +01:00
import resonant.api.tile.INodeProvider
2015-01-21 12:08:36 +01:00
import resonant.lib.grid.energy.electric.{NodeElectricComponent, NodeElectricJunction}
import scala.collection.convert.wrapAll._
/**
* This is the class for all flat wire types. It can be used for any sub type, as it contains the
* base calculations necessary to create a working wire. This calculates all possible connections to
* sides, around corners, and inside corners, while checking for microblock obstructions.
*
* @author Calclavia, MrTJP
*/
object PartFlatWire
{
var selectionBounds = Array.ofDim[Cuboid6](3, 6)
var occlusionBounds = Array.ofDim[Cuboid6](3, 6)
2014-09-16 05:33:38 +02:00
init()
2014-09-16 05:33:38 +02:00
def init()
{
2014-09-16 05:33:38 +02:00
for (t <- 0 until 3)
{
2014-09-16 05:33:38 +02:00
val selection = new Cuboid6(0, 0, 0, 1, (t + 2) / 16D, 1).expand(-0.005)
val occlusion = new Cuboid6(2 / 8D, 0, 2 / 8D, 6 / 8D, (t + 2) / 16D, 6 / 8D)
for (s <- 0 until 6)
{
selectionBounds(t)(s) = selection.copy.apply(Rotation.sideRotations(s).at(Vector3.center))
occlusionBounds(t)(s) = occlusion.copy.apply(Rotation.sideRotations(s).at(Vector3.center))
}
}
}
}
class PartFlatWire extends PartAbstract with TWire with TFacePart with TNormalOcclusion
{
private val electricNode = new NodeFlatWire(this)
2014-09-14 09:02:11 +02:00
/**
* The current side the wire is placed on
*/
var side: Byte = 0
/**
* A map of the corners.
*
* Currently split into 4 nybbles (from lowest) 0 = Corner connections (this wire should connect
* around a corner to something external) 1 = Straight connections (this wire should connect to
* something external) 2 = Internal connections (this wire should connect to something internal)
* 3 = Internal open connections (this wire is not blocked by a cover/edge part and *could*
* connect through side) bit 16 = connection to the centerpart 5 = Render corner connections.
* Like corner connections but set to low if the other wire part is smaller than this (they
* render to us not us to them)
*/
2014-09-21 09:17:33 +02:00
var connectionMask = 0x00
nodes.add(electricNode)
2014-09-14 09:02:11 +02:00
2014-09-14 09:48:55 +02:00
def preparePlacement(side: Int, meta: Int)
{
this.side = (side ^ 1).toByte
setMaterial(meta)
2014-10-12 09:09:59 +02:00
}
2015-01-08 14:24:04 +01:00
override def setMaterial(i: Int)
{
super.setMaterial(i)
electricNode.resistance = material.resistance
2015-01-08 14:24:04 +01:00
}
2014-10-12 10:51:44 +02:00
override def update()
2014-10-12 09:09:59 +02:00
{
2014-10-12 10:51:44 +02:00
super.update()
2014-11-04 15:52:14 +01:00
}
2014-10-12 10:51:44 +02:00
override def activate(player: EntityPlayer, hit: MovingObjectPosition, item: ItemStack): Boolean =
{
if (!world.isRemote)
{
println(electricNode)
2014-10-12 10:51:44 +02:00
}
2014-10-12 09:09:59 +02:00
return true
2014-09-14 09:48:55 +02:00
}
def renderThisCorner(part: PartFlatWire): Boolean =
{
2014-09-14 09:48:55 +02:00
if (!(part.isInstanceOf[PartFlatWire]))
{
return false
}
val wire: PartFlatWire = part
if (wire.getThickness == getThickness)
{
return side < wire.side
}
return wire.getThickness > getThickness
}
2015-01-17 05:26:14 +01:00
def getThickness: Int = if (insulated) 1 else 0
/**
2014-09-14 09:48:55 +02:00
* Packet Methods
*/
override def load(tag: NBTTagCompound)
{
super.load(tag)
2014-09-16 06:00:10 +02:00
side = tag.getByte("side")
2014-09-21 09:17:33 +02:00
connectionMask = tag.getInteger("connMap")
}
override def save(tag: NBTTagCompound)
{
super.save(tag)
2014-09-16 06:00:10 +02:00
tag.setByte("side", side)
2014-09-21 09:17:33 +02:00
tag.setInteger("connMap", connectionMask)
}
2014-11-10 14:41:46 +01:00
override def write(packet: MCDataOutput, id: Int)
{
super[PartAbstract].write(packet, id)
2014-11-10 14:41:46 +01:00
super.write(packet, id)
2014-11-10 14:41:46 +01:00
id match
{
case 0 =>
packet.writeByte(side)
packet.writeInt(connectionMask)
case 3 =>
packet.writeInt(connectionMask)
}
2014-09-16 05:33:38 +02:00
}
2014-11-10 14:41:46 +01:00
override def read(packet: MCDataInput, id: Int)
{
super[PartAbstract].read(packet, id)
2014-11-10 14:41:46 +01:00
super.read(packet, id)
2014-09-16 06:00:10 +02:00
2014-11-10 14:41:46 +01:00
id match
2014-09-16 06:00:10 +02:00
{
2014-11-10 14:41:46 +01:00
case 0 =>
side = packet.readByte()
connectionMask = packet.readInt()
2014-11-10 14:41:46 +01:00
case 3 =>
connectionMask = packet.readInt()
2014-11-10 14:41:46 +01:00
tile.markRender()
2014-09-16 06:00:10 +02:00
}
}
2014-09-14 09:48:55 +02:00
/**
* Events
*/
override def onRemoved()
{
2014-09-14 09:48:55 +02:00
super.onRemoved()
if (!world.isRemote)
{
2014-09-14 09:02:11 +02:00
for (r <- 0 until 4)
{
2014-09-14 09:02:11 +02:00
if (maskConnects(r))
{
2014-09-21 09:17:33 +02:00
if ((connectionMask & 1 << r) != 0)
2014-09-14 09:02:11 +02:00
notifyCornerChange(r)
2014-09-21 09:17:33 +02:00
else if ((connectionMask & 0x10 << r) != 0)
2014-09-14 09:02:11 +02:00
notifyStraightChange(r)
}
}
}
}
2015-01-08 14:24:04 +01:00
def notifyCornerChange(r: Int)
{
val absDir = Rotation.rotateSide(side, r)
val pos = new BlockCoord(tile).offset(absDir).offset(side)
world.notifyBlockOfNeighborChange(pos.x, pos.y, pos.z, tile.getBlockType)
}
def notifyStraightChange(r: Int)
{
val absDir = Rotation.rotateSide(side, r)
val pos = new BlockCoord(tile).offset(absDir)
world.notifyBlockOfNeighborChange(pos.x, pos.y, pos.z, tile.getBlockType)
}
def maskConnects(r: Int): Boolean =
{
return (connectionMask & 0x111 << r) != 0
}
2014-09-14 09:48:55 +02:00
override def onChunkLoad()
{
2014-09-21 09:17:33 +02:00
if ((connectionMask & 0x80000000) != 0)
{
if (dropIfCantStay)
return
2014-09-14 09:48:55 +02:00
2014-09-21 09:17:33 +02:00
connectionMask = 0
2014-09-14 09:48:55 +02:00
tile.markDirty()
}
2014-09-14 09:02:11 +02:00
super.onChunkLoad()
}
2015-01-17 05:28:43 +01:00
def dropIfCantStay: Boolean =
{
if (!canStay)
{
drop
return true
}
return false
}
def canStay: Boolean =
{
val pos: BlockCoord = new BlockCoord(tile).offset(side)
return MultipartUtil.canPlaceWireOnSide(world, pos.x, pos.y, pos.z, ForgeDirection.getOrientation(side ^ 1), false)
}
def drop
{
TileMultipart.dropItem(getItem, world, Vector3.fromTileEntityCenter(tile))
tile.remPart(this)
}
2014-09-16 05:33:38 +02:00
override def onAdded()
{
2014-09-14 09:02:11 +02:00
super.onAdded()
if (!world.isRemote)
2014-11-10 14:41:46 +01:00
sendPacket(3)
}
override def onPartChanged(part: TMultiPart)
{
super.onPartChanged(part)
if (!world.isRemote)
2014-11-10 14:41:46 +01:00
sendPacket(3)
}
2014-09-16 05:33:38 +02:00
override def onNeighborChanged()
{
if (!world.isRemote)
if (dropIfCantStay)
return
2014-09-14 09:48:55 +02:00
super.onNeighborChanged()
if (!world.isRemote)
2014-11-10 14:41:46 +01:00
sendPacket(3)
}
2014-09-14 09:48:55 +02:00
def maskOpen(r: Int): Boolean =
{
2014-09-21 09:17:33 +02:00
return (connectionMask & 0x1000 << r) != 0
2014-09-14 09:48:55 +02:00
}
2014-09-14 09:48:55 +02:00
/**
2014-09-16 06:00:10 +02:00
* Multipart Methods
2014-09-14 09:48:55 +02:00
*/
2014-11-02 15:53:45 +01:00
override def getStrength(hit: MovingObjectPosition, player: EntityPlayer): Float = 4
2014-09-16 05:33:38 +02:00
def getSlotMask: Int = 1 << side
2014-09-14 09:48:55 +02:00
override def getSubParts: JIterable[IndexedCuboid6] = Seq(new IndexedCuboid6(0, PartFlatWire.selectionBounds(getThickness)(side)))
2015-01-14 12:06:03 +01:00
def getOcclusionBoxes: JIterable[Cuboid6] = Seq(PartFlatWire.occlusionBounds(getThickness)(side))
2014-09-14 09:48:55 +02:00
override def solid(arg0: Int) = false
2014-09-14 09:48:55 +02:00
/**
* Rendering
*/
@SideOnly(Side.CLIENT)
2014-11-04 14:41:07 +01:00
def getIcon: IIcon = RenderFlatWire.wireIcon
2014-09-14 09:48:55 +02:00
@SideOnly(Side.CLIENT)
override def renderStatic(pos: Vector3, pass: Int): Boolean =
{
2014-09-14 09:48:55 +02:00
if (pass == 0 && useStaticRenderer)
{
2014-09-14 09:48:55 +02:00
CCRenderState.setBrightness(world, x, y, z)
RenderFlatWire.render(this, pos)
CCRenderState.setColour(-1)
return true
}
2014-09-14 09:48:55 +02:00
return false
}
2014-09-14 09:48:55 +02:00
@SideOnly(Side.CLIENT)
override def renderDynamic(pos: Vector3, frame: Float, pass: Int)
{
2014-09-14 09:48:55 +02:00
if (pass == 0 && !useStaticRenderer)
{
2014-09-14 09:48:55 +02:00
GL11.glDisable(GL11.GL_LIGHTING)
TextureUtils.bindAtlas(0)
CCRenderState.startDrawing(7)
RenderFlatWire.render(this, pos)
2015-01-17 05:26:14 +01:00
CCRenderState.draw()
2014-09-14 09:48:55 +02:00
CCRenderState.setColour(-1)
GL11.glEnable(GL11.GL_LIGHTING)
}
}
2015-01-21 12:08:36 +01:00
def useStaticRenderer: Boolean = true
2014-09-14 09:48:55 +02:00
@SideOnly(Side.CLIENT)
override def drawBreaking(renderBlocks: RenderBlocks)
{
2014-09-14 09:48:55 +02:00
CCRenderState.reset()
RenderFlatWire.renderBreakingOverlay(renderBlocks.overrideBlockTexture, this)
}
/**
2014-09-14 09:48:55 +02:00
* Flat wire node handles all the connection logic
* TODO: ForgeDirection may NOT be suitable. Integers are better.
* @param provider
*/
2015-01-21 12:08:36 +01:00
class NodeFlatWire(provider: INodeProvider) extends NodeElectricJunction(provider) with TMultipartNode[NodeElectricComponent]
{
2014-10-26 15:41:40 +01:00
override def reconstruct()
{
2014-09-16 06:00:10 +02:00
if (!world.isRemote)
2014-09-14 09:48:55 +02:00
{
2014-11-02 15:53:45 +01:00
directionMap.clear()
2014-09-16 06:00:10 +02:00
updateOpenConnections()
/**
* 6 bit bitmask to mark sides that are already calculated to determine which side to disconnect.
* TODO: Check if the bitshifting is correct
* E.g: 000010
*/
var calculatedMask = 0x00
/**
* External connections
*/
for (r <- 0 until 4)
{
2014-09-16 06:00:10 +02:00
if (maskOpen(r))
{
2014-09-16 06:00:10 +02:00
val absDir = Rotation.rotateSide(side, r)
2014-09-14 09:48:55 +02:00
if (setExternalConnection(r, absDir) || setCornerConnection(r, absDir))
2014-11-02 15:53:45 +01:00
calculatedMask |= 1 << absDir
2014-09-14 09:48:55 +02:00
2014-10-12 10:51:44 +02:00
if ((calculatedMask & (1 << absDir)) == 0)
2014-09-16 06:00:10 +02:00
disconnect(absDir)
2014-09-14 09:48:55 +02:00
}
}
2014-09-16 06:00:10 +02:00
/**
* Internal connections
*/
for (r <- 0 until 4)
{
var skip = false
2014-09-14 09:48:55 +02:00
val absDir = Rotation.rotateSide(side, r)
2014-09-14 09:48:55 +02:00
2014-09-16 06:00:10 +02:00
if (tile.partMap(PartMap.edgeBetween(absDir, side)) == null)
{
val part = tile.partMap(absDir)
val to = ForgeDirection.getOrientation(absDir)
2014-11-04 14:41:07 +01:00
val from = to.getOpposite
2014-09-14 09:48:55 +02:00
2014-11-08 15:35:48 +01:00
if (part != null)
2014-09-16 06:00:10 +02:00
{
2015-01-21 12:08:36 +01:00
val node = part.asInstanceOf[INodeProvider].getNode(classOf[NodeElectricComponent], from)
2014-11-04 14:41:07 +01:00
if (canConnect(node, to))
{
//TODO: Check dir
connect(node, to)
skip = true
}
2014-09-16 06:00:10 +02:00
}
}
2014-10-12 10:51:44 +02:00
if ((calculatedMask & (1 << absDir)) == 0 && !skip)
2014-09-14 09:48:55 +02:00
{
2014-09-16 06:00:10 +02:00
disconnect(absDir)
2014-09-14 09:48:55 +02:00
}
}
2014-10-12 10:51:44 +02:00
//External connection
2014-09-16 06:00:10 +02:00
setExternalConnection(-1, side)
2014-09-16 06:00:10 +02:00
updateExternalConnections()
updateInternalConnections()
//Reconstruct the grid
grid.reconstruct(this)
2014-09-16 06:00:10 +02:00
}
}
def setExternalConnection(r: Int, absDir: Int): Boolean =
{
val pos = new BlockCoord(tile).offset(absDir)
2014-09-16 06:00:10 +02:00
val tilePart = MultipartUtil.getMultipartTile(world, pos)
2014-11-02 15:53:45 +01:00
val toDir = ForgeDirection.getOrientation(absDir)
2014-10-26 15:41:40 +01:00
val fromDir = ForgeDirection.getOrientation(absDir).getOpposite
2014-09-16 06:00:10 +02:00
if (tilePart != null && r != -1)
{
2014-09-16 06:00:10 +02:00
val part = tilePart.partMap(side)
2014-11-04 14:41:07 +01:00
val dcNode = getComponent(part, fromDir)
2014-11-04 14:41:07 +01:00
//Check if it's another flat wire.
if (canConnect(dcNode, toDir))
2014-09-14 09:48:55 +02:00
{
val otherR = (r + 2) % 4
2014-10-26 15:41:40 +01:00
2014-11-04 14:41:07 +01:00
if (part.isInstanceOf[PartFlatWire])
2014-09-14 09:48:55 +02:00
{
2014-11-04 14:41:07 +01:00
val wire = part.asInstanceOf[PartFlatWire]
2014-11-04 14:41:07 +01:00
//Check other wire connectability
if (dcNode.canConnect(this, fromDir) && wire.maskOpen(otherR))
{
2014-11-02 15:53:45 +01:00
connect(dcNode, toDir)
return true
}
2014-09-14 09:48:55 +02:00
}
2014-11-04 15:06:08 +01:00
else if (canConnect(dcNode, toDir))
2014-11-04 14:41:07 +01:00
{
connect(dcNode, toDir)
return true
}
2014-09-14 09:48:55 +02:00
}
disconnect(absDir)
}
2014-10-26 15:41:40 +01:00
/**
* Can't find another wire. Try TileEntity.
*/
2014-11-02 15:53:45 +01:00
val tileEntity = pos.getTileEntity(world)
2014-11-04 14:41:07 +01:00
val dcNode = getComponent(tileEntity, fromDir)
2014-11-04 15:45:58 +01:00
if (canConnect(dcNode, toDir))
2014-09-14 09:48:55 +02:00
{
2014-11-08 15:35:48 +01:00
if (dcNode.canConnect(this, ForgeDirection.UNKNOWN))
2014-11-04 15:45:58 +01:00
{
connect(dcNode, toDir)
return true
}
2014-09-14 09:48:55 +02:00
}
disconnect(absDir)
return false
}
def setCornerConnection(r: Int, absDir: Int): Boolean =
{
val cornerPos = new BlockCoord(tile)
cornerPos.offset(absDir)
if (canConnectThroughCorner(cornerPos, absDir ^ 1, side))
{
cornerPos.offset(side)
val tpCorner = MultipartUtil.getMultipartTile(world, cornerPos)
if (tpCorner != null)
{
val part = tpCorner.partMap(absDir ^ 1)
2014-11-02 15:53:45 +01:00
val absToDir = ForgeDirection.getOrientation(absDir)
val absFromDir = ForgeDirection.getOrientation(absDir).getOpposite
2015-01-21 12:08:36 +01:00
val node = part.asInstanceOf[INodeProvider].getNode(classOf[NodeElectricComponent], absFromDir)
2014-11-04 14:41:07 +01:00
if (canConnect(node, absFromDir))
{
//TODO: Check dir
2014-11-04 14:41:07 +01:00
connect(node, absToDir)
return true
}
}
}
return false
}
2014-09-14 09:48:55 +02:00
def connectionOpen(r: Int): Boolean =
{
2014-11-02 15:53:45 +01:00
val absDir = Rotation.rotateSide(side, r)
val facePart = tile.partMap(absDir)
val toDir = ForgeDirection.getOrientation(absDir)
2015-01-21 12:08:36 +01:00
if (facePart != null && (!facePart.isInstanceOf[PartFlatWire] || !canConnect(facePart.asInstanceOf[INodeProvider].getNode(classOf[NodeElectricComponent], toDir.getOpposite), toDir.getOpposite)))
{
2014-09-14 09:48:55 +02:00
return false
}
2014-09-14 09:48:55 +02:00
if (tile.partMap(PartMap.edgeBetween(side, absDir)) != null)
{
2014-09-14 09:48:55 +02:00
return false
}
2014-11-02 15:53:45 +01:00
return true
}
2014-09-14 09:48:55 +02:00
/**
* Return a corner connection state. 0 = No connection 1 = Physical connection 2 = Render
* connection
*/
def connectCorner(r: Int): Int =
{
2014-09-14 09:48:55 +02:00
val absDir: Int = Rotation.rotateSide(side, r)
val pos: BlockCoord = new BlockCoord(tile)
pos.offset(absDir)
2014-11-02 15:53:45 +01:00
2014-09-14 09:48:55 +02:00
if (!canConnectThroughCorner(pos, absDir ^ 1, side))
{
2014-09-14 09:48:55 +02:00
return 0
}
2014-11-02 15:53:45 +01:00
2014-09-14 09:48:55 +02:00
pos.offset(side)
val t: TileMultipart = MultipartUtil.getMultipartTile(world, pos)
if (t != null)
{
2014-10-26 15:41:40 +01:00
val part = t.partMap(absDir ^ 1)
2014-11-04 14:41:07 +01:00
val dcNode = getComponent(part, ForgeDirection.getOrientation(absDir))
2014-09-14 09:48:55 +02:00
2014-11-04 14:41:07 +01:00
if (canConnect(dcNode, ForgeDirection.getOrientation(absDir)))
2014-09-14 09:48:55 +02:00
{
if (dcNode.isInstanceOf[NodeFlatWire])
2014-09-14 09:48:55 +02:00
{
if (dcNode.asInstanceOf[NodeFlatWire].connectCorner(PartFlatWire.this, Rotation.rotationTo(absDir ^ 1, side ^ 1)))
2014-09-14 09:48:55 +02:00
{
2014-10-26 15:41:40 +01:00
if (!renderThisCorner(part.asInstanceOf[PartFlatWire]))
2014-09-14 09:48:55 +02:00
{
return 1
}
return 2
}
}
return 2
}
}
return 0
}
2014-09-14 09:48:55 +02:00
def canConnectThroughCorner(pos: BlockCoord, side1: Int, side2: Int): Boolean =
{
2014-09-14 09:48:55 +02:00
if (world.isAirBlock(pos.x, pos.y, pos.z))
{
2014-09-14 09:48:55 +02:00
return true
}
2014-09-14 09:48:55 +02:00
val t: TileMultipart = MultipartUtil.getMultipartTile(world, pos)
if (t != null)
{
return t.partMap(side1) == null && t.partMap(side2) == null && t.partMap(PartMap.edgeBetween(side1, side2)) == null
}
return false
}
2014-09-14 09:48:55 +02:00
def connectStraight(r: Int): Boolean =
{
2014-11-04 14:41:07 +01:00
val absDir = Rotation.rotateSide(side, r)
val pos = new BlockCoord(tile).offset(absDir)
val t = MultipartUtil.getMultipartTile(world, pos)
val toDir = ForgeDirection.getOrientation(absDir)
val fromDir = toDir.getOpposite
2014-09-14 09:48:55 +02:00
if (t != null)
{
2014-10-26 15:41:40 +01:00
val part = t.partMap(side)
2014-11-04 14:41:07 +01:00
val dcNode = getComponent(part, ForgeDirection.getOrientation(absDir))
2014-11-04 14:41:07 +01:00
if (canConnect(dcNode, ForgeDirection.getOrientation(absDir)))
{
if (dcNode.isInstanceOf[NodeFlatWire])
2014-09-14 09:48:55 +02:00
{
return dcNode.asInstanceOf[NodeFlatWire].connectStraight(PartFlatWire.this, (r + 2) % 4)
2014-09-14 09:48:55 +02:00
}
2014-11-04 15:45:58 +01:00
2014-09-14 09:48:55 +02:00
return true
}
}
else
{
2014-10-26 15:41:40 +01:00
val tileEntity = world.getTileEntity(pos.x, pos.y, pos.z)
2014-11-04 14:41:07 +01:00
val dcNode = getComponent(tileEntity, fromDir)
if (dcNode != null)
2014-11-04 15:45:58 +01:00
return canConnect(dcNode, toDir) && dcNode.canConnect(this, fromDir)
2014-09-14 09:48:55 +02:00
}
2014-11-04 14:41:07 +01:00
2014-09-14 09:48:55 +02:00
return false
}
2014-09-14 09:48:55 +02:00
def connectInternal(r: Int): Boolean =
{
2014-11-04 14:41:07 +01:00
val absDir = Rotation.rotateSide(side, r)
val toDir = ForgeDirection.getOrientation(absDir)
2014-09-14 09:48:55 +02:00
if (tile.partMap(PartMap.edgeBetween(absDir, side)) != null)
{
return false
}
2014-11-04 14:41:07 +01:00
val part = tile.partMap(absDir)
val dcNode = getComponent(part, toDir)
2014-10-26 15:41:40 +01:00
2014-11-04 14:41:07 +01:00
if (canConnect(dcNode, toDir))
{
if (dcNode.isInstanceOf[NodeFlatWire])
return dcNode.asInstanceOf[NodeFlatWire].connectInternal(PartFlatWire.this, Rotation.rotationTo(absDir, side))
2014-09-14 09:48:55 +02:00
}
2014-09-14 09:48:55 +02:00
return false
}
2014-09-14 09:48:55 +02:00
def connectCenter: Boolean =
{
2014-11-04 14:41:07 +01:00
val tp = tile.partMap(6)
2014-11-04 14:41:07 +01:00
//TODO: Check other appliances that may connect to center but are not wires?
if (tp.isInstanceOf[PartFlatWire])
2014-09-14 09:48:55 +02:00
{
val dcNode = tp.asInstanceOf[PartFlatWire].getNode(classOf[NodeFlatWire], null)
2014-11-04 14:41:07 +01:00
if (canConnect(dcNode, null))
{
return dcNode.connectInternal(PartFlatWire.this, side)
}
2014-09-14 09:48:55 +02:00
}
2014-09-14 09:48:55 +02:00
return false
}
2014-09-14 09:48:55 +02:00
def connectCorner(wire: PartFlatWire, r: Int): Boolean =
{
2014-11-04 14:41:07 +01:00
val absDir = Rotation.rotateSide(side, r)
val toDir = ForgeDirection.getOrientation(absDir)
val fromDir = toDir.getOpposite
val dcNode = getComponent(wire, fromDir)
if (canConnect(dcNode, fromDir) && maskOpen(r))
2014-09-14 09:48:55 +02:00
{
2014-11-02 15:53:45 +01:00
val oldConn: Int = PartFlatWire.this.connectionMask
PartFlatWire.this.connectionMask |= 0x1 << r
2014-09-14 09:48:55 +02:00
if (renderThisCorner(wire))
{
2014-11-02 15:53:45 +01:00
PartFlatWire.this.connectionMask |= 0x100000 << r
2014-09-14 09:48:55 +02:00
}
2014-11-02 15:53:45 +01:00
if (oldConn != PartFlatWire.this.connectionMask)
2014-09-14 09:48:55 +02:00
{
2014-11-10 14:41:46 +01:00
sendPacket(3)
2014-09-14 09:48:55 +02:00
}
return true
}
return false
}
2014-09-14 09:48:55 +02:00
def connectStraight(wire: PartFlatWire, r: Int): Boolean =
{
2014-11-04 14:41:07 +01:00
val absDir = Rotation.rotateSide(side, r)
val toDir = ForgeDirection.getOrientation(absDir)
val fromDir = toDir.getOpposite
val dcNode = getComponent(wire, fromDir)
if (canConnect(dcNode, fromDir) && maskOpen(r))
2014-09-14 09:48:55 +02:00
{
2014-11-02 15:53:45 +01:00
val oldConn: Int = PartFlatWire.this.connectionMask
PartFlatWire.this.connectionMask |= 0x10 << r
if (oldConn != PartFlatWire.this.connectionMask)
2014-09-14 09:48:55 +02:00
{
2014-11-10 14:41:46 +01:00
sendPacket(3)
2014-09-14 09:48:55 +02:00
}
return true
}
return false
}
2014-09-14 09:48:55 +02:00
def connectInternal(wire: PartFlatWire, r: Int): Boolean =
{
2014-11-04 14:41:07 +01:00
val absDir = Rotation.rotateSide(side, r)
val toDir = ForgeDirection.getOrientation(absDir)
val fromDir = toDir.getOpposite
val dcNode = getComponent(wire, fromDir)
if (canConnect(dcNode, fromDir))
2014-09-14 09:48:55 +02:00
{
2014-11-02 15:53:45 +01:00
val oldConn: Int = PartFlatWire.this.connectionMask
PartFlatWire.this.connectionMask |= 0x100 << r
if (oldConn != PartFlatWire.this.connectionMask)
2014-09-14 09:48:55 +02:00
{
2014-11-10 14:41:46 +01:00
sendPacket(3)
2014-09-14 09:48:55 +02:00
}
return true
}
return false
}
2015-01-21 12:08:36 +01:00
override def canConnect[B <: NodeElectricComponent](node: B, from: ForgeDirection): Boolean =
2014-11-04 14:41:07 +01:00
{
if (node.isInstanceOf[NodeFlatWire])
2014-11-04 14:41:07 +01:00
{
val wire = node.asInstanceOf[NodeFlatWire].getParent.asInstanceOf[TWire]
2014-11-04 14:41:07 +01:00
if (material == wire.material)
{
if (insulated && wire.insulated)
return PartFlatWire.this.getColor == wire.getColor || (getColor == TColorable.defaultColor || wire.getColor == TColorable.defaultColor)
return true
}
}
return super.canConnect(node, from)
}
2015-01-08 14:24:04 +01:00
/**
* Recalculates connections to blocks outside this space
*
* @return true if a new connection was added or one was removed
*/
protected def updateExternalConnections(): Boolean =
{
var newConn: Int = 0
for (r <- 0 until 4)
{
if (maskOpen(r))
{
if (connectStraight(r))
{
newConn |= 0x10 << r
}
else
{
val cnrMode: Int = connectCorner(r)
if (cnrMode != 0)
{
newConn |= 1 << r
if (cnrMode == 2)
{
newConn |= 0x100000 << r
}
}
}
}
}
if (newConn != (PartFlatWire.this.connectionMask & 0xF000FF))
{
val diff: Int = PartFlatWire.this.connectionMask ^ newConn
PartFlatWire.this.connectionMask = PartFlatWire.this.connectionMask & ~0xF000FF | newConn
for (r <- 0 until 4)
{
if ((diff & 1 << r) != 0)
{
notifyCornerChange(r)
}
}
return true
}
return false
}
/**
* Recalculates connections to other parts within this space
*
* @return true if a new connection was added or one was removed
*/
protected def updateInternalConnections(): Boolean =
{
var newConn: Int = 0
for (r <- 0 until 4)
{
if (connectInternal(r))
{
newConn |= 0x100 << r
}
}
if (connectCenter)
{
newConn |= 0x10000
}
if (newConn != (PartFlatWire.this.connectionMask & 0x10F00))
{
PartFlatWire.this.connectionMask = PartFlatWire.this.connectionMask & ~0x10F00 | newConn
return true
}
return false
}
/**
* Recalculates connections that can be made to other parts outside of this space
*
* @return true if external connections should be recalculated
*/
protected def updateOpenConnections(): Boolean =
{
var newConn: Int = 0
for (r <- 0 until 4)
{
if (connectionOpen(r))
{
newConn |= 0x1000 << r
}
}
if (newConn != (PartFlatWire.this.connectionMask & 0xF000))
{
PartFlatWire.this.connectionMask = PartFlatWire.this.connectionMask & ~0xF000 | newConn
return true
}
return false
}
private def disconnect(i: Int)
{
if (!world.isRemote)
{
//TODO: Refine this. It's very hacky and may cause errors when the wire connects to a block both ways
val inverseCon = directionMap.map(_.swap)
val forgeDir = ForgeDirection.getOrientation(i)
if (inverseCon.contains(forgeDir))
{
val connected = inverseCon(forgeDir)
if (connected != null)
{
disconnect(connected)
}
}
}
}
/**
* Gets a potential DCNode from an object.
*/
2015-01-21 12:08:36 +01:00
private def getComponent(obj: AnyRef, from: ForgeDirection): NodeElectricComponent =
2015-01-08 14:24:04 +01:00
{
if (obj.isInstanceOf[INodeProvider])
2015-01-21 12:08:36 +01:00
return obj.asInstanceOf[INodeProvider].getNode(classOf[NodeElectricComponent], from)
2015-01-08 14:24:04 +01:00
return null
}
2014-09-14 09:48:55 +02:00
}
2014-09-14 10:08:24 +02:00
}