From 4860eb871fa0e24dcc1b35775bf6e91d0d39c07c Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Wed, 6 Dec 2017 14:53:45 +0100 Subject: [PATCH] Add chat message recolouring API - Update api of SendMessage to also include message type - Create API for updating chat message based on saved colors for normal and highlighted message and for adding game messages that can be recolored too - Update chat commands plugin to use the new API - Add option to globally disable recoloring to RuneliteConfig Signed-off-by: Tomas Slusny --- .../net/runelite/api/ChatMessageType.java | 6 + .../main/java/net/runelite/api/Client.java | 2 +- .../java/net/runelite/client/RuneLite.java | 5 + .../net/runelite/client/RuneliteModule.java | 2 + .../chatcommands => chat}/ChatColor.java | 29 +- .../runelite/client/chat/ChatColorType.java | 31 +++ .../client/chat/ChatMessageBuilder.java | 47 ++++ .../client/chat/ChatMessageManager.java | 163 +++++++++++ .../client/config/RuneliteConfig.java | 10 + .../chatcommands/ChatCommandsConfig.java | 55 +--- .../chatcommands/ChatCommandsPlugin.java | 258 ++++++------------ .../volcanicmine/VolcanicMinePlugin.java | 3 +- .../net/runelite/mixins/RSClientMixin.java | 5 +- .../src/main/java/ExamplePlugin.java | 5 +- 14 files changed, 373 insertions(+), 248 deletions(-) rename runelite-client/src/main/java/net/runelite/client/{plugins/chatcommands => chat}/ChatColor.java (74%) create mode 100644 runelite-client/src/main/java/net/runelite/client/chat/ChatColorType.java create mode 100644 runelite-client/src/main/java/net/runelite/client/chat/ChatMessageBuilder.java create mode 100644 runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java diff --git a/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java b/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java index 9ea4471dce..e1e2f46e19 100644 --- a/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java +++ b/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java @@ -42,6 +42,7 @@ public enum ChatMessageType FRIENDS_LIST_ADD(30), IGNORE_LIST_ADD(31), AUTOCHAT(90), + GAME(99), TRADE(101), DUEL(103), FILTERED(105), @@ -66,4 +67,9 @@ public enum ChatMessageType } return UNKNOWN; } + + public int getType() + { + return type; + } } 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 2461fa5507..b59ab26d79 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -40,7 +40,7 @@ public interface Client int getRealSkillLevel(Skill skill); - void sendGameMessage(String message); + void sendGameMessage(ChatMessageType type, String message); GameState getGameState(); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 3fce666eb2..8386bcd770 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -58,6 +58,7 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.Query; import net.runelite.client.account.AccountSession; +import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.events.SessionClose; import net.runelite.client.events.SessionOpen; @@ -101,6 +102,9 @@ public class RuneLite @Inject private ConfigManager configManager; + @Inject + private ChatMessageManager chatMessageManager; + @Inject private ScheduledExecutorService executor; @@ -166,6 +170,7 @@ public class RuneLite configManager.load(); eventBus.register(menuManager); + eventBus.register(chatMessageManager); // Setup the notifier notifier = new Notifier(trayIcon); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java index d897c281a5..8da6c16c3f 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java @@ -33,6 +33,7 @@ import java.util.concurrent.ScheduledExecutorService; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.config.RuneliteConfig; import net.runelite.client.game.ItemManager; @@ -50,6 +51,7 @@ public class RuneliteModule extends AbstractModule { bind(ScheduledExecutorService.class).toInstance(Executors.newSingleThreadScheduledExecutor()); bind(MenuManager.class); + bind(ChatMessageManager.class); bind(ItemManager.class); bind(InfoBoxManager.class); bind(Scheduler.class); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatColor.java similarity index 74% rename from runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java rename to runelite-client/src/main/java/net/runelite/client/chat/ChatColor.java index 4c95aaa72b..c47266b65b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatColor.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatColor.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2017. l2- - * Copyright (c) 2017, Adam + * Copyright (c) 2017, Tomas Slusny * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,23 +22,19 @@ * (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; +package net.runelite.client.chat; import java.awt.Color; -import net.runelite.api.ChatMessageType; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; -class ChatColor +@Data +@AllArgsConstructor +@EqualsAndHashCode(exclude = "color") +public 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; - } + private ChatColorType type; + private Color color; + private boolean transparent; } diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatColorType.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatColorType.java new file mode 100644 index 0000000000..1066bd68d7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatColorType.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Tomas Slusny + * 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.chat; + +public enum ChatColorType +{ + NORMAL, + HIGHLIGHT +} diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageBuilder.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageBuilder.java new file mode 100644 index 0000000000..0a1ca887ce --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageBuilder.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017, Tomas Slusny + * 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.chat; + +public class ChatMessageBuilder +{ + private final StringBuilder builder = new StringBuilder(); + + public ChatMessageBuilder append(final ChatColorType type) + { + builder.append(""); + return this; + } + + public ChatMessageBuilder append(final String message) + { + builder.append(message); + return this; + } + + public String build() + { + return builder.toString(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java new file mode 100644 index 0000000000..dc0eda1628 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017, Tomas Slusny + * 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.chat; + +import com.google.common.eventbus.Subscribe; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatLineBuffer; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.MessageNode; +import net.runelite.api.Varbits; +import net.runelite.client.config.RuneliteConfig; +import net.runelite.client.events.ResizeableChanged; +import net.runelite.client.events.VarbitChanged; + +@Slf4j +@Singleton +public class ChatMessageManager +{ + private final Map> colorCache = new HashMap<>(); + private final Provider clientProvider; + private final ScheduledExecutorService executor; + private final RuneliteConfig config; + private int transparancyVarbit = -1; + + @Inject + public ChatMessageManager(Provider clientProvider, ScheduledExecutorService executor, RuneliteConfig config) + { + this.clientProvider = clientProvider; + this.executor = executor; + this.config = config; + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + int setting = clientProvider.get().getSetting(Varbits.TRANSPARANT_CHATBOX); + + if (transparancyVarbit != setting) + { + transparancyVarbit = setting; + refreshAll(); + } + } + + @Subscribe + public void onResizableChanged(ResizeableChanged event) + { + refreshAll(); + } + + public ChatMessageManager cacheColor(final ChatColor chatColor, final ChatMessageType... types) + { + for (ChatMessageType chatMessageType : types) + { + colorCache.putIfAbsent(chatMessageType, new HashSet<>()); + final Set chatColors = colorCache.get(chatMessageType); + chatColors.remove(chatColor); + chatColors.add(chatColor); + } + + return this; + } + + public void add(final ChatMessageType type, final String mesage) + { + final Client client = clientProvider.get(); + client.sendGameMessage(type, mesage); + final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(type.getType()); + final MessageNode[] lines = chatLineBuffer.getLines(); + final MessageNode line = lines[0]; + update(line.getType(), mesage, line); + } + + public void update(final ChatMessageType type, final String message, final MessageNode target) + { + final Client client = clientProvider.get(); + final Set chatColors = colorCache.get(type); + + // If we do not have any colors cached or recoloring is disabled, simply set message + if (!config.chatCommandsRecolorEnabled() || chatColors == null || chatColors.isEmpty()) + { + target.setRuneLiteFormatMessage(message); + target.setValue(message); + return; + } + + final AtomicReference resultMessage = new AtomicReference<>(message); + + // Replace custom formatting with actual colors + chatColors.stream() + .filter(chatColor -> chatColor.isTransparent() == + (client.isResized() && client.getSetting(Varbits.TRANSPARANT_CHATBOX) != 0)) + .forEach(chatColor -> + resultMessage.getAndUpdate(oldMessage -> oldMessage.replaceAll( + "", + ""))); + + target.setRuneLiteFormatMessage(message); + target.setValue(resultMessage.get()); + } + + public void refreshAll() + { + if (!config.chatCommandsRecolorEnabled()) + { + return; + } + + final Client client = clientProvider.get(); + + executor.submit(() -> + { + final Set chatLines = client.getChatLineMap().values().stream() + .filter(Objects::nonNull) + .flatMap(clb -> Arrays.stream(clb.getLines())) + .filter(Objects::nonNull) + .filter(mn -> mn.getRuneLiteFormatMessage() != null) + .collect(Collectors.toSet()); + + chatLines.forEach(chatLine -> update(chatLine.getType(), chatLine.getRuneLiteFormatMessage(), chatLine)); + + if (!chatLines.isEmpty()) + { + client.refreshChat(); + } + }); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneliteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneliteConfig.java index e05cd77731..4d59f847f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneliteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneliteConfig.java @@ -41,6 +41,16 @@ public interface RuneliteConfig extends Config return false; } + @ConfigItem( + keyName = "chatCommandsRecolorEnabled", + name = "Enable chat commands recolor", + description = "Determines if recoloring of custom RuneLite chat commands is enabled" + ) + default boolean chatCommandsRecolorEnabled() + { + return true; + } + @ConfigItem( keyName = "enablePlugins", name = "Enable loading of external plugins", 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 2170224268..089acbe8db 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 @@ -60,28 +60,6 @@ public interface ChatCommandsConfig extends Config @ConfigItem( position = 2, - keyName = "enableRecolor", - name = "Enable command recolor", - description = "Configures whether chat commands are recolored" - ) - default boolean recolorEnabled() - { - return true; - } - - @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" @@ -92,7 +70,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 5, + position = 3, keyName = "hexColorPublicH", name = "Public chat highlight", description = "Color of Public chat highlight" @@ -103,7 +81,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 6, + position = 4, keyName = "hexColorPrivate", name = "Private chat", description = "Color of Private chat" @@ -114,7 +92,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 7, + position = 5, keyName = "hexColorPrivateH", name = "Private chat highlight", description = "Color of Private chat highlight" @@ -125,7 +103,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 8, + position = 6, keyName = "hexColorCc", name = "Clan chat", description = "Color of Clan chat" @@ -136,7 +114,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 9, + position = 7, keyName = "hexColorCcH", name = "Clan chat Highlight", description = "Color of Clan chat highlight" @@ -147,18 +125,7 @@ public interface ChatCommandsConfig extends Config } @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, + position = 8, keyName = "transparentHexColorPublic", name = "Transparent public chat", description = "Color of Public chat" @@ -169,7 +136,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 12, + position = 9, keyName = "transparentHexColorPublicH", name = "Transparent public chat highlight", description = "Color of Public chat highlight" @@ -180,7 +147,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 13, + position = 10, keyName = "transparentHexColorPrivate", name = "Transparent private chat", description = "Color of Private chat" @@ -191,7 +158,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 14, + position = 11, keyName = "transparentHexColorPrivateH", name = "Transparent private chat highlight", description = "Color of Private chat highlight" @@ -202,7 +169,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 15, + position = 12, keyName = "transparentHexColorCc", name = "Transparent clan chat", description = "Color of Clan chat" @@ -213,7 +180,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 16, + position = 13, keyName = "transparentHexColorCcH", name = "Transparent clan chat Highlight", description = "Color of Clan chat highlight" diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index af09ef7a28..1df341b824 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -27,15 +27,10 @@ package net.runelite.client.plugins.chatcommands; import com.google.common.eventbus.Subscribe; import com.google.inject.Provides; -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.ExecutionException; import java.util.concurrent.ScheduledExecutorService; -import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; @@ -44,12 +39,14 @@ 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.chat.ChatColor; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.events.ConfigChanged; -import net.runelite.client.events.ResizeableChanged; +import net.runelite.client.events.GameStateChanged; import net.runelite.client.events.SetMessage; -import net.runelite.client.events.VarbitChanged; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -69,10 +66,7 @@ public class ChatCommandsPlugin extends Plugin { private static final float HIGH_ALCHEMY_CONSTANT = 0.6f; - private final String colKeyword = ""; - private final String colKeywordHighLight = ""; private final HiscoreClient hiscoreClient = new HiscoreClient(); - private int transparancyVarbit = -1; @Inject @Nullable @@ -84,6 +78,9 @@ public class ChatCommandsPlugin extends Plugin @Inject ItemManager itemManager; + @Inject + ChatMessageManager chatMessageManager; + @Inject ScheduledExecutorService executor; @@ -93,58 +90,52 @@ public class ChatCommandsPlugin extends Plugin return configManager.getConfig(ChatCommandsConfig.class); } - /** - * 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) + public void onGameStateChange(GameStateChanged event) { - if (transparancyVarbit == -1) + if (event.getGameState().equals(GameState.LOGIN_SCREEN)) { - transparancyVarbit = client.getSetting(Varbits.TRANSPARANT_CHATBOX); - } - else if (transparancyVarbit != client.getSetting(Varbits.TRANSPARANT_CHATBOX)) - { - transparancyVarbit = client.getSetting(Varbits.TRANSPARANT_CHATBOX); - executor.submit(() -> recolorChat()); + cacheConfiguredColors(); } } - @Subscribe - public void onResizableChanged(ResizeableChanged event) - { - 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) { - executor.submit(() -> recolorChat()); + if (event.getGroup().equals("chatcommands")) + { + cacheConfiguredColors(); + chatMessageManager.refreshAll(); + } + } + + private void cacheConfiguredColors() + { + chatMessageManager + .cacheColor(new ChatColor(ChatColorType.NORMAL, config.getPublicRecolor(), false), + ChatMessageType.PUBLIC) + .cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, config.getPublicHRecolor(), false), + ChatMessageType.PUBLIC) + .cacheColor(new ChatColor(ChatColorType.NORMAL, config.getPrivateRecolor(), false), + ChatMessageType.PRIVATE_MESSAGE_SENT, ChatMessageType.PRIVATE_MESSAGE_RECEIVED) + .cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, config.getPrivateHRecolor(), false), + ChatMessageType.PRIVATE_MESSAGE_SENT, ChatMessageType.PRIVATE_MESSAGE_RECEIVED) + .cacheColor(new ChatColor(ChatColorType.NORMAL, config.getCcRecolor(), false), + ChatMessageType.CLANCHAT) + .cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, config.getCcHRecolor(), false), + ChatMessageType.CLANCHAT) + .cacheColor(new ChatColor(ChatColorType.NORMAL, config.getTransparentPublicRecolor(), true), + ChatMessageType.PUBLIC) + .cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, config.getTransparentPublicHRecolor(), true), + ChatMessageType.PUBLIC) + .cacheColor(new ChatColor(ChatColorType.NORMAL, config.getTransparentPrivateRecolor(), true), + ChatMessageType.PRIVATE_MESSAGE_SENT, ChatMessageType.PRIVATE_MESSAGE_RECEIVED) + .cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, config.getTransparentPrivateHRecolor(), true), + ChatMessageType.PRIVATE_MESSAGE_SENT, ChatMessageType.PRIVATE_MESSAGE_RECEIVED) + .cacheColor(new ChatColor(ChatColorType.NORMAL, config.getTransparentCcRecolor(), true), + ChatMessageType.CLANCHAT) + .cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, config.getTransparentCcHRecolor(), true), + ChatMessageType.CLANCHAT); } /** @@ -243,27 +234,31 @@ public class ChatCommandsPlugin extends Plugin return; } - StringBuilder builder = new StringBuilder(); - builder.append(colKeyword).append("Price of ") - .append(colKeywordHighLight).append(item.getName()) - .append(colKeyword).append(": GE average ") - .append(colKeywordHighLight).append(String.format("%,d", itemPrice.getPrice())); + final ChatMessageBuilder builder = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Price of ") + .append(ChatColorType.HIGHLIGHT) + .append(item.getName()) + .append(ChatColorType.NORMAL) + .append(": GE average ") + .append(ChatColorType.HIGHLIGHT) + .append(String.format("%,d", itemPrice.getPrice())); - ItemComposition itemComposition = client.getItemDefinition(itemId); + ItemComposition itemComposition = itemManager.getItemComposition(itemId); if (itemComposition != null) { int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT); - builder.append(colKeyword).append(" HA value ") - .append(colKeywordHighLight).append(String.format("%,d", alchPrice)); + builder + .append(ChatColorType.NORMAL) + .append(" HA value ") + .append(ChatColorType.HIGHLIGHT) + .append(String.format("%,d", alchPrice)); } - String response = builder.toString(); + String response = builder.build(); log.debug("Setting response {}", response); - - // XXX hopefully messageNode hasn't been reused yet? - messageNode.setRuneLiteFormatMessage(response); - messageNode.setValue(recolorMessage(messageNode.getType(), response)); + chatMessageManager.update(type, response, messageNode); client.refreshChat(); } } @@ -309,20 +304,23 @@ public class ChatCommandsPlugin extends Plugin SingleHiscoreSkillResult result = hiscoreClient.lookup(player, skill); Skill hiscoreSkill = result.getSkill(); - String response = new StringBuilder() - .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(); + String response = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Level ") + .append(ChatColorType.HIGHLIGHT) + .append(skill.getName()).append(": ").append(String.valueOf(hiscoreSkill.getLevel())) + .append(ChatColorType.NORMAL) + .append(" Experience: ") + .append(ChatColorType.HIGHLIGHT) + .append(String.format("%,d", hiscoreSkill.getExperience())) + .append(ChatColorType.NORMAL) + .append(" Rank: ") + .append(ChatColorType.HIGHLIGHT) + .append(String.format("%,d", hiscoreSkill.getRank())) + .build(); log.debug("Setting response {}", response); - - // XXX hopefully messageNode hasn't been reused yet? - setMessage.getMessageNode().setRuneLiteFormatMessage(response); - setMessage.getMessageNode().setValue(recolorMessage(setMessage.getType(), response)); + chatMessageManager.update(type, response, setMessage.getMessageNode()); client.refreshChat(); } catch (IOException ex) @@ -352,108 +350,6 @@ public class ChatCommandsPlugin extends Plugin return null; } - private ChatColor getChatColor(ChatMessageType type) - { - if ((type == ChatMessageType.PRIVATE_MESSAGE_SENT || type == ChatMessageType.PRIVATE_MESSAGE_RECEIVED) && !config.isPrivateRecolor()) - { - 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 ChatColor getChatColorH(ChatMessageType type) - { - if ((type == ChatMessageType.PRIVATE_MESSAGE_SENT || type == ChatMessageType.PRIVATE_MESSAGE_RECEIVED) && !config.isPrivateRecolor()) - { - 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 String recolorMessage(ChatMessageType type, String value) - { - 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 ? "" : ""; - } - /** * Cleans the playername string from ironman status icon if present and * corrects spaces diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/volcanicmine/VolcanicMinePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/volcanicmine/VolcanicMinePlugin.java index ac06f6785e..ccc7de65ec 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/volcanicmine/VolcanicMinePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/volcanicmine/VolcanicMinePlugin.java @@ -30,6 +30,7 @@ import com.google.inject.Binder; import com.google.inject.Provides; import java.awt.Color; import static java.lang.Math.abs; +import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameObject; import net.runelite.api.GameState; @@ -281,7 +282,7 @@ public class VolcanicMinePlugin extends Plugin { if (warningMode == WarningMode.INGAME || warningMode == WarningMode.INGAME_AND_NOTIFICATION) { - client.sendGameMessage(getColTag(config.platformColorHigh()) + "Volcanic Mine helper: " + warning); + client.sendGameMessage(ChatMessageType.GAME, getColTag(config.platformColorHigh()) + "Volcanic Mine helper: " + warning); } if (warningMode == WarningMode.NOTIFICATION || warningMode == WarningMode.INGAME_AND_NOTIFICATION) { diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index b19752522c..70cade0279 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -26,6 +26,7 @@ package net.runelite.mixins; import java.util.ArrayList; import java.util.List; +import net.runelite.api.ChatMessageType; import net.runelite.api.GameState; import net.runelite.api.IndexedSprite; import net.runelite.api.MenuAction; @@ -99,9 +100,9 @@ public abstract class RSClientMixin implements RSClient @Inject @Override - public void sendGameMessage(String message) + public void sendGameMessage(ChatMessageType type, String message) { - sendGameMessage(99, "", message); + sendGameMessage(type.getType(), "", message); } @Inject diff --git a/runelite-plugin-archetype/src/main/resources/archetype-resources/src/main/java/ExamplePlugin.java b/runelite-plugin-archetype/src/main/resources/archetype-resources/src/main/java/ExamplePlugin.java index 1c38a3712c..b047e16751 100644 --- a/runelite-plugin-archetype/src/main/resources/archetype-resources/src/main/java/ExamplePlugin.java +++ b/runelite-plugin-archetype/src/main/resources/archetype-resources/src/main/java/ExamplePlugin.java @@ -10,6 +10,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.GameState; +import net.runelite.api.ChatMessageType; import net.runelite.client.config.ConfigManager; import net.runelite.client.events.GameStateChanged; import net.runelite.client.plugins.Plugin; @@ -49,7 +50,7 @@ public class ExamplePlugin extends Plugin { if (gameStateChanged.getGameState() == GameState.LOGGED_IN) { - client.sendGameMessage("Example plugin is running!"); + client.sendGameMessage(ChatMessageType.GAME, "Example plugin is running!"); } } @@ -71,4 +72,4 @@ public class ExamplePlugin extends Plugin return configManager.getConfig(ExamplePluginConfiguration.class); } -} \ No newline at end of file +}