diff --git a/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java b/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java index 45b96ee22b..9defe5fd89 100644 --- a/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java +++ b/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java @@ -27,6 +27,7 @@ package net.runelite.api.coords; import lombok.Value; import net.runelite.api.Client; +import static net.runelite.api.Constants.CHUNK_SIZE; import net.runelite.api.Perspective; import net.runelite.api.Point; @@ -149,6 +150,72 @@ public class WorldPoint ); } + /** + * Gets the coordinate of the tile that contains the passed local point. + * + * @param client the client + * @param localPoint the local coordinate + * @return the tile coordinate containing the local point + */ + public static WorldPoint fromLocalInstance(Client client, LocalPoint localPoint) + { + if (client.isInInstancedRegion()) + { + // get position in the scene + int sceneX = localPoint.getSceneX(); + int sceneY = localPoint.getSceneY(); + + // get chunk from scene + int chunkX = sceneX / CHUNK_SIZE; + int chunkY = sceneY / CHUNK_SIZE; + + // get the template chunk for the chunk + int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); + int templateChunk = instanceTemplateChunks[client.getPlane()][chunkX][chunkY]; + + int rotation = templateChunk >> 1 & 0x3; + int templateChunkY = (templateChunk >> 3 & 0x7FF) * CHUNK_SIZE; + int templateChunkX = (templateChunk >> 14 & 0x3FF) * CHUNK_SIZE; + int plane = templateChunk >> 24 & 0x3; + + // calculate world point of the template + int x = templateChunkX + (sceneX & (CHUNK_SIZE - 1)); + int y = templateChunkY + (sceneY & (CHUNK_SIZE - 1)); + + // create and rotate point back to 0, to match with template + return rotate(new WorldPoint(x, y, plane), 4 - rotation); + } + else + { + return fromLocal(client, localPoint); + } + } + + /** + * Rotate the coordinates in the chunk according to chunk rotation + * + * @param point point + * @param rotation rotation + * @return world point + */ + private static WorldPoint rotate(WorldPoint point, int rotation) + { + int chunkX = point.getX() & ~(CHUNK_SIZE - 1); + int chunkY = point.getY() & ~(CHUNK_SIZE - 1); + int x = point.getX() & (CHUNK_SIZE - 1); + int y = point.getY() & (CHUNK_SIZE - 1); + switch (rotation) + { + case 1: + return new WorldPoint(chunkX + y, chunkY + (CHUNK_SIZE - 1 - x), point.getPlane()); + case 2: + return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - x), chunkY + (CHUNK_SIZE - 1 - y), point.getPlane()); + case 3: + return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - y), chunkY + x, point.getPlane()); + } + return point; + } + /** * Gets the shortest distance from this point to a WorldArea. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java index c2605d5186..f5e382ea95 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java @@ -34,11 +34,9 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import net.runelite.api.Client; -import static net.runelite.api.Constants.CHUNK_SIZE; import net.runelite.api.GameState; import net.runelite.api.Skill; import net.runelite.api.WorldType; -import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ExperienceChanged; @@ -186,7 +184,7 @@ public class DiscordPlugin extends Plugin return; } - final int playerRegionID = getCurrentRegion(); + final int playerRegionID = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID(); if (playerRegionID == 0) { @@ -238,26 +236,4 @@ public class DiscordPlugin extends Plugin return false; } - - private int getCurrentRegion() - { - if (!client.isInInstancedRegion()) - { - return client.getLocalPlayer().getWorldLocation().getRegionID(); - } - - // get chunk data of current chunk - final LocalPoint localPoint = client.getLocalPlayer().getLocalLocation(); - final int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); - final int z = client.getPlane(); - final int chunkData = instanceTemplateChunks[z][localPoint.getSceneX() / CHUNK_SIZE][localPoint.getSceneY() / CHUNK_SIZE]; - - // extract world point from chunk data - final int chunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; - final int chunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; - - final WorldPoint worldPoint = new WorldPoint(chunkX, chunkY, z); - return worldPoint.getRegionID(); - } - } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index ffbea44f19..199683301f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -311,39 +311,7 @@ public class GroundMarkerPlugin extends Plugin return; } - WorldPoint worldPoint; - - if (client.isInInstancedRegion()) - { - // get position in the scene - int sceneX = localPoint.getSceneX(); - int sceneY = localPoint.getSceneY(); - - // get chunk from scene - int chunkX = sceneX / CHUNK_SIZE; - int chunkY = sceneY / CHUNK_SIZE; - - // get the template chunk for the chunk - int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); - int templateChunk = instanceTemplateChunks[client.getPlane()][chunkX][chunkY]; - - int rotation = templateChunk >> 1 & 0x3; - int templateChunkY = (templateChunk >> 3 & 0x7FF) * CHUNK_SIZE; - int templateChunkX = (templateChunk >> 14 & 0x3FF) * CHUNK_SIZE; - int plane = templateChunk >> 24 & 0x3; - - // calculate world point of the template - int x = templateChunkX + (sceneX & (CHUNK_SIZE - 1)); - int y = templateChunkY + (sceneY & (CHUNK_SIZE - 1)); - - worldPoint = new WorldPoint(x, y, plane); - // rotate point back to 0, to match with template - worldPoint = rotateInverse(worldPoint, rotation); - } - else - { - worldPoint = WorldPoint.fromLocal(client, localPoint); - } + WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()); int regionId = worldPoint.getRegionID(); GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getX() & 0x3f, worldPoint.getY() & 0x3f, client.getPlane());