blob: 5878a76d73133e658de55eeeea78668b2f2c54ed [file] [log] [blame] [raw]
package li.cil.oc.server.driver
import java.nio.charset.Charset
import com.google.common.hash.Hashing
import li.cil.oc.api.driver
import li.cil.oc.api.network._
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.OpenComputers
import li.cil.oc.api
import net.minecraft.nbt.NBTTagCompound
class CompoundBlockEnvironment(val name: String, val environments: (driver.Block, ManagedEnvironment)*) extends ManagedEnvironment {
// Block drivers with visibility < network usually won't make much sense,
// but let's play it safe and use the least possible visibility based on
// the drivers we encapsulate.
val node = api.Network.newNode(this, (environments.filter(_._2.node != null).map(_._2.node.reachability) ++ Seq(Visibility.None)).max).
withComponent(name).
create()
val updatingEnvironments = environments.map(_._2).filter(_.canUpdate)
// Force all wrapped components to be neighbor visible, since we as their
// only neighbor will take care of all component-related interaction.
for ((_, environment) <- environments) environment.node match {
case component: Component => component.setVisibility(Visibility.Neighbors)
case _ =>
}
override def canUpdate = environments.exists(_._2.canUpdate)
override def update() {
for (environment <- updatingEnvironments) {
environment.update()
}
}
override def onMessage(message: Message) {}
override def onConnect(node: Node) {
if (node == this.node) {
for ((_, environment) <- environments if environment.node != null) {
node.connect(environment.node)
}
}
}
override def onDisconnect(node: Node) {
if (node == this.node) {
for ((_, environment) <- environments if environment.node != null) {
environment.node.remove()
}
}
}
override def load(nbt: NBTTagCompound) {
// Ignore existing data if the underlying type is different.
if (nbt.hasKey("typeHash") && nbt.getLong("typeHash") != typeHash) return
node.load(nbt)
for ((driver, environment) <- environments) {
val name = driver.getClass.getName
if (nbt.hasKey(name)) {
try {
environment.load(nbt.getCompoundTag(name))
} catch {
case e: Throwable => OpenComputers.log.warn("A block component of type '%s' (provided by driver '%s') threw an error while loading.".format(environment.getClass.getName, name), e)
}
}
}
}
override def save(nbt: NBTTagCompound) {
nbt.setLong("typeHash", typeHash)
node.save(nbt)
for ((driver, environment) <- environments) {
val name = driver.getClass.getName
try {
nbt.setNewCompoundTag(name, environment.save)
} catch {
case e: Throwable => OpenComputers.log.warn("A block component of type '%s' (provided by driver '%s') threw an error while saving.".format(environment.getClass.getName, name), e)
}
}
}
private def typeHash = {
val hash = Hashing.sha256().newHasher()
environments.map(_._2.getClass.getName).sorted.foreach(hash.putString(_, Charset.defaultCharset()))
hash.hash().asLong()
}
}