From efc37e00d5b6948cf0f14c29a1e520cf4e77aedd Mon Sep 17 00:00:00 2001 From: dekvall Date: Wed, 7 Aug 2019 20:07:16 +0200 Subject: [PATCH 01/25] Add Nullable to Actor::getName --- runelite-api/src/main/java/net/runelite/api/Actor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Actor.java b/runelite-api/src/main/java/net/runelite/api/Actor.java index a736b32fa4..2b35102832 100644 --- a/runelite-api/src/main/java/net/runelite/api/Actor.java +++ b/runelite-api/src/main/java/net/runelite/api/Actor.java @@ -50,6 +50,7 @@ public interface Actor extends Renderable * * @return the name */ + @Nullable String getName(); /** From 85a5eb0cf96d8d33a88522ee215515060523cf5b Mon Sep 17 00:00:00 2001 From: dekvall Date: Wed, 7 Aug 2019 20:25:23 +0200 Subject: [PATCH 02/25] Fix NPE in groundmarker plugin Right-clicking the void in puro-puro sets the selectedSceneTile to null. --- .../src/main/java/net/runelite/api/Client.java | 1 + .../plugins/groundmarkers/GroundMarkerPlugin.java | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 95cf40931a..0773f61357 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -418,6 +418,7 @@ public interface Client extends GameEngine * * @return the selected tile */ + @Nullable Tile getSelectedSceneTile(); /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index d9b1a1cac5..af3dae8f87 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -209,12 +209,18 @@ public class GroundMarkerPlugin extends Plugin { if (hotKeyPressed && event.getOption().equals(WALK_HERE)) { + final Tile selectedSceneTile = client.getSelectedSceneTile(); + + if (selectedSceneTile == null) + { + return; + } + MenuEntry[] menuEntries = client.getMenuEntries(); menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); - MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, client.getSelectedSceneTile().getLocalLocation()); + final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, selectedSceneTile.getLocalLocation()); final int regionId = worldPoint.getRegionID(); final GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), config.markerColor()); From 0c76f473ec97b7f1cbba6f468da71aa4bdc2b9c1 Mon Sep 17 00:00:00 2001 From: dekvall Date: Thu, 8 Aug 2019 00:44:28 +0200 Subject: [PATCH 03/25] Add Nullable to Client::getLocalPlayer At startup on loginscreen this method returns null --- runelite-api/src/main/java/net/runelite/api/Client.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 0773f61357..4376159063 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -338,6 +338,7 @@ public interface Client extends GameEngine * * @return the logged in player */ + @Nullable Player getLocalPlayer(); /** From 9fe8e8347e8468771b1283373284ecc3467e1206 Mon Sep 17 00:00:00 2001 From: dekvall Date: Thu, 8 Aug 2019 00:47:24 +0200 Subject: [PATCH 04/25] Add Nullable to widget dragging methods The docs say both return null if no item is dragged --- runelite-api/src/main/java/net/runelite/api/Client.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 4376159063..7cc3e97f8b 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -434,6 +434,7 @@ public interface Client extends GameEngine * * @return the dragged widget, null if not dragging any widget */ + @Nullable Widget getDraggedWidget(); /** @@ -444,6 +445,7 @@ public interface Client extends GameEngine * * @return the dragged on widget, null if not dragging any widget */ + @Nullable Widget getDraggedOnWidget(); /** From 23d8bfe765d4334a7bf50a8b6f7a81430aee8d87 Mon Sep 17 00:00:00 2001 From: xDemoN Date: Thu, 15 Aug 2019 09:11:06 -0400 Subject: [PATCH 05/25] timers: update imbued heart to reset on death --- .../main/java/net/runelite/client/plugins/timers/GameTimer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b146107d52..0a37f8cd96 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 @@ -61,7 +61,7 @@ enum GameTimer ICEBURST(SpriteID.SPELL_ICE_BURST, GameTimerImageType.SPRITE, "Ice burst", GraphicID.ICE_BURST, 10, ChronoUnit.SECONDS, true), ICEBLITZ(SpriteID.SPELL_ICE_BLITZ, GameTimerImageType.SPRITE, "Ice blitz", GraphicID.ICE_BLITZ, 15, ChronoUnit.SECONDS, true), ICEBARRAGE(SpriteID.SPELL_ICE_BARRAGE, GameTimerImageType.SPRITE, "Ice barrage", GraphicID.ICE_BARRAGE, 20, ChronoUnit.SECONDS, true), - IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued heart", GraphicID.IMBUED_HEART, 420, ChronoUnit.SECONDS), + IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued heart", GraphicID.IMBUED_HEART, 420, ChronoUnit.SECONDS, true), 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), From b87e50e43b9bb4b10342d4ec1a96833e2b9f4109 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Thu, 15 Aug 2019 23:52:18 +0100 Subject: [PATCH 06/25] clues: correct "Has no one told you it is rude to ask a lady her age?" --- .../runelite/client/plugins/cluescrolls/clues/CrypticClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java index 81372ec6d3..7b4bec5941 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java @@ -322,7 +322,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("More resources than I can handle, but in a very dangerous area. Can't wait to strike gold!", new WorldPoint(3183, 3941, 0), "Dig between the three gold ores in the Wilderness Resource Area."), new CrypticClue("Observing someone in a swamp, under the telescope lies treasure.", new WorldPoint(2221, 3091, 0), "Dig next to the telescope on Broken Handz's island in the poison wastes. (Accessible only through fairy ring DLR)"), new CrypticClue("A general who sets a 'shining' example.", "General Hining", new WorldPoint(2186, 3148, 0), "Talk to General Hining in Tyras Camp."), - new CrypticClue("Has no one told you it is rude to ask a lady her age?", "Lady Tangwen Trahaearn", new WorldPoint(3280, 6042, 0), "Talk to Lady Tangwen Trahaearn, SSE Prifddinas by the teleporter."), + new CrypticClue("Has no one told you it is rude to ask a lady her age?", "Mawrth", new WorldPoint(2333, 3165, 0), "Talk to Mawrth in Lletya."), new CrypticClue("Elvish onions.", new WorldPoint(3303, 6092, 0), "Dig in the onion patch east of the Prifddinas allotments.") ); From 50d74c63153a3466883cfaee22e4320232c72c4a Mon Sep 17 00:00:00 2001 From: Quasindro Date: Sat, 17 Aug 2019 20:21:19 +0200 Subject: [PATCH 07/25] skybox: add Braindeath Island --- .../resources/net/runelite/client/plugins/skybox/skybox.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skybox/skybox.txt b/runelite-client/src/main/resources/net/runelite/client/plugins/skybox/skybox.txt index 4d37a271ef..9451d6a707 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skybox/skybox.txt +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skybox/skybox.txt @@ -961,3 +961,7 @@ R 49 92 51 92 // Iorwerth dungeon #030A0A R 49 193 51 194 + +// Braindeath Island +#8AD2DF +R 33 79 33 80 \ No newline at end of file From 799a8943d3d0ca15e01b44ead0f0913399524e47 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 16 Aug 2019 09:27:05 -0400 Subject: [PATCH 08/25] overlay renderer: fix drawing overlay drag bounds The graphics transform needs to be reset prior to drawing the overlay bounds --- .../client/ui/overlay/OverlayRenderer.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index f2fcd059ac..e0810cef00 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -240,6 +240,14 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) { safeRender(client, overlay, layer, graphics, new Point()); + + // Restore graphics2d properties + graphics.setTransform(transform); + graphics.setStroke(stroke); + graphics.setComposite(composite); + graphics.setPaint(paint); + graphics.setRenderingHints(renderingHints); + graphics.setBackground(background); } else { @@ -276,6 +284,14 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener safeRender(client, overlay, layer, graphics, location); + // Restore graphics2d properties prior to drawing bounds + graphics.setTransform(transform); + graphics.setStroke(stroke); + graphics.setComposite(composite); + graphics.setPaint(paint); + graphics.setRenderingHints(renderingHints); + graphics.setBackground(background); + final Rectangle bounds = overlay.getBounds(); if (!bounds.isEmpty()) @@ -294,14 +310,6 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener } } } - - // Restore graphics2d properties - graphics.setTransform(transform); - graphics.setStroke(stroke); - graphics.setComposite(composite); - graphics.setPaint(paint); - graphics.setRenderingHints(renderingHints); - graphics.setBackground(background); } } From bd0badf7fc9b249265eca2e0e05a13754862b39a Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 17 Aug 2019 23:02:00 -0400 Subject: [PATCH 09/25] authfilter: cache sessions --- .../http/service/account/AccountService.java | 2 + .../http/service/account/AuthFilter.java | 52 ++++++++++++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java index f9951446aa..4f39ed00e1 100644 --- a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java +++ b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java @@ -263,6 +263,8 @@ public class AccountService return; } + auth.invalidate(session.getUuid()); + try (Connection con = sql2o.open()) { con.createQuery("delete from sessions where uuid = :uuid") diff --git a/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java b/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java index 1f57127bf5..d283e71c5c 100644 --- a/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java +++ b/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java @@ -24,14 +24,18 @@ */ package net.runelite.http.service.account; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.RemovalNotification; import java.io.IOException; -import net.runelite.http.service.account.beans.SessionEntry; import java.sql.Timestamp; import java.time.Instant; import java.util.UUID; +import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.runelite.http.api.RuneLiteAPI; +import net.runelite.http.service.account.beans.SessionEntry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @@ -43,6 +47,12 @@ public class AuthFilter { private final Sql2o sql2o; + private final Cache sessionCache = CacheBuilder.newBuilder() + .maximumSize(10000L) + .expireAfterAccess(30, TimeUnit.MINUTES) + .removalListener(this::removalListener) + .build(); + @Autowired public AuthFilter(@Qualifier("Runelite SQL2O") Sql2o sql2o) { @@ -59,30 +69,48 @@ public class AuthFilter } UUID uuid = UUID.fromString(runeliteAuth); + SessionEntry sessionEntry = sessionCache.getIfPresent(uuid); + if (sessionEntry != null) + { + return sessionEntry; + } try (Connection con = sql2o.open()) { - SessionEntry sessionEntry = con.createQuery("select user, uuid, created from sessions where uuid = :uuid") + sessionEntry = con.createQuery("select user, uuid, created, last_used as lastUsed from sessions where uuid = :uuid") .addParameter("uuid", uuid.toString()) .executeAndFetchFirst(SessionEntry.class); + } - if (sessionEntry == null) - { - response.sendError(401, "Access denied"); - return null; - } + if (sessionEntry == null) + { + response.sendError(401, "Access denied"); + return null; + } - Instant now = Instant.now(); + sessionCache.put(uuid, sessionEntry); + return sessionEntry; + } + + private void removalListener(RemovalNotification notification) + { + UUID uuid = notification.getKey(); + Instant now = Instant.now(); + + try (Connection con = sql2o.open()) + { con.createQuery("update sessions set last_used = :last_used where uuid = :uuid") .addParameter("last_used", Timestamp.from(now)) .addParameter("uuid", uuid.toString()) .executeUpdate(); - - sessionEntry.setLastUsed(now); - - return sessionEntry; } } + public void invalidate(UUID uuid) + { + // If we ever run multiple services, may need to publish something here to invalidate... + sessionCache.invalidate(uuid); + } + } From c8ffa3994d66ac5a508c13899160e5cfe9bbe870 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 18 Aug 2019 12:26:33 -0400 Subject: [PATCH 10/25] loot tracker: batch loot submissions --- .../api/loottracker/LootTrackerClient.java | 4 +- .../loottracker/LootTrackerController.java | 4 +- .../loottracker/LootTrackerService.java | 46 +++++++++---- .../LootTrackerControllerTest.java | 4 +- .../loottracker/LootTrackerPlugin.java | 67 ++++++++++++++++--- 5 files changed, 98 insertions(+), 27 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java b/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java index d250620905..59d1a567ff 100644 --- a/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java @@ -53,7 +53,7 @@ public class LootTrackerClient private final UUID uuid; - public void submit(LootRecord lootRecord) + public void submit(Collection lootRecords) { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() .addPathSegment("loottracker") @@ -61,7 +61,7 @@ public class LootTrackerClient Request request = new Request.Builder() .header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString()) - .post(RequestBody.create(JSON, GSON.toJson(lootRecord))) + .post(RequestBody.create(JSON, GSON.toJson(lootRecords))) .url(url) .build(); diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java index 2c1bd77140..1033d62187 100644 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java @@ -53,7 +53,7 @@ public class LootTrackerController private AuthFilter auth; @RequestMapping(method = RequestMethod.POST) - public void storeLootRecord(HttpServletRequest request, HttpServletResponse response, @RequestBody LootRecord record) throws IOException + public void storeLootRecord(HttpServletRequest request, HttpServletResponse response, @RequestBody Collection records) throws IOException { SessionEntry e = auth.handle(request, response); if (e == null) @@ -62,7 +62,7 @@ public class LootTrackerController return; } - service.store(record, e.getUser()); + service.store(records, e.getUser()); response.setStatus(HttpStatusCodes.STATUS_CODE_OK); } diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java index b999f4eabb..8f97ce144d 100644 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java @@ -64,7 +64,7 @@ public class LootTrackerService // Queries for inserting kills private static final String INSERT_KILL_QUERY = "INSERT INTO kills (accountId, type, eventId) VALUES (:accountId, :type, :eventId)"; - private static final String INSERT_DROP_QUERY = "INSERT INTO drops (killId, itemId, itemQuantity) VALUES (LAST_INSERT_ID(), :itemId, :itemQuantity)"; + private static final String INSERT_DROP_QUERY = "INSERT INTO drops (killId, itemId, itemQuantity) VALUES (:killId, :itemId, :itemQuantity)"; private static final String SELECT_LOOT_QUERY = "SELECT killId,time,type,eventId,itemId,itemQuantity FROM kills JOIN drops ON drops.killId = kills.id WHERE accountId = :accountId ORDER BY TIME DESC LIMIT :limit OFFSET :offset"; @@ -89,29 +89,49 @@ public class LootTrackerService /** * Store LootRecord * - * @param record LootRecord to store + * @param records LootRecords to store * @param accountId runelite account id to tie data too */ - public void store(LootRecord record, int accountId) + public void store(Collection records, int accountId) { try (Connection con = sql2o.beginTransaction()) { // Kill Entry Query - con.createQuery(INSERT_KILL_QUERY, true) - .addParameter("accountId", accountId) - .addParameter("type", record.getType()) - .addParameter("eventId", record.getEventId()) - .executeUpdate(); + Query killQuery = con.createQuery(INSERT_KILL_QUERY, true); + + for (LootRecord record : records) + { + killQuery + .addParameter("accountId", accountId) + .addParameter("type", record.getType()) + .addParameter("eventId", record.getEventId()) + .addToBatch(); + } + + killQuery.executeBatch(); + Object[] keys = con.getKeys(); + + if (keys.length != records.size()) + { + throw new RuntimeException("Mismatch in keys vs records size"); + } Query insertDrop = con.createQuery(INSERT_DROP_QUERY); // Append all queries for inserting drops - for (GameItem drop : record.getDrops()) + int idx = 0; + for (LootRecord record : records) { - insertDrop - .addParameter("itemId", drop.getId()) - .addParameter("itemQuantity", drop.getQty()) - .addToBatch(); + for (GameItem drop : record.getDrops()) + { + insertDrop + .addParameter("killId", keys[idx]) + .addParameter("itemId", drop.getId()) + .addParameter("itemQuantity", drop.getQty()) + .addToBatch(); + } + + ++idx; } insertDrop.executeBatch(); diff --git a/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java b/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java index 3c80dd72d4..ccf7ab7603 100644 --- a/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java +++ b/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java @@ -83,10 +83,10 @@ public class LootTrackerControllerTest lootRecord.setTime(Instant.now()); lootRecord.setDrops(Collections.singletonList(new GameItem(4151, 1))); - String data = RuneLiteAPI.GSON.toJson(lootRecord); + String data = RuneLiteAPI.GSON.toJson(Collections.singletonList(lootRecord)); mockMvc.perform(post("/loottracker").content(data).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); - verify(lootTrackerService).store(eq(lootRecord), anyInt()); + verify(lootTrackerService).store(eq(Collections.singletonList(lootRecord)), anyInt()); } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index 72b89c8406..edec90e676 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -34,6 +34,7 @@ import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.io.IOException; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -81,6 +82,7 @@ import net.runelite.client.game.ItemStack; import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.task.Schedule; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ImageUtil; @@ -167,6 +169,7 @@ public class LootTrackerPlugin extends Plugin @Getter(AccessLevel.PACKAGE) private LootTrackerClient lootTrackerClient; + private final List queuedLoots = new ArrayList<>(); private static Collection stack(Collection items) { @@ -220,6 +223,7 @@ public class LootTrackerPlugin extends Plugin @Subscribe public void onSessionClose(SessionClose sessionClose) { + submitLoot(); lootTrackerClient = null; } @@ -300,6 +304,7 @@ public class LootTrackerPlugin extends Plugin @Override protected void shutDown() { + submitLoot(); clientToolbar.removeNavigation(navButton); lootTrackerClient = null; chestLooted = false; @@ -324,10 +329,13 @@ public class LootTrackerPlugin extends Plugin final LootTrackerItem[] entries = buildEntries(stack(items)); SwingUtilities.invokeLater(() -> panel.add(name, combat, entries)); - if (lootTrackerClient != null && config.saveLoot()) + if (config.saveLoot()) { LootRecord lootRecord = new LootRecord(name, LootRecordType.NPC, toGameItems(items), Instant.now()); - lootTrackerClient.submit(lootRecord); + synchronized (queuedLoots) + { + queuedLoots.add(lootRecord); + } } } @@ -347,10 +355,13 @@ public class LootTrackerPlugin extends Plugin final LootTrackerItem[] entries = buildEntries(stack(items)); SwingUtilities.invokeLater(() -> panel.add(name, combat, entries)); - if (lootTrackerClient != null && config.saveLoot()) + if (config.saveLoot()) { LootRecord lootRecord = new LootRecord(name, LootRecordType.PLAYER, toGameItems(items), Instant.now()); - lootTrackerClient.submit(lootRecord); + synchronized (queuedLoots) + { + queuedLoots.add(lootRecord); + } } } @@ -420,10 +431,13 @@ public class LootTrackerPlugin extends Plugin final LootTrackerItem[] entries = buildEntries(stack(items)); SwingUtilities.invokeLater(() -> panel.add(eventType, -1, entries)); - if (lootTrackerClient != null && config.saveLoot()) + if (config.saveLoot()) { LootRecord lootRecord = new LootRecord(eventType, LootRecordType.EVENT, toGameItems(items), Instant.now()); - lootTrackerClient.submit(lootRecord); + synchronized (queuedLoots) + { + queuedLoots.add(lootRecord); + } } } @@ -521,6 +535,40 @@ public class LootTrackerPlugin extends Plugin } } + @Schedule( + period = 5, + unit = ChronoUnit.MINUTES, + asynchronous = true + ) + public void submitLootTask() + { + submitLoot(); + } + + private void submitLoot() + { + List copy; + synchronized (queuedLoots) + { + if (queuedLoots.isEmpty()) + { + return; + } + + copy = new ArrayList<>(queuedLoots); + queuedLoots.clear(); + } + + if (lootTrackerClient == null || !config.saveLoot()) + { + return; + } + + log.debug("Submitting {} loot records", copy.size()); + + lootTrackerClient.submit(copy); + } + private void takeInventorySnapshot() { final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); @@ -549,10 +597,13 @@ public class LootTrackerPlugin extends Plugin final LootTrackerItem[] entries = buildEntries(stack(items)); SwingUtilities.invokeLater(() -> panel.add(chestType, -1, entries)); - if (lootTrackerClient != null && config.saveLoot()) + if (config.saveLoot()) { LootRecord lootRecord = new LootRecord(chestType, LootRecordType.EVENT, toGameItems(items), Instant.now()); - lootTrackerClient.submit(lootRecord); + synchronized (queuedLoots) + { + queuedLoots.add(lootRecord); + } } inventorySnapshot = null; From dea4972c00891bb18ee1578d15df990fa248936d Mon Sep 17 00:00:00 2001 From: Alexsuperfly Date: Mon, 19 Aug 2019 12:47:33 -0400 Subject: [PATCH 11/25] slayer plugin: fix unknown tasks not decrementing counter --- .../client/plugins/slayer/SlayerPlugin.java | 9 ++-- .../plugins/slayer/SlayerPluginTest.java | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index 7215821734..8bb9d42b3a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -537,12 +537,9 @@ public class SlayerPlugin extends Plugin final Task task = Task.getTask(taskName); - if (task == null) - { - return; - } - - final int taskKillExp = task.getExpectedKillExp(); + // null tasks are technically valid, it only means they arent explicitly defined in the Task enum + // allow them through so that if there is a task capture failure the counter will still work + final int taskKillExp = task != null ? task.getExpectedKillExp() : 0; // Only count exp gain as a kill if the task either has no expected exp for a kill, or if the exp gain is equal // to the expected exp gain for the task. diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java index f2007e7393..fb4cdabe81 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java @@ -420,6 +420,52 @@ public class SlayerPluginTest verifyNoMoreInteractions(notifier); } + @Test + public void testCorrectlyCapturedTaskKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + final ExperienceChanged experienceChanged = new ExperienceChanged(); + experienceChanged.setSkill(Skill.SLAYER); + + when(client.getSkillExperience(Skill.SLAYER)).thenReturn(100); + slayerPlugin.onExperienceChanged(experienceChanged); + + slayerPlugin.setTaskName("Dagannoth"); + slayerPlugin.setAmount(143); + + when(client.getSkillExperience(Skill.SLAYER)).thenReturn(110); + slayerPlugin.onExperienceChanged(experienceChanged); + + assertEquals(142, slayerPlugin.getAmount()); + } + + @Test + public void testIncorrectlyCapturedTaskKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + final ExperienceChanged experienceChanged = new ExperienceChanged(); + experienceChanged.setSkill(Skill.SLAYER); + + when(client.getSkillExperience(Skill.SLAYER)).thenReturn(100); + slayerPlugin.onExperienceChanged(experienceChanged); + + slayerPlugin.setTaskName("Monster"); + slayerPlugin.setAmount(98); + + assert Task.getTask("Monster") == null; + + when(client.getSkillExperience(Skill.SLAYER)).thenReturn(110); + slayerPlugin.onExperienceChanged(experienceChanged); + + assertEquals(97, slayerPlugin.getAmount()); + } + @Test public void testJadTaskKill() { From 82dd5835b092d43e072c16af9a6733ff180931a0 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 19 Aug 2019 11:40:06 +0100 Subject: [PATCH 12/25] clues: fix names for skilling outfits --- .../plugins/cluescrolls/clues/SkillChallengeClue.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index 123d73ef44..4aea490fdc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -164,7 +164,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll any("", item(ItemID.GRACEFUL_GLOVES), item(ItemID.GRACEFUL_GLOVES_11859), item(ItemID.GRACEFUL_GLOVES_13587), item(ItemID.GRACEFUL_GLOVES_13588), item(ItemID.GRACEFUL_GLOVES_13599), item(ItemID.GRACEFUL_GLOVES_13600), item(ItemID.GRACEFUL_GLOVES_13611), item(ItemID.GRACEFUL_GLOVES_13612), item(ItemID.GRACEFUL_GLOVES_13623), item(ItemID.GRACEFUL_GLOVES_13624), item(ItemID.GRACEFUL_GLOVES_13635), item(ItemID.GRACEFUL_GLOVES_13636), item(ItemID.GRACEFUL_GLOVES_13675), item(ItemID.GRACEFUL_GLOVES_13676), item(ItemID.GRACEFUL_GLOVES_21073), item(ItemID.GRACEFUL_GLOVES_21075)), any("", item(ItemID.GRACEFUL_BOOTS), item(ItemID.GRACEFUL_BOOTS_11861), item(ItemID.GRACEFUL_BOOTS_13589), item(ItemID.GRACEFUL_BOOTS_13590), item(ItemID.GRACEFUL_BOOTS_13601), item(ItemID.GRACEFUL_BOOTS_13602), item(ItemID.GRACEFUL_BOOTS_13613), item(ItemID.GRACEFUL_BOOTS_13614), item(ItemID.GRACEFUL_BOOTS_13625), item(ItemID.GRACEFUL_BOOTS_13626), item(ItemID.GRACEFUL_BOOTS_13637), item(ItemID.GRACEFUL_BOOTS_13638), item(ItemID.GRACEFUL_BOOTS_13677), item(ItemID.GRACEFUL_BOOTS_13678), item(ItemID.GRACEFUL_BOOTS_21076), item(ItemID.GRACEFUL_BOOTS_21078)))), new SkillChallengeClue("Mix an anti-venom potion.", item(ItemID.ANTIDOTE4_5952), xOfItem(ItemID.ZULRAHS_SCALES, 20)), - new SkillChallengeClue("Mine a piece of Runite ore", "mine a piece of runite ore whilst sporting the finest mining gear.", true, ANY_PICKAXE, all(item(ItemID.PROSPECTOR_HELMET), item(ItemID.PROSPECTOR_JACKET), item(ItemID.PROSPECTOR_LEGS), item(ItemID.PROSPECTOR_BOOTS))), + new SkillChallengeClue("Mine a piece of Runite ore", "mine a piece of runite ore whilst sporting the finest mining gear.", true, ANY_PICKAXE, all("Prospector kit", item(ItemID.PROSPECTOR_HELMET), item(ItemID.PROSPECTOR_JACKET), item(ItemID.PROSPECTOR_LEGS), item(ItemID.PROSPECTOR_BOOTS))), new SkillChallengeClue("Steal a gem from the Ardougne market."), new SkillChallengeClue("Pickpocket an elf."), new SkillChallengeClue("Bind a blood rune at the blood altar.", item(ItemID.DARK_ESSENCE_FRAGMENTS)), @@ -173,8 +173,8 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll new SkillChallengeClue("Cremate a set of fiyr remains.", any("Magic or Redwood Pyre Logs", item(ItemID.MAGIC_PYRE_LOGS), item(ItemID.REDWOOD_PYRE_LOGS)), item(ItemID.TINDERBOX), item(ItemID.FIYR_REMAINS)), new SkillChallengeClue("Dissect a sacred eel.", item(ItemID.KNIFE), any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.FISHING_BAIT)), new SkillChallengeClue("Kill a lizardman shaman."), - new SkillChallengeClue("Catch an Anglerfish.", "angle for an anglerfish in your finest fishing gear.", true, any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.SANDWORMS), all(item(ItemID.ANGLER_HAT), item(ItemID.ANGLER_TOP), item(ItemID.ANGLER_WADERS), item(ItemID.ANGLER_BOOTS))), - new SkillChallengeClue("Chop a redwood log.", "chop a redwood log whilst sporting the finest lumberjack gear.", true, ANY_AXE, all(item(ItemID.LUMBERJACK_HAT), item(ItemID.LUMBERJACK_TOP), item(ItemID.LUMBERJACK_LEGS), item(ItemID.LUMBERJACK_BOOTS))), + new SkillChallengeClue("Catch an Anglerfish.", "angle for an anglerfish in your finest fishing gear.", true, any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.SANDWORMS), all("Angler's outfit", item(ItemID.ANGLER_HAT), item(ItemID.ANGLER_TOP), item(ItemID.ANGLER_WADERS), item(ItemID.ANGLER_BOOTS))), + new SkillChallengeClue("Chop a redwood log.", "chop a redwood log whilst sporting the finest lumberjack gear.", true, ANY_AXE, all("Lumberjack outfit", item(ItemID.LUMBERJACK_HAT), item(ItemID.LUMBERJACK_TOP), item(ItemID.LUMBERJACK_LEGS), item(ItemID.LUMBERJACK_BOOTS))), new SkillChallengeClue("Craft a light orb in the Dorgesh-Kaan bank.", item(ItemID.CAVE_GOBLIN_WIRE), item(ItemID.EMPTY_LIGHT_ORB)), new SkillChallengeClue("Kill a reanimated Abyssal Demon.", "kill a reanimated abyssal.", xOfItem(ItemID.SOUL_RUNE, 4), xOfItem(ItemID.BLOOD_RUNE, 1), any("Nature Rune x4", xOfItem(ItemID.NATURE_RUNE, 4), item(ItemID.BRYOPHYTAS_STAFF)), item(ItemID.ENSOULED_ABYSSAL_HEAD)), new SkillChallengeClue("Kill a Fiyr shade inside Mort'tons shade catacombs.", any("Any Silver Shade Key", item(ItemID.SILVER_KEY_RED), item(ItemID.SILVER_KEY_BROWN), item(ItemID.SILVER_KEY_CRIMSON), item(ItemID.SILVER_KEY_BLACK), item(ItemID.SILVER_KEY_PURPLE))) From 54bdb8c1129eb573358ad458a6a2f021c6fd21aa Mon Sep 17 00:00:00 2001 From: Thomas Cedeno <51754610+thomas-cedeno@users.noreply.github.com> Date: Mon, 19 Aug 2019 14:00:21 -0400 Subject: [PATCH 13/25] clues: add agility and max capes to graceful set --- .../client/plugins/cluescrolls/clues/SkillChallengeClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index 4aea490fdc..ce7b5119e1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -158,7 +158,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll new SkillChallengeClue("Complete a lap of Rellekka's Rooftop Agility Course", "complete a lap of the rellekka rooftop agility course whilst sporting the finest amount of grace.", true, all("A full Graceful set", any("", item(ItemID.GRACEFUL_HOOD), item(ItemID.GRACEFUL_HOOD_11851), item(ItemID.GRACEFUL_HOOD_13579), item(ItemID.GRACEFUL_HOOD_13580), item(ItemID.GRACEFUL_HOOD_13591), item(ItemID.GRACEFUL_HOOD_13592), item(ItemID.GRACEFUL_HOOD_13603), item(ItemID.GRACEFUL_HOOD_13604), item(ItemID.GRACEFUL_HOOD_13615), item(ItemID.GRACEFUL_HOOD_13616), item(ItemID.GRACEFUL_HOOD_13627), item(ItemID.GRACEFUL_HOOD_13628), item(ItemID.GRACEFUL_HOOD_13667), item(ItemID.GRACEFUL_HOOD_13668), item(ItemID.GRACEFUL_HOOD_21061), item(ItemID.GRACEFUL_HOOD_21063)), - any("", item(ItemID.GRACEFUL_CAPE), item(ItemID.GRACEFUL_CAPE_11853), item(ItemID.GRACEFUL_CAPE_13581), item(ItemID.GRACEFUL_CAPE_13582), item(ItemID.GRACEFUL_CAPE_13593), item(ItemID.GRACEFUL_CAPE_13594), item(ItemID.GRACEFUL_CAPE_13605), item(ItemID.GRACEFUL_CAPE_13606), item(ItemID.GRACEFUL_CAPE_13617), item(ItemID.GRACEFUL_CAPE_13618), item(ItemID.GRACEFUL_CAPE_13629), item(ItemID.GRACEFUL_CAPE_13630), item(ItemID.GRACEFUL_CAPE_13669), item(ItemID.GRACEFUL_CAPE_13670), item(ItemID.GRACEFUL_CAPE_21064), item(ItemID.GRACEFUL_CAPE_21066)), + any("", item(ItemID.GRACEFUL_CAPE), item(ItemID.GRACEFUL_CAPE_11853), item(ItemID.GRACEFUL_CAPE_13581), item(ItemID.GRACEFUL_CAPE_13582), item(ItemID.GRACEFUL_CAPE_13593), item(ItemID.GRACEFUL_CAPE_13594), item(ItemID.GRACEFUL_CAPE_13605), item(ItemID.GRACEFUL_CAPE_13606), item(ItemID.GRACEFUL_CAPE_13617), item(ItemID.GRACEFUL_CAPE_13618), item(ItemID.GRACEFUL_CAPE_13629), item(ItemID.GRACEFUL_CAPE_13630), item(ItemID.GRACEFUL_CAPE_13669), item(ItemID.GRACEFUL_CAPE_13670), item(ItemID.GRACEFUL_CAPE_21064), item(ItemID.GRACEFUL_CAPE_21066), item(ItemID.AGILITY_CAPE), item(ItemID.AGILITY_CAPET), item(ItemID.MAX_CAPE)), any("", item(ItemID.GRACEFUL_TOP), item(ItemID.GRACEFUL_TOP_11855), item(ItemID.GRACEFUL_TOP_13583), item(ItemID.GRACEFUL_TOP_13584), item(ItemID.GRACEFUL_TOP_13595), item(ItemID.GRACEFUL_TOP_13596), item(ItemID.GRACEFUL_TOP_13607), item(ItemID.GRACEFUL_TOP_13608), item(ItemID.GRACEFUL_TOP_13619), item(ItemID.GRACEFUL_TOP_13620), item(ItemID.GRACEFUL_TOP_13631), item(ItemID.GRACEFUL_TOP_13632), item(ItemID.GRACEFUL_TOP_13671), item(ItemID.GRACEFUL_TOP_13672), item(ItemID.GRACEFUL_TOP_21067), item(ItemID.GRACEFUL_TOP_21069)), any("", item(ItemID.GRACEFUL_LEGS), item(ItemID.GRACEFUL_LEGS_11857), item(ItemID.GRACEFUL_LEGS_13585), item(ItemID.GRACEFUL_LEGS_13586), item(ItemID.GRACEFUL_LEGS_13597), item(ItemID.GRACEFUL_LEGS_13598), item(ItemID.GRACEFUL_LEGS_13609), item(ItemID.GRACEFUL_LEGS_13610), item(ItemID.GRACEFUL_LEGS_13621), item(ItemID.GRACEFUL_LEGS_13622), item(ItemID.GRACEFUL_LEGS_13633), item(ItemID.GRACEFUL_LEGS_13634), item(ItemID.GRACEFUL_LEGS_13673), item(ItemID.GRACEFUL_LEGS_13674), item(ItemID.GRACEFUL_LEGS_21070), item(ItemID.GRACEFUL_LEGS_21072)), any("", item(ItemID.GRACEFUL_GLOVES), item(ItemID.GRACEFUL_GLOVES_11859), item(ItemID.GRACEFUL_GLOVES_13587), item(ItemID.GRACEFUL_GLOVES_13588), item(ItemID.GRACEFUL_GLOVES_13599), item(ItemID.GRACEFUL_GLOVES_13600), item(ItemID.GRACEFUL_GLOVES_13611), item(ItemID.GRACEFUL_GLOVES_13612), item(ItemID.GRACEFUL_GLOVES_13623), item(ItemID.GRACEFUL_GLOVES_13624), item(ItemID.GRACEFUL_GLOVES_13635), item(ItemID.GRACEFUL_GLOVES_13636), item(ItemID.GRACEFUL_GLOVES_13675), item(ItemID.GRACEFUL_GLOVES_13676), item(ItemID.GRACEFUL_GLOVES_21073), item(ItemID.GRACEFUL_GLOVES_21075)), From 07cf27c8fcbb50d82c95bbf32ca677ee4354361c Mon Sep 17 00:00:00 2001 From: Ron Young Date: Mon, 19 Aug 2019 13:19:52 -0500 Subject: [PATCH 14/25] ChatboxItemSearch: fix null name check --- .../net/runelite/client/game/chatbox/ChatboxItemSearch.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxItemSearch.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxItemSearch.java index 0ff26af690..906e338b55 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxItemSearch.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxItemSearch.java @@ -290,9 +290,9 @@ public class ChatboxItemSearch extends ChatboxTextInput for (int i = 0; i < client.getItemCount() && results.size() < MAX_RESULTS; i++) { ItemComposition itemComposition = itemManager.getItemComposition(itemManager.canonicalize(i)); - String name = itemComposition.getName(); + String name = itemComposition.getName().toLowerCase(); // The client assigns "null" to item names of items it doesn't know about - if (!name.equals("null") && name.toLowerCase().contains(search)) + if (!name.equals("null") && name.contains(search)) { // This may already be in the map due to canonicalize mapping the item to something we've already seen results.putIfAbsent(itemComposition.getId(), itemComposition); From 5fafa6faf1ee6468dd1af488e00a3449c2ac361b Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 19 Aug 2019 17:34:48 -0400 Subject: [PATCH 15/25] ui: center fatal error dialog on screen --- .../src/main/java/net/runelite/client/ui/FatalErrorDialog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/FatalErrorDialog.java b/runelite-client/src/main/java/net/runelite/client/ui/FatalErrorDialog.java index 746546fc10..34517868d8 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/FatalErrorDialog.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/FatalErrorDialog.java @@ -161,6 +161,7 @@ public class FatalErrorDialog extends JDialog addButton("Exit", () -> System.exit(-1)); pack(); + setLocationRelativeTo(null); SplashScreen.stop(); setVisible(true); } From 7d23b16ef4faebd54a74f2c84149aa2d94db4c57 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 19 Aug 2019 17:39:38 -0400 Subject: [PATCH 16/25] rs: validate loaded config If an empty body or error response is received, the client would attempt to use a null code base and initial jar, which immediately failed --- .../net/runelite/client/rs/ClientConfigLoader.java | 10 +++++++--- .../main/java/net/runelite/client/rs/ClientLoader.java | 7 +++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java index 29459d9e7f..ed105ec830 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java @@ -55,11 +55,15 @@ class ClientConfigLoader final RSConfig config = new RSConfig(); - try (final Response response = RuneLiteAPI.CLIENT.newCall(request).execute(); - final BufferedReader in = new BufferedReader(new InputStreamReader(response.body().byteStream()))) + try (final Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) { - String str; + if (!response.isSuccessful()) + { + throw new IOException("Unsuccessful response: " + response.message()); + } + String str; + final BufferedReader in = new BufferedReader(new InputStreamReader(response.body().byteStream())); while ((str = in.readLine()) != null) { int idx = str.indexOf('='); diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java index f6c77916c4..dbd2c0c95e 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java @@ -26,6 +26,7 @@ */ package net.runelite.client.rs; +import com.google.common.base.Strings; import com.google.common.hash.Hashing; import com.google.common.io.ByteStreams; import com.google.common.reflect.TypeToken; @@ -110,6 +111,12 @@ public class ClientLoader implements Supplier try { config = ClientConfigLoader.fetch(host); + + if (Strings.isNullOrEmpty(config.getCodeBase()) || Strings.isNullOrEmpty(config.getInitialJar()) || Strings.isNullOrEmpty(config.getInitialClass())) + { + throw new IOException("Invalid or missing jav_config"); + } + break; } catch (IOException e) From 6c56880989a72143a8e670729d3e6f2fbd318682 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Aug 2019 08:34:27 -0400 Subject: [PATCH 17/25] slayer plugin: update desert lizards task to lizards --- .../src/main/java/net/runelite/client/plugins/slayer/Task.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a85812e723..da5f237ab4 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 @@ -79,7 +79,6 @@ enum Task DARK_BEASTS("Dark beasts", ItemID.DARK_BEAST, "Night beast"), DARK_WARRIORS("Dark warriors", ItemID.BLACK_MED_HELM, "Dark warrior"), DERANGED_ARCHAEOLOGIST("Deranged Archaeologist", ItemID.ARCHAEOLOGISTS_DIARY), - DESERT_LIZARDS("Desert lizards", ItemID.DESERT_LIZARD, 4, ItemID.ICE_COOLER, "Small lizard", "Lizard"), DOGS("Dogs", ItemID.GUARD_DOG, "Jackal"), DRAKES("Drakes", ItemID.DRAKE), DUST_DEVILS("Dust devils", ItemID.DUST_DEVIL, "Choke devil"), @@ -124,6 +123,7 @@ enum Task KURASK("Kurask", ItemID.KURASK), ROGUES("Rogues", ItemID.ROGUE_MASK, "Rogue"), LESSER_DEMONS("Lesser demons", ItemID.LESSER_DEMON_MASK), + LIZARDS("Lizards", ItemID.DESERT_LIZARD, "Desert lizard", "Sulphur lizard", "Small lizard", "Lizard"), LIZARDMEN("Lizardmen", ItemID.LIZARDMAN_FANG, "Lizardman"), MINIONS_OF_SCABARAS("Minions of scabaras", ItemID.GOLDEN_SCARAB, "Scarab swarm", "Locust rider", "Scarab mage"), MINOTAURS("Minotaurs", ItemID.ENSOULED_MINOTAUR_HEAD), From 6bd7e4fb02bf2a4021f744c477702b76b23e7b59 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Tue, 20 Aug 2019 14:13:12 +0100 Subject: [PATCH 18/25] gpu: fix MSAA white pixels --- .../main/resources/net/runelite/client/plugins/gpu/frag.glsl | 2 +- .../main/resources/net/runelite/client/plugins/gpu/geom.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/frag.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/frag.glsl index 03d8464642..646d5dfd7d 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/frag.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/frag.glsl @@ -31,7 +31,7 @@ uniform float smoothBanding; uniform vec4 fogColor; in vec4 Color; -in float fHsl; +centroid in float fHsl; in vec4 fUv; in float fogAmount; diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl index c644b1960e..28a339f788 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl @@ -52,7 +52,7 @@ in vec4 vUv[]; in float vFogAmount[]; out vec4 Color; -out float fHsl; +centroid out float fHsl; out vec4 fUv; out float fogAmount; From 65758d54f3b82f0dd6964410551a5a28b0eab76f Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Tue, 20 Aug 2019 14:41:53 -0700 Subject: [PATCH 19/25] itemskeptondeath: fix avernic defender price --- .../itemskeptondeath/FixedPriceItem.java | 5 +++- .../ItemsKeptOnDeathPluginTest.java | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/FixedPriceItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/FixedPriceItem.java index 74120a47d6..aae7d1694b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/FixedPriceItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/FixedPriceItem.java @@ -214,7 +214,10 @@ enum FixedPriceItem VERACS_FLAIL_25(ItemID.VERACS_FLAIL_25, 2500, ItemID.VERACS_FLAIL_0), VERACS_FLAIL_50(ItemID.VERACS_FLAIL_50, 5000, ItemID.VERACS_FLAIL_0), VERACS_FLAIL_75(ItemID.VERACS_FLAIL_75, 7500, ItemID.VERACS_FLAIL_0), - VERACS_FLAIL_100(ItemID.VERACS_FLAIL_100, 10000, ItemID.VERACS_FLAIL_0); + VERACS_FLAIL_100(ItemID.VERACS_FLAIL_100, 10000, ItemID.VERACS_FLAIL_0), + + AVERNIC_DEFENDER(ItemID.AVERNIC_DEFENDER, 4040000), + ; private final int itemId; private final int offset; diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java index 19ffc8f9a8..7294a55f0c 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java @@ -628,4 +628,29 @@ public class ItemsKeptOnDeathPluginTest final List lost = deathItems.getLostItems(); assertTrue(lost.contains(new ItemStack(ItemID.DRAGON_DEFENDER, 1))); } + + @Test + public void avernicDefenderPriceTest() + { + final Item defender = mItem(ItemID.AVERNIC_DEFENDER, 1, "Avernic defender", false, 0); + final int defenderOffset = FixedPriceItem.AVERNIC_DEFENDER.getOffset(); + final Integer defenderBrokenPrice = BrokenOnDeathItem.getRepairPrice(ItemID.AVERNIC_DEFENDER); + final int defenderExpectedPrice = (defenderBrokenPrice == null ? 0 : defenderBrokenPrice) + defenderOffset; + assertEquals(defenderExpectedPrice, plugin.getDeathPrice(defender)); + + final Item[] inv = new Item[] + { + defender, + mItem(ItemID.BERSERKER_RING_I, 1, "Berserker Ring (i)", false, 3042579) + }; + + plugin.isSkulled = true; + plugin.protectingItem = true; + plugin.wildyLevel = 21; + + final DeathItems deathItems = plugin.calculateKeptLostItems(inv, new Item[0]); + + final List kept = deathItems.getKeptItems(); + assertTrue(kept.contains(new ItemStack(ItemID.AVERNIC_DEFENDER, 1))); + } } From de89277e7601430d87ef77fdcb6616de8ec86f1b Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Aug 2019 17:33:31 -0400 Subject: [PATCH 20/25] low memory plugin: set low memory mode after startup Setting low memory mode too early prevents high detail textures from loading, which breaks the gpu plugin --- .../plugins/lowmemory/LowMemoryPlugin.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java index 195feefaf4..66270da3ad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java @@ -26,7 +26,10 @@ package net.runelite.client.plugins.lowmemory; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.events.GameStateChanged; import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -47,7 +50,10 @@ public class LowMemoryPlugin extends Plugin @Override protected void startUp() { - clientThread.invoke(() -> client.changeMemoryMode(true)); + if (client.getGameState() == GameState.LOGGED_IN) + { + clientThread.invoke(() -> client.changeMemoryMode(true)); + } } @Override @@ -55,4 +61,16 @@ public class LowMemoryPlugin extends Plugin { clientThread.invoke(() -> client.changeMemoryMode(false)); } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + // When the client starts it initializes the texture size based on the memory mode setting. + // Don't set low memory before the login screen is ready to prevent loading the low detail textures, + // which breaks the gpu plugin due to it requiring the 128x128px textures + if (event.getGameState() == GameState.LOGIN_SCREEN) + { + client.changeMemoryMode(true); + } + } } From b250f9fb2f51fbbce2c7681ef4cff7cf63772ab7 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Aug 2019 17:34:28 -0400 Subject: [PATCH 21/25] gpu plugin: require high detail textures The texture storage buffer is fixed at 128x128 per texture, smaller textures won't render correctly --- .../runelite/client/plugins/gpu/TextureManager.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/TextureManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/TextureManager.java index 0ce04acb1e..82caedafc5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/TextureManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/TextureManager.java @@ -38,7 +38,6 @@ class TextureManager private static final float PERC_64 = 1f / 64f; private static final float PERC_128 = 1f / 128f; - private static final int SMALL_TEXTURE_SIZE = 64; private static final int TEXTURE_SIZE = 128; int initTextureArray(TextureProvider textureProvider, GL4 gl) @@ -130,8 +129,15 @@ class TextureManager ++cnt; - int srcSize = srcPixels.length == 4096 ? SMALL_TEXTURE_SIZE : TEXTURE_SIZE; - byte[] pixels = convertPixels(srcPixels, srcSize, srcSize, TEXTURE_SIZE, TEXTURE_SIZE); + if (srcPixels.length != TEXTURE_SIZE * TEXTURE_SIZE) + { + // The texture storage is 128x128 bytes, and will only work correctly with the + // 128x128 textures from high detail mode + log.warn("Texture size for {} is {}!", textureId, srcPixels.length); + continue; + } + + byte[] pixels = convertPixels(srcPixels, TEXTURE_SIZE, TEXTURE_SIZE, TEXTURE_SIZE, TEXTURE_SIZE); ByteBuffer pixelBuffer = ByteBuffer.wrap(pixels); gl.glTexSubImage3D(gl.GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureId, TEXTURE_SIZE, TEXTURE_SIZE, 1, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, pixelBuffer); From bd8a31cc0b9bac73a4a31a374c1f5708b0f70f8c Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Aug 2019 19:44:03 -0400 Subject: [PATCH 22/25] fishing plugin: deduplicate spot overlay color logic --- .../plugins/fishing/FishingSpotOverlay.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java index 80cdaec1e4..ca5e289b8a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java @@ -95,7 +95,19 @@ class FishingSpotOverlay extends Overlay continue; } - Color color = npc.getGraphic() == GraphicID.FLYING_FISH ? Color.RED : Color.CYAN; + Color color; + if (npc.getGraphic() == GraphicID.FLYING_FISH) + { + color = Color.RED; + } + else if (spot == FishingSpot.COMMON_TENCH && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) + { + color = Color.GREEN; + } + else + { + color = Color.CYAN; + } if (spot == FishingSpot.MINNOW && config.showMinnowOverlay()) { @@ -127,12 +139,6 @@ class FishingSpotOverlay extends Overlay { Polygon poly = npc.getCanvasTilePoly(); - if (spot == FishingSpot.COMMON_TENCH - && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) - { - color = Color.GREEN; - } - if (poly != null) { OverlayUtil.renderPolygon(graphics, poly, color.darker()); @@ -164,12 +170,6 @@ class FishingSpotOverlay extends Overlay String text = spot.getName(); Point textLocation = npc.getCanvasTextLocation(graphics, text, npc.getLogicalHeight() + 40); - if (spot == FishingSpot.COMMON_TENCH - && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) - { - color = Color.GREEN; - } - if (textLocation != null) { OverlayUtil.renderTextLocation(graphics, textLocation, text, color.darker()); From 9fc04bf7e2469b4f77445c62464dedc9d117092b Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Aug 2019 19:44:14 -0400 Subject: [PATCH 23/25] fishing plugin: don't render the same fishing spot twice --- .../client/plugins/fishing/FishingPlugin.java | 16 +++++++++++++++- .../plugins/fishing/FishingSpotOverlay.java | 12 ++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) 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 2f55bf8158..a145d357a8 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 @@ -430,7 +430,21 @@ public class FishingPlugin extends Plugin private void inverseSortSpotDistanceFromPlayer() { + if (fishingSpots.isEmpty()) + { + return; + } + final LocalPoint cameraPoint = new LocalPoint(client.getCameraX(), client.getCameraY()); - fishingSpots.sort(Comparator.comparing(npc -> -1 * npc.getLocalLocation().distanceTo(cameraPoint))); + fishingSpots.sort( + Comparator.comparing( + // Negate to have the furthest first + (NPC npc) -> -npc.getLocalLocation().distanceTo(cameraPoint)) + // Order by position + .thenComparing(NPC::getLocalLocation, Comparator.comparing(LocalPoint::getX) + .thenComparing(LocalPoint::getY)) + // And then by id + .thenComparing(NPC::getId) + ); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java index ca5e289b8a..5c4b6b0d21 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java @@ -40,6 +40,7 @@ import net.runelite.api.NPC; import net.runelite.api.Perspective; import net.runelite.api.Point; import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; import net.runelite.client.game.ItemManager; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; @@ -81,6 +82,8 @@ class FishingSpotOverlay extends Overlay return null; } + FishingSpot previousSpot = null; + WorldPoint previousLocation = null; for (NPC npc : plugin.getFishingSpots()) { FishingSpot spot = FishingSpot.getSPOTS().get(npc.getId()); @@ -95,6 +98,12 @@ class FishingSpotOverlay extends Overlay continue; } + // This relies on the sort order to keep identical npcs on the same tile adjacent to each other + if (previousSpot == spot && previousLocation.equals(npc.getWorldLocation())) + { + continue; + } + Color color; if (npc.getGraphic() == GraphicID.FLYING_FISH) { @@ -175,6 +184,9 @@ class FishingSpotOverlay extends Overlay OverlayUtil.renderTextLocation(graphics, textLocation, text, color.darker()); } } + + previousSpot = spot; + previousLocation = npc.getWorldLocation(); } return null; From d8be3b85cfbd902e500e15423f4e584b15d3e1d0 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Aug 2019 19:46:16 -0400 Subject: [PATCH 24/25] fishingspot: don't expose spots map --- .../net/runelite/client/plugins/fishing/FishingPlugin.java | 6 +++--- .../net/runelite/client/plugins/fishing/FishingSpot.java | 6 +++++- .../client/plugins/fishing/FishingSpotMinimapOverlay.java | 2 +- .../runelite/client/plugins/fishing/FishingSpotOverlay.java | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) 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 a145d357a8..39cbb4253e 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 @@ -217,7 +217,7 @@ public class FishingPlugin extends Plugin } final NPC npc = (NPC) target; - FishingSpot spot = FishingSpot.getSPOTS().get(npc.getId()); + FishingSpot spot = FishingSpot.findSpot(npc.getId()); if (spot == null) { @@ -289,7 +289,7 @@ public class FishingPlugin extends Plugin for (NPC npc : fishingSpots) { - if (FishingSpot.getSPOTS().get(npc.getId()) == FishingSpot.MINNOW && config.showMinnowOverlay()) + if (FishingSpot.findSpot(npc.getId()) == FishingSpot.MINNOW && config.showMinnowOverlay()) { final int id = npc.getIndex(); final MinnowSpot minnowSpot = minnowSpots.get(id); @@ -315,7 +315,7 @@ public class FishingPlugin extends Plugin { final NPC npc = event.getNpc(); - if (!FishingSpot.getSPOTS().containsKey(npc.getId())) + if (FishingSpot.findSpot(npc.getId()) == null) { return; } 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 a26c216ad0..0a5242178c 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 @@ -172,7 +172,6 @@ enum FishingSpot COMMON_TENCH("Common tench, Bluegill, Greater siren, Mottled eel", ItemID.COMMON_TENCH, FISHING_SPOT_8523); - @Getter private static final Map SPOTS; private final String name; @@ -200,4 +199,9 @@ enum FishingSpot this.fishSpriteId = fishSpriteId; this.ids = ids; } + + static FishingSpot findSpot(int id) + { + return SPOTS.get(id); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotMinimapOverlay.java index fd01d32acc..09a6b612fc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotMinimapOverlay.java @@ -64,7 +64,7 @@ class FishingSpotMinimapOverlay extends Overlay for (NPC npc : plugin.getFishingSpots()) { - FishingSpot spot = FishingSpot.getSPOTS().get(npc.getId()); + FishingSpot spot = FishingSpot.findSpot(npc.getId()); if (spot == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java index 5c4b6b0d21..257955c878 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java @@ -86,7 +86,7 @@ class FishingSpotOverlay extends Overlay WorldPoint previousLocation = null; for (NPC npc : plugin.getFishingSpots()) { - FishingSpot spot = FishingSpot.getSPOTS().get(npc.getId()); + FishingSpot spot = FishingSpot.findSpot(npc.getId()); if (spot == null) { From 664ab26de91523249580dcb2a8e6d16d232ef7fd Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 13 Jul 2019 00:00:57 -0700 Subject: [PATCH 25/25] slayerplugin: Fix first slayer kill not being registered Because a user can have 0 slayer experience on a new account, we cannot rely on 0 as the pre-login value. Prior to this change, a player getting their first slayer kill in the described scenario would cause it not to be counted toward the tracked task. --- .../client/plugins/slayer/SlayerPlugin.java | 27 +++++++++++-------- .../plugins/slayer/SlayerPluginTest.java | 22 +++++++++++++++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index 8bb9d42b3a..228a0c6101 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -204,7 +204,7 @@ public class SlayerPlugin extends Plugin private int points; private TaskCounter counter; - private int cachedXp; + private int cachedXp = -1; private Instant infoTimer; private boolean loginFlag; private List targetNames = new ArrayList<>(); @@ -217,15 +217,19 @@ public class SlayerPlugin extends Plugin overlayManager.add(targetWeaknessOverlay); overlayManager.add(targetMinimapOverlay); - if (client.getGameState() == GameState.LOGGED_IN - && config.amount() != -1 - && !config.taskName().isEmpty()) + if (client.getGameState() == GameState.LOGGED_IN) { - points = config.points(); - streak = config.streak(); - setExpeditiousChargeCount(config.expeditious()); - setSlaughterChargeCount(config.slaughter()); - clientThread.invoke(() -> setTask(config.taskName(), config.amount(), config.initialAmount(), config.taskLocation())); + cachedXp = client.getSkillExperience(SLAYER); + + if (config.amount() != -1 + && !config.taskName().isEmpty()) + { + points = config.points(); + streak = config.streak(); + setExpeditiousChargeCount(config.expeditious()); + setSlaughterChargeCount(config.slaughter()); + clientThread.invoke(() -> setTask(config.taskName(), config.amount(), config.initialAmount(), config.taskLocation())); + } } chatCommandManager.registerCommandAsync(TASK_COMMAND_STRING, this::taskLookup, this::taskSubmit); @@ -240,6 +244,7 @@ public class SlayerPlugin extends Plugin overlayManager.remove(targetMinimapOverlay); removeCounter(); highlightedTargets.clear(); + cachedXp = -1; chatCommandManager.unregisterCommand(TASK_COMMAND_STRING); } @@ -257,7 +262,7 @@ public class SlayerPlugin extends Plugin { case HOPPING: case LOGGING_IN: - cachedXp = 0; + cachedXp = -1; taskName = ""; amount = 0; loginFlag = true; @@ -528,7 +533,7 @@ public class SlayerPlugin extends Plugin return; } - if (cachedXp == 0) + if (cachedXp == -1) { // this is the initial xp sent on login cachedXp = slayerExp; diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java index fb4cdabe81..4eed41d277 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java @@ -681,4 +681,26 @@ public class SlayerPluginTest verify(chatMessageManager, never()).update(any(MessageNode.class)); } + + @Test + public void testNewAccountSlayerKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + final ExperienceChanged experienceChanged = new ExperienceChanged(); + experienceChanged.setSkill(Skill.SLAYER); + + slayerPlugin.setTaskName("Bears"); + slayerPlugin.setAmount(35); + + when(client.getSkillExperience(Skill.SLAYER)).thenReturn(0); + slayerPlugin.onExperienceChanged(experienceChanged); + + when(client.getSkillExperience(Skill.SLAYER)).thenReturn(27); + slayerPlugin.onExperienceChanged(experienceChanged); + + assertEquals(34, slayerPlugin.getAmount()); + } }