mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-14 17:56:34 -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.{PacketSender => ClientPacketSender}
|
||||
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.util
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
@ -32,6 +33,12 @@ import scala.concurrent.Future
|
||||
object EventHandler {
|
||||
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) {
|
||||
if (SideTracker.isServer) pending.synchronized {
|
||||
pending += (() => Network.joinOrCreateNetwork(tileEntity))
|
||||
@ -64,6 +71,8 @@ object EventHandler {
|
||||
case t: Throwable => OpenComputers.log.warn("Error in scheduled tick action.", t)
|
||||
}
|
||||
})
|
||||
|
||||
runningRobots.foreach(_.machine.update())
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
@ -106,7 +106,7 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
|
||||
|
||||
override def createNewTileEntity(world: World, metadata: Int) = {
|
||||
moving.get match {
|
||||
case Some(robot) => null // new tileentity.RobotProxy(robot)
|
||||
case Some(robot) => new tileentity.RobotProxy(robot)
|
||||
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.network._
|
||||
import li.cil.oc.client.gui
|
||||
import li.cil.oc.common.EventHandler
|
||||
import li.cil.oc.common.Slot
|
||||
import li.cil.oc.common.Tier
|
||||
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
|
||||
// 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.
|
||||
// world.setBlockToAir(newPosition)
|
||||
world.setBlockToAir(newPosition)
|
||||
// In some cases (though I couldn't quite figure out which one) setBlock
|
||||
// will return true, even though the block was not created / adjusted.
|
||||
val created = world.setBlockState(newPosition, blockRobotProxy.getDefaultState, 1)
|
||||
val newProxy = world.getTileEntity(newPosition)
|
||||
if (created && newProxy != null) {
|
||||
assert(newProxy.getPos == newPosition)
|
||||
proxy = newProxy.asInstanceOf[RobotProxy]
|
||||
setPos(newPosition)
|
||||
val created = world.setBlockState(newPosition, world.getBlockState(oldPosition), 1) &&
|
||||
world.getTileEntity(newPosition) == proxy
|
||||
if (created) {
|
||||
assert(getPos == newPosition)
|
||||
world.setBlockState(oldPosition, net.minecraft.init.Blocks.air.getDefaultState, 1)
|
||||
world.setBlockState(oldPosition, blockRobotAfterImage.getDefaultState, 1)
|
||||
assert(world.getBlockState(oldPosition).getBlock == blockRobotAfterImage)
|
||||
@ -383,6 +382,16 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
||||
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() {
|
||||
if (isServer) {
|
||||
// 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 _ =>
|
||||
}
|
||||
}
|
||||
else EventHandler.onRobotStopped(this)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -422,10 +432,12 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
||||
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
|
||||
animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft")
|
||||
if (animationTicksLeft > 0) {
|
||||
val moveFromX = nbt.getInteger(Settings.namespace + "moveFromX")
|
||||
val moveFromY = nbt.getInteger(Settings.namespace + "moveFromY")
|
||||
val moveFromZ = nbt.getInteger(Settings.namespace + "moveFromZ")
|
||||
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
||||
if (nbt.hasKey(Settings.namespace + "moveFromX")) {
|
||||
val moveFromX = nbt.getInteger(Settings.namespace + "moveFromX")
|
||||
val moveFromY = nbt.getInteger(Settings.namespace + "moveFromY")
|
||||
val moveFromZ = nbt.getInteger(Settings.namespace + "moveFromZ")
|
||||
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
||||
}
|
||||
swingingTool = nbt.getBoolean(Settings.namespace + "swingingTool")
|
||||
turnAxis = nbt.getByte(Settings.namespace + "turnAxis")
|
||||
}
|
||||
@ -445,9 +457,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||
nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal)
|
||||
nbt.setInteger(Settings.namespace + "animationTicksLeft", animationTicksLeft)
|
||||
nbt.setInteger(Settings.namespace + "moveFromX", moveFrom.get.getX)
|
||||
nbt.setInteger(Settings.namespace + "moveFromY", moveFrom.get.getY)
|
||||
nbt.setInteger(Settings.namespace + "moveFromZ", moveFrom.get.getZ)
|
||||
moveFrom match {
|
||||
case Some(blockPos) =>
|
||||
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.setByte(Settings.namespace + "turnAxis", turnAxis.toByte)
|
||||
}
|
||||
@ -465,10 +481,12 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
||||
animationTicksTotal = nbt.getInteger("animationTicksTotal")
|
||||
animationTicksLeft = nbt.getInteger("animationTicksLeft")
|
||||
if (animationTicksLeft > 0) {
|
||||
val moveFromX = nbt.getInteger("moveFromX")
|
||||
val moveFromY = nbt.getInteger("moveFromY")
|
||||
val moveFromZ = nbt.getInteger("moveFromZ")
|
||||
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
||||
if (nbt.hasKey("moveFromX")) {
|
||||
val moveFromX = nbt.getInteger("moveFromX")
|
||||
val moveFromY = nbt.getInteger("moveFromY")
|
||||
val moveFromZ = nbt.getInteger("moveFromZ")
|
||||
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
|
||||
}
|
||||
swingingTool = nbt.getBoolean("swingingTool")
|
||||
turnAxis = nbt.getByte("turnAxis")
|
||||
}
|
||||
@ -484,9 +502,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||
nbt.setInteger("animationTicksTotal", animationTicksTotal)
|
||||
nbt.setInteger("animationTicksLeft", animationTicksLeft)
|
||||
nbt.setInteger("moveFromX", moveFrom.get.getX)
|
||||
nbt.setInteger("moveFromY", moveFrom.get.getY)
|
||||
nbt.setInteger("moveFromZ", moveFrom.get.getZ)
|
||||
moveFrom match {
|
||||
case Some(blockPos) =>
|
||||
nbt.setInteger("moveFromX", blockPos.getX)
|
||||
nbt.setInteger("moveFromY", blockPos.getY)
|
||||
nbt.setInteger("moveFromZ", blockPos.getZ)
|
||||
case _ =>
|
||||
}
|
||||
nbt.setBoolean("swingingTool", swingingTool)
|
||||
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 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).
|
||||
machine.update()
|
||||
updateComputer()
|
||||
|
||||
if (_isRunning != machine.isRunning) {
|
||||
_isRunning = machine.isRunning
|
||||
@ -115,6 +115,10 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
|
||||
super.updateEntity()
|
||||
}
|
||||
|
||||
protected def updateComputer(): Unit = {
|
||||
machine.update()
|
||||
}
|
||||
|
||||
protected def onRunningChanged(): Unit = {
|
||||
markDirty()
|
||||
ServerPacketSender.sendComputerState(this)
|
||||
|
@ -4,6 +4,7 @@ import li.cil.oc.api.internal
|
||||
import li.cil.oc.common.block
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import net.minecraft.block.state.IBlockState
|
||||
import net.minecraft.entity.Entity
|
||||
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. */
|
||||
private var cachedTranslation: Array[EnumFacing] = null
|
||||
|
||||
@ -83,7 +90,7 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
|
||||
def pitch = getBlockType match {
|
||||
case rotatable: block.traits.OmniRotatable => rotatable.getPitch(world.getBlockState(getPos))
|
||||
case _ => EnumFacing.NORTH
|
||||
case _ => _pitch
|
||||
}
|
||||
|
||||
def pitch_=(value: EnumFacing): Unit =
|
||||
@ -95,7 +102,7 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
def yaw = getBlockType match {
|
||||
case rotatable: block.traits.OmniRotatable => rotatable.getYaw(world.getBlockState(getPos))
|
||||
case rotatable: block.traits.Rotatable => rotatable.getFacing(world.getBlockState(getPos))
|
||||
case _ => EnumFacing.SOUTH
|
||||
case _ => _yaw
|
||||
}
|
||||
|
||||
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. */
|
||||
private def trySetPitchYaw(pitch: EnumFacing, yaw: EnumFacing) = {
|
||||
val oldState = world.getBlockState(getPos)
|
||||
val newState = getBlockType match {
|
||||
case rotatable: block.traits.OmniRotatable => rotatable.withPitchAndYaw(oldState, pitch, yaw)
|
||||
case rotatable: block.traits.Rotatable => rotatable.withFacing(oldState, yaw)
|
||||
case _ => oldState
|
||||
def setState(newState: IBlockState): Boolean = {
|
||||
if (oldState.hashCode() != newState.hashCode()) {
|
||||
world.setBlockState(getPos, newState)
|
||||
cacheDirty = true
|
||||
true
|
||||
}
|
||||
else false
|
||||
}
|
||||
if (oldState.hashCode() != newState.hashCode()) {
|
||||
world.setBlockState(getPos, newState)
|
||||
cacheDirty = true
|
||||
true
|
||||
getBlockType match {
|
||||
case rotatable: block.traits.OmniRotatable =>
|
||||
setState(rotatable.withPitchAndYaw(oldState, pitch, yaw))
|
||||
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]) =
|
||||
|
Loading…
x
Reference in New Issue
Block a user