From 37c95ff75e459d5c334d3af26425b3b5e74ddef7 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 22 Jul 2018 19:43:57 -0400 Subject: [PATCH] Add private message input event and add !kc to chatcommands for private messages --- .../main/java/net/runelite/api/ScriptID.java | 5 + .../client/chat/ChatboxInputListener.java | 3 + .../runelite/client/chat/CommandManager.java | 53 ++++ .../client/events/PrivateMessageInput.java | 36 +++ .../chatcommands/ChatCommandsPlugin.java | 40 +++ runelite-scripts/scripts/PrivateMessage.hash | 1 + .../scripts/PrivateMessage.rs2asm | 280 ++++++++++++++++++ .../scripts/SendPrivateMessage.rs2asm | 34 +++ 8 files changed, 452 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java create mode 100644 runelite-scripts/scripts/PrivateMessage.hash create mode 100644 runelite-scripts/scripts/PrivateMessage.rs2asm create mode 100644 runelite-scripts/scripts/SendPrivateMessage.rs2asm diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 761c8b2f08..517402dcaa 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -70,4 +70,9 @@ public final class ScriptID * because you need an op listener attached to it for it to work */ public static final int NULL = 10003; + + /** + * Send a private message. + */ + public static final int PRIVMSG = 10004; } diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatboxInputListener.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatboxInputListener.java index 41e1ba9301..9213ba0fbf 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatboxInputListener.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatboxInputListener.java @@ -25,8 +25,11 @@ package net.runelite.client.chat; import net.runelite.client.events.ChatboxInput; +import net.runelite.client.events.PrivateMessageInput; public interface ChatboxInputListener { boolean onChatboxInput(ChatboxInput chatboxInput); + + boolean onPrivateMessageInput(PrivateMessageInput privateMessageInput); } diff --git a/runelite-client/src/main/java/net/runelite/client/chat/CommandManager.java b/runelite-client/src/main/java/net/runelite/client/chat/CommandManager.java index 0c6f5734aa..77cc3607e7 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/CommandManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/CommandManager.java @@ -41,6 +41,7 @@ import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.client.callback.ClientThread; import net.runelite.client.events.ChatboxInput; +import net.runelite.client.events.PrivateMessageInput; @Slf4j @Singleton @@ -48,6 +49,7 @@ public class CommandManager { private static final String RUNELITE_COMMAND = "runeliteCommand"; private static final String CHATBOX_INPUT = "chatboxInput"; + private static final String PRIVMATE_MESSAGE = "privateMessage"; private final Provider clientProvider; private final EventBus eventBus; @@ -90,6 +92,9 @@ public class CommandManager case CHATBOX_INPUT: handleInput(event); break; + case PRIVMATE_MESSAGE: + handlePrivateMessage(event); + break; } } @@ -156,6 +161,48 @@ public class CommandManager } } + private void handlePrivateMessage(ScriptCallbackEvent event) + { + Client client = clientProvider.get(); + final String[] stringStack = client.getStringStack(); + final int[] intStack = client.getIntStack(); + int stringStackCount = client.getStringStackSize(); + int intStackCount = client.getIntStackSize(); + + final String target = stringStack[stringStackCount - 2]; + final String message = stringStack[stringStackCount - 1]; + + PrivateMessageInput privateMessageInput = new PrivateMessageInput(target, message) + { + private boolean resumed; + + @Override + public void resume() + { + if (resumed) + { + return; + } + resumed = true; + + ClientThread clientThread = clientThreadProvider.get(); + clientThread.invokeLater(() -> sendPrivmsg(target, message)); + } + }; + + boolean stop = false; + for (ChatboxInputListener chatboxInputListener : chatboxInputListenerList) + { + stop |= chatboxInputListener.onPrivateMessageInput(privateMessageInput); + } + + if (stop) + { + intStack[intStackCount - 1] = 1; + client.setStringStackSize(stringStackCount - 2); // remove both target and message + } + } + private void sendChatboxInput(int chatType, String input) { Client client = clientProvider.get(); @@ -169,4 +216,10 @@ public class CommandManager sending = false; } } + + private void sendPrivmsg(String target, String message) + { + Client client = clientProvider.get(); + client.runScript(ScriptID.PRIVMSG, target, message); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java b/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java new file mode 100644 index 0000000000..8b54dc698e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, 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.events; + +import lombok.Data; + +@Data +public abstract class PrivateMessageInput +{ + private final String target; + private final String message; + + public abstract void resume(); +} 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 9d04dcc028..80578b15aa 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 @@ -56,6 +56,7 @@ import net.runelite.client.chat.ChatboxInputListener; import net.runelite.client.chat.CommandManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.events.ChatboxInput; +import net.runelite.client.events.PrivateMessageInput; import net.runelite.client.game.ItemManager; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; @@ -356,6 +357,45 @@ public class ChatCommandsPlugin extends Plugin implements ChatboxInputListener return true; } + @Override + public boolean onPrivateMessageInput(PrivateMessageInput privateMessageInput) + { + final String message = privateMessageInput.getMessage(); + if (!message.startsWith("!kc ")) + { + return false; + } + + int idx = message.indexOf(' '); + final String boss = longBossName(message.substring(idx + 1)); + + final int kc = getKc(boss); + if (kc <= 0) + { + return false; + } + + final String playerName = client.getLocalPlayer().getName(); + + executor.execute(() -> + { + try + { + killCountClient.submit(playerName, boss, kc); + } + catch (Exception ex) + { + log.warn("unable to submit killcount", ex); + } + finally + { + privateMessageInput.resume(); + } + }); + + return true; + } + private void killCountLookup(ChatMessageType type, SetMessage setMessage, String search) { final String player; diff --git a/runelite-scripts/scripts/PrivateMessage.hash b/runelite-scripts/scripts/PrivateMessage.hash new file mode 100644 index 0000000000..93ac7d20bc --- /dev/null +++ b/runelite-scripts/scripts/PrivateMessage.hash @@ -0,0 +1 @@ +36262759CFFFD94A6495B6BFA9B86C859921C5CE0340E465B1878461417A2470 \ No newline at end of file diff --git a/runelite-scripts/scripts/PrivateMessage.rs2asm b/runelite-scripts/scripts/PrivateMessage.rs2asm new file mode 100644 index 0000000000..7d1ecf410a --- /dev/null +++ b/runelite-scripts/scripts/PrivateMessage.rs2asm @@ -0,0 +1,280 @@ +.id 681 +.int_stack_count 0 +.string_stack_count 0 +.int_var_count 2 +.string_var_count 1 + get_varc 5 + load_int 14 + if_icmpeq LABEL4 + jump LABEL7 +LABEL4: + load_int 1 + put_varc 66 + return +LABEL7: + load_int -1 + istore 0 + load_string "" + sstore 0 + get_varc_string 22 + string_length + istore 1 + iload 1 + load_int 0 + if_icmpgt LABEL18 + jump LABEL193 +LABEL18: + get_varc 5 + switch + 1: LABEL21 + 2: LABEL44 + 3: LABEL44 + 4: LABEL23 + 5: LABEL23 + 6: LABEL44 + 7: LABEL110 + 8: LABEL114 + 9: LABEL120 + 10: LABEL123 + 11: LABEL185 + 12: LABEL142 + 13: LABEL160 + 15: LABEL120 + 16: LABEL190 + jump LABEL192 +LABEL21: + return + jump LABEL192 +LABEL23: + get_ignorecount + load_int 0 + if_icmplt LABEL27 + jump LABEL30 +LABEL27: + load_string "Unable to update ignore list - system busy." + send_game_message + jump LABEL43 +LABEL30: + get_varc 5 + load_int 4 + if_icmpeq LABEL34 + jump LABEL37 +LABEL34: + get_varc_string 22 + add_ignore + jump LABEL43 +LABEL37: + get_varc 5 + load_int 5 + if_icmpeq LABEL41 + jump LABEL43 +LABEL41: + get_varc_string 22 + remove_ignore +LABEL43: + jump LABEL192 +LABEL44: + get_friendcount + load_int 0 + if_icmplt LABEL48 + jump LABEL51 +LABEL48: + load_string "Unable to complete action - system busy." + send_game_message + jump LABEL109 +LABEL51: + get_varc 5 + load_int 2 + if_icmpeq LABEL55 + jump LABEL58 +LABEL55: + get_varc_string 22 + add_friend + jump LABEL109 +LABEL58: + get_varc 5 + load_int 3 + if_icmpeq LABEL62 + jump LABEL65 +LABEL62: + get_varc_string 22 + remove_friend + jump LABEL109 +LABEL65: + get_varc 5 + load_int 6 + if_icmpeq LABEL69 + jump LABEL109 +LABEL69: + get_varc 203 + load_int 0 + if_icmpeq LABEL76 + get_varc 203 + load_int -1 + if_icmpeq LABEL76 + jump LABEL82 +LABEL76: + load_int 1 + load_int 1 + invoke 299 + load_string "You must set a name before you can chat." + send_game_message + return +LABEL82: + 5005 + load_int 2 + if_icmpeq LABEL86 + jump LABEL97 +LABEL86: + 5000 + load_int 1 + 5016 + chatfilter_update + invoke 178 + invoke 553 + istore 0 + iload 0 + invoke 84 + iload 0 + invoke 89 +LABEL97: + get_varbit 4394 + load_int 1 + if_icmpeq LABEL101 + jump LABEL104 +LABEL101: + get_varc_string 23 + remove_friend + jump LABEL107 +LABEL104: + get_varc_string 23 + get_varc_string 22 + load_string "privateMessage" ; load event name + load_int 0 ; whether or not to skip + runelite_callback ; invoke callback + load_int 1 + if_icmpeq LABEL107 ; if skipped, do not message + privmsg +LABEL107: + get_gamecycle + put_varc 61 +LABEL109: + jump LABEL192 +LABEL110: + get_varc_string 22 + invoke 212 + numeric_input + jump LABEL192 +LABEL114: + get_varc_string 22 + string_remove_html + put_varc_string 128 + get_varc_string 22 + string_input_1 + jump LABEL192 +LABEL120: + get_varc_string 22 + string_input_2 + jump LABEL192 +LABEL123: + get_varc 203 + load_int 0 + if_icmpeq LABEL130 + get_varc 203 + load_int -1 + if_icmpeq LABEL130 + jump LABEL136 +LABEL130: + load_int 1 + load_int 1 + invoke 299 + load_string "You must set a name before you can chat." + send_game_message + return +LABEL136: + get_varc_string 22 + string_remove_html + put_varc_string 129 + get_varc_string 22 + join_clanchat + jump LABEL192 +LABEL142: + iload 1 + load_int 10 + if_icmpgt LABEL146 + jump LABEL152 +LABEL146: + get_varc_string 22 + load_int 0 + load_int 9 + string_substring + sstore 0 + jump LABEL154 +LABEL152: + get_varc_string 22 + sstore 0 +LABEL154: + sload 0 + tolowercase + 5021 + invoke 553 + invoke 84 + jump LABEL192 +LABEL160: + get_varc 203 + load_int 0 + if_icmpeq LABEL167 + get_varc 203 + load_int -1 + if_icmpeq LABEL167 + jump LABEL173 +LABEL167: + load_int 1 + load_int 1 + invoke 299 + load_string "You must set a name before you can chat." + send_game_message + return +LABEL173: + get_varc_string 22 + load_int 0 + put_varc 62 + put_varc_string 28 + invoke 95 + load_int 552 + load_int -2147483645 + load_int 1 + load_string "I1" + load_int 10616843 + widget_put_render_listener_widget + jump LABEL192 +LABEL185: + load_int 0 + load_int 1 + invoke 299 + return + jump LABEL192 +LABEL190: + get_varc_string 22 + invoke 2061 +LABEL192: + jump LABEL199 +LABEL193: + get_varc 5 + switch + 16: LABEL198 + 7: LABEL196 + 8: LABEL196 + 9: LABEL196 + 15: LABEL196 + jump LABEL199 +LABEL196: + return + jump LABEL199 +LABEL198: + return +LABEL199: + load_int 1 + load_int 1 + invoke 299 + return diff --git a/runelite-scripts/scripts/SendPrivateMessage.rs2asm b/runelite-scripts/scripts/SendPrivateMessage.rs2asm new file mode 100644 index 0000000000..f2102c1328 --- /dev/null +++ b/runelite-scripts/scripts/SendPrivateMessage.rs2asm @@ -0,0 +1,34 @@ +; Copyright (c) 2018 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. + +.id 10004 +.int_stack_count 0 +.string_stack_count 2 +.int_var_count 0 +.string_var_count 2 + +; Send a private message + sload 0 + sload 1 + privmsg + return \ No newline at end of file