From e40b1a7b10e0378e948f56deec43b2fbce9ba04f Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 7 May 2019 09:51:18 -0400 Subject: [PATCH 01/43] cooking plugin: rename session to cooking session Co-authored-by: LucasChilders --- .../plugins/cooking/CookingOverlay.java | 4 +-- .../client/plugins/cooking/CookingPlugin.java | 34 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java index 7e25f3ad31..a5af5309d9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java @@ -29,8 +29,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.text.DecimalFormat; -import java.time.Instant; import java.time.Duration; +import java.time.Instant; import javax.inject.Inject; import static net.runelite.api.AnimationID.COOKING_FIRE; import static net.runelite.api.AnimationID.COOKING_RANGE; @@ -72,7 +72,7 @@ class CookingOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { - CookingSession session = plugin.getSession(); + CookingSession session = plugin.getCookingSession(); if (session == null) { return null; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java index 7766438a73..bbcb8ddf02 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java @@ -54,13 +54,13 @@ public class CookingPlugin extends Plugin private CookingConfig config; @Inject - private CookingOverlay overlay; + private CookingOverlay cookingOverlay; @Inject private OverlayManager overlayManager; @Getter(AccessLevel.PACKAGE) - private CookingSession session; + private CookingSession cookingSession; @Provides CookingConfig getConfig(ConfigManager configManager) @@ -71,31 +71,31 @@ public class CookingPlugin extends Plugin @Override protected void startUp() throws Exception { - session = null; - overlayManager.add(overlay); + cookingSession = null; + overlayManager.add(cookingOverlay); } @Override protected void shutDown() throws Exception { - overlayManager.remove(overlay); - session = null; + overlayManager.remove(cookingOverlay); + cookingSession = null; } @Subscribe public void onGameTick(GameTick gameTick) { - if (session == null || config.statTimeout() == 0) + if (cookingSession == null || config.statTimeout() == 0) { return; } Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastCookingAction(), Instant.now()); + Duration sinceCut = Duration.between(cookingSession.getLastCookingAction(), Instant.now()); if (sinceCut.compareTo(statTimeout) >= 0) { - session = null; + cookingSession = null; } } @@ -116,24 +116,24 @@ public class CookingPlugin extends Plugin || message.startsWith("You cook") || message.startsWith("You squeeze the grapes into the jug")) { - if (session == null) + if (cookingSession == null) { - session = new CookingSession(); + cookingSession = new CookingSession(); } - session.updateLastCookingAction(); - session.increaseCookAmount(); + cookingSession.updateLastCookingAction(); + cookingSession.increaseCookAmount(); } else if (message.startsWith("You accidentally burn")) { - if (session == null) + if (cookingSession == null) { - session = new CookingSession(); + cookingSession = new CookingSession(); } - session.updateLastCookingAction(); - session.increaseBurnAmount(); + cookingSession.updateLastCookingAction(); + cookingSession.increaseBurnAmount(); } } } From e6113dc82af8d8697546e1a51ee19d23636f9f19 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 7 May 2019 09:51:43 -0400 Subject: [PATCH 02/43] cooking plugin: add wine ferment timer Co-authored-by: LucasChilders --- .../client/plugins/cooking/CookingConfig.java | 11 ++ .../client/plugins/cooking/CookingPlugin.java | 49 +++++++-- .../plugins/cooking/FermentTimerOverlay.java | 101 ++++++++++++++++++ .../plugins/cooking/FermentTimerSession.java | 40 +++++++ .../plugins/cooking/CookingPluginTest.java | 31 +++++- 5 files changed, 224 insertions(+), 8 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerSession.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java index f8ec60a607..1a1db71368 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java @@ -42,4 +42,15 @@ public interface CookingConfig extends Config { return 5; } + + @ConfigItem( + position = 2, + keyName = "fermentTimer", + name = "Show wine fermenting timer", + description = "Conifgures if the timer before wines are fermented is shown." + ) + default boolean fermentTimer() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java index bbcb8ddf02..93ee8e6412 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java @@ -50,18 +50,26 @@ import net.runelite.client.ui.overlay.OverlayManager; @PluginDependency(XpTrackerPlugin.class) public class CookingPlugin extends Plugin { + private static final String WINE_MESSAGE = "You squeeze the grapes into the jug"; + @Inject private CookingConfig config; @Inject private CookingOverlay cookingOverlay; + @Inject + private FermentTimerOverlay fermentTimerOverlay; + @Inject private OverlayManager overlayManager; @Getter(AccessLevel.PACKAGE) private CookingSession cookingSession; + @Getter(AccessLevel.PACKAGE) + private FermentTimerSession fermentTimerSession; + @Provides CookingConfig getConfig(ConfigManager configManager) { @@ -72,30 +80,47 @@ public class CookingPlugin extends Plugin protected void startUp() throws Exception { cookingSession = null; + fermentTimerSession = null; overlayManager.add(cookingOverlay); + overlayManager.add(fermentTimerOverlay); } @Override protected void shutDown() throws Exception { + overlayManager.remove(fermentTimerOverlay); overlayManager.remove(cookingOverlay); + fermentTimerSession = null; cookingSession = null; } @Subscribe public void onGameTick(GameTick gameTick) { - if (cookingSession == null || config.statTimeout() == 0) + if (config.statTimeout() == 0) { return; } - Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(cookingSession.getLastCookingAction(), Instant.now()); - - if (sinceCut.compareTo(statTimeout) >= 0) + if (cookingSession != null) { - cookingSession = null; + Duration statTimeout = Duration.ofMinutes(config.statTimeout()); + Duration sinceCut = Duration.between(cookingSession.getLastCookingAction(), Instant.now()); + + if (sinceCut.compareTo(statTimeout) >= 0) + { + cookingSession = null; + } + } + if (fermentTimerSession != null) + { + Duration statTimeout = Duration.ofMinutes(config.statTimeout()); + Duration sinceCut = Duration.between(fermentTimerSession.getLastWineMakingAction(), Instant.now()); + + if (sinceCut.compareTo(statTimeout) >= 0) + { + fermentTimerSession = null; + } } } @@ -109,12 +134,22 @@ public class CookingPlugin extends Plugin final String message = event.getMessage(); + if (message.startsWith(WINE_MESSAGE) && config.fermentTimer()) + { + if (fermentTimerSession == null) + { + fermentTimerSession = new FermentTimerSession(); + } + + fermentTimerSession.updateLastWineMakingAction(); + } + if (message.startsWith("You successfully cook") || message.startsWith("You successfully bake") || message.startsWith("You manage to cook") || message.startsWith("You roast a") || message.startsWith("You cook") - || message.startsWith("You squeeze the grapes into the jug")) + || message.startsWith(WINE_MESSAGE)) { if (cookingSession == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerOverlay.java new file mode 100644 index 0000000000..3ec1783bb0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerOverlay.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019, Lucas C + * 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.client.plugins.cooking; + +import com.google.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.time.Duration; +import java.time.Instant; +import lombok.extern.slf4j.Slf4j; +import static net.runelite.api.AnimationID.COOKING_WINE; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +@Slf4j +class FermentTimerOverlay extends Overlay +{ + private static final int INITIAL_TIME = 12; + + private final Client client; + private final CookingPlugin plugin; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + private FermentTimerOverlay(final Client client, final CookingPlugin plugin) + { + super(plugin); + setPosition(OverlayPosition.TOP_LEFT); + this.client = client; + this.plugin = plugin; + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Fermenting Timer overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + FermentTimerSession session = plugin.getFermentTimerSession(); + if (session == null) + { + return null; + } + + panelComponent.getChildren().clear(); + + if (isMakingWine() || Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds() < INITIAL_TIME) + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("Making Wine") + .color(Color.GREEN) + .build()); + panelComponent.getChildren().add(LineComponent.builder() + .left("Ferments in: ") + .right(String.valueOf(INITIAL_TIME - Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds())) + .build()); + } + else + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("Wine Fermented") + .color(Color.ORANGE) + .build()); + } + + return panelComponent.render(graphics); + } + + private boolean isMakingWine() + { + return (client.getLocalPlayer().getAnimation() == COOKING_WINE); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerSession.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerSession.java new file mode 100644 index 0000000000..1e6520d091 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/FermentTimerSession.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, Lucas C + * 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.client.plugins.cooking; + +import java.time.Instant; +import lombok.AccessLevel; +import lombok.Getter; + +class FermentTimerSession +{ + @Getter(AccessLevel.PACKAGE) + private Instant lastWineMakingAction; + + void updateLastWineMakingAction() + { + this.lastWineMakingAction = Instant.now(); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cooking/CookingPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cooking/CookingPluginTest.java index ae6418ee05..067c02943c 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/cooking/CookingPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/cooking/CookingPluginTest.java @@ -33,6 +33,9 @@ import net.runelite.api.events.ChatMessage; import net.runelite.client.ui.overlay.OverlayManager; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.when; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -64,6 +67,10 @@ public class CookingPluginTest @Bind CookingOverlay cookingOverlay; + @Mock + @Bind + FermentTimerOverlay fermentTimerOverlay; + @Mock @Bind OverlayManager overlayManager; @@ -83,8 +90,30 @@ public class CookingPluginTest cookingPlugin.onChatMessage(chatMessage); } - CookingSession cookingSession = cookingPlugin.getSession(); + CookingSession cookingSession = cookingPlugin.getCookingSession(); assertNotNull(cookingSession); assertEquals(COOKING_MESSAGES.length, cookingSession.getCookAmount()); } + + @Test + public void testFermentTimerOnChatMessage() + { + when(config.fermentTimer()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", COOKING_MESSAGES[6], "", 0); + cookingPlugin.onChatMessage(chatMessage); + FermentTimerSession fermentTimerSession = cookingPlugin.getFermentTimerSession(); + + assertNotNull(fermentTimerSession); + } + + @Test + public void testFermentTimerOnChatMessage_pluginDisabled() + { + when(config.fermentTimer()).thenReturn(false); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", COOKING_MESSAGES[6], "", 0); + cookingPlugin.onChatMessage(chatMessage); + FermentTimerSession fermentTimerSession = cookingPlugin.getFermentTimerSession(); + + assertNull(fermentTimerSession); + } } \ No newline at end of file From c1b0ca4ffdf95e6e6979cdf2058b4522530f742a Mon Sep 17 00:00:00 2001 From: Macweese <50101641+Macweese@users.noreply.github.com> Date: Tue, 7 May 2019 16:53:54 +0200 Subject: [PATCH 03/43] agility shortcuts: fix north Arceuus Dense essence mine shortcut --- .../src/main/java/net/runelite/client/game/AgilityShortcut.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java index 33cbdb1510..4a0312485c 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java @@ -165,7 +165,7 @@ public enum AgilityShortcut YANILLE_DUNGEON_RUBBLE_CLIMB(67, "Pile of Rubble", null, PILE_OF_RUBBLE_23563, PILE_OF_RUBBLE_23564), ELVEN_OVERPASS_MEDIUM_CLIFF(68, "Rocks", new WorldPoint(2337, 3288, 0), ROCKS_16514, ROCKS_16515), WEISS_OBSTACLES(68, "Shortcut", null, LITTLE_BOULDER, ROCKSLIDE_33184, ROCKSLIDE_33185, NULL_33327, NULL_33328, LEDGE_33190, ROCKSLIDE_33191, FALLEN_TREE_33192), - ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1759, 3873, 0), ROCKS_27984, ROCKS_27985), + ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1761, 3873, 0), ROCKS_34741), TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509), TAVERLEY_DUNGEON_ROCKS_NORTH(70, "Rocks", new WorldPoint(2887, 9823, 0), ROCKS, ROCKS_14106), TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106), From b996175b70a49be19a36abaf606b1d9197b1b2af Mon Sep 17 00:00:00 2001 From: xdesr <49791189+xdesr@users.noreply.github.com> Date: Tue, 7 May 2019 16:53:10 +0100 Subject: [PATCH 04/43] widget item overlay: add seed vault inventory --- .../src/main/java/net/runelite/api/widgets/WidgetID.java | 1 + .../net/runelite/client/ui/overlay/WidgetItemOverlay.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index ed593ca11a..c450620abd 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -133,6 +133,7 @@ public class WidgetID public static final int BARROWS_PUZZLE_GROUP_ID = 25; public static final int KEPT_ON_DEATH_GROUP_ID = 4; public static final int GUIDE_PRICE_GROUP_ID = 464; + public static final int SEED_VAULT_INVENTORY_GROUP_ID = 630; static class WorldMap { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java index 9cf6f39217..3d8f1ab2e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java @@ -41,6 +41,7 @@ import static net.runelite.api.widgets.WidgetID.EQUIPMENT_INVENTORY_GROUP_ID; import static net.runelite.api.widgets.WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID; import static net.runelite.api.widgets.WidgetID.GUIDE_PRICES_INVENTORY_GROUP_ID; import static net.runelite.api.widgets.WidgetID.INVENTORY_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.SEED_VAULT_INVENTORY_GROUP_ID; import static net.runelite.api.widgets.WidgetID.SHOP_INVENTORY_GROUP_ID; import static net.runelite.api.widgets.WidgetInfo.TO_GROUP; import net.runelite.api.widgets.WidgetItem; @@ -92,7 +93,8 @@ public abstract class WidgetItemOverlay extends Overlay GRAND_EXCHANGE_INVENTORY_GROUP_ID, GUIDE_PRICES_INVENTORY_GROUP_ID, EQUIPMENT_INVENTORY_GROUP_ID, - INVENTORY_GROUP_ID); + INVENTORY_GROUP_ID, + SEED_VAULT_INVENTORY_GROUP_ID); } protected void showOnBank() From 3c48ee2d491fe4bef1c8468280362721d16372f4 Mon Sep 17 00:00:00 2001 From: Lotto Date: Mon, 6 May 2019 19:57:32 +0200 Subject: [PATCH 05/43] ba: use equipment ItemContainer instead of PlayerComposition Makes equipment querying consistent across the client by changing the Barbarian Assault plugin to use the equipment ItemContainer instead of the local player's PlayerComposition. --- .../BarbarianAssaultPlugin.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java index 985ef626f5..ba2069498b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java @@ -31,13 +31,15 @@ import java.awt.Image; import javax.inject.Inject; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; import net.runelite.api.ItemID; import net.runelite.api.Varbits; import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.GameTick; +import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.kit.KitType; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; @@ -145,14 +147,27 @@ public class BarbarianAssaultPlugin extends Plugin } @Subscribe - public void onGameTick(GameTick event) + public void onItemContainerChanged(final ItemContainerChanged event) { - if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null) + if (event.getItemContainer() != client.getItemContainer(InventoryID.EQUIPMENT)) { return; } - switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE)) + if (overlay.getCurrentRound() != null) + { + return; + } + + final Item[] items = event.getItemContainer().getItems(); + + // Check that the local player is wearing enough items to be wearing a cape. + if (items == null || items.length <= EquipmentInventorySlot.CAPE.getSlotIdx()) + { + return; + } + + switch (items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId()) { case ItemID.ATTACKER_ICON: overlay.setCurrentRound(new Round(Role.ATTACKER)); From c76b86b88d445222232660d4f07cf6ed6b565993 Mon Sep 17 00:00:00 2001 From: xDemoN Date: Tue, 7 May 2019 18:18:50 -0400 Subject: [PATCH 06/43] idlenotifier: add plank-make from the lunar spellbook --- runelite-api/src/main/java/net/runelite/api/AnimationID.java | 1 + .../runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java | 1 + 2 files changed, 2 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index 591a778366..7aa4a7f8a3 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -176,6 +176,7 @@ public final class AnimationID public static final int MAGIC_LUNAR_SHARED = 4413; // Utilized by Fertile Soil, Boost/Stat Potion Share, NPC Contact, Bake Pie public static final int MAGIC_LUNAR_CURE_PLANT = 4432; public static final int MAGIC_LUNAR_GEOMANCY = 7118; + public static final int MAGIC_LUNAR_PLANK_MAKE = 6298; public static final int MAGIC_LUNAR_STRING_JEWELRY = 4412; // Arceuus spellbook diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 5dc0ca9459..129f7a26e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -204,6 +204,7 @@ public class IdleNotifierPlugin extends Plugin case HERBLORE_MAKE_TAR: /* Magic */ case MAGIC_CHARGING_ORBS: + case MAGIC_LUNAR_PLANK_MAKE: case MAGIC_LUNAR_STRING_JEWELRY: case MAGIC_MAKE_TABLET: case MAGIC_ENCHANTING_JEWELRY: From 31c2d5301108e6d59cb1e0ec8fe3c9fb9c7546c5 Mon Sep 17 00:00:00 2001 From: Alec Mikell Date: Tue, 7 May 2019 18:53:28 -0400 Subject: [PATCH 07/43] Fix Hot/Cold Misthalin Location Spelling Error Nort-east -> North-east --- .../plugins/cluescrolls/clues/hotcold/HotColdLocation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java index e659fca397..cd700835a0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java @@ -118,7 +118,7 @@ public enum HotColdLocation MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."), MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."), MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."), - MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "Nort-east of Gertrude's house west of Varrock."), + MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock."), MISTHALIN_DRAYNOR_BANK(new WorldPoint(3096, 3235, 0), MISTHALIN, "South of Draynor Village bank."), MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf."), MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins."), From ca377c719604f1ef396052eb17be2cf62ca0a5cd Mon Sep 17 00:00:00 2001 From: Lotto Date: Wed, 8 May 2019 00:42:55 +0200 Subject: [PATCH 08/43] xp tracker: display >1m exp with thousandths precision --- .../client/plugins/xptracker/XpInfoBox.java | 2 +- .../runelite/client/util/StackFormatter.java | 34 ++++++++++++++++++- .../client/util/StackFormatterTest.java | 25 ++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java index f6e4e77f27..4aac706e4f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java @@ -266,7 +266,7 @@ class XpInfoBox extends JPanel static String htmlLabel(String key, int value) { - String valueStr = StackFormatter.quantityToRSDecimalStack(value); + String valueStr = StackFormatter.quantityToRSDecimalStack(value, true); return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java index 40dda01a4e..c9282f7f46 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java +++ b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java @@ -61,6 +61,14 @@ public class StackFormatter DecimalFormatSymbols.getInstance(Locale.ENGLISH) ); + /** + * A more precise decimal number formatter, outputting thousandths + */ + private static final NumberFormat PRECISE_DECIMAL_FORMATTER = new DecimalFormat( + "#,###.###", + DecimalFormatSymbols.getInstance(Locale.ENGLISH) + ); + /** * Convert a quantity to a nicely formatted stack size. * See the StackFormatterTest to see expected output. @@ -152,6 +160,24 @@ public class StackFormatter * with K after 100,000 and M after 10,000,000 */ public static String quantityToRSDecimalStack(int quantity) + { + return quantityToRSDecimalStack(quantity, false); + } + + /** + * Convert a quantity to stack size as it would + * appear in RuneScape. (with decimals) + *

+ * This differs from quantityToRSStack in that it displays + * decimals. Ex: 27100 is 27.1k (not 27k) + *

+ * + * @param quantity The quantity to convert. + * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. + * @return The stack size as it would appear in RS, with decimals, + * with K after 100,000 and M after 10,000,000 + */ + public static String quantityToRSDecimalStack(int quantity, boolean precise) { String quantityStr = String.valueOf(quantity); if (quantityStr.length() <= 4) @@ -160,7 +186,13 @@ public class StackFormatter } int power = (int) Math.log10(quantity); - return DECIMAL_FORMATTER.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3]; + + // Output thousandths for values above a million + NumberFormat format = precise && power >= 6 + ? PRECISE_DECIMAL_FORMATTER + : DECIMAL_FORMATTER; + + return format.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3]; } /** diff --git a/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java b/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java index 53a1c963d1..1e297a8513 100644 --- a/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java +++ b/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java @@ -97,6 +97,31 @@ public class StackFormatterTest assertEquals("-400B", StackFormatter.quantityToStackSize(-400_000_000_000L)); } + @Test + public void quantityToPreciseStackSize() + { + assertEquals("0", StackFormatter.quantityToRSDecimalStack(0)); + assertEquals("8500", StackFormatter.quantityToRSDecimalStack(8_500, true)); + assertEquals("10K", StackFormatter.quantityToRSDecimalStack(10_000, true)); + assertEquals("21.7K", StackFormatter.quantityToRSDecimalStack(21_710, true)); + assertEquals("100K", StackFormatter.quantityToRSDecimalStack(100_000, true)); + assertEquals("100.3K", StackFormatter.quantityToRSDecimalStack(100_310, true)); + assertEquals("1M", StackFormatter.quantityToRSDecimalStack(1_000_000, true)); + assertEquals("8.45M", StackFormatter.quantityToRSDecimalStack(8_450_000, true)); + assertEquals("8.451M", StackFormatter.quantityToRSDecimalStack(8_451_000, true)); + assertEquals("10M", StackFormatter.quantityToRSDecimalStack(10_000_000, true)); + assertEquals("12.8M", StackFormatter.quantityToRSDecimalStack(12_800_000, true)); + assertEquals("12.85M", StackFormatter.quantityToRSDecimalStack(12_850_000, true)); + assertEquals("12.851M", StackFormatter.quantityToRSDecimalStack(12_851_000, true)); + assertEquals("100M", StackFormatter.quantityToRSDecimalStack(100_000_000, true)); + assertEquals("250.1M", StackFormatter.quantityToRSDecimalStack(250_100_000, true)); + assertEquals("250.151M", StackFormatter.quantityToRSDecimalStack(250_151_000, true)); + assertEquals("1B", StackFormatter.quantityToRSDecimalStack(1_000_000_000, true)); + assertEquals("1.5B", StackFormatter.quantityToRSDecimalStack(1500_000_000, true)); + assertEquals("1.55B", StackFormatter.quantityToRSDecimalStack(1550_000_000, true)); + assertEquals("2.147B", StackFormatter.quantityToRSDecimalStack(Integer.MAX_VALUE, true)); + } + @Test public void stackSizeToQuantity() throws ParseException { From cd192087ccb71aa1b0a743c201d059d2d7a76828 Mon Sep 17 00:00:00 2001 From: Brandon White Date: Thu, 9 May 2019 00:37:36 -0400 Subject: [PATCH 09/43] blast furance plugin: add foreman fee timer For players that are utilizing the blast furnace and require to pay the foreman fee every 10 minutes, this will assist in tracking the time remaining before the next fee payment is required. Co-authored-by: Adam --- .../blastfurnace/BlastFurnacePlugin.java | 52 +++++++++++++++++++ .../plugins/blastfurnace/ForemanTimer.java | 42 +++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/ForemanTimer.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnacePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnacePlugin.java index af39f8912b..15d602a324 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnacePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnacePlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Seth + * Copyright (c) 2019, Brandon White * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,21 +26,31 @@ package net.runelite.client.plugins.blastfurnace; import com.google.inject.Provides; +import java.time.Duration; +import java.time.Instant; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; +import net.runelite.api.Client; import net.runelite.api.GameObject; import net.runelite.api.GameState; import static net.runelite.api.NullObjectID.NULL_9092; import static net.runelite.api.ObjectID.CONVEYOR_BELT; +import net.runelite.api.Skill; import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.Text; @PluginDescriptor( name = "Blast Furnace", @@ -49,6 +60,7 @@ import net.runelite.client.ui.overlay.OverlayManager; public class BlastFurnacePlugin extends Plugin { private static final int BAR_DISPENSER = NULL_9092; + private static final String FOREMAN_PERMISSION_TEXT = "Okay, you can use the furnace for ten minutes. Remember, you only need half as much coal as with a regular furnace."; @Getter(AccessLevel.PACKAGE) private GameObject conveyorBelt; @@ -56,6 +68,8 @@ public class BlastFurnacePlugin extends Plugin @Getter(AccessLevel.PACKAGE) private GameObject barDispenser; + private ForemanTimer foremanTimer; + @Inject private OverlayManager overlayManager; @@ -68,6 +82,15 @@ public class BlastFurnacePlugin extends Plugin @Inject private BlastFurnaceClickBoxOverlay clickBoxOverlay; + @Inject + private Client client; + + @Inject + private ItemManager itemManager; + + @Inject + private InfoBoxManager infoBoxManager; + @Override protected void startUp() throws Exception { @@ -79,11 +102,13 @@ public class BlastFurnacePlugin extends Plugin @Override protected void shutDown() { + infoBoxManager.removeIf(ForemanTimer.class::isInstance); overlayManager.remove(overlay); overlayManager.remove(cofferOverlay); overlayManager.remove(clickBoxOverlay); conveyorBelt = null; barDispenser = null; + foremanTimer = null; } @Provides @@ -135,4 +160,31 @@ public class BlastFurnacePlugin extends Plugin barDispenser = null; } } + + @Subscribe + public void onGameTick(GameTick event) + { + Widget npcDialog = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT); + if (npcDialog == null) + { + return; + } + + // blocking dialog check until 5 minutes needed to avoid re-adding while dialog message still displayed + boolean shouldCheckForemanFee = client.getRealSkillLevel(Skill.SMITHING) < 60 + && (foremanTimer == null || Duration.between(Instant.now(), foremanTimer.getEndTime()).toMinutes() <= 5); + + if (shouldCheckForemanFee) + { + String npcText = Text.sanitizeMultilineText(npcDialog.getText()); + + if (npcText.equals(FOREMAN_PERMISSION_TEXT)) + { + infoBoxManager.removeIf(ForemanTimer.class::isInstance); + + foremanTimer = new ForemanTimer(this, itemManager); + infoBoxManager.addInfoBox(foremanTimer); + } + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/ForemanTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/ForemanTimer.java new file mode 100644 index 0000000000..0a246b690c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/ForemanTimer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, Brandon White + * 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.client.plugins.blastfurnace; + +import java.time.temporal.ChronoUnit; +import net.runelite.api.ItemID; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.infobox.Timer; + +class ForemanTimer extends Timer +{ + private static final String TOOLTIP_TEXT = "Foreman Fee"; + + ForemanTimer(BlastFurnacePlugin plugin, ItemManager itemManager) + { + super(10, ChronoUnit.MINUTES, itemManager.getImage(ItemID.COAL_BAG), plugin); + + setTooltip(TOOLTIP_TEXT); + } +} \ No newline at end of file From 85e787c8dd76fe9f7fb00c4ad670f14607c199fa Mon Sep 17 00:00:00 2001 From: John Kryspin Date: Thu, 9 May 2019 19:34:00 -0400 Subject: [PATCH 10/43] fishing plugin: fix trawler timer with one tick left --- .../net/runelite/client/plugins/fishing/FishingPlugin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java index d27886c1aa..2f55bf8158 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java @@ -396,6 +396,11 @@ public class FishingPlugin extends Plugin } long timeLeft = TRAWLER_TIME_LIMIT_IN_SECONDS - Duration.between(trawlerStartTime, Instant.now()).getSeconds(); + if (timeLeft < 0) + { + timeLeft = 0; + } + int minutes = (int) timeLeft / 60; int seconds = (int) timeLeft % 60; From a92095b878c2ad24a476b39acd95d808f0f01f3e Mon Sep 17 00:00:00 2001 From: xdesr <49791189+xdesr@users.noreply.github.com> Date: Fri, 10 May 2019 13:16:44 +0100 Subject: [PATCH 11/43] Remove gray pixel from Dragon Scimitar cursor (#8725) --- .../customcursor/cursor-dragon-scimitar.png | Bin 570 -> 343 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/customcursor/cursor-dragon-scimitar.png b/runelite-client/src/main/resources/net/runelite/client/plugins/customcursor/cursor-dragon-scimitar.png index 1db7d1a0bc53d1e155c225adc800ad90ba3c51bb..b1a4bd230cac5b1b36fb65f26f1c254f766ace8e 100644 GIT binary patch delta 232 zcmVUY;AkBBTnbZmG^{QFkkajZovH?qvVIH%H>&R ibf&`R!VANH5W*XTYXy(6V+Uve0000(0r%1acITJ%W507^>757#dm_ z7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10A}YWq#1%+S)CsTOR&zfV$Yd-D@(X5g zcy=QV#7XjYcaeR~TsRTP;VkfoEC$jiz&QEW^R*zsvI56+Agut#?Z4*C1v1unx;Tbt zoUfgHlIf5FkIO_)rFB=Mx^MrlU*7V{RdPo`MWmWA$7%^HcEhqA46NoQZYws$VtlMF4J1$q2Jk?DU_qkqq#{9v* z{)x}qSI_!v?4RM&dcIYB*MEf;^F}AuzTM6R9-=^(tCqM%l%yn}$cBg+s2Ln~7gD+4oa0|P4qgHOlvK!JhKkei>9nO2EgL-VX_=Ybj+JYD@<);T3K F0RR;fpfUge From 637d305ceb992558f00923899c9e806dda126b3b Mon Sep 17 00:00:00 2001 From: Lotto Date: Sat, 11 May 2019 16:16:38 +0200 Subject: [PATCH 12/43] ui: add SplitComponent SplitComponent is a component containing two other components, with the area split between the two, either horizontally or vertically. Co-authored-by: Jasper Ketelaar --- .../blastfurnace/BlastFurnaceOverlay.java | 3 +- .../blastmine/BlastMineOreCountOverlay.java | 3 +- .../plugins/cerberus/CerberusOverlay.java | 3 +- .../InventoryViewerOverlay.java | 3 +- .../plugins/teamcapes/TeamCapesOverlay.java | 3 +- .../components/ComponentOrientation.java | 31 ++++++ .../ui/overlay/components/PanelComponent.java | 8 +- .../ui/overlay/components/SplitComponent.java | 105 ++++++++++++++++++ .../ui/overlay/infobox/InfoBoxOverlay.java | 5 +- 9 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ComponentOrientation.java create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceOverlay.java index d57fd53fc9..48253cdfe3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceOverlay.java @@ -35,6 +35,7 @@ import net.runelite.client.ui.overlay.Overlay; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -54,7 +55,7 @@ class BlastFurnaceOverlay extends Overlay this.plugin = plugin; this.client = client; setPosition(OverlayPosition.TOP_LEFT); - imagePanelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + imagePanelComponent.setOrientation(ComponentOrientation.HORIZONTAL); getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Blast furnace overlay")); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java index d4566f89c8..f660eb2b63 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java @@ -39,6 +39,7 @@ import net.runelite.client.ui.overlay.Overlay; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -57,7 +58,7 @@ class BlastMineOreCountOverlay extends Overlay this.client = client; this.config = config; this.itemManager = itemManager; - panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + panelComponent.setOrientation(ComponentOrientation.HORIZONTAL); getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Blast mine overlay")); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java index 5ddbf21f7a..2f384fcd80 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java @@ -31,6 +31,7 @@ import javax.inject.Singleton; import net.runelite.client.game.SkillIconManager; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -47,7 +48,7 @@ public class CerberusOverlay extends Overlay this.plugin = plugin; this.iconManager = iconManager; setPosition(OverlayPosition.BOTTOM_RIGHT); - panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + panelComponent.setOrientation(ComponentOrientation.HORIZONTAL); } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java index 71da3492aa..7162be5290 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java @@ -37,6 +37,7 @@ import net.runelite.api.ItemContainer; import net.runelite.client.game.ItemManager; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -58,7 +59,7 @@ class InventoryViewerOverlay extends Overlay setPosition(OverlayPosition.BOTTOM_RIGHT); panelComponent.setWrapping(4); panelComponent.setGap(new Point(6, 4)); - panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + panelComponent.setOrientation(ComponentOrientation.HORIZONTAL); this.itemManager = itemManager; this.client = client; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java index b5cc7858bf..9dbd2dc861 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java @@ -36,6 +36,7 @@ import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -55,7 +56,7 @@ public class TeamCapesOverlay extends Overlay this.plugin = plugin; this.config = config; this.manager = manager; - panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + panelComponent.setOrientation(ComponentOrientation.HORIZONTAL); panelComponent.setWrapping(4); getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Teamcapes overlay")); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ComponentOrientation.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ComponentOrientation.java new file mode 100644 index 0000000000..e06875e970 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ComponentOrientation.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, Jasper Ketelaar + * 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.client.ui.overlay.components; + +public enum ComponentOrientation +{ + HORIZONTAL, + VERTICAL +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java index 5ea81f2006..6baf20985e 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java @@ -37,12 +37,6 @@ import lombok.Setter; public class PanelComponent implements LayoutableRenderableEntity { - public enum Orientation - { - HORIZONTAL, - VERTICAL; - } - @Getter private final Rectangle bounds = new Rectangle(); @@ -60,7 +54,7 @@ public class PanelComponent implements LayoutableRenderableEntity private final List children = new ArrayList<>(); @Setter - private Orientation orientation = Orientation.VERTICAL; + private ComponentOrientation orientation = ComponentOrientation.VERTICAL; @Setter private int wrapping = -1; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java new file mode 100644 index 0000000000..2e77a7dde2 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018, Jasper Ketelaar + * 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.client.ui.overlay.components; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Builder +public class SplitComponent implements LayoutableRenderableEntity +{ + private LayoutableRenderableEntity first; + private LayoutableRenderableEntity second; + + @Builder.Default + private Point preferredLocation = new Point(); + + @Builder.Default + private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); + + @Builder.Default + private ComponentOrientation orientation = ComponentOrientation.VERTICAL; + + @Builder.Default + private Point gap = new Point(0, 0); + + @Builder.Default + @Getter + private final Rectangle bounds = new Rectangle(); + + @Override + public Dimension render(Graphics2D graphics) + { + graphics.translate(preferredLocation.x, preferredLocation.y); + first.setPreferredSize(preferredSize); + first.setPreferredLocation(new Point(0, 0)); + + final Dimension firstDimension = first.render(graphics); + int x = 0, y = 0; + + if (orientation == ComponentOrientation.VERTICAL) + { + y = firstDimension.height + gap.y; + } + else + { + x = firstDimension.width + gap.x; + } + + second.setPreferredLocation(new Point(x, y)); + // Make the second component fit to whatever size is left after the first component is rendered + second.setPreferredSize(new Dimension(preferredSize.width - x, preferredSize.height - y)); + + // The total width/height need to be determined as they are now always the same as the + // individual width/height (for example image width/height will just be the height of the image + // and not the height of the area the image is in + final Dimension secondDimension = second.render(graphics); + int totalWidth, totalHeight; + + if (orientation == ComponentOrientation.VERTICAL) + { + totalWidth = Math.max(firstDimension.width, secondDimension.width); + totalHeight = y + secondDimension.height; + } + else + { + totalHeight = Math.max(firstDimension.height, secondDimension.height); + totalWidth = x + secondDimension.width; + } + + graphics.translate(-preferredLocation.x, -preferredLocation.y); + + final Dimension dimension = new Dimension(totalWidth, totalHeight); + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); + return dimension; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java index 58f20aae63..08412783f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java @@ -38,6 +38,7 @@ import net.runelite.api.Client; import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.InfoBoxComponent; import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -84,8 +85,8 @@ public class InfoBoxOverlay extends Overlay panelComponent.getChildren().clear(); panelComponent.setWrapping(config.infoBoxWrap()); panelComponent.setOrientation(config.infoBoxVertical() - ? PanelComponent.Orientation.VERTICAL - : PanelComponent.Orientation.HORIZONTAL); + ? ComponentOrientation.VERTICAL + : ComponentOrientation.HORIZONTAL); panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize())); for (InfoBox box : infoBoxes) From 9a0d783bf9b8ae08f5d8a2d2e6836d610e27b91e Mon Sep 17 00:00:00 2001 From: Stephen Zhu Date: Mon, 15 Apr 2019 12:55:42 -0400 Subject: [PATCH 13/43] client: add smelting plugin Co-authored-by: Adam --- .../plugins/smelting/SmeltingConfig.java | 44 ++++++ .../plugins/smelting/SmeltingOverlay.java | 135 ++++++++++++++++++ .../plugins/smelting/SmeltingPlugin.java | 125 ++++++++++++++++ .../plugins/smelting/SmeltingSession.java | 53 +++++++ .../plugins/smelting/SmeltingPluginTest.java | 90 ++++++++++++ 5 files changed, 447 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingSession.java create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java new file mode 100644 index 0000000000..9671f29e1a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019, Stephen + * 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.client.plugins.smelting; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("smelting") +public interface SmeltingConfig extends Config +{ + @ConfigItem( + position = 1, + keyName = "statTimeout", + name = "Reset stats (minutes)", + description = "The time it takes for the current smelting session to be reset" + ) + default int statTimeout() + { + return 5; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java new file mode 100644 index 0000000000..7a49c00144 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019, Stephen + * 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.client.plugins.smelting; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.time.Duration; +import java.time.Instant; +import javax.inject.Inject; +import static net.runelite.api.AnimationID.SMITHING_CANNONBALL; +import static net.runelite.api.AnimationID.SMITHING_SMELTING; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.api.Skill; +import net.runelite.client.plugins.xptracker.XpTrackerService; +import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +class SmeltingOverlay extends Overlay +{ + private static final int SMELT_TIMEOUT = 5; + + private final Client client; + private final SmeltingPlugin plugin; + private final XpTrackerService xpTrackerService; + + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + SmeltingOverlay(Client client, SmeltingPlugin plugin, XpTrackerService xpTrackerService) + { + super(plugin); + this.client = client; + this.plugin = plugin; + this.xpTrackerService = xpTrackerService; + setPosition(OverlayPosition.TOP_LEFT); + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Smelting overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + SmeltingSession session = plugin.getSession(); + if (session == null) + { + return null; + } + + panelComponent.getChildren().clear(); + + if (isSmelting() || Duration.between(session.getLastItemSmelted(), Instant.now()).getSeconds() < SMELT_TIMEOUT) + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("Smelting") + .color(Color.GREEN) + .build()); + } + else + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("NOT smelting") + .color(Color.RED) + .build()); + } + + int actions = xpTrackerService.getActions(Skill.SMITHING); + if (actions > 0) + { + if (plugin.getSession().getBarsSmelted() > 0) + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Bars:") + .right(Integer.toString(session.getBarsSmelted())) + .build()); + } + if (plugin.getSession().getCannonBallsSmelted() > 0) + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Cannonballs:") + .right(Integer.toString(session.getCannonBallsSmelted())) + .build()); + } + if (actions > 2) + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Actions/hr:") + .right(Integer.toString(xpTrackerService.getActionsHr(Skill.SMITHING))) + .build()); + } + } + + return panelComponent.render(graphics); + + } + + private boolean isSmelting() + { + switch (client.getLocalPlayer().getAnimation()) + { + case SMITHING_SMELTING: + case SMITHING_CANNONBALL: + return true; + default: + return false; + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingPlugin.java new file mode 100644 index 0000000000..21a3b5440b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingPlugin.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019, Stephen + * 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.client.plugins.smelting; + +import com.google.inject.Provides; +import java.time.Duration; +import java.time.Instant; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.ChatMessageType; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDependency; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.xptracker.XpTrackerPlugin; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Smelting", + description = "Show Smelting stats", + tags = {"overlay", "skilling"} +) +@PluginDependency(XpTrackerPlugin.class) +public class SmeltingPlugin extends Plugin +{ + @Inject + private SmeltingConfig config; + + @Inject + private SmeltingOverlay overlay; + + @Inject + private OverlayManager overlayManager; + + @Getter(AccessLevel.PACKAGE) + private SmeltingSession session; + + @Provides + SmeltingConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(SmeltingConfig.class); + } + + @Override + protected void startUp() + { + session = null; + overlayManager.add(overlay); + } + + @Override + protected void shutDown() + { + overlayManager.remove(overlay); + session = null; + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (event.getType() != ChatMessageType.SPAM) + { + return; + } + + if (event.getMessage().startsWith("You retrieve a bar of")) + { + if (session == null) + { + session = new SmeltingSession(); + } + session.increaseBarsSmelted(); + } + else if (event.getMessage().startsWith("You remove the cannonballs from the mould")) + { + if (session == null) + { + session = new SmeltingSession(); + } + session.increaseCannonBallsSmelted(); + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (session != null) + { + final Duration statTimeout = Duration.ofMinutes(config.statTimeout()); + final Duration sinceCaught = Duration.between(session.getLastItemSmelted(), Instant.now()); + + if (sinceCaught.compareTo(statTimeout) >= 0) + { + session = null; + } + } + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingSession.java b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingSession.java new file mode 100644 index 0000000000..b49cfff6c0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingSession.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, Stephen + * 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.client.plugins.smelting; + +import java.time.Instant; +import lombok.AccessLevel; +import lombok.Getter; + +class SmeltingSession +{ + @Getter(AccessLevel.PACKAGE) + private int barsSmelted; + + @Getter(AccessLevel.PACKAGE) + private int cannonBallsSmelted; + + @Getter(AccessLevel.PACKAGE) + private Instant lastItemSmelted; + + void increaseBarsSmelted() + { + barsSmelted++; + lastItemSmelted = Instant.now(); + } + + void increaseCannonBallsSmelted() + { + cannonBallsSmelted += 4; + lastItemSmelted = Instant.now(); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java new file mode 100644 index 0000000000..1c8573f26c --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019, Stephen + * 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.client.plugins.smelting; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.events.ChatMessage; +import net.runelite.client.ui.overlay.OverlayManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SmeltingPluginTest +{ + private static final String SMELT_CANNONBALL = "You remove the cannonballs from the mould"; + private static final String SMELT_BAR = "You retrieve a bar of steel."; + + @Inject + SmeltingPlugin smeltingPlugin; + + @Mock + @Bind + SmeltingConfig config; + + @Mock + @Bind + SmeltingOverlay smeltingOverlay; + + @Mock + @Bind + OverlayManager overlayManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testCannonballs() + { + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", SMELT_CANNONBALL, "", 0); + smeltingPlugin.onChatMessage(chatMessage); + + SmeltingSession smeltingSession = smeltingPlugin.getSession(); + assertNotNull(smeltingSession); + assertEquals(4, smeltingSession.getCannonBallsSmelted()); + } + + @Test + public void testBars() + { + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", SMELT_BAR, "", 0); + smeltingPlugin.onChatMessage(chatMessage); + + SmeltingSession smeltingSession = smeltingPlugin.getSession(); + assertNotNull(smeltingSession); + assertEquals(1, smeltingSession.getBarsSmelted()); + } +} From 9623ed4b3068534d152cc17d1b2aedb2c9c561eb Mon Sep 17 00:00:00 2001 From: seandewar <6256228+seandewar@users.noreply.github.com> Date: Fri, 10 May 2019 18:46:02 +0100 Subject: [PATCH 14/43] constants: add GAME_TICK_LENGTH and use where needed Also update many usages of 20ms to CLIENT_TICK_LENGTH --- .../src/main/java/net/runelite/api/Constants.java | 8 ++++++++ .../src/main/java/net/runelite/client/callback/Hooks.java | 3 ++- .../runelite/client/plugins/antidrag/AntiDragConfig.java | 3 ++- .../client/plugins/barbarianassault/GameTimer.java | 3 ++- .../runelite/client/plugins/barbarianassault/Round.java | 3 ++- .../net/runelite/client/plugins/boosts/BoostsPlugin.java | 3 ++- .../client/plugins/idlenotifier/IdleNotifierPlugin.java | 6 ++++-- .../client/plugins/npchighlight/NpcSceneOverlay.java | 6 ++---- .../java/net/runelite/client/plugins/poh/PohPlugin.java | 7 ++++--- .../runelite/client/plugins/prayer/PrayerDoseOverlay.java | 3 ++- .../net/runelite/client/plugins/prayer/PrayerPlugin.java | 3 ++- .../client/plugins/runenergy/RunEnergyPlugin.java | 5 +++-- 12 files changed, 35 insertions(+), 18 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Constants.java b/runelite-api/src/main/java/net/runelite/api/Constants.java index b1cfde8dde..ffb2c1ba66 100644 --- a/runelite-api/src/main/java/net/runelite/api/Constants.java +++ b/runelite-api/src/main/java/net/runelite/api/Constants.java @@ -89,4 +89,12 @@ public class Constants * the maximum framerate of 50 fps. */ public static final int CLIENT_TICK_LENGTH = 20; + + /** + * The number of milliseconds in a server game tick. + *

+ * This is the length of a single game cycle under ideal conditions. + * All game-play actions operate within multiples of this duration. + */ + public static final int GAME_TICK_LENGTH = 600; } diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index fea751ffcf..12de2c567b 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -42,6 +42,7 @@ import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.BufferProvider; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.MainBufferProvider; import net.runelite.api.NullItemID; import net.runelite.api.RenderOverview; @@ -79,7 +80,7 @@ import net.runelite.client.util.DeferredEventBus; @Slf4j public class Hooks implements Callbacks { - private static final long CHECK = 600; // ms - how often to run checks + private static final long CHECK = Constants.GAME_TICK_LENGTH; // ms - how often to run checks private static final Injector injector = RuneLite.getInjector(); private static final Client client = injector.getInstance(Client.class); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java index 1bed02603e..01767c5b4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.antidrag; +import net.runelite.api.Constants; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @@ -39,6 +40,6 @@ public interface AntiDragConfig extends Config ) default int dragDelay() { - return 600 / 20; // one game tick + return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java index 6ed8c4957c..1aae11adbd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java @@ -28,6 +28,7 @@ import java.time.Duration; import java.time.Instant; import java.time.LocalTime; import java.time.format.DateTimeFormatter; +import net.runelite.api.Constants; class GameTimer { @@ -45,7 +46,7 @@ class GameTimer } else { - elapsed = Duration.between(startTime, now).minusMillis(600); + elapsed = Duration.between(startTime, now).minusMillis(Constants.GAME_TICK_LENGTH); } return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds())); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java index 7da563d9cd..4428d504b4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java @@ -29,6 +29,7 @@ import java.time.Instant; import javax.inject.Inject; import lombok.Getter; import lombok.Setter; +import net.runelite.api.Constants; class Round { @@ -52,7 +53,7 @@ class Round public Round(Role role) { this.roundRole = role; - this.roundStartTime = Instant.now().plusMillis(1200); + this.roundStartTime = Instant.now().plusMillis(2 * Constants.GAME_TICK_LENGTH); } public long getRoundTime() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java index 4f09b12a8b..1962320efb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java @@ -33,6 +33,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import lombok.Getter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.Prayer; import net.runelite.api.Skill; import net.runelite.api.events.BoostedLevelChanged; @@ -372,6 +373,6 @@ public class BoostsPlugin extends Plugin int getChangeTime(final int time) { final long diff = System.currentTimeMillis() - lastTickMillis; - return time != -1 ? (int)(time * 0.6 - (diff / 1000d)) : time; + return time != -1 ? (int)((time * Constants.GAME_TICK_LENGTH - diff) / 1000d) : time; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 129f7a26e9..bb7dee8b47 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -35,6 +35,7 @@ import net.runelite.api.Actor; import net.runelite.api.AnimationID; import static net.runelite.api.AnimationID.*; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.GameState; import net.runelite.api.GraphicID; import net.runelite.api.Hitsplat; @@ -64,9 +65,10 @@ import net.runelite.client.plugins.PluginDescriptor; public class IdleNotifierPlugin extends Plugin { // This must be more than 500 client ticks (10 seconds) before you get AFK kicked - private static final int LOGOUT_WARNING_CLIENT_TICKS = ((4 * 60) + 40) * 50;// 4 minutes and 40 seconds + private static final int LOGOUT_WARNING_MILLIS = (4 * 60 + 40) * 1000; // 4 minutes and 40 seconds private static final int COMBAT_WARNING_MILLIS = 19 * 60 * 1000; // 19 minutes - private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / 20; + private static final int LOGOUT_WARNING_CLIENT_TICKS = LOGOUT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH; + private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH; private static final int HIGHEST_MONSTER_ATTACK_SPEED = 8; // Except Scarab Mage, but they are with other monsters private static final Duration SIX_HOUR_LOGOUT_WARNING_AFTER_DURATION = Duration.ofMinutes(340); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index 6c41b2f24d..9e87b3f278 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -36,6 +36,7 @@ import java.time.Instant; import java.util.Locale; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.NPC; import net.runelite.api.NPCComposition; import net.runelite.api.Perspective; @@ -54,9 +55,6 @@ public class NpcSceneOverlay extends Overlay // a dark background private static final Color TEXT_COLOR = Color.WHITE; - // Estimated time of a game tick in seconds - private static final double ESTIMATED_TICK_LENGTH = 0.6; - private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US); static @@ -123,7 +121,7 @@ public class NpcSceneOverlay extends Overlay } final Instant now = Instant.now(); - final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * ESTIMATED_TICK_LENGTH; + final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * (Constants.GAME_TICK_LENGTH / 1000.0); final double sinceLast = (now.toEpochMilli() - plugin.getLastTickUpdate().toEpochMilli()) / 1000.0; final double timeLeft = Math.max(0.0, baseTick - sinceLast); final String timeLeftStr = TIME_LEFT_FORMATTER.format(timeLeft); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java index 03a3f02729..04df91d05c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java @@ -39,6 +39,7 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Actor; import net.runelite.api.AnimationID; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.GameState; @@ -74,7 +75,6 @@ public class PohPlugin extends Plugin { static final Set BURNER_UNLIT = Sets.newHashSet(ObjectID.INCENSE_BURNER, ObjectID.INCENSE_BURNER_13210, ObjectID.INCENSE_BURNER_13212); static final Set BURNER_LIT = Sets.newHashSet(ObjectID.INCENSE_BURNER_13209, ObjectID.INCENSE_BURNER_13211, ObjectID.INCENSE_BURNER_13213); - private static final double ESTIMATED_TICK_LENGTH = 0.6; @Getter(AccessLevel.PACKAGE) private final Map pohObjects = new HashMap<>(); @@ -243,7 +243,8 @@ public class PohPlugin extends Plugin private static void updateBurner(IncenseBurner incenseBurner, int fmLevel) { - incenseBurner.setCountdownTimer((200 + fmLevel) * ESTIMATED_TICK_LENGTH); - incenseBurner.setRandomTimer(fmLevel * ESTIMATED_TICK_LENGTH); + final double tickLengthSeconds = Constants.GAME_TICK_LENGTH / 1000.0; + incenseBurner.setCountdownTimer((200 + fmLevel) * tickLengthSeconds); + incenseBurner.setRandomTimer(fmLevel * tickLengthSeconds); } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java index 6798d4e545..ab1d91fb16 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java @@ -35,6 +35,7 @@ import javax.inject.Inject; import lombok.AccessLevel; import lombok.Setter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.Point; import net.runelite.api.Prayer; import net.runelite.api.Skill; @@ -50,7 +51,7 @@ import org.apache.commons.lang3.StringUtils; class PrayerDoseOverlay extends Overlay { - private static final float PULSE_TIME = 1200f; + private static final float PULSE_TIME = 2f * Constants.GAME_TICK_LENGTH; private static final Color START_COLOR = new Color(0, 255, 255); private static final Color END_COLOR = new Color(0, 92, 92); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java index 04b7ec194c..2755703f8f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java @@ -32,6 +32,7 @@ import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; @@ -268,7 +269,7 @@ public class PrayerPlugin extends Plugin { long timeSinceLastTick = Duration.between(startOfLastTick, Instant.now()).toMillis(); - float tickProgress = (timeSinceLastTick % 600) / 600f; + float tickProgress = (timeSinceLastTick % Constants.GAME_TICK_LENGTH) / (float) Constants.GAME_TICK_LENGTH; return tickProgress * Math.PI; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java index 7cef60a826..fff84a100d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.InventoryID; import net.runelite.api.Item; @@ -171,7 +172,7 @@ public class RunEnergyPlugin extends Plugin String getEstimatedRunTimeRemaining(boolean inSeconds) { - // Calculate the amount of energy lost every 2 ticks (0.6 seconds). + // Calculate the amount of energy lost every tick. // Negative weight has the same depletion effect as 0 kg. final int effectiveWeight = Math.max(client.getWeight(), 0); double lossRate = (Math.min(effectiveWeight, 64) / 100.0) + 0.64; @@ -182,7 +183,7 @@ public class RunEnergyPlugin extends Plugin } // Calculate the number of seconds left - final double secondsLeft = (client.getEnergy() * 0.6) / lossRate; + final double secondsLeft = (client.getEnergy() * Constants.GAME_TICK_LENGTH) / (lossRate * 1000.0); // Return the text if (inSeconds) From a8728b9b566e330c3b75aaca9ba142c1bd0ef85e Mon Sep 17 00:00:00 2001 From: seandewar <6256228+seandewar@users.noreply.github.com> Date: Wed, 8 May 2019 04:11:25 +0100 Subject: [PATCH 15/43] regenmeter: add option to notify before next hp regen --- .../plugins/regenmeter/RegenMeterConfig.java | 10 ++++++++ .../plugins/regenmeter/RegenMeterPlugin.java | 23 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java index b3b4dd546c..2e8b577381 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java @@ -57,4 +57,14 @@ public interface RegenMeterConfig extends Config { return false; } + + @ConfigItem( + keyName = "notifyBeforeHpRegenDuration", + name = "Hitpoint Regen Notification (seconds)", + description = "Notify approximately when your next hitpoint is about to regen. A value of 0 will disable notification." + ) + default int getNotifyBeforeHpRegenSeconds() + { + return 0; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java index 8620b7fac3..004441b6e3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2018 Abex + * Copyright (c) 2019, Sean Dewar + * Copyright (c) 2018, Abex * Copyright (c) 2018, Zimaya * Copyright (c) 2017, Adam * All rights reserved. @@ -30,6 +31,7 @@ import com.google.inject.Provides; import javax.inject.Inject; import lombok.Getter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.GameState; import net.runelite.api.Prayer; import net.runelite.api.Skill; @@ -37,6 +39,7 @@ import net.runelite.api.VarPlayer; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.VarbitChanged; +import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; @@ -46,7 +49,7 @@ import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( name = "Regeneration Meter", description = "Track and show the hitpoints and special attack regeneration timers", - tags = {"combat", "health", "hitpoints", "special", "attack", "overlay"} + tags = {"combat", "health", "hitpoints", "special", "attack", "overlay", "notifications"} ) public class RegenMeterPlugin extends Plugin { @@ -59,6 +62,9 @@ public class RegenMeterPlugin extends Plugin @Inject private OverlayManager overlayManager; + @Inject + private Notifier notifier; + @Inject private RegenMeterOverlay overlay; @@ -149,5 +155,18 @@ public class RegenMeterPlugin extends Plugin // Show it going down hitpointsPercentage = 1 - hitpointsPercentage; } + + if (config.getNotifyBeforeHpRegenSeconds() > 0 && currentHP < maxHP && shouldNotifyHpRegenThisTick(ticksPerHPRegen)) + { + notifier.notify("[" + client.getLocalPlayer().getName() + "] regenerates their next hitpoint soon!"); + } + } + + private boolean shouldNotifyHpRegenThisTick(int ticksPerHPRegen) + { + // if the configured duration lies between two ticks, choose the earlier tick + final int ticksBeforeHPRegen = ticksPerHPRegen - ticksSinceHPRegen; + final int notifyTick = (int) Math.ceil(config.getNotifyBeforeHpRegenSeconds() * 1000d / Constants.GAME_TICK_LENGTH); + return ticksBeforeHPRegen == notifyTick; } } From 1bfffb7c9d400aa809353754c1f246e7262cad18 Mon Sep 17 00:00:00 2001 From: Ryan H Date: Fri, 3 May 2019 20:25:28 -0400 Subject: [PATCH 16/43] barrows plugin: add prayer drain timer --- .../client/plugins/barrows/BarrowsConfig.java | 11 +++ .../client/plugins/barrows/BarrowsPlugin.java | 55 +++++++++++++ .../barrows/BarrowsPrayerDrainTimer.java | 77 +++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java index 41f2bbc67d..663e03fbb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java @@ -97,4 +97,15 @@ public interface BarrowsConfig extends Config { return true; } + + @ConfigItem( + keyName = "showPrayerDrainTimer", + name = "Show Prayer Drain Timer", + description = "Configure whether or not a countdown until the next prayer drain is displayed", + position = 6 + ) + default boolean showPrayerDrainTimer() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java index bc505755ff..72bf08fe7e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java @@ -42,6 +42,7 @@ import net.runelite.api.ItemContainer; import net.runelite.api.NullObjectID; import net.runelite.api.ObjectID; import net.runelite.api.WallObject; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameObjectChanged; import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectSpawned; @@ -60,9 +61,11 @@ import net.runelite.client.chat.QueuedMessage; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.StackFormatter; @PluginDescriptor( @@ -89,12 +92,16 @@ public class BarrowsPlugin extends Plugin WidgetInfo.BARROWS_PUZZLE_ANSWER3 ); + private static final int CRYPT_REGION_ID = 14231; + @Getter(AccessLevel.PACKAGE) private final Set walls = new HashSet<>(); @Getter(AccessLevel.PACKAGE) private final Set ladders = new HashSet<>(); + private boolean wasInCrypt = false; + @Getter private Widget puzzleAnswer; @@ -113,6 +120,12 @@ public class BarrowsPlugin extends Plugin @Inject private ItemManager itemManager; + @Inject + private SpriteManager spriteManager; + + @Inject + private InfoBoxManager infoBoxManager; + @Inject private ChatMessageManager chatMessageManager; @@ -140,6 +153,8 @@ public class BarrowsPlugin extends Plugin walls.clear(); ladders.clear(); puzzleAnswer = null; + wasInCrypt = false; + stopPrayerDrainTimer(); // Restore widgets final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL); @@ -155,6 +170,15 @@ public class BarrowsPlugin extends Plugin } } + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("barrows") && !config.showPrayerDrainTimer()) + { + stopPrayerDrainTimer(); + } + } + @Subscribe public void onWallObjectSpawned(WallObjectSpawned event) { @@ -220,11 +244,24 @@ public class BarrowsPlugin extends Plugin { if (event.getGameState() == GameState.LOADING) { + wasInCrypt = isInCrypt(); // on region changes the tiles get set to null walls.clear(); ladders.clear(); puzzleAnswer = null; } + else if (event.getGameState() == GameState.LOGGED_IN) + { + boolean isInCrypt = isInCrypt(); + if (wasInCrypt && !isInCrypt) + { + stopPrayerDrainTimer(); + } + else if (!wasInCrypt && isInCrypt) + { + startPrayerDrainTimer(); + } + } } @Subscribe @@ -271,4 +308,22 @@ public class BarrowsPlugin extends Plugin } } } + + private void startPrayerDrainTimer() + { + if (config.showPrayerDrainTimer()) + { + infoBoxManager.addInfoBox(new BarrowsPrayerDrainTimer(this, spriteManager)); + } + } + + private void stopPrayerDrainTimer() + { + infoBoxManager.removeIf(BarrowsPrayerDrainTimer.class::isInstance); + } + + private boolean isInCrypt() + { + return client.getLocalPlayer().getWorldLocation().getRegionID() == CRYPT_REGION_ID; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java new file mode 100644 index 0000000000..4428a54f07 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Ryan + * 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.client.plugins.barrows; + +import java.awt.Color; +import java.time.Duration; +import java.time.Instant; +import net.runelite.api.SpriteID; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.ui.overlay.infobox.InfoBox; +import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; + +class BarrowsPrayerDrainTimer extends InfoBox +{ + private static final long PRAYER_DRAIN_INTERVAL_MS = 18200; + + private final Instant startTime; + + BarrowsPrayerDrainTimer(BarrowsPlugin plugin, SpriteManager spriteManager) + { + super(spriteManager.getSprite(SpriteID.TAB_PRAYER, 0), plugin); + setPriority(InfoBoxPriority.MED); + setTooltip("Prayer Drain"); + startTime = Instant.now(); + } + + @Override + public String getText() + { + Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime()); + int seconds = (int) (timeLeft.toMillis() / 1000L); + return String.format("0:%02d", seconds); + } + + @Override + public Color getTextColor() + { + Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime()); + + //check if timer has 10% of time left + if (timeLeft.getSeconds() < (PRAYER_DRAIN_INTERVAL_MS / 1000 * .10)) + { + return Color.RED.brighter(); + } + + return Color.WHITE; + } + + private Instant getNextPrayerDrainTime() + { + Duration timePassed = Duration.between(startTime, Instant.now()); + // Get how many intervals have passed so far and add one more to find the next prayer drain time + return startTime.plusMillis((timePassed.toMillis() / PRAYER_DRAIN_INTERVAL_MS + 1) * PRAYER_DRAIN_INTERVAL_MS); + } +} From d1c692e72e5ed15c4c8c380559f9e3c2df162d1d Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 11 May 2019 14:46:45 -0700 Subject: [PATCH 17/43] western diary: Fix elf pickpocket quest requirement The requirement for pickpocketing an elf is to have started Mourning's End Part I for access to Lletya, not to have completed Mourning's End Part II. Fixes runelite/runelite#8806 --- .../achievementdiary/diaries/WesternDiaryRequirement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/WesternDiaryRequirement.java b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/WesternDiaryRequirement.java index ee67f45132..b136f889fe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/WesternDiaryRequirement.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/WesternDiaryRequirement.java @@ -140,6 +140,6 @@ public class WesternDiaryRequirement extends GenericDiaryRequirement new QuestRequirement(Quest.BIG_CHOMPY_BIRD_HUNTING)); add("Pickpocket an Elf.", new SkillRequirement(Skill.THIEVING, 85), - new QuestRequirement(Quest.MOURNINGS_ENDS_PART_II)); + new QuestRequirement(Quest.MOURNINGS_ENDS_PART_I, true)); } } From 78bf68e03639bd0f7be733e9ae794f3bfe6c68eb Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 May 2019 19:56:47 -0400 Subject: [PATCH 18/43] chat: ensure queued messages are always cleared after adding Mark queued message type as non null because addChatMessage will throw if it is. This was causing the client to get stuck trying to add the same broken message each loop. --- .../net/runelite/client/chat/ChatMessageManager.java | 10 ++++++++-- .../java/net/runelite/client/chat/QueuedMessage.java | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java index bc0d3bc58a..da4c222fd6 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java @@ -548,8 +548,14 @@ public class ChatMessageManager { if (!queuedMessages.isEmpty()) { - queuedMessages.forEach(this::add); - queuedMessages.clear(); + try + { + queuedMessages.forEach(this::add); + } + finally + { + queuedMessages.clear(); + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java b/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java index 9c88826af7..f89ce84b43 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java @@ -26,12 +26,14 @@ package net.runelite.client.chat; import lombok.Builder; import lombok.Data; +import lombok.NonNull; import net.runelite.api.ChatMessageType; @Data @Builder public class QueuedMessage { + @NonNull private final ChatMessageType type; private final String value; private String name; From 6165bfabdff33be84e24df9477212a132db9b618 Mon Sep 17 00:00:00 2001 From: Lotto Date: Tue, 7 May 2019 01:07:26 +0200 Subject: [PATCH 19/43] xp tracker: show on canvas Co-authored-by: Jasper Ketelaar --- .../client/plugins/xptracker/XpInfoBox.java | 20 +++ .../plugins/xptracker/XpInfoBoxOverlay.java | 129 ++++++++++++++++++ .../plugins/xptracker/XpTrackerPlugin.java | 30 +++- .../ui/overlay/components/SplitComponent.java | 7 +- 4 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java index f6e4e77f27..7846807341 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java @@ -67,6 +67,9 @@ class XpInfoBox extends JPanel private static final String HTML_LABEL_TEMPLATE = "%s%s"; + private static final String REMOVE_STATE = "Remove from canvas"; + private static final String ADD_STATE = "Add to canvas"; + // Instance members private final JPanel panel; @@ -89,6 +92,7 @@ class XpInfoBox extends JPanel private final JLabel expLeft = new JLabel(); private final JLabel actionsLeft = new JLabel(); private final JMenuItem pauseSkill = new JMenuItem("Pause"); + private final JMenuItem canvasItem = new JMenuItem(ADD_STATE); private final XpTrackerConfig xpTrackerConfig; @@ -128,6 +132,21 @@ class XpInfoBox extends JPanel popupMenu.add(reset); popupMenu.add(resetOthers); popupMenu.add(pauseSkill); + popupMenu.add(canvasItem); + + canvasItem.addActionListener(e -> + { + if (canvasItem.getText().equals(REMOVE_STATE)) + { + xpTrackerPlugin.removeOverlay(skill); + canvasItem.setText(ADD_STATE); + } + else + { + xpTrackerPlugin.addOverlay(skill); + canvasItem.setText(REMOVE_STATE); + } + }); JLabel skillIcon = new JLabel(new ImageIcon(iconManager.getSkillImage(skill))); skillIcon.setHorizontalAlignment(SwingConstants.CENTER); @@ -177,6 +196,7 @@ class XpInfoBox extends JPanel void reset() { + canvasItem.setText(ADD_STATE); container.remove(statsPanel); panel.remove(this); panel.revalidate(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java new file mode 100644 index 0000000000..99c5880901 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018, Jasper Ketelaar + * 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.client.plugins.xptracker; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.Skill; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.components.ComponentOrientation; +import net.runelite.client.ui.overlay.components.ImageComponent; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.ProgressBarComponent; +import net.runelite.client.ui.overlay.components.SplitComponent; +import net.runelite.client.util.StackFormatter; + +class XpInfoBoxOverlay extends Overlay +{ + private static final int PANEL_PREFERRED_WIDTH = 150; + private static final int BORDER_SIZE = 2; + private static final int XP_AND_PROGRESS_BAR_GAP = 2; + private static final int XP_AND_ICON_GAP = 4; + private static final Rectangle XP_AND_ICON_COMPONENT_BORDER = new Rectangle(2, 1, 4, 0); + + private final PanelComponent panel = new PanelComponent(); + private final PanelComponent iconXpSplitPanel = new PanelComponent(); + private final XpTrackerPlugin plugin; + + @Getter(AccessLevel.PACKAGE) + private final Skill skill; + private final BufferedImage icon; + + XpInfoBoxOverlay( + XpTrackerPlugin plugin, + Skill skill, + BufferedImage icon) + { + super(plugin); + this.plugin = plugin; + this.skill = skill; + this.icon = icon; + panel.setBorder(new Rectangle(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + panel.setGap(new Point(0, XP_AND_PROGRESS_BAR_GAP)); + panel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0)); + iconXpSplitPanel.setBorder(XP_AND_ICON_COMPONENT_BORDER); + iconXpSplitPanel.setBackgroundColor(null); + iconXpSplitPanel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0)); + } + + @Override + public Dimension render(Graphics2D graphics) + { + panel.getChildren().clear(); + iconXpSplitPanel.getChildren().clear(); + + //Setting the font to rs small font so that the overlay isn't huge + graphics.setFont(FontManager.getRunescapeSmallFont()); + + final XpSnapshotSingle snapshot = plugin.getSkillSnapshot(skill); + + final LineComponent xpLine = LineComponent.builder() + .left("XP Gained:") + .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpGainedInSession())) + .build(); + + final LineComponent xpHour = LineComponent.builder() + .left("XP/Hour:") + .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour())) + .build(); + + final SplitComponent xpSplit = SplitComponent.builder() + .first(xpLine) + .second(xpHour) + .orientation(ComponentOrientation.VERTICAL) + .build(); + + final ImageComponent imageComponent = new ImageComponent(icon); + final SplitComponent iconXpSplit = SplitComponent.builder() + .first(imageComponent) + .second(xpSplit) + .orientation(ComponentOrientation.HORIZONTAL) + .gap(new Point(XP_AND_ICON_GAP, 0)) + .build(); + + iconXpSplitPanel.getChildren().add(iconXpSplit); + + final ProgressBarComponent progressBarComponent = new ProgressBarComponent(); + progressBarComponent.setValue(snapshot.getSkillProgressToGoal()); + + panel.getChildren().add(iconXpSplitPanel); + panel.getChildren().add(progressBarComponent); + + return panel.render(graphics); + } + + @Override + public String getName() + { + return super.getName() + skill.getName(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index a8d65962a5..8f08b0ba7b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -59,6 +59,7 @@ import static net.runelite.client.plugins.xptracker.XpWorldType.NORMAL; import net.runelite.client.task.Schedule; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.ImageUtil; import net.runelite.http.api.xp.XpClient; @@ -98,6 +99,9 @@ public class XpTrackerPlugin extends Plugin @Inject private NPCManager npcManager; + @Inject + private OverlayManager overlayManager; + private NavigationButton navButton; private XpPanel xpPanel; private XpWorldType lastWorldType; @@ -142,6 +146,7 @@ public class XpTrackerPlugin extends Plugin @Override protected void shutDown() throws Exception { + overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay); xpState.reset(); clientToolbar.removeNavigation(navButton); } @@ -208,6 +213,27 @@ public class XpTrackerPlugin extends Plugin return xpType; } + /** + * Adds an overlay to the canvas for tracking a specific skill. + * + * @param skill the skill for which the overlay should be added + */ + void addOverlay(Skill skill) + { + removeOverlay(skill); + overlayManager.add(new XpInfoBoxOverlay(this, skill, skillIconManager.getSkillImage(skill))); + } + + /** + * Removes an overlay from the overlayManager if it's present. + * + * @param skill the skill for which the overlay should be removed. + */ + void removeOverlay(Skill skill) + { + overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay && ((XpInfoBoxOverlay) e).getSkill() == skill); + } + /** * Reset internal state and re-initialize all skills with XP currently cached by the RS client * This is called by the user manually clicking resetSkillState in the UI. @@ -230,6 +256,7 @@ public class XpTrackerPlugin extends Plugin } xpState.initializeSkill(skill, currentXp); + removeOverlay(skill); } } @@ -242,6 +269,7 @@ public class XpTrackerPlugin extends Plugin xpState.reset(); xpPanel.resetAllInfoBoxes(); xpPanel.updateTotal(new XpSnapshotSingle.XpSnapshotSingleBuilder().build()); + overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay); } /** @@ -254,6 +282,7 @@ public class XpTrackerPlugin extends Plugin int currentXp = client.getSkillExperience(skill); xpState.resetSkill(skill, currentXp); xpPanel.resetSkill(skill); + removeOverlay(skill); } /** @@ -272,7 +301,6 @@ public class XpTrackerPlugin extends Plugin } } - @Subscribe public void onExperienceChanged(ExperienceChanged event) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java index 2e77a7dde2..75ab98f137 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/SplitComponent.java @@ -58,9 +58,8 @@ public class SplitComponent implements LayoutableRenderableEntity @Override public Dimension render(Graphics2D graphics) { - graphics.translate(preferredLocation.x, preferredLocation.y); + first.setPreferredLocation(preferredLocation); first.setPreferredSize(preferredSize); - first.setPreferredLocation(new Point(0, 0)); final Dimension firstDimension = first.render(graphics); int x = 0, y = 0; @@ -74,7 +73,7 @@ public class SplitComponent implements LayoutableRenderableEntity x = firstDimension.width + gap.x; } - second.setPreferredLocation(new Point(x, y)); + second.setPreferredLocation(new Point(x + preferredLocation.x, y + preferredLocation.y)); // Make the second component fit to whatever size is left after the first component is rendered second.setPreferredSize(new Dimension(preferredSize.width - x, preferredSize.height - y)); @@ -95,8 +94,6 @@ public class SplitComponent implements LayoutableRenderableEntity totalWidth = x + secondDimension.width; } - graphics.translate(-preferredLocation.x, -preferredLocation.y); - final Dimension dimension = new Dimension(totalWidth, totalHeight); bounds.setLocation(preferredLocation); bounds.setSize(dimension); From e18652f517e0f49d6a7b6d98875eacd9e1e783e0 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 May 2019 19:59:11 -0400 Subject: [PATCH 20/43] party plugin: add partyinfo debug command --- .../client/plugins/party/PartyPlugin.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java index b824f17157..2d7bddc3a6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.UUID; import javax.annotation.Nullable; import javax.inject.Inject; +import javax.inject.Named; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; @@ -48,6 +49,7 @@ import net.runelite.api.Skill; import net.runelite.api.SoundEffectID; import net.runelite.api.Tile; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.MenuOptionClicked; @@ -120,6 +122,10 @@ public class PartyPlugin extends Plugin implements KeyListener @Inject private ChatMessageManager chatMessageManager; + @Inject + @Named("developerMode") + boolean developerMode; + @Getter private final Map partyDataMap = Collections.synchronizedMap(new HashMap<>()); @@ -448,6 +454,23 @@ public class PartyPlugin extends Plugin implements KeyListener worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance); } + @Subscribe + public void onCommandExecuted(CommandExecuted commandExecuted) + { + if (!developerMode || !commandExecuted.getCommand().equals("partyinfo")) + { + return; + } + + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Party " + party.getPartyId()).build()); + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local Party " + party.getLocalPartyId()).build()); + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local ID " + party.getLocalMember().getMemberId()).build()); + for (PartyMember partyMember : party.getMembers()) + { + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value(" " + partyMember.getName() + " " + partyMember.getMemberId()).build()); + } + } + @Nullable PartyData getPartyData(final UUID uuid) { From c95cd3bfd52b6f843acbcb2af38729076157d9ab Mon Sep 17 00:00:00 2001 From: Lotto Date: Tue, 7 May 2019 02:47:11 +0200 Subject: [PATCH 21/43] xp tracker: add start and goal levels to on-canvas tracker --- .../plugins/xptracker/XpInfoBoxOverlay.java | 12 ++++++++++ .../components/ProgressBarComponent.java | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index 99c5880901..8718f44468 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.xptracker; +import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; @@ -31,8 +32,10 @@ import java.awt.Rectangle; import java.awt.image.BufferedImage; import lombok.AccessLevel; import lombok.Getter; +import net.runelite.api.Experience; import net.runelite.api.Skill; import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.SkillColor; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; @@ -113,6 +116,15 @@ class XpInfoBoxOverlay extends Overlay iconXpSplitPanel.getChildren().add(iconXpSplit); final ProgressBarComponent progressBarComponent = new ProgressBarComponent(); + + progressBarComponent.setBackgroundColor(new Color(61, 56, 49)); + progressBarComponent.setForegroundColor(SkillColor.find(skill).getColor()); + + progressBarComponent.setLeftLabel(String.valueOf(snapshot.getStartLevel())); + progressBarComponent.setRightLabel(snapshot.getEndGoalXp() == Experience.MAX_SKILL_XP + ? "200M" + : String.valueOf(snapshot.getEndLevel())); + progressBarComponent.setValue(snapshot.getSkillProgressToGoal()); panel.getChildren().add(iconXpSplitPanel); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java index ba4634deec..cadced4e96 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java @@ -46,10 +46,14 @@ public class ProgressBarComponent implements LayoutableRenderableEntity private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.0"); private static final DecimalFormat DECIMAL_FORMAT_ABS = new DecimalFormat("#0"); + private static final int SIDE_LABEL_OFFSET = 4; + private long minimum; private long maximum = 100; private double value; private LabelDisplayMode labelDisplayMode = LabelDisplayMode.PERCENTAGE; + private String leftLabel; + private String rightLabel; private Color foregroundColor = new Color(82, 161, 82); private Color backgroundColor = new Color(255, 255, 255, 127); private Color fontColor = Color.WHITE; @@ -99,6 +103,24 @@ public class ProgressBarComponent implements LayoutableRenderableEntity textComponent.setText(textToWrite); textComponent.render(graphics); + if (leftLabel != null) + { + final TextComponent leftTextComponent = new TextComponent(); + leftTextComponent.setPosition(new Point(barX + SIDE_LABEL_OFFSET, progressTextY)); + leftTextComponent.setColor(fontColor); + leftTextComponent.setText(leftLabel); + leftTextComponent.render(graphics); + } + + if (rightLabel != null) + { + final TextComponent leftTextComponent = new TextComponent(); + leftTextComponent.setPosition(new Point(barX + width - metrics.stringWidth(rightLabel) - SIDE_LABEL_OFFSET, progressTextY)); + leftTextComponent.setColor(fontColor); + leftTextComponent.setText(rightLabel); + leftTextComponent.render(graphics); + } + final Dimension dimension = new Dimension(width, height); bounds.setLocation(preferredLocation); bounds.setSize(dimension); From ad16bf5b3f55223d775936ae9b20ffb421c1a4d1 Mon Sep 17 00:00:00 2001 From: Lotto Date: Tue, 7 May 2019 17:00:51 +0200 Subject: [PATCH 22/43] xp tracker (onscreen): add toggle between displaying XP Left/XP Gained --- .../client/plugins/xptracker/XpInfoBoxOverlay.java | 8 ++++++-- .../client/plugins/xptracker/XpTrackerConfig.java | 11 +++++++++++ .../client/plugins/xptracker/XpTrackerPlugin.java | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index 8718f44468..290dffe01f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -56,6 +56,7 @@ class XpInfoBoxOverlay extends Overlay private final PanelComponent panel = new PanelComponent(); private final PanelComponent iconXpSplitPanel = new PanelComponent(); private final XpTrackerPlugin plugin; + private final XpTrackerConfig config; @Getter(AccessLevel.PACKAGE) private final Skill skill; @@ -63,11 +64,13 @@ class XpInfoBoxOverlay extends Overlay XpInfoBoxOverlay( XpTrackerPlugin plugin, + XpTrackerConfig config, Skill skill, BufferedImage icon) { super(plugin); this.plugin = plugin; + this.config = config; this.skill = skill; this.icon = icon; panel.setBorder(new Rectangle(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); @@ -90,8 +93,9 @@ class XpInfoBoxOverlay extends Overlay final XpSnapshotSingle snapshot = plugin.getSkillSnapshot(skill); final LineComponent xpLine = LineComponent.builder() - .left("XP Gained:") - .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpGainedInSession())) + .left(config.displayXpLeftOnScreen() ? "XP Left:" : "XP Gained:") + .right(StackFormatter.quantityToRSDecimalStack(config.displayXpLeftOnScreen() + ? snapshot.getXpRemainingToGoal() : snapshot.getXpGainedInSession())) .build(); final LineComponent xpHour = LineComponent.builder() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java index d32abf2aa9..f14b442825 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java @@ -74,4 +74,15 @@ public interface XpTrackerConfig extends Config { return 0; } + + @ConfigItem( + position = 4, + keyName = "onScreenXpLeft", + name = "Display XP Left on-screen", + description = "Display remaining experience instead of experience gained on on-screen trackers" + ) + default boolean displayXpLeftOnScreen() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index 8f08b0ba7b..7d3006ddc9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -221,7 +221,7 @@ public class XpTrackerPlugin extends Plugin void addOverlay(Skill skill) { removeOverlay(skill); - overlayManager.add(new XpInfoBoxOverlay(this, skill, skillIconManager.getSkillImage(skill))); + overlayManager.add(new XpInfoBoxOverlay(this, xpTrackerConfig, skill, skillIconManager.getSkillImage(skill))); } /** From bf2eccc54714350894054b556635203df25ef959 Mon Sep 17 00:00:00 2001 From: Lotto Date: Tue, 7 May 2019 21:44:17 +0200 Subject: [PATCH 23/43] xp tracker: add right-click configure on on-screen trackers --- .../runelite/client/plugins/xptracker/XpInfoBoxOverlay.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index 290dffe01f..d5172d6452 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -37,6 +37,7 @@ import net.runelite.api.Skill; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.SkillColor; import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.LineComponent; @@ -44,6 +45,8 @@ import net.runelite.client.ui.overlay.components.PanelComponent; import net.runelite.client.ui.overlay.components.ProgressBarComponent; import net.runelite.client.ui.overlay.components.SplitComponent; import net.runelite.client.util.StackFormatter; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; class XpInfoBoxOverlay extends Overlay { @@ -79,6 +82,7 @@ class XpInfoBoxOverlay extends Overlay iconXpSplitPanel.setBorder(XP_AND_ICON_COMPONENT_BORDER); iconXpSplitPanel.setBackgroundColor(null); iconXpSplitPanel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0)); + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "XP Tracker overlay")); } @Override From 7e6476ce6702acd7ea3d496657d5d4e7a46434f2 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 May 2019 19:59:51 -0400 Subject: [PATCH 24/43] party service: check joins are for the current party The server can resume party membership on handshake to parties other than the current client party (eg. if the client is restarted or for any other reason the current party changes). This desyncs otherwise if the joins aren't checked to be in the current party. --- .../net/runelite/http/api/ws/messages/party/UserJoin.java | 1 + .../src/main/java/net/runelite/client/ws/PartyService.java | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java index 81abe76827..7f940e8060 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java @@ -34,5 +34,6 @@ import net.runelite.http.api.ws.WebsocketMessage; public class UserJoin extends WebsocketMessage { private final UUID memberId; + private final UUID partyId; private final String name; } diff --git a/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java b/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java index 47e9c18148..caec527320 100644 --- a/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java +++ b/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java @@ -114,6 +114,13 @@ public class PartyService @Subscribe public void onUserJoin(final UserJoin message) { + if (!partyId.equals(message.getPartyId())) + { + // This can happen when a session is resumed server side after the client party + // changes when disconnected. + return; + } + final PartyMember partyMember = new PartyMember(message.getMemberId(), message.getName()); members.add(partyMember); From bbb8cff0d5d1fc8c1d4c5fb34aa5e8858a3033a0 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 11 May 2019 23:58:35 -0700 Subject: [PATCH 25/43] game timers: Don't remove antipoison effects on death --- .../java/net/runelite/client/plugins/timers/GameTimer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java index 03473991f5..529103d204 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java @@ -48,7 +48,7 @@ enum GameTimer HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Half Teleblock", 150, ChronoUnit.SECONDS, true), DMM_FULLTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Full Teleblock", 150, ChronoUnit.SECONDS, true), DMM_HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Half Teleblock", 75, ChronoUnit.SECONDS, true), - ANTIVENOMPLUS(ItemID.ANTIVENOM4_12913, GameTimerImageType.ITEM, "Anti-venom+", 3, ChronoUnit.MINUTES, true), + ANTIVENOMPLUS(ItemID.ANTIVENOM4_12913, GameTimerImageType.ITEM, "Anti-venom+", 3, ChronoUnit.MINUTES), ANTIVENOMPLUS_ANTIPOSION(ItemID.SUPERANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom+ Antipoison", 15, ChronoUnit.MINUTES, 3), SUPERANTIFIRE(ItemID.SUPER_ANTIFIRE_POTION4, GameTimerImageType.ITEM, "Super antifire", 3, ChronoUnit.MINUTES), ANTIDOTEPLUSPLUS(ItemID.ANTIDOTE4_5952, GameTimerImageType.ITEM, "Antidote++", 12, ChronoUnit.MINUTES), @@ -65,10 +65,10 @@ enum GameTimer IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued heart", GraphicID.IMBUED_HEART, 420, ChronoUnit.SECONDS), VENGEANCE(SpriteID.SPELL_VENGEANCE, GameTimerImageType.SPRITE, "Vengeance", 30, ChronoUnit.SECONDS), ANTIDOTEPLUS(ItemID.ANTIDOTE4, GameTimerImageType.ITEM, "Antidote+", 518, ChronoUnit.SECONDS), - ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom", 1, ChronoUnit.MINUTES, true), + ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom", 1, ChronoUnit.MINUTES), ANTIVENOM_ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom Antipoison", 12, ChronoUnit.MINUTES, 1), EXSUPERANTIFIRE(ItemID.EXTENDED_SUPER_ANTIFIRE4, GameTimerImageType.ITEM, "Extended Super AntiFire", 6, ChronoUnit.MINUTES), - SANFEW(ItemID.SANFEW_SERUM4, GameTimerImageType.ITEM, "Sanfew serum", 6, ChronoUnit.MINUTES, true), + SANFEW(ItemID.SANFEW_SERUM4, GameTimerImageType.ITEM, "Sanfew serum", 6, ChronoUnit.MINUTES), OVERLOAD_RAID(ItemID.OVERLOAD_4_20996, GameTimerImageType.ITEM, "Overload", 5, ChronoUnit.MINUTES, true), PRAYER_ENHANCE(ItemID.PRAYER_ENHANCE_4, GameTimerImageType.ITEM, "Prayer enhance", 290, ChronoUnit.SECONDS, true), GOD_WARS_ALTAR(SpriteID.SKILL_PRAYER, GameTimerImageType.SPRITE, "God wars altar", 10, ChronoUnit.MINUTES), From 34b30313ca05ca57cff305f878395daa498c71b9 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 12 May 2019 17:42:13 +0200 Subject: [PATCH 26/43] Add options for actions left and done for on screen XP Add configurable option for on screen XP display mode, what now includes: - Actions done - Actions left - Xp gained - Xp left Signed-off-by: Tomas Slusny --- .../plugins/xptracker/XpInfoBoxOverlay.java | 33 ++++++++++++++++--- .../plugins/xptracker/XpTrackerConfig.java | 28 +++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index d5172d6452..32b9a44bfe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -96,15 +96,38 @@ class XpInfoBoxOverlay extends Overlay final XpSnapshotSingle snapshot = plugin.getSkillSnapshot(skill); + final String leftStr; + final int rightNum; + + switch (config.onScreenDisplayMode()) + { + case ACTIONS_DONE: + leftStr = snapshot.getActionType().getLabel() + " Done"; + rightNum = snapshot.getActionsInSession(); + break; + case ACTIONS_LEFT: + leftStr = snapshot.getActionType().getLabel() + " Left"; + rightNum = snapshot.getActionsRemainingToGoal(); + break; + case XP_LEFT: + leftStr = config.onScreenDisplayMode().toString(); + rightNum = snapshot.getXpRemainingToGoal(); + break; + case XP_GAINED: + default: + leftStr = config.onScreenDisplayMode().toString(); + rightNum = snapshot.getXpGainedInSession(); + break; + } + final LineComponent xpLine = LineComponent.builder() - .left(config.displayXpLeftOnScreen() ? "XP Left:" : "XP Gained:") - .right(StackFormatter.quantityToRSDecimalStack(config.displayXpLeftOnScreen() - ? snapshot.getXpRemainingToGoal() : snapshot.getXpGainedInSession())) - .build(); + .left(leftStr + ":") + .right(StackFormatter.quantityToRSDecimalStack(rightNum, true)) + .build(); final LineComponent xpHour = LineComponent.builder() .left("XP/Hour:") - .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour())) + .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour(), true)) .build(); final SplitComponent xpSplit = SplitComponent.builder() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java index f14b442825..6bac32802a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.xptracker; +import lombok.AllArgsConstructor; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @@ -31,6 +32,23 @@ import net.runelite.client.config.ConfigItem; @ConfigGroup("xpTracker") public interface XpTrackerConfig extends Config { + @AllArgsConstructor + enum OnScreenDisplayMode + { + XP_GAINED("XP Gained"), + XP_LEFT("XP Left"), + ACTIONS_DONE("Actions Done"), + ACTIONS_LEFT("Actions Left"); + + private final String name; + + @Override + public String toString() + { + return name; + } + } + @ConfigItem( position = 0, keyName = "hideMaxed", @@ -77,12 +95,12 @@ public interface XpTrackerConfig extends Config @ConfigItem( position = 4, - keyName = "onScreenXpLeft", - name = "Display XP Left on-screen", - description = "Display remaining experience instead of experience gained on on-screen trackers" + keyName = "onScreenDisplayMode", + name = "On-screen tracker display mode", + description = "Configures the information displayed in the first line of on-screen XP overlays" ) - default boolean displayXpLeftOnScreen() + default OnScreenDisplayMode onScreenDisplayMode() { - return false; + return OnScreenDisplayMode.XP_GAINED; } } From 7d22663756d4dbb7a629cb4129c2faf60ef587ed Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 12 May 2019 11:57:40 -0400 Subject: [PATCH 27/43] client: use immutablemap for maps built in class initializers --- .../client/game/ItemVariationMapping.java | 8 +- .../client/plugins/agility/Courses.java | 10 ++- .../plugins/attackstyles/WeaponType.java | 22 +++-- .../client/plugins/blastfurnace/BarsOres.java | 10 ++- .../plugins/blastmine/BlastMineRockType.java | 10 ++- .../client/plugins/bosstimer/Boss.java | 10 ++- .../plugins/cerberus/CerberusGhost.java | 13 +-- .../chatcommands/SkillAbbreviations.java | 86 ++++++++++--------- .../plugins/discord/DiscordGameEventType.java | 17 ++-- .../client/plugins/fishing/FishingSpot.java | 12 +-- .../client/plugins/implings/Impling.java | 10 ++- .../plugins/itemcharges/ItemWithCharge.java | 18 +++- .../ItemIdentification.java | 10 ++- .../runelite/client/plugins/poh/PohIcons.java | 26 ++++-- .../client/plugins/prayer/PrayerItems.java | 8 +- .../plugins/prayer/PrayerRestoreType.java | 8 +- .../puzzlesolver/VarrockMuseumAnswer.java | 10 ++- .../client/plugins/runecraft/AbyssRifts.java | 10 ++- .../client/plugins/runepouch/Runes.java | 8 +- .../runelite/client/plugins/slayer/Task.java | 10 ++- .../plugins/tithefarm/TitheFarmPlantType.java | 12 +-- .../client/plugins/woodcutting/Axe.java | 10 ++- .../client/plugins/woodcutting/Tree.java | 10 ++- 23 files changed, 223 insertions(+), 125 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java index c471a1a814..9629bd99ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java @@ -25,12 +25,12 @@ package net.runelite.client.game; +import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -39,7 +39,7 @@ import java.util.Map; */ public class ItemVariationMapping { - private static final Map MAPPINGS = new HashMap<>(); + private static final Map MAPPINGS; static { @@ -51,6 +51,7 @@ public class ItemVariationMapping final InputStream geLimitData = ItemVariationMapping.class.getResourceAsStream("/item_variations.json"); final Map> itemVariations = gson.fromJson(new InputStreamReader(geLimitData), typeToken.getType()); + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); for (Collection value : itemVariations.values()) { final Iterator iterator = value.iterator(); @@ -58,9 +59,10 @@ public class ItemVariationMapping while (iterator.hasNext()) { - MAPPINGS.put(iterator.next(), base); + builder.put(iterator.next(), base); } } + MAPPINGS = builder.build(); } /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Courses.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Courses.java index bbd6b181cb..cc732561c0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Courses.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Courses.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.agility; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.coords.WorldPoint; @@ -48,7 +48,7 @@ enum Courses RELLEKA(780.0, 475, 10553), ARDOUGNE(793.0, 529, 10547); - private final static Map coursesByRegion = new HashMap<>(); + private final static Map coursesByRegion; @Getter private final double totalXp; @@ -64,10 +64,14 @@ enum Courses static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Courses course : values()) { - coursesByRegion.put(course.regionId, course); + builder.put(course.regionId, course); } + + coursesByRegion = builder.build(); } Courses(double totalXp, int lastObstacleXp, int regionId, WorldPoint... courseEndWorldPoints) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackstyles/WeaponType.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackstyles/WeaponType.java index ef9ba0a188..0a0e443d55 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/attackstyles/WeaponType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackstyles/WeaponType.java @@ -24,9 +24,17 @@ */ package net.runelite.client.plugins.attackstyles; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; -import static net.runelite.client.plugins.attackstyles.AttackStyle.*; +import static net.runelite.client.plugins.attackstyles.AttackStyle.ACCURATE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.AGGRESSIVE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.CASTING; +import static net.runelite.client.plugins.attackstyles.AttackStyle.CONTROLLED; +import static net.runelite.client.plugins.attackstyles.AttackStyle.DEFENSIVE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.DEFENSIVE_CASTING; +import static net.runelite.client.plugins.attackstyles.AttackStyle.LONGRANGE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.OTHER; +import static net.runelite.client.plugins.attackstyles.AttackStyle.RANGING; enum WeaponType { @@ -59,16 +67,20 @@ enum WeaponType TYPE_26(AGGRESSIVE, AGGRESSIVE, null, AGGRESSIVE), TYPE_27(ACCURATE, null, null, OTHER); - private static final Map weaponTypes = new HashMap<>(); - private final AttackStyle[] attackStyles; + private static final Map weaponTypes; + static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (WeaponType weaponType : values()) { - weaponTypes.put(weaponType.ordinal(), weaponType); + builder.put(weaponType.ordinal(), weaponType); } + + weaponTypes = builder.build(); } WeaponType(AttackStyle... attackStyles) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.java index 1f9bc2c244..52a295afd3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.blastfurnace; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.ItemID; @@ -50,14 +50,18 @@ public enum BarsOres SILVER_BAR(Varbits.BLAST_FURNACE_SILVER_BAR, ItemID.SILVER_BAR), GOLD_BAR(Varbits.BLAST_FURNACE_GOLD_BAR, ItemID.GOLD_BAR); - private static final Map VARBIT = new HashMap<>(); + private static final Map VARBIT; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (BarsOres s : values()) { - VARBIT.put(s.getVarbit(), s); + builder.put(s.getVarbit(), s); } + + VARBIT = builder.build(); } @Getter diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineRockType.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineRockType.java index 7c7bda870a..20e1d37f58 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineRockType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineRockType.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.blastmine; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.ObjectID; @@ -37,17 +37,21 @@ public enum BlastMineRockType LIT(ObjectID.POT_OF_DYNAMITE_28585, ObjectID.POT_OF_DYNAMITE_28586), EXPLODED(ObjectID.SHATTERED_ROCKFACE, ObjectID.SHATTERED_ROCKFACE_28588); - private static final Map rockTypes = new HashMap<>(); + private static final Map rockTypes; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (BlastMineRockType type : values()) { for (int spotId : type.getObjectIds()) { - rockTypes.put(spotId, type); + builder.put(spotId, type); } } + + rockTypes = builder.build(); } @Getter diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java b/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java index 95839b9e96..47752f415b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java @@ -25,9 +25,9 @@ */ package net.runelite.client.plugins.bosstimer; +import com.google.common.collect.ImmutableMap; import java.time.Duration; import java.time.temporal.ChronoUnit; -import java.util.HashMap; import java.util.Map; import net.runelite.api.ItemID; import net.runelite.api.NpcID; @@ -59,7 +59,7 @@ enum Boss DUSK(NpcID.DUSK_7889, 2, ChronoUnit.MINUTES, ItemID.NOON), ALCHEMICAL_HYDRA(NpcID.ALCHEMICAL_HYDRA_8622, 25200, ChronoUnit.MILLIS, ItemID.IKKLE_HYDRA); - private static final Map bosses = new HashMap<>(); + private static final Map bosses; private final int id; private final Duration spawnTime; @@ -67,10 +67,14 @@ enum Boss static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Boss boss : values()) { - bosses.put(boss.getId(), boss); + builder.put(boss.getId(), boss); } + + bosses = builder.build(); } private Boss(int id, long period, ChronoUnit unit, int itemSpriteId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java index 7bdf9d6788..744085c9a4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.cerberus; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import java.util.Optional; import lombok.Getter; @@ -41,18 +41,21 @@ public enum CerberusGhost MAGE(NpcID.SUMMONED_SOUL_5868, Skill.MAGIC), MELEE(NpcID.SUMMONED_SOUL_5869, Skill.ATTACK); - private static final Map MAP = new HashMap<>(); private final int npcId; private final Skill type; + private static final Map MAP; + static { - final CerberusGhost[] values = CerberusGhost.values(); + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - for (final CerberusGhost ghost : values) + for (final CerberusGhost ghost : values()) { - MAP.put(ghost.getNpcId(), ghost); + builder.put(ghost.getNpcId(), ghost); } + + MAP = builder.build(); } /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/SkillAbbreviations.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/SkillAbbreviations.java index da89769172..754c2f869e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/SkillAbbreviations.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/SkillAbbreviations.java @@ -24,56 +24,58 @@ */ package net.runelite.client.plugins.chatcommands; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import net.runelite.api.Skill; class SkillAbbreviations { - private static final Map MAP = new HashMap<>(); + private static final Map MAP; static { - MAP.put("ATK", Skill.ATTACK.getName()); - MAP.put("ATT", Skill.ATTACK.getName()); - MAP.put("DEF", Skill.DEFENCE.getName()); - MAP.put("STR", Skill.STRENGTH.getName()); - MAP.put("HEALTH", Skill.HITPOINTS.getName()); - MAP.put("HIT", Skill.HITPOINTS.getName()); - MAP.put("HITPOINT", Skill.HITPOINTS.getName()); - MAP.put("HP", Skill.HITPOINTS.getName()); - MAP.put("RANGE", Skill.RANGED.getName()); - MAP.put("RANGING", Skill.RANGED.getName()); - MAP.put("RNG", Skill.RANGED.getName()); - MAP.put("PRAY", Skill.PRAYER.getName()); - MAP.put("MAG", Skill.MAGIC.getName()); - MAP.put("MAGE", Skill.MAGIC.getName()); - MAP.put("COOK", Skill.COOKING.getName()); - MAP.put("WC", Skill.WOODCUTTING.getName()); - MAP.put("WOOD", Skill.WOODCUTTING.getName()); - MAP.put("WOODCUT", Skill.WOODCUTTING.getName()); - MAP.put("FLETCH", Skill.FLETCHING.getName()); - MAP.put("FISH", Skill.FISHING.getName()); - MAP.put("FM", Skill.FIREMAKING.getName()); - MAP.put("FIRE", Skill.FIREMAKING.getName()); - MAP.put("CRAFT", Skill.CRAFTING.getName()); - MAP.put("SMITH", Skill.SMITHING.getName()); - MAP.put("MINE", Skill.MINING.getName()); - MAP.put("HL", Skill.HERBLORE.getName()); - MAP.put("HERB", Skill.HERBLORE.getName()); - MAP.put("AGI", Skill.AGILITY.getName()); - MAP.put("AGIL", Skill.AGILITY.getName()); - MAP.put("THIEF", Skill.THIEVING.getName()); - MAP.put("SLAY", Skill.SLAYER.getName()); - MAP.put("FARM", Skill.FARMING.getName()); - MAP.put("RC", Skill.RUNECRAFT.getName()); - MAP.put("RUNE", Skill.RUNECRAFT.getName()); - MAP.put("RUNECRAFTING", Skill.RUNECRAFT.getName()); - MAP.put("HUNT", Skill.HUNTER.getName()); - MAP.put("CON", Skill.CONSTRUCTION.getName()); - MAP.put("CONSTRUCT", Skill.CONSTRUCTION.getName()); - MAP.put("ALL", Skill.OVERALL.getName()); - MAP.put("TOTAL", Skill.OVERALL.getName()); + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put("ATK", Skill.ATTACK.getName()); + builder.put("ATT", Skill.ATTACK.getName()); + builder.put("DEF", Skill.DEFENCE.getName()); + builder.put("STR", Skill.STRENGTH.getName()); + builder.put("HEALTH", Skill.HITPOINTS.getName()); + builder.put("HIT", Skill.HITPOINTS.getName()); + builder.put("HITPOINT", Skill.HITPOINTS.getName()); + builder.put("HP", Skill.HITPOINTS.getName()); + builder.put("RANGE", Skill.RANGED.getName()); + builder.put("RANGING", Skill.RANGED.getName()); + builder.put("RNG", Skill.RANGED.getName()); + builder.put("PRAY", Skill.PRAYER.getName()); + builder.put("MAG", Skill.MAGIC.getName()); + builder.put("MAGE", Skill.MAGIC.getName()); + builder.put("COOK", Skill.COOKING.getName()); + builder.put("WC", Skill.WOODCUTTING.getName()); + builder.put("WOOD", Skill.WOODCUTTING.getName()); + builder.put("WOODCUT", Skill.WOODCUTTING.getName()); + builder.put("FLETCH", Skill.FLETCHING.getName()); + builder.put("FISH", Skill.FISHING.getName()); + builder.put("FM", Skill.FIREMAKING.getName()); + builder.put("FIRE", Skill.FIREMAKING.getName()); + builder.put("CRAFT", Skill.CRAFTING.getName()); + builder.put("SMITH", Skill.SMITHING.getName()); + builder.put("MINE", Skill.MINING.getName()); + builder.put("HL", Skill.HERBLORE.getName()); + builder.put("HERB", Skill.HERBLORE.getName()); + builder.put("AGI", Skill.AGILITY.getName()); + builder.put("AGIL", Skill.AGILITY.getName()); + builder.put("THIEF", Skill.THIEVING.getName()); + builder.put("SLAY", Skill.SLAYER.getName()); + builder.put("FARM", Skill.FARMING.getName()); + builder.put("RC", Skill.RUNECRAFT.getName()); + builder.put("RUNE", Skill.RUNECRAFT.getName()); + builder.put("RUNECRAFTING", Skill.RUNECRAFT.getName()); + builder.put("HUNT", Skill.HUNTER.getName()); + builder.put("CON", Skill.CONSTRUCTION.getName()); + builder.put("CONSTRUCT", Skill.CONSTRUCTION.getName()); + builder.put("ALL", Skill.OVERALL.getName()); + builder.put("TOTAL", Skill.OVERALL.getName()); + MAP = builder.build(); } /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java index 7258c6c7bb..cd05521228 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java @@ -25,8 +25,8 @@ */ package net.runelite.client.plugins.discord; -import java.util.ArrayList; -import java.util.HashMap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.util.List; import java.util.Map; import lombok.AllArgsConstructor; @@ -250,16 +250,18 @@ enum DiscordGameEventType RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, Varbits.IN_RAID), RAIDS_THEATRE_OF_BLOOD("Theatre of Blood", DiscordAreaType.RAIDS, Varbits.THEATRE_OF_BLOOD); - private static final Map FROM_REGION = new HashMap<>(); - private static final List FROM_VARBITS = new ArrayList<>(); + private static final Map FROM_REGION; + private static final List FROM_VARBITS; static { + ImmutableMap.Builder regionMapBuilder = new ImmutableMap.Builder<>(); + ImmutableList.Builder fromVarbitsBuilder = ImmutableList.builder(); for (DiscordGameEventType discordGameEventType : DiscordGameEventType.values()) { if (discordGameEventType.getVarbits() != null) { - FROM_VARBITS.add(discordGameEventType); + fromVarbitsBuilder.add(discordGameEventType); continue; } @@ -270,10 +272,11 @@ enum DiscordGameEventType for (int region : discordGameEventType.getRegionIds()) { - assert !FROM_REGION.containsKey(region); - FROM_REGION.put(region, discordGameEventType); + regionMapBuilder.put(region, discordGameEventType); } } + FROM_REGION = regionMapBuilder.build(); + FROM_VARBITS = fromVarbitsBuilder.build(); } private String imageKey; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpot.java index 0221e7c32c..94f774ccc0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpot.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.fishing; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.ItemID; @@ -160,7 +160,7 @@ enum FishingSpot FISHING_SPOT_8523); @Getter - private static final Map SPOTS = new HashMap<>(); + private static final Map SPOTS; private final String name; private final int fishSpriteId; @@ -168,15 +168,17 @@ enum FishingSpot static { - FishingSpot[] spots = values(); + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - for (FishingSpot spot : spots) + for (FishingSpot spot : values()) { for (int spotId : spot.getIds()) { - SPOTS.put(spotId, spot); + builder.put(spotId, spot); } } + + SPOTS = builder.build(); } FishingSpot(String spot, int fishSpriteId, int... ids) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/implings/Impling.java b/runelite-client/src/main/java/net/runelite/client/plugins/implings/Impling.java index 0273b5da04..473fad2c23 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/implings/Impling.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/implings/Impling.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.implings; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.AllArgsConstructor; import lombok.Getter; @@ -70,14 +70,18 @@ enum Impling private ImplingType implingType; private final int npcId; - private static final Map IMPLINGS = new HashMap<>(); + private static final Map IMPLINGS; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Impling impling : values()) { - IMPLINGS.put(impling.npcId, impling); + builder.put(impling.npcId, impling); } + + IMPLINGS = builder.build(); } static Impling findImpling(int npcId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java index 10f905aff4..f696097817 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java @@ -24,13 +24,19 @@ */ package net.runelite.client.plugins.itemcharges; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import javax.annotation.Nullable; import lombok.AllArgsConstructor; import lombok.Getter; import static net.runelite.api.ItemID.*; -import static net.runelite.client.plugins.itemcharges.ItemChargeType.*; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.ABYSSAL_BRACELET; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.BELLOWS; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.FUNGICIDE_SPRAY; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.IMPBOX; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.TELEPORT; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERCAN; +import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERSKIN; @AllArgsConstructor @Getter @@ -168,14 +174,18 @@ enum ItemWithCharge private final int id; private final int charges; - private static final Map ID_MAP = new HashMap<>(); + private static final Map ID_MAP; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (ItemWithCharge itemCharge : values()) { - ID_MAP.put(itemCharge.getId(), itemCharge); + builder.put(itemCharge.getId(), itemCharge); } + + ID_MAP = builder.build(); } @Nullable diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java index 8ef3efcf8b..622ab1c04e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.itemidentification; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import net.runelite.api.ItemID; @@ -100,17 +100,21 @@ enum ItemIdentification this.itemIDs = ids; } - private static final Map itemIdentifications = new HashMap<>(); + private static final Map itemIdentifications; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (ItemIdentification i : values()) { for (int id : i.itemIDs) { - itemIdentifications.put(id, i); + builder.put(id, i); } } + + itemIdentifications = builder.build(); } static ItemIdentification get(int id) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java index 1cde69a8ea..656cf85716 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java @@ -24,12 +24,22 @@ */ package net.runelite.client.plugins.poh; +import com.google.common.collect.ImmutableMap; import java.awt.image.BufferedImage; -import java.util.HashMap; import java.util.Map; import lombok.Getter; +import static net.runelite.api.NullObjectID.NULL_13615; +import static net.runelite.api.NullObjectID.NULL_13618; +import static net.runelite.api.NullObjectID.NULL_13620; +import static net.runelite.api.NullObjectID.NULL_13622; +import static net.runelite.api.NullObjectID.NULL_13625; +import static net.runelite.api.NullObjectID.NULL_13627; +import static net.runelite.api.NullObjectID.NULL_13629; +import static net.runelite.api.NullObjectID.NULL_13632; +import static net.runelite.api.NullObjectID.NULL_13634; +import static net.runelite.api.NullObjectID.NULL_29228; +import static net.runelite.api.NullObjectID.NULL_29229; import static net.runelite.api.ObjectID.*; -import static net.runelite.api.NullObjectID.*; import net.runelite.client.util.ImageUtil; public enum PohIcons @@ -56,7 +66,7 @@ public enum PohIcons ALTAR("altar", ALTAR_13179, ALTAR_13180, ALTAR_13181, ALTAR_13182, ALTAR_13183, ALTAR_13184, ALTAR_13185, ALTAR_13186, ALTAR_13187, ALTAR_13188, ALTAR_13189, ALTAR_13190, ALTAR_13191, ALTAR_13192, ALTAR_13193, ALTAR_13194, - ALTAR_13194, ALTAR_13196, ALTAR_13197, ALTAR_13198, ALTAR_13199 + ALTAR_13196, ALTAR_13197, ALTAR_13198, ALTAR_13199 ), POOLS("pool", POOL_OF_RESTORATION, POOL_OF_REVITALISATION, POOL_OF_REJUVENATION, FANCY_REJUVENATION_POOL, ORNATE_REJUVENATION_POOL), GLORY("glory", AMULET_OF_GLORY), @@ -83,7 +93,7 @@ public enum PohIcons DIGSITE_PENDANT, DIGSITE_PENDANT_33417, DIGSITE_PENDANT_33418, DIGSITE_PENDANT_33420 ); - private static final Map minimapIcons = new HashMap<>(); + private static final Map minimapIcons; @Getter private final String imageResource; @@ -94,15 +104,17 @@ public enum PohIcons static { - PohIcons[] icons = values(); + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - for (PohIcons icon : icons) + for (PohIcons icon : values()) { for (Integer spotId : icon.getIds()) { - minimapIcons.put(spotId, icon); + builder.put(spotId, icon); } } + + minimapIcons = builder.build(); } PohIcons(String imageResource, int... ids) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerItems.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerItems.java index 24ffbc5a56..d07ff8cf6c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerItems.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerItems.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.prayer; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.AllArgsConstructor; import lombok.Getter; @@ -453,17 +453,19 @@ enum PrayerItems DAMAGED_BOOK_3841(ItemID.DAMAGED_BOOK_3841, 5), FALADOR_SHIELD_4(ItemID.FALADOR_SHIELD_4, 5); - private static final Map prayerBonuses = new HashMap<>(); + private static final Map prayerBonuses; private final int itemId; private final int prayerBonus; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); for (PrayerItems item : values()) { - prayerBonuses.put(item.getItemId(), item.getPrayerBonus()); + builder.put(item.getItemId(), item.getPrayerBonus()); } + prayerBonuses = builder.build(); } static int getItemPrayerBonus(int itemId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerRestoreType.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerRestoreType.java index 2ef3c1a46f..d30b790a9e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerRestoreType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerRestoreType.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.prayer; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import net.runelite.api.ItemID; @@ -36,7 +36,7 @@ enum PrayerRestoreType HOLYWRENCH(ItemID.PRAYER_CAPE, ItemID.PRAYER_CAPET, ItemID.PRAYER_CAPE_10643, ItemID.MAX_CAPE, ItemID.MAX_CAPE_13282, ItemID.MAX_CAPE_13342, ItemID.HOLY_WRENCH, ItemID.RING_OF_THE_GODS_I); - private static final Map prayerRestores = new HashMap<>(); + private static final Map prayerRestores; private final int[] items; @@ -47,13 +47,15 @@ enum PrayerRestoreType static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); for (PrayerRestoreType prayerRestoreType : values()) { for (int itemId : prayerRestoreType.items) { - prayerRestores.put(itemId, prayerRestoreType); + builder.put(itemId, prayerRestoreType); } } + prayerRestores = builder.build(); } static PrayerRestoreType getType(final int itemId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/VarrockMuseumAnswer.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/VarrockMuseumAnswer.java index e574dd1023..0e4307d550 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/VarrockMuseumAnswer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/VarrockMuseumAnswer.java @@ -25,7 +25,7 @@ */ package net.runelite.client.plugins.puzzlesolver; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -135,14 +135,18 @@ enum VarrockMuseumAnswer LEECH_5("What is special about Morytanian leeches?", "They attack by jumping."), LEECH_6("How does a leech change when it feeds?", "It doubles in size."); - private static final Map MATCHES = new HashMap<>(); + private static final Map MATCHES; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (VarrockMuseumAnswer varrockMuseumAnswer : VarrockMuseumAnswer.values()) { - MATCHES.put(varrockMuseumAnswer.question, varrockMuseumAnswer.answer); + builder.put(varrockMuseumAnswer.question, varrockMuseumAnswer.answer); } + + MATCHES = builder.build(); } private final String question; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java index 60f02d5080..1ecedafe00 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.runecraft; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import static net.runelite.api.ItemID.AIR_RUNE; @@ -64,14 +64,18 @@ public enum AbyssRifts @Getter private final int itemId; - private static final Map rifts = new HashMap<>(); + private static final Map rifts; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (AbyssRifts s : values()) { - rifts.put(s.getObjectId(), s); + builder.put(s.getObjectId(), s); } + + rifts = builder.build(); } AbyssRifts(int objectId, int itemId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java index 26dd1148a9..b5aebe9bf6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java @@ -25,8 +25,8 @@ package net.runelite.client.plugins.runepouch; +import com.google.common.collect.ImmutableMap; import java.awt.image.BufferedImage; -import java.util.HashMap; import java.util.Map; import lombok.Getter; import lombok.Setter; @@ -85,14 +85,16 @@ public enum Runes @Setter private BufferedImage image; - private static final Map runes = new HashMap<>(); + private static final Map runes; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); for (Runes rune : values()) { - runes.put(rune.getId(), rune); + builder.put(rune.getId(), rune); } + runes = builder.build(); } Runes(int id, int itemId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java index 69725f6d1b..5ba47383e1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java @@ -26,7 +26,7 @@ package net.runelite.client.plugins.slayer; import com.google.common.base.Preconditions; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.ItemID; @@ -174,7 +174,7 @@ enum Task ZUK("TzKal-Zuk", ItemID.TZREKZUK); // - private static final Map tasks = new HashMap<>(); + private static final Map tasks; private final String name; private final int itemSpriteId; @@ -184,10 +184,14 @@ enum Task static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Task task : values()) { - tasks.put(task.getName().toLowerCase(), task); + builder.put(task.getName().toLowerCase(), task); } + + tasks = builder.build(); } Task(String name, int itemSpriteId, String... targetNames) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tithefarm/TitheFarmPlantType.java b/runelite-client/src/main/java/net/runelite/client/plugins/tithefarm/TitheFarmPlantType.java index 413838c144..04a48e6eb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tithefarm/TitheFarmPlantType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tithefarm/TitheFarmPlantType.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.tithefarm; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.ObjectID; @@ -60,19 +60,21 @@ public enum TitheFarmPlantType @Getter private final int[] objectIds; - private static final Map plantTypes = new HashMap<>(); + private static final Map plantTypes; static { - TitheFarmPlantType[] types = values(); + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - for (TitheFarmPlantType type : types) + for (TitheFarmPlantType type : values()) { for (int spotId : type.getObjectIds()) { - plantTypes.put(spotId, type); + builder.put(spotId, type); } } + + plantTypes = builder.build(); } TitheFarmPlantType(String name, int baseId, int... objectIds) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java index 80b4dc7b92..7b8a5c5f4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.woodcutting; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.AllArgsConstructor; import lombok.Getter; @@ -67,14 +67,18 @@ enum Axe private final Integer animId; private final Integer itemId; - private static final Map AXE_ANIM_IDS = new HashMap<>(); + private static final Map AXE_ANIM_IDS; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Axe axe : values()) { - AXE_ANIM_IDS.put(axe.animId, axe); + builder.put(axe.animId, axe); } + + AXE_ANIM_IDS = builder.build(); } static Axe findAxeByAnimId(int animId) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Tree.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Tree.java index 021ce9da9f..befc78df8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Tree.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Tree.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.woodcutting; -import java.util.HashMap; +import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import static net.runelite.api.ObjectID.REDWOOD; @@ -42,17 +42,21 @@ enum Tree this.treeIds = treeIds; } - private static final Map TREES = new HashMap<>(); + private static final Map TREES; static { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Tree tree : values()) { for (int treeId : tree.treeIds) { - TREES.put(treeId, tree); + builder.put(treeId, tree); } } + + TREES = builder.build(); } static Tree findTree(int objectId) From 471a0ba73f926c33b3e04b25b7e27c4d59f64671 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 10 May 2019 17:42:16 +0200 Subject: [PATCH 28/43] Add loop timer infobox Add loop timer infobox that will keep looping through specified interval. Signed-off-by: Tomas Slusny --- .../client/ui/overlay/infobox/LoopTimer.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/LoopTimer.java diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/LoopTimer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/LoopTimer.java new file mode 100644 index 0000000000..1e11f1900e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/LoopTimer.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, Tomas Slusny + * 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.client.ui.overlay.infobox; + +import com.google.common.base.Preconditions; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import lombok.Getter; +import lombok.ToString; +import net.runelite.client.plugins.Plugin; + +@Getter +@ToString +public class LoopTimer extends InfoBox +{ + private final Instant startTime; + private final Duration duration; + private final boolean reverse; + + public LoopTimer(long period, ChronoUnit unit, BufferedImage image, Plugin plugin, boolean reverse) + { + super(image, plugin); + + Preconditions.checkArgument(period > 0, "negative period!"); + + startTime = Instant.now(); + duration = Duration.of(period, unit); + this.reverse = reverse; + } + + public LoopTimer(long period, ChronoUnit unit, BufferedImage image, Plugin plugin) + { + this(period, unit, image, plugin, false); + } + + @Override + public String getText() + { + final Duration progress = getProgress(); + final int seconds = (int) (progress.toMillis() / 1000L); + final int minutes = (seconds % 3600) / 60; + final int secs = seconds % 60; + return String.format("%d:%02d", minutes, secs); + } + + @Override + public Color getTextColor() + { + final Duration progress = getProgress(); + + // check if timer has 10% of time left + if (progress.getSeconds() < (duration.getSeconds() * .10)) + { + return Color.RED.brighter(); + } + + return Color.WHITE; + } + + private Duration getProgress() + { + final Duration passed = Duration.between(startTime, Instant.now()); + final long passedMillis = passed.toMillis(); + final long durationMillis = duration.toMillis(); + final long progress = passedMillis % durationMillis; + + return Duration.ofMillis(reverse + ? durationMillis - progress + : progress); + } +} \ No newline at end of file From f82aa6be93e7f5387ac1697e9216bf8b79ddc506 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 14 May 2019 00:00:36 +0200 Subject: [PATCH 29/43] Use LoopTimer in Barrows plugin Signed-off-by: Tomas Slusny --- .../client/plugins/barrows/BarrowsPlugin.java | 22 +++++- .../barrows/BarrowsPrayerDrainTimer.java | 77 ------------------- 2 files changed, 20 insertions(+), 79 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java index 72bf08fe7e..30ecefb885 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.barrows; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import com.google.inject.Provides; +import java.time.temporal.ChronoUnit; import java.util.HashSet; import java.util.Set; import javax.inject.Inject; @@ -41,6 +42,7 @@ import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.NullObjectID; import net.runelite.api.ObjectID; +import net.runelite.api.SpriteID; import net.runelite.api.WallObject; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameObjectChanged; @@ -66,6 +68,8 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; +import net.runelite.client.ui.overlay.infobox.LoopTimer; import net.runelite.client.util.StackFormatter; @PluginDescriptor( @@ -92,6 +96,7 @@ public class BarrowsPlugin extends Plugin WidgetInfo.BARROWS_PUZZLE_ANSWER3 ); + private static final long PRAYER_DRAIN_INTERVAL_MS = 18200; private static final int CRYPT_REGION_ID = 14231; @Getter(AccessLevel.PACKAGE) @@ -100,6 +105,7 @@ public class BarrowsPlugin extends Plugin @Getter(AccessLevel.PACKAGE) private final Set ladders = new HashSet<>(); + private LoopTimer barrowsPrayerDrainTimer; private boolean wasInCrypt = false; @Getter @@ -313,13 +319,25 @@ public class BarrowsPlugin extends Plugin { if (config.showPrayerDrainTimer()) { - infoBoxManager.addInfoBox(new BarrowsPrayerDrainTimer(this, spriteManager)); + final LoopTimer loopTimer = new LoopTimer( + PRAYER_DRAIN_INTERVAL_MS, + ChronoUnit.MILLIS, + spriteManager.getSprite(SpriteID.TAB_PRAYER, 0), + this, + true); + + loopTimer.setPriority(InfoBoxPriority.MED); + loopTimer.setTooltip("Prayer Drain"); + + infoBoxManager.addInfoBox(loopTimer); + barrowsPrayerDrainTimer = loopTimer; } } private void stopPrayerDrainTimer() { - infoBoxManager.removeIf(BarrowsPrayerDrainTimer.class::isInstance); + infoBoxManager.removeInfoBox(barrowsPrayerDrainTimer); + barrowsPrayerDrainTimer = null; } private boolean isInCrypt() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java deleted file mode 100644 index 4428a54f07..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019, Ryan - * 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.client.plugins.barrows; - -import java.awt.Color; -import java.time.Duration; -import java.time.Instant; -import net.runelite.api.SpriteID; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.ui.overlay.infobox.InfoBox; -import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; - -class BarrowsPrayerDrainTimer extends InfoBox -{ - private static final long PRAYER_DRAIN_INTERVAL_MS = 18200; - - private final Instant startTime; - - BarrowsPrayerDrainTimer(BarrowsPlugin plugin, SpriteManager spriteManager) - { - super(spriteManager.getSprite(SpriteID.TAB_PRAYER, 0), plugin); - setPriority(InfoBoxPriority.MED); - setTooltip("Prayer Drain"); - startTime = Instant.now(); - } - - @Override - public String getText() - { - Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime()); - int seconds = (int) (timeLeft.toMillis() / 1000L); - return String.format("0:%02d", seconds); - } - - @Override - public Color getTextColor() - { - Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime()); - - //check if timer has 10% of time left - if (timeLeft.getSeconds() < (PRAYER_DRAIN_INTERVAL_MS / 1000 * .10)) - { - return Color.RED.brighter(); - } - - return Color.WHITE; - } - - private Instant getNextPrayerDrainTime() - { - Duration timePassed = Duration.between(startTime, Instant.now()); - // Get how many intervals have passed so far and add one more to find the next prayer drain time - return startTime.plusMillis((timePassed.toMillis() / PRAYER_DRAIN_INTERVAL_MS + 1) * PRAYER_DRAIN_INTERVAL_MS); - } -} From 4e8e1822143727ef62a6ac12f50f425a6e3fa240 Mon Sep 17 00:00:00 2001 From: Ville Kopio <13101000+vkopio@users.noreply.github.com> Date: Tue, 14 May 2019 04:25:47 +0300 Subject: [PATCH 30/43] combatlevel plugin: fix prayer levels until combat level calculation Add more prayer level tests to expose a bug in which needed prayer levels for next combat level was 0 instead of 2 in some corner cases and implemented fixes. For example: Let prayer level p be an odd number. The current combat level is exactly same for p and p - 1. Therefore given n is the needed prayer levels for a combat level with p - 1 prayer then n - 1 is the needed prayer levels for a combal level with p prayer. Further more the usage of Math.floor was incorrect in every cases so it is changed to Math.ceil. --- .../combatlevel/CombatLevelOverlay.java | 8 +++- .../combatlevel/CombatLevelPluginTest.java | 43 +++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java index bc107e31b2..6e81a7a983 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java @@ -168,12 +168,18 @@ class CombatLevelOverlay extends Overlay @VisibleForTesting static int calcLevelsPray(double start, int end, int prayerLevel) { - final int neededLevels = (int) Math.floor(calcMultipliedLevels(start, end, PRAY_MULT)); + int neededLevels = (int) Math.ceil(calcMultipliedLevels(start, end, PRAY_MULT)); + + if (prayerLevel % 2 != 0) + { + neededLevels--; + } if ((prayerLevel + neededLevels) % 2 != 0) { return neededLevels + 1; } + return neededLevels; } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java index 3c1ff06f0c..361fa04aea 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java @@ -270,10 +270,47 @@ public class CombatLevelPluginTest when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(99); when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(99); + assertEquals(1, neededPrayerLevels()); + } + + @Test + public void testEvenPrayerLevelsNeededWhenNearNextCombatLevel() + { + when(player.getCombatLevel()).thenReturn(90); + when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(74); + when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(75); + when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(72); + when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(52); + when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(44); + when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(60); + when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(72); + + assertEquals(2, neededPrayerLevels()); + } + + @Test + public void testOddPrayerLevelsNeededWhenNearNextCombatLevel() + { + when(player.getCombatLevel()).thenReturn(90); + when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(74); + when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(75); + when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(72); + when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(53); + when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(44); + when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(60); + when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(72); + + assertEquals(1, neededPrayerLevels()); + } + + private int neededPrayerLevels() + { HashMap baseValues = getBaseValues(); - // test prayer - assertEquals(1, calcLevelsPray(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER))); + return calcLevelsPray( + baseValues.get("base") + baseValues.get("max"), + player.getCombatLevel() + 1, + client.getRealSkillLevel(Skill.PRAYER) + ); } } From 6ddb82c532f6204dd2e5b39aac9f2e109cb94472 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 14 May 2019 15:52:54 +1000 Subject: [PATCH 31/43] clue scroll plugin: fix typo in Arnold Lydspor clue (#8832) Fixes #8828 --- .../runelite/client/plugins/cluescrolls/clues/CipherClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java index 4dcf3849e0..404ce70eae 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java @@ -57,7 +57,7 @@ public class CipherClue extends ClueScroll implements TextClueScroll, NpcClueScr new CipherClue("GBJSZ RVFFO", "Fairy Queen", new WorldPoint(2347, 4435, 0), "Fairy Resistance Hideout", "Puzzle"), new CipherClue("QSPGFTTPS HSBDLMFCPOF", "Professor Gracklebone", new WorldPoint(1625, 3802, 0), "Ground floor of Arceuus Library", "9"), new CipherClue("IWPPLQTP", "Gunnjorn", new WorldPoint(2541, 3548, 0), "Barbarian Outpost Agility course", "Puzzle"), - new CipherClue("BSOPME MZETQPS", "Arnold Lydspor", new WorldPoint(2329, 3689, 0), "Piscatorus Fishing Colony general store/bank", "Puzzle") + new CipherClue("BSOPME MZETQPS", "Arnold Lydspor", new WorldPoint(2329, 3689, 0), "Piscatoris Fishing Colony general store/bank", "Puzzle") ); private String text; From bd309135cecd4442b445838f09076f330fd17448 Mon Sep 17 00:00:00 2001 From: JZomerlei Date: Tue, 14 May 2019 02:43:42 -0400 Subject: [PATCH 32/43] itemstats: Add missing CoX fish, fix Leckish fish healing value (#8831) Closes #8829 --- .../client/plugins/itemstats/ItemStatChanges.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java index 099b5a16a7..bcce08ffe5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java @@ -59,22 +59,22 @@ public class ItemStatChanges add(food(3), SHRIMPS, COOKED_MEAT, COOKED_CHICKEN, ROE, CHOCOLATE_BAR); add(food(4), SARDINE, CAKE, _23_CAKE, SLICE_OF_CAKE, CHOCOLATEY_MILK, BAKED_POTATO, EDIBLE_SEAWEED, MOONLIGHT_MEAD); add(food(5), BREAD, HERRING, CHOCOLATE_CAKE, _23_CHOCOLATE_CAKE, CHOCOLATE_SLICE, COOKED_RABBIT, CHILLI_CON_CARNE, - FRIED_MUSHROOMS, FRIED_ONIONS, REDBERRY_PIE, HALF_A_REDBERRY_PIE, CAVIAR); + FRIED_MUSHROOMS, FRIED_ONIONS, REDBERRY_PIE, HALF_A_REDBERRY_PIE, CAVIAR, PYSK_FISH_0); add(food(6), CHOCICE, MACKEREL, MEAT_PIE, HALF_A_MEAT_PIE, GUANIC_BAT_0, ROAST_BIRD_MEAT, SQUARE_SANDWICH, ROLL, BAGUETTE, TRIANGLE_SANDWICH, GIANT_CARP); add(food(7), TROUT, COD, PLAIN_PIZZA, _12_PLAIN_PIZZA, APPLE_PIE, HALF_AN_APPLE_PIE, ROAST_RABBIT, PREMADE_CH_CRUNCH, CHOCCHIP_CRUNCHIES, PREMADE_SY_CRUNCH, SPICY_CRUNCHIES); add(food(8), PIKE, ROAST_BEAST_MEAT, MEAT_PIZZA, _12_MEAT_PIZZA, PREMADE_WM_CRUN, WORM_CRUNCHIES, PREMADE_TD_CRUNCH, - TOAD_CRUNCHIES, EGG_AND_TOMATO, LECKISH_FISH_2, PRAEL_BAT_1, PEACH); + TOAD_CRUNCHIES, EGG_AND_TOMATO, PRAEL_BAT_1, PEACH, SUPHI_FISH_1); add(food(9), PREMADE_P_PUNCH, PINEAPPLE_PUNCH, PREMADE_FR_BLAST, FRUIT_BLAST, SALMON, ANCHOVY_PIZZA, _12_ANCHOVY_PIZZA); add(food(10), TUNA, COOKED_CRAB_MEAT, CHOPPED_TUNA, COOKED_CHOMPY, FIELD_RATION); add(food(11), RAINBOW_FISH, STEW, PINEAPPLE_PIZZA, _12_PINEAPPLE_PIZZA, COOKED_FISHCAKE, PREMADE_VEG_BATTA, VEGETABLE_BATTA, PREMADE_WM_BATTA, WORM_BATTA, PREMADE_TD_BATTA, TOAD_BATTA, PREMADE_CT_BATTA, - CHEESETOM_BATTA, PREMADE_FRT_BATTA, FRUIT_BATTA, MUSHROOM__ONION, GIRAL_BAT_2, LAVA_EEL); + CHEESETOM_BATTA, PREMADE_FRT_BATTA, FRUIT_BATTA, MUSHROOM__ONION, GIRAL_BAT_2, LAVA_EEL, LECKISH_FISH_2); add(food(12), LOBSTER, PREMADE_WORM_HOLE, WORM_HOLE, PREMADE_VEG_BALL, VEG_BALL); add(food(13), BASS, TUNA_AND_CORN); - add(food(14), POTATO_WITH_BUTTER, CHILLI_POTATO, SWORDFISH, PHLUXIA_BAT_3, PUMPKIN, EASTER_EGG); + add(food(14), POTATO_WITH_BUTTER, CHILLI_POTATO, SWORDFISH, PHLUXIA_BAT_3, PUMPKIN, EASTER_EGG, BRAWK_FISH_3); add(food(15), PREMADE_TTL, TANGLED_TOADS_LEGS, PREMADE_CHOC_BOMB, CHOCOLATE_BOMB, COOKED_JUBBLY); add(food(16), MONKFISH, POTATO_WITH_CHEESE, EGG_POTATO); add(food(17), MYCIL_FISH_4, KRYKET_BAT_4); From 869fa9d93dfd8fbc46f97c6f17f8c9a33961f3ab Mon Sep 17 00:00:00 2001 From: Vincent Sevilla Date: Tue, 14 May 2019 05:24:45 -0700 Subject: [PATCH 33/43] notifier: Log notifications to console in debug mode (#8805) --- runelite-client/src/main/java/net/runelite/client/Notifier.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/Notifier.java b/runelite-client/src/main/java/net/runelite/client/Notifier.java index e29d66c87c..d1423f168e 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -150,6 +150,8 @@ public class Notifier { flashStart = Instant.now(); } + + log.debug(message); } public void processFlash(final Graphics2D graphics) From 69e57c9a612700aba711f59019f5a7548c850c55 Mon Sep 17 00:00:00 2001 From: Lotto Date: Sun, 12 May 2019 16:08:14 +0200 Subject: [PATCH 34/43] client: format enum config options as "Config Opt" instead of CONFIG_OPT --- .../client/plugins/config/ConfigPanel.java | 4 +-- .../ui/components/ComboBoxListRenderer.java | 12 ++++++++- .../java/net/runelite/client/util/Text.java | 25 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index b71d5e8b0e..cfd5fca7c6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -492,7 +492,7 @@ public class ConfigPanel extends PluginPanel { Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); box.setSelectedItem(selectedItem); - box.setToolTipText(selectedItem.toString()); + box.setToolTipText(Text.titleCase(selectedItem)); } catch (IllegalArgumentException ex) { @@ -503,7 +503,7 @@ public class ConfigPanel extends PluginPanel if (e.getStateChange() == ItemEvent.SELECTED) { changeConfiguration(listItem, config, box, cd, cid); - box.setToolTipText(box.getSelectedItem().toString()); + box.setToolTipText(Text.titleCase((Enum) box.getSelectedItem())); } }); item.add(box, BorderLayout.EAST); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java index a397cc3050..5aeb710115 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java @@ -31,6 +31,7 @@ import javax.swing.JList; import javax.swing.ListCellRenderer; import javax.swing.border.EmptyBorder; import net.runelite.client.ui.ColorScheme; +import net.runelite.client.util.Text; /** * A custom list renderer to avoid substance's weird coloring. @@ -57,7 +58,16 @@ public final class ComboBoxListRenderer extends JLabel implements ListCellRender setBorder(new EmptyBorder(5, 5, 5, 0)); - String text = o.toString(); + String text; + if (o instanceof Enum) + { + text = Text.titleCase((Enum) o); + } + else + { + text = o.toString(); + } + setText(text); return this; diff --git a/runelite-client/src/main/java/net/runelite/client/util/Text.java b/runelite-client/src/main/java/net/runelite/client/util/Text.java index 890b24fd32..6158b9a32f 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/Text.java +++ b/runelite-client/src/main/java/net/runelite/client/util/Text.java @@ -31,6 +31,7 @@ import com.google.common.base.Splitter; import java.util.Collection; import java.util.List; import java.util.regex.Pattern; +import org.apache.commons.text.WordUtils; /** * A set of utilities to use when dealing with text. @@ -159,4 +160,28 @@ public class Text String cleaned = name.contains("') + 1) : name; return cleaned.replace('\u00A0', ' '); } + + /** + * If passed in enum doesn't implement its own toString, + * converts enum name format from THIS_FORMAT to This Format. + * + * @param o an enum + * @return the enum's name in title case, + * or if it overrides toString, + * the value returned by toString + */ + public static String titleCase(Enum o) + { + String toString = o.toString(); + + // .toString() returns the value of .name() if not overridden + if (o.name().equals(toString)) + { + return WordUtils + .capitalize(toString.toLowerCase(), '_') + .replace("_", " "); + } + + return toString; + } } From 69d788d20cfb1be60b242db482b0268a2b358e6a Mon Sep 17 00:00:00 2001 From: Lotto Date: Sun, 12 May 2019 16:13:47 +0200 Subject: [PATCH 35/43] client: remove overrides in config enums with same converted name --- .../plugins/chatfilter/ChatFilterType.java | 17 +++------------ .../client/plugins/fps/FpsLimitMode.java | 19 +++-------------- .../ItemIdentificationMode.java | 17 ++------------- .../plugins/npchighlight/RenderStyle.java | 21 ++++--------------- .../plugins/prayer/PrayerFlickLocation.java | 21 ++++--------------- .../config/RunePouchOverlayMode.java | 19 +++-------------- .../worldhopper/SubscriptionFilterMode.java | 19 +++-------------- .../plugins/xptracker/XpTrackerConfig.java | 16 ++++---------- 8 files changed, 26 insertions(+), 123 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterType.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterType.java index cf52fa969f..f0aef43471 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterType.java @@ -24,20 +24,9 @@ */ package net.runelite.client.plugins.chatfilter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor public enum ChatFilterType { - CENSOR_WORDS("Censor words"), - CENSOR_MESSAGE("Censor message"), - REMOVE_MESSAGE("Remove message"); - - private final String name; - - @Override - public String toString() - { - return name; - } + CENSOR_WORDS, + CENSOR_MESSAGE, + REMOVE_MESSAGE } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsLimitMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsLimitMode.java index 8536f7a67a..25f855f1c5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsLimitMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsLimitMode.java @@ -24,22 +24,9 @@ */ package net.runelite.client.plugins.fps; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor public enum FpsLimitMode { - NEVER("Never"), - UNFOCUSED("Unfocused"), - ALWAYS("Always"); - - private final String name; - - @Override - public String toString() - { - return name; - } + NEVER, + UNFOCUSED, + ALWAYS } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentificationMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentificationMode.java index 7b9f11217c..3a692822b9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentificationMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentificationMode.java @@ -24,21 +24,8 @@ */ package net.runelite.client.plugins.itemidentification; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor public enum ItemIdentificationMode { - SHORT("Short"), - MEDIUM("Medium"); - - private final String type; - - @Override - public String toString() - { - return type; - } + SHORT, + MEDIUM } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/RenderStyle.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/RenderStyle.java index d00029abe0..811ee5dda9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/RenderStyle.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/RenderStyle.java @@ -26,21 +26,8 @@ package net.runelite.client.plugins.npchighlight; public enum RenderStyle { - OFF("Off"), - TILE("Tile"), - HULL("Hull"), - SOUTH_WEST_TILE("South West Tile"); - - private final String name; - - RenderStyle(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } + OFF, + TILE, + HULL, + SOUTH_WEST_TILE } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickLocation.java index a39825677e..593ad87bc8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickLocation.java @@ -26,23 +26,10 @@ package net.runelite.client.plugins.prayer; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor public enum PrayerFlickLocation { - NONE("Off"), - PRAYER_ORB("Prayer Orb"), - PRAYER_BAR("Prayer Bar"), - BOTH("Both"); - - private final String name; - - @Override - public String toString() - { - return name; - } + NONE, + PRAYER_ORB, + PRAYER_BAR, + BOTH } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/config/RunePouchOverlayMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/config/RunePouchOverlayMode.java index 2ea02e883c..70d2564f26 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/config/RunePouchOverlayMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/config/RunePouchOverlayMode.java @@ -24,22 +24,9 @@ */ package net.runelite.client.plugins.runepouch.config; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor public enum RunePouchOverlayMode { - INVENTORY("Inventory"), - MOUSE_HOVER("Mouse hover"), - BOTH("Both"); - - private final String name; - - @Override - public String toString() - { - return name; - } + INVENTORY, + MOUSE_HOVER, + BOTH } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/SubscriptionFilterMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/SubscriptionFilterMode.java index 42352f64aa..b95a41a468 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/SubscriptionFilterMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/SubscriptionFilterMode.java @@ -24,22 +24,9 @@ */ package net.runelite.client.plugins.worldhopper; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor public enum SubscriptionFilterMode { - BOTH("Both"), - FREE("Free"), - MEMBERS("Member"); - - private final String name; - - @Override - public String toString() - { - return name; - } + BOTH, + FREE, + MEMBERS } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java index 6bac32802a..d3ded4f54c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java @@ -35,18 +35,10 @@ public interface XpTrackerConfig extends Config @AllArgsConstructor enum OnScreenDisplayMode { - XP_GAINED("XP Gained"), - XP_LEFT("XP Left"), - ACTIONS_DONE("Actions Done"), - ACTIONS_LEFT("Actions Left"); - - private final String name; - - @Override - public String toString() - { - return name; - } + XP_GAINED, + XP_LEFT, + ACTIONS_DONE, + ACTIONS_LEFT } @ConfigItem( From 1cd1bbb005a89ad466ebacb67a010698627b9c6c Mon Sep 17 00:00:00 2001 From: Lotto Date: Sun, 12 May 2019 01:43:19 +0200 Subject: [PATCH 36/43] client: add BufferedImage -> IndexedSprite converter to ImageUtil --- .../net/runelite/client/util/ImageUtil.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java index 16a6b1c78a..d7f579b722 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java @@ -24,6 +24,7 @@ */ package net.runelite.client.util; +import com.google.common.primitives.Ints; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; @@ -34,12 +35,15 @@ import java.awt.image.DirectColorModel; import java.awt.image.PixelGrabber; import java.awt.image.RescaleOp; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import javax.imageio.ImageIO; import javax.swing.GrayFilter; import java.util.function.Predicate; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.IndexedSprite; import net.runelite.api.SpritePixels; /** @@ -448,4 +452,74 @@ public class ImageUtil return client.createSpritePixels(pixels, image.getWidth(), image.getHeight()); } + + /** + * Converts an image into an {@code IndexedSprite} instance. + * + * The passed in image can only have at max 255 different colors. + * + * @param image The image to be converted + * @param client Current client instance + * @return The image as an {@code IndexedSprite} + */ + public static IndexedSprite getImageIndexedSprite(BufferedImage image, Client client) + { + final byte[] pixels = new byte[image.getWidth() * image.getHeight()]; + final List palette = new ArrayList<>(); + /* + When drawing the indexed sprite, palette idx 0 is seen as fully transparent, + so pad the palette out so that our colors start at idx 1. + */ + palette.add(0); + + final int[] sourcePixels = image.getRGB(0, 0, + image.getWidth(), image.getHeight(), + null, 0, image.getWidth()); + + /* + Build a color palette and assign the pixels to positions in the palette. + */ + for (int j = 0; j < sourcePixels.length; j++) + { + final int argb = sourcePixels[j]; + final int a = (argb >> 24) & 0xFF; + final int rgb = argb & 0xFF_FF_FF; + + // Default to not drawing the pixel. + int paletteIdx = 0; + + // If the pixel is fully opaque, draw it. + if (a == 0xFF) + { + paletteIdx = palette.indexOf(rgb); + + if (paletteIdx == -1) + { + paletteIdx = palette.size(); + palette.add(rgb); + } + } + + pixels[j] = (byte) paletteIdx; + } + + if (palette.size() > 256) + { + throw new RuntimeException("Passed in image had " + (palette.size() - 1) + + " different colors, exceeding the max of 255."); + } + + final IndexedSprite sprite = client.createIndexedSprite(); + + sprite.setPixels(pixels); + sprite.setPalette(Ints.toArray(palette)); + sprite.setWidth(image.getWidth()); + sprite.setHeight(image.getHeight()); + sprite.setOriginalWidth(image.getWidth()); + sprite.setOriginalHeight(image.getHeight()); + sprite.setOffsetX(0); + sprite.setOffsetY(0); + + return sprite; + } } From da2c195a17f253fe96fa2057992cb4749963a015 Mon Sep 17 00:00:00 2001 From: Lotto Date: Sun, 12 May 2019 01:44:39 +0200 Subject: [PATCH 37/43] client: change ClanManager to use ImageUtil image converter --- .../net/runelite/client/game/ClanManager.java | 56 +------------------ 1 file changed, 2 insertions(+), 54 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/ClanManager.java b/runelite-client/src/main/java/net/runelite/client/game/ClanManager.java index bbfd3452cf..0b80bbc7e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ClanManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ClanManager.java @@ -30,10 +30,6 @@ import com.google.common.cache.LoadingCache; import java.awt.Color; import java.awt.Dimension; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.DataBufferByte; -import java.awt.image.IndexColorModel; -import java.awt.image.WritableRaster; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -152,8 +148,8 @@ public class ClanManager for (int i = 0; i < CLANCHAT_IMAGES.length; i++, curPosition++) { final int resource = CLANCHAT_IMAGES[i]; - clanChatImages[i] = rgbaToIndexedBufferedImage(clanChatImageFromSprite(spriteManager.getSprite(resource, 0))); - newModIcons[curPosition] = createIndexedSprite(client, clanChatImages[i]); + clanChatImages[i] = clanChatImageFromSprite(spriteManager.getSprite(resource, 0)); + newModIcons[curPosition] = ImageUtil.getImageIndexedSprite(clanChatImages[i], client); } client.setModIcons(newModIcons); @@ -166,54 +162,6 @@ public class ClanManager return cleaned.replace('\u00A0', ' '); } - private static IndexedSprite createIndexedSprite(final Client client, final BufferedImage bufferedImage) - { - final IndexColorModel indexedCM = (IndexColorModel) bufferedImage.getColorModel(); - - final int width = bufferedImage.getWidth(); - final int height = bufferedImage.getHeight(); - final byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData(); - final int[] palette = new int[indexedCM.getMapSize()]; - indexedCM.getRGBs(palette); - - final IndexedSprite newIndexedSprite = client.createIndexedSprite(); - newIndexedSprite.setPixels(pixels); - newIndexedSprite.setPalette(palette); - newIndexedSprite.setWidth(width); - newIndexedSprite.setHeight(height); - newIndexedSprite.setOriginalWidth(width); - newIndexedSprite.setOriginalHeight(height); - newIndexedSprite.setOffsetX(0); - newIndexedSprite.setOffsetY(0); - return newIndexedSprite; - } - - private static BufferedImage rgbaToIndexedBufferedImage(final BufferedImage sourceBufferedImage) - { - final BufferedImage indexedImage = new BufferedImage( - sourceBufferedImage.getWidth(), - sourceBufferedImage.getHeight(), - BufferedImage.TYPE_BYTE_INDEXED); - - final ColorModel cm = indexedImage.getColorModel(); - final IndexColorModel icm = (IndexColorModel) cm; - - final int size = icm.getMapSize(); - final byte[] reds = new byte[size]; - final byte[] greens = new byte[size]; - final byte[] blues = new byte[size]; - icm.getReds(reds); - icm.getGreens(greens); - icm.getBlues(blues); - - final WritableRaster raster = indexedImage.getRaster(); - final int pixel = raster.getSample(0, 0, 0); - final IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel); - final BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null); - resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null); - return resultIndexedImage; - } - private static BufferedImage clanChatImageFromSprite(final BufferedImage clanSprite) { final BufferedImage clanChatCanvas = ImageUtil.resizeCanvas(clanSprite, CLANCHAT_IMAGE_DIMENSION.width, CLANCHAT_IMAGE_DIMENSION.height); From 64019ea785ab062f0e0524ccbeb6ca60260ad07a Mon Sep 17 00:00:00 2001 From: Lotto Date: Sun, 12 May 2019 01:47:40 +0200 Subject: [PATCH 38/43] client: add emoji plugin Replaces various emoticons entered in public/friends/private chats with their corresponding emoji images. Co-authored-by: Adam Co-authored-by: Tomas Slusny --- .../runelite/client/plugins/emojis/Emoji.java | 114 +++++++++++ .../client/plugins/emojis/EmojiPlugin.java | 192 ++++++++++++++++++ .../runelite/client/plugins/emojis/LICENSE | 1 + .../runelite/client/plugins/emojis/blush.png | Bin 0 -> 1323 bytes .../client/plugins/emojis/broken_heart.png | Bin 0 -> 16185 bytes .../runelite/client/plugins/emojis/cat.png | Bin 0 -> 1501 bytes .../client/plugins/emojis/confused.png | Bin 0 -> 1225 bytes .../client/plugins/emojis/cooking.png | Bin 0 -> 1320 bytes .../runelite/client/plugins/emojis/cowboy.png | Bin 0 -> 1371 bytes .../runelite/client/plugins/emojis/crab.png | Bin 0 -> 15828 bytes .../runelite/client/plugins/emojis/cry.png | Bin 0 -> 312 bytes .../runelite/client/plugins/emojis/dancer.png | Bin 0 -> 15813 bytes .../runelite/client/plugins/emojis/dog.png | Bin 0 -> 1457 bytes .../client/plugins/emojis/expressionless.png | Bin 0 -> 1154 bytes .../runelite/client/plugins/emojis/eyes.png | Bin 0 -> 1406 bytes .../runelite/client/plugins/emojis/fish.png | Bin 0 -> 1280 bytes .../client/plugins/emojis/flushed.png | Bin 0 -> 1434 bytes .../client/plugins/emojis/fork_and_knife.png | Bin 0 -> 16173 bytes .../client/plugins/emojis/frowning2.png | Bin 0 -> 1215 bytes .../client/plugins/emojis/grinning.png | Bin 0 -> 1348 bytes .../runelite/client/plugins/emojis/hearts.png | Bin 0 -> 16179 bytes .../client/plugins/emojis/hugging.png | Bin 0 -> 1374 bytes .../runelite/client/plugins/emojis/hushed.png | Bin 0 -> 1285 bytes .../client/plugins/emojis/innocent.png | Bin 0 -> 1439 bytes .../runelite/client/plugins/emojis/joy.png | Bin 0 -> 1444 bytes .../client/plugins/emojis/kissing.png | Bin 0 -> 1181 bytes .../client/plugins/emojis/neutral_face.png | Bin 0 -> 1196 bytes .../client/plugins/emojis/ok_hand.png | Bin 0 -> 16210 bytes .../client/plugins/emojis/open_mouth.png | Bin 0 -> 1229 bytes .../client/plugins/emojis/party_popper.png | Bin 0 -> 1403 bytes .../client/plugins/emojis/persevere.png | Bin 0 -> 1366 bytes .../client/plugins/emojis/pile_of_poo.png | Bin 0 -> 1286 bytes .../runelite/client/plugins/emojis/rage.png | Bin 0 -> 1233 bytes .../runelite/client/plugins/emojis/scream.png | Bin 0 -> 1413 bytes .../client/plugins/emojis/see_no_evil.png | Bin 0 -> 1483 bytes .../client/plugins/emojis/slight_frown.png | Bin 0 -> 1243 bytes .../client/plugins/emojis/slight_smile.png | Bin 0 -> 1253 bytes .../runelite/client/plugins/emojis/smile.png | Bin 0 -> 1321 bytes .../client/plugins/emojis/smiling_imp.png | Bin 0 -> 1250 bytes .../runelite/client/plugins/emojis/sob.png | Bin 0 -> 1349 bytes .../plugins/emojis/stuck_out_tongue.png | Bin 0 -> 1314 bytes .../emojis/stuck_out_tongue_closed_eyes.png | Bin 0 -> 1344 bytes .../client/plugins/emojis/sunglasses.png | Bin 0 -> 1311 bytes .../runelite/client/plugins/emojis/sweat.png | Bin 0 -> 1081 bytes .../client/plugins/emojis/thinking.png | Bin 0 -> 15849 bytes .../client/plugins/emojis/thumbsdown.png | Bin 0 -> 1223 bytes .../client/plugins/emojis/thumbsup.png | Bin 0 -> 1218 bytes .../client/plugins/emojis/triumph.png | Bin 0 -> 1433 bytes .../client/plugins/emojis/unamused.png | Bin 0 -> 16276 bytes .../runelite/client/plugins/emojis/wink.png | Bin 0 -> 1303 bytes .../runelite/client/plugins/emojis/yum.png | Bin 0 -> 1318 bytes .../client/plugins/emojis/zipper_mouth.png | Bin 0 -> 1296 bytes .../runelite/client/plugins/emojis/zzz.png | Bin 0 -> 16185 bytes 53 files changed, 307 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/LICENSE create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/blush.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/broken_heart.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cat.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/confused.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cooking.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cowboy.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/crab.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cry.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/dancer.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/dog.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/expressionless.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/eyes.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fish.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/flushed.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/frowning2.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/grinning.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hearts.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hugging.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hushed.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/innocent.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/joy.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/kissing.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/neutral_face.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/ok_hand.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/open_mouth.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/party_popper.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/persevere.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/pile_of_poo.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/rage.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/scream.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/see_no_evil.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/slight_frown.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/slight_smile.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/smile.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/smiling_imp.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/sob.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/stuck_out_tongue.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/stuck_out_tongue_closed_eyes.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/sunglasses.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/sweat.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thinking.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thumbsdown.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thumbsup.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/triumph.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/unamused.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/wink.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/yum.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/zipper_mouth.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/zzz.png diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java new file mode 100644 index 0000000000..b0ed60a55e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019, Lotto + * 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.client.plugins.emojis; + +import com.google.common.collect.ImmutableMap; +import java.awt.image.BufferedImage; +import java.util.Map; +import net.runelite.client.util.ImageUtil; + +enum Emoji +{ + SLIGHT_SMILE(":)"), + JOY("=')"), + COWBOY("3:)"), + BLUSH("^_^"), + SMILE(":D"), + GRINNING("=D"), + WINK(";)"), + STUCK_OUT_TONGUE_CLOSED_EYES("X-P"), + STUCK_OUT_TONGUE(":P"), + YUM("=P~"), + HUGGING(":D"), // >:D< + TRIUMPH(":"), // :> + THINKING(":-?"), + CONFUSED(":/"), + NEUTRAL_FACE("=|"), + EXPRESSIONLESS(":|"), + UNAMUSED(":-|"), + SLIGHT_FROWN(":("), + FROWNING2("=("), + CRY(":'("), + SOB(":_("), + FLUSHED(":$"), + ZIPPER_MOUTH(":-#"), + PERSEVERE("_"), // >_< + SUNGLASSES("8-)"), + INNOCENT("O:)"), + SMILING_IMP(":)"), // >:) + RAGE(":("), // >:( + HUSHED(":-O"), + OPEN_MOUTH(":O"), + SCREAM(":-@"), + SEE_NO_EVIL("X_X"), + DANCER("\\:D/"), + OK_HAND("(Ok)"), + THUMBSUP("(Y)"), + THUMBSDOWN("(N)"), + HEARTS("3"), // <3 + BROKEN_HEART("/3"), // "), // <>< + CAT(":3"), + DOG("=3"), + CRAB("V(;,;)V"), + FORK_AND_KNIFE("--E"), + COOKING("--(o)"), + PARTY_POPPER("@@@"), + EYES("O.O"), + SWEAT(";;"), + PILE_OF_POO("~@~"); + + private static final Map emojiMap; + + private final String trigger; + + static + { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + + for (final Emoji emoji : values()) + { + builder.put(emoji.trigger, emoji); + } + + emojiMap = builder.build(); + } + + Emoji(String trigger) + { + this.trigger = trigger; + } + + BufferedImage loadImage() + { + return ImageUtil.getResourceStreamFromClass(getClass(), this.name().toLowerCase() + ".png"); + } + + static Emoji getEmoji(String trigger) + { + return emojiMap.get(trigger); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java new file mode 100644 index 0000000000..bfca89c184 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019, Lotto + * 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.client.plugins.emojis; + +import java.awt.image.BufferedImage; +import java.util.Arrays; +import javax.annotation.Nullable; +import javax.inject.Inject; +import joptsimple.internal.Strings; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.IndexedSprite; +import net.runelite.api.MessageNode; +import net.runelite.api.Player; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.OverheadTextChanged; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.ImageUtil; + +@PluginDescriptor( + name = "Emojis", + description = "Replaces common emoticons such as :) with their corresponding emoji in the chat", + enabledByDefault = false +) +@Slf4j +public class EmojiPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ChatMessageManager chatMessageManager; + + private int modIconsStart = -1; + + @Override + protected void startUp() + { + loadEmojiIcons(); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + if (gameStateChanged.getGameState() == GameState.LOGGED_IN) + { + loadEmojiIcons(); + } + } + + private void loadEmojiIcons() + { + final IndexedSprite[] modIcons = client.getModIcons(); + if (modIconsStart != -1 || modIcons == null) + { + return; + } + + final Emoji[] emojis = Emoji.values(); + final IndexedSprite[] newModIcons = Arrays.copyOf(modIcons, modIcons.length + emojis.length); + modIconsStart = modIcons.length; + + for (int i = 0; i < emojis.length; i++) + { + final Emoji emoji = emojis[i]; + + try + { + final BufferedImage image = emoji.loadImage(); + final IndexedSprite sprite = ImageUtil.getImageIndexedSprite(image, client); + newModIcons[modIconsStart + i] = sprite; + } + catch (Exception ex) + { + log.warn("Failed to load the sprite for emoji " + emoji, ex); + } + } + + log.debug("Adding emoji icons"); + client.setModIcons(newModIcons); + } + + @Subscribe + public void onChatMessage(ChatMessage chatMessage) + { + if (client.getGameState() != GameState.LOGGED_IN || modIconsStart == -1) + { + return; + } + + switch (chatMessage.getType()) + { + case PUBLICCHAT: + case MODCHAT: + case FRIENDSCHAT: + case PRIVATECHAT: + case PRIVATECHATOUT: + break; + default: + return; + } + + final String message = chatMessage.getMessage(); + final String updatedMessage = updateMessage(message); + + if (updatedMessage == null) + { + return; + } + + final MessageNode messageNode = chatMessage.getMessageNode(); + messageNode.setRuneLiteFormatMessage(updatedMessage); + chatMessageManager.update(messageNode); + client.refreshChat(); + } + + @Subscribe + public void onOverheadTextChanged(final OverheadTextChanged event) + { + if (!(event.getActor() instanceof Player)) + { + return; + } + + final String message = event.getOverheadText(); + final String updatedMessage = updateMessage(message); + + if (updatedMessage == null) + { + return; + } + + event.getActor().setOverheadText(updatedMessage); + } + + @Nullable + private String updateMessage(final String message) + { + final String[] messageWords = message.split(" "); + + boolean editedMessage = false; + for (int i = 0; i < messageWords.length; i++) + { + final Emoji emoji = Emoji.getEmoji(messageWords[i]); + + if (emoji == null) + { + continue; + } + + final int emojiId = modIconsStart + emoji.ordinal(); + + messageWords[i] = ""; + editedMessage = true; + } + + // If we haven't edited the message any, don't update it. + if (!editedMessage) + { + return null; + } + + return Strings.join(messageWords, " "); + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/LICENSE b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/LICENSE new file mode 100644 index 0000000000..9e2a9503a0 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/LICENSE @@ -0,0 +1 @@ +The images in this folder are derivatives of "twemoji" (https://github.com/twitter/twemoji) by "Twitter, Inc", used under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). The derivatives are licensed under the same license. \ No newline at end of file diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/blush.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/blush.png new file mode 100644 index 0000000000000000000000000000000000000000..7024942ef0f45b10647ef71ec21a477b4b4f0d1a GIT binary patch literal 1323 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 fW`n)Y5bl9y&kkB zx;ZokGPk%8$JETIxGWoHOkv#|erA$L#x}q?Kr@$xXiSW5j1A?(p6>xg|5z4d;+xz( z@B7~Kd!FC(b?w!@@-_L7(2LE!w5vUcJUK zbWufav|~%8>b=#dQIWj-+%1y1X#x zO=2UIpDtVW1y6P?D$8*S$CJsVHfhj`QUgwqB#G#_( zxVX%T0;*bMLSmC_#~{KEGG)43{Np}oY3lUo>${q)K18L@HdUyY9|8e zIKcfNAvQ^2SdU0S4h(a5XGf|cWJ7J1I9L=WMvLJl9tg6Vwqx*%mgQKA1caHjFjfu0 z8cZ5<$Otry#lUI|AqHj@=qzCa$l19a-r}&9nvG7Y#b|I4go`9i7Ax&^ILa)9!Q#}> zIjmbq$czvMIo}-gy^OWo5lcBGz{sK$5XD%o3#y}{EGD929CbR?s$0;ZxERd-c;0xo69tDFxiXFbZfEy{(h%8*YP32np;v&W0(Pdj$M)}fsBX2;Th zbX&9IJCyUazYm47W2uENT&{}p`BNpCF5%P%?aD>|7k>M}w(9J}uIV#Xy+?M>_1Wio z?R(S3%4p>JV07U^sHnu*|0bg@^Y{H#Jkb1!$&oGgEFx*J6LsV!1HTUG&}yn%(+-5)1wSOJ$$6R%(Hp_&XSXz zu1qI=xzBwyxM#WyC*PMy$~67@rtzMNKh;2zUF{BK6wJKyvUSWWTRQ`9Bs?>5WZ54}08nX(08Taj$dT-CK|WeTM%&!(UN0P4`Er z?!s-K=3n2p>i&kRwfA*=_UNH)wKtsUw&CG|$!6?QXJy{@s;L+69X-8X{wXgQeeC1$ z^}l&f)a|);_2;8+XCEA3Y-cpqkGjn-*#=+!_SMz_?enqpCzFVI>YFQv^ZCi4TN|{k nmkxCZZyl_hTf6Y%j(Z+LX4h?CM@DW0Au+`5^3lf}&$j*rOk8Qi literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/confused.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/confused.png new file mode 100644 index 0000000000000000000000000000000000000000..0d3275a23660e27b81ce51dd679b08be5d17e1bc GIT binary patch literal 1225 zcmbVLOKj6-95+on3IbN73IPXZ+#Z;OV>^xG*lI|V*r91Z5CVyZ!~rhA=eFr~sHzD|_V@7b z_y7H$$BTu%8`p1NPY}e$T)$ij*5GXq;jhAX7VxqSDMM%wR#07a0g*DG2FRSH4ucX< zjmEJXpqC&*V`g~>4dn+U9a>>Ez=VCv!EA!)P5O?ij{rn!VA!-1)XOVV6lod>>JXo2 z^G*g-&Hiy042~Dd`uK=08dP!*+3QQ#fCZ3B`c}>MBtJnd*p=`;xMnDF0fI&n)S^>E z`68KtE+F}EjMllHI4Ou>ju+#R=x#E?axsP#87@k*oWzO}%aKbDh1Fc6B9-Lqk`_KC zs47B^#4z=GJzVbzLwA_rL{Vhe2os6W7(sgt8>v2RdtFTnGVpZQbdU*cGO(y>a1bM@2t|l4h zZgrsmh`o^xxF#-&T9ctZY5^PN0LRCLSVg0G(NJlv5{=Vp571~s7X?ia zbU}>>O*<>`SuPdj<%}RiBN>iU#CTSS#Fea);>EO(meWmc&i0UM>!7J^V(levY*nt5 zae<1UTZXXK?1EwyBIs42LuN8T)dh0bA=5Ts-TN{q(_+*zaLqAbWL;>H3wf5z6@2)A z@h|d?Pt6~LonnG!`A_pSuW&~O+vQQfhvi`cHl83CkBSNBx8N~5QXD8NA7=CKuJ3y_ zrM#NTRutmx^?k3Wv-i(Q-|L&7U&-8_nleP8}YyMp0-tqgU|5?{P*LpIorDr#6craPqk(}5a3Vpuz zm%p!V>h6B`aK6z7^FLwodwoB9oyZ6j#>mkR;SuTIh5g7vkLwt_SP&EYkVp1ci6gLR$PFzXm$ahDO2eM zGElUEt!F_qf~?wR!#0+c0UxJpNwP>v^PmTzLB_o56%$4H7N=_pRo0>ujyjV>(=dUG{hkj2&| zU+@&iioWj%Bv~$(iE@On-CmOBd7h*gl3{SDfqMg%uLQW|HB>E#z*Akr@eSKTLyJnm zF8Of`GOdJQI+@I}Var=e6igWzC=N*z6lt1aT#MSCFN42ntf=kf1{^@jz_UxP3hSXa zRKYNJ*LD;tLN>xC*MLP)`bAqUnZWW>VjP1ngl1?$tU&9W#__n$@;t8T(HLG}V+>A5 z02k3CG{-ivRXZ!;sRY*|aZ!qkMj4ux_$HcW6B5UZ49!R_5>v&dEYDXg6;yp2(02tJ zX}u;^NV-7rZ8vAz{najLFWSEC6>SGiCc~<8=(^2@rP*b#F)ULhY7w}`HlVe-wuvt0 zSuj@M@bBWU;I;poKN6B6!)EzM^Hi^3M~2(wQGkc#VFDJMAQz6x;M%Wmgk$!6dpajI zl99P9zw4!)>#1nsA-R!?cBy@Tp4hVEnHM^GiWh&JT^Nl#`k4Fj8^;o9`H%7Kb8|mm zJyYH_G<;=d{G&6Ujl6PXi*Ap9F*$!}>b0X|>CW!b&Zi$X+`0LA-P?Zb{SWt!9QuCt z@=uq4eNfKNT>RnnqhsC^dlruK)8Aflc08Nu>i+GkcMlwX3(^_or-q>*d^y{(@Lv|P zd!N?{kwHpq$pv2)CN5k6$aRm@Bg5z9+Qa7`KUaU}hJCdS4M%G3*^s|&=s=#n*VXqRSAV(XouNcc9pr$dq^x*6(X;z6BJk&v literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cowboy.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cowboy.png new file mode 100644 index 0000000000000000000000000000000000000000..9c255c613b6081abcbb7602d27361d8717b7399b GIT binary patch literal 1371 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 literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cry.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/cry.png new file mode 100644 index 0000000000000000000000000000000000000000..dda95de8f96a1f27e1893d854b1af7f022d26e55 GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{D72XiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-0{?RV8FpFdGn>*pZ_aMCvS0cvP)!15is5R>@zQ?f%pw0 z=D?e&YJ7Toggej7Fm%uSDRMDM>h?j!&V=h57jyD|iksAzopr0KdkCfdBvi literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/dancer.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/dancer.png new file mode 100644 index 0000000000000000000000000000000000000000..4a307a4d4da930e1b99322437cf4dc21bb42903b GIT binary patch literal 15813 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 E0?*VvHUIzs literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/expressionless.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/expressionless.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6904de0622e2954c7ec4e765cc0540c0759818 GIT binary patch literal 1154 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 H`NHHs6Ys^i literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/flushed.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/flushed.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca84e2af01239b489b3d1be13169caddddb8b18 GIT binary patch literal 1434 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 ONO(wuW=-?>0sjEWP9^{V literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/frowning2.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/frowning2.png new file mode 100644 index 0000000000000000000000000000000000000000..bbc46462e141c3547f1b40c9e77f045834967254 GIT binary patch literal 1215 zcmbVLOK8(z9FIC0|Uwu31sk z9mL@fFN%sFJBZ-H2cjrL)PnhzAdP@bzU|r-w1bK=M8E`~Cj!p=6?U zC-34&M|Ym-vm>b=V<@K+A5OW{pFXafhIfChr7 z=+`q@l#TBbRcQDW594zU3$qELq0zMzwHF{V2fB4LLVX^6K#{r@p*n(bHf}{hkKR_Y zLAsR4sHI+2(5S{eWP>YW0Rtd~bd5gK5#0zitt;Zacg;}bGz9fVs2QiS@gy0AHXwsO zo>sZ~Fc}hjTu=!61G`8+%kc~=FkFCUIgu4amLq2$3R|u3Ca8Y5_Dz(k5mn@&wxK?06y>lV_XNqUM(4i->^!k*5AU|8|^ zoUrN4CJLvFaTSZSv*YszGtyM+yTKoz%Rs=s?F9b9?$MJv;hxvSc&d;&AJSgkT z$LE@5o(~4Xp@2WiaWa=ffQ%U{h?zQP^pZRbV-ALfP$n0SJ0JSw{jOOD_%>qzd)$iK$pw@>cK%fy#Qt$N$y ziIKqJ&Z;*zBKJo1|8(kWW9_zV?!?#k8|0yzRpH5phXixYk8`KrRV0I3*59cZJoCJJ`{~m6RBJz9 r_4yn({K|M+d8I1x>Gk^;UsiV!cULT3H2Jgr2bL#dazeV++%@`nL{K#g2fUyHtS@QDmso`P~7cG}&rtU3UT>2?9&NmK0s zS)l5Jug!u8hSd%jxjf9LQ=(>@l?{Wnz-R4LwTi z45pcMDFJ$o_8|v!4rOxMP@g8~#O6(Sq#_~$6F?QOm_^GKD^X&BS44a7nkMiC6WA9e z7DeUL9eBca03M`5q{ar?@UTF!L7|P~U%)wr4bhB1vpmVLA|r?li!VI{^5*E>VpdX? ze4$g6=!LK((sa38rpf`zc6w-55CodxXpSS11?di2P_2-b+gxRkfU7x12^zMAdyHzq z?uStVDP0V~ETz-S#Fo31D3mg~qLyfuVrbL!;##nFVHW%=V?}E>H&_C67Pxl5qoI0q zH&?+ZcMo>t86q{}Hpf6kQHzqT^_#$gNhwO8Ka_6hA_sVmXY~LX3ThfD6nK^_=vvDyV4y*9MnUb}=R5?Q$U&nramzo7#_U{2DktBc zOLxoIcb6l7%)IpXoz!2Sr|yo6r{OcZ+gJT|L%DFY@5`~!wZpB`C+RB(Tkc*Gubdm6 zImLYQf$-xev7aXrUtb7+`^9HJT-);J?XB}4isJ`}{jd6G&#*U-Q+v9akL}CMO^wf9 zKR;4#935=Bc-(^9AHDRR`|G6q`%H4`7&ZUZ%{!A9?_HPPA71yTNM_T9l!TTL%w{_8Kg@%TzMWwa1M1XRt}9$Dpk91EN+){oRo)i|+; z-+I#L3-$XB9N3o8c*y$_0Gpl(>~Qu6lKT0kM?e%Rv#TbQa4TBzE@YzVBg<(Z0&G7whQ^k Ml5$469N+c&KPTkm`v3p{ literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hearts.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hearts.png new file mode 100644 index 0000000000000000000000000000000000000000..4639733791b63f61a3ac9950b347f09b01078b0e GIT binary patch literal 16179 zcmeI3ONbmr7{@CHL{|c$LL>+_6GcUPx~rel?aai@%*0)jS(n|BY)+;hHM?zQy2tL` z%Q~Q8zrDWp;)$hGO8|fqt1I;l@=HGV9mn4d{gE~NbANB;QUbsO50lR^@Zm>~0`R;a zw6@Z%<^|h}x<$v2TvQx%d$=|L9AEP z?4)VWmZW~aU+k;JDBhN!Wm%G}NQxrj8e*~+rp`bNlheZ><2ZGccyZ86gD4b8T*r-e z(@LR05>1{_zq-9dV7RGjjJe3=Z3;##tt+uzwb?adb@Ea1MPbf>Yy&plVApLE`Z)nlt#%; zv>@d~&LGZ9oCfU$0Ex2D4Gn??ZbTWnWpipc)MX5%*|cAd13dkmPCfE=NxxR>RV)z1n2v|6Jsm&W09t}|g*!z6V=4~<$L;FhbZr9fAaMWf_cqS4k2(S>bQR9#Qg zy|(EqhBXeIbDs%aM{#f!`RC%On=P206DNpF-b!ISdnYSwL^YfKb}-u}-&K+9D4M95 zx*~c$X_KQP5&D{MYARF>Q!Ps~?$b8m1m&UZ|I@LWai2yX4E`=!$LV8lvxN zj_7!R-p~`XJy5f<#AK9T8o1u zQ9JEBFROLk?u79$5Q=~fhVjxrHx zmnrUPG*ov|bZCvpHZ*c;WD;aplZw%d{Gh!z6GO2NjTVWKt4YVeH!#uU1u9fy>PoMO$&21CnvgHi#kz^n}xeymgW`byvSKjPG7tQIN4?g%hF64 zU4M%lJDuIEzNyIgks$dVx#nfs^%C1PFVn75&sV}AC4I{pN)_k4$c1AFV-sJpQPt3O zRWD0)G3~J)3{YpQ9^iXOLbiX1_vXxp7Unu$TI84$MvlXUlDiIPJK(SsU$*f*Uz%L> zXEw*lv2!>7OnY=Uqf)VW5()_0|d?=OUqJXeX zj*HEQQaLUP2;1bi*nB9J|d?=OUqJXeXj*HEQQaLUP2;1bi*nB9J|d?=OUqJXeXCa$IFtFtJ?@5}b_i?P>#v9|F`wSu>@(F9=sNdVq>3xK~4@b7N` z?8*TAei;D!0{~7&@4kBT9013``h`~GcCmhNfNSxG6Zk(8c<1bG@+SK|>BidT0r>R` z`6X;gtM%p9;O9@j|K!-W@`K;KaQn{rlh=ND;>&yAzxmkp<Szszd+) literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hugging.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/hugging.png new file mode 100644 index 0000000000000000000000000000000000000000..146af729064b96a972807421cd21d656c164409d GIT binary patch literal 1374 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{D72XiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-lO)W`O zsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S;PP%yXDGc>id zFf!3mFfuSS(>JixH#E^TFtjqTv@$SMfC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz{qpj1 zy>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@x4_pIZg5^PG@yV%reBd*pl_&Wpr4xy@)uZjaY;}r!Wmdq7l%|9r0NHy z7U!21B?IFlO&O*c7&4a6BsFpIWGChrManjC7v#}N>@2e7^0=Xz?c(ce=(9}l>FKkE5yj>M!KvA>6${-5@K-7WZas?fjV?(e#|pEq+? zhH<^^S>wl1&llSr|DEu>vC6VPQ}k0G&-Vqg&ziVC_w)We z==i>0@LeDOugyk(kGNb~V)k>jW|}L*lX|Z23*~Oi)Bd$y@B4h2Ii=D+*XjJ;X8O3E z>)&ag&;2~#=14Zj^FP{T_h%2V&|ru(U?>GrRwY4x!T-qx4CV*^gUYWuPZ!6Kid#14 zuJbho2(Vm`bYK6FVdQ&MBb@0IlO)W`O zsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S;PP%yXDGc>id zFf!3mFfuSS(>JixH#E^TFtjqTv@$SMfC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz{qpj1 zy>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@x4_pIZg5^PG@yV%reBd*pl_&Wpr4xy@)uZjaY;}r!Wmdq7l%|9r0NHy z7U!21B?IFlO&O*c7&4a6BsFpIWGChrManjC7v#}NOLId5 z%haSKU4uju16|WplVsgQLlbk|L?c7tSm^wL{!Ss6O6_+IDC8xsd&IH;G)oYGdua$FAYGO%#QAmD%4lES} zWaO9R7iZ)bC^$QVV%=OpBRn%NCBM8_6BJDlU%R9hWtOF;xE1B+DuBb;Diezvi1R;0 ze+s$brw??LJ}9vuB_5a%Fhzox@T>sjz%x^79xw+L0kg^}_Y>N{Y*rWG6XN>+jBlDN z!;fR0|IYY+I_SQwM{{eJ`niQBn>*EipYT2~MK{Nbd2yB8%N_fOINxZmyV9+&0yichxKZ|l~$x87!Z zkH*P4M$fl9W_d8JY*53Spz}R;TskoKX z=g!w)z{4Wz^nUO6dH?GL9xEJaoXBrIDOZ<+B~Rmlifq@adx0M;FI}8=M)%^QdyCFq zSocDuJS^Z3vx>6uf#jpf2iGx}tN&2HD<%1&|Cry*leelWeD?gl^5*hqp#%o)2#$nS T!Jpzl3mH6J{an^LB{Ts5HfGJs literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/innocent.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/innocent.png new file mode 100644 index 0000000000000000000000000000000000000000..01ee7c2f754c917c80a392c4ab59b4abad4c6a0e GIT binary patch literal 1439 zcmb_beM}o=7(cTtF(_L!Xi(!k5B@+$dv|TG^e$9Zu4PnchouU-EpokkOHb%sy}PcZ zxX26y9cIyBSYl>OaApatEQ)MIK4%G$fisY}Fc)W>n-1ArrbNvotM36t{~(JozRCOj zJiq7ne7#ZS-I<;Ba2A3f+3s?uPv7-<_a?Zys2nfc9@1R3TD2V1Vw?gHhad+4>JD@D zzy~;?>E$UFywa@fe}GRAl~0<{sOxFjCo_y(Y%0Z=bWcI?K`7>0_1 z9jl={geSs+kXW8jKy||F=MxP)Enp>2p~Z0q0)&Caq498|q%v_kwt~yRv;K@@=!%He zV8>QT)q1K>R#pH?8LbAMG~3W3+DKBg&15M=O$2Gh2^uFY27+V=njuJZZD7!vA_N(q zvuw>4yxFmkrbQSWkHuofnAs>R^*Bk>G)|aslgR)j3~H04adCsB=4B9^K;;!NqKUGE z>WExGj%s!cGF^2c9PxP8fhBb2I1`kNvE_W@Oo zDm=_bFfXGFV|Qmmx*%l3>{3LS6t2-J^U*MnG`G`^!5^a_3Jf2lIJ4PC7|aAA7--&N zHE=;d830dNY-W>%vf`KJ#!MAdg=9@uLvjRVSv~7TXhDrA335z*LQm7G*G`~_ z`+!iU$YFFP&WyMLhkxh)s=n}FKd=CSXmqtHrNuR0szP}_rvGY(UCq2fd z#@lb5srqUn$|tXMH*dQ+UN+EC&|0_k`QD$pp6hU z_s|FSZux!Ky)anXo!ADQ8+uZ?47YO4=dDivKLa^(?Uy=;+3t2a{PC}g-)!5G+Ho)2 zIq(e=3|@uvw{&{;=ftrWp1yo+{&93q?u()5$YXZ}@-F1t6c{(Op51 literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/joy.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/joy.png new file mode 100644 index 0000000000000000000000000000000000000000..6bc95ee669d52efe9836473b180bccf7b1104dc1 GIT binary patch literal 1444 zcmb_beM}o=9KMZzmN_(z?cJ4r-AO5JuSgy3NLxdbDRA7qr6=^RyF1!K zmQ2io7#tX*W9&nguuL)s4EMntStLWo&`mSK#&8S4DI{|Yk|m2FOT_npqJNOZ7%#bd zKkoNDzvuV$QIYS>^z|9*5d=y16fk~m)!ub!@ar~h^ugsN)g4j;Qdmu}GC&->R1Q#2 zl&t`M!16V_hCvR3q{W3`NDX-lX-;hC?73)8l7<9Ppt5K(S|uuU(uOVa(r~X`;~2VV zqE_0lB~c-75$cj;fSUAX9Yu6qq!}kDoHXhPk|rpcAkpOqgWhC5 zO#7MqWnb`Q!y>90qj5ZuNaz#UdP%OpNs6Ly!hjnLI%uI&YDASy>O>_o#lQfClZBWn zNFu5+vgJ~>YQvz?r4XVquXlx5RF)G3Q-&wm7*6U5JQ~&FTC`SFKloe5s@6)dCI)an zP^4;^gY^h!rob?FPj;jkLN)XbS%5`hs~Cx^jsj8jFg6VS(enaNlVNkVndf;OOOQav z@kXVl$(q)JLeilHu-R&@)ywO9~&DWPoB%CrP8fexFNfA2_z6!9}1fy8+$IceyrHfHE!+NyZKaoR%Q1D*Kw<@ z`}5tQrw-MJDvpml8YsBhUpqc1pYLesJQOeKyx$yW1`iP5U#k10_rm3a#IfDz#MqU+ zWzUQrx4hRq`NyDVcDRK9^48Z4TYl-uegDkx)Y-hL$Z%WSR>98@w|2j8R@E10G BKPCVG literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/kissing.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/kissing.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc6f2ee44280e2d1c64512dbaa88621b06225cd GIT binary patch literal 1181 zcmbVLPiWIn7|*QA5QjU+aOxpuA_}I-OOv*VtGXr8)va}O)$M4OyslwQUY5MA*$$$+ zh4A-plvkxDn~ZL&qa%it5}KdWJa)F+B`NY&XMvemKL>wv}N9r5vC0R9LoqrhGUs zl`oo8qo!;z`}WeEp+X28hz&Y)DsG^J8D^1JA?N6sW9UT{JepyaoEpmY(<<^IEya_p z2@+{KCC7mzrv-60E$|@8@iGTQmIn$iD?FgGJ^b%Txug9ZcBw>@klmyQ^XVKk024Doa+1jozemWkb< zo+y$sE;Kw2#CgtfqPP~d16+W=-B?jOC{B8iE5HDa`zEPJsiOfVx%<1JNRfD>9QJKe z6r-XcbKHS0&T1Kk{E1t(rKD40N-7x=D{7ZQ2fAhx?r?{wD z{%D@Y6Y0q4xI7BvvOG-CB@^V6QF(jlaWrP#{e4CK=kwg_Yx1W@YUNPu&Y7LJPwgn_ z)Q5Xr-{!K{PcSbpOAA+%AMba6nbAKz(rV|~@AJLqDs4BWJ7&(aU!V36nz0|#4~S^P zh5W$Jl@`_Xs`j2}xL&=*EStLx_!&0HSOCv`3q-{Yg<}J@Whg{_m5S^q#d1 z8yg6MSexuovi|D7t84K$E;Og{(t_gss1FuUNp%1b)nOixNmCsFS)l5pM<0Vuf~Xxa za{Z`3)hlbz45~gR=$STV6GUg1XRF#EKx7^a7*>S(Ff&V$h902~3Mn>a$3W5O8FN72 zSURVT4Qi53b?qWMJsAs_0I8&B4q2}3MX0i_jQ9RELy=_&8jMgCr}|SFG6o$$3PF+9 zxKIb#E(JM3>fpmWNS@_HhLspDOtYNKN;1olOAm#uIeJ0PDv2dq_!Oav2-z~jluD&w zDHMdx0K-X=#IQWW^E5`#?x=-SkG9;_s)7Ps%`t3bK#TMh)jS+V5ej=+3Bj~esbyiy zT}l*A8RMxo!v$H!H2t{BXcuL{FE>_1ySY&tFj?TjVMoLDD703|ICpV6paeexY!*P#8|f=g+f(s(sGe%X`pJ`@NHMP++VqJ%mFHbP7cDMY8PaR z5J9&HZ88?~tKLp-J7`!sEVfu;EazD^R`TJW;;-=a|IHtRonriE z`K@`XSGXhn?eZw#!}2fz3r~=PM`iuh0RfNMzD#c}{^LpN^^M5Q@hxwsqaSDEFR$(V zG?#dPPkA>J8`sv^>H5pZHh+J(_v38h&8@C4_xC)%BA0S&3UT7|eBxBG`Rjw^)aa%o zJvCVG(3#shURqE#-S^`U4-p7AOk+?csYG+$i~MP#W>pgrx-_)*aFwwNLwsynTvyUjE?c2m;=Yd31(}{BnPwHx}O^BE7)IUE@1XdB= VR9zdjC>+JwL^7UMu6G|k{u5JajzItb literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/ok_hand.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/ok_hand.png new file mode 100644 index 0000000000000000000000000000000000000000..677a3f045f18dbef35706fb256debd6cfdeb742f GIT binary patch literal 16210 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 KcCusd%YOkT#tq>B literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/persevere.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/persevere.png new file mode 100644 index 0000000000000000000000000000000000000000..743a6d40c6e5666a5038cb6d0d9dd09a6d2a30ef GIT binary patch literal 1366 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{D72XiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-lO)W`O zsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S;PP%yXDGc>id zFf!3mFfuSS(>JixH#E^TFtjqTv@$SMfC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz{qpj1 zy>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@x4_pIZg5^PG@yV%reBd*pl_&Wpr4xy@)uZjaY;}r!Wmdq7l%|9r0NHy z7U!21B?IFlO&O*c7&4a6BsFpIWGChrManjC7v#}N^As~9 z^R(1NT~i~2G~Fai6EoeUq$D%l6l2rGG!rumb7M0Tm^s+=n;97xn^`(KnVT3n8ydP= zT9~@HIk}md8kxDcI5|1H!t{FP6_+IDC8xsd&IH;G)$52?ua$FAYGO%#QAmD%4lES} zWaO9R7iZ)bC^$QVV%=OpBRn%NCBM8_6BJDlU%R9hWtOF;xE1B+DuBb;Diezvi1R;0 ze+s$brw??LJ}9vuB_5a%Fhzox@T>sjz%x^79xw+L0kcY@i}o>KHd_(k6XN>+jPLt> zuFtkP++An$^SIaENje+aR6p!@eX+yo-)Y}@o>>qFRYYnh~d4q!t&fglkZ18 zw{~kh+vYeSOZ3N4&p#)zeGpk6dCW3oO zwS0y<}O}(6Y z!7TMMQ=!UH*Pf-4GeSc}BpPiTC0FnX^RjKQ)cJJE=8yt=L#0s7o>!X|CCsyIo++o! k+$_a@L-)ix77hc3(kPzO{{3z8K$kFhy85}Sb4q9e049g-YXATM literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/pile_of_poo.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/pile_of_poo.png new file mode 100644 index 0000000000000000000000000000000000000000..9626a3582c6170668c4549747e593d5cfbe2107f GIT binary patch literal 1286 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 S`=7;%nj){;&-Bx8y!{uz^Fa6j literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/see_no_evil.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/see_no_evil.png new file mode 100644 index 0000000000000000000000000000000000000000..8c24967ce84d07bbbc4580b507144cd6f37ca42a GIT binary patch literal 1483 zcmb_bZA=?w9B(#F=7g9{qropbkA!Hny_deg-6*s4iquh7OE(a4c)fet9_3zoceJIT z7CN^1#wIZRu+2|SoikJ8=As~oo#SOV>6j2r)Tnd%VTs9{*%Cj@=YXOg$YP9_+&wS% z|NZ{I|J!r^`bUb_-@D#qG8KDknSikx@4B_{>#^Te50?_%)1)`ZVLi#Jz~tiP5J0>l z8vy~p@}2Q1P-!x)O$fmzy~$TcbFye*4I4{JR3O@9s@#%NSS|*1Bm^RYsvvC-AtX*XFr2~&n;9o)oT708S$yb1y4>is_P1kVaa6DlC)Z6HG&ZoMPWFJk)#<~n6*wxXH#ZLD=jcEK;u+F(FIvT z3`RC2cj!(ODqRXeRD8Y_Vo6(06igYGVikFDJDJj4~}n%>Y$M z0KP_*MPxD0w6KbXe;5A}p8v1;!=Nb4XqJC8PvHu7q_JHY1$bB)CLqBHQsJlwt~dJO znEmdr3wp+cz`|?0`1|gDUvEA4f;!zJoO?b#)7QRmIQvnAnLpH<)0+>s`c84xbFXyI z_UqF<(XqCMxdUCJU3@P7_}oy}5iSl z8R7g;I;XWvba7{U+s>pz)7iH3gXyVEli=#J$x66)(ZO5*Cutq4#lw2w<`{9o4 ziF_k-ar@_0rG1xuzsw;sPTFCH!X^3`n1;OLqn(-pns Vk9%Iq{|cp%_F*{6rXm)%D(LWo78FEKMDPV1bAs!hw7t#`Ma4k!yyW-$ z|NgIgIp++MOtQ@>Jl?t z##KPC)jr~Z&XH{180j}8lWJW@wv=UTzy?Ss%l3fd%jGyVWmm@g;F_h#DG2J1Q`1g$ zXF5m)dVmy}2yO787#WoqUX)@&cnv9Ve1zpBmJib$FLRR2@#M@yVKvVz$~iSPqlHg# zsuv+wX4z7y#FRn|^m(5Qfp2)0i!A7nfknLl2T`2D zo=%5gyP3?aVaK0I6iyji)?JooIM%jihh4ztfDZ>f1J|S2SRv!w zy^arSn`{LGEGOV0?!%(X3B#$IhAMGn!|_p zi+`GLerWz!>=YX`%Nxy8xxyV8Y-dLSA7+OMICz3QJSx>M79GW7R_sXUlap67#U%0M zSM~49+Uq~kFE4Aie~?dYUvYd}!#`siUR~Mn?0oXaubVC&WX|nv{>J!pbpPrzI~$*0 zNWC1>9{jw%uYKOllhKJY@?V$Qj}F%#DJ|Re)#880)5o?oJRVgZolD#}7Qs?Wzn?dP z7YgOFos;i+h}!Fywqo>`n%b5xPYmqcxab16P&qu5ULLwTd0@3V(R8ihyCaFQ6CXGB z- XRaYxMtf_9^bn1Bhj;8u6*7`fU)06UP@>)z>KzCE*LH_8t1| ei@Os1XgT; literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/slight_smile.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/slight_smile.png new file mode 100644 index 0000000000000000000000000000000000000000..7fe967d03368e540b42e7ed43bd4ec5827d5af48 GIT binary patch literal 1253 zcmbVMTWHi+7!EDUTCB35tW}U06_hpCxizulSd$q$(u`$hu!E>HlblSmo#e#i)S0P> zBEBdn!m{|Hh`Oj05p~&BsG{|u;N?Y8min|P=!594?n_0~P_9wzU$-0?nxH zz6aU}qH&LvFQ9_jDe2H=v_OZc+Ac;DL|dZjYI+|)WD%4sCrMj^s}NpC3LGD0Ig#bVG{;MvC~-VFy(rA)8K#s~Qqx@c6sLL- zawV3nR4Pm*#6Yja@}elRoWKeKjWuY$<{+&~JO0YL1qJxJXSv9N4jEX~im)HWDeUP~ z2)3)LGlm_1I#D=fY*lkvp5a*A4&s{B_E8pma${C)KVNeJn*~1X_jFtjb7dWjbN6MU zKoNT*ZS^c%6s@d4z2627N-J>+e_;&EkOV`B@tjtqO@RkAh=p5eQH+Q*2!mowi~=*l znRPp};iF+i4yW3MSXhvGJ}HWd!YPUzl0$q*P6?4ZHtqOGb97MWwlMcJmj5DFl0Bdy z=;a|S*Snyr7b58QLYI`~pz1MlO}FJ3u;Q-`$}|B9aMA4ayky`{Xlsf<79e0L``Hj+M5TmJq|>dE=o%ilH*9smB1tMNzYqOXVK+P0>P z`&W!VP{&5L{B=9|qy3$mnKS-S9sY^gy>;%hOVSS=4WonNy_3TG;mt38NnpZn|1m#c zu?l4~xrzT?L}6WX@Ne0fR@(E`XXRtv3l4De zU4u&&u6eTP<%XVLxn=2jJC2O?{M<5J3?0rNy*qsRx!O}$`1j)erzdj1yA4-L%U|sq ey192(!+c`X#M~RV8qdDKL_|87Q7&)lIrtII(7Mh5 literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/smile.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/smile.png new file mode 100644 index 0000000000000000000000000000000000000000..547d0c1af61f249a1c16bf5ba0fb67ebdf794b93 GIT binary patch literal 1321 zcmbVLTWl0n7@n4B2o+Kd5~(DeOrrsHb}l=!bFoWzJF~S*y34vOB$_Lu~NDXaZgzG#KOMK|IrTs}BuPPcrkL z%m4lV_uqDA()TT2*0v18u;s~KH5ll>?$Ygb15;F==vSrs@G zCFV%wQyE-wT!8bT2&pq+5f`Ko!%HH|-Gj3<6QO8{VmOj!WLlDG2A^L9^5z;vIji=} z`$DHEF$iHUPr@%3OwC4%g}UeJg}%0 zoC=H*i0NDiRymbgFl>ACi9#u(e636|A)2zRAg)<$4`#vNG#1tNawBCxWr62ZTpiV; z*wFx^++E*MporMW8(k9>MJuU}Ua^1;lWLSeFCoJ;WR_=nO%OFw<5`L102d)eK@dq+ zWQBqd7Q#k^YuH%~FQ`&NjB}j8u?oW^BvFj;i3q1EoDz@6BTNIEv^}WVI%xPdk?(nI z__|nGae)RMH|IE|Mi*oT9q4$2P8nB}py~p?c9UrvPR&~vlxZ$%6}V;<7(K3I;j?*` z%|$r;yZGnu#{bP9g-B6Bv;3oZ8dsT43vz6}2EyQcP?%GvV>yNho`cCrDX!|d3^`1KNbai%Pd)t6i`=D2`P~WH&D}cTwLRl? zA$B`fbo_us7-rM`*Z%XuhWEWWhTy0};yM5G0^QtvV=ERuP+Gdb>0Fb0!M`o`acpAC zL-)s4oxfQxd{fNK?4G&d=M%8*=T2Y#ZTnPbYL&G@c`(kWk4eu>-ZFiVedCYKt+(%4 t9gnRkweNoE?K`LI*l^47dz+eX!gh|ev~Ion*b~ShmQ1A8m%AU?`WN3W+!+7> literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/smiling_imp.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/smiling_imp.png new file mode 100644 index 0000000000000000000000000000000000000000..988f863b67fe66c11e186488baa644092ad40e5d GIT binary patch literal 1250 zcmbVLTWHi+7>d>R@NuosK%iYbH6^86)P$#;uR4UMXiF0h=}aI`6&3fFDu=XPN(`%R175NlJEP!|2o)` zS~06`ZXH1ovl1)Sw7>dq?R5N&i*r(V`3c3ds1@c>Npk_wXuupG6PDHv(m*r1wvK`Z zf|$O|%w$nE*(B@GVl*Galr0Cd38G5Y(Yi6{oVv7BU81 zK#EL=*7-n$3`-0zN)aKrgcLYF#BvhL2WgI%IZ5Vta^j(|nrr0cw7Psk3!fCKfRH1z zY^hXYN&yDC?JO@z63Yp!AkY{=dtElt%Czm(S1qW((_Pa+CbUW4qLzc5NTIN&l@Kf^ znVd9idlQMmDPzl;!}1KrT9zNzINC#L@X3uS(O#y@0c;w0u+!CXJ@WNcGS1zXg?u3P zMs9XZTokRSLcP-hHcF@ph5s;yX~^M-Vem#IM+ZSfqa{8VqNQLS&_O{IL%BQ%>zY`# zGbKM7h=#&}KsYGGcs?#g8+j=j5rwFzsv%Y7s@#O_AS!vt(RK`tJZ!}r>r;W0B?nlkaTzrQ)L_r+>yV8FaO z-1F#wb@N#7Q!_bybmwTBa$t?T@2@@2huqs8%}0ASpWk1+-nIVBpmk$IH8l~em(_8FH>55DTvFaFu@tM%R=>A_1qN~c=K zzWNaPMY|7U_{N0Vm?^(SLv26YC2Q4R&;9f74tR5H{%?hs?1H}GA8V%(v+vd2uG!o7 z{?+1`@`3$1@T3mCo@r+v&pWjK19KSj#rEC(}9Ic?9H`=|hdrNak?nsNcQ%lG~C&QzJ}v!!EN3OR^2Hm}(XPp4R1F zkOi_@eti){Fl@tqE!PdZrFKCvbxQUyl&f2ajbV{Jt|cq|0OAGEs~J(^?#v|u*VHJn zmy;ODN`OACZO8^)Lz$d1)UWU=vF8Om;tEKB4xo&?`hejGZj@M-E1*0_JgbmE39)354;0A)#}rAx zaSRWbV1Q*pRXOYNLt!rDXZTPk;7_n@l8>`&C>3VoEFVuLQ~p?$n>HLM8w#lE){yR1 zZt$U8Az=d<(?vT-SJ6SdiRM|&>$ zU`gsZbLaMgK70A-;+5gsQ_<0a@1r-KyLC-Je{AO|g}HyVZK1*(w;IkKYW{mkx_If> zsjl$%laaf#$>|b%t~2r5mDZ1o-0$=0iHbTiw(Igc@uh=3Pn4fxS6>!+WdBX)%^_zbh~`kJb9HmWhG7@tV0BI~Hk@ z-m0w)KJOcwYkT$JQ#+`oh3z#b=D!8}zQ(V(Ez`LdPoK;+-EVL=4#Gd?-fOJ<`1Scp zL#1IN!Yi-UU4MLj^EX?6!0xr&6D*~?CkKb Oo;T@aMx2c2hyMYtwCK+O literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/stuck_out_tongue.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/stuck_out_tongue.png new file mode 100644 index 0000000000000000000000000000000000000000..3e650a63e6840075b938c930a4611912f4c12c1e GIT binary patch literal 1314 zcmbVLTWs4@7fd#D83R4zhmS*HmmO@I)BJ%B(HATFC$5Su`39Jfu`Lp2SK zWdG;#fB*mew|#?!%-S`#uc0VvZMI)61~T|M+Q~l^Syv!p15OR&A!Ohta3Ph@Q5n)% z3shhc0)6a>k6NYv)K$a#Sn5UoFL0G$A`Iam?avlH)dntv$ogWvY@E$fg5} zpo|(g&Jd=HAy`g6ziim{mJ&r$#`(bEgb>eJRuI>Mwug)GUm7cFd!;c4az*H&hO3c! z7~L%}$=&rG1&V}?vfVXFQ9xZqTEl`i&Z=>Syo7X9S9lGGnjz|}VMrQl012|P!D}qg zV=@qFb5k_7WIdn1^R6R;>+F{x{YI>W4GA%}}Lf704^|XsDdLhq> zxdMk9i+>TX|KI#^gcKJv%Qel@x*{DJY?nuY9F~U(+GK)UGAhUJdio18X3r1iN~x=- zb3cyQFmuOu>drq;4ZPCWa^8o>CZuz@^3U(3&o_*BUWmNCPnw_UKl9M8ucs2f)Xe=u z@}9@nP@uj%5I zk8@|ektZMR{`AANAuyyVaR(e^Gg(KS); moTm2NciS6JG0(Pjj#78tvihs-KXv>{JX6_JL7nOw-TMzezTP?j literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/stuck_out_tongue_closed_eyes.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/stuck_out_tongue_closed_eyes.png new file mode 100644 index 0000000000000000000000000000000000000000..a92049bb60ad19c5260cf18fac1aeff8a3bbbd1d GIT binary patch literal 1344 zcmbVLU2GIp6rNIDYYPbvJV-ThG7Sk!x;sC+)7cqzTic!O?%?jyY!})p80P2hcCtHj zr!&*;v=4-ssIe-L@?wIC1%k$ykOK8TsKqLRpwal$m>7`<6#@iIG#bS_ZMXW+5cOte z&b@cecg}bIp6$!0*EP2`V;Hth%7_JD`fpPs`li?oc_cQvsX@0NmfV_b1FTzv3cw{p zE`tJ)wegYjAdX>;V|sDW9n56~6&hjL*9m)uh0qul@A52JtpFESKv_2v#EthpAaGqv z5Cd$E%2`P;tY;={&_9tcsuLBJ*NCo8Jnjj|fB{??_l&CP2ws9%v@4*!e@znjqKaEd z5KE*6bA5Oc+5l(69U+yD#Bh!e(<~ojqU|_C(H$hklXNsh(E`N_6pb%00(rBwl28zP zmwlmAf*5vPOCZTwtro6D!q6_0G|%%S#gGgWLK-1w+;n9xWIAni3nFk-Ten;tnz(OK zR^X_cAQ01~5DY7qTQO`p%ZWlMBR$z7=`ckah9B3Ww&NDS-!xX$c8cQ`APc~Oqqd6b zQEID$QSR>U$X7&cgzdJDiXvA zXW1WyOpt!?_+IjtdFkrAy+6H^x-336WdyH}mcBaP`Rm8qu6y9zVd0On`PoA5_qPhK z?(8`{)_w?XnRzC1^ZoR-ihgE_+q=&p+_pEKkCvr}Zk$P9IuifxWY3k^x?Cx*7Zy`Q}_9e=T(KTrvN{YvN0bD3{7 z1reMs2WTXsZXw@)=f5xP(E$P=yeEm>MQ=f&0&4>6vB-3_>E(vG2K!5I?OK7j^~ltY z=Qg&V{p8~OMLhh`k><-YO;>Mkp=N$;4xU~!{*8TV&!(q$9mOx~leSBb?>;ECR`<8w z*VVT5*wK4h<^#bT{zc~A>ca)!HRlkEIABsL KFP`Yx^Wc6xQvPc59z= z2GS+E*vnj-KO6*wXj ztE8%>K3wqvfTxo@X)-AR&xlDTEeb667|zlRPthX9a3sx0v?$RGzP1SDEwJiRMJ=xR zLMNFRhR~NNs@ZHNo2jH13{i|IiWJRKEK4E{G8}WE5s_}#*|MO5&Ia*RF8UR z3ygAiXGgIjVj~?4Y*ZAZp?c=116-)7GJ#%_mTgHUU^8N>ZjqdjHb|4_>ZF+Fc@mf= zD+oNBN%3sU&PI5?ATq3?6f+#FFib%d)I49zq{Y0*a%#7lYGE}ugobN^mTw#RUc(md zh?SH87|;uJ&ug^0pl{fNUO4RexT3^W&)|CpY}fLd;l8*`t5K^Uu#W(%7;b&AAahfcn0qJcuIlw z?DBlicb{rMeW9H{seJb8BfP+!fL+r^bBN2_J;iP$NLVTN-~JB^J9l&2Ed&fTHLpk4 zYhSl*+I%0DdbhFVowmzuK?0thoe@5N>D-Myvx}oUbuN)eEKgUD@9Es#{sK2u8T@h6 zsgH6?zviAkcKp!9$tSnH|JK0t?w*dx4M^x@J4g zA&B4~;L*G2bq5cE7ZJRwAb6a35d0JLrCq0oGQ>dgeczYw=kxvjq}jMJH+yLo05Dgp z8m&~O@A(<_HI<7ECg!Qxrt73j2X=%($t4{OYregOTiAB@9=ylP0L<)qR-3l#YnnrR z!A@<2#19!7faR4Ww4H5CVFzz{fzJJW{f2{{t8*Jl9o54!?s?Vy2(RxqEN6e)QC)83 z8eC2^M&M&=!^GbSVlC0RA+N^H>9xqgp$XmAxlvHv? zt58N#UPP)W<#;4%NY#)8PackWi`=f(GAbv&n5J_*N<&Q)2ZMny$OT>LVNA4+t-TP7EgX}6G$JkmBQ#)|**teJZ9%0Qhv06F8HYJfo$j*2Qnms~E+#?|@m(#8n;L?T{ zxMUDtN!v8a+Q5;wi`_~@d^oJL=1q#>pYk8!-T$qh$bu5nVfkx###d}2)8pwXFy(Za zaKJVwVyj}_|5jydmT9h8=Dn9c*m24`S7KtCwi@fd!0{2f$uzZQl&s`SXY09{vWaXGg~X literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thinking.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thinking.png new file mode 100644 index 0000000000000000000000000000000000000000..6be3b18d7fd93e22faa11df3f0a7c3a3f2a8bdba GIT binary patch literal 15849 zcmeI3c~BEs9>;sis;yaPX8%~HYNobocVg6?b=T0{IY}FWkOV;qBA|dLO?L-cl5|WO z2zcK&-WT4tc;6`AqKM#yx8i*tc!0MeY$6JI5h<60^JUrNTFCsB9%nj1Eeqa9+XOGGC&%uG9zY(fl8)BGo4g) zW<(5;nL=nuX`sHP&W&*aY!r)2+%~J-g}DQyp12ri^Tn`K;*qc^0n#8op(M^6DKRik zN}}>p%Lr8AFVSfIP?gqSuIwO@Bd8iiv@oiaAt;7uF$9&=K2m*4&eAza3l?PzsZGcI z3y>zWtOJAL^z?MUbcG+|OoCCZRtqC?ST2`w3Yjaz&f;#F-PNWhh&PUrauH72!P1Of z!pFrEnN&7FD&-T^J+=L^In3s|RCZS_J&q&n#vL%~hrl))+?c0}jiTxs*{G*0Cc{C& zQIv~GbrKXOZ_{`nQySO0+TJ!JkSUF_vyF!0#_ZdH8p}@-bv}+%r_}?RBw)%)*|L>-rcsgpG8Lk<$ovUXDN}0*6@e&81+G@;;3mV= z&#Kx~jigWqhp07(QLa(S4Jc~TY7vtm$e;-J4-O7iYE2q%c)+zm*f6_`#q9)D+j5#~ zxl)-(q6lS?k#Y+z(~?SmS)xTl$Pf!6M@W@iAt#jH(13e`&_>Ehr%_~xld*Xgj01PN zD1Pz=NWHVSZiUrS^-O<^ZrG;g(QM#e-zF}BuBMv&f5)nUdwp~-4xq~oCrc>pVi{)! zP{B8f-%6sXfnS$;E39-g$<^`WRy~Fj{3fM$;T(M(>|%kk`X<+S@QG>!jX-bSL}=jN zbdL07%C6^jZLJJZ$xt*#F2|H8hARGp$T0-*Hr1nQI*5z0u<5vy3QFP@oWACmi1h9n z5`%$17BrH7#nN_?Nq4pPM*Z5Y>F`7{Zcm~}J?wS#7Wlg8V1DSV^w%R-Q~LFQdS^$& z3Ba#y%;2POZeqkRjI}x4@pY+hSA8_fh_e((8dYO*6qBpHr0aszD1Bm>8IrbS_{Q)Z zEj|XI^o_xt=OoVJ&58nQfjA_ASs14cXZ5rVPoiLlJxK@G7Xr$sLSi|f7) zZmbya;!gyA59cNl?pZRZ4sKB9tB>P1FKentuaP6%1Ec(Rtt(jV>l*)USFqaGwcfLb zoo4yIc^c|d40!R!Rt=13?p2M_t5qt6N(cKE`+7vuZps>Gq`A|~#cv`gcSw1Bd@CAt zjBm;jsHkHf`~wYhzq14Xp6W65rF~`7f3_U7I6t80tF&2kcOZw;u1sz3PfBW4MF>x zxLVdK{ob2N3p~$`?ytGvN9lN1d`2ms4nVSRTN&futUY{Hdk^2E9SI)mKTy5 zBgvbl-Z4p8S=e=HhOF{HaOsAiw4RbryL9hXz!fv3yR%f~(OArE!PJWMdfn2LZMJ9l`54=tyXI^8h?L(?xH4!VI4bm)ai5q0ReiwJ}@w_Q>RWr zK|$P=H-o`oG#X7NQ%Fci=gyr&Lqo&D!n$X@bGZ6*&GoO(XCsz$jHd<-MdFc zMMXzP$Hc_+=+UER&z`Zdv2k&6@$vD!diCnvyLX>Hefsw8+pk~0{{8zWBqZQCo|u?O z5Cln*6h&DqmZYSl-Mn>2$hWE|z6eQ&ZE@ z(zxrUZnrxlBO^02bI_ncg9i^DGGxfmp+koa8#a9S@DU?Mj2t;~)TmLTM~@yeX3W^J zW5*0Z)TvXaO`A4-`t%tyX3U&9bJna`vuDqq zGiT1+xpU{un>T;{{Os)P1q&7|T)1%2qD6}rFJ7`_$KR!V@P>6crT}7Z;yAdGge$Q>Ra#K6B>G*|TR$N=nY1J9qy4`3n~= zT)cSk(xpq6FJHcL<;vBoSFc^WR$5wm{rdGAH*Va#dGpq-TeolDzH{f!-Me@1-Me@H z{{06J9z1;b@X@13j~_pN^5n_Wr%#_fdsbFf_Wb$t7cXACeEIU#t5@aab#?Wt?1HEKoMWRRqPf5S z(*ymM9nqR|c7z#&V%*olvs8c0?*z4oU5#Mje>skSsZMSGV&dA;l9OGo{0S;8co_3M zdjz_n-;>`j{ObPkF>|ohkI1mxJGyqO_l}cKIqP3Bw|Lt>{;n>`f2B?d_$A(v)#K;) vDZhV5Y;N~<+irVUQLFFIbZDPz`>cV=ihoFNT^Loy<%Ysc5ynly2_ydt0i{2s literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thumbsdown.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thumbsdown.png new file mode 100644 index 0000000000000000000000000000000000000000..674b5dd6592c1e3428ca38a76238cbe449963a49 GIT binary patch literal 1223 zcmbVLOK8++9M9TCv?%VugNkTK6!EHBU;FLRR2@#OqNVQa3@Dd&{rye)i+Qr!qS zGRu}qC8iW)pxedrk|eQQfDHs_jG(=K8);?Q_8Mvm3h;E-bdU*c(pS_vU>}N7*weWX zEJsxrgl%s=Q8;C6S#wyP;aJP^sH$>3uh7K8z`&AdoZLOwlz>@c~U#7XJ72ukOfRS{eMb73~HW%^X+v1<& z8{eBh7CXiI&GJ?A)UI$x`rCz3z=wrl0ydr?7mvyym|la&Y=1UgNK{|9f4o(g{D1F< zYuTycTxFy<^Rlfv+CKBDt@3c+)Np?MlKTF9diq}L=IF!Q2q{6f0& zXy3cDzm1(~9>19Wc)R7pwLO&w#p#ja_+=H#|0kVXj+ad+m&sR`dWg5{HnwAAYf6a~ z%A?00iOUXitLpBYS(`ijpJskoPHa83qGjjkuYY0_L@JR{t~MP! F@)-sMvlajV literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thumbsup.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/thumbsup.png new file mode 100644 index 0000000000000000000000000000000000000000..e52f8364ff61260b46b4083b7e73098b814d8c95 GIT binary patch literal 1218 zcmbVLNodqi7!K$`iVJ8FEs7z%D4I!LnpqM$md<3fqt0|TJ5#mAO!C^sHhD35b*4o@ zdJuZ^=s{6DxE!kD0)n7;P!v=U5x0vTL{P+vZK+jTU)oOfP>L8x-jeV8{(Uf&+`g=; zri!AdW$`8@Zl0mxT$u+3{>^LgAZXnMJ+mH z}5Yt82X;@+A%dI;MZRlYp?@#avI|{purhW%z z`;$4Xzgv@ZreP~xUzUl039(9-%^u5@%VB0(S0;P!nq%l`2<{FuGfou}DLRTANc(*O zRs(e*Iw<*oUkVB07Fyszfa4_&h%66eUXpo0&pr&X=I9-AM%gxNi=4tt7sj^Caivnp zSE}ZAC$WuI3mvHjqVoifR${;xI!zoe9CT6Nx!t z%biUWNf}pGZ4UT&&NRKarqM3Wz&~!xi*|E;HsmtUMZJzj>d{eKA(PxKY{&x=Z{%jj zAVpDo6r}Z<(86&g%#c4m-Oy!G6nP!$0aok?KsLmS0k#N&fE7iZ_p3qOAFR_VI`i=r zMF1f_77U7l0zgcPfSAw-B9X?35)vXoe}x;jT&!9etk^b)?OASML9QHipo)=`L#U_H z1*tBCk=uoAIvVw=9;7$s4NFHQcavA9nWz=$7>A&~%|RwTooCsY$A^E5e}=FBZ~i#q z6z4U|U(HjwA|2^%=SG1X=7tGcWP%(rD#s?%)nv@_sa?6))SLE^%c;p1Z4>wNqgT`4 z@9rMEnfZ1xG4;BACr2x@!Ppy&-Q*jvvcxg+t`it#J&8;Q1jQbJ4dgl z$8KhaPwn{ieBbcN_|&VmpHKD>?QG2vlPv3TCYhaD;GtTNeKlO)W`O zsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S;PP%yXDGc>id zFf!3mFfuSS(>JixH#E^TFtjqTv@$SMfC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz{qpj1 zy>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@x4_pIZg5^PG@yV%reBd*pl_&Wpr4xy@)uZjaY;}r!Wmdq7l%|9r0NHy z7U!21B?IFlO&O*c7&4a6BsFpIWGChrManjC7v#}NH1jlF^AwXLBXbK=1B)bMm^s+=JDZzWn!A}hnwuC~8XCG< zI=VUsjz%x^79xw+L0kcZj%J=-hY<4xkC&cyt8Q+I5 z-oD!D^y`H8uM4T454rz2<@4~x>rc04J$dsKhR(tDtJEn%yz$l=%L}wOY>BKfqx0T|gq#`;sEiK@6U*elF{r5}E-07(yBV literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/unamused.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/unamused.png new file mode 100644 index 0000000000000000000000000000000000000000..342dd80e79b03c82f84b7d81a1017c951daa88df GIT binary patch literal 16276 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 literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/wink.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/wink.png new file mode 100644 index 0000000000000000000000000000000000000000..def8b2775ac1aeab2a233be49dede62fc7813ce0 GIT binary patch literal 1303 zcmbVLTWB0r7@j1wwCNTiR%k`*I8kg`=eoO@Ipc2A&CIS@o85-ZLKpGDvomLtF*}#e zoMd++Vri?Q6`!P{sIAdd(NasHRw)vVRg4i0T11QbAmUwH^reEeo=LLNhfvf5Gyl2# z-~WIA?ZJWkt!vw_Zl@?}ZMIJ@gfjeAwUK{1zAjJ12AnS8LAQcy&_`6tbjyg&+HeRJ z5HuURW>A8n+QzJ6372yHs^Quk40X7=?GZFZC3@-}G)54n%V@}QlFYeNQw(jHNoHp} zC*(X04O@NVJ{la)7me`|1DH(DRyt8vi2)m7NZ0ME6R7nhGjCTV`|z4)=y?@9l4KT0 zm2v~L=K6?^bKR^VMip8HoEQg+6uX(01hJbJ058T^K~x2x3L?F@7~;)0D{4W{Eczm+ zBr}Y$r}BKQR^w_>&h>|Q5dgpo5-&+C(O`pygJGR@g3hJ|9R-GOdDwCtI_LB>$cVj)tVg?3Km_r06PtAc3>^bCeOtu$A{Ja0t7<-i z*!7F9TWxm1z_5$mVA%C&O$)0o)0=i$j_KBduCPoCQR~RJ#*mruU7McIvuZ8F;orr- zfH(hd{&+%)51Zv5&C|Rh9T{$yMu8lbh6y=jf_yS6;Mv)|WXv8I=r5)(y`TH>lvYVo zzr3y=yZ^?|UR1w0nm9j|`Sp#=*_YI(#;%z@z)jvme|IwV$ISL4dppk@mcM_k_k%;R z1Md1=`4!LIeci>`{%=pF{+#VUKb3y#G5)T;*5BW`?aP-FUmf52$qULW`!`*9J8Si| z9;{va+nbq*#>Tmc_{Wp-tB-U&fA95QpV&4rzL9VlL0hJYU~wTocT&eUVM!1k61rxzDz#elXH!3Gqic@e b($X5CoX=NlAC~Sb61P+~o!5`{-nr*5kDk$y literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/yum.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/yum.png new file mode 100644 index 0000000000000000000000000000000000000000..29d1bf7761cae8471154e0c3f0f4c8e2c374a225 GIT binary patch literal 1318 zcmbVLZ*0_L81Fa(jJV{`1=%F5>7oI&*Y>XWr{!*JckSSGJ;$xU1;5a1-`h32_APD4 z^`KL|uZ!s0#|lg+o=Zu(&%>YKFB z`{(&R&+qwnyg#?IWnKF^48vNoyM(+i{cmjm{l#c&4v98bEVu)(4I!-b)b+c6qe-uPFjwP;rM+ z#3HGJ)Q@MN4e)3vMygCCfycQJ6Xg!&Ep-A`Q~1nXclIrqkK5AOJ_Tb<5SEiTf6n zA{=&81Y)`vf?-M0vSHI%N)$>N>7BiAfI<$(i-Z57p{ z)Y$-|+&$cpuZY<2FW5RNic%4vI&1*b%?c?3y@WJfp!M3&z!&n& z>nm{hckwUcwf~zx3X!7xX8A|+G_Fub`rGAEK!@dF0w$Uu8;#1u6Vub&Ta|Ru%^`*AvaeJcdh9_p0TW$6V9a%9Q_Luw%c9+ literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/zipper_mouth.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/zipper_mouth.png new file mode 100644 index 0000000000000000000000000000000000000000..37e137c0c9a370aa227ba71be694e748511fcb23 GIT binary patch literal 1296 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{D72XiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-lO)W`O zsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S;PP%yXDGc>id zFf!3mFfuSS(>JixH#E^TFtjqTv@$SMfC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz{qpj1 zy>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@x4_pIZg5^PG@yV%reBd*pl_&Wpr4xy@)uZjaY;}r!Wmdq7l%|9r0NHy z7U!21B?IFlO&O*c7&4a6BsFpIWGChrManjC7v#}NQ&U6J zG&3`EUE?%MLtRUAlSJJ_bF*aKL^DfEL(`Nb0~1pNm^s+=TNpdK8W>x+nwuCo8ydP= zTDXB?!_v{f$i>Lq&BYO>*E6rUBrz{J6=ruP&~B(+7rc6{oQqNuOY)0C^7C_GsURRD zza+mnBfmhw*%=h;<_a3&nRzMs<;9wyXoC3KCABECEH%ZgC_h&L9L`pmSlmFI{~`KQ z$PGVzpriCbi3KU~z=VJ)62ydO1t15WnNstBIj9JjRnmgOM1a|>J-{c#_5T^)nX9&b zI3Dx)MC7A=aW9W1r@1oBDV4dhId;;Nwq5;NS)NR#K^$kc7XCZ!vwq{eNmDz1p9;LR zCE?zB+j9#|rp@XEaktaVzNpBNLkdgYkkKj`@rS8H*0ua9Z$l?5LO`DIs!Xq0^h3RXjX*E(Ofn zU?b1m+{VFdcHq!KZ58EZM|cd~TZ6r09i~j27%!BgHCbx%q6KqAHtQVHU2|)e6_3U{ c77hc3n|nF7+CCTV2HMBq>FVdQ&MBb@03n#tHvj+t literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/zzz.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/zzz.png new file mode 100644 index 0000000000000000000000000000000000000000..02fc33fe713d9f0bb2931f94aa5a2e5cb4b1e6ef GIT binary patch literal 16185 zcmeI3O^72!6vs;kWF6g;3yL7LSp-EpUEN71>E0yEOpVhJIcwIz~9t34kuOcj7Jg651MHIn{r?IL#o%B?aVvs$ERzp5s{p-C~ z^{dZIU)$Pz^7Qh9%K(7W8|%$&@=HFamhg8=J+p~_?)KL&g#g@hANkw?-g)-{0M6M? zXE)kyU(hXYkT-14METLc$F%{do*(&!bp=I&iF%G(%l-bzXF0*KYq^VR8@Bxh+H=+q z1GICv*|83ItNpewyvJN#J%EI``)tB+VYG8Nu?dIAz9kyz@ zy(sc^Ng57^`C%dN1wBdDG);nvq$nb;A%+KTWQ;^NJeveb<1|rd1&$v%o-2^JhUx7` zwOo!Qnmprv4g7X{lFALo^e{(hWcZSthtgmm&GQVSZ8UA2LI#p0!WWV7XW-RHcPsrn73CYEFs@tP~nbd8J%b8nWEd zDh0KmzT61#

z{i+m3nX+k<6AzLosW1;Zgk8<5SfXr{6tQd-O|hck9kOUEWz{s1Y?^W!KjXeQ$8Zn1 zb-Zh9B2-0L?kI|0DC-67aj57J y(ajnHcLa!SQjR39m@Pex+$HZ2;YY2@7ITp&o zqZb|5_J-kOY1HFxi^E%chTB7ST}mC(0@|f2k)i85|HhF!*%F=^c)E+z*>Qa2lny>` z6;&_7|Io-K<9U23rt5lk>5^SpZv@D|OSn$=BU6)(fp22A5g8|nlC7JGV_SOH3kF71cLqieNxs{wO4Gtj z&B=+bH@v#*?ob@Wj6t?z$*vj^a-;FX`w?VKSP NH(Hy`4_7b0^fxrFvZ??8 literal 0 HcmV?d00001 From 09595863cde0e1080a4aae5acfeae8df50bef4cb Mon Sep 17 00:00:00 2001 From: Lotto Date: Wed, 15 May 2019 20:38:09 +0200 Subject: [PATCH 39/43] xp tracker: fix on-screen information type label --- .../runelite/client/plugins/xptracker/XpInfoBoxOverlay.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index 32b9a44bfe..5ff11871e5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -110,12 +110,12 @@ class XpInfoBoxOverlay extends Overlay rightNum = snapshot.getActionsRemainingToGoal(); break; case XP_LEFT: - leftStr = config.onScreenDisplayMode().toString(); + leftStr = "XP Left"; rightNum = snapshot.getXpRemainingToGoal(); break; case XP_GAINED: default: - leftStr = config.onScreenDisplayMode().toString(); + leftStr = "XP Gained"; rightNum = snapshot.getXpGainedInSession(); break; } From 2e0050c644f024036f3697cfac45bc5f9fed3ae6 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 16 May 2019 11:46:29 +0000 Subject: [PATCH 40/43] [maven-release-plugin] prepare release runelite-parent-1.5.23 --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- protocol-api/pom.xml | 2 +- protocol/pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-mixins/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- runescape-api/pom.xml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 691bb1d95c..efbac66e21 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 9c925c8cb4..ef06afb381 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index efb80c0240..409cd871d8 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index ca41b36b2e..81abdbe684 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 81d8de533c..35946b78f7 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 Web Service diff --git a/pom.xml b/pom.xml index 3e7f02b50c..743e7fe058 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 pom RuneLite @@ -59,7 +59,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - HEAD + runelite-parent-1.5.23 diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index fae727ac70..36b6f27d91 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index 814c33de88..fbe9e12141 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 38f6ace8a7..7c24f8fe54 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 3a84ed3124..ae138ada5b 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 client diff --git a/runelite-mixins/pom.xml b/runelite-mixins/pom.xml index a37ea94421..9a9de17c72 100644 --- a/runelite-mixins/pom.xml +++ b/runelite-mixins/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 mixins diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 5302a199d1..307f6b71c5 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 script-assembler-plugin diff --git a/runescape-api/pom.xml b/runescape-api/pom.xml index cc70e2bdd1..6d75d248cb 100644 --- a/runescape-api/pom.xml +++ b/runescape-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23-SNAPSHOT + 1.5.23 net.runelite.rs From 5075547a8ceaf88d50d822744a8674d61a42957a Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 16 May 2019 11:46:35 +0000 Subject: [PATCH 41/43] [maven-release-plugin] prepare for next development iteration --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- protocol-api/pom.xml | 2 +- protocol/pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-mixins/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- runescape-api/pom.xml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index efbac66e21..279c8f05ee 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index ef06afb381..acd78bee14 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 409cd871d8..183d47e500 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 81abdbe684..d87f850ccc 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 35946b78f7..b018f6a016 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index 743e7fe058..4f7e2deaf5 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT pom RuneLite @@ -59,7 +59,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - runelite-parent-1.5.23 + HEAD diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index 36b6f27d91..ed9eb46e42 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index fbe9e12141..0566215d29 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 7c24f8fe54..065207af3d 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index ae138ada5b..dd715d917f 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT client diff --git a/runelite-mixins/pom.xml b/runelite-mixins/pom.xml index 9a9de17c72..d1e4cac819 100644 --- a/runelite-mixins/pom.xml +++ b/runelite-mixins/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT mixins diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 307f6b71c5..98e762168a 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT script-assembler-plugin diff --git a/runescape-api/pom.xml b/runescape-api/pom.xml index 6d75d248cb..3990dada08 100644 --- a/runescape-api/pom.xml +++ b/runescape-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.23 + 1.5.24-SNAPSHOT net.runelite.rs From 51f2d0ed430922de2b8f783b3851a0bca552de33 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 16 May 2019 09:06:30 -0400 Subject: [PATCH 42/43] emoji plugin: add modprivatechat too --- .../java/net/runelite/client/plugins/emojis/EmojiPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java index bfca89c184..988e73a625 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java @@ -122,6 +122,7 @@ public class EmojiPlugin extends Plugin case FRIENDSCHAT: case PRIVATECHAT: case PRIVATECHATOUT: + case MODPRIVATECHAT: break; default: return; From 07680c5aa101848cd86c46f8461ecddec4aedceb Mon Sep 17 00:00:00 2001 From: Timer180 <36247639+Timer180@users.noreply.github.com> Date: Thu, 16 May 2019 10:17:22 -0700 Subject: [PATCH 43/43] Add item mapping for Tormented Bracelent (or) --- .../src/main/java/net/runelite/client/game/ItemMapping.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index 22eed36031..782a77dc7f 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -103,6 +103,8 @@ public enum ItemMapping ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), + ITEM_TORMENTED_BRACELET(TORMENTED_BRACELET, TORMENTED_BRACELET_OR), + ITEM_TORMENTED_ORNAMENT_KIT(TORMENTED_ORNAMENT_KIT, TORMENTED_BRACELET_OR), // Ensouled heads ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD),