using tile entity description packets to initialize client tile entities instead of the delayed request/response scheme in validate() which seems to solve moving robot problems... at least until there's massive lag, I suppose?

This commit is contained in:
Florian Nücke 2013-11-28 14:27:10 +01:00
parent 0d1e3b0bb4
commit e175a26fe1
23 changed files with 219 additions and 289 deletions

View File

@ -25,19 +25,18 @@ class PacketHandler extends CommonPacketHandler {
override def dispatch(p: PacketParser) =
p.packetType match {
case PacketType.Analyze => onAnalyze(p)
case PacketType.ChargerStateResponse => onChargerStateResponse(p)
case PacketType.ComputerStateResponse => onComputerStateResponse(p)
case PacketType.ChargerState => onChargerState(p)
case PacketType.ComputerState => onComputerState(p)
case PacketType.ItemComponentAddress => onItemComponentAddress(p)
case PacketType.PowerStateResponse => onPowerStateResponse(p)
case PacketType.RedstoneStateResponse => onRedstoneStateResponse(p)
case PacketType.PowerState => onPowerState(p)
case PacketType.RedstoneState => onRedstoneState(p)
case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p)
case PacketType.RobotAnimateTurn => onRobotAnimateTurn(p)
case PacketType.RobotEquippedItemChange => onRobotEquippedItemChange(p)
case PacketType.RobotMove => onRobotMove(p)
case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p)
case PacketType.RobotStateResponse => onRobotStateResponse(p)
case PacketType.RotatableStateResponse => onRotatableStateResponse(p)
case PacketType.ScreenBufferResponse => onScreenBufferResponse(p)
case PacketType.RobotState => onRobotState(p)
case PacketType.RotatableState => onRotatableState(p)
case PacketType.ScreenColorChange => onScreenColorChange(p)
case PacketType.ScreenCopy => onScreenCopy(p)
case PacketType.ScreenDepthChange => onScreenDepthChange(p)
@ -64,13 +63,13 @@ class PacketHandler extends CommonPacketHandler {
}
}
def onChargerStateResponse(p: PacketParser) =
def onChargerState(p: PacketParser) =
p.readTileEntity[Charger]() match {
case Some(t) => t.chargeSpeed = p.readDouble()
case _ => // Invalid packet.
}
def onComputerStateResponse(p: PacketParser) =
def onComputerState(p: PacketParser) =
p.readTileEntity[Computer]() match {
case Some(t) => t.isRunning = p.readBoolean()
case _ => // Invalid packet.
@ -102,7 +101,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onPowerStateResponse(p: PacketParser) =
def onPowerState(p: PacketParser) =
p.readTileEntity[PowerInformation]() match {
case Some(t) =>
t.globalBuffer = p.readDouble()
@ -110,7 +109,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onRedstoneStateResponse(p: PacketParser) =
def onRedstoneState(p: PacketParser) =
p.readTileEntity[Redstone]() match {
case Some(t) =>
t.isOutputEnabled = p.readBoolean()
@ -150,7 +149,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onRobotStateResponse(p: PacketParser) =
def onRobotState(p: PacketParser) =
p.readTileEntity[RobotProxy]() match {
case Some(t) =>
t.robot.selectedSlot = p.readInt()
@ -163,7 +162,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onRotatableStateResponse(p: PacketParser) =
def onRotatableState(p: PacketParser) =
p.readTileEntity[Rotatable]() match {
case Some(t) =>
t.pitch = p.readDirection()
@ -171,28 +170,6 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onScreenBufferResponse(p: PacketParser) =
p.readTileEntity[Buffer]() match {
case Some(t) =>
val screen = t.buffer
val w = p.readInt()
val h = p.readInt()
screen.resolution = (w, h)
p.readUTF.split('\n').zipWithIndex.foreach {
case (line, i) => screen.set(0, i, line)
}
screen.depth = PackedColor.Depth(p.readInt())
screen.foreground = p.readInt()
screen.background = p.readInt()
for (row <- 0 until h) {
val rowColor = screen.color(row)
for (col <- 0 until w) {
rowColor(col) = p.readShort()
}
}
case _ => // Invalid packet.
}
def onScreenColorChange(p: PacketParser) =
p.readTileEntity[Buffer]() match {
case Some(t) =>

View File

@ -5,14 +5,6 @@ import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity._
object PacketSender {
def sendChargerStateRequest(t: Charger) {
val pb = new PacketBuilder(PacketType.ChargerStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendComputerPower(t: Computer, power: Boolean) {
val pb = new PacketBuilder(PacketType.ComputerPower)
@ -22,54 +14,6 @@ object PacketSender {
pb.sendToServer()
}
def sendComputerStateRequest(t: Computer) {
val pb = new PacketBuilder(PacketType.ComputerStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendPowerStateRequest(t: PowerInformation) {
val pb = new PacketBuilder(PacketType.PowerStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendRedstoneStateRequest(t: Redstone) {
val pb = new PacketBuilder(PacketType.RedstoneStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendRobotStateRequest(t: Robot) {
val pb = new PacketBuilder(PacketType.RobotStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendRotatableStateRequest(t: Rotatable) {
val pb = new PacketBuilder(PacketType.RotatableStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendScreenBufferRequest(t: Buffer) {
val pb = new PacketBuilder(PacketType.ScreenBufferRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendKeyDown[T <: Buffer](t: T, char: Char, code: Int) = if (t.hasKeyboard) {
val pb = new PacketBuilder(PacketType.KeyDown)

View File

@ -5,7 +5,7 @@ import cpw.mods.fml.common.network.Player
import java.io.ByteArrayInputStream
import java.io.DataInputStream
import java.util.logging.Level
import li.cil.oc.{Blocks, OpenComputers}
import li.cil.oc.OpenComputers
import net.minecraft.item.ItemStack
import net.minecraft.nbt.{NBTTagCompound, NBTBase}
import net.minecraft.network.INetworkManager
@ -58,11 +58,6 @@ abstract class PacketHandler extends IPacketHandler {
if (t != null && classTag[T].runtimeClass.isAssignableFrom(t.getClass)) {
return Some(t.asInstanceOf[T])
}
// Special handling for robot after images to avoid them having to
Blocks.robotAfterimage.findMovingRobot(world, x, y, z) match {
case Some(robot) if classTag[T].runtimeClass.isAssignableFrom(robot.proxy.getClass) => return Some(robot.proxy.asInstanceOf[T])
case _ =>
}
}
None
}

View File

@ -2,36 +2,20 @@ package li.cil.oc.common
object PacketType extends Enumeration {
val
ChargerStateRequest,
ChargerStateResponse,
ComputerPower,
ComputerStateRequest,
ComputerStateResponse,
// Server -> Client
Analyze,
ChargerState,
ComputerState,
ItemComponentAddress,
PowerStateRequest,
PowerStateResponse,
RedstoneStateRequest,
RedstoneStateResponse,
PowerState,
RedstoneState,
RobotAnimateSwing,
RobotAnimateTurn,
RobotEquippedItemChange,
RobotMove,
RobotSelectedSlotChange,
RobotStateRequest,
RobotStateResponse,
RotatableStateRequest,
RotatableStateResponse,
ScreenBufferRequest,
ScreenBufferResponse,
RobotState,
RotatableState,
ScreenColorChange,
ScreenCopy,
ScreenDepthChange,
@ -40,9 +24,9 @@ object PacketType extends Enumeration {
ScreenResolutionChange,
ScreenSet,
// Client -> Server
ComputerPower,
KeyDown,
KeyUp,
Clipboard,
Analyze = Value
Clipboard = Value
}

View File

@ -5,10 +5,10 @@ import li.cil.oc.api.network.Node
import li.cil.oc.client.gui
import li.cil.oc.common.component
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.{PackedColor, Persistable}
import li.cil.oc.util.PackedColor
import net.minecraft.nbt.NBTTagCompound
trait Buffer extends Environment with Persistable {
trait Buffer extends Environment {
protected val _buffer = new component.Buffer(this)
protected var _bufferIsDirty = false
@ -43,6 +43,17 @@ trait Buffer extends Environment with Persistable {
buffer.save(nbt)
}
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
buffer.buffer.load(nbt)
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
buffer.buffer.save(nbt)
}
// ----------------------------------------------------------------------- //
def onScreenColorChange(foreground: Int, background: Int) {

View File

@ -1,9 +1,10 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.api.network.{Node, Visibility}
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.{Settings, api}
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection
class Charger extends Environment with Redstone {
@ -38,15 +39,6 @@ class Charger extends Environment with Redstone {
}
}
override def validate() {
super.validate()
chargeSpeed = 0.0 max (ForgeDirection.VALID_DIRECTIONS.map(input).max min 15) / 15.0
if (isClient) {
ClientPacketSender.sendChargerStateRequest(this)
ClientPacketSender.sendRedstoneStateRequest(this)
}
}
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
@ -54,6 +46,31 @@ class Charger extends Environment with Redstone {
}
}
// ----------------------------------------------------------------------- //
override def load(nbt: NBTTagCompound) {
super.load(nbt)
chargeSpeed = nbt.getDouble("chargeSpeed")
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDouble("chargeSpeed", chargeSpeed)
}
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
chargeSpeed = nbt.getDouble("chargeSpeed")
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setDouble("chargeSpeed", chargeSpeed)
}
// ----------------------------------------------------------------------- //
override protected def onRedstoneInputChanged(side: ForgeDirection) {
super.onRedstoneInputChanged(side)
chargeSpeed = 0.0 max (ForgeDirection.VALID_DIRECTIONS.map(input).max min 15) / 15.0

View File

@ -5,11 +5,10 @@ import li.cil.oc.api.network
import li.cil.oc.api.network.{ManagedEnvironment, Node}
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.Persistable
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
trait ComponentInventory extends Inventory with network.Environment with Persistable {
trait ComponentInventory extends Inventory with network.Environment {
protected lazy val components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None)
// ----------------------------------------------------------------------- //

View File

@ -1,8 +1,8 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.Settings
import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
@ -75,15 +75,6 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
super.updateEntity()
}
override def validate() = {
super.validate()
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
ClientPacketSender.sendComputerStateRequest(this)
ClientPacketSender.sendRedstoneStateRequest(this)
}
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
@ -100,6 +91,17 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
}
}
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
isRunning = nbt.getBoolean("isRunning")
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setBoolean("isRunning", isRunning)
}
// ----------------------------------------------------------------------- //
override def onInventoryChanged() {

View File

@ -2,7 +2,6 @@ package li.cil.oc.common.tileentity
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network.{Component, Visibility}
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.driver.Registry
import li.cil.oc.{Blocks, api, Settings}
import net.minecraft.item.ItemStack
@ -16,9 +15,6 @@ class DiskDrive extends Environment with ComponentInventory with Rotatable {
override def validate() = {
super.validate()
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
}
world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.diskDrive.parent.blockID, 0, 0)
}

View File

@ -5,6 +5,8 @@ import li.cil.oc.api.{Network, network}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.Persistable
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.network.INetworkManager
import net.minecraft.network.packet.Packet132TileEntityData
import scala.math.ScalaNumber
abstract class Environment extends net.minecraft.tileentity.TileEntity with TileEntity with network.Environment with Persistable {
@ -53,6 +55,18 @@ abstract class Environment extends net.minecraft.tileentity.TileEntity with Tile
// ----------------------------------------------------------------------- //
override def getDescriptionPacket = {
val nbt = new NBTTagCompound()
writeToNBTForClient(nbt)
if (nbt.hasNoTags) null else new Packet132TileEntityData(x, y, z, -1, nbt)
}
override def onDataPacket(manager: INetworkManager, packet: Packet132TileEntityData) {
readFromNBTForClient(packet.data)
}
// ----------------------------------------------------------------------- //
def onMessage(message: network.Message) {}
def onConnect(node: network.Node) {}

View File

@ -1,7 +1,6 @@
package li.cil.oc.common.tileentity
import li.cil.oc.api.network.{Analyzable, SidedEnvironment}
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.{Blocks, Settings}
@ -29,9 +28,6 @@ class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with
override def validate() {
super.validate()
world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.keyboard.parent.blockID, 0, 0)
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
}
}
override def readFromNBT(nbt: NBTTagCompound) {

View File

@ -2,7 +2,6 @@ package li.cil.oc.common.tileentity
import li.cil.oc.Settings
import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
@ -44,11 +43,4 @@ class PowerDistributor extends Environment with PowerInformation with Analyzable
super.updateEntity()
distributor.update()
}
override def validate() {
super.validate()
if (isClient) {
ClientPacketSender.sendPowerStateRequest(this)
}
}
}

View File

@ -1,5 +1,8 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import net.minecraft.nbt.NBTTagCompound
trait PowerInformation extends TileEntity {
def globalBuffer: Double
@ -8,4 +11,17 @@ trait PowerInformation extends TileEntity {
def globalBufferSize: Double
def globalBufferSize_=(value: Double)
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
globalBuffer = nbt.getDouble("globalBuffer")
globalBufferSize = nbt.getDouble("globalBufferSize")
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setDouble("globalBuffer", globalBuffer)
nbt.setDouble("globalBufferSize", globalBufferSize)
}
}

View File

@ -2,6 +2,7 @@ package li.cil.oc.common.tileentity
import cpw.mods.fml.common.Optional.Interface
import cpw.mods.fml.common.{Loader, Optional}
import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.Settings
import li.cil.oc.api.network
import li.cil.oc.server.{PacketSender => ServerPacketSender}
@ -17,7 +18,7 @@ import net.minecraftforge.common.ForgeDirection
new Interface(iface = "mods.immibis.redlogic.api.wiring.IRedstoneEmitter", modid = "RedLogic"),
new Interface(iface = "mods.immibis.redlogic.api.wiring.IRedstoneUpdatable", modid = "RedLogic")
))
trait Redstone extends TileEntity with network.Environment with Rotatable with Persistable with IConnectable with IRedstoneEmitter with IRedstoneUpdatable {
trait Redstone extends RotationAware with network.Environment with Persistable with IConnectable with IRedstoneEmitter with IRedstoneUpdatable {
protected val _input = Array.fill(6)(-1)
protected val _output = Array.fill(6)(0)
@ -86,6 +87,19 @@ trait Redstone extends TileEntity with network.Environment with Rotatable with P
nbt.setIntArray(Settings.namespace + "rs.output", _output)
}
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
isOutputEnabled = nbt.getBoolean("isOutputEnabled")
nbt.getIntArray("output").copyToArray(_output)
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setBoolean("isOutputEnabled", isOutputEnabled)
nbt.setIntArray("output", _output)
}
// ----------------------------------------------------------------------- //
protected def computeInput(side: ForgeDirection) = {

View File

@ -221,11 +221,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
case _ =>
}
}
else {
ClientPacketSender.sendPowerStateRequest(this)
ClientPacketSender.sendRobotStateRequest(this)
ClientPacketSender.sendScreenBufferRequest(this)
}
}
override def invalidate() {
@ -275,6 +270,37 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
}
}
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
selectedSlot = nbt.getInteger("selectedSlot")
if (nbt.hasKey("equipped")) {
equippedItem = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("equipped")))
}
animationTicksTotal = nbt.getInteger("animationTicksTotal")
animationTicksLeft = nbt.getInteger("animationTicksLeft")
if (animationTicksLeft > 0) {
moveDirection = ForgeDirection.getOrientation(nbt.getByte("moveDirection"))
swingingTool = nbt.getBoolean("swingingTool")
turnAxis = nbt.getByte("turnAxis")
}
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setInteger("selectedSlot", selectedSlot)
if (getStackInSlot(0) != null) {
nbt.setNewCompoundTag("equipped", getStackInSlot(0).writeToNBT)
}
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
nbt.setInteger("animationTicksTotal", animationTicksTotal)
nbt.setInteger("animationTicksLeft", animationTicksLeft)
nbt.setByte("moveDirection", moveDirection.ordinal.toByte)
nbt.setBoolean("swingingTool", swingingTool)
nbt.setByte("turnAxis", turnAxis.toByte)
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {

View File

@ -12,6 +12,7 @@ import net.minecraft.inventory.ISidedInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection
import cpw.mods.fml.relauncher.{Side, SideOnly}
class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedInventory with Buffer with PowerInformation {
def this() = this(new Robot(false))
@ -86,6 +87,11 @@ class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedI
override def load(nbt: NBTTagCompound) = robot.load(nbt)
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) = robot.readFromNBTForClient(nbt)
override def writeToNBTForClient(nbt: NBTTagCompound) = robot.writeToNBTForClient(nbt)
override def getMaxRenderDistanceSquared = robot.getMaxRenderDistanceSquared
override def getRenderBoundingBox = robot.getRenderBoundingBox

View File

@ -1,5 +1,6 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.Settings
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.Persistable
@ -9,7 +10,7 @@ import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection
/** TileEntity base class for rotatable blocks. */
trait Rotatable extends TileEntity with Persistable {
trait Rotatable extends RotationAware with Persistable {
// ----------------------------------------------------------------------- //
// Lookup tables
// ----------------------------------------------------------------------- //
@ -137,9 +138,9 @@ trait Rotatable extends TileEntity with Persistable {
trySetPitchYaw(newPitch, newYaw)
}
def toLocal(value: ForgeDirection) = cachedTranslation(value.ordinal)
override def toLocal(value: ForgeDirection) = cachedTranslation(value.ordinal)
def toGlobal(value: ForgeDirection) = cachedInverseTranslation(value.ordinal)
override def toGlobal(value: ForgeDirection) = cachedInverseTranslation(value.ordinal)
// ----------------------------------------------------------------------- //
@ -155,7 +156,6 @@ trait Rotatable extends TileEntity with Persistable {
override def load(nbt: NBTTagCompound) = {
super.load(nbt)
_pitch = ForgeDirection.getOrientation(nbt.getInteger(Settings.namespace + "pitch"))
_yaw = ForgeDirection.getOrientation(nbt.getInteger(Settings.namespace + "yaw"))
updateTranslation()
@ -163,11 +163,24 @@ trait Rotatable extends TileEntity with Persistable {
override def save(nbt: NBTTagCompound) = {
super.save(nbt)
nbt.setInteger(Settings.namespace + "pitch", _pitch.ordinal)
nbt.setInteger(Settings.namespace + "yaw", _yaw.ordinal)
}
@SideOnly(Side.CLIENT)
override def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
_pitch = ForgeDirection.getOrientation(nbt.getInteger("pitch"))
_yaw = ForgeDirection.getOrientation(nbt.getInteger("yaw"))
updateTranslation()
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setInteger("pitch", _pitch.ordinal)
nbt.setInteger("yaw", _yaw.ordinal)
}
// ----------------------------------------------------------------------- //
/** Updates cached translation array and sends notification to clients. */

View File

@ -0,0 +1,9 @@
package li.cil.oc.common.tileentity
import net.minecraftforge.common.ForgeDirection
trait RotationAware extends TileEntity {
def toLocal(value: ForgeDirection) = value
def toGlobal(value: ForgeDirection) = value
}

View File

@ -9,18 +9,15 @@ import net.minecraftforge.common.ForgeDirection
class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedEnvironment {
private val plugs = ForgeDirection.VALID_DIRECTIONS.map(side => new Plug(side))
// ----------------------------------------------------------------------- //
def canConnect(side: ForgeDirection) = true
def sidedNode(side: ForgeDirection) = plugs(side.ordinal()).node
override def canUpdate = false
// ----------------------------------------------------------------------- //
override def onChunkUnload() {
super.onChunkUnload()
for (plug <- plugs if plug.node != null) {
plug.node.remove()
}
}
override def canUpdate = false
override def validate() {
super.validate()
@ -34,6 +31,22 @@ class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedE
}
}
override def onChunkUnload() {
super.onChunkUnload()
for (plug <- plugs if plug.node != null) {
plug.node.remove()
}
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
nbt.getTagList(Settings.namespace + "plugs").iterator[NBTTagCompound].zip(plugs).foreach {
case (plugNbt, plug) => plug.node.load(plugNbt)
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
nbt.setNewTagList(Settings.namespace + "plugs", plugs.map(plug => {
@ -43,12 +56,7 @@ class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedE
}))
}
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
nbt.getTagList(Settings.namespace + "plugs").iterator[NBTTagCompound].zip(plugs).foreach {
case (plugNbt, plug) => plug.node.load(plugNbt)
}
}
// ----------------------------------------------------------------------- //
private class Plug(val side: ForgeDirection) extends api.network.Environment {
val node = api.Network.newNode(this, Visibility.Network).create()

View File

@ -140,14 +140,6 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
}
}
override def validate() {
super.validate()
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
ClientPacketSender.sendScreenBufferRequest(this)
}
}
override def invalidate() {
super.invalidate()
if (currentGui.isDefined) {

View File

@ -1,6 +1,8 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import net.minecraft.block.Block
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
trait TileEntity {
@ -17,4 +19,9 @@ trait TileEntity {
def isClient = world.isRemote
def isServer = !isClient
@SideOnly(Side.CLIENT)
def readFromNBTForClient(nbt: NBTTagCompound) {}
def writeToNBTForClient(nbt: NBTTagCompound) {}
}

View File

@ -14,26 +14,13 @@ class PacketHandler extends CommonPacketHandler {
def dispatch(p: PacketParser) =
p.packetType match {
case PacketType.ChargerStateRequest => onChargerStateRequest(p)
case PacketType.ComputerPower => onComputerPower(p)
case PacketType.ComputerStateRequest => onComputerStateRequest(p)
case PacketType.PowerStateRequest => onPowerStateRequest(p)
case PacketType.RedstoneStateRequest => onRedstoneStateRequest(p)
case PacketType.RobotStateRequest => onRobotStateRequest(p)
case PacketType.RotatableStateRequest => onRotatableStateRequest(p)
case PacketType.ScreenBufferRequest => onScreenBufferRequest(p)
case PacketType.KeyDown => onKeyDown(p)
case PacketType.KeyUp => onKeyUp(p)
case PacketType.Clipboard => onClipboard(p)
case _ => // Invalid packet.
}
def onChargerStateRequest(p: PacketParser) =
p.readTileEntity[Charger]() match {
case Some(t) => PacketSender.sendChargerState(t, Option(p.player))
case _ => // Invalid packet.
}
def onComputerPower(p: PacketParser) =
p.readTileEntity[Computer]() match {
case Some(t) => p.player match {
@ -47,42 +34,6 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onComputerStateRequest(p: PacketParser) =
p.readTileEntity[Computer]() match {
case Some(t) => PacketSender.sendComputerState(t, Option(p.player))
case _ => // Invalid packet.
}
def onPowerStateRequest(p: PacketParser) =
p.readTileEntity[PowerInformation]() match {
case Some(t) => PacketSender.sendPowerState(t, Option(p.player))
case _ => // Invalid packet.
}
def onRedstoneStateRequest(p: PacketParser) =
p.readTileEntity[Redstone]() match {
case Some(t) => PacketSender.sendRedstoneState(t, Option(p.player))
case _ => // Invalid packet.
}
def onRobotStateRequest(p: PacketParser) =
p.readTileEntity[RobotProxy]() match {
case Some(t) => PacketSender.sendRobotState(t.robot, Option(p.player))
case _ => // Invalid packet.
}
def onRotatableStateRequest(p: PacketParser) =
p.readTileEntity[Rotatable]() match {
case Some(t) => PacketSender.sendRotatableState(t, Option(p.player))
case _ => // Invalid packet.
}
def onScreenBufferRequest(p: PacketParser) =
p.readTileEntity[Buffer]() match {
case Some(t) => PacketSender.sendScreenBufferState(t, Option(p.player))
case _ => // Invalid packet.
}
def onKeyDown(p: PacketParser) =
p.readTileEntity[Buffer]() match {
case Some(s: Screen) =>

View File

@ -23,7 +23,7 @@ object PacketSender {
}
def sendChargerState(t: Charger, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.ChargerStateResponse)
val pb = new PacketBuilder(PacketType.ChargerState)
pb.writeTileEntity(t)
pb.writeDouble(t.chargeSpeed)
@ -35,7 +35,7 @@ object PacketSender {
}
def sendComputerState(t: Computer, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.ComputerStateResponse)
val pb = new PacketBuilder(PacketType.ComputerState)
pb.writeTileEntity(t)
pb.writeBoolean(t.isRunning)
@ -59,7 +59,7 @@ object PacketSender {
}
def sendPowerState(t: PowerInformation, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.PowerStateResponse)
val pb = new PacketBuilder(PacketType.PowerState)
pb.writeTileEntity(t)
pb.writeDouble(t.globalBuffer)
@ -72,7 +72,7 @@ object PacketSender {
}
def sendRedstoneState(t: Redstone, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.RedstoneStateResponse)
val pb = new PacketBuilder(PacketType.RedstoneState)
pb.writeTileEntity(t)
pb.writeBoolean(t.isOutputEnabled)
@ -136,26 +136,8 @@ object PacketSender {
pb.sendToAllPlayers()
}
def sendRobotState(t: Robot, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.RobotStateResponse)
pb.writeTileEntity(t.proxy)
pb.writeInt(t.selectedSlot)
pb.writeItemStack(t.getStackInSlot(0))
pb.writeInt(t.animationTicksTotal)
pb.writeInt(t.animationTicksLeft)
pb.writeDirection(t.moveDirection)
pb.writeBoolean(t.swingingTool)
pb.writeByte(t.turnAxis)
player match {
case Some(p) => pb.sendToPlayer(p)
case _ => pb.sendToAllPlayers()
}
}
def sendRotatableState(t: Rotatable, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.RotatableStateResponse)
val pb = new PacketBuilder(PacketType.RotatableState)
pb.writeTileEntity(t)
pb.writeDirection(t.pitch)
@ -167,27 +149,6 @@ object PacketSender {
}
}
def sendScreenBufferState(t: Buffer, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.ScreenBufferResponse)
pb.writeTileEntity(t)
val screen = t.buffer
val (w, h) = screen.resolution
pb.writeInt(w)
pb.writeInt(h)
pb.writeUTF(screen.text)
pb.writeInt(screen.depth.id)
pb.writeInt(screen.foreground)
pb.writeInt(screen.background)
for (cs <- screen.color) for (c <- cs) pb.writeShort(c)
player match {
case Some(p) => pb.sendToPlayer(p)
case _ => pb.sendToAllPlayers()
}
}
def sendScreenColorChange(t: Buffer, foreground: Int, background: Int) {
val pb = new PacketBuilder(PacketType.ScreenColorChange)