clearing robot afterimages in a scheduled block update, which should be a bit more stable... should. minecraft. whatever; catching error in analyzer if node has no address; added setting to allow robots to ignore cobwebs, the most stupid invention ever (hardness of four without tools? seriously?), defaults to on; fixed threading issue with setBlockBoundsBasedOnState, hopefully resolving robot suicides

This commit is contained in:
Florian Nücke 2013-12-05 23:23:13 +01:00
parent 76f3e03925
commit 14f47fd637
7 changed files with 44 additions and 15 deletions

View File

@ -48,6 +48,7 @@ class Settings(config: Config) {
val allowActivateBlocks = config.getBoolean("robot.allowActivateBlocks") val allowActivateBlocks = config.getBoolean("robot.allowActivateBlocks")
val allowUseItemsWithDuration = config.getBoolean("robot.allowUseItemsWithDuration") val allowUseItemsWithDuration = config.getBoolean("robot.allowUseItemsWithDuration")
val canAttackPlayers = config.getBoolean("robot.canAttackPlayers") val canAttackPlayers = config.getBoolean("robot.canAttackPlayers")
val screwCobwebs = config.getBoolean("robot.notAfraidOfSpiders")
val swingRange = config.getDouble("robot.swingRange") val swingRange = config.getDouble("robot.swingRange")
val useAndPlaceRange = config.getDouble("robot.useAndPlaceRange") val useAndPlaceRange = config.getDouble("robot.useAndPlaceRange")
val itemDamageRate = config.getDouble("robot.itemDamageRate") max 0 min 1 val itemDamageRate = config.getDouble("robot.itemDamageRate") max 0 min 1

View File

@ -154,7 +154,13 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
override def setBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int) = override def setBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int) =
subBlock(world, x, y, z) match { subBlock(world, x, y, z) match {
case Some(subBlock) => subBlock.updateBounds(world, x, y, z) // This function can mess things up badly in single player if not
// synchronized because it sets fields in an instance stored in the
// static block list... which is used by both server and client thread.
// The other place where this is locked is in collisionRayTrace below,
// which seems to be the only built-in function that *logically* depends
// on the state bounds (rest is rendering which is unimportant).
case Some(subBlock) => subBlock.synchronized(subBlock.updateBounds(world, x, y, z))
case _ => case _ =>
} }
@ -166,7 +172,8 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) {
override def collisionRayTrace(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) = override def collisionRayTrace(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) =
subBlock(world, x, y, z) match { subBlock(world, x, y, z) match {
case Some(subBlock) => subBlock.intersect(world, x, y, z, origin, direction) // See setBlockBoundsBasedOnState for info on the lock.
case Some(subBlock) => subBlock.synchronized(subBlock.intersect(world, x, y, z, origin, direction))
case _ => super.collisionRayTrace(world, x, y, z, origin, direction) case _ => super.collisionRayTrace(world, x, y, z, origin, direction)
} }

View File

@ -50,6 +50,13 @@ class RobotAfterimage(val parent: SpecialDelegator) extends SpecialDelegate {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def update(world: World, x: Int, y: Int, z: Int) {
parent.subBlock(world, x, y, z) match {
case Some(_: RobotAfterimage) => world.setBlockToAir(x, y, z)
case _ =>
}
}
override def removedByEntity(world: World, x: Int, y: Int, z: Int, player: EntityPlayer) = { override def removedByEntity(world: World, x: Int, y: Int, z: Int, player: EntityPlayer) = {
super.removedFromWorld(world, x, y, z, blockId) super.removedFromWorld(world, x, y, z, blockId)
findMovingRobot(world, x, y, z) match { findMovingRobot(world, x, y, z) match {

View File

@ -52,7 +52,9 @@ class Analyzer(val parent: Delegator) extends Delegate {
case _ => case _ =>
} }
val address = node.address() val address = node.address()
stats.setString(Settings.namespace + "gui.Analyzer.Address", address) if (address != null && !address.isEmpty) {
stats.setString(Settings.namespace + "gui.Analyzer.Address", address)
}
PacketSender.sendAnalyze(stats, address, player.asInstanceOf[Player]) PacketSender.sendAnalyze(stats, address, player.asInstanceOf[Player])
} }

View File

@ -138,8 +138,10 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
Blocks.robotAfterimage.setBlock(world, ox, oy, oz, 1) Blocks.robotAfterimage.setBlock(world, ox, oy, oz, 1)
assert(Delegator.subBlock(world, ox, oy, oz).exists(_ == Blocks.robotAfterimage)) assert(Delegator.subBlock(world, ox, oy, oz).exists(_ == Blocks.robotAfterimage))
// Here instead of Lua callback so that it gets called on client, too. // Here instead of Lua callback so that it gets called on client, too.
animateMove(ox, oy, oz, Settings.get.moveDelay) val moveTicks = (Settings.get.moveDelay * 20).toInt max 1
setAnimateMove(ox, oy, oz, moveTicks)
if (isServer) { if (isServer) {
world.scheduleBlockUpdate(ox, oy, oz, Blocks.robotAfterimage.parent.blockID, moveTicks - 1)
ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction) ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction)
checkRedstoneInputChanged() checkRedstoneInputChanged()
} }
@ -190,9 +192,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
def isAnimatingTurn = animationTicksLeft > 0 && turnAxis != 0 def isAnimatingTurn = animationTicksLeft > 0 && turnAxis != 0
def animateMove(fromX: Int, fromY: Int, fromZ: Int, duration: Double) =
setAnimateMove(fromX, fromY, fromZ, (duration * 20).toInt)
def animateSwing(duration: Double) = { def animateSwing(duration: Double) = {
setAnimateSwing((duration * 20).toInt) setAnimateSwing((duration * 20).toInt)
ServerPacketSender.sendRobotAnimateSwing(this) ServerPacketSender.sendRobotAnimateSwing(this)
@ -248,12 +247,11 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
if (animationTicksLeft > 0) { if (animationTicksLeft > 0) {
animationTicksLeft -= 1 animationTicksLeft -= 1
if (animationTicksLeft == 0) { if (animationTicksLeft == 0) {
if (Blocks.blockSpecial.subBlock(world, moveFromX, moveFromY, moveFromZ).exists(_ == Blocks.robotAfterimage)) { moveFromX = Int.MaxValue
world.setBlock(moveFromX, moveFromY, moveFromZ, 0, 0, 1) moveFromY = Int.MaxValue
} moveFromZ = Int.MaxValue
moveFromX = x swingingTool = false
moveFromY = y turnAxis = 0
moveFromZ = z
} }
} }
super.updateEntity() super.updateEntity()

View File

@ -222,7 +222,9 @@ class Player(val robot: Robot) extends EntityPlayer(robot.world, Settings.get.na
return 0 return 0
} }
if (!ForgeHooks.canHarvestBlock(block, this, metadata)) { val cobwebOverride = block == Block.web && Settings.get.screwCobwebs
if (!ForgeHooks.canHarvestBlock(block, this, metadata) && !cobwebOverride) {
return 0 return 0
} }
@ -235,7 +237,9 @@ class Player(val robot: Robot) extends EntityPlayer(robot.world, Settings.get.na
val hardness = block.getBlockHardness(world, x, y, z) val hardness = block.getBlockHardness(world, x, y, z)
val strength = getCurrentPlayerStrVsBlock(block, false, metadata) val strength = getCurrentPlayerStrVsBlock(block, false, metadata)
val breakTime = hardness * 1.5 / strength val breakTime =
if (cobwebOverride) Settings.get.swingDelay
else hardness * 1.5 / strength
if (stack != null) { if (stack != null) {
val oldDamage = stack.getItemDamage val oldDamage = stack.getItemDamage

View File

@ -149,6 +149,16 @@ opencomputers {
# in the game. # in the game.
canAttackPlayers: false canAttackPlayers: false
# Determines whether robots are a pretty cool guy. Ususally cobwebs are
# the bane of anything using a tool other than a sword or shears. This is
# an utter pain in the part you sit on, because it makes robots meant to
# dig holes utterly useless: the poor things couldn't break cobwebs in
# mining shafts with their golden pick axes. So, if this setting is true,
# we check for cobweb and allow robots to break 'em anyway, no matter
# their current tool. After all, the hardness value of cobweb can only
# rationally explained by Steve's fear of spiders, anyway.
notAfraidOfSpiders: true
# The 'range' of robots when swinging an equipped tool (left click). This # The 'range' of robots when swinging an equipped tool (left click). This
# is the distance to the center of block the robot swings the tool in to # is the distance to the center of block the robot swings the tool in to
# the side the tool is swung towards. I.e. for the collision check, which # the side the tool is swung towards. I.e. for the collision check, which