blob: ba4380df7e451cb8f70148e6657d0b0e13762070 [file] [log] [blame] [raw]
package li.cil.oc.common.tileentity
import li.cil.oc.Settings
import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection
import scala.Some
abstract class Computer(isRemote: Boolean) extends Environment with ComponentInventory with Rotatable with BundledRedstone with Analyzable {
protected val _computer = if (isRemote) null else new component.Computer(this)
def computer = _computer
def node = if (isClient) null else computer.node
override def isClient = computer == null
private var _isRunning = false
private var hasChanged = false
// ----------------------------------------------------------------------- //
def isRunning = _isRunning
def isRunning_=(value: Boolean) = {
_isRunning = value
world.markBlockForRenderUpdate(x, y, z)
this
}
def markAsChanged() = hasChanged = true
def hasRedstoneCard = items.exists {
case Some(item) => driver.item.RedstoneCard.worksWith(item)
case _ => false
}
// ----------------------------------------------------------------------- //
override def updateEntity() {
if (isServer) {
// If we're not yet in a network we might have just been loaded from disk,
// meaning there may be other tile entities that also have not re-joined
// the network. We skip the update this round to allow other tile entities
// to join the network, too, avoiding issues of missing nodes (e.g. in the
// GPU which would otherwise loose track of its screen).
if (node != null && node.network != null) {
computer.update()
if (hasChanged) {
hasChanged = false
world.markTileEntityChunkModified(x, y, z, this)
}
if (_isRunning != computer.isRunning) {
isOutputEnabled = hasRedstoneCard && computer.isRunning
ServerPacketSender.sendComputerState(this, computer.isRunning)
}
_isRunning = computer.isRunning
updateRedstoneInput()
for (component <- components) component match {
case Some(environment) => environment.update()
case _ => // Empty.
}
}
}
super.updateEntity()
}
override def validate() = {
super.validate()
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
ClientPacketSender.sendComputerStateRequest(this)
ClientPacketSender.sendRedstoneStateRequest(this)
}
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (isServer) {
computer.load(nbt.getCompoundTag(Settings.namespace + "computer"))
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
if (isServer) {
nbt.setNewCompoundTag(Settings.namespace + "computer", computer.save)
}
}
// ----------------------------------------------------------------------- //
override def onInventoryChanged() {
super.onInventoryChanged()
if (isServer) {
computer.recomputeMemory()
isOutputEnabled = hasRedstoneCard && computer.isRunning
}
}
override protected def onRotationChanged() {
super.onRotationChanged()
checkRedstoneInputChanged()
}
override protected def onRedstoneInputChanged(side: ForgeDirection) {
super.onRedstoneInputChanged(side)
computer.signal("redstone_changed", Int.box(side.ordinal()))
}
// ----------------------------------------------------------------------- //
def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float): Node = {
if (computer != null) computer.lastError match {
case Some(value) => stats.setString(Settings.namespace + "text.Analyzer.LastError", value)
case _ =>
}
computer.node
}
}