blob: 74dece7d5af0064c14dbb002fa07b8e2899aaf12 [file] [log] [blame] [raw]
package li.cil.oc.server.network
import li.cil.oc.Settings
import li.cil.oc.api.network
import li.cil.oc.api.network.{Node => ImmutableNode}
import li.cil.oc.server.component.PowerDistributor
import li.cil.oc.util.Persistable
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._
trait Connector extends Node with network.Connector with Persistable {
var localBufferSize: Double
var localBuffer = 0.0
var dirty = true
private var distributor: Option[PowerDistributor] = None
// ----------------------------------------------------------------------- //
def globalBuffer = distributor.fold(localBuffer)(_.globalBuffer)
def globalBufferSize = distributor.fold(localBufferSize)(_.globalBufferSize)
// ----------------------------------------------------------------------- //
def changeBuffer(delta: Double): Double = {
if (delta == 0) {
return 0
}
if (Settings.get.ignorePower) {
if (delta < 0) {
return 0
}
else /* if (delta > 0) */ {
return delta
}
}
def change() = {
val oldBuffer = localBuffer
localBuffer += delta
val remaining = if (localBuffer < 0) {
val remaining = localBuffer
localBuffer = 0
remaining
}
else if (localBuffer > localBufferSize) {
val remaining = localBuffer - localBufferSize
localBuffer = localBufferSize
remaining
}
else 0
dirty ||= (localBuffer != oldBuffer)
remaining
}
this.synchronized(distributor match {
case Some(d) => d.synchronized(d.changeBuffer(change()))
case _ => change()
})
}
def tryChangeBuffer(delta: Double): Boolean = {
if (delta == 0) {
return true
}
if (Settings.get.ignorePower) {
if (delta < 0) {
return true
}
else /* if (delta > 0) */ {
return false
}
}
this.synchronized(distributor match {
case Some(d) => d.synchronized {
val newGlobalBuffer = globalBuffer + delta
newGlobalBuffer >= 0 && newGlobalBuffer <= globalBufferSize && d.changeBuffer(delta) == 0
}
case _ =>
val newLocalBuffer = localBuffer + delta
if (newLocalBuffer < 0 || newLocalBuffer > localBufferSize) {
false
}
else {
localBuffer = newLocalBuffer
true
}
})
}
def setLocalBufferSize(size: Double) {
this.synchronized(distributor match {
case Some(d) => d.synchronized {
localBufferSize = size max 0
val surplus = (localBuffer - localBufferSize) max 0
localBuffer = localBuffer min localBufferSize
d.changeBuffer(surplus)
}
case _ =>
localBufferSize = size max 0
localBuffer = localBuffer min localBufferSize
})
}
// ----------------------------------------------------------------------- //
override def onConnect(node: ImmutableNode) {
if (node == this) {
findDistributor()
}
else if (distributor.isEmpty) {
node.host match {
case d: PowerDistributor => this.synchronized(distributor = Some(d))
case _ =>
}
}
super.onConnect(node)
}
override def onDisconnect(node: ImmutableNode) {
if (node == this) this.synchronized {
setLocalBufferSize(0)
distributor = None
}
else if (distributor.exists(_ == node.host)) {
findDistributor()
}
super.onDisconnect(node)
}
private def findDistributor() = {
this.synchronized(distributor = reachableNodes.find(_.host.isInstanceOf[PowerDistributor]).fold(None: Option[PowerDistributor])(n => Some(n.host.asInstanceOf[PowerDistributor])))
}
// ----------------------------------------------------------------------- //
override def load(nbt: NBTTagCompound) {
super.load(nbt)
localBuffer = nbt.getDouble("buffer") max 0 min localBufferSize
dirty = true
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDouble("buffer", localBuffer)
}
}