diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java index 9923b02b8b..d16d8c798d 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java @@ -182,17 +182,31 @@ public class WorldMapOverlay extends Overlay Float pixelsPerTile = ro.getWorldMapZoom(); - Point worldMapPosition = ro.getWorldMapPosition(); - int xWorldDiff = worldPoint.getX() - worldMapPosition.getX(); - int yWorldDiff = worldPoint.getY() - worldMapPosition.getY(); - yWorldDiff = -yWorldDiff; - Widget map = clientProvider.get().getWidget(WidgetInfo.WORLD_MAP_VIEW); if (map != null) { Rectangle worldMapRect = map.getBounds(); - int xGraphDiff = (int) (xWorldDiff * pixelsPerTile + worldMapRect.getWidth() / 2 + worldMapRect.getX()); - int yGraphDiff = (int) (yWorldDiff * pixelsPerTile + worldMapRect.getHeight() / 2 + worldMapRect.getY()); + + int widthInTiles = (int) Math.ceil(worldMapRect.getWidth() / pixelsPerTile); + int heightInTiles = (int) Math.ceil(worldMapRect.getHeight() / pixelsPerTile); + + Point worldMapPosition = ro.getWorldMapPosition(); + + //Offset in tiles from anchor sides + int yTileMax = worldMapPosition.getY() - heightInTiles / 2; + int yTileOffset = (yTileMax - worldPoint.getY() - 1) * -1; + int xTileOffset = worldPoint.getX() + widthInTiles / 2 - worldMapPosition.getX(); + + int xGraphDiff = ((int) (xTileOffset * pixelsPerTile)); + int yGraphDiff = (int) (yTileOffset * pixelsPerTile); + + //Center on tile. + yGraphDiff -= pixelsPerTile - Math.ceil(pixelsPerTile / 2); + xGraphDiff += pixelsPerTile - Math.ceil(pixelsPerTile / 2); + + yGraphDiff = worldMapRect.height - yGraphDiff; + yGraphDiff += (int) worldMapRect.getY(); + xGraphDiff += (int) worldMapRect.getX(); return new Point(xGraphDiff, yGraphDiff); } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/WorldMapManagerMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/WorldMapManagerMixin.java new file mode 100644 index 0000000000..3f51e31e48 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/WorldMapManagerMixin.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, Morgan Lewis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.mixins; + +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Replace; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSWorldMapManager; + +@Mixin(RSWorldMapManager.class) +public abstract class WorldMapManagerMixin implements RSWorldMapManager +{ + @Shadow("clientInstance") + static RSClient client; + + /* + The worldMapZoom is essentially pixels per tile. In most instances + getPixelsPerTile returns the same as worldMapZoom. + + At some map widths when 100% zoomed in the Jagex version of this function + returns 7.89 instead of 8.0 (the worldMapZoom at this level). + This would cause both the x and y positions of the map to shift + slightly when the map was certain widths. + + This mixin function replaces Jagex calculation with getWorldMapZoom. + This small change makes the world map tile sizing predictable. + */ + @Replace("getPixelsPerTile") + @Override + public float getPixelsPerTile(int graphicsDiff, int worldDiff) + { + return client.getRenderOverview().getWorldMapZoom(); + } + +} diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapManager.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapManager.java index 7c34747cca..60377bc659 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapManager.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapManager.java @@ -38,4 +38,7 @@ public interface RSWorldMapManager extends WorldMapManager @Import("mapSurfaceBaseOffsetY") int getSurfaceOffsetY(); + + @Import("getPixelsPerTile") + float getPixelsPerTile(int graphicsDiff, int worldDiff); }