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 66dc3b66c6..080f6443a1 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -2339,6 +2339,7 @@ public interface Client extends GameEngine ClanSettings getClanSettings(int clanId); void setUnlockedFps(boolean unlock); + void setUnlockedFpsTarget(int fps); /** * Gets the ambient sound effects diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java b/runelite-client/src/main/java/net/runelite/client/game/RunepouchRune.java similarity index 91% rename from runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java rename to runelite-client/src/main/java/net/runelite/client/game/RunepouchRune.java index 3031aa7b97..f9a863124f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java +++ b/runelite-client/src/main/java/net/runelite/client/game/RunepouchRune.java @@ -22,7 +22,7 @@ * (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.runepouch; +package net.runelite.client.game; import com.google.common.collect.ImmutableMap; @@ -52,7 +52,7 @@ import static net.runelite.api.ItemID.STEAM_RUNE; import static net.runelite.api.ItemID.WATER_RUNE; import static net.runelite.api.ItemID.WRATH_RUNE; -public enum Runes +public enum RunepouchRune { AIR(1, AIR_RUNE), WATER(2, WATER_RUNE), @@ -85,25 +85,25 @@ public enum Runes @Setter private BufferedImage image; - private static final Map runes; + private static final Map runes; static { - ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - for (Runes rune : values()) + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (RunepouchRune rune : values()) { builder.put(rune.getId(), rune); } runes = builder.build(); } - Runes(int id, int itemId) + RunepouchRune(int id, int itemId) { this.id = id; this.itemId = itemId; } - public static Runes getRune(int varbit) + public static RunepouchRune getRune(int varbit) { return runes.get(varbit); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java index 187510d517..43a5eb22c9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java @@ -477,6 +477,32 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener Widget bankTitle = client.getWidget(WidgetInfo.BANK_TITLE_BAR); bankTitle.setText("Tag tab " + activeTab.getTag() + ""); } + + // Recompute scroll size. Only required for tag tab tab and with remove separators, to remove the + // space that the separators took. + if (tabInterface.isTagTabActive() || (tabInterface.isActive() && config.removeSeparators())) + { + Widget itemContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER); + Widget[] children = itemContainer.getChildren(); + int items = 0; + for (Widget child : children) + { + if (child != null && child.getItemId() != -1 && !child.isHidden()) + { + ++items; + } + } + + // New scroll height for if_setscrollsize + final int adjustedScrollHeight = (Math.max(0, items - 1) / ITEMS_PER_ROW) * ITEM_VERTICAL_SPACING + + ITEM_VERTICAL_SPACING + ITEM_CONTAINER_BOTTOM_PADDING; + + // This is prior to bankmain_finishbuilding running, so the arguments are still on the stack. Overwrite + // argument int12 (7 from the end) which is the height passed to if_setscrollsize + final int[] intStack = client.getIntStack(); + final int intStackSize = client.getIntStackSize(); + intStack[intStackSize - 7] = adjustedScrollHeight; + } } else if (scriptId == ScriptID.BANKMAIN_SEARCH_TOGGLE) { @@ -510,15 +536,6 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener return; } - if (tabInterface.isTagTabActive()) - { - int numTabs = (int) Arrays.stream(itemContainer.getDynamicChildren()) - .filter(child -> child.getItemId() != -1 && !child.isHidden()) - .count(); - updateBankContainerScrollHeight(numTabs); - return; - } - if (!tabInterface.isActive() || !config.removeSeparators()) { return; @@ -540,14 +557,9 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener int adjYOffset = (items / ITEMS_PER_ROW) * ITEM_VERTICAL_SPACING; int adjXOffset = (items % ITEMS_PER_ROW) * ITEM_HORIZONTAL_SPACING + ITEM_ROW_START; - if (child.getOriginalY() != adjYOffset) + if (child.getOriginalY() != adjYOffset || child.getOriginalX() != adjXOffset) { child.setOriginalY(adjYOffset); - child.revalidate(); - } - - if (child.getOriginalX() != adjXOffset) - { child.setOriginalX(adjXOffset); child.revalidate(); } @@ -562,23 +574,6 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener child.setHidden(true); } } - - updateBankContainerScrollHeight(items); - } - - private void updateBankContainerScrollHeight(int items) - { - Widget bankItemContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER); - int itemContainerHeight = bankItemContainer.getHeight(); - final int adjustedScrollHeight = (Math.max(0, items - 1) / ITEMS_PER_ROW) * ITEM_VERTICAL_SPACING + ITEM_VERTICAL_SPACING + ITEM_CONTAINER_BOTTOM_PADDING; - bankItemContainer.setScrollHeight(Math.max(adjustedScrollHeight, itemContainerHeight)); - - final int itemContainerScroll = bankItemContainer.getScrollY(); - clientThread.invokeLater(() -> - client.runScript(ScriptID.UPDATE_SCROLLBAR, - WidgetInfo.BANK_SCROLLBAR.getId(), - WidgetInfo.BANK_ITEM_CONTAINER.getId(), - itemContainerScroll)); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index 0342ef45e8..05a3240f95 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -316,7 +316,7 @@ public class TabInterface return; } - chatboxPanelManager.openTextInput((inventory ? "Inventory " : "Equipment ") + " tags:") + chatboxPanelManager.openTextInput((inventory ? "Inventory" : "Equipment") + " tags:") .addCharValidator(FILTERED_CHARS) .onDone((Consumer) (newTags) -> clientThread.invoke(() -> @@ -573,7 +573,7 @@ public class TabInterface switch (eventName) { - case "setBankScroll": + case "skipBankLayout": if (!isTabMenuActive()) { setTabMenuVisible(false); @@ -582,11 +582,8 @@ public class TabInterface setTabMenuVisible(true); - // scroll height - intStack[intStackSize - 3] = (((tabManager.getTabs().size() - 1) / BANK_ITEMS_PER_ROW) + 1) * (BANK_ITEM_HEIGHT + BANK_ITEM_Y_PADDING); - // skip normal bank layout - intStack[intStackSize - 2] = 1; + intStack[intStackSize - 1] = 1; break; case "beforeBankLayout": setTabMenuVisible(false); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java index b5d111035a..ab0e0e7149 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -316,6 +317,9 @@ public class ChatFilterPlugin extends Plugin { String strippedMessage = jagexPrintableCharMatcher.retainFrom(message) .replace('\u00A0', ' '); + String strippedAccents = StringUtils.stripAccents(strippedMessage); + assert strippedMessage.length() == strippedAccents.length(); + if (username != null && shouldFilterByName(username)) { switch (config.filterType()) @@ -332,16 +336,20 @@ public class ChatFilterPlugin extends Plugin boolean filtered = false; for (Pattern pattern : filteredPatterns) { - Matcher m = pattern.matcher(strippedMessage); + Matcher m = pattern.matcher(strippedAccents); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); + int idx = 0; while (m.find()) { switch (config.filterType()) { case CENSOR_WORDS: - m.appendReplacement(sb, StringUtils.repeat('*', m.group(0).length())); + MatchResult matchResult = m.toMatchResult(); + sb.append(strippedMessage, idx, matchResult.start()) + .append(StringUtils.repeat('*', matchResult.group().length())); + idx = m.end(); filtered = true; break; case CENSOR_MESSAGE: @@ -350,9 +358,10 @@ public class ChatFilterPlugin extends Plugin return null; } } - m.appendTail(sb); + sb.append(strippedMessage.substring(idx)); strippedMessage = sb.toString(); + assert strippedMessage.length() == strippedAccents.length(); } return filtered ? strippedMessage : message; @@ -364,15 +373,18 @@ public class ChatFilterPlugin extends Plugin filteredNamePatterns.clear(); Text.fromCSV(config.filteredWords()).stream() + .map(StringUtils::stripAccents) .map(s -> Pattern.compile(Pattern.quote(s), Pattern.CASE_INSENSITIVE)) .forEach(filteredPatterns::add); NEWLINE_SPLITTER.splitToList(config.filteredRegex()).stream() + .map(StringUtils::stripAccents) .map(ChatFilterPlugin::compilePattern) .filter(Objects::nonNull) .forEach(filteredPatterns::add); NEWLINE_SPLITTER.splitToList(config.filteredNames()).stream() + .map(StringUtils::stripAccents) .map(ChatFilterPlugin::compilePattern) .filter(Objects::nonNull) .forEach(filteredNamePatterns::add); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java index bcc207325b..ac333a0e6b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java @@ -64,6 +64,7 @@ import net.runelite.api.Scene; import net.runelite.api.ScriptID; import net.runelite.api.Tile; import net.runelite.api.TileObject; +import net.runelite.api.Varbits; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; @@ -95,6 +96,7 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.OverlayMenuClicked; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.RunepouchRune; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDependency; import net.runelite.client.plugins.PluginDescriptor; @@ -143,6 +145,12 @@ public class ClueScrollPlugin extends Plugin private static final Color HIGHLIGHT_HOVER_BORDER_COLOR = HIGHLIGHT_BORDER_COLOR.darker(); private static final Color HIGHLIGHT_FILL_COLOR = new Color(0, 255, 0, 20); private static final String CLUE_TAG_NAME = "clue"; + private static final Varbits[] RUNEPOUCH_AMOUNT_VARBITS = { + Varbits.RUNE_POUCH_AMOUNT1, Varbits.RUNE_POUCH_AMOUNT2, Varbits.RUNE_POUCH_AMOUNT3 + }; + private static final Varbits[] RUNEPOUCH_RUNE_VARBITS = { + Varbits.RUNE_POUCH_RUNE1, Varbits.RUNE_POUCH_RUNE2, Varbits.RUNE_POUCH_RUNE3 + }; @Getter private ClueScroll clue; @@ -350,19 +358,44 @@ public class ClueScrollPlugin extends Plugin @Subscribe public void onItemContainerChanged(final ItemContainerChanged event) { - if (event.getItemContainer() == client.getItemContainer(InventoryID.EQUIPMENT)) + if (event.getContainerId() == InventoryID.EQUIPMENT.getId()) { equippedItems = event.getItemContainer().getItems(); return; } - if (event.getItemContainer() != client.getItemContainer(InventoryID.INVENTORY)) + if (event.getContainerId() != InventoryID.INVENTORY.getId()) { return; } inventoryItems = event.getItemContainer().getItems(); + // Add runes from rune pouch to inventoryItems + if (event.getItemContainer().contains(ItemID.RUNE_POUCH) || event.getItemContainer().contains(ItemID.RUNE_POUCH_L)) + { + List runePouchContents = getRunepouchContents(); + + if (!runePouchContents.isEmpty()) + { + for (int i = 0; i < inventoryItems.length; i++) + { + Item invItem = inventoryItems[i]; + for (Item rune : runePouchContents) + { + if (invItem.getId() == rune.getId()) + { + inventoryItems[i] = new Item(invItem.getId(), rune.getQuantity() + invItem.getQuantity()); + runePouchContents.remove(rune); + break; + } + } + } + + inventoryItems = ArrayUtils.addAll(inventoryItems, runePouchContents.toArray(new Item[0])); + } + } + // Check if item was removed from inventory if (clue != null && clueItemId != null) { @@ -393,6 +426,30 @@ public class ClueScrollPlugin extends Plugin } } + private List getRunepouchContents() + { + List items = new ArrayList<>(RUNEPOUCH_AMOUNT_VARBITS.length); + for (int i = 0; i < RUNEPOUCH_AMOUNT_VARBITS.length; i++) + { + int amount = client.getVar(RUNEPOUCH_AMOUNT_VARBITS[i]); + if (amount <= 0) + { + continue; + } + + int varbId = client.getVar(RUNEPOUCH_RUNE_VARBITS[i]); + RunepouchRune rune = RunepouchRune.getRune(varbId); + if (rune == null) + { + continue; + } + + Item item = new Item(rune.getItemId(), amount); + items.add(item); + } + return items; + } + @Subscribe public void onNpcSpawned(final NpcSpawned event) { 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 7ff2f150ba..1b7925b380 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 @@ -143,7 +143,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam new SkillChallengeClue("Equip a Dragon Scimitar.", true, any("Any Dragon Scimitar", item(ItemID.DRAGON_SCIMITAR), item(ItemID.DRAGON_SCIMITAR_OR))), new SkillChallengeClue("Enchant some Dragonstone Jewellery.", "enchant a piece of dragonstone jewellery.", xOfItem(ItemID.COSMIC_RUNE, 1), - any("Water Rune x15", xOfItem(ItemID.WATER_RUNE, 15), xOfItem(ItemID.MIST_RUNE, 15), xOfItem(ItemID.MUD_RUNE, 15), xOfItem(ItemID.STEAM_RUNE, 15), item(ItemID.STAFF_OF_WATER), item(ItemID.WATER_BATTLESTAFF), item(ItemID.MYSTIC_WATER_STAFF), item(ItemID.MUD_BATTLESTAFF), item(ItemID.MYSTIC_MUD_STAFF), item(ItemID.MIST_BATTLESTAFF), item(ItemID.MYSTIC_MIST_STAFF), item(ItemID.STEAM_BATTLESTAFF), item(ItemID.MYSTIC_STEAM_STAFF), item(ItemID.STEAM_BATTLESTAFF_12795), item(ItemID.MYSTIC_STEAM_STAFF_12796), item(ItemID.KODAI_WAND)), + any("Water Rune x15", xOfItem(ItemID.WATER_RUNE, 15), xOfItem(ItemID.MIST_RUNE, 15), xOfItem(ItemID.MUD_RUNE, 15), xOfItem(ItemID.STEAM_RUNE, 15), item(ItemID.STAFF_OF_WATER), item(ItemID.WATER_BATTLESTAFF), item(ItemID.MYSTIC_WATER_STAFF), item(ItemID.MUD_BATTLESTAFF), item(ItemID.MYSTIC_MUD_STAFF), item(ItemID.MIST_BATTLESTAFF), item(ItemID.MYSTIC_MIST_STAFF), item(ItemID.STEAM_BATTLESTAFF), item(ItemID.MYSTIC_STEAM_STAFF), item(ItemID.STEAM_BATTLESTAFF_12795), item(ItemID.MYSTIC_STEAM_STAFF_12796), item(ItemID.KODAI_WAND), item(ItemID.TOME_OF_WATER)), any("Earth Rune x15", xOfItem(ItemID.EARTH_RUNE, 15), xOfItem(ItemID.DUST_RUNE, 15), xOfItem(ItemID.MUD_RUNE, 15), xOfItem(ItemID.LAVA_RUNE, 15), item(ItemID.STAFF_OF_EARTH), item(ItemID.EARTH_BATTLESTAFF), item(ItemID.MYSTIC_EARTH_STAFF), item(ItemID.MUD_BATTLESTAFF), item(ItemID.MYSTIC_MUD_STAFF), item(ItemID.DUST_BATTLESTAFF), item(ItemID.MYSTIC_DUST_STAFF), item(ItemID.LAVA_BATTLESTAFF), item(ItemID.MYSTIC_LAVA_STAFF), item(ItemID.LAVA_BATTLESTAFF_21198), item(ItemID.MYSTIC_LAVA_STAFF_21200)), any("Unenchanted Dragonstone Jewellery", item(ItemID.DRAGONSTONE_RING), item(ItemID.DRAGON_NECKLACE), item(ItemID.DRAGONSTONE_BRACELET), item(ItemID.DRAGONSTONE_AMULET))), new SkillChallengeClue("Craft a nature rune.", item(ItemID.PURE_ESSENCE)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index b9900a988e..b275fd7d4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -394,9 +394,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks this.gl = glContext.getGL().getGL4(); - final boolean unlockFps = this.config.unlockFps(); - client.setUnlockedFps(unlockFps); - gl.setSwapInterval(unlockFps ? -1 : 0); + setupSyncMode(); if (log.isDebugEnabled()) { @@ -556,18 +554,43 @@ public class GpuPlugin extends Plugin implements DrawCallbacks { if (configChanged.getGroup().equals(GpuPluginConfig.GROUP)) { - if (configChanged.getKey().equals("unlockFps")) + if (configChanged.getKey().equals("unlockFps") + || configChanged.getKey().equals("vsyncMode") + || configChanged.getKey().equals("fpsTarget")) { - boolean unlockFps = Boolean.parseBoolean(configChanged.getNewValue()); - clientThread.invokeLater(() -> - { - client.setUnlockedFps(unlockFps); - invokeOnMainThread(() -> gl.setSwapInterval(unlockFps ? -1 : 0)); - }); + log.debug("Rebuilding sync mode"); + clientThread.invokeLater(() -> invokeOnMainThread(this::setupSyncMode)); } } } + private void setupSyncMode() + { + final boolean unlockFps = config.unlockFps(); + client.setUnlockedFps(unlockFps); + + // Without unlocked fps, the client manages sync on its 20ms timer + GpuPluginConfig.SyncMode syncMode = unlockFps + ? this.config.syncMode() + : GpuPluginConfig.SyncMode.OFF; + + switch (syncMode) + { + case ON: + gl.setSwapInterval(1); + client.setUnlockedFpsTarget(0); + break; + case OFF: + gl.setSwapInterval(0); + client.setUnlockedFpsTarget(config.fpsTarget()); // has no effect with unlockFps=false + break; + case ADAPTIVE: + gl.setSwapInterval(-1); + client.setUnlockedFpsTarget(0); + break; + } + } + private void initProgram() throws ShaderException { String versionHeader = OSType.getOSType() == OSType.Linux ? LINUX_VERSION_HEADER : WINDOWS_VERSION_HEADER; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java index ff69cd80e8..3d5f1095ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java @@ -159,4 +159,37 @@ public interface GpuPluginConfig extends Config { return false; } + + enum SyncMode + { + OFF, + ON, + ADAPTIVE + } + + @ConfigItem( + keyName = "vsyncMode", + name = "Vsync Mode", + description = "Method to synchronize frame rate with refresh rate", + position = 11 + ) + default SyncMode syncMode() + { + return SyncMode.ADAPTIVE; + } + + @ConfigItem( + keyName = "fpsTarget", + name = "FPS Target", + description = "Target FPS when unlock FPS is enabled and Vsync mode is OFF", + position = 12 + ) + @Range( + min = 1, + max = 999 + ) + default int fpsTarget() + { + return 60; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java index 9fb512c688..8fb08840af 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java @@ -78,6 +78,7 @@ public class GroundItemsOverlay extends Overlay private static final Duration DESPAWN_TIME_DROP = Duration.ofMinutes(3); private static final Duration DESPAWN_TIME_TABLE = Duration.ofMinutes(10); private static final int KRAKEN_REGION = 9116; + private static final int CLAN_HALL_REGION = 6997; private static final int KBD_NMZ_REGION = 9033; private static final int ZILYANA_REGION = 11602; private static final int GRAARDOR_REGION = 11347; @@ -456,7 +457,8 @@ public class GroundItemsOverlay extends Overlay } else if (playerRegionID == ZILYANA_REGION || playerRegionID == GRAARDOR_REGION || playerRegionID == KRIL_TSUTSAROTH_REGION || playerRegionID == KREEARRA_REGION || - playerRegionID == NIGHTMARE_REGION || playerRegionID == TEMPOROSS_REGION) + playerRegionID == NIGHTMARE_REGION || playerRegionID == TEMPOROSS_REGION || + playerRegionID == CLAN_HALL_REGION) { // GWD, Nightmare, and Tempoross instances use the normal despawn timers despawnTime = spawnTime.plus(groundItem.getLootType() == LootType.DROPPED diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java index 255f3f9ac1..962e47d413 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java @@ -35,6 +35,7 @@ import net.runelite.api.Point; import net.runelite.api.Varbits; import net.runelite.api.widgets.WidgetItem; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.RunepouchRune; import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.BOTH; import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.MOUSE_HOVER; import net.runelite.client.ui.FontManager; @@ -100,7 +101,7 @@ public class RunepouchOverlay extends WidgetItemOverlay Varbits runeVarbit = RUNE_VARBITS[i]; int runeId = client.getVar(runeVarbit); - Runes rune = Runes.getRune(runeId); + RunepouchRune rune = RunepouchRune.getRune(runeId); if (rune == null) { continue; @@ -149,7 +150,7 @@ public class RunepouchOverlay extends WidgetItemOverlay } } - private BufferedImage getRuneImage(Runes rune) + private BufferedImage getRuneImage(RunepouchRune rune) { BufferedImage runeImg = rune.getImage(); if (runeImg != null) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java index 6c612efff9..b2b78e9a52 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java @@ -72,7 +72,8 @@ public class SpecialCounterPlugin extends Plugin { private static final Set IGNORED_NPCS = ImmutableSet.of( NpcID.DARK_ENERGY_CORE, NpcID.ZOMBIFIED_SPAWN, NpcID.ZOMBIFIED_SPAWN_8063, - NpcID.COMBAT_DUMMY, NpcID.UNDEAD_COMBAT_DUMMY + NpcID.COMBAT_DUMMY, NpcID.UNDEAD_COMBAT_DUMMY, + NpcID.SKELETON_HELLHOUND_6613, NpcID.GREATER_SKELETON_HELLHOUND ); private static final Set RESET_ON_LEAVE_INSTANCED_REGIONS = ImmutableSet.of( diff --git a/runelite-client/src/main/scripts/BankSearchFilter.rs2asm b/runelite-client/src/main/scripts/BankSearchFilter.rs2asm index 0555737bdb..0c809b35e3 100644 --- a/runelite-client/src/main/scripts/BankSearchFilter.rs2asm +++ b/runelite-client/src/main/scripts/BankSearchFilter.rs2asm @@ -1,4 +1,4 @@ -.id 279 +.id 279 ; [proc,bankmain_filteritem] .int_stack_count 1 .string_stack_count 0 .int_var_count 2 ; +1 for storage of search filter result diff --git a/runelite-client/src/main/scripts/BankSearchLayout.rs2asm b/runelite-client/src/main/scripts/BankSearchLayout.rs2asm index f67c6a9bfe..ea13a99a47 100644 --- a/runelite-client/src/main/scripts/BankSearchLayout.rs2asm +++ b/runelite-client/src/main/scripts/BankSearchLayout.rs2asm @@ -1,4 +1,4 @@ -.id 277 +.id 277 ; [proc,bankmain_build] .int_stack_count 17 .string_stack_count 0 .int_var_count 36 @@ -7,8 +7,8 @@ ; Fired before the bank starts its layout ; Used by the TabInterface to hide fake bank items for tag tabs ; -; callback "setBankScroll" -; Fired before bank is calculated +; callback "skipBankLayout" +; Fired before bank is built ; Used by the TabInterface to show fake bank items for tag tabs sconst "beforeBankLayout" runelite_callback @@ -403,13 +403,11 @@ LABEL348: sub istore 30 LABEL352: - iconst 0 ; Scroll height variable iconst 0 ; Compare variable iconst 0 ; - sconst "setBankScroll" ; Show fake bank items for tag tabs + sconst "skipBankLayout" ; Show fake bank items for tag tabs runelite_callback ; If tag tab menu search isn't active if_icmpeq CONTINUE_SEARCH ; continue to normal bank search - istore 27 ; Load scroll height into variable jump GetTabRange ; Skip normal bank layout CONTINUE_SEARCH: iload 31 @@ -842,7 +840,7 @@ LABEL729: iload 14 iload 15 iload 16 - invoke 505 + invoke 505 ; [proc,bankmain_finishbuilding] return LABEL750: invoke 514 diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java index 501787576a..b93f3b1078 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java @@ -186,6 +186,36 @@ public class ChatFilterPluginTest assertNull(chatFilterPlugin.censorMessage("Blue", "hello\u00A0osrs")); } + @Test + public void testFilterUnicode() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_WORDS); + when(chatFilterConfig.filteredWords()).thenReturn("filterme"); + + chatFilterPlugin.updateFilteredPatterns(); + assertEquals("plëäsë ******** plügïn", chatFilterPlugin.censorMessage("Blue", "plëäsë fïltërmë plügïn")); + } + + @Test + public void testUnicodeFiltersUnicode() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_WORDS); + when(chatFilterConfig.filteredWords()).thenReturn("plëäsë"); + + chatFilterPlugin.updateFilteredPatterns(); + assertEquals("****** fïltërmë plügïn", chatFilterPlugin.censorMessage("Blue", "plëäsë fïltërmë plügïn")); + } + + @Test + public void testMixedUnicodeFiltersUnicode() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_WORDS); + when(chatFilterConfig.filteredWords()).thenReturn("plëäsë, filterme"); + + chatFilterPlugin.updateFilteredPatterns(); + assertEquals("****** ******** plügïn", chatFilterPlugin.censorMessage("Blue", "plëäsë fïltërmë plügïn")); + } + @Test public void testMessageFromFriendIsFiltered() { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java index 668e7fe837..7db5ce3f6e 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java @@ -30,14 +30,22 @@ import com.google.inject.Inject; import com.google.inject.name.Named; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.Arrays; +import java.util.List; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.NullObjectID; import net.runelite.api.Player; +import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; 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.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -45,8 +53,11 @@ import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.banktags.TagManager; import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation; import net.runelite.client.ui.overlay.OverlayManager; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -183,4 +194,40 @@ public class ClueScrollPluginTest plugin.onChatMessage(withdrawMessage); assertNull(plugin.getActiveSTASHClue()); } + + @Test + public void testThatRunepouchIsAddedToInventory() + { + ItemContainer container = mock(ItemContainer.class); + ItemContainerChanged event = new ItemContainerChanged(InventoryID.INVENTORY.getId(), container); + + final Item[] inventory = { + new Item(ItemID.COINS_995, 100), + new Item(ItemID.MITHRIL_BAR, 1), + new Item(ItemID.MITHRIL_BAR, 1), + new Item(ItemID.MITHRIL_BAR, 1), + new Item(ItemID.SOUL_RUNE, 30), + new Item(ItemID.COSMIC_RUNE, 100), + new Item(ItemID.RUNE_POUCH, 1), + new Item(ItemID.SPADE, 1), + new Item(ItemID.CLUE_SCROLL_MASTER, 1) + }; + + when(container.getItems()).thenReturn(inventory); + when(container.contains(ItemID.RUNE_POUCH)).thenReturn(true); + + when(client.getVar(Varbits.RUNE_POUCH_RUNE1)).thenReturn(9); // Cosmic Rune + when(client.getVar(Varbits.RUNE_POUCH_AMOUNT1)).thenReturn(20); + when(client.getVar(Varbits.RUNE_POUCH_RUNE3)).thenReturn(4); // Fire Rune + when(client.getVar(Varbits.RUNE_POUCH_AMOUNT3)).thenReturn(4000); + + plugin.onItemContainerChanged(event); + + assertFalse(Arrays.equals(inventory, plugin.getInventoryItems())); + + List inventoryList = Arrays.asList(plugin.getInventoryItems()); + + assertThat(inventoryList, hasItem(new Item(ItemID.COSMIC_RUNE, 120))); + assertThat(inventoryList, hasItem(new Item(ItemID.FIRE_RUNE, 4000))); + } }