blob: 402cbc1c4a43f7d279e26bd4acd441af661e887e [file] [log] [blame] [raw]
package li.cil.oc.common.tileentity
import cpw.mods.fml.common.{Optional, Loader}
import li.cil.oc.Settings
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.mods.ProjectRed
import mods.immibis.redlogic.api.wiring.{IInsulatedRedstoneWire, IBundledUpdatable, IBundledEmitter}
import mrtjp.projectred.api.{ProjectRedAPI, IBundledTile}
import net.minecraft.block.Block
import net.minecraft.nbt.{NBTTagIntArray, NBTTagCompound}
import net.minecraftforge.common.ForgeDirection
import powercrystals.minefactoryreloaded.api.rednet.IRedNetNetworkContainer
import scala.Array
@Optional.InterfaceList(Array(
new Optional.Interface(iface = "mods.immibis.redlogic.api.wiring.IBundledEmitter", modid = "RedLogic"),
new Optional.Interface(iface = "mods.immibis.redlogic.api.wiring.IBundledUpdatable", modid = "RedLogic"),
new Optional.Interface(iface = "mrtjp.projectred.api.IBundledTile", modid = "ProjRed|Transmission")
))
trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBundledUpdatable with IBundledTile {
private val _bundledInput = Array.fill(6)(Array.fill(16)(-1))
private val _rednetInput = Array.fill(6)(Array.fill(16)(-1))
private val _bundledOutput = Array.fill(6)(Array.fill(16)(0))
// ----------------------------------------------------------------------- //
override def isOutputEnabled_=(value: Boolean) = {
if (value != isOutputEnabled) {
if (!value) {
for (i <- 0 until _bundledOutput.length) {
for (j <- 0 until _bundledOutput(i).length) {
_bundledOutput(i)(j) = 0
}
}
}
}
super.isOutputEnabled_=(value)
}
def bundledInput(side: ForgeDirection, color: Int) =
math.max(_bundledInput(side.ordinal())(color), _rednetInput(side.ordinal())(color))
def rednetInput(side: ForgeDirection, color: Int, value: Int) =
if (_rednetInput(side.ordinal())(color) != value) {
if (_rednetInput(side.ordinal())(color) != -1) {
onRedstoneInputChanged(side)
}
_rednetInput(side.ordinal())(color) = value
}
def bundledOutput(side: ForgeDirection) = _bundledOutput(toLocal(side).ordinal())
def bundledOutput(side: ForgeDirection, color: Int): Int = bundledOutput(side)(color)
def bundledOutput(side: ForgeDirection, color: Int, value: Int): Unit = if (value != bundledOutput(side, color)) {
_bundledOutput(toLocal(side).ordinal())(color) = value
onRedstoneOutputChanged(side)
}
// ----------------------------------------------------------------------- //
override def updateRedstoneInput() {
if (shouldUpdateInput) {
for (side <- ForgeDirection.VALID_DIRECTIONS) {
val oldBundledInput = _bundledInput(side.ordinal())
val newBundledInput = computeBundledInput(side)
var changed = false
if (newBundledInput != null) for (color <- 0 until 16) {
changed = changed || (oldBundledInput(color) >= 0 && oldBundledInput(color) != newBundledInput(color))
oldBundledInput(color) = newBundledInput(color)
}
else for (color <- 0 until 16) {
changed = changed || oldBundledInput(color) > 0
oldBundledInput(color) = 0
}
if (changed) {
onRedstoneInputChanged(side)
}
}
}
super.updateRedstoneInput()
}
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
nbt.getTagList(Settings.namespace + "rs.bundledInput").iterator[NBTTagIntArray].zipWithIndex.foreach {
case (input, side) if side < _bundledInput.length =>
val safeLength = input.intArray.length min _bundledInput(side).length
input.intArray.copyToArray(_bundledInput(side), 0, safeLength)
}
nbt.getTagList(Settings.namespace + "rs.bundledOutput").iterator[NBTTagIntArray].zipWithIndex.foreach {
case (input, side) if side < _bundledOutput.length =>
val safeLength = input.intArray.length min _bundledOutput(side).length
input.intArray.copyToArray(_bundledOutput(side), 0, safeLength)
}
nbt.getTagList(Settings.namespace + "rs.rednetInput").iterator[NBTTagIntArray].zipWithIndex.foreach {
case (input, side) if side < _rednetInput.length =>
val safeLength = input.intArray.length min _rednetInput(side).length
input.intArray.copyToArray(_rednetInput(side), 0, safeLength)
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
nbt.setNewTagList(Settings.namespace + "rs.bundledInput", _bundledInput.view)
nbt.setNewTagList(Settings.namespace + "rs.bundledOutput", _bundledOutput.view)
nbt.setNewTagList(Settings.namespace + "rs.rednetInput", _rednetInput.view)
}
// ----------------------------------------------------------------------- //
protected def computeBundledInput(side: ForgeDirection): Array[Int] = {
val redLogic = if (Loader.isModLoaded("RedLogic")) {
world.getBlockTileEntity(
x + side.offsetX,
y + side.offsetY,
z + side.offsetZ) match {
case wire: IInsulatedRedstoneWire =>
var strength: Array[Int] = null
for (face <- -1 to 5 if wire.wireConnectsInDirection(face, side.ordinal()) && strength == null) {
strength = Array.fill(16)(0)
strength(wire.getInsulatedWireColour) = wire.getEmittedSignalStrength(face, side.ordinal())
}
strength
case emitter: IBundledEmitter =>
var strength: Array[Int] = null
for (i <- -1 to 5 if strength == null) {
strength = Option(emitter.getBundledCableStrength(i, side.getOpposite.ordinal())).fold(null: Array[Int])(_.map(_ & 0xFF))
}
strength
case _ => null
}
} else null
val projectRed = if (ProjectRed.isAvailable && ProjectRed.isAPIAvailable) {
Option(ProjectRedAPI.transmissionAPI.getBundledInput(world, x, y, z, side.ordinal)).fold(null: Array[Int])(_.map(_ & 0xFF))
} else null
(redLogic, projectRed) match {
case (a: Array[Int], b: Array[Int]) => (a, b).zipped.map((r1, r2) => math.max(r1, r2))
case (a: Array[Int], _) => a
case (_, b: Array[Int]) => b
case _ => null
}
}
override protected def onRedstoneOutputChanged(side: ForgeDirection) {
if (side == ForgeDirection.UNKNOWN) {
if (Loader.isModLoaded("MineFactoryReloaded")) {
for (side <- ForgeDirection.VALID_DIRECTIONS) {
val nx = x + side.offsetX
val ny = y + side.offsetY
val nz = z + side.offsetZ
Block.blocksList(world.getBlockId(nx, ny, nz)) match {
case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z)
case _ =>
}
}
}
}
else {
val nx = x + side.offsetX
val ny = y + side.offsetY
val nz = z + side.offsetZ
if (Loader.isModLoaded("MineFactoryReloaded")) {
Block.blocksList(world.getBlockId(nx, ny, nz)) match {
case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z)
case _ =>
}
}
}
super.onRedstoneOutputChanged(side)
}
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "RedLogic")
def getBundledCableStrength(blockFace: Int, toDirection: Int): Array[Byte] = bundledOutput(ForgeDirection.getOrientation(toDirection)).map(value => math.min(math.max(value, 0), 255).toByte)
@Optional.Method(modid = "RedLogic")
def onBundledInputChanged() = checkRedstoneInputChanged()
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "ProjRed|Transmission")
def canConnectBundled(side: Int) = isOutputEnabled
@Optional.Method(modid = "ProjRed|Transmission")
def getBundledSignal(side: Int) = bundledOutput(ForgeDirection.getOrientation(side)).map(value => math.min(math.max(value, 0), 255).toByte)
}