blob: 8395cc23c13fc3ec94cf1f9ed80b134d0beef65a [file] [log] [blame] [raw]
package li.cil.oc.server.component
import li.cil.oc.api.network.{Message, Node}
import net.minecraft.nbt.{NBTTagByte, NBTTagList, NBTTagCompound}
import net.minecraftforge.common.ForgeDirection
trait Redstone extends Node {
private val _input = Array.fill[Byte](6)(-1)
private val _output = Array.fill[Byte](6)(0)
private var _isOutputEnabled = true
private var _shouldUpdateInput = true
def isOutputEnabled = _isOutputEnabled
def isOutputEnabled_=(value: Boolean) = {
if (value != isOutputEnabled) {
_isOutputEnabled = value
if (!isOutputEnabled) {
for (i <- 0 until _output.length) {
_output(i) = 0.toByte
}
}
onRedstoneOutputChanged(ForgeDirection.UNKNOWN)
}
this
}
def input(side: ForgeDirection): Int
def output(side: ForgeDirection): Int = _output(side.ordinal())
def output(side: ForgeDirection, value: Int): Unit = if (value != output(side)) {
_output(side.ordinal()) = (value max 0 min 15).toByte
onRedstoneOutputChanged(side)
}
def checkRedstoneInputChanged() {
_shouldUpdateInput = true
}
// ----------------------------------------------------------------------- //
override def update() {
super.update()
if (_shouldUpdateInput) {
_shouldUpdateInput = false
for (side <- ForgeDirection.VALID_DIRECTIONS) {
val oldInput = _input(side.ordinal())
val newInput = input(side)
_input(side.ordinal()) = newInput.toByte
if (oldInput >= 0 && _input(side.ordinal()) != oldInput) {
onRedstoneInputChanged(side)
}
}
}
}
override def receive(message: Message) = super.receive(message).orElse {
message.data match {
case Array(side: ForgeDirection) if message.name == "redstone.input" && side != ForgeDirection.UNKNOWN =>
checkRedstoneInputChanged()
result(_input(side.ordinal()))
case Array(side: ForgeDirection) if message.name == "redstone.output" && side != ForgeDirection.UNKNOWN =>
result(output(side))
case Array(side: ForgeDirection, value: Int) if message.name == "redstone.output=" && side != ForgeDirection.UNKNOWN =>
output(side, value)
result(true)
case _ => None
}
}
// ----------------------------------------------------------------------- //
override def load(nbt: NBTTagCompound) = {
super.load(nbt)
if (nbt.hasKey("redstone.input")) {
val inputNbt = nbt.getTagList("redstone.input")
for (i <- 0 until (_input.length min inputNbt.tagCount)) {
_input(i) = inputNbt.tagAt(i).asInstanceOf[NBTTagByte].data
}
}
if (nbt.hasKey("redstone.output")) {
val outputNbt = nbt.getTagList("redstone.output")
for (i <- 0 until (_output.length min outputNbt.tagCount)) {
_output(i) = outputNbt.tagAt(i).asInstanceOf[NBTTagByte].data
}
}
}
override def save(nbt: NBTTagCompound) = {
super.save(nbt)
val inputNbt = new NBTTagList()
for (i <- 0 until _input.length) {
inputNbt.appendTag(new NBTTagByte(null, _input(i)))
}
nbt.setTag("redstone.input", inputNbt)
val outputNbt = new NBTTagList()
for (i <- 0 until _output.length) {
outputNbt.appendTag(new NBTTagByte(null, _output(i)))
}
nbt.setTag("redstone.output", outputNbt)
}
// ----------------------------------------------------------------------- //
protected def onRedstoneInputChanged(side: ForgeDirection) {}
protected def onRedstoneOutputChanged(side: ForgeDirection) {}
}