From 7539e7b6404d366196eb8d09ba8d58aab97d4407 Mon Sep 17 00:00:00 2001 From: l2- Date: Fri, 10 Nov 2017 13:46:16 -0500 Subject: [PATCH] runelite-client: recolor chat command messages when chatbox transparency changes Support different colors for transparent chat boxes --- .../java/net/runelite/api/MessageNode.java | 4 + .../main/java/net/runelite/api/Varbits.java | 6 + .../net/runelite/api/widgets/WidgetID.java | 1 + .../net/runelite/api/widgets/WidgetInfo.java | 2 + .../plugins/chatcommands/ChatColor.java | 45 ++++ .../plugins/chatcommands/ChatCommands.java | 252 +++++++++++++----- .../chatcommands/ChatCommandsConfig.java | 100 ++++++- .../runelite/mixins/RSMessageNodeMixin.java | 17 ++ 8 files changed, 359 insertions(+), 68 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java diff --git a/runelite-api/src/main/java/net/runelite/api/MessageNode.java b/runelite-api/src/main/java/net/runelite/api/MessageNode.java index 346757f667..0b9aa00835 100644 --- a/runelite-api/src/main/java/net/runelite/api/MessageNode.java +++ b/runelite-api/src/main/java/net/runelite/api/MessageNode.java @@ -33,4 +33,8 @@ public interface MessageNode String getValue(); void setValue(String value); + + String getRuneLiteFormatMessage(); + + void setRuneLiteFormatMessage(String runeLiteFormatMessage); } diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index 9b1e87c0a4..bd3516893a 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -26,6 +26,12 @@ package net.runelite.api; public enum Varbits { + /* + * If chatbox is transparent or not + */ + TRANSPARANT_CHATBOX(4608, 1055, 9, 9), + SPLIT_CHAT(287, 0, 0), + /** * Runecraft pouches */ diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index d0543c996d..eb28cf242e 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -45,6 +45,7 @@ class WidgetID static final int COMBAT_GROUP_ID = 593; static final int DIALOG_NPC_GROUP_ID = 231; static final int SLAYER_REWARDS_GROUP_ID = 426; + static final int PRIVATE_CHAT = 163; static class SlayerRewards { diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 2313307254..ee173eeb75 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -88,6 +88,8 @@ public enum WidgetInfo DIALOG_NPC_HEAD_MODEL(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.HEAD_MODEL), DIALOG_NPC_CONTINUE(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.CONTINUE), + PRIVATE_CHAT_MESSAGE(WidgetID.PRIVATE_CHAT, 0), + SLAYER_REWARDS_TOPBAR(WidgetID.SLAYER_REWARDS_GROUP_ID, WidgetID.SlayerRewards.TOP_BAR); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java new file mode 100644 index 0000000000..4c95aaa72b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017. l2- + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.chatcommands; + +import java.awt.Color; +import net.runelite.api.ChatMessageType; + +class ChatColor +{ + Color color; + ChatMessageType type; + boolean transparent; + boolean highlight; + + ChatColor(Color color, ChatMessageType type, boolean transparent, boolean highlight) + { + this.color = color; + this.type = type; + this.transparent = transparent; + this.highlight = highlight; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommands.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommands.java index 302fbb496f..ab2d804758 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommands.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommands.java @@ -28,15 +28,23 @@ package net.runelite.client.plugins.chatcommands; import com.google.common.eventbus.Subscribe; import java.awt.Color; import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.concurrent.ScheduledExecutorService; +import java.util.stream.Collectors; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.ItemComposition; import net.runelite.api.MessageNode; +import net.runelite.api.Varbits; import net.runelite.client.RuneLite; import net.runelite.client.events.SetMessage; +import net.runelite.client.events.ResizeableChanged; +import net.runelite.client.events.ConfigChanged; +import net.runelite.client.events.VarbitChanged; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -58,14 +66,17 @@ public class ChatCommands extends Plugin { private static final Logger logger = LoggerFactory.getLogger(ChatCommands.class); + private static final float HIGH_ALCHEMY_CONSTANT = 0.6f; + + private final String colKeyword = ""; + private final String colKeywordHighLight = ""; private final ChatCommandsConfig config = RuneLite.getRunelite().getConfigManager().getConfig(ChatCommandsConfig.class); private final ItemManager itemManager = RuneLite.getRunelite().getItemManager(); private final ItemClient itemClient = new ItemClient(); private final RuneLite runelite = RuneLite.getRunelite(); private final Client client = RuneLite.getClient(); private final HiscoreClient hiscoreClient = new HiscoreClient(); - - private static final float HIGH_ALCHEMY_CONSTANT = 0.6f; + private int transparancyVarbit = -1; @Override protected void startUp() throws Exception @@ -77,6 +88,63 @@ public class ChatCommands extends Plugin { } + /** + * Checks if the chatbox is no longer transparent and if messages need + * to be recolored + * + * @param event the event object + */ + @Subscribe + public void onVarbitChange(VarbitChanged event) + { + if (transparancyVarbit == -1) + { + transparancyVarbit = client.getSetting(Varbits.TRANSPARANT_CHATBOX); + } + else if (transparancyVarbit != client.getSetting(Varbits.TRANSPARANT_CHATBOX)) + { + transparancyVarbit = client.getSetting(Varbits.TRANSPARANT_CHATBOX); + ScheduledExecutorService executor = runelite.getExecutor(); + executor.submit(() -> recolorChat()); + } + } + + @Subscribe + public void onResizableChanged(ResizeableChanged event) + { + ScheduledExecutorService executor = runelite.getExecutor(); + executor.submit(() -> recolorChat()); + } + + /** + * get the MessageNodes that have a runeltie message + * + * @return + */ + private Collection getRuneliteMessages() + { + return client.getChatLineMap().values().stream() + .filter(Objects::nonNull) + .flatMap(clb -> Arrays.stream(clb.getLines())) + .filter(Objects::nonNull) + .filter(mn -> mn.getRuneLiteFormatMessage() != null) + .collect(Collectors.toList()); + } + + /** + * Updates the ingame recolored messages to the new config recolorChat + * cannot color messages without color tags because it won't know what + * to replace. + * + * @param event the event object + */ + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + ScheduledExecutorService executor = runelite.getExecutor(); + executor.submit(() -> recolorChat()); + } + /** * Checks if the chat message is a command. * @@ -102,6 +170,11 @@ public class ChatCommands extends Plugin } String message = setMessage.getValue(); + MessageNode messageNode = setMessage.getMessageNode(); + + // clear runelite formatted messsage as the message node is + // being reused + messageNode.setRuneLiteFormatMessage(null); if (config.lvl() && message.toLowerCase().equals("!total")) { @@ -171,35 +244,27 @@ public class ChatCommands extends Plugin return; } - Color color1 = getColor(type), - color2 = getColorH(type); - - String hexColor1 = "", hexColor2 = ""; - - if (config.recolorEnabled() && color1 != null && color2 != null) - { - hexColor1 = toHexCol(color1); - hexColor2 = toHexCol(color2); - } - StringBuilder builder = new StringBuilder(); - builder.append("").append("Price of ") - .append("").append(item.getName()) - .append("").append(": GE average ") - .append("").append(String.format("%,d", itemPrice.getPrice())); + builder.append(colKeyword).append("Price of ") + .append(colKeywordHighLight).append(item.getName()) + .append(colKeyword).append(": GE average ") + .append(colKeywordHighLight).append(String.format("%,d", itemPrice.getPrice())); ItemComposition itemComposition = client.getItemDefinition(itemId); if (itemComposition != null) { int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT); - builder.append("").append(" HA value ") - .append("").append(String.format("%,d", alchPrice)); + builder.append(colKeyword).append(" HA value ") + .append(colKeywordHighLight).append(String.format("%,d", alchPrice)); } - logger.debug("Setting response {}", builder.toString()); + String response = builder.toString(); + + logger.debug("Setting response {}", response); // XXX hopefully messageNode hasn't been reused yet? - messageNode.setValue(builder.toString()); + messageNode.setRuneLiteFormatMessage(response); + messageNode.setValue(recolorMessage(messageNode.getType(), response)); client.refreshChat(); } } @@ -213,8 +278,15 @@ public class ChatCommands extends Plugin */ private void playerSkillLookup(ChatMessageType type, SetMessage setMessage, String search) { - String player = sanitize(setMessage.getName()); - + String player; + if (type.equals(ChatMessageType.PRIVATE_MESSAGE_SENT)) + { + player = client.getLocalPlayer().getName(); + } + else + { + player = sanitize(setMessage.getName()); + } try { search = SkillAbbreviations.valueOf(search.toUpperCase()).getName(); @@ -238,30 +310,20 @@ public class ChatCommands extends Plugin SingleHiscoreSkillResult result = hiscoreClient.lookup(player, skill); Skill hiscoreSkill = result.getSkill(); - Color color1 = getColor(type), - color2 = getColorH(type); - - String hexColor1 = "", hexColor2 = ""; - - if (config.recolorEnabled() && color1 != null && color2 != null) - { - hexColor1 = toHexCol(color1); - hexColor2 = toHexCol(color2); - } - String response = new StringBuilder() - .append("").append("Level ") - .append("").append(skill.getName()).append(": ").append(hiscoreSkill.getLevel()) - .append("").append(" Experience: ") - .append("").append(String.format("%,d", hiscoreSkill.getExperience())) - .append("").append(" Rank: ") - .append("").append(String.format("%,d", hiscoreSkill.getRank())) + .append(colKeyword).append("Level ") + .append(colKeywordHighLight).append(skill.getName()).append(": ").append(hiscoreSkill.getLevel()) + .append(colKeyword).append(" Experience: ") + .append(colKeywordHighLight).append(String.format("%,d", hiscoreSkill.getExperience())) + .append(colKeyword).append(" Rank: ") + .append(colKeywordHighLight).append(String.format("%,d", hiscoreSkill.getRank())) .toString(); logger.debug("Setting response {}", response); // XXX hopefully messageNode hasn't been reused yet? - setMessage.getMessageNode().setValue(response); + setMessage.getMessageNode().setRuneLiteFormatMessage(response); + setMessage.getMessageNode().setValue(recolorMessage(setMessage.getType(), response)); client.refreshChat(); } catch (IOException ex) @@ -291,40 +353,106 @@ public class ChatCommands extends Plugin return null; } - private Color getColor(ChatMessageType type) + private ChatColor getChatColor(ChatMessageType type) { - switch (type) + if ((type == ChatMessageType.PRIVATE_MESSAGE_SENT || type == ChatMessageType.PRIVATE_MESSAGE_RECEIVED) && !config.isPrivateRecolor()) { - case PUBLIC: - return config.getPublicRecolor(); - case CLANCHAT: - return config.getCcRecolor(); - case PRIVATE_MESSAGE_RECEIVED: - case PRIVATE_MESSAGE_SENT: - return config.getPrivateRecolor(); + return null; + } + if (client.getSetting(Varbits.TRANSPARANT_CHATBOX) == 0 || !client.isResized() || !config.transparancyRecolor()) + { + switch (type) + { + case PUBLIC: + return new ChatColor(config.getPublicRecolor(), type, false, false); + case PRIVATE_MESSAGE_RECEIVED: + case PRIVATE_MESSAGE_SENT: + return new ChatColor(config.getPrivateRecolor(), type, false, false); + case CLANCHAT: + return new ChatColor(config.getCcRecolor(), type, false, false); + } + } + else + { + switch (type) + { + case PUBLIC: + return new ChatColor(config.getTransparentPublicRecolor(), type, true, false); + case PRIVATE_MESSAGE_RECEIVED: + case PRIVATE_MESSAGE_SENT: + return new ChatColor(config.getTransparentPrivateRecolor(), type, true, false); + case CLANCHAT: + return new ChatColor(config.getTransparentCcRecolor(), type, true, false); + } } return null; } - private Color getColorH(ChatMessageType type) + private ChatColor getChatColorH(ChatMessageType type) { - switch (type) + if ((type == ChatMessageType.PRIVATE_MESSAGE_SENT || type == ChatMessageType.PRIVATE_MESSAGE_RECEIVED) && !config.isPrivateRecolor()) { - case PUBLIC: - return config.getPublicHRecolor(); - case CLANCHAT: - return config.getCcHRecolor(); - case PRIVATE_MESSAGE_RECEIVED: - case PRIVATE_MESSAGE_SENT: - return config.getPrivateHRecolor(); + return null; + } + if (client.getSetting(Varbits.TRANSPARANT_CHATBOX) == 0 || !client.isResized() || !config.transparancyRecolor()) + { + switch (type) + { + case PUBLIC: + return new ChatColor(config.getPublicHRecolor(), type, false, true); + case PRIVATE_MESSAGE_RECEIVED: + case PRIVATE_MESSAGE_SENT: + return new ChatColor(config.getPrivateHRecolor(), type, false, true); + case CLANCHAT: + return new ChatColor(config.getCcHRecolor(), type, false, true); + } + } + else + { + switch (type) + { + case PUBLIC: + return new ChatColor(config.getTransparentPublicHRecolor(), type, true, true); + case PRIVATE_MESSAGE_RECEIVED: + case PRIVATE_MESSAGE_SENT: + return new ChatColor(config.getTransparentPrivateHRecolor(), type, true, true); + case CLANCHAT: + return new ChatColor(config.getTransparentCcHRecolor(), type, true, true); + } } return null; } - private static String toHexCol(Color color) + private String recolorMessage(ChatMessageType type, String value) { - // doesn't support alpha - return color == null ? "" : Integer.toHexString(color.getRGB() & 0xFFFFFF); + ChatColor chatcolor = getChatColor(type); + ChatColor chatColorH = getChatColorH(type); + if (config.recolorEnabled() && chatcolor != null && chatColorH != null) + { + value = value.replace(colKeyword, getColTag(chatcolor.color)) + .replace(colKeywordHighLight, getColTag(chatColorH.color)); + } + else + { + value = value.replace(colKeyword, "") + .replace(colKeywordHighLight, ""); + } + return value; + } + + private void recolorChat() + { + Collection nodes = getRuneliteMessages(); + for (MessageNode message : nodes) + { + message.setValue(recolorMessage(message.getType(), message.getRuneLiteFormatMessage())); + } + client.refreshChat(); + } + + public static String getColTag(Color color) + { + return color == null ? "" : ""; } /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java index 1168559dc3..59517fc97b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java @@ -70,6 +70,17 @@ public interface ChatCommandsConfig @ConfigItem( position = 3, + keyName = "enablePrivateRecolor", + name = "enable private recolor", + description = "enable private recolor" + ) + default boolean isPrivateRecolor() + { + return false; + } + + @ConfigItem( + position = 4, keyName = "hexColorPublic", name = "Public chat", description = "Color of Public chat" @@ -80,7 +91,7 @@ public interface ChatCommandsConfig } @ConfigItem( - position = 4, + position = 5, keyName = "hexColorPublicH", name = "Public chat highlight", description = "Color of Public chat highlight" @@ -91,7 +102,7 @@ public interface ChatCommandsConfig } @ConfigItem( - position = 5, + position = 6, keyName = "hexColorPrivate", name = "Private chat", description = "Color of Private chat" @@ -102,7 +113,7 @@ public interface ChatCommandsConfig } @ConfigItem( - position = 6, + position = 7, keyName = "hexColorPrivateH", name = "Private chat highlight", description = "Color of Private chat highlight" @@ -113,18 +124,18 @@ public interface ChatCommandsConfig } @ConfigItem( - position = 7, + position = 8, keyName = "hexColorCc", name = "Clan chat", description = "Color of Clan chat" ) default Color getCcRecolor() { - return Color.decode("#900000"); + return Color.decode("#7f0000"); } @ConfigItem( - position = 8, + position = 9, keyName = "hexColorCcH", name = "Clan chat Highlight", description = "Color of Clan chat highlight" @@ -133,4 +144,81 @@ public interface ChatCommandsConfig { return Color.decode("#000000"); } + + @ConfigItem( + position = 10, + keyName = "transparancyRecolor", + name = "Different colors for transparent chatbox", + description = "Configures whether colors are different for transparent chatbox" + ) + default boolean transparancyRecolor() + { + return true; + } + + @ConfigItem( + position = 11, + keyName = "transparentHexColorPublic", + name = "Transparent public chat", + description = "Color of Public chat" + ) + default Color getTransparentPublicRecolor() + { + return Color.decode("#9090FF"); + } + + @ConfigItem( + position = 12, + keyName = "transparentHexColorPublicH", + name = "Transparent public chat highlight", + description = "Color of Public chat highlight" + ) + default Color getTransparentPublicHRecolor() + { + return Color.decode("#FFFFFF"); + } + + @ConfigItem( + position = 13, + keyName = "transparentHexColorPrivate", + name = "Transparent private chat", + description = "Color of Private chat" + ) + default Color getTransparentPrivateRecolor() + { + return Color.decode("#FFFFFF"); + } + + @ConfigItem( + position = 14, + keyName = "transparentHexColorPrivateH", + name = "Transparent private chat highlight", + description = "Color of Private chat highlight" + ) + default Color getTransparentPrivateHRecolor() + { + return Color.decode("#00FFFF"); + } + + @ConfigItem( + position = 15, + keyName = "transparentHexColorCc", + name = "Transparent clan chat", + description = "Color of Clan chat" + ) + default Color getTransparentCcRecolor() + { + return Color.decode("#Ef5050"); + } + + @ConfigItem( + position = 16, + keyName = "transparentHexColorCcH", + name = "Transparent clan chat Highlight", + description = "Color of Clan chat highlight" + ) + default Color getTransparentCcHRecolor() + { + return Color.decode("#FFFFFF"); + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSMessageNodeMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSMessageNodeMixin.java index cee32848e7..0a6eff03dc 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSMessageNodeMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSMessageNodeMixin.java @@ -32,10 +32,27 @@ import net.runelite.rs.api.RSMessageNode; @Mixin(RSMessageNode.class) public abstract class RSMessageNodeMixin implements RSMessageNode { + @Inject + private String runeLiteFormatMessage; + @Inject @Override public ChatMessageType getType() { return ChatMessageType.of(getRSType()); } + + @Inject + @Override + public String getRuneLiteFormatMessage() + { + return runeLiteFormatMessage; + } + + @Inject + @Override + public void setRuneLiteFormatMessage(String runeLiteFormatMessage) + { + this.runeLiteFormatMessage = runeLiteFormatMessage; + } }