diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 87093b7156..4b1efbca99 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -29,7 +29,7 @@ object ProjectVersions { const val launcherVersion = "2.0.4" const val rlVersion = "1.5.43-SNAPSHOT" - const val openosrsVersion = "2.1.17.0-SNAPSHOT" + const val openosrsVersion = "2.1.16.0" const val rsversion = 186 const val cacheversion = 165 diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java index 6ec40a00fd..2abb7c2255 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java @@ -52,4 +52,24 @@ public interface KourendLibraryConfig extends Config { return true; } + + @ConfigItem( + keyName = "hideVarlamoreEnvoy", + name = "Hide Varlamore Envoy", + description = "Whether to hide Varlamore Envoy, as it is only required in the Depths of Despair quest, and is never asked for." + ) + default boolean hideVarlamoreEnvoy() + { + return false; + } + + @ConfigItem( + keyName = "showTutorialOverlay", + name = "Show tutorial overlay", + description = "Whether to show an overlay to help understand how to use the plugin" + ) + default boolean showTutorialOverlay() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java index fb60cb0262..2b54575b48 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java @@ -37,9 +37,8 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nullable; -import lombok.AccessLevel; -import lombok.Setter; import net.runelite.api.Client; +import net.runelite.api.NPC; import net.runelite.api.Perspective; import static net.runelite.api.Perspective.getCanvasTilePoly; import net.runelite.api.Player; @@ -54,14 +53,11 @@ import net.runelite.client.ui.overlay.OverlayUtil; @Singleton class KourendLibraryOverlay extends Overlay { - private final static int MAXIMUM_DISTANCE = 24; + private static final int MAXIMUM_DISTANCE = 24; private final Library library; private final Client client; private final KourendLibraryPlugin plugin; - @Setter(AccessLevel.PACKAGE) - private boolean hidden; - @Inject private KourendLibraryOverlay(final Library library, final Client client, final KourendLibraryPlugin plugin) { @@ -76,11 +72,6 @@ class KourendLibraryOverlay extends Overlay @Override public Dimension render(Graphics2D g) { - if (hidden) - { - return null; - } - Player player = client.getLocalPlayer(); if (player == null) { @@ -135,7 +126,12 @@ class KourendLibraryOverlay extends Overlay book = possible.iterator().next(); bookIsKnown = true; } - Color color = bookIsKnown ? Color.ORANGE : Color.WHITE; + + if (book == Book.VARLAMORE_ENVOY && plugin.isHideVarlamoreEnvoy()) + { + continue; + } + Color color = bookIsKnown ? (book == library.getCustomerBook() ? Color.GREEN : Color.ORANGE) : Color.WHITE; // Render the poly on the floor if (!(bookIsKnown && book == null) && (library.getState() == SolvedState.NO_DATA || book != null || !possible.isEmpty()) && shouldShowOverlayIfDuplicateBook(book)) @@ -213,27 +209,27 @@ class KourendLibraryOverlay extends Overlay } // Render the customer's wanted book on their head and a poly under their feet - LibraryCustomer customer = library.getCustomer(); - if (customer != null) + int customerId = library.getCustomerId(); + if (customerId != -1) { - client.getNpcs().stream() - .filter(n -> n.getId() == customer.getId()) - .forEach(n -> + for (NPC n : plugin.getNpcsToMark()) + { + if (n.getId() != customerId) { - Book b = library.getCustomerBook(); - boolean doesPlayerContainBook = b != null && plugin.doesPlayerContainBook(b); - LocalPoint local = n.getLocalLocation(); - Polygon poly = getCanvasTilePoly(client, local); - OverlayUtil.renderPolygon(g, poly, doesPlayerContainBook ? Color.GREEN : Color.WHITE); - Point screen = Perspective.localToCanvas(client, local, client.getPlane(), n.getLogicalHeight()); - if (screen != null) - { - if (b != null) - { - g.drawImage(b.getIcon(), screen.getX() - (b.getIcon().getWidth() / 2), screen.getY() - b.getIcon().getHeight(), null); - } - } - }); + continue; + } + + Book b = library.getCustomerBook(); + boolean doesPlayerContainBook = plugin.doesPlayerContainBook(b); + LocalPoint local = n.getLocalLocation(); + Polygon poly = getCanvasTilePoly(client, local); + OverlayUtil.renderPolygon(g, poly, doesPlayerContainBook ? Color.GREEN : Color.WHITE); + Point screen = Perspective.localToCanvas(client, local, client.getPlane(), n.getLogicalHeight()); + if (screen != null) + { + g.drawImage(b.getIcon(), screen.getX() - (b.getIcon().getWidth() / 2), screen.getY() - b.getIcon().getHeight(), null); + } + } } return null; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java index aba91b0911..cb4673383f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java @@ -53,8 +53,8 @@ class KourendLibraryPanel extends PluginPanel private static final ImageIcon RESET_ICON; private static final ImageIcon RESET_CLICK_ICON; - @Inject - private Library library; + private final KourendLibraryConfig config; + private final Library library; private final HashMap bookPanels = new HashMap<>(); @@ -65,6 +65,15 @@ class KourendLibraryPanel extends PluginPanel RESET_CLICK_ICON = new ImageIcon(ImageUtil.alphaOffset(resetIcon, -100)); } + @Inject + KourendLibraryPanel(KourendLibraryConfig config, Library library) + { + super(); + + this.config = config; + this.library = library; + } + void init() { setLayout(new BorderLayout(0, 5)); @@ -79,6 +88,7 @@ class KourendLibraryPanel extends PluginPanel c.gridy = 0; Stream.of(Book.values()) .filter(b -> !b.isDarkManuscript()) + .filter(b -> !config.hideVarlamoreEnvoy() || b != Book.VARLAMORE_ENVOY) .sorted(Comparator.comparing(Book::getShortName)) .forEach(b -> { @@ -155,4 +165,11 @@ class KourendLibraryPanel extends PluginPanel } }); } + + void reload() + { + bookPanels.clear(); + removeAll(); + init(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java index 87434af369..4f8759e011 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java @@ -27,6 +27,8 @@ package net.runelite.client.plugins.kourendlibrary; import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; @@ -42,6 +44,8 @@ import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.MenuOpcode; +import net.runelite.api.NPC; +import net.runelite.api.NpcID; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.AnimationChanged; @@ -49,6 +53,8 @@ import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameTick; import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.NpcDespawned; +import net.runelite.api.events.NpcSpawned; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; @@ -73,9 +79,9 @@ public class KourendLibraryPlugin extends Plugin { private static final Pattern BOOK_EXTRACTOR = Pattern.compile("'(.*)'"); private static final Pattern TAG_MATCHER = Pattern.compile("(<[^>]*>)"); - final static int REGION = 6459; + static final int REGION = 6459; - final static boolean debug = false; + static final boolean debug = false; @Inject private ClientToolbar clientToolbar; @@ -95,6 +101,9 @@ public class KourendLibraryPlugin extends Plugin @Inject private KourendLibraryConfig config; + @Inject + private KourendLibraryTutorialOverlay tutorialOverlay; + @Inject private ItemManager itemManager; @@ -105,9 +114,16 @@ public class KourendLibraryPlugin extends Plugin private WorldPoint lastBookcaseAnimatedOn = null; private EnumSet playerBooks = null; + @Getter(AccessLevel.PACKAGE) + private final Set npcsToMark = new HashSet<>(); + private boolean hideButton; @Getter(AccessLevel.PACKAGE) private boolean hideDuplicateBook; + @Getter(AccessLevel.PACKAGE) + private boolean hideVarlamoreEnvoy; + @Getter(AccessLevel.PACKAGE) + private boolean showTutorialOverlay; @Provides KourendLibraryConfig provideConfig(ConfigManager configManager) @@ -121,6 +137,8 @@ public class KourendLibraryPlugin extends Plugin hideButton = config.hideButton(); hideDuplicateBook = config.hideDuplicateBook(); + hideVarlamoreEnvoy = config.hideVarlamoreEnvoy(); + showTutorialOverlay = config.showTutorialOverlay(); Book.fillImages(itemManager); @@ -137,6 +155,7 @@ public class KourendLibraryPlugin extends Plugin .build(); overlayManager.add(overlay); + overlayManager.add(tutorialOverlay); updatePlayerBooks(); @@ -149,8 +168,8 @@ public class KourendLibraryPlugin extends Plugin @Override protected void shutDown() { - overlay.setHidden(true); overlayManager.remove(overlay); + overlayManager.remove(tutorialOverlay); clientToolbar.removeNavigation(navButton); buttonAttached = false; lastBookcaseClick = null; @@ -166,8 +185,15 @@ public class KourendLibraryPlugin extends Plugin return; } + if (ev.getKey().equals("hideVarlamoreEnvoy")) + { + panel.reload(); + } + this.hideButton = config.hideButton(); this.hideDuplicateBook = config.hideDuplicateBook(); + this.hideVarlamoreEnvoy = config.hideVarlamoreEnvoy(); + this.showTutorialOverlay = config.showTutorialOverlay(); SwingUtilities.invokeLater(() -> { @@ -197,7 +223,6 @@ public class KourendLibraryPlugin extends Plugin if (MenuOpcode.GAME_OBJECT_FIRST_OPTION == menuOpt.getMenuOpcode() && menuOpt.getTarget().contains("Bookshelf")) { lastBookcaseClick = WorldPoint.fromScene(client, menuOpt.getParam0(), menuOpt.getParam1(), client.getPlane()); - overlay.setHidden(false); } } @@ -267,8 +292,7 @@ public class KourendLibraryPlugin extends Plugin Widget npcHead = client.getWidget(WidgetInfo.DIALOG_NPC_HEAD_MODEL); if (npcHead != null) { - LibraryCustomer cust = LibraryCustomer.getById(npcHead.getModelId()); - if (cust != null) + if (isLibraryCustomer(npcHead.getModelId())) { Widget textw = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT); String text = textw.getText(); @@ -283,13 +307,12 @@ public class KourendLibraryPlugin extends Plugin return; } - overlay.setHidden(false); - library.setCustomer(cust, book); + library.setCustomer(npcHead.getModelId(), book); panel.update(); } else if (text.contains("You can have this other book") || text.contains("please accept a token of my thanks.") || text.contains("Thanks, I'll get on with reading it.")) { - library.setCustomer(null, null); + library.setCustomer(-1, null); panel.update(); } } @@ -302,6 +325,21 @@ public class KourendLibraryPlugin extends Plugin updatePlayerBooks(); } + @Subscribe + public void onNpcSpawned(NpcSpawned event) + { + if (isLibraryCustomer(event.getNpc().getId())) + { + npcsToMark.add(event.getNpc()); + } + } + + @Subscribe + public void onNpcDespawned(NpcDespawned event) + { + npcsToMark.remove(event.getNpc()); + } + boolean doesPlayerContainBook(Book book) { return playerBooks.contains(book); @@ -328,4 +366,9 @@ public class KourendLibraryPlugin extends Plugin playerBooks = books; } } + + static boolean isLibraryCustomer(int npcId) + { + return npcId == NpcID.VILLIA || npcId == NpcID.PROFESSOR_GRACKLEBONE || npcId == NpcID.SAM_7049; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryTutorialOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryTutorialOverlay.java new file mode 100644 index 0000000000..6d6f3b4796 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryTutorialOverlay.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019 Hydrox6 + * 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.kourendlibrary; + +import net.runelite.api.Client; +import net.runelite.api.Player; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import javax.inject.Inject; +import java.awt.Dimension; +import java.awt.Graphics2D; + +class KourendLibraryTutorialOverlay extends Overlay +{ + private final Client client; + private final KourendLibraryConfig config; + private final Library library; + + private final PanelComponent panelComponent; + private final LineComponent noDataMessageComponent; + private final LineComponent incompleteMessageComponent; + private final LineComponent completeMessageComponent; + private final LineComponent sidebarMessageComponent; + + @Inject + private KourendLibraryTutorialOverlay(Client client, KourendLibraryConfig config, Library library) + { + this.client = client; + this.config = config; + this.library = library; + + panelComponent = new PanelComponent(); + panelComponent.setPreferredSize(new Dimension(177, 0)); + + noDataMessageComponent = LineComponent.builder().left("Click on the white squares to start finding books.").build(); + incompleteMessageComponent = LineComponent.builder().left("Some books have been found. Keep checking marked bookcases to find more.").build(); + completeMessageComponent = LineComponent.builder().left("All books found.").build(); + sidebarMessageComponent = LineComponent.builder().left("Locations are in the sidebar.").build(); + + setPriority(OverlayPriority.LOW); + setPosition(OverlayPosition.TOP_LEFT); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!config.showTutorialOverlay()) + { + return null; + } + + Player player = client.getLocalPlayer(); + if (player == null) + { + return null; + } + + WorldPoint playerLoc = player.getWorldLocation(); + if (playerLoc.getRegionID() != KourendLibraryPlugin.REGION) + { + return null; + } + + panelComponent.getChildren().clear(); + + switch (library.getState()) + { + case NO_DATA: + panelComponent.getChildren().add(noDataMessageComponent); + break; + case INCOMPLETE: + panelComponent.getChildren().add(incompleteMessageComponent); + panelComponent.getChildren().add(sidebarMessageComponent); + break; + case COMPLETE: + panelComponent.getChildren().add(completeMessageComponent); + panelComponent.getChildren().add(sidebarMessageComponent); + break; + } + + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java index 5fd23ac9b1..3b81dc0250 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java @@ -74,7 +74,7 @@ class Library private Book customerBook; @Getter(AccessLevel.PACKAGE) - private LibraryCustomer customer; + private int customerId; Library() { @@ -93,9 +93,9 @@ class Library return Collections.unmodifiableList(byIndex); } - void setCustomer(LibraryCustomer customer, Book book) + void setCustomer(int customerId, Book book) { - this.customer = customer; + this.customerId = customerId; this.customerBook = book; } @@ -131,7 +131,7 @@ class Library else if (state != SolvedState.NO_DATA) { // We know all of the possible things in this shelf. - if (book != null) + if (book != null || bookcase.getPossibleBooks().stream().noneMatch(Book::isDarkManuscript)) { // Check to see if our guess is wrong if (!bookcase.getPossibleBooks().contains(book)) diff --git a/runelite-client/src/main/scripts/ChatSplitBuilder.rs2asm b/runelite-client/src/main/scripts/ChatSplitBuilder.rs2asm index 6c87c8b256..f8e1ca2f4c 100644 --- a/runelite-client/src/main/scripts/ChatSplitBuilder.rs2asm +++ b/runelite-client/src/main/scripts/ChatSplitBuilder.rs2asm @@ -482,7 +482,7 @@ LABEL407: runelite_callback ; Invoke callback pop_int ; Pop the id of the messageNode sload 0 ; Load the log in/out message - join_string 3 ; Add the timestamp to the message + join_string 2 ; Add the timestamp to the message iload 9 iload 10 iconst 10682368