mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 10:21:45 -04:00
Hallelujah! Robot movement works again.
Updating robots from tick handler now, to ensure tile entities are set immediately. Also making rotatable trait for tile entities "hybrid" so it can use either metadata *or* its own data.
This commit is contained in:
parent
19f614a3eb
commit
e9d74f21a7
@ -8,6 +8,7 @@ import li.cil.oc.api.detail.ItemInfo
|
|||||||
import li.cil.oc.client.renderer.PetRenderer
|
import li.cil.oc.client.renderer.PetRenderer
|
||||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||||
import li.cil.oc.common.item.data.MicrocontrollerData
|
import li.cil.oc.common.item.data.MicrocontrollerData
|
||||||
|
import li.cil.oc.common.tileentity.Robot
|
||||||
import li.cil.oc.integration.Mods
|
import li.cil.oc.integration.Mods
|
||||||
import li.cil.oc.integration.util
|
import li.cil.oc.integration.util
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
@ -32,6 +33,12 @@ import scala.concurrent.Future
|
|||||||
object EventHandler {
|
object EventHandler {
|
||||||
private val pending = mutable.Buffer.empty[() => Unit]
|
private val pending = mutable.Buffer.empty[() => Unit]
|
||||||
|
|
||||||
|
private val runningRobots = mutable.Set.empty[Robot]
|
||||||
|
|
||||||
|
def onRobotStart(robot: Robot): Unit = runningRobots += robot
|
||||||
|
|
||||||
|
def onRobotStopped(robot: Robot): Unit = runningRobots -= robot
|
||||||
|
|
||||||
def schedule(tileEntity: TileEntity) {
|
def schedule(tileEntity: TileEntity) {
|
||||||
if (SideTracker.isServer) pending.synchronized {
|
if (SideTracker.isServer) pending.synchronized {
|
||||||
pending += (() => Network.joinOrCreateNetwork(tileEntity))
|
pending += (() => Network.joinOrCreateNetwork(tileEntity))
|
||||||
@ -64,6 +71,8 @@ object EventHandler {
|
|||||||
case t: Throwable => OpenComputers.log.warn("Error in scheduled tick action.", t)
|
case t: Throwable => OpenComputers.log.warn("Error in scheduled tick action.", t)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
runningRobots.foreach(_.machine.update())
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
@ -106,7 +106,7 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
|
|||||||
|
|
||||||
override def createNewTileEntity(world: World, metadata: Int) = {
|
override def createNewTileEntity(world: World, metadata: Int) = {
|
||||||
moving.get match {
|
moving.get match {
|
||||||
case Some(robot) => null // new tileentity.RobotProxy(robot)
|
case Some(robot) => new tileentity.RobotProxy(robot)
|
||||||
case _ => new tileentity.RobotProxy()
|
case _ => new tileentity.RobotProxy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import li.cil.oc.api.event.RobotMoveEvent
|
|||||||
import li.cil.oc.api.internal
|
import li.cil.oc.api.internal
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.client.gui
|
import li.cil.oc.client.gui
|
||||||
|
import li.cil.oc.common.EventHandler
|
||||||
import li.cil.oc.common.Slot
|
import li.cil.oc.common.Slot
|
||||||
import li.cil.oc.common.Tier
|
import li.cil.oc.common.Tier
|
||||||
import li.cil.oc.common.inventory.InventorySelection
|
import li.cil.oc.common.inventory.InventorySelection
|
||||||
@ -243,15 +244,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
// worked before the client is notified so that we can use the same trick on
|
// worked before the client is notified so that we can use the same trick on
|
||||||
// the client by sending a corresponding packet. This also saves us from
|
// the client by sending a corresponding packet. This also saves us from
|
||||||
// having to send the complete state again (e.g. screen buffer) each move.
|
// having to send the complete state again (e.g. screen buffer) each move.
|
||||||
// world.setBlockToAir(newPosition)
|
world.setBlockToAir(newPosition)
|
||||||
// In some cases (though I couldn't quite figure out which one) setBlock
|
// In some cases (though I couldn't quite figure out which one) setBlock
|
||||||
// will return true, even though the block was not created / adjusted.
|
// will return true, even though the block was not created / adjusted.
|
||||||
val created = world.setBlockState(newPosition, blockRobotProxy.getDefaultState, 1)
|
val created = world.setBlockState(newPosition, world.getBlockState(oldPosition), 1) &&
|
||||||
val newProxy = world.getTileEntity(newPosition)
|
world.getTileEntity(newPosition) == proxy
|
||||||
if (created && newProxy != null) {
|
if (created) {
|
||||||
assert(newProxy.getPos == newPosition)
|
assert(getPos == newPosition)
|
||||||
proxy = newProxy.asInstanceOf[RobotProxy]
|
|
||||||
setPos(newPosition)
|
|
||||||
world.setBlockState(oldPosition, net.minecraft.init.Blocks.air.getDefaultState, 1)
|
world.setBlockState(oldPosition, net.minecraft.init.Blocks.air.getDefaultState, 1)
|
||||||
world.setBlockState(oldPosition, blockRobotAfterImage.getDefaultState, 1)
|
world.setBlockState(oldPosition, blockRobotAfterImage.getDefaultState, 1)
|
||||||
assert(world.getBlockState(oldPosition).getBlock == blockRobotAfterImage)
|
assert(world.getBlockState(oldPosition).getBlock == blockRobotAfterImage)
|
||||||
@ -383,6 +382,16 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
inventory.decrementAnimations()
|
inventory.decrementAnimations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The robot's machine is updated in a tick handler, to avoid delayed tile
|
||||||
|
// entity creation when moving, which would screw over all the things...
|
||||||
|
override protected def updateComputer(): Unit = {}
|
||||||
|
|
||||||
|
override protected def onRunningChanged(): Unit = {
|
||||||
|
super.onRunningChanged()
|
||||||
|
if (isRunning) EventHandler.onRobotStart(this)
|
||||||
|
else EventHandler.onRobotStopped(this)
|
||||||
|
}
|
||||||
|
|
||||||
override protected def initialize() {
|
override protected def initialize() {
|
||||||
if (isServer) {
|
if (isServer) {
|
||||||
// Ensure we have a node address, because the proxy needs this to initialize
|
// Ensure we have a node address, because the proxy needs this to initialize
|
||||||
@ -400,6 +409,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else EventHandler.onRobotStopped(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
@ -422,10 +432,12 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
|
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
|
||||||
animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft")
|
animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft")
|
||||||
if (animationTicksLeft > 0) {
|
if (animationTicksLeft > 0) {
|
||||||
val moveFromX = nbt.getInteger(Settings.namespace + "moveFromX")
|
if (nbt.hasKey(Settings.namespace + "moveFromX")) {
|
||||||
val moveFromY = nbt.getInteger(Settings.namespace + "moveFromY")
|
val moveFromX = nbt.getInteger(Settings.namespace + "moveFromX")
|
||||||
val moveFromZ = nbt.getInteger(Settings.namespace + "moveFromZ")
|
val moveFromY = nbt.getInteger(Settings.namespace + "moveFromY")
|
||||||
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
val moveFromZ = nbt.getInteger(Settings.namespace + "moveFromZ")
|
||||||
|
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
||||||
|
}
|
||||||
swingingTool = nbt.getBoolean(Settings.namespace + "swingingTool")
|
swingingTool = nbt.getBoolean(Settings.namespace + "swingingTool")
|
||||||
turnAxis = nbt.getByte(Settings.namespace + "turnAxis")
|
turnAxis = nbt.getByte(Settings.namespace + "turnAxis")
|
||||||
}
|
}
|
||||||
@ -445,9 +457,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||||
nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal)
|
nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal)
|
||||||
nbt.setInteger(Settings.namespace + "animationTicksLeft", animationTicksLeft)
|
nbt.setInteger(Settings.namespace + "animationTicksLeft", animationTicksLeft)
|
||||||
nbt.setInteger(Settings.namespace + "moveFromX", moveFrom.get.getX)
|
moveFrom match {
|
||||||
nbt.setInteger(Settings.namespace + "moveFromY", moveFrom.get.getY)
|
case Some(blockPos) =>
|
||||||
nbt.setInteger(Settings.namespace + "moveFromZ", moveFrom.get.getZ)
|
nbt.setInteger(Settings.namespace + "moveFromX", blockPos.getX)
|
||||||
|
nbt.setInteger(Settings.namespace + "moveFromY", blockPos.getY)
|
||||||
|
nbt.setInteger(Settings.namespace + "moveFromZ", blockPos.getZ)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
nbt.setBoolean(Settings.namespace + "swingingTool", swingingTool)
|
nbt.setBoolean(Settings.namespace + "swingingTool", swingingTool)
|
||||||
nbt.setByte(Settings.namespace + "turnAxis", turnAxis.toByte)
|
nbt.setByte(Settings.namespace + "turnAxis", turnAxis.toByte)
|
||||||
}
|
}
|
||||||
@ -465,10 +481,12 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
animationTicksTotal = nbt.getInteger("animationTicksTotal")
|
animationTicksTotal = nbt.getInteger("animationTicksTotal")
|
||||||
animationTicksLeft = nbt.getInteger("animationTicksLeft")
|
animationTicksLeft = nbt.getInteger("animationTicksLeft")
|
||||||
if (animationTicksLeft > 0) {
|
if (animationTicksLeft > 0) {
|
||||||
val moveFromX = nbt.getInteger("moveFromX")
|
if (nbt.hasKey("moveFromX")) {
|
||||||
val moveFromY = nbt.getInteger("moveFromY")
|
val moveFromX = nbt.getInteger("moveFromX")
|
||||||
val moveFromZ = nbt.getInteger("moveFromZ")
|
val moveFromY = nbt.getInteger("moveFromY")
|
||||||
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
val moveFromZ = nbt.getInteger("moveFromZ")
|
||||||
|
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
||||||
|
}
|
||||||
swingingTool = nbt.getBoolean("swingingTool")
|
swingingTool = nbt.getBoolean("swingingTool")
|
||||||
turnAxis = nbt.getByte("turnAxis")
|
turnAxis = nbt.getByte("turnAxis")
|
||||||
}
|
}
|
||||||
@ -484,9 +502,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
|||||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||||
nbt.setInteger("animationTicksTotal", animationTicksTotal)
|
nbt.setInteger("animationTicksTotal", animationTicksTotal)
|
||||||
nbt.setInteger("animationTicksLeft", animationTicksLeft)
|
nbt.setInteger("animationTicksLeft", animationTicksLeft)
|
||||||
nbt.setInteger("moveFromX", moveFrom.get.getX)
|
moveFrom match {
|
||||||
nbt.setInteger("moveFromY", moveFrom.get.getY)
|
case Some(blockPos) =>
|
||||||
nbt.setInteger("moveFromZ", moveFrom.get.getZ)
|
nbt.setInteger("moveFromX", blockPos.getX)
|
||||||
|
nbt.setInteger("moveFromY", blockPos.getY)
|
||||||
|
nbt.setInteger("moveFromZ", blockPos.getZ)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
nbt.setBoolean("swingingTool", swingingTool)
|
nbt.setBoolean("swingingTool", swingingTool)
|
||||||
nbt.setByte("turnAxis", turnAxis.toByte)
|
nbt.setByte("turnAxis", turnAxis.toByte)
|
||||||
}
|
}
|
||||||
|
@ -95,14 +95,14 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def updateEntity() {
|
override def updateEntity(): Unit = {
|
||||||
|
// If we're not yet in a network we might have just been loaded from disk,
|
||||||
|
// meaning there may be other tile entities that also have not re-joined
|
||||||
|
// the network. We skip the update this round to allow other tile entities
|
||||||
|
// to join the network, too, avoiding issues of missing nodes (e.g. in the
|
||||||
|
// GPU which would otherwise loose track of its screen).
|
||||||
if (isServer && isConnected) {
|
if (isServer && isConnected) {
|
||||||
// If we're not yet in a network we might have just been loaded from disk,
|
updateComputer()
|
||||||
// meaning there may be other tile entities that also have not re-joined
|
|
||||||
// the network. We skip the update this round to allow other tile entities
|
|
||||||
// to join the network, too, avoiding issues of missing nodes (e.g. in the
|
|
||||||
// GPU which would otherwise loose track of its screen).
|
|
||||||
machine.update()
|
|
||||||
|
|
||||||
if (_isRunning != machine.isRunning) {
|
if (_isRunning != machine.isRunning) {
|
||||||
_isRunning = machine.isRunning
|
_isRunning = machine.isRunning
|
||||||
@ -115,6 +115,10 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
|
|||||||
super.updateEntity()
|
super.updateEntity()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected def updateComputer(): Unit = {
|
||||||
|
machine.update()
|
||||||
|
}
|
||||||
|
|
||||||
protected def onRunningChanged(): Unit = {
|
protected def onRunningChanged(): Unit = {
|
||||||
markDirty()
|
markDirty()
|
||||||
ServerPacketSender.sendComputerState(this)
|
ServerPacketSender.sendComputerState(this)
|
||||||
|
@ -4,6 +4,7 @@ import li.cil.oc.api.internal
|
|||||||
import li.cil.oc.common.block
|
import li.cil.oc.common.block
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
import li.cil.oc.util.ExtendedWorld._
|
import li.cil.oc.util.ExtendedWorld._
|
||||||
|
import net.minecraft.block.state.IBlockState
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.util.EnumFacing
|
import net.minecraft.util.EnumFacing
|
||||||
|
|
||||||
@ -66,9 +67,15 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
// State
|
// State - stored either in metadata or locally
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
/** One of Up, Down and North (where north means forward/no pitch). */
|
||||||
|
private var _pitch = EnumFacing.NORTH
|
||||||
|
|
||||||
|
/** One of the four cardinal directions. */
|
||||||
|
private var _yaw = EnumFacing.SOUTH
|
||||||
|
|
||||||
/** Translation for facings based on current pitch and yaw. */
|
/** Translation for facings based on current pitch and yaw. */
|
||||||
private var cachedTranslation: Array[EnumFacing] = null
|
private var cachedTranslation: Array[EnumFacing] = null
|
||||||
|
|
||||||
@ -83,7 +90,7 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
|||||||
|
|
||||||
def pitch = getBlockType match {
|
def pitch = getBlockType match {
|
||||||
case rotatable: block.traits.OmniRotatable => rotatable.getPitch(world.getBlockState(getPos))
|
case rotatable: block.traits.OmniRotatable => rotatable.getPitch(world.getBlockState(getPos))
|
||||||
case _ => EnumFacing.NORTH
|
case _ => _pitch
|
||||||
}
|
}
|
||||||
|
|
||||||
def pitch_=(value: EnumFacing): Unit =
|
def pitch_=(value: EnumFacing): Unit =
|
||||||
@ -95,7 +102,7 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
|||||||
def yaw = getBlockType match {
|
def yaw = getBlockType match {
|
||||||
case rotatable: block.traits.OmniRotatable => rotatable.getYaw(world.getBlockState(getPos))
|
case rotatable: block.traits.OmniRotatable => rotatable.getYaw(world.getBlockState(getPos))
|
||||||
case rotatable: block.traits.Rotatable => rotatable.getFacing(world.getBlockState(getPos))
|
case rotatable: block.traits.Rotatable => rotatable.getFacing(world.getBlockState(getPos))
|
||||||
case _ => EnumFacing.SOUTH
|
case _ => _yaw
|
||||||
}
|
}
|
||||||
|
|
||||||
def yaw_=(value: EnumFacing): Unit =
|
def yaw_=(value: EnumFacing): Unit =
|
||||||
@ -196,17 +203,35 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
|||||||
/** Validates new values against the allowed rotations as set in our block. */
|
/** Validates new values against the allowed rotations as set in our block. */
|
||||||
private def trySetPitchYaw(pitch: EnumFacing, yaw: EnumFacing) = {
|
private def trySetPitchYaw(pitch: EnumFacing, yaw: EnumFacing) = {
|
||||||
val oldState = world.getBlockState(getPos)
|
val oldState = world.getBlockState(getPos)
|
||||||
val newState = getBlockType match {
|
def setState(newState: IBlockState): Boolean = {
|
||||||
case rotatable: block.traits.OmniRotatable => rotatable.withPitchAndYaw(oldState, pitch, yaw)
|
if (oldState.hashCode() != newState.hashCode()) {
|
||||||
case rotatable: block.traits.Rotatable => rotatable.withFacing(oldState, yaw)
|
world.setBlockState(getPos, newState)
|
||||||
case _ => oldState
|
cacheDirty = true
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else false
|
||||||
}
|
}
|
||||||
if (oldState.hashCode() != newState.hashCode()) {
|
getBlockType match {
|
||||||
world.setBlockState(getPos, newState)
|
case rotatable: block.traits.OmniRotatable =>
|
||||||
cacheDirty = true
|
setState(rotatable.withPitchAndYaw(oldState, pitch, yaw))
|
||||||
true
|
case rotatable: block.traits.Rotatable =>
|
||||||
|
setState(rotatable.withFacing(oldState, yaw))
|
||||||
|
case _ =>
|
||||||
|
var changed = false
|
||||||
|
if (pitch != _pitch) {
|
||||||
|
changed = true
|
||||||
|
_pitch = pitch
|
||||||
|
}
|
||||||
|
if (yaw != _yaw) {
|
||||||
|
changed = true
|
||||||
|
_yaw = yaw
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
cacheDirty = true
|
||||||
|
updateTranslation()
|
||||||
|
}
|
||||||
|
changed
|
||||||
}
|
}
|
||||||
else false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def invert(t: Array[EnumFacing]) =
|
private def invert(t: Array[EnumFacing]) =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user