Improved pathfinding to stationary targets to not unnecessarily recalculate the path

Fixed an issue where end-of-movement was not being considered properly
Added admin command for drawing chunk boundaries ::drawchunks
Added admin command for drawing region boundaries ::drawregions
Added admin command for drawing the current route ::drawroute
Fixed impling IndexOutOfBoundsException
This commit is contained in:
Ceikry
2023-04-21 16:19:23 +00:00
committed by Ryan
parent f92fde2800
commit 9619f5b3a7
6 changed files with 137 additions and 56 deletions
@@ -16,7 +16,7 @@ class ImplingController : TickListener, Commands {
if (--nextCycle > getTicksBeforeNextCycleToDespawn()) if (--nextCycle > getTicksBeforeNextCycleToDespawn())
return return
if (activeImplings.size > 0) { if (activeImplings.size > 0) {
clearSomeImplings(implingsClearedPerTick) clearSomeImplings(min(activeImplings.size, implingsClearedPerTick))
return return
} }
generateSpawners() generateSpawners()
@@ -269,6 +269,7 @@ public abstract class MovementPulse extends Pulse {
return; return;
} }
if (destination instanceof Entity || interactLocation == null) {
Location ml = mover.getLocation(); Location ml = mover.getLocation();
Location dl = destination.getLocation(); Location dl = destination.getLocation();
// Lead the target if they're walking/running, unless they're already within interaction range // Lead the target if they're walking/running, unless they're already within interaction range
@@ -290,11 +291,12 @@ public abstract class MovementPulse extends Pulse {
} }
} }
} }
Path path = Pathfinder.find(mover, loc != null ? loc : destination, true, pathfinder); Path path = Pathfinder.find(mover, loc != null ? loc : destination, true, pathfinder);
near = !path.isSuccessful() || path.isMoveNear(); near = !path.isSuccessful() || path.isMoveNear();
interactLocation = mover.getLocation(); interactLocation = mover.getLocation();
boolean canMove = true; boolean canMove = true;
if (destination instanceof NPC || destination instanceof Player) { if (destination instanceof Entity) {
Entity e = (Entity) destination; Entity e = (Entity) destination;
Location l = e.getLocation(); Location l = e.getLocation();
Deque<Point> npcPath = e.getWalkingQueue().getQueue(); Deque<Point> npcPath = e.getWalkingQueue().getQueue();
@@ -328,6 +330,7 @@ public abstract class MovementPulse extends Pulse {
} }
} }
} }
}
last = destination.getLocation(); last = destination.getLocation();
} }
@@ -60,7 +60,7 @@ class ScriptProcessor(val entity: Entity) {
fun postMovement(didMove: Boolean) { fun postMovement(didMove: Boolean) {
if (didMove) if (didMove)
entity.clocks[Clocks.MOVEMENT] = GameWorld.ticks + 1 entity.clocks[Clocks.MOVEMENT] = GameWorld.ticks + if (entity.walkingQueue.isRunning) 0 else 1
var canProcess = !entity.delayed() var canProcess = !entity.delayed()
if (entity is Player) if (entity is Player)
canProcess = canProcess && !entity.interfaceManager.isOpened && !entity.interfaceManager.hasChatbox() canProcess = canProcess && !entity.interfaceManager.isOpened && !entity.interfaceManager.hasChatbox()
@@ -80,7 +80,7 @@ class ScriptProcessor(val entity: Entity) {
} }
} }
if (canProcess && (apScript != null || opScript != null)) { if (canProcess && (apScript != null || opScript != null)) {
if (!interacted && !didMove) { if (!interacted && !didMove && finishedMoving(entity)) {
sendMessage(entity, "I can't reach that!") sendMessage(entity, "I can't reach that!")
reset() reset()
} }
@@ -4,15 +4,19 @@ import content.global.skill.skillcapeperks.SkillcapePerks;
import core.game.node.entity.Entity; import core.game.node.entity.Entity;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.entity.skill.Skills; import core.game.node.entity.skill.Skills;
import core.game.node.item.Item;
import core.game.node.item.GroundItem;
import core.game.world.map.Direction; import core.game.world.map.Direction;
import core.game.world.map.Location; import core.game.world.map.Location;
import core.game.world.map.Point; import core.game.world.map.Point;
import core.game.world.map.RegionManager; import core.game.world.map.RegionManager;
import core.game.world.update.flag.chunk.ItemUpdateFlag;
import core.tools.Log; import core.tools.Log;
import core.tools.SystemLogger; import core.tools.SystemLogger;
import java.util.Deque; import java.util.Deque;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList;
import static core.api.ContentAPIKt.log; import static core.api.ContentAPIKt.log;
@@ -58,6 +62,8 @@ public final class WalkingQueue {
*/ */
private Location footPrint; private Location footPrint;
public ArrayList<GroundItem> routeItems = new ArrayList<GroundItem>();
/** /**
* Constructs a new {@code WalkingQueue} {@code Object}. * Constructs a new {@code WalkingQueue} {@code Object}.
* @param entity The entity. * @param entity The entity.
@@ -84,8 +90,17 @@ public final class WalkingQueue {
return; return;
} }
Point point = walkingQueue.poll(); Point point = walkingQueue.poll();
boolean drawPath = entity.getAttribute("routedraw", false);
if (point == null) { if (point == null) {
updateRunEnergy(false); updateRunEnergy(false);
if (isPlayer && drawPath) {
for (GroundItem item : routeItems) {
if (item != null) {
RegionManager.getRegionPlane(item.getLocation()).remove(item);
}
}
routeItems.clear();
}
return; return;
} }
if (isPlayer && ((Player) entity).getSettings().getRunEnergy() < 1.0) { if (isPlayer && ((Player) entity).getSettings().getRunEnergy() < 1.0) {
@@ -300,6 +315,13 @@ public final class WalkingQueue {
if (point == null) { if (point == null) {
return; return;
} }
boolean drawRoute = entity.getAttribute("routedraw", false);
if (drawRoute && entity instanceof Player) {
Player p = (Player) entity;
GroundItem item = new GroundItem(new Item(13444), Location.create(x, y, p.getLocation().getZ()), p);
routeItems.add (item);
RegionManager.getRegionPlane(item.getLocation()).add(item);
}
int diffX = x - point.getX(), diffY = y - point.getY(); int diffX = x - point.getX(), diffY = y - point.getY();
int max = Math.max(Math.abs(diffX), Math.abs(diffY)); int max = Math.max(Math.abs(diffX), Math.abs(diffY));
for (int i = 0; i < max; i++) { for (int i = 0; i < max; i++) {
@@ -212,5 +212,17 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
addItem(player, item, 1000) addItem(player, item, 1000)
} }
} }
define("drawchunks", Privilege.ADMIN, "", "Draws the border of the chunk you're standing in") {player, _ ->
setAttribute (player, "chunkdraw", !getAttribute(player, "chunkdraw", false))
}
define("drawregions", Privilege.ADMIN, "", "DRaws the border of the region you're standing in") {player, _ ->
setAttribute (player, "regiondraw", !getAttribute(player, "regiondraw", false))
}
define("drawroute", Privilege.ADMIN, "", "Visualizes the path your player is taking") {player, _ ->
setAttribute (player, "routedraw", !getAttribute(player, "routedraw", false))
}
} }
} }
@@ -149,8 +149,52 @@ public class RegionChunk {
} }
} }
} }
if (items != null) { ArrayList<GroundItem> totalItems = items != null ? new ArrayList(items) : new ArrayList();
for (Item item : items) {
boolean drawChunks = player.getAttribute("chunkdraw", false);
boolean drawRegions = player.getAttribute("regiondraw", false);
if (drawChunks) {
Location l = currentBase;
for (int x = 0; x < SIZE; x++) {
for (int y = 0; y < SIZE; y++) {
boolean add = false;
if (y == 0 || y == SIZE - 1)
add = true;
else if (x == 0 || x == SIZE - 1)
add = true;
if (add)
totalItems.add(new GroundItem(new Item(13444), l.transform(x, y, 0), player));
}
}
}
if (drawRegions) {
Location l = currentBase;
int localX = l.getLocalX();
int localY = l.getLocalY();
for (int x = 0; x < SIZE; x++)
for (int y = 0; y < SIZE; y++) {
boolean add = false;
if (localY == 0 || localY == 56)
if (localY == 0 && y == 0)
add = true;
else if (localY == 56 && y == SIZE - 1)
add = true;
if (localX == 0 || localX == 56)
if (localX == 0 && x == 0)
add = true;
else if (localX == 56 && x == SIZE - 1)
add = true;
if (add)
totalItems.add(new GroundItem(new Item(13444), l.transform(x,y,0), player));
}
}
if (totalItems != null) {
for (Item item : totalItems) {
if (item != null && item.isActive() && item.getLocation() != null) { if (item != null && item.isActive() && item.getLocation() != null) {
GroundItem g = (GroundItem) item; GroundItem g = (GroundItem) item;
if (!g.isPrivate() || g.droppedBy(player)) { if (!g.isPrivate() || g.droppedBy(player)) {