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) = override def dispatch(p: PacketParser) =
p.packetType match { p.packetType match {
case PacketType.Analyze => onAnalyze(p) case PacketType.Analyze => onAnalyze(p)
case PacketType.ChargerStateResponse => onChargerStateResponse(p) case PacketType.ChargerState => onChargerState(p)
case PacketType.ComputerStateResponse => onComputerStateResponse(p) case PacketType.ComputerState => onComputerState(p)
case PacketType.ItemComponentAddress => onItemComponentAddress(p) case PacketType.ItemComponentAddress => onItemComponentAddress(p)
case PacketType.PowerStateResponse => onPowerStateResponse(p) case PacketType.PowerState => onPowerState(p)
case PacketType.RedstoneStateResponse => onRedstoneStateResponse(p) case PacketType.RedstoneState => onRedstoneState(p)
case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p) case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p)
case PacketType.RobotAnimateTurn => onRobotAnimateTurn(p) case PacketType.RobotAnimateTurn => onRobotAnimateTurn(p)
case PacketType.RobotEquippedItemChange => onRobotEquippedItemChange(p) case PacketType.RobotEquippedItemChange => onRobotEquippedItemChange(p)
case PacketType.RobotMove => onRobotMove(p) case PacketType.RobotMove => onRobotMove(p)
case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p) case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p)
case PacketType.RobotStateResponse => onRobotStateResponse(p) case PacketType.RobotState => onRobotState(p)
case PacketType.RotatableStateResponse => onRotatableStateResponse(p) case PacketType.RotatableState => onRotatableState(p)
case PacketType.ScreenBufferResponse => onScreenBufferResponse(p)
case PacketType.ScreenColorChange => onScreenColorChange(p) case PacketType.ScreenColorChange => onScreenColorChange(p)
case PacketType.ScreenCopy => onScreenCopy(p) case PacketType.ScreenCopy => onScreenCopy(p)
case PacketType.ScreenDepthChange => onScreenDepthChange(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 { p.readTileEntity[Charger]() match {
case Some(t) => t.chargeSpeed = p.readDouble() case Some(t) => t.chargeSpeed = p.readDouble()
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onComputerStateResponse(p: PacketParser) = def onComputerState(p: PacketParser) =
p.readTileEntity[Computer]() match { p.readTileEntity[Computer]() match {
case Some(t) => t.isRunning = p.readBoolean() case Some(t) => t.isRunning = p.readBoolean()
case _ => // Invalid packet. case _ => // Invalid packet.
@ -102,7 +101,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onPowerStateResponse(p: PacketParser) = def onPowerState(p: PacketParser) =
p.readTileEntity[PowerInformation]() match { p.readTileEntity[PowerInformation]() match {
case Some(t) => case Some(t) =>
t.globalBuffer = p.readDouble() t.globalBuffer = p.readDouble()
@ -110,7 +109,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onRedstoneStateResponse(p: PacketParser) = def onRedstoneState(p: PacketParser) =
p.readTileEntity[Redstone]() match { p.readTileEntity[Redstone]() match {
case Some(t) => case Some(t) =>
t.isOutputEnabled = p.readBoolean() t.isOutputEnabled = p.readBoolean()
@ -150,7 +149,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onRobotStateResponse(p: PacketParser) = def onRobotState(p: PacketParser) =
p.readTileEntity[RobotProxy]() match { p.readTileEntity[RobotProxy]() match {
case Some(t) => case Some(t) =>
t.robot.selectedSlot = p.readInt() t.robot.selectedSlot = p.readInt()
@ -163,7 +162,7 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onRotatableStateResponse(p: PacketParser) = def onRotatableState(p: PacketParser) =
p.readTileEntity[Rotatable]() match { p.readTileEntity[Rotatable]() match {
case Some(t) => case Some(t) =>
t.pitch = p.readDirection() t.pitch = p.readDirection()
@ -171,28 +170,6 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. 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) = def onScreenColorChange(p: PacketParser) =
p.readTileEntity[Buffer]() match { p.readTileEntity[Buffer]() match {
case Some(t) => case Some(t) =>

View File

@ -5,14 +5,6 @@ import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity._ import li.cil.oc.common.tileentity._
object PacketSender { object PacketSender {
def sendChargerStateRequest(t: Charger) {
val pb = new PacketBuilder(PacketType.ChargerStateRequest)
pb.writeTileEntity(t)
pb.sendToServer()
}
def sendComputerPower(t: Computer, power: Boolean) { def sendComputerPower(t: Computer, power: Boolean) {
val pb = new PacketBuilder(PacketType.ComputerPower) val pb = new PacketBuilder(PacketType.ComputerPower)
@ -22,54 +14,6 @@ object PacketSender {
pb.sendToServer() 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) { def sendKeyDown[T <: Buffer](t: T, char: Char, code: Int) = if (t.hasKeyboard) {
val pb = new PacketBuilder(PacketType.KeyDown) 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.ByteArrayInputStream
import java.io.DataInputStream import java.io.DataInputStream
import java.util.logging.Level import java.util.logging.Level
import li.cil.oc.{Blocks, OpenComputers} import li.cil.oc.OpenComputers
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.{NBTTagCompound, NBTBase} import net.minecraft.nbt.{NBTTagCompound, NBTBase}
import net.minecraft.network.INetworkManager import net.minecraft.network.INetworkManager
@ -58,11 +58,6 @@ abstract class PacketHandler extends IPacketHandler {
if (t != null && classTag[T].runtimeClass.isAssignableFrom(t.getClass)) { if (t != null && classTag[T].runtimeClass.isAssignableFrom(t.getClass)) {
return Some(t.asInstanceOf[T]) 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 None
} }

View File

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

View File

@ -5,10 +5,10 @@ import li.cil.oc.api.network.Node
import li.cil.oc.client.gui import li.cil.oc.client.gui
import li.cil.oc.common.component import li.cil.oc.common.component
import li.cil.oc.server.{PacketSender => ServerPacketSender} 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 import net.minecraft.nbt.NBTTagCompound
trait Buffer extends Environment with Persistable { trait Buffer extends Environment {
protected val _buffer = new component.Buffer(this) protected val _buffer = new component.Buffer(this)
protected var _bufferIsDirty = false protected var _bufferIsDirty = false
@ -43,6 +43,17 @@ trait Buffer extends Environment with Persistable {
buffer.save(nbt) 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) { def onScreenColorChange(foreground: Int, background: Int) {

View File

@ -1,9 +1,10 @@
package li.cil.oc.common.tileentity 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.api.network.{Node, Visibility}
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.{Settings, api} import li.cil.oc.{Settings, api}
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
class Charger extends Environment with Redstone { 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) { override def onConnect(node: Node) {
super.onConnect(node) super.onConnect(node)
if (node == this.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) { override protected def onRedstoneInputChanged(side: ForgeDirection) {
super.onRedstoneInputChanged(side) super.onRedstoneInputChanged(side)
chargeSpeed = 0.0 max (ForgeDirection.VALID_DIRECTIONS.map(input).max min 15) / 15.0 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.api.network.{ManagedEnvironment, Node}
import li.cil.oc.server.driver.Registry import li.cil.oc.server.driver.Registry
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.Persistable
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound 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) protected lazy val components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None)
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -1,8 +1,8 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api.network._ 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.server.{PacketSender => ServerPacketSender, driver, component}
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
@ -75,15 +75,6 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
super.updateEntity() super.updateEntity()
} }
override def validate() = {
super.validate()
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
ClientPacketSender.sendComputerStateRequest(this)
ClientPacketSender.sendRedstoneStateRequest(this)
}
}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) { 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() { 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.driver.Slot
import li.cil.oc.api.network.{Component, Visibility} 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.server.driver.Registry
import li.cil.oc.{Blocks, api, Settings} import li.cil.oc.{Blocks, api, Settings}
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
@ -16,9 +15,6 @@ class DiskDrive extends Environment with ComponentInventory with Rotatable {
override def validate() = { override def validate() = {
super.validate() super.validate()
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
}
world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.diskDrive.parent.blockID, 0, 0) 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.ExtendedNBT._
import li.cil.oc.util.Persistable import li.cil.oc.util.Persistable
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.network.INetworkManager
import net.minecraft.network.packet.Packet132TileEntityData
import scala.math.ScalaNumber import scala.math.ScalaNumber
abstract class Environment extends net.minecraft.tileentity.TileEntity with TileEntity with network.Environment with Persistable { 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 onMessage(message: network.Message) {}
def onConnect(node: network.Node) {} def onConnect(node: network.Node) {}

View File

@ -1,7 +1,6 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import li.cil.oc.api.network.{Analyzable, SidedEnvironment} 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.server.component
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.{Blocks, Settings} import li.cil.oc.{Blocks, Settings}
@ -29,9 +28,6 @@ class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with
override def validate() { override def validate() {
super.validate() super.validate()
world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.keyboard.parent.blockID, 0, 0) world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.keyboard.parent.blockID, 0, 0)
if (isClient) {
ClientPacketSender.sendRotatableStateRequest(this)
}
} }
override def readFromNBT(nbt: NBTTagCompound) { 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.Settings
import li.cil.oc.api.network._ import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.component import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
@ -44,11 +43,4 @@ class PowerDistributor extends Environment with PowerInformation with Analyzable
super.updateEntity() super.updateEntity()
distributor.update() distributor.update()
} }
override def validate() {
super.validate()
if (isClient) {
ClientPacketSender.sendPowerStateRequest(this)
}
}
} }

View File

@ -1,5 +1,8 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import net.minecraft.nbt.NBTTagCompound
trait PowerInformation extends TileEntity { trait PowerInformation extends TileEntity {
def globalBuffer: Double def globalBuffer: Double
@ -8,4 +11,17 @@ trait PowerInformation extends TileEntity {
def globalBufferSize: Double def globalBufferSize: Double
def globalBufferSize_=(value: 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.Optional.Interface
import cpw.mods.fml.common.{Loader, Optional} import cpw.mods.fml.common.{Loader, Optional}
import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api.network import li.cil.oc.api.network
import li.cil.oc.server.{PacketSender => ServerPacketSender} 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.IRedstoneEmitter", modid = "RedLogic"),
new Interface(iface = "mods.immibis.redlogic.api.wiring.IRedstoneUpdatable", 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 _input = Array.fill(6)(-1)
protected val _output = Array.fill(6)(0) 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) 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) = { protected def computeInput(side: ForgeDirection) = {

View File

@ -221,11 +221,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
case _ => case _ =>
} }
} }
else {
ClientPacketSender.sendPowerStateRequest(this)
ClientPacketSender.sendRobotStateRequest(this)
ClientPacketSender.sendScreenBufferRequest(this)
}
} }
override def invalidate() { 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) { override def onConnect(node: Node) {

View File

@ -12,6 +12,7 @@ import net.minecraft.inventory.ISidedInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection 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 { class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedInventory with Buffer with PowerInformation {
def this() = this(new Robot(false)) 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) 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 getMaxRenderDistanceSquared = robot.getMaxRenderDistanceSquared
override def getRenderBoundingBox = robot.getRenderBoundingBox override def getRenderBoundingBox = robot.getRenderBoundingBox

View File

@ -1,5 +1,6 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.Persistable import li.cil.oc.util.Persistable
@ -9,7 +10,7 @@ import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
/** TileEntity base class for rotatable blocks. */ /** TileEntity base class for rotatable blocks. */
trait Rotatable extends TileEntity with Persistable { trait Rotatable extends RotationAware with Persistable {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
// Lookup tables // Lookup tables
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -137,9 +138,9 @@ trait Rotatable extends TileEntity with Persistable {
trySetPitchYaw(newPitch, newYaw) 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) = { override def load(nbt: NBTTagCompound) = {
super.load(nbt) super.load(nbt)
_pitch = ForgeDirection.getOrientation(nbt.getInteger(Settings.namespace + "pitch")) _pitch = ForgeDirection.getOrientation(nbt.getInteger(Settings.namespace + "pitch"))
_yaw = ForgeDirection.getOrientation(nbt.getInteger(Settings.namespace + "yaw")) _yaw = ForgeDirection.getOrientation(nbt.getInteger(Settings.namespace + "yaw"))
updateTranslation() updateTranslation()
@ -163,11 +163,24 @@ trait Rotatable extends TileEntity with Persistable {
override def save(nbt: NBTTagCompound) = { override def save(nbt: NBTTagCompound) = {
super.save(nbt) super.save(nbt)
nbt.setInteger(Settings.namespace + "pitch", _pitch.ordinal) nbt.setInteger(Settings.namespace + "pitch", _pitch.ordinal)
nbt.setInteger(Settings.namespace + "yaw", _yaw.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. */ /** 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 { class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedEnvironment {
private val plugs = ForgeDirection.VALID_DIRECTIONS.map(side => new Plug(side)) private val plugs = ForgeDirection.VALID_DIRECTIONS.map(side => new Plug(side))
// ----------------------------------------------------------------------- //
def canConnect(side: ForgeDirection) = true def canConnect(side: ForgeDirection) = true
def sidedNode(side: ForgeDirection) = plugs(side.ordinal()).node def sidedNode(side: ForgeDirection) = plugs(side.ordinal()).node
override def canUpdate = false // ----------------------------------------------------------------------- //
override def onChunkUnload() { override def canUpdate = false
super.onChunkUnload()
for (plug <- plugs if plug.node != null) {
plug.node.remove()
}
}
override def validate() { override def validate() {
super.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) { override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt) super.writeToNBT(nbt)
nbt.setNewTagList(Settings.namespace + "plugs", plugs.map(plug => { 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 { private class Plug(val side: ForgeDirection) extends api.network.Environment {
val node = api.Network.newNode(this, Visibility.Network).create() 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() { override def invalidate() {
super.invalidate() super.invalidate()
if (currentGui.isDefined) { if (currentGui.isDefined) {

View File

@ -1,6 +1,8 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World import net.minecraft.world.World
trait TileEntity { trait TileEntity {
@ -17,4 +19,9 @@ trait TileEntity {
def isClient = world.isRemote def isClient = world.isRemote
def isServer = !isClient 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) = def dispatch(p: PacketParser) =
p.packetType match { p.packetType match {
case PacketType.ChargerStateRequest => onChargerStateRequest(p)
case PacketType.ComputerPower => onComputerPower(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.KeyDown => onKeyDown(p)
case PacketType.KeyUp => onKeyUp(p) case PacketType.KeyUp => onKeyUp(p)
case PacketType.Clipboard => onClipboard(p) case PacketType.Clipboard => onClipboard(p)
case _ => // Invalid packet. 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) = def onComputerPower(p: PacketParser) =
p.readTileEntity[Computer]() match { p.readTileEntity[Computer]() match {
case Some(t) => p.player match { case Some(t) => p.player match {
@ -47,42 +34,6 @@ class PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. 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) = def onKeyDown(p: PacketParser) =
p.readTileEntity[Buffer]() match { p.readTileEntity[Buffer]() match {
case Some(s: Screen) => case Some(s: Screen) =>

View File

@ -23,7 +23,7 @@ object PacketSender {
} }
def sendChargerState(t: Charger, player: Option[Player] = None) { def sendChargerState(t: Charger, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.ChargerStateResponse) val pb = new PacketBuilder(PacketType.ChargerState)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeDouble(t.chargeSpeed) pb.writeDouble(t.chargeSpeed)
@ -35,7 +35,7 @@ object PacketSender {
} }
def sendComputerState(t: Computer, player: Option[Player] = None) { def sendComputerState(t: Computer, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.ComputerStateResponse) val pb = new PacketBuilder(PacketType.ComputerState)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeBoolean(t.isRunning) pb.writeBoolean(t.isRunning)
@ -59,7 +59,7 @@ object PacketSender {
} }
def sendPowerState(t: PowerInformation, player: Option[Player] = None) { def sendPowerState(t: PowerInformation, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.PowerStateResponse) val pb = new PacketBuilder(PacketType.PowerState)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeDouble(t.globalBuffer) pb.writeDouble(t.globalBuffer)
@ -72,7 +72,7 @@ object PacketSender {
} }
def sendRedstoneState(t: Redstone, player: Option[Player] = None) { def sendRedstoneState(t: Redstone, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.RedstoneStateResponse) val pb = new PacketBuilder(PacketType.RedstoneState)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeBoolean(t.isOutputEnabled) pb.writeBoolean(t.isOutputEnabled)
@ -136,26 +136,8 @@ object PacketSender {
pb.sendToAllPlayers() 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) { def sendRotatableState(t: Rotatable, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.RotatableStateResponse) val pb = new PacketBuilder(PacketType.RotatableState)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeDirection(t.pitch) 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) { def sendScreenColorChange(t: Buffer, foreground: Int, background: Int) {
val pb = new PacketBuilder(PacketType.ScreenColorChange) val pb = new PacketBuilder(PacketType.ScreenColorChange)