Add pathfinding API

This commit is contained in:
GeChallengeM
2021-08-01 18:15:15 +02:00
parent c726d477a8
commit 38939ac971
3 changed files with 347 additions and 0 deletions

View File

@@ -140,6 +140,14 @@ public interface Tile extends Locatable
*/
boolean hasLineOfSightTo(Tile other);
/**
* Computes and returns the path from this tile to another.
*
* @param other the other tile
* @return the checkpoint tiles of the path, or null if no path found
*/
List<Tile> pathTo(Tile other);
/**
* Get all the ground items for this tile
*

View File

@@ -34,6 +34,7 @@ import net.runelite.api.Client;
import static net.runelite.api.Constants.CHUNK_SIZE;
import static net.runelite.api.Constants.REGION_SIZE;
import net.runelite.api.Perspective;
import net.runelite.api.Tile;
/**
* A three-dimensional point representing the coordinate of a Tile.
@@ -436,4 +437,90 @@ public class WorldPoint
{
return position & (REGION_SIZE - 1);
}
/**
* Determine the checkpoint tiles of a server-sided path from this WorldPoint to another WorldPoint.
* <p>
* The checkpoint tiles of a path are the "corner tiles" of a path and determine the path completely.
*
* Note that true server-sided pathfinding uses collisiondata of the 128x128 area around this WorldPoint,
* while the client only has access to collisiondata within the 104x104 loaded area.
* This means that the results would differ in case the server's path goes near (or over) the border of the loaded area.
*
* @param client The client to compare in
* @param other The other WorldPoint to compare with
* @return Returns the checkpoint tiles of the path
*/
public List<WorldPoint> pathTo(Client client, WorldPoint other)
{
if (plane != other.getPlane())
{
return null;
}
LocalPoint sourceLp = LocalPoint.fromWorld(client, x, y);
LocalPoint targetLp = LocalPoint.fromWorld(client, other.getX(), other.getY());
if (sourceLp == null || targetLp == null)
{
return null;
}
int thisX = sourceLp.getSceneX();
int thisY = sourceLp.getSceneY();
int otherX = targetLp.getSceneX();
int otherY = targetLp.getSceneY();
Tile[][][] tiles = client.getScene().getTiles();
Tile sourceTile = tiles[plane][thisX][thisY];
Tile targetTile = tiles[plane][otherX][otherY];
List<Tile> checkpointTiles = sourceTile.pathTo(targetTile);
if (checkpointTiles == null)
{
return null;
}
List<WorldPoint> checkpointWPs = new ArrayList<>();
for (Tile checkpointTile : checkpointTiles)
{
if (checkpointTile == null) {
break;
}
checkpointWPs.add(checkpointTile.getWorldLocation());
}
return checkpointWPs;
}
/**
* Gets the path distance from this point to a WorldPoint.
* <p>
* If the other point is unreachable, this method will return {@link Integer#MAX_VALUE}.
*
* @param client
* @param other
* @return Returns the path distance
*/
public int distanceToPath(Client client, WorldPoint other)
{
List<WorldPoint> checkpointWPs = this.pathTo(client, other);
if (checkpointWPs == null)
{
// No path found
return Integer.MAX_VALUE;
}
WorldPoint destinationPoint = checkpointWPs.get(checkpointWPs.size() - 1);
if (other.getX() != destinationPoint.getX() || other.getY() != destinationPoint.getY())
{
// Path found but not to the requested tile
return Integer.MAX_VALUE;
}
WorldPoint Point1 = this;
int distance = 0;
for (WorldPoint Point2 : checkpointWPs)
{
distance += Point1.distanceTo2D(Point2);
Point1 = Point2;
}
return distance;
}
}