From ac071771b076abd398af3efe76552e310c8d2b54 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 21 Nov 2017 17:35:10 -0500 Subject: [PATCH 1/3] runelite-api: add getRegionMin/MaxLocation for GameObject --- .../main/java/net/runelite/api/GameObject.java | 15 +++++++++++++++ .../net/runelite/mixins/RSGameObjectMixin.java | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/GameObject.java b/runelite-api/src/main/java/net/runelite/api/GameObject.java index 07cd9680ff..1fa5c11891 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameObject.java +++ b/runelite-api/src/main/java/net/runelite/api/GameObject.java @@ -32,5 +32,20 @@ import java.awt.Polygon; */ public interface GameObject extends TileObject { + /** + * Returns the min x,y for this game object + * + * @return + */ + Point getRegionMinLocation(); + + /** + * Returns the max x,y for this game object. This is different from + * {@link #getRegionMinLocation()} for objects larger than 1 tile. + * + * @return + */ + Point getRegionMaxLocation(); + Polygon getConvexHull(); } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java index 4c549c5235..1f509ca478 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java @@ -26,6 +26,7 @@ package net.runelite.mixins; import java.awt.Polygon; import net.runelite.api.Model; +import net.runelite.api.Point; import net.runelite.api.Renderable; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; @@ -34,6 +35,20 @@ import net.runelite.rs.api.RSGameObject; @Mixin(RSGameObject.class) public abstract class RSGameObjectMixin implements RSGameObject { + @Inject + @Override + public Point getRegionMinLocation() + { + return new Point(getRelativeX(), getRelativeY()); + } + + @Inject + @Override + public Point getRegionMaxLocation() + { + return new Point(getOffsetX(), getOffsetY()); + } + @Inject @Override public Polygon getConvexHull() From 1cad0c15040edbe750dc46a8daa7f1848c2ab612 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 21 Nov 2017 18:58:54 -0500 Subject: [PATCH 2/3] runelite-api: add SpritePixels.toBufferedImage --- .../java/net/runelite/api/SpritePixels.java | 9 +++ .../net/runelite/client/game/ItemManager.java | 16 +----- .../runelite/mixins/RSSpritePixelsMixin.java | 56 +++++++++++++++++++ 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/RSSpritePixelsMixin.java diff --git a/runelite-api/src/main/java/net/runelite/api/SpritePixels.java b/runelite-api/src/main/java/net/runelite/api/SpritePixels.java index dbc3c6c3bb..49fd5fc973 100644 --- a/runelite-api/src/main/java/net/runelite/api/SpritePixels.java +++ b/runelite-api/src/main/java/net/runelite/api/SpritePixels.java @@ -24,6 +24,8 @@ */ package net.runelite.api; +import java.awt.image.BufferedImage; + public interface SpritePixels { int DEFAULT_SHADOW_COLOR = 3153952; @@ -35,4 +37,11 @@ public interface SpritePixels int getHeight(); int[] getPixels(); + + /** + * Covert the SpritePixels to a BufferedImage + * + * @return + */ + BufferedImage toBufferedImage(); } diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index a56647e911..99c7aa330f 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -148,21 +148,7 @@ public class ItemManager private BufferedImage loadImage(int itemId) { SpritePixels sprite = client.createItemSprite(itemId, 1, 1, SpritePixels.DEFAULT_SHADOW_COLOR, 0, false); - int[] pixels = sprite.getPixels(); - int[] transPixels = new int[pixels.length]; - BufferedImage img = new BufferedImage(sprite.getWidth(), sprite.getHeight(), BufferedImage.TYPE_INT_ARGB); - - for (int i = 0; i < pixels.length; i++) - { - if (pixels[i] != 0) - { - transPixels[i] = pixels[i] | 0xff000000; - } - } - - img.setRGB(0, 0, sprite.getWidth(), sprite.getHeight(), transPixels, 0, sprite.getWidth()); - - return img; + return sprite.toBufferedImage(); } /** diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSSpritePixelsMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSSpritePixelsMixin.java new file mode 100644 index 0000000000..eeca0febcb --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSSpritePixelsMixin.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016-2017, Adam + * 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 java.awt.image.BufferedImage; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.rs.api.RSSpritePixels; + +@Mixin(RSSpritePixels.class) +public abstract class RSSpritePixelsMixin implements RSSpritePixels +{ + @Inject + @Override + public BufferedImage toBufferedImage() + { + int width = getWidth(); + int height = getHeight(); + int[] pixels = getPixels(); + int[] transPixels = new int[pixels.length]; + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + + for (int i = 0; i < pixels.length; i++) + { + if (pixels[i] != 0) + { + transPixels[i] = pixels[i] | 0xff000000; + } + } + + img.setRGB(0, 0, width, height, transPixels, 0, width); + return img; + } +} From 6c14b083845c730c89afa787326948f508d69a68 Mon Sep 17 00:00:00 2001 From: Toocanzs Date: Tue, 21 Nov 2017 19:04:35 -0500 Subject: [PATCH 3/3] instance map: draw map icons, objects, doors, and improve walls --- .../src/main/java/net/runelite/api/Area.java | 30 ++ .../main/java/net/runelite/api/Client.java | 8 + .../java/net/runelite/api/GameObject.java | 2 + .../java/net/runelite/api/IndexedSprite.java | 42 ++ .../net/runelite/api/ObjectComposition.java | 34 ++ .../java/net/runelite/api/TileObject.java | 2 + .../java/net/runelite/api/WallObject.java | 2 + .../instancemap/InstanceMapOverlay.java | 406 ++++++++++++++---- ...eMapPlugin.java => InstanceMapPlugin.java} | 2 +- .../client/plugins/instancemap/PixelMaps.java | 66 ++- .../net/runelite/mixins/TileObjectMixin.java | 13 +- .../main/java/net/runelite/rs/api/RSArea.java | 35 ++ .../java/net/runelite/rs/api/RSClient.java | 17 +- .../net/runelite/rs/api/RSGameObject.java | 1 + .../net/runelite/rs/api/RSIndexedSprite.java | 59 +++ .../runelite/rs/api/RSObjectComposition.java | 12 +- .../net/runelite/rs/api/RSWallObject.java | 4 + 17 files changed, 642 insertions(+), 93 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/Area.java create mode 100644 runelite-api/src/main/java/net/runelite/api/IndexedSprite.java create mode 100644 runelite-api/src/main/java/net/runelite/api/ObjectComposition.java rename runelite-client/src/main/java/net/runelite/client/plugins/instancemap/{IntanceMapPlugin.java => InstanceMapPlugin.java} (99%) create mode 100644 runescape-api/src/main/java/net/runelite/rs/api/RSArea.java create mode 100644 runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java diff --git a/runelite-api/src/main/java/net/runelite/api/Area.java b/runelite-api/src/main/java/net/runelite/api/Area.java new file mode 100644 index 0000000000..db50308fbc --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/Area.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, Adam + * 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.api; + +public interface Area +{ + SpritePixels getMapIcon(boolean var1); +} diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 052a82ff0c..33718195eb 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -145,4 +145,12 @@ public interface Client Map getChatLineMap(); Widget getViewportWidget(); + + ObjectComposition getObjectDefinition(int objectId); + + Area[] getMapAreas(); + + IndexedSprite[] getMapScene(); + + SpritePixels[] getMapIcons(); } diff --git a/runelite-api/src/main/java/net/runelite/api/GameObject.java b/runelite-api/src/main/java/net/runelite/api/GameObject.java index 1fa5c11891..894f155c8c 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameObject.java +++ b/runelite-api/src/main/java/net/runelite/api/GameObject.java @@ -32,6 +32,8 @@ import java.awt.Polygon; */ public interface GameObject extends TileObject { + int getFlags(); + /** * Returns the min x,y for this game object * diff --git a/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java b/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java new file mode 100644 index 0000000000..23394f194c --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Adam + * 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.api; + +public interface IndexedSprite +{ + byte[] getPixels(); + + int[] getPalette(); + + int getOffsetX(); + + int getOffsetY(); + + int getWidth(); + + int getOriginalWidth(); + + int getHeight(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/ObjectComposition.java b/runelite-api/src/main/java/net/runelite/api/ObjectComposition.java new file mode 100644 index 0000000000..22cf87256e --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/ObjectComposition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, Adam + * 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.api; + +public interface ObjectComposition +{ + String getName(); + + int getMapSceneId(); + + int getMapIconId(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/TileObject.java b/runelite-api/src/main/java/net/runelite/api/TileObject.java index 0bc7086a1a..4076bd1483 100644 --- a/runelite-api/src/main/java/net/runelite/api/TileObject.java +++ b/runelite-api/src/main/java/net/runelite/api/TileObject.java @@ -41,6 +41,8 @@ public interface TileObject Point getLocalLocation(); + Point getRegionLocation(); + Point getCanvasLocation(); Polygon getCanvasTilePoly(); diff --git a/runelite-api/src/main/java/net/runelite/api/WallObject.java b/runelite-api/src/main/java/net/runelite/api/WallObject.java index a16216a8c2..8cfd488a55 100644 --- a/runelite-api/src/main/java/net/runelite/api/WallObject.java +++ b/runelite-api/src/main/java/net/runelite/api/WallObject.java @@ -34,4 +34,6 @@ public interface WallObject extends TileObject int getOrientationA(); int getOrientationB(); + + int getConfig(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java index 568fb9b099..100a82db8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java @@ -31,12 +31,17 @@ import java.awt.image.BufferedImage; import javax.annotation.Nullable; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.GameObject; import net.runelite.api.GameState; +import net.runelite.api.GroundObject; +import net.runelite.api.IndexedSprite; +import net.runelite.api.ObjectComposition; import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.api.Region; import net.runelite.api.SceneTileModel; import net.runelite.api.SceneTilePaint; +import net.runelite.api.SpritePixels; import net.runelite.api.Tile; import net.runelite.api.WallObject; import net.runelite.client.events.GameStateChanged; @@ -44,14 +49,23 @@ import net.runelite.client.events.MapRegionChanged; import static net.runelite.client.plugins.instancemap.PixelMaps.ALL; import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM; import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM_LEFT_CORNER; +import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM_LEFT_DOT; import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM_LEFT_TO_TOP_RIGHT; import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM_RIGHT_CORNER; +import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM_RIGHT_DOT; import static net.runelite.client.plugins.instancemap.PixelMaps.LEFT; import static net.runelite.client.plugins.instancemap.PixelMaps.RIGHT; import static net.runelite.client.plugins.instancemap.PixelMaps.TOP; import static net.runelite.client.plugins.instancemap.PixelMaps.TOP_LEFT_CORNER; +import static net.runelite.client.plugins.instancemap.PixelMaps.TOP_LEFT_DOT; +import static net.runelite.client.plugins.instancemap.PixelMaps.TOP_LEFT_TO_BOTTOM_RIGHT; import static net.runelite.client.plugins.instancemap.PixelMaps.TOP_RIGHT_CORNER; -import static net.runelite.client.plugins.instancemap.PixelMaps.TOP_RIGHT_TO_BOTTOM_LEFT; +import static net.runelite.client.plugins.instancemap.PixelMaps.TOP_RIGHT_DOT; +import static net.runelite.client.plugins.instancemap.WallOffset.BOTTOM_LEFT; +import static net.runelite.client.plugins.instancemap.WallOffset.BOTTOM_RIGHT; +import static net.runelite.client.plugins.instancemap.WallOffset.NONE; +import static net.runelite.client.plugins.instancemap.WallOffset.TOP_LEFT; +import static net.runelite.client.plugins.instancemap.WallOffset.TOP_RIGHT; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; @@ -88,6 +102,7 @@ class InstanceMapOverlay extends Overlay private final Client client; private final InstanceMapConfig config; + private final InstanceMapPlugin plugin; /** * Saved image of the region, no reason to draw the whole thing every @@ -97,11 +112,12 @@ class InstanceMapOverlay extends Overlay private boolean showMap = false; @Inject - InstanceMapOverlay(@Nullable Client client, InstanceMapConfig config) + InstanceMapOverlay(@Nullable Client client, InstanceMapConfig config, InstanceMapPlugin plugin) { super(OverlayPosition.DYNAMIC); this.client = client; this.config = config; + this.plugin = plugin; } public boolean isMapShown() @@ -262,6 +278,7 @@ class InstanceMapOverlay extends Overlay graphics.setColor(Color.white); graphics.drawRect(0, 0, mapOverlaySize.width - 1, mapOverlaySize.height - 1);//draw outline + //These loops are seperated on purpose to prevent layering issues. This is how it's written in the client //Draw the base colors first for (int x = 0; x < tiles.length; x++) { @@ -271,7 +288,16 @@ class InstanceMapOverlay extends Overlay } } - //Draw walls on top + //environment + for (int x = 0; x < tiles.length; x++) + { + for (int y = tiles[x].length - 1; y >= 0; y--)//Flip y value + { + drawEnvironment(graphics, region, tiles[x][(tiles[x].length - 1) - y], x, y);//draw trees/rocks/bushes + } + } + + //Draw walls for (int x = 0; x < tiles.length; x++) { for (int y = tiles[x].length - 1; y >= 0; y--)//Flip y value @@ -280,34 +306,164 @@ class InstanceMapOverlay extends Overlay } } + //Finally draw map icons on top of that + for (int x = 0; x < tiles.length; x++) + { + for (int y = tiles[x].length - 1; y >= 0; y--)//Flip y value + { + drawMapIcons(graphics, region, tiles[x][(tiles[x].length - 1) - y], x, y);//draw map icons + } + } + } private void drawTileWalls(Graphics2D graphics, Tile curTile, int x, int y) { - if (curTile != null) + if (curTile == null) { - WallObject wallObject = curTile.getWallObject(); - if (wallObject != null) - { - drawWallObject(graphics, wallObject, curTile, x * TILE_SIZE, y * TILE_SIZE); - } + return; + } + + WallObject wallObject = curTile.getWallObject(); + if (wallObject != null) + { + drawWallObject(graphics, wallObject, curTile, x * TILE_SIZE, y * TILE_SIZE); } } private void drawTileColor(Graphics2D graphics, Region region, Tile curTile, int x, int y) { - if (curTile != null) + if (curTile == null) { - SceneTilePaint sceneTilePaint = curTile.getSceneTilePaint(); - SceneTileModel sceneTileModel = curTile.getSceneTileModel(); + return; + } - if (sceneTilePaint != null) + SceneTilePaint sceneTilePaint = curTile.getSceneTilePaint(); + SceneTileModel sceneTileModel = curTile.getSceneTileModel(); + + if (sceneTilePaint != null) + { + drawMapPixel(graphics, sceneTilePaint, x * TILE_SIZE, y * TILE_SIZE); + } + else if (sceneTileModel != null) + { + drawComplexMapPixel(graphics, sceneTileModel, region, x * TILE_SIZE, y * TILE_SIZE); + } + } + + private void drawMapIcons(Graphics2D graphics, Region region, Tile curTile, int x, int y) + { + if (curTile == null) + { + return; + } + + //Draw game objects + GroundObject groundObject = curTile.getGroundObject(); + if (groundObject == null) + { + return; + } + + int hash = groundObject.getHash(); + int objId = groundObject.getId(); + + int startX = x * TILE_SIZE; + int startY = y * TILE_SIZE; + + if (hash != 0) + { + ObjectComposition objectComposition = client.getObjectDefinition(objId); + int mapIconId = objectComposition.getMapIconId(); + if (mapIconId >= 0) { - drawMapPixel(graphics, sceneTilePaint, x * TILE_SIZE, y * TILE_SIZE); + // this parameter is unused + SpritePixels sprite = client.getMapAreas()[mapIconId].getMapIcon(false); + + if (sprite == null) + { + return; + } + + BufferedImage img = sprite.toBufferedImage(); + graphics.drawImage(img, startX - (img.getWidth() / 2), startY - (img.getHeight() / 2), null); } - else if (sceneTileModel != null) + } + } + + private void drawEnvironment(Graphics2D graphics, Region region, Tile curTile, int x, int y) + { + if (curTile == null) + { + return; + } + + //Draw game objects + GameObject[] gameObjects = curTile.getGameObjects(); + if (gameObjects != null) + { + Tile[][] tiles = getTiles(); + for (GameObject gameObject : gameObjects) { - drawComplexMapPixel(graphics, sceneTileModel, region, x * TILE_SIZE, y * TILE_SIZE); + if (gameObject == null) + { + continue; + } + + int hash = gameObject.getHash(); + int objId = gameObject.getId(); + + int startX = x * TILE_SIZE; + int startY = y * TILE_SIZE; + + if (hash == 0) + { + continue; + } + + ObjectComposition objectComposition = client.getObjectDefinition(objId); + if (objectComposition.getMapSceneId() != -1) + { + Point gameObjectLocation = gameObject.getRegionMinLocation(); + int tileX = x; + int tileY = ((tiles[x].length - 1) - y);//flip y value + + if (gameObjectLocation.getX() == tileX && gameObjectLocation.getY() == tileY) + { + + IndexedSprite objectMapSprite = client.getMapScene()[objectComposition.getMapSceneId()]; + if (objectMapSprite != null) + { + drawIndexedSprite(graphics, objectMapSprite, gameObject, startX, startY); + } + } + } + + } + } + } + + private void drawIndexedSprite(Graphics2D graphics, IndexedSprite indexedSprite, GameObject gameObject, int startX, int startY) + { + //Mostly from code in IndexedSprite + int sourceOffset = 0; + + //For some reason some sprites don't have a byte array that is the same size as the width*height + if (indexedSprite.getPixels().length != indexedSprite.getHeight() * indexedSprite.getWidth()) + { + return; + } + + for (int y = -indexedSprite.getHeight(); y < 0; y++) + { + for (int x = -indexedSprite.getWidth(); x < 0; x++) + { + int index = indexedSprite.getPixels()[sourceOffset++] & 0xff; + if (index != 0) + { + graphics.setColor(new Color(indexedSprite.getPalette()[index]));//Get color from the pallete + drawPoint(graphics, startX + x + indexedSprite.getWidth() + indexedSprite.getOffsetX(), startY + y + indexedSprite.getHeight() / 2 + indexedSprite.getOffsetY()); + } } } } @@ -324,82 +480,145 @@ class InstanceMapOverlay extends Overlay */ private void drawMapPixel(Graphics2D graphics, SceneTilePaint sceneTilePaint, int startX, int startY) { - Color c = new Color(sceneTilePaint.getRBG());//Normal map pixels have only 1 solid color + //Normal map pixels have only 1 solid color + Color c = new Color(sceneTilePaint.getRBG()); graphics.setColor(c); graphics.fillRect(startX, startY, TILE_SIZE, TILE_SIZE); } - /** - * Gets the walls shape from the orientation - * - * @param orientationA the wall object's orientationA - * @param orientationB the wall object's orientationB - * @return A WallShape representing the wall as a 4x4 set of pixels with - * an offset - */ - private WallShape getWallShape(int orientationA, int orientationB) + private WallShape getWallShape(WallObject wallObject) { int[][] pixels = ALL; - WallOffset wallOffset = WallOffset.NONE; + WallOffset wallOffset = NONE; - switch (orientationA) + //Warning: Gower code below + int flags = wallObject.getConfig() & 255; + int config1 = flags >> 6 & 3; + int config2 = flags & 31; + + // Straight walls + if (config2 == 0) { - case 16: - //Diagonal / - pixels = BOTTOM_LEFT_TO_TOP_RIGHT; - wallOffset = WallOffset.TOP_LEFT; - break; - case 32: - //Diagonal \ - pixels = TOP_RIGHT_TO_BOTTOM_LEFT; - wallOffset = WallOffset.TOP_RIGHT; - break; - case 64: - //Diagonal / - pixels = BOTTOM_LEFT_TO_TOP_RIGHT; - wallOffset = WallOffset.BOTTOM_RIGHT; - break; - case 1: - //Left wall - pixels = LEFT; - break; - case 2: - //Top wall - pixels = TOP; - break; - case 4: - //Right wall - pixels = RIGHT; - break; - case 8: - //Bottom wall - pixels = BOTTOM; - break; - case 128: - //Diagonal \ - pixels = TOP_RIGHT_TO_BOTTOM_LEFT; - wallOffset = WallOffset.BOTTOM_LEFT; - break; + switch (config1) + { + case 0: + //draw left wall + pixels = LEFT; + wallOffset = NONE; + break; + case 1: + //draw top wall + pixels = TOP; + wallOffset = NONE; + break; + case 2: + //draw right wall + pixels = RIGHT; + wallOffset = NONE; + break; + case 3: + //draw bottom wall + pixels = BOTTOM; + wallOffset = NONE; + break; + + } } - - switch (orientationB) + // Corners + else if (config2 == 2) { - case 2: - //top left corner - pixels = TOP_LEFT_CORNER; - break; - case 4: - //top right corner - pixels = TOP_RIGHT_CORNER; - break; - case 8: - //bottom right corner - pixels = BOTTOM_RIGHT_CORNER; - break; - case 1: - //Bottom left corner - pixels = BOTTOM_LEFT_CORNER; - break; + switch (config1) + { + case 0: + pixels = TOP_LEFT_CORNER; + break; + case 1: + pixels = TOP_RIGHT_CORNER; + wallOffset = NONE; + break; + case 2: + pixels = BOTTOM_RIGHT_CORNER; + wallOffset = NONE; + break; + case 3: + pixels = BOTTOM_LEFT_CORNER; + wallOffset = NONE; + break; + default: + break; + } + } + // Dots + else if (config2 == 3) + { + switch (config1) + { + case 0: + //draw dot top left + pixels = TOP_LEFT_DOT; + wallOffset = NONE; + break; + case 1: + //draw dot top right + pixels = TOP_RIGHT_DOT; + wallOffset = NONE; + break; + case 2: + //draw dot bottom right + pixels = BOTTOM_RIGHT_DOT; + wallOffset = NONE; + break; + case 3: + //draw dot bottom left + pixels = BOTTOM_LEFT_DOT; + wallOffset = NONE; + break; + default: + break; + } + } + //This part never gets called, but it's written in the client. ¯\_(ツ)_/¯ + else if (config2 == 9) + { + if (config1 != 0 && config1 != 2) + { + //draw diagonal \ + pixels = TOP_LEFT_TO_BOTTOM_RIGHT; + wallOffset = NONE; + } + else + { + //draw diagonal / + pixels = BOTTOM_LEFT_TO_TOP_RIGHT; + wallOffset = NONE; + } + } + //Diagonals + else if (config2 == 1) + { + switch (config1) + { + case 0: + //draw diagonal / + pixels = BOTTOM_LEFT_TO_TOP_RIGHT; + wallOffset = TOP_LEFT; + break; + case 1: + //draw diagonal \ + pixels = TOP_LEFT_TO_BOTTOM_RIGHT; + wallOffset = TOP_RIGHT; + break; + case 2: + pixels = BOTTOM_LEFT_TO_TOP_RIGHT; + wallOffset = BOTTOM_RIGHT; + break; + case 3: + pixels = TOP_LEFT_TO_BOTTOM_RIGHT; + wallOffset = BOTTOM_LEFT; + break; + default: + break; + } } return new WallShape(pixels, wallOffset); @@ -418,10 +637,24 @@ class InstanceMapOverlay extends Overlay { graphics.setColor(Color.white); - int orientationA = wallObject.getOrientationA();//Orientation is a set of flags stored as an int - int orientationB = wallObject.getOrientationB(); + if (wallObject.getHash() == 0) + { + return; + } - WallShape wallShape = getWallShape(orientationA, orientationB); + //door + if (wallObject.getHash() > 0) + { + graphics.setColor(Color.red); + } + ObjectComposition objectComposition = client.getObjectDefinition(wallObject.getId()); + + if (objectComposition.getMapSceneId() != -1) + { + return; + } + + WallShape wallShape = getWallShape(wallObject); int[][] pixels = wallShape.getPixels(); for (int i = 0; i < pixels.length; i++) @@ -471,7 +704,8 @@ class InstanceMapOverlay extends Overlay int shape = sceneTileModel.getShape(); int rotation = sceneTileModel.getRotation(); - int overlay = sceneTileModel.getModelOverlay();//SceneTileModels have only two colors, and overlay and underlay. + //SceneTileModels have only two colors, and overlay and underlay. + int overlay = sceneTileModel.getModelOverlay(); int underlay = sceneTileModel.getModelUnderlay(); int[] shapes = TILE_MASK_2D[shape]; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/IntanceMapPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapPlugin.java similarity index 99% rename from runelite-client/src/main/java/net/runelite/client/plugins/instancemap/IntanceMapPlugin.java rename to runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapPlugin.java index 00ad626fa4..eace4dcab0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/IntanceMapPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapPlugin.java @@ -44,7 +44,7 @@ import net.runelite.client.ui.overlay.Overlay; @PluginDescriptor( name = "Instance Map" ) -public class IntanceMapPlugin extends Plugin +public class InstanceMapPlugin extends Plugin { private final WidgetMenuOption openMapOption = new WidgetMenuOption("Show", "Instance Map", WidgetInfo.WORLD_MAP); private final WidgetMenuOption ascendOption = new WidgetMenuOption("Ascend", "Instance Map", WidgetInfo.WORLD_MAP); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/PixelMaps.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/PixelMaps.java index 052436bf23..09d74671e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/PixelMaps.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/PixelMaps.java @@ -59,8 +59,72 @@ class PixelMaps } }; + static final int[][] TOP_LEFT_DOT = new int[][] + { + { + 1, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + } + }; + + static final int[][] TOP_RIGHT_DOT = new int[][] + { + { + 0, 0, 0, 1 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + } + }; + + static final int[][] BOTTOM_RIGHT_DOT = new int[][] + { + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 1 + } + }; + + static final int[][] BOTTOM_LEFT_DOT = new int[][] + { + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0 + }, + { + 1, 0, 0, 0 + } + }; + //Diagonal \ - static final int[][] TOP_RIGHT_TO_BOTTOM_LEFT = new int[][] + static final int[][] TOP_LEFT_TO_BOTTOM_RIGHT = new int[][] { { 1, 0, 0, 0 diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/TileObjectMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/TileObjectMixin.java index 4c6ded9bd6..e0ec89dc1a 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/TileObjectMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/TileObjectMixin.java @@ -30,14 +30,15 @@ import java.util.ArrayList; import java.util.List; import net.runelite.api.Model; import net.runelite.api.Perspective; +import static net.runelite.api.Perspective.LOCAL_COORD_BITS; import net.runelite.api.Point; import net.runelite.api.TileObject; -import net.runelite.api.model.Jarvis; -import net.runelite.api.model.Vertex; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Mixins; import net.runelite.api.mixins.Shadow; +import net.runelite.api.model.Jarvis; +import net.runelite.api.model.Vertex; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSDecorativeObject; import net.runelite.rs.api.RSGameObject; @@ -80,6 +81,14 @@ public abstract class TileObjectMixin implements TileObject return new Point(getX(), getY()); } + @Override + @Inject + public Point getRegionLocation() + { + Point locaLocation = getLocalLocation(); + return new Point(locaLocation.getX() >>> LOCAL_COORD_BITS, locaLocation.getY() >>> LOCAL_COORD_BITS); + } + @Override @Inject public Point getCanvasLocation() diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSArea.java b/runescape-api/src/main/java/net/runelite/rs/api/RSArea.java new file mode 100644 index 0000000000..3496778672 --- /dev/null +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSArea.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017, Adam + * 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.rs.api; + +import net.runelite.api.Area; +import net.runelite.mapping.Import; + +public interface RSArea extends RSCacheableNode, Area +{ + @Import("getMapIcon") + @Override + RSSpritePixels getMapIcon(boolean var1); +} diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index dbd8c73fdc..088e10b066 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -129,10 +129,10 @@ public interface RSClient extends RSGameEngine, Client @Import("collisionMaps") RSCollisionData[] getCollisionMaps(); - + @Import("playerIndexesCount") int getPlayerIndexesCount(); - + @Import("playerIndices") int[] getPlayerIndices(); @@ -204,6 +204,7 @@ public interface RSClient extends RSGameEngine, Client @Import("sendGameMessage") void sendGameMessage(int var1, String var2, String var3); + @Override @Import("getObjectDefinition") RSObjectComposition getObjectDefinition(int objectId); @@ -304,4 +305,16 @@ public interface RSClient extends RSGameEngine, Client */ @Import("widgetRoot") int getWidgetRoot(); + + @Import("mapAreaType") + @Override + RSArea[] getMapAreas(); + + @Import("mapscene") + @Override + RSIndexedSprite[] getMapScene(); + + @Import("mapIcons") + @Override + RSSpritePixels[] getMapIcons(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSGameObject.java b/runescape-api/src/main/java/net/runelite/rs/api/RSGameObject.java index 8fdfe1c47f..3595beda6b 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSGameObject.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSGameObject.java @@ -66,6 +66,7 @@ public interface RSGameObject extends GameObject @Override int getHash(); + @Override @Import("flags") int getFlags(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java b/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java new file mode 100644 index 0000000000..b18a753fdf --- /dev/null +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, Adam + * 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.rs.api; + +import net.runelite.api.IndexedSprite; +import net.runelite.mapping.Import; + +public interface RSIndexedSprite extends IndexedSprite +{ + @Import("pixels") + @Override + byte[] getPixels(); + + @Import("palette") + @Override + int[] getPalette(); + + @Import("originalWidth") + @Override + int getOriginalWidth(); + + @Import("height") + @Override + int getHeight(); + + @Import("offsetX") + @Override + int getOffsetX(); + + @Import("offsetY") + @Override + int getOffsetY(); + + @Import("width") + @Override + int getWidth(); +} diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSObjectComposition.java b/runescape-api/src/main/java/net/runelite/rs/api/RSObjectComposition.java index 73aa6a1b7b..82bb7fa939 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSObjectComposition.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSObjectComposition.java @@ -24,13 +24,23 @@ */ package net.runelite.rs.api; +import net.runelite.api.ObjectComposition; import net.runelite.mapping.Import; -public interface RSObjectComposition +public interface RSObjectComposition extends ObjectComposition { @Import("name") + @Override String getName(); @Import("actions") String[] getActions(); + + @Import("mapSceneId") + @Override + int getMapSceneId(); + + @Import("mapIconId") + @Override + int getMapIconId(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWallObject.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWallObject.java index 9c7cd76eff..f68f6715c7 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWallObject.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWallObject.java @@ -48,4 +48,8 @@ public interface RSWallObject extends WallObject @Import("orientationB") @Override int getOrientationB(); + + @Import("config") + @Override + int getConfig(); }