diff --git a/Server/src/main/core/game/node/entity/combat/CombatMovementIntents.kt b/Server/src/main/core/game/node/entity/combat/CombatMovementIntents.kt index dab817cc2..82ab74e25 100644 --- a/Server/src/main/core/game/node/entity/combat/CombatMovementIntents.kt +++ b/Server/src/main/core/game/node/entity/combat/CombatMovementIntents.kt @@ -14,6 +14,7 @@ import core.game.world.map.Point import core.game.world.map.RegionManager import core.game.world.map.path.Path import core.game.world.map.path.Pathfinder +import core.game.world.map.path.SmartPathfinder import core.game.world.repository.Repository import java.util.LinkedHashMap @@ -405,6 +406,11 @@ object CombatMovementIntents { if (attacker.location == destination.location) { return null } + if (destination.pathfinder === Pathfinder.SMART && + !SmartPathfinder.canAttempt(attacker.location, destination.location) + ) { + return null + } val path = Pathfinder.find(attacker, destination.node, destination.allowPartialPath, destination.pathfinder) if (!path.reaches(destination.location) && (!destination.allowPartialPath || path.points.isEmpty())) { diff --git a/Server/src/main/core/game/world/map/path/SmartPathfinder.kt b/Server/src/main/core/game/world/map/path/SmartPathfinder.kt index 2dcae4a9c..1087d318b 100644 --- a/Server/src/main/core/game/world/map/path/SmartPathfinder.kt +++ b/Server/src/main/core/game/world/map/path/SmartPathfinder.kt @@ -71,6 +71,13 @@ internal constructor() : Pathfinder() { */ private var foundPath = false + companion object { + fun canAttempt(start: Location, dest: Location): Boolean { + val distance = kotlin.math.floor(Vector.betweenLocs(start, dest).magnitude()) + return distance < ServerConstants.MAX_PATHFIND_DISTANCE * 2.0 + } + } + /** * Resets the pathfinder. */ @@ -101,16 +108,16 @@ internal constructor() : Pathfinder() { override fun find(start: Location?, moverSize: Int, dest: Location?, sizeX: Int, sizeY: Int, rotation: Int, type: Int, walkingFlag: Int, near: Boolean, clipMaskSupplier: ClipMaskSupplier?): Path { reset() - assert(start != null && dest != null) - var vec = Vector.betweenLocs(start!!, dest!!) + val startLoc = requireNotNull(start) + var end = requireNotNull(dest) + var vec = Vector.betweenLocs(startLoc, end) var mag = kotlin.math.floor(vec.magnitude()) - var end = dest!! if (mag > ServerConstants.MAX_PATHFIND_DISTANCE) { try { - if (mag < 50.0) { //truncate the path if it's realistically long + if (canAttempt(startLoc, end)) { //truncate the path if it's realistically long vec = vec.normalized() * (ServerConstants.MAX_PATHFIND_DISTANCE - 1) - end = start!!.transform(vec) - } else throw Exception("Pathfinding distance exceeds server max! -> " + mag.toString() + " {" + start + "->" + end + "}") + end = startLoc.transform(vec) + } else throw Exception("Pathfinding distance exceeds server max! -> " + mag.toString() + " {" + startLoc + "->" + end + "}") } catch (e: Exception) { val sw = StringWriter() val pw = PrintWriter(sw) @@ -129,12 +136,12 @@ internal constructor() : Pathfinder() { cost[x][y] = 99999999 } } - val z = start!!.z - val location = Location.create(start.regionX - 6 shl 3, start.regionY - 6 shl 3, z) - curX = start.sceneX - curY = start.sceneY - dstX = end!!.getSceneX(start) - dstY = end.getSceneY(start) + val z = startLoc.z + val location = Location.create(startLoc.regionX - 6 shl 3, startLoc.regionY - 6 shl 3, z) + curX = startLoc.sceneX + curY = startLoc.sceneY + dstX = end.getSceneX(startLoc) + dstY = end.getSceneY(startLoc) var attempts: Int var readPosition: Int check(curX, curY, 99, 0) diff --git a/Server/src/test/kotlin/core/PathfinderTests.kt b/Server/src/test/kotlin/core/PathfinderTests.kt index 84f6c640c..c30c69402 100644 --- a/Server/src/test/kotlin/core/PathfinderTests.kt +++ b/Server/src/test/kotlin/core/PathfinderTests.kt @@ -17,6 +17,7 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.world.GameWorld import core.game.world.map.Region +import core.game.world.map.path.SmartPathfinder import core.net.packet.PacketProcessor import core.plugin.ClassScanner import core.plugin.Plugin @@ -26,6 +27,13 @@ import org.rs09.consts.NPCs class PathfinderTests { companion object {init {TestUtils.preTestSetup(); GatheringSkillOptionListeners().defineListeners(); WoodcuttingListener().defineListeners() }; val NPC_TEST_LOC = ServerConstants.HOME_LOCATION!!.transform(2, 10, 0)} + @Test fun smartPathfinderShouldRejectDestinationsAtTheTruncationLimit() { + val start = Location.create(3165, 3218, 0) + + Assertions.assertTrue(SmartPathfinder.canAttempt(start, Location.create(3203, 3186, 0))) + Assertions.assertFalse(SmartPathfinder.canAttempt(start, Location.create(3203, 3185, 0))) + } + @Test fun getOccupiedTilesShouldReturnCorrectSetOfTilesThatAnObjectOccupiesAtAllRotations() { //clay fireplace - 13609 - sizex: 1, sizey: 2 val scenery = Scenery(13609, Location.create(50, 50, 0)) @@ -257,4 +265,4 @@ class PathfinderTests { Assertions.assertEquals(true, npc.location.getDistance(ServerConstants.HOME_LOCATION!!) <= 5) } } -} \ No newline at end of file +}