Files
ForgeMultipart/src/main/scala/codechicken/multipart/PacketScheduler.scala
T

81 lines
2.3 KiB
Scala

package codechicken.multipart
import scala.collection.mutable.{Map => MMap}
import codechicken.lib.data.MCDataOutput
import codechicken.lib.data.MCDataInput
/** Static class for packing update data. When a specific property of a part
* changes and needs sending to the client, a bit can be set in the mask. This
* bit can then be checked in the writeScheduled callback. This prevents
* sending multiple packets if the same property updates more than once per
* tick.
*/
object PacketScheduler {
private val map = MMap[TMultiPart, Long]()
/** Add bits to the current update mask for part. (binary OR)
*/
def schedulePacket(part: TMultiPart, mask: Long) {
if (part.world.isRemote)
throw new IllegalArgumentException(
"Cannot use PacketScheduler on a client world"
)
map.put(part, map.getOrElse(part, 0L) | mask)
}
private[multipart] def sendScheduled() {
map.foreach { e =>
val (part, mask) = e
if (part.tile != null) {
val ipart = part.asInstanceOf[IScheduledPacketPart]
val w = part.getWriteStream
ipart.maskWidth match {
case 1 => w.writeByte(mask.toInt)
case 2 => w.writeShort(mask.toInt)
case 4 => w.writeInt(mask.toInt)
case 8 => w.writeLong(mask)
}
ipart.writeScheduled(mask, w)
}
}
map.clear()
}
}
/** Callback interface for PacketScheduler
*/
trait IScheduledPacketPart {
/** Write scheduled data to the packet, mask is the cumulative mask from calls
* to schedulePacket
*/
def writeScheduled(mask: Long, packet: MCDataOutput)
/** Returns the width (in bytes) of the data type required to hold all valid
* mask bits. Valid values are 1, 2, 4 and 8
*/
def maskWidth: Int
/** Read data matching mask. Estiablishes a method for subclasses to override.
* This should be called from read
*/
def readScheduled(mask: Long, packet: MCDataInput)
}
trait TScheduledPacketPart extends TMultiPart with IScheduledPacketPart {
final override def read(packet: MCDataInput) {
val mask = maskWidth match {
case 1 => packet.readUByte
case 2 => packet.readUShort
case 4 => packet.readInt
case 8 => packet.readLong
}
readScheduled(mask, packet)
}
def writeScheduled(mask: Long, packet: MCDataOutput) {}
def readScheduled(mask: Long, packet: MCDataInput) {}
}