add sync calls for tablet state on client

only adding fix for 1.12 thanks to player inventory change count

closes #2696
This commit is contained in:
payonel 2018-11-14 18:04:06 -08:00
parent 71f54dd631
commit acf244034e
6 changed files with 103 additions and 11 deletions

View File

@ -12,6 +12,7 @@ import li.cil.oc.client.renderer.PetRenderer
import li.cil.oc.common.Loot import li.cil.oc.common.Loot
import li.cil.oc.common.PacketType import li.cil.oc.common.PacketType
import li.cil.oc.common.container import li.cil.oc.common.container
import li.cil.oc.common.item.{Tablet, TabletWrapper}
import li.cil.oc.common.nanomachines.ControllerImpl import li.cil.oc.common.nanomachines.ControllerImpl
import li.cil.oc.common.tileentity._ import li.cil.oc.common.tileentity._
import li.cil.oc.common.tileentity.traits._ import li.cil.oc.common.tileentity.traits._
@ -58,6 +59,7 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.ClientLog => onClientLog(p) case PacketType.ClientLog => onClientLog(p)
case PacketType.Clipboard => onClipboard(p) case PacketType.Clipboard => onClipboard(p)
case PacketType.ColorChange => onColorChange(p) case PacketType.ColorChange => onColorChange(p)
case PacketType.MachineItemStateResponse => onMachineItemStateResponse(p)
case PacketType.ComputerState => onComputerState(p) case PacketType.ComputerState => onComputerState(p)
case PacketType.ComputerUserList => onComputerUserList(p) case PacketType.ComputerUserList => onComputerUserList(p)
case PacketType.ContainerUpdate => onContainerUpdate(p) case PacketType.ContainerUpdate => onContainerUpdate(p)
@ -152,6 +154,15 @@ object PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onMachineItemStateResponse(p: PacketParser) : Unit = {
val stack = p.readItemStack()
val running = p.readBoolean()
val wrapper = Tablet.Client.get(stack, p.player)
wrapper.data.isRunning = running
wrapper.isDirty = false
}
def onComputerState(p: PacketParser): Unit = def onComputerState(p: PacketParser): Unit =
p.readTileEntity[Computer]() match { p.readTileEntity[Computer]() match {
case Some(t) => case Some(t) =>

View File

@ -9,10 +9,14 @@ import li.cil.oc.common.tileentity._
import li.cil.oc.common.tileentity.traits.Computer import li.cil.oc.common.tileentity.traits.Computer
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.audio.PositionedSoundRecord import net.minecraft.client.audio.PositionedSoundRecord
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.SoundEvents import net.minecraft.init.SoundEvents
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumFacing import net.minecraft.util.EnumFacing
import net.minecraft.util.SoundCategory import net.minecraft.util.SoundCategory
import scala.tools.nsc.doc.model.Entity
object PacketSender { object PacketSender {
// Timestamp after which the next clipboard message may be sent. Used to // Timestamp after which the next clipboard message may be sent. Used to
// avoid spamming large packets on key repeat. // avoid spamming large packets on key repeat.
@ -91,6 +95,14 @@ object PacketSender {
} }
} }
def sendMachineItemStateRequest(stack: ItemStack): Unit = {
val pb = new SimplePacketBuilder(PacketType.MachineItemStateRequest)
pb.writeItemStack(stack)
pb.sendToServer()
}
def sendMouseClick(address: String, x: Double, y: Double, drag: Boolean, button: Int) { def sendMouseClick(address: String, x: Double, y: Double, drag: Boolean, button: Int) {
val pb = new SimplePacketBuilder(PacketType.MouseClickOrDrag) val pb = new SimplePacketBuilder(PacketType.MouseClickOrDrag)

View File

@ -79,6 +79,8 @@ object PacketType extends Enumeration {
KeyDown, KeyDown,
KeyUp, KeyUp,
Clipboard, Clipboard,
MachineItemStateRequest,
MachineItemStateResponse,
MouseClickOrDrag, MouseClickOrDrag,
MouseScroll, MouseScroll,
MouseUp, MouseUp,

View File

@ -21,6 +21,7 @@ import li.cil.oc.api.machine.MachineHost
import li.cil.oc.api.network.Connector import li.cil.oc.api.network.Connector
import li.cil.oc.api.network.Message import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node import li.cil.oc.api.network.Node
import li.cil.oc.{client, server}
import li.cil.oc.client.KeyBindings import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType import li.cil.oc.common.GuiType
import li.cil.oc.common.Slot import li.cil.oc.common.Slot
@ -28,7 +29,7 @@ import li.cil.oc.common.Tier
import li.cil.oc.common.inventory.ComponentInventory import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.item.data.TabletData import li.cil.oc.common.item.data.TabletData
import li.cil.oc.integration.opencomputers.DriverScreen import li.cil.oc.integration.opencomputers.DriverScreen
import li.cil.oc.server.component import li.cil.oc.server.{PacketSender, component}
import li.cil.oc.util.Audio import li.cil.oc.util.Audio
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
@ -40,7 +41,7 @@ import net.minecraft.client.renderer.block.model.ModelBakery
import net.minecraft.client.renderer.block.model.ModelResourceLocation import net.minecraft.client.renderer.block.model.ModelResourceLocation
import net.minecraft.entity.Entity import net.minecraft.entity.Entity
import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
import net.minecraft.item.EnumRarity import net.minecraft.item.EnumRarity
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
@ -91,8 +92,10 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
override def durability(stack: ItemStack): Double = { override def durability(stack: ItemStack): Double = {
if (stack.hasTagCompound) { if (stack.hasTagCompound) {
val data = new TabletData() val data = Tablet.Client.getWeak(stack) match {
data.load(stack.getTagCompound) case Some(wrapper) => wrapper.data
case _ => new TabletData(stack)
}
1 - data.energy / data.maxEnergy 1 - data.energy / data.maxEnergy
} }
else 1.0 else 1.0
@ -111,10 +114,10 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
override def getModelLocation(stack: ItemStack): ModelResourceLocation = { override def getModelLocation(stack: ItemStack): ModelResourceLocation = {
if (stack.hasTagCompound) modelLocationFromState(Tablet.Client.getWeak(stack) match {
modelLocationFromState(Some(new TabletData(stack).isRunning)) case Some(tablet: TabletWrapper) => Some(tablet.data.isRunning)
else case _ => None
modelLocationFromState(None) })
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@ -242,12 +245,20 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
val tablet: component.Tablet = if (world.isRemote) null else new component.Tablet(this) val tablet: component.Tablet = if (world.isRemote) null else new component.Tablet(this)
var autoSave = true //// Client side only
private var isInitialized = !world.isRemote private var isInitialized = !world.isRemote
var timesChanged: Int = 0
var isDirty: Boolean = true
////
// Server side only
private var lastRunning = false private var lastRunning = false
var autoSave = true
////
def isCreative: Boolean = data.tier == Tier.Four def isCreative: Boolean = data.tier == Tier.Four
def items: Array[ItemStack] = data.items def items: Array[ItemStack] = data.items
@ -414,6 +425,8 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
buffer.setMaximumColorDepth(api.internal.TextBuffer.ColorDepth.FourBit) buffer.setMaximumColorDepth(api.internal.TextBuffer.ColorDepth.FourBit)
buffer.setMaximumResolution(80, 25) buffer.setMaximumResolution(80, 25)
} }
client.PacketSender.sendMachineItemStateRequest(stack)
} }
if (!world.isRemote) { if (!world.isRemote) {
if (isCreative && world.getTotalWorldTime % Settings.get.tickFrequency == 0) { if (isCreative && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
@ -429,6 +442,11 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
lastRunning = machine.isRunning lastRunning = machine.isRunning
markDirty() markDirty()
player match {
case mp: EntityPlayerMP => server.PacketSender.sendMachineItemState(mp, stack, machine.isRunning)
case _ =>
}
if (machine.isRunning) { if (machine.isRunning) {
components collect { components collect {
case Some(buffer: api.internal.TextBuffer) => case Some(buffer: api.internal.TextBuffer) =>
@ -520,6 +538,23 @@ object Tablet {
cache.synchronized { cache.synchronized {
currentStack = stack currentStack = stack
currentHolder = holder currentHolder = holder
// if the item is still cached, we can detect if it is dirty (client side only)
if (holder.world.isRemote) {
Client.getWeak(stack) match {
case Some(weak) =>
val timesChanged = holder.inventory.getTimesChanged
if (timesChanged != weak.timesChanged) {
if (!weak.isDirty) {
weak.isDirty = true
client.PacketSender.sendMachineItemStateRequest(stack)
}
weak.timesChanged = timesChanged
}
case _ =>
}
}
var wrapper = cache.get(id, this) var wrapper = cache.get(id, this)
// Force re-load on world change, in case some components store a // Force re-load on world change, in case some components store a
@ -532,6 +567,9 @@ object Tablet {
wrapper = cache.get(id, this) wrapper = cache.get(id, this)
} }
currentStack = null
currentHolder = null
wrapper.stack = stack wrapper.stack = stack
wrapper.player = holder wrapper.player = holder
wrapper wrapper
@ -552,6 +590,7 @@ object Tablet {
node.remove() node.remove()
} }
if (tablet.autoSave) tablet.writeToNBT() if (tablet.autoSave) tablet.writeToNBT()
tablet.markDirty()
} }
} }
@ -576,6 +615,15 @@ object Tablet {
object Client extends Cache { object Client extends Cache {
override protected def timeout = 5 override protected def timeout = 5
def getWeak(stack: ItemStack): Option[TabletWrapper] = {
val key = getId(stack)
val map = cache.asMap
if (map.containsKey(key))
Some(map.entrySet.find(entry => entry.getKey == key).get.getValue)
else
None
}
def get(stack: ItemStack): Option[TabletWrapper] = { def get(stack: ItemStack): Option[TabletWrapper] = {
if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "tablet")) { if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "tablet")) {
val id = stack.getTagCompound.getString(Settings.namespace + "tablet") val id = stack.getTagCompound.getString(Settings.namespace + "tablet")

View File

@ -4,11 +4,12 @@ import li.cil.oc.Localization
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.internal.Server import li.cil.oc.api.internal.Server
import li.cil.oc.api.machine.Machine import li.cil.oc.api.machine.Machine
import li.cil.oc.api.network.Connector
import li.cil.oc.common.Achievement import li.cil.oc.common.Achievement
import li.cil.oc.common.PacketType import li.cil.oc.common.PacketType
import li.cil.oc.common.component.TextBuffer import li.cil.oc.common.component.TextBuffer
import li.cil.oc.common.entity.Drone import li.cil.oc.common.entity.Drone
import li.cil.oc.common.item.Delegator import li.cil.oc.common.item.{Delegator, Tablet, TabletWrapper}
import li.cil.oc.common.item.data.DriveData import li.cil.oc.common.item.data.DriveData
import li.cil.oc.common.item.traits.FileSystemLike import li.cil.oc.common.item.traits.FileSystemLike
import li.cil.oc.common.tileentity._ import li.cil.oc.common.tileentity._
@ -41,6 +42,7 @@ object PacketHandler extends CommonPacketHandler {
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 PacketType.MachineItemStateRequest => onMachineItemStateRequest(p)
case PacketType.MouseClickOrDrag => onMouseClick(p) case PacketType.MouseClickOrDrag => onMouseClick(p)
case PacketType.MouseScroll => onMouseScroll(p) case PacketType.MouseScroll => onMouseScroll(p)
case PacketType.MouseUp => onMouseUp(p) case PacketType.MouseUp => onMouseUp(p)
@ -265,6 +267,14 @@ object PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet. case _ => // Invalid packet.
} }
def onMachineItemStateRequest(p: PacketParser): Unit = p.player match {
case player: EntityPlayerMP => {
val stack = p.readItemStack()
PacketSender.sendMachineItemState(player, stack, Tablet.get(stack, p.player).machine.isRunning)
}
case _ => // ignore
}
def onTextBufferInit(p: PacketParser) { def onTextBufferInit(p: PacketParser) {
val address = p.readUTF() val address = p.readUTF()
p.player match { p.player match {

View File

@ -90,6 +90,15 @@ object PacketSender {
pb.sendToPlayersNearTileEntity(t) pb.sendToPlayersNearTileEntity(t)
} }
def sendMachineItemState(player: EntityPlayerMP, stack: ItemStack, isRunning: Boolean): Unit = {
val pb = new SimplePacketBuilder(PacketType.MachineItemStateResponse)
pb.writeItemStack(stack)
pb.writeBoolean(isRunning)
pb.sendToPlayer(player)
}
def sendComputerUserList(t: Computer, list: Array[String]) { def sendComputerUserList(t: Computer, list: Array[String]) {
val pb = new SimplePacketBuilder(PacketType.ComputerUserList) val pb = new SimplePacketBuilder(PacketType.ComputerUserList)