From 003463ec4aad662759a54818f1b17fe6a88cd826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Thu, 5 Feb 2015 20:02:14 +0100 Subject: [PATCH] Limiting robot flight height, by default to 8 blocks above ground for now. Movement rules are as follows now: 1. Robots may only move if the start or target position is valid (e.g. to allow building bridges). 2. The position below a robot is always valid (can always move down). 3. Positions up to above a block are valid (limited flight capabilities). 4. Any position that has an adjacent block with a solid face towards the position is valid (robots can "climb"). --- src/main/resources/application.conf | 13 +++++++ src/main/scala/li/cil/oc/Settings.scala | 1 + .../oc/common/event/RobotCommonHandler.scala | 35 +++++++++++++++++++ .../scala/li/cil/oc/util/BlockPosition.scala | 10 +++--- .../scala/li/cil/oc/util/ExtendedWorld.scala | 2 ++ 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 722d69bfd..209560f09 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -274,6 +274,19 @@ opencomputers { # in the game. canAttackPlayers: false + # Limit robot flight height, based on the following rules: + # - Robots may only move if the start or target position is valid (e.g. + # to allow building bridges). + # - The position below a robot is always valid (can always move down). + # - Positions up to above a block are valid (limited + # flight capabilities). + # - Any position that has an adjacent block with a solid face towards the + # position is valid (robots can "climb"). + # Set this to 256 to allow robots to fly whereever, as was the case + # before the 1.5 update. Consider using drones for cases where you need + # unlimited flight capabilities instead! + limitFlightHeight: 8 + # 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 diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 909816d1e..81565de64 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -95,6 +95,7 @@ class Settings(val config: Config) { val allowActivateBlocks = config.getBoolean("robot.allowActivateBlocks") val allowUseItemsWithDuration = config.getBoolean("robot.allowUseItemsWithDuration") val canAttackPlayers = config.getBoolean("robot.canAttackPlayers") + val limitFlightHeight = config.getInt("robot.limitFlightHeight") max 0 val screwCobwebs = config.getBoolean("robot.notAfraidOfSpiders") val swingRange = config.getDouble("robot.swingRange") val useAndPlaceRange = config.getDouble("robot.useAndPlaceRange") diff --git a/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala b/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala index 906796aa2..45a077fd2 100644 --- a/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala +++ b/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala @@ -1,7 +1,13 @@ package li.cil.oc.common.event import cpw.mods.fml.common.eventhandler.SubscribeEvent +import li.cil.oc.Settings +import li.cil.oc.api.event.RobotMoveEvent import li.cil.oc.api.event.RobotUsedToolEvent +import li.cil.oc.api.internal.Robot +import li.cil.oc.util.BlockPosition +import li.cil.oc.util.ExtendedWorld._ +import net.minecraftforge.common.util.ForgeDirection object RobotCommonHandler { @SubscribeEvent @@ -15,4 +21,33 @@ object RobotCommonHandler { } } } + + @SubscribeEvent + def onRobotMove(e: RobotMoveEvent.Pre): Unit = { + if (Settings.get.limitFlightHeight < 256) e.agent match { + case robot: Robot => + val world = robot.world + // TODO Allow increasing this via upgrades? + val maxFlyingHeight = Settings.get.limitFlightHeight + def isMovingDown = e.direction == ForgeDirection.DOWN + def hasAdjacentBlock(pos: BlockPosition) = ForgeDirection.VALID_DIRECTIONS.exists(side => world.isSideSolid(pos.offset(side), side.getOpposite)) + def isWithinFlyingHeight(pos: BlockPosition) = (1 to maxFlyingHeight).exists(n => !world.isAirBlock(pos.offset(e.direction.getOpposite, n))) + val startPos = BlockPosition(robot) + val targetPos = startPos.offset(e.direction) + // New movement rules as of 1.5: + // 1. Robots may only move if the start or target position is valid (e.g. to allow building bridges). + // 2. The position below a robot is always valid (can always move down). + // 3. Positions up to above a block are valid (limited flight capabilities). + // 4. Any position that has an adjacent block with a solid face towards the position is valid (robots can "climb"). + val validMove = isMovingDown || + hasAdjacentBlock(startPos) || + hasAdjacentBlock(targetPos) || + isWithinFlyingHeight(startPos) + + if (!validMove) { + e.setCanceled(true) + } + case _ => + } + } } diff --git a/src/main/scala/li/cil/oc/util/BlockPosition.scala b/src/main/scala/li/cil/oc/util/BlockPosition.scala index 212264096..7f2e8c286 100644 --- a/src/main/scala/li/cil/oc/util/BlockPosition.scala +++ b/src/main/scala/li/cil/oc/util/BlockPosition.scala @@ -19,13 +19,15 @@ class BlockPosition(val x: Int, val y: Int, val z: Int, val world: Option[World] world ) - def offset(direction: ForgeDirection) = new BlockPosition( - x + direction.offsetX, - y + direction.offsetY, - z + direction.offsetZ, + def offset(direction: ForgeDirection, n: Int) = new BlockPosition( + x + direction.offsetX * n, + y + direction.offsetY * n, + z + direction.offsetZ * n, world ) + def offset(direction: ForgeDirection): BlockPosition = offset(direction, 1) + def offset(x: Double, y: Double, z: Double) = Vec3.createVectorHelper(this.x + x, this.y + y, this.z + z) def bounds = AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 1, z + 1) diff --git a/src/main/scala/li/cil/oc/util/ExtendedWorld.scala b/src/main/scala/li/cil/oc/util/ExtendedWorld.scala index a3934f2c4..b58921f43 100644 --- a/src/main/scala/li/cil/oc/util/ExtendedWorld.scala +++ b/src/main/scala/li/cil/oc/util/ExtendedWorld.scala @@ -60,6 +60,8 @@ object ExtendedWorld { def setBlock(position: BlockPosition, block: Block, metadata: Int, flag: Int) = world.setBlock(position.x, position.y, position.z, block, metadata, flag) def setBlockToAir(position: BlockPosition) = world.setBlockToAir(position.x, position.y, position.z) + + def isSideSolid(position: BlockPosition, side: ForgeDirection) = world.isSideSolid(position.x, position.y, position.z, side) } }