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 c667680326..76bc27cf77 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1665,6 +1665,10 @@ public interface Client extends GameShell */ void setInventoryDragDelay(int delay); + boolean isHdMinimapEnabled(); + + void setHdMinimapEnabled(boolean enabled); + /** * Gets a set of current world types that apply to the logged in world. * diff --git a/runelite-api/src/main/java/net/runelite/api/TileModel.java b/runelite-api/src/main/java/net/runelite/api/TileModel.java index 9dd05d97c2..c6f7fd2876 100644 --- a/runelite-api/src/main/java/net/runelite/api/TileModel.java +++ b/runelite-api/src/main/java/net/runelite/api/TileModel.java @@ -85,4 +85,36 @@ public interface TileModel int getBufferLen(); void setBufferLen(int bufferLen); + + int getUnderlaySwColor(); + + void setUnderlaySwColor(int color); + + int getUnderlaySeColor(); + + void setUnderlaySeColor(int color); + + int getUnderlayNeColor(); + + void setUnderlayNeColor(int color); + + int getUnderlayNwColor(); + + void setUnderlayNwColor(int color); + + int getOverlaySwColor(); + + void setOverlaySwColor(int color); + + int getOverlaySeColor(); + + void setOverlaySeColor(int color); + + int getOverlayNeColor(); + + void setOverlayNeColor(int color); + + int getOverlayNwColor(); + + void setOverlayNwColor(int color); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapConfig.java index c771854645..36e82fb2e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapConfig.java @@ -32,6 +32,17 @@ import net.runelite.client.config.ConfigItem; @ConfigGroup("minimap") public interface MinimapConfig extends Config { + @ConfigItem( + keyName = "hdMinimapEnabled", + name = "HD minimap", + description = "Configures whether to show the minimap in higher detail (relog to see changes)", + position = 1 + ) + default boolean hdMinimapEnabled() + { + return false; + } + @ConfigItem( keyName = "item", name = "Item color", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapPlugin.java index 1df45356d5..134c78db92 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/minimap/MinimapPlugin.java @@ -28,7 +28,6 @@ import com.google.inject.Provides; import java.awt.Color; import java.util.Arrays; import javax.inject.Inject; -import javax.inject.Singleton; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.Sprite; @@ -45,13 +44,10 @@ import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( name = "Minimap", description = "Customize the color of minimap dots", - tags = {"items", "npcs", "players"} + tags = {"items", "npcs", "players", "hd"} ) -@Singleton public class MinimapPlugin extends Plugin { - private static final int NUM_MAPDOTS = 6; - @Inject private Client client; @@ -59,14 +55,7 @@ public class MinimapPlugin extends Plugin private MinimapConfig config; private Sprite[] originalDotSprites; - - private Color itemColor; - private Color npcColor; - private Color playerColor; - private Color friendColor; - private Color teamColor; - private Color clanColor; - private boolean hideMinimap; + private Color[] colors; @Provides private MinimapConfig provideConfig(ConfigManager configManager) @@ -77,11 +66,11 @@ public class MinimapPlugin extends Plugin @Override protected void startUp() { - updateConfig(); - - updateMinimapWidgetVisibility(this.hideMinimap); + updateMinimapWidgetVisibility(config.hideMinimap()); storeOriginalDots(); replaceMapDots(); + + client.setHdMinimapEnabled(config.hdMinimapEnabled()); } @Override @@ -89,6 +78,8 @@ public class MinimapPlugin extends Plugin { updateMinimapWidgetVisibility(false); restoreOriginalDots(); + + client.setHdMinimapEnabled(false); } @Subscribe @@ -109,21 +100,30 @@ public class MinimapPlugin extends Plugin return; } - updateConfig(); + if (event.getKey().equals("hdMinimapEnabled")) + { + client.setHdMinimapEnabled(config.hdMinimapEnabled()); + return; + } if (event.getKey().equals("hideMinimap")) { - updateMinimapWidgetVisibility(this.hideMinimap); + updateMinimapWidgetVisibility(config.hideMinimap()); return; } + if (event.getKey().endsWith("Color")) + { + colors = null; + } + replaceMapDots(); } @Subscribe private void onWidgetHiddenChanged(WidgetHiddenChanged event) { - updateMinimapWidgetVisibility(this.hideMinimap); + updateMinimapWidgetVisibility(config.hideMinimap()); } private void updateMinimapWidgetVisibility(boolean enable) @@ -168,14 +168,18 @@ public class MinimapPlugin extends Plugin private Color[] getColors() { - Color[] colors = new Color[NUM_MAPDOTS]; - colors[0] = this.itemColor; - colors[1] = this.npcColor; - colors[2] = this.playerColor; - colors[3] = this.friendColor; - colors[4] = this.teamColor; - colors[5] = this.clanColor; - + if (colors == null) + { + colors = new Color[] + { + config.itemColor(), + config.npcColor(), + config.playerColor(), + config.friendColor(), + config.teamColor(), + config.clanColor() + }; + } return colors; } @@ -202,15 +206,4 @@ public class MinimapPlugin extends Plugin System.arraycopy(originalDotSprites, 0, mapDots, 0, mapDots.length); } - - private void updateConfig() - { - this.itemColor = config.itemColor(); - this.npcColor = config.npcColor(); - this.playerColor = config.playerColor(); - this.friendColor = config.friendColor(); - this.teamColor = config.teamColor(); - this.clanColor = config.clanColor(); - this.hideMinimap = config.hideMinimap(); - } } \ No newline at end of file diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 88c9654fdd..7c723cdd09 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -53,18 +53,9 @@ import net.runelite.api.IntegerNode; import net.runelite.api.InventoryID; import net.runelite.api.MenuEntry; import net.runelite.api.MenuOpcode; -import static net.runelite.api.MenuOpcode.PLAYER_EIGTH_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_FIFTH_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_FIRST_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_FOURTH_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_SECOND_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_SEVENTH_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_SIXTH_OPTION; -import static net.runelite.api.MenuOpcode.PLAYER_THIRD_OPTION; import net.runelite.api.MessageNode; import net.runelite.api.NPC; import net.runelite.api.Node; -import static net.runelite.api.Perspective.LOCAL_TILE_SIZE; import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.api.Prayer; @@ -135,6 +126,8 @@ import net.runelite.rs.api.RSTileItem; import net.runelite.rs.api.RSUsername; import net.runelite.rs.api.RSWidget; import org.slf4j.Logger; +import static net.runelite.api.MenuOpcode.*; +import static net.runelite.api.Perspective.LOCAL_TILE_SIZE; @Mixin(RSClient.class) public abstract class RSClientMixin implements RSClient @@ -283,6 +276,9 @@ public abstract class RSClientMixin implements RSClient { } + @Inject + private static boolean hdMinimapEnabled; + @Inject @Override public Callbacks getCallbacks() @@ -374,6 +370,20 @@ public abstract class RSClientMixin implements RSClient inventoryDragDelay = delay; } + @Inject + @Override + public boolean isHdMinimapEnabled() + { + return hdMinimapEnabled; + } + + @Inject + @Override + public void setHdMinimapEnabled(boolean enabled) + { + hdMinimapEnabled = enabled; + } + @Inject @Override public AccountType getAccountType() diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSSceneMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSSceneMixin.java index 656e86b4cc..327d945905 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSSceneMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSSceneMixin.java @@ -26,13 +26,14 @@ package net.runelite.mixins; import net.runelite.api.Entity; import net.runelite.api.Perspective; +import net.runelite.api.Tile; import net.runelite.api.TileModel; import net.runelite.api.TilePaint; -import net.runelite.api.Tile; import net.runelite.api.coords.WorldPoint; import net.runelite.api.hooks.DrawCallbacks; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.MethodHook; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Shadow; @@ -40,30 +41,33 @@ import net.runelite.rs.api.RSBoundaryObject; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSFloorDecoration; import net.runelite.rs.api.RSNodeDeque; -import net.runelite.rs.api.RSTileItem; -import net.runelite.rs.api.RSTileItemPile; import net.runelite.rs.api.RSScene; import net.runelite.rs.api.RSTile; +import net.runelite.rs.api.RSTileItem; +import net.runelite.rs.api.RSTileItemPile; import net.runelite.rs.api.RSTileModel; import net.runelite.rs.api.RSWallDecoration; @Mixin(RSScene.class) public abstract class RSSceneMixin implements RSScene { + private static final int INVALID_HSL_COLOR = 12345678; private static final int DEFAULT_DISTANCE = 25; - private static final int MAX_DISTANCE = 90; - private static final int PITCH_LOWER_LIMIT = 128; private static final int PITCH_UPPER_LIMIT = 383; - private static final int MAX_TARGET_DISTANCE = 45; - @Shadow("client") static RSClient client; @Shadow("pitchRelaxEnabled") private static boolean pitchRelaxEnabled; + @Shadow("hdMinimapEnabled") + private static boolean hdMinimapEnabled; + + @Shadow("Rasterizer3D_colorPalette") + private static int[] colorPalette; + @Inject private static int[] tmpX = new int[6]; @@ -630,15 +634,15 @@ public abstract class RSSceneMixin implements RSScene return; } - RSTileModel sceneTileModel = (RSTileModel) tile; + RSTileModel tileModel = (RSTileModel) tile; - final int[] faceX = sceneTileModel.getFaceX(); - final int[] faceY = sceneTileModel.getFaceY(); - final int[] faceZ = sceneTileModel.getFaceZ(); + final int[] faceX = tileModel.getFaceX(); + final int[] faceY = tileModel.getFaceY(); + final int[] faceZ = tileModel.getFaceZ(); - final int[] vertexX = sceneTileModel.getVertexX(); - final int[] vertexY = sceneTileModel.getVertexY(); - final int[] vertexZ = sceneTileModel.getVertexZ(); + final int[] vertexX = tileModel.getVertexX(); + final int[] vertexY = tileModel.getVertexY(); + final int[] vertexZ = tileModel.getVertexZ(); final int vertexCount = vertexX.length; final int faceCount = faceX.length; @@ -714,7 +718,7 @@ public abstract class RSSceneMixin implements RSScene } @Inject - static void setTargetTile(int targetX, int targetY) + private static void setTargetTile(int targetX, int targetY) { client.setSelectedSceneTileX(targetX); client.setSelectedSceneTileY(targetY); @@ -787,4 +791,253 @@ public abstract class RSSceneMixin implements RSScene client.updateItemPile(sceneX, sceneY); } + + @MethodHook(value = "addTile", end = true) + @Inject + public void rl$addTile(int z, int x, int y, int shape, int rotation, int texture, int heightSw, int heightNw, + int heightNe, int heightSe, int underlaySwColor, int underlayNwColor, int underlayNeColor, + int underlaySeColor, int overlaySwColor, int overlayNwColor, int overlayNeColor, + int overlaySeColor, int underlayRgb, int overlayRgb) + { + if (shape != 0 && shape != 1) + { + Tile tile = getTiles()[z][x][y]; + TileModel sceneTileModel = tile.getTileModel(); + + sceneTileModel.setUnderlaySwColor(underlaySwColor); + sceneTileModel.setUnderlayNwColor(underlayNwColor); + sceneTileModel.setUnderlayNeColor(underlayNeColor); + sceneTileModel.setUnderlaySeColor(underlaySeColor); + + sceneTileModel.setOverlaySwColor(overlaySwColor); + sceneTileModel.setOverlayNwColor(overlayNwColor); + sceneTileModel.setOverlayNeColor(overlayNeColor); + sceneTileModel.setOverlaySeColor(overlaySeColor); + } + } + + @Copy("drawTileMinimap") + abstract void rs$drawTile(int[] pixels, int pixelOffset, int width, int z, int x, int y); + + @Replace("drawTileMinimap") + public void rl$drawTile(int[] pixels, int pixelOffset, int width, int z, int x, int y) + { + if (!hdMinimapEnabled) + { + rs$drawTile(pixels, pixelOffset, width, z, x, y); + return; + } + Tile tile = getTiles()[z][x][y]; + if (tile == null) + { + return; + } + TilePaint sceneTilePaint = tile.getTilePaint(); + if (sceneTilePaint != null) + { + int rgb = sceneTilePaint.getRBG(); + if (sceneTilePaint.getSwColor() != INVALID_HSL_COLOR) + { + // hue and saturation + int hs = sceneTilePaint.getSwColor() & ~0x7F; + // I know this looks dumb (and it probably is) but I don't feel like hunting down the problem + int seLightness = sceneTilePaint.getNwColor() & 0x7F; + int neLightness = sceneTilePaint.getNeColor() & 0x7F; + int southDeltaLightness = (sceneTilePaint.getSwColor() & 0x7F) - seLightness; + int northDeltaLightness = (sceneTilePaint.getSeColor() & 0x7F) - neLightness; + seLightness <<= 2; + neLightness <<= 2; + for (int i = 0; i < 4; i++) + { + if (sceneTilePaint.getTexture() == -1) + { + pixels[pixelOffset] = colorPalette[hs | seLightness >> 2]; + pixels[pixelOffset + 1] = colorPalette[hs | seLightness * 3 + neLightness >> 4]; + pixels[pixelOffset + 2] = colorPalette[hs | seLightness + neLightness >> 3]; + pixels[pixelOffset + 3] = colorPalette[hs | seLightness + neLightness * 3 >> 4]; + } + else + { + int lig = 0xFF - ((seLightness >> 1) * (seLightness >> 1) >> 8); + pixels[pixelOffset] = ((rgb & 0xFF00FF) * lig & ~0xFF00FF) + ((rgb & 0xFF00) * lig & 0xFF0000) >> 8; + lig = 0xFF - ((seLightness * 3 + neLightness >> 3) * (seLightness * 3 + neLightness >> 3) >> 8); + pixels[pixelOffset + 1] = ((rgb & 0xFF00FF) * lig & ~0xFF00FF) + ((rgb & 0xFF00) * lig & 0xFF0000) >> 8; + lig = 0xFF - ((seLightness + neLightness >> 2) * (seLightness + neLightness >> 2) >> 8); + pixels[pixelOffset + 2] = ((rgb & 0xFF00FF) * lig & ~0xFF00FF) + ((rgb & 0xFF00) * lig & 0xFF0000) >> 8; + lig = 0xFF - ((seLightness + neLightness * 3 >> 3) * (seLightness + neLightness * 3 >> 3) >> 8); + pixels[pixelOffset + 3] = ((rgb & 0xFF00FF) * lig & ~0xFF00FF) + ((rgb & 0xFF00) * lig & 0xFF0000) >> 8; + } + seLightness += southDeltaLightness; + neLightness += northDeltaLightness; + + pixelOffset += width; + } + } + else if (rgb != 0) + { + for (int i = 0; i < 4; i++) + { + pixels[pixelOffset] = rgb; + pixels[pixelOffset + 1] = rgb; + pixels[pixelOffset + 2] = rgb; + pixels[pixelOffset + 3] = rgb; + pixelOffset += width; + } + } + return; + } + + TileModel sceneTileModel = tile.getTileModel(); + if (sceneTileModel != null) + { + int shape = sceneTileModel.getShape(); + int rotation = sceneTileModel.getRotation(); + int overlayRgb = sceneTileModel.getModelOverlay(); + int underlayRgb = sceneTileModel.getModelUnderlay(); + int[] points = getTileShape2D()[shape]; + int[] indices = getTileRotation2D()[rotation]; + + int shapeOffset = 0; + + if (sceneTileModel.getOverlaySwColor() != INVALID_HSL_COLOR) + { + // hue and saturation + int hs = sceneTileModel.getOverlaySwColor() & ~0x7F; + int seLightness = sceneTileModel.getOverlaySeColor() & 0x7F; + int neLightness = sceneTileModel.getOverlayNeColor() & 0x7F; + int southDeltaLightness = (sceneTileModel.getOverlaySwColor() & 0x7F) - seLightness; + int northDeltaLightness = (sceneTileModel.getOverlayNwColor() & 0x7F) - neLightness; + seLightness <<= 2; + neLightness <<= 2; + for (int i = 0; i < 4; i++) + { + if (sceneTileModel.getTriangleTextureId() == null) + { + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset] = colorPalette[hs | (seLightness >> 2)]; + } + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset + 1] = colorPalette[hs | (seLightness * 3 + neLightness >> 4)]; + } + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset + 2] = colorPalette[hs | (seLightness + neLightness >> 3)]; + } + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset + 3] = colorPalette[hs | (seLightness + neLightness * 3 >> 4)]; + } + } + else + { + if (points[indices[shapeOffset++]] != 0) + { + int lig = 0xFF - ((seLightness >> 1) * (seLightness >> 1) >> 8); + pixels[pixelOffset] = ((overlayRgb & 0xFF00FF) * lig & ~0xFF00FF) + + ((overlayRgb & 0xFF00) * lig & 0xFF0000) >> 8; + } + if (points[indices[shapeOffset++]] != 0) + { + int lig = 0xFF - ((seLightness * 3 + neLightness >> 3) * + (seLightness * 3 + neLightness >> 3) >> 8); + pixels[pixelOffset + 1] = ((overlayRgb & 0xFF00FF) * lig & ~0xFF00FF) + + ((overlayRgb & 0xFF00) * lig & 0xFF0000) >> 8; + } + if (points[indices[shapeOffset++]] != 0) + { + int lig = 0xFF - ((seLightness + neLightness >> 2) * + (seLightness + neLightness >> 2) >> 8); + pixels[pixelOffset + 2] = ((overlayRgb & 0xFF00FF) * lig & ~0xFF00FF) + + ((overlayRgb & 0xFF00) * lig & 0xFF0000) >> 8; + } + if (points[indices[shapeOffset++]] != 0) + { + int lig = 0xFF - ((seLightness + neLightness * 3 >> 3) * + (seLightness + neLightness * 3 >> 3) >> 8); + pixels[pixelOffset + 3] = ((overlayRgb & 0xFF00FF) * lig & ~0xFF00FF) + + ((overlayRgb & 0xFF00) * lig & 0xFF0000) >> 8; + } + } + seLightness += southDeltaLightness; + neLightness += northDeltaLightness; + + pixelOffset += width; + } + if (underlayRgb != 0 && sceneTileModel.getUnderlaySwColor() != INVALID_HSL_COLOR) + { + pixelOffset -= width << 2; + shapeOffset -= 16; + hs = sceneTileModel.getUnderlaySwColor() & ~0x7F; + seLightness = sceneTileModel.getUnderlaySeColor() & 0x7F; + neLightness = sceneTileModel.getUnderlayNeColor() & 0x7F; + southDeltaLightness = (sceneTileModel.getUnderlaySwColor() & 0x7F) - seLightness; + northDeltaLightness = (sceneTileModel.getUnderlayNwColor() & 0x7F) - neLightness; + seLightness <<= 2; + neLightness <<= 2; + for (int i = 0; i < 4; i++) + { + if (points[indices[shapeOffset++]] == 0) + { + pixels[pixelOffset] = colorPalette[hs | (seLightness >> 2)]; + } + if (points[indices[shapeOffset++]] == 0) + { + pixels[pixelOffset + 1] = colorPalette[hs | (seLightness * 3 + neLightness >> 4)]; + } + if (points[indices[shapeOffset++]] == 0) + { + pixels[pixelOffset + 2] = colorPalette[hs | (seLightness + neLightness >> 3)]; + } + if (points[indices[shapeOffset++]] == 0) + { + pixels[pixelOffset + 3] = colorPalette[hs | (seLightness + neLightness * 3 >> 4)]; + } + seLightness += southDeltaLightness; + neLightness += northDeltaLightness; + + pixelOffset += width; + } + } + } + else if (underlayRgb != 0) + { + for (int i = 0; i < 4; i++) + { + pixels[pixelOffset] = points[indices[shapeOffset++]] != 0 ? overlayRgb : underlayRgb; + pixels[pixelOffset + 1] = + points[indices[shapeOffset++]] != 0 ? overlayRgb : underlayRgb; + pixels[pixelOffset + 2] = + points[indices[shapeOffset++]] != 0 ? overlayRgb : underlayRgb; + pixels[pixelOffset + 3] = + points[indices[shapeOffset++]] != 0 ? overlayRgb : underlayRgb; + pixelOffset += width; + } + } + else + { + for (int i = 0; i < 4; i++) + { + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset] = overlayRgb; + } + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset + 1] = overlayRgb; + } + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset + 2] = overlayRgb; + } + if (points[indices[shapeOffset++]] != 0) + { + pixels[pixelOffset + 3] = overlayRgb; + } + pixelOffset += width; + } + } + } + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSSpriteMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSSpriteMixin.java index 80dd042f07..b8070779eb 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSSpriteMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSSpriteMixin.java @@ -1,14 +1,50 @@ +/* + * 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.Color; import java.awt.image.BufferedImage; +import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Inject; 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.RSSprite; @Mixin(RSSprite.class) public abstract class RSSpriteMixin implements RSSprite { + private static final int ALPHA = 0xFF000000; + + @Shadow("client") + private static RSClient client; + + @Shadow("hdMinimapEnabled") + private static boolean hdMinimapEnabled; + @Inject @Override public BufferedImage toBufferedImage() @@ -109,4 +145,84 @@ public abstract class RSSpriteMixin implements RSSprite img.setRGB(0, 0, width, height, newPixels, 0, width); } + + @Copy("drawRotatedMaskedCenteredAround") + abstract void rs$drawAlphaMapped(int x, int y, int width, int height, int xOffset, int yOffset, + int rotation, int zoom, int[] xOffsets, int[] yOffsets); + + @Replace("drawRotatedMaskedCenteredAround") + public void rl$drawAlphaMapped(int x, int y, int width, int height, int xOffset, int yOffset, int rotation, + int zoom, int[] xOffsets, int[] yOffsets) + { + if (!hdMinimapEnabled) + { + rs$drawAlphaMapped(x, y, width, height, xOffset, yOffset, rotation, zoom, xOffsets, yOffsets); + return; + } + try + { + int[] graphicsPixels = client.getGraphicsPixels(); + + int[] spritePixels = getPixels(); + int spriteWidth = getWidth(); + + int centerX = -width / 2; + int centerY = -height / 2; + int rotSin = (int) (Math.sin((double) rotation / 326.11D) * 65536.0D); + int rotCos = (int) (Math.cos((double) rotation / 326.11D) * 65536.0D); + rotSin = rotSin * zoom >> 8; + rotCos = rotCos * zoom >> 8; + int posX = centerY * rotSin + centerX * rotCos + (xOffset << 16); + int posY = centerY * rotCos - centerX * rotSin + (yOffset << 16); + int pixelIndex = x + y * client.getGraphicsPixelsWidth(); + + for (y = 0; y < height; ++y) + { + int spriteOffsetX = xOffsets[y]; + int graphicsPixelIndex = pixelIndex + spriteOffsetX; + int spriteX = posX + rotCos * spriteOffsetX; + int spriteY = posY - rotSin * spriteOffsetX; + + for (x = -yOffsets[y]; x < 0; ++x) + { + // bilinear interpolation + // Thanks to Bubletan + int x1 = spriteX >> 16; + int y1 = spriteY >> 16; + int x2 = x1 + 1; + int y2 = y1 + 1; + int c1 = spritePixels[x1 + y1 * spriteWidth]; + int c2 = spritePixels[x2 + y1 * spriteWidth]; + int c3 = spritePixels[x1 + y2 * spriteWidth]; + int c4 = spritePixels[x2 + y2 * spriteWidth]; + int u1 = (spriteX >> 8) - (x1 << 8); + int v1 = (spriteY >> 8) - (y1 << 8); + int u2 = (x2 << 8) - (spriteX >> 8); + int v2 = (y2 << 8) - (spriteY >> 8); + int a1 = u2 * v2; + int a2 = u1 * v2; + int a3 = u2 * v1; + int a4 = u1 * v1; + int r = (c1 >> 16 & 0xFF) * a1 + (c2 >> 16 & 0xFF) * a2 + + (c3 >> 16 & 0xFF) * a3 + (c4 >> 16 & 0xFF) * a4 & 0xFF0000; + int g = (c1 >> 8 & 0xFF) * a1 + (c2 >> 8 & 0xFF) * a2 + + (c3 >> 8 & 0xFF) * a3 + (c4 >> 8 & 0xFF) * a4 >> 8 & 0xFF00; + int b = (c1 & 0xFF) * a1 + (c2 & 0xFF) * a2 + + (c3 & 0xFF) * a3 + (c4 & 0xFF) * a4 >> 16; + graphicsPixels[graphicsPixelIndex++] = ALPHA | r | g | b; + spriteX += rotCos; + spriteY -= rotSin; + } + + posX += rotSin; + posY += rotCos; + pixelIndex += client.getGraphicsPixelsWidth(); + } + } + catch (Exception e) + { + // ignored + } + + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSTileModelMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSTileModelMixin.java index e22bf131b0..06cc88a4fa 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSTileModelMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSTileModelMixin.java @@ -16,6 +16,30 @@ public abstract class RSTileModelMixin implements RSTileModel @Inject private int rl$modelBufferLen; + @Inject + private int underlaySwColor; + + @Inject + private int underlaySeColor; + + @Inject + private int underlayNeColor; + + @Inject + private int underlayNwColor; + + @Inject + private int overlaySwColor; + + @Inject + private int overlaySeColor; + + @Inject + private int overlayNeColor; + + @Inject + private int overlayNwColor; + @Inject @Override public int getBufferOffset() @@ -57,4 +81,116 @@ public abstract class RSTileModelMixin implements RSTileModel { rl$modelBufferLen = bufferLen; } + + @Inject + @Override + public int getUnderlaySwColor() + { + return underlaySwColor; + } + + @Inject + @Override + public void setUnderlaySwColor(int color) + { + underlaySwColor = color; + } + + @Inject + @Override + public int getUnderlaySeColor() + { + return underlaySeColor; + } + + @Inject + @Override + public void setUnderlaySeColor(int color) + { + underlaySeColor = color; + } + + @Inject + @Override + public int getUnderlayNeColor() + { + return underlayNeColor; + } + + @Inject + @Override + public void setUnderlayNeColor(int color) + { + underlayNeColor = color; + } + + @Inject + @Override + public int getUnderlayNwColor() + { + return underlayNwColor; + } + + @Inject + @Override + public void setUnderlayNwColor(int color) + { + underlayNwColor = color; + } + + @Inject + @Override + public int getOverlaySwColor() + { + return overlaySwColor; + } + + @Inject + @Override + public void setOverlaySwColor(int color) + { + overlaySwColor = color; + } + + @Inject + @Override + public int getOverlaySeColor() + { + return overlaySeColor; + } + + @Inject + @Override + public void setOverlaySeColor(int color) + { + overlaySeColor = color; + } + + @Inject + @Override + public int getOverlayNeColor() + { + return overlayNeColor; + } + + @Inject + @Override + public void setOverlayNeColor(int color) + { + overlayNeColor = color; + } + + @Inject + @Override + public int getOverlayNwColor() + { + return overlayNwColor; + } + + @Inject + @Override + public void setOverlayNwColor(int color) + { + overlayNwColor = color; + } } 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 ef9f3a27d3..518ac112a3 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 @@ -1,18 +1,15 @@ /* - * BSD 2-Clause License - * - * Copyright (c) 2019, ThatGamerBlue + * 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: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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. + * 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 @@ -475,10 +472,6 @@ public interface RSClient extends RSGameShell, Client @Override int getGameCycle(); - // unused - //@Import("packetHandler") - //void packetHandler(); - @Import("Messages_channels") @Override Map getChatLineMap(); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSScene.java b/runescape-api/src/main/java/net/runelite/rs/api/RSScene.java index 73e306a680..84d6d058eb 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSScene.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSScene.java @@ -13,6 +13,12 @@ public interface RSScene extends Scene @Override RSTile[][][] getTiles(); + @Import("tileShape2D") + int[][] getTileShape2D(); + + @Import("tileRotation2D") + int[][] getTileRotation2D(); + @Import("drawTile") void draw(Tile tile, boolean var2);