blob: 0a618ac3ad633be3e70d2b5307ca3796c9c99c3b [file] [log] [blame] [raw]
package li.cil.oc.common
import cpw.mods.fml.common.network.IPacketHandler
import cpw.mods.fml.common.network.Player
import java.io.ByteArrayInputStream
import java.io.DataInputStream
import net.minecraft.network.INetworkManager
import net.minecraft.network.packet.Packet250CustomPayload
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection
import scala.reflect.runtime.{universe => ru}
abstract class PacketHandler extends IPacketHandler {
/** Top level dispatcher based on packet type. */
def onPacketData(manager: INetworkManager, packet: Packet250CustomPayload, player: Player) {
dispatch(new PacketParser(packet, player))
}
/**
* Gets the world for the specified dimension.
*
* For clients this returns the client's world if it is the specified
* dimension; None otherwise. For the server it returns the world for the
* specified dimension, if such a dimension exists; None otherwise.
*/
protected def world(player: Player, dimension: Int): Option[World]
/** Handles packets based on their type. */
protected def dispatch(p: PacketParser)
/** Utility class for packet parsing. */
protected class PacketParser(packet: Packet250CustomPayload, val player: Player) extends DataInputStream(new ByteArrayInputStream(packet.data)) {
val packetType = PacketType(readByte())
def readTileEntity[T: ru.TypeTag](): Option[T] = {
val dimension = readInt()
val x = readInt()
val y = readInt()
val z = readInt()
world(player, dimension) match {
case None => // Invalid dimension.
case Some(world) => ru.synchronized {
val t = world.getBlockTileEntity(x, y, z)
val m = ru.runtimeMirror(this.getClass.getClassLoader)
if (t != null && m.classSymbol(t.getClass).toType <:< ru.typeOf[T])
return Some(t.asInstanceOf[T])
}
}
None
}
def readDirection() = ForgeDirection.getOrientation(readInt())
}
}