| 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.util.Persistable |
| import net.minecraft.nbt.NBTTagCompound |
| |
| trait Connector extends Node with network.Connector with Persistable { |
| var localBufferSize: Double |
| |
| var localBuffer = 0.0 |
| |
| var distributor: Option[Distributor] = None |
| |
| // ----------------------------------------------------------------------- // |
| |
| def globalBuffer = distributor.fold(localBuffer)(_.globalBuffer) |
| |
| def globalBufferSize = distributor.fold(localBufferSize)(_.globalBufferSize) |
| |
| // ----------------------------------------------------------------------- // |
| |
| def changeBuffer(delta: Double): Double = { |
| if (delta == 0) 0 |
| else if (Settings.get.ignorePower) { |
| if (delta < 0) 0 |
| else /* if (delta > 0) */ delta |
| } |
| else { |
| this.synchronized(distributor match { |
| case Some(d) => d.synchronized(d.changeBuffer(change(delta))) |
| case _ => change(delta) |
| }) |
| } |
| } |
| |
| private def change(delta: Double): Double = { |
| if (localBufferSize <= 0) return delta |
| 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 |
| if (localBuffer != oldBuffer) { |
| this.synchronized(distributor match { |
| case Some(d) => d.globalBuffer = math.max(0, math.min(d.globalBufferSize, d.globalBuffer - oldBuffer + localBuffer)) |
| case _ => |
| }) |
| } |
| remaining |
| } |
| |
| def tryChangeBuffer(delta: Double): Boolean = { |
| if (delta == 0) true |
| else if (Settings.get.ignorePower) delta < 0 |
| else { |
| 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 { |
| if (network != null) { |
| if (localBufferSize <= 0 && size > 0) d.addConnector(this) |
| else if (localBufferSize > 0 && size == 0) d.removeConnector(this) |
| d.globalBufferSize = math.max(d.globalBufferSize - localBufferSize + size, 0) |
| } |
| localBufferSize = math.max(size, 0) |
| val surplus = math.max(localBuffer - localBufferSize, 0) |
| localBuffer = math.min(localBuffer, localBufferSize) |
| d.changeBuffer(surplus) |
| } |
| case _ => |
| localBufferSize = math.max(size, 0) |
| localBuffer = math.min(localBuffer, localBufferSize) |
| }) |
| } |
| |
| // ----------------------------------------------------------------------- // |
| |
| override def onDisconnect(node: ImmutableNode) { |
| if (node == this) this.synchronized { |
| setLocalBufferSize(0) |
| distributor = None |
| } |
| super.onDisconnect(node) |
| } |
| |
| // ----------------------------------------------------------------------- // |
| |
| override def load(nbt: NBTTagCompound) { |
| super.load(nbt) |
| localBuffer = math.min(nbt.getDouble("buffer"), math.max(0, localBufferSize)) |
| } |
| |
| override def save(nbt: NBTTagCompound) { |
| super.save(nbt) |
| nbt.setDouble("buffer", localBuffer) |
| } |
| } |