From 5c28375c3bf8057f401fd9479deb1f0623856c37 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Sat, 11 Jun 2022 12:35:16 +0000 Subject: [PATCH] Pathfinder now correctly paths to the closest accessible tile of an object, not the closest tile numerically. This should fix instances where you end up running around an object before interacting with it. --- .../core/game/interaction/MovementPulse.java | 26 +++++---- .../java/core/game/node/scenery/Scenery.java | 44 ++++++++++++++- .../game/interaction/InteractionListeners.kt | 2 +- .../kotlin/rs09/worker/ManagementEvents.kt | 7 +++ .../src/test/kotlin/core/PathfinderTests.kt | 53 +++++++++++++++++++ 5 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 Server/src/test/kotlin/core/PathfinderTests.kt diff --git a/Server/src/main/java/core/game/interaction/MovementPulse.java b/Server/src/main/java/core/game/interaction/MovementPulse.java index fe10c2f98..a48b8009b 100644 --- a/Server/src/main/java/core/game/interaction/MovementPulse.java +++ b/Server/src/main/java/core/game/interaction/MovementPulse.java @@ -5,6 +5,7 @@ import core.game.node.entity.Entity; import core.game.node.entity.impl.WalkingQueue; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import core.game.node.scenery.Scenery; import core.game.system.task.Pulse; import core.game.world.map.Direction; import core.game.world.map.Location; @@ -241,26 +242,33 @@ public abstract class MovementPulse extends Pulse { if (last != null && last.equals(destination.getLocation()) && !inside) { return; } + Location loc = null; + if (destinationFlag != null && overrideMethod == null) { loc = destinationFlag.getDestination(mover, destination); } - if(overrideMethod != null){ + else if(overrideMethod != null){ loc = overrideMethod.invoke(mover,destination); if(loc == destination.getLocation()) loc = destinationFlag.getDestination(mover,destination); } - if (loc == null && optionHandler != null) { - loc = optionHandler.getDestination(mover, destination); - } - if (loc == null && useHandler != null) { - loc = useHandler.getDestination((Player) mover, destination); - } - if (loc == null && inside) { - loc = findBorderLocation(); + + if (loc == null) { + if (optionHandler != null) { + loc = optionHandler.getDestination(mover, destination); + } + else if (useHandler != null) { + loc = useHandler.getDestination((Player) mover, destination); + } + else if (inside) { + loc = findBorderLocation(); + } } + if (destination == null) { return; } + Location ml = mover.getLocation(); Location dl = destination.getLocation(); // Lead the target if they're walking/running, unless they're already within interaction range diff --git a/Server/src/main/java/core/game/node/scenery/Scenery.java b/Server/src/main/java/core/game/node/scenery/Scenery.java index 4493620ff..c8c55b04b 100644 --- a/Server/src/main/java/core/game/node/scenery/Scenery.java +++ b/Server/src/main/java/core/game/node/scenery/Scenery.java @@ -10,6 +10,11 @@ import core.game.node.entity.player.Player; import core.game.system.task.Pulse; import core.game.world.map.Direction; import core.game.world.map.Location; +import org.jetbrains.annotations.NotNull; +import rs09.game.system.SystemLogger; + +import java.util.ArrayList; +import java.util.List; /** * Represents a scenery. @@ -30,7 +35,7 @@ public class Scenery extends Node { /** * The rotation. */ - private final int rotation; + private int rotation; /** * The object's definition. @@ -309,6 +314,10 @@ public class Scenery extends Node { return rotation; } + public void setRotation(int rot) { + rotation = rot; + } + /** * @return the location */ @@ -426,4 +435,37 @@ public class Scenery extends Node { this.wrapper = wrapper; } + @SuppressWarnings("SuspiciousNameCombination") + @NotNull + public List getOccupiedTiles() { + List occupied = new ArrayList<>(); + occupied.add(location); + + int sizeX = getSizeX(); + int sizeY = getSizeY(); + + if (rotation % 2 == 1) { + int tmp = sizeX; + sizeX = sizeY; + sizeY = tmp; + } + + boolean sub = rotation >= 2; + + if (sizeX > 1) { + for (int i = 1; i < sizeX; i++) { + int modifier = sub ? -i : i; + occupied.add(location.transform(modifier, 0, 0)); + } + } + + if (sizeY > 1) { + for (int i = 1; i < sizeY; i++) { + int modifier = sub ? -i : i; + occupied.add(location.transform(0, modifier, 0)); + } + } + + return occupied; + } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/InteractionListeners.kt b/Server/src/main/kotlin/rs09/game/interaction/InteractionListeners.kt index d37dffff3..7c17868b8 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/InteractionListeners.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/InteractionListeners.kt @@ -207,7 +207,7 @@ object InteractionListeners { val flag = when(type){ 3 -> DestinationFlag.ITEM 2 -> DestinationFlag.ENTITY - 1 -> DestinationFlag.OBJECT + 1 -> null else -> DestinationFlag.OBJECT } diff --git a/Server/src/main/kotlin/rs09/worker/ManagementEvents.kt b/Server/src/main/kotlin/rs09/worker/ManagementEvents.kt index 8a6f2da10..472fca3e6 100644 --- a/Server/src/main/kotlin/rs09/worker/ManagementEvents.kt +++ b/Server/src/main/kotlin/rs09/worker/ManagementEvents.kt @@ -149,6 +149,13 @@ object ManagementEvents { } + is FriendUpdate -> { + val remove = event.type == FriendUpdate.Type.REMOVE + val f = Repository.getPlayerByName(event.friend) + val p = Repository.getPlayerByName(event.username) + val world = if (f != null) GameWorld.settings!!.worldId else 0 + } + is PrivateMessage -> { val sender = Repository.getPlayerByName(event.sender) val receiver = Repository.getPlayerByName(event.receiver) diff --git a/Server/src/test/kotlin/core/PathfinderTests.kt b/Server/src/test/kotlin/core/PathfinderTests.kt new file mode 100644 index 000000000..519902a66 --- /dev/null +++ b/Server/src/test/kotlin/core/PathfinderTests.kt @@ -0,0 +1,53 @@ +package core + +import TestUtils +import api.replaceScenery +import core.cache.def.impl.SceneryDefinition +import core.game.interaction.MovementPulse +import core.game.node.scenery.Scenery +import core.game.world.map.Location +import core.game.world.map.RegionManager +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import rs09.game.interaction.InteractionListener +import rs09.game.interaction.InteractionListeners +import rs09.game.node.entity.skill.gather.GatheringSkillOptionListeners +import rs09.game.system.SystemLogger +import rs09.game.world.GameWorld + +class PathfinderTests { + companion object {init {TestUtils.preTestSetup(); GatheringSkillOptionListeners().defineListeners() }} + + @Test fun getOccupiedTilesShouldReturnCorrectSetOfTilesThatAnObjectOccupiesAtAllRotations() { + //clay fireplace - 13609 - sizex: 1, sizey: 2 + val scenery = Scenery(13609, Location.create(50, 50, 0)) + + scenery.rotation = 0 + val occupiedAt0 = scenery.occupiedTiles.toTypedArray() + Assertions.assertArrayEquals(arrayOf(Location.create(50, 50), Location.create(50,51)), occupiedAt0) + + scenery.rotation = 1 + val occupiedAt1 = scenery.occupiedTiles.toTypedArray() + Assertions.assertArrayEquals(arrayOf(Location.create(50,50), Location.create(51,50)), occupiedAt1) + + scenery.rotation = 2 + val occupiedAt2 = scenery.occupiedTiles.toTypedArray() + Assertions.assertArrayEquals(arrayOf(Location.create(50,50), Location.create(50,49)), occupiedAt2) + + scenery.rotation = 3 + val occupiedAt3 = scenery.occupiedTiles.toTypedArray() + Assertions.assertArrayEquals(arrayOf(Location.create(50,50), Location.create(49,50)), occupiedAt3) + } + + @Test fun movementPulseShouldStopEarlyIfNextToATileOccupiedByTargetObject() { + val start = Location.create(2731, 3481) + val dest = RegionManager.getObject(0, 2720, 3475, 1307) + val p = TestUtils.getMockPlayer("treefindtest") + p.location = start + p.init() + + Assertions.assertEquals(true, InteractionListeners.run(1307, InteractionListener.SCENERY, "chop-down", p, dest!!)) + TestUtils.advanceTicks(20) + Assertions.assertEquals(Location.create(2722, 3475, 0), p.location) + } +} \ No newline at end of file