From 8fb47dd54e54ccc184324868706c4c8e32bb0ba4 Mon Sep 17 00:00:00 2001 From: ThatGamerBlue Date: Tue, 10 Sep 2019 19:03:14 +0100 Subject: [PATCH] npchider: change method by which npcs are hidden by name (#1573) * npchider: change method by which npcs are hidden by name * fix bug on client startup/shutdown where nothing gets hidden * entityhider: change method by which npcs are hidden on death --- .../main/java/net/runelite/api/Client.java | 40 ++++++++-- .../entityhider/EntityHiderPlugin.java | 39 ++++++++- .../mixins/EntityHiderBridgeMixin.java | 75 ++++++++++++++++-- .../net/runelite/mixins/EntityHiderMixin.java | 79 +++++-------------- 4 files changed, 157 insertions(+), 76 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 922e39c42f..b7a0492384 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1464,18 +1464,46 @@ public interface Client extends GameShell void setNPCsHidden(boolean state); /** - * Sets which NPCs are hidden + * Increments the counter for how many times this npc has been selected to be hidden * - * @param names the names of the npcs + * @param name npc name */ - void setNPCsNames(List names); + void addHiddenNpcName(String name); /** - * Sets which NPCs are hidden on death + * Decrements the counter for how many times this npc has been selected to be hidden * - * @param names the names of the npcs + * @param name npc name */ - void setNPCsHiddenOnDeath(List names); + void removeHiddenNpcName(String name); + + /** + * Forcibly unhides an npc by setting its counter to zero + * + * @param name npc name + */ + void forciblyUnhideNpcName(String name); + + /** + * Increments the counter for how many times this npc has been selected to be hidden on death + * + * @param name npc name + */ + void addHiddenNpcDeath(String name); + + /** + * Decrements the counter for how many times this npc has been selected to be hidden on death + * + * @param name npc name + */ + void removeHiddenNpcDeath(String name); + + /** + * Forcibly unhides a hidden-while-dead npc by setting its counter to zero + * + * @param name npc name + */ + void forciblyUnhideNpcDeath(String name); /** * Sets whether 2D sprites (ie. overhead prayers) related to diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java index 8eaebc94fe..ef97f51e82 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Lotto + * Copyright (c) 2019, ThatGamerBlue * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,6 +41,10 @@ import net.runelite.client.eventbus.EventBus; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + @PluginDescriptor( name = "Entity Hider", description = "Hide players, NPCs, and/or projectiles", @@ -69,6 +74,9 @@ public class EntityHiderPlugin extends Plugin { updateConfig(); addSubscriptions(); + + Text.fromCSV(config.hideNPCsNames()).forEach(client::addHiddenNpcName); + Text.fromCSV(config.hideNPCsOnDeath()).forEach(client::addHiddenNpcDeath); } private void addSubscriptions() @@ -82,6 +90,30 @@ public class EntityHiderPlugin extends Plugin if (event.getGroup().equals("entityhider")) { updateConfig(); + + if (event.getKey().equals("hideNPCsNames")) + { + List oldList = Text.fromCSV(event.getOldValue()); + List newList = Text.fromCSV(event.getNewValue()); + + ArrayList removed = oldList.stream().filter(s -> !newList.contains(s)).collect(Collectors.toCollection(ArrayList::new)); + ArrayList added = newList.stream().filter(s -> !oldList.contains(s)).collect(Collectors.toCollection(ArrayList::new)); + + removed.forEach(client::removeHiddenNpcName); + added.forEach(client::addHiddenNpcName); + } + + if (event.getKey().equals("hideNPCsOnDeath")) + { + List oldList = Text.fromCSV(event.getOldValue()); + List newList = Text.fromCSV(event.getNewValue()); + + ArrayList removed = oldList.stream().filter(s -> !newList.contains(s)).collect(Collectors.toCollection(ArrayList::new)); + ArrayList added = newList.stream().filter(s -> !oldList.contains(s)).collect(Collectors.toCollection(ArrayList::new)); + + removed.forEach(client::removeHiddenNpcDeath); + added.forEach(client::addHiddenNpcDeath); + } } } @@ -109,8 +141,8 @@ public class EntityHiderPlugin extends Plugin client.setNPCsHidden(config.hideNPCs()); client.setNPCsHidden2D(config.hideNPCs2D()); - client.setNPCsNames(Text.fromCSV(config.hideNPCsNames())); - client.setNPCsHiddenOnDeath(Text.fromCSV(config.hideNPCsOnDeath())); + //client.setNPCsNames(Text.fromCSV(config.hideNPCsNames())); + //client.setNPCsHiddenOnDeath(Text.fromCSV(config.hideNPCsOnDeath())); client.setAttackersHidden(config.hideAttackers()); @@ -143,6 +175,9 @@ public class EntityHiderPlugin extends Plugin client.setProjectilesHidden(false); client.setDeadNPCsHidden(false); + + Text.fromCSV(config.hideNPCsNames()).forEach(client::removeHiddenNpcName); + Text.fromCSV(config.hideNPCsOnDeath()).forEach(client::removeHiddenNpcDeath); } private boolean isPlayerRegionAllowed() diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java index 53fd640c46..f7f78593cc 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Lotto + * Copyright (c) 2019, ThatGamerBlue * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,6 +25,8 @@ */ package net.runelite.mixins; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; @@ -69,13 +72,13 @@ public abstract class EntityHiderBridgeMixin implements RSClient public static boolean hideDeadNPCs; @Inject - public static List hideNPCsNames; + public static HashMap hiddenNpcsName = new HashMap<>(); @Inject - public static List hideNPCsOnDeath; + public static HashMap hiddenNpcsDeath = new HashMap<>(); @Inject - public static List hideSpecificPlayers; + public static List hideSpecificPlayers = new ArrayList<>(); @Inject @Override @@ -142,16 +145,74 @@ public abstract class EntityHiderBridgeMixin implements RSClient @Inject @Override - public void setNPCsNames(List NPCs) + public void addHiddenNpcName(String npc) { - hideNPCsNames = NPCs; + npc = npc.toLowerCase(); + int i = hiddenNpcsName.getOrDefault(npc, 0); + if (i == Integer.MAX_VALUE) + { + throw new RuntimeException("NPC name " + npc + " has been hidden Integer.MAX_VALUE times, is something wrong?"); + } + + hiddenNpcsName.put(npc, ++i); } @Inject @Override - public void setNPCsHiddenOnDeath(List NPCs) + public void removeHiddenNpcName(String npc) { - hideNPCsOnDeath = NPCs; + npc = npc.toLowerCase(); + int i = hiddenNpcsName.getOrDefault(npc, 0); + if (i == 0) + { + return; + } + + hiddenNpcsName.put(npc, --i); + } + + @Inject + @Override + public void forciblyUnhideNpcName(String npc) + { + npc = npc.toLowerCase(); + hiddenNpcsName.put(npc, 0); + } + + @Inject + @Override + public void addHiddenNpcDeath(String npc) + { + npc = npc.toLowerCase(); + int i = hiddenNpcsDeath.getOrDefault(npc, 0); + if (i == Integer.MAX_VALUE) + { + throw new RuntimeException("NPC death " + npc + " has been hidden Integer.MAX_VALUE times, is something wrong?"); + } + + hiddenNpcsDeath.put(npc, ++i); + } + + @Inject + @Override + public void removeHiddenNpcDeath(String npc) + { + npc = npc.toLowerCase(); + int i = hiddenNpcsDeath.getOrDefault(npc, 0); + if (i == 0) + { + return; + } + + hiddenNpcsDeath.put(npc, --i); + } + + @Inject + @Override + public void forciblyUnhideNpcDeath(String npc) + { + npc = npc.toLowerCase(); + hiddenNpcsDeath.put(npc, 0); } @Inject diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java index 900d4c7e4d..61eae9c6e1 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Lotto + * Copyright (c) 2019, ThatGamerBlue * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,9 +25,6 @@ */ package net.runelite.mixins; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; @@ -41,15 +39,12 @@ import net.runelite.rs.api.RSPlayer; import net.runelite.rs.api.RSProjectile; import net.runelite.rs.api.RSScene; +import java.util.HashMap; +import java.util.List; + @Mixin(RSScene.class) public abstract class EntityHiderMixin implements RSScene { - @Inject - private static final Pattern WILDCARD_PATTERN = Pattern.compile("(?i)[^*]+|(\\*)"); - - @Inject - private static final Pattern TAG_REGEXP = Pattern.compile("<[^>]*>"); - @Shadow("client") private static RSClient client; @@ -77,11 +72,11 @@ public abstract class EntityHiderMixin implements RSScene @Shadow("hideNPCs") private static boolean hideNPCs; - @Shadow("hideNPCsNames") - private static List hideNPCsNames; + @Shadow("hiddenNpcsName") + private static HashMap hiddenNpcsName; - @Shadow("hideNPCsOnDeath") - private static List hideNPCsOnDeath; + @Shadow("hiddenNpcsDeath") + private static HashMap hiddenNpcsDeath; @Shadow("hideSpecificPlayers") private static List hideSpecificPlayers; @@ -117,7 +112,8 @@ public abstract class EntityHiderMixin implements RSScene client.getOccupiedTilesTick()[tileX][tileY] = -1; } - return shouldDraw && addEntityMarker(var1, var2, var3, var4, var5, x, y, var8, entity, var10, var11, var12, var13); + return shouldDraw && + addEntityMarker(var1, var2, var3, var4, var5, x, y, var8, entity, var10, var11, var12, var13); } @Copy("drawActor2d") @@ -177,7 +173,8 @@ public abstract class EntityHiderMixin implements RSScene return false; } - return (!hideFriends && player.isFriend()) || (!isLocalPlayer && !hideClanMates && player.isClanMember()); + return (!hideFriends && player.isFriend()) || + (!isLocalPlayer && !hideClanMates && player.isClanMember()); } } else if (entity instanceof RSNPC) @@ -197,26 +194,16 @@ public abstract class EntityHiderMixin implements RSScene return false; } - for (String name : hideNPCsNames) + if (npc.getName() != null && + hiddenNpcsName.getOrDefault(Text.standardize(npc.getName().toLowerCase()), 0) > 0) { - if (name != null && !name.equals("")) - { - if (npc.getName() != null && matches(name, npc.getName())) - { - return false; - } - } + return false; } - for (String name : hideNPCsOnDeath) + if (npc.getName() != null && npc.getHealthRatio() == 0 && + hiddenNpcsDeath.getOrDefault(Text.standardize(npc.getName().toLowerCase()), 0) > 0) { - if (name != null && !name.equals("")) - { - if (npc.getName() != null && matches(name, npc.getName()) && npc.getHealthRatio() == 0) - { - return false; - } - } + return false; } return drawingUI ? !hideNPCs2D : !hideNPCs; @@ -228,34 +215,4 @@ public abstract class EntityHiderMixin implements RSScene return true; } - - @Inject - static private boolean matches(String pattern, String text) - { - String standardized = TAG_REGEXP.matcher(text) - .replaceAll("") - .replace('\u00A0', ' ') - .toLowerCase(); - - final Matcher matcher = WILDCARD_PATTERN.matcher(pattern.toLowerCase()); - final StringBuffer buffer = new StringBuffer(); - - buffer.append("(?i)"); - while (matcher.find()) - { - if (matcher.group(1) != null) - { - matcher.appendReplacement(buffer, ".*"); - } - else - { - matcher.appendReplacement(buffer, "\\\\Q" + matcher.group(0) + "\\\\E"); - } - } - - matcher.appendTail(buffer); - final String replaced = buffer.toString(); - - return standardized.matches(replaced); - } }