Merge pull request #6875 from TheStonedTurtle/PrivateMessageCycle
Add PM Target Cycling to Chat History plugin
This commit is contained in:
@@ -45,6 +45,24 @@ public final class ScriptID
|
|||||||
*/
|
*/
|
||||||
public static final int CHATBOX_INPUT = 96;
|
public static final int CHATBOX_INPUT = 96;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the Private Message chat interface
|
||||||
|
*
|
||||||
|
* Jagex refers to this script as {@code meslayer_mode6}
|
||||||
|
* <ul>
|
||||||
|
* <li> String Player to send private message to</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static final int OPEN_PRIVATE_MESSAGE_INTERFACE = 107;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuilds the text input widget inside the chat interface
|
||||||
|
* <ul>
|
||||||
|
* <li> String Message Prefix. Only used inside the GE search interfaces
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static final int CHAT_TEXT_INPUT_REBUILD = 222;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layouts the bank widgets
|
* Layouts the bank widgets
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public enum VarClientStr
|
|||||||
{
|
{
|
||||||
CHATBOX_TYPED_TEXT(1),
|
CHATBOX_TYPED_TEXT(1),
|
||||||
INPUT_TEXT(22),
|
INPUT_TEXT(22),
|
||||||
|
PRIVATE_MESSAGE_TARGET(23),
|
||||||
RECENT_CLAN_CHAT(129);
|
RECENT_CLAN_CHAT(129);
|
||||||
|
|
||||||
private final int index;
|
private final int index;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public enum InputType
|
|||||||
RUNELITE_CHATBOX_PANEL(-3),
|
RUNELITE_CHATBOX_PANEL(-3),
|
||||||
RUNELITE(-2),
|
RUNELITE(-2),
|
||||||
NONE(0),
|
NONE(0),
|
||||||
|
PRIVATE_MESSAGE(6),
|
||||||
SEARCH(11);
|
SEARCH(11);
|
||||||
|
|
||||||
private final int type;
|
private final int type;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* 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.chathistory;
|
||||||
|
|
||||||
|
import net.runelite.client.config.Config;
|
||||||
|
import net.runelite.client.config.ConfigGroup;
|
||||||
|
import net.runelite.client.config.ConfigItem;
|
||||||
|
|
||||||
|
@ConfigGroup("chathistory")
|
||||||
|
public interface ChatHistoryConfig extends Config
|
||||||
|
{
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "retainChatHistory",
|
||||||
|
name = "Retain Chat History",
|
||||||
|
description = "Retains chat history when logging in/out or world hopping",
|
||||||
|
position = 0
|
||||||
|
)
|
||||||
|
default boolean retainChatHistory()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "pmTargetCycling",
|
||||||
|
name = "PM Target Cycling",
|
||||||
|
description = "Pressing Tab while sending a PM will cycle the target username based on PM history",
|
||||||
|
position = 1
|
||||||
|
)
|
||||||
|
default boolean pmTargetCycling()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,47 +25,74 @@
|
|||||||
package net.runelite.client.plugins.chathistory;
|
package net.runelite.client.plugins.chathistory;
|
||||||
|
|
||||||
import com.google.common.collect.EvictingQueue;
|
import com.google.common.collect.EvictingQueue;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.inject.Provides;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import net.runelite.api.ChatMessageType;
|
import net.runelite.api.ChatMessageType;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.ScriptID;
|
||||||
|
import net.runelite.api.VarClientInt;
|
||||||
|
import net.runelite.api.VarClientStr;
|
||||||
import net.runelite.api.events.ChatMessage;
|
import net.runelite.api.events.ChatMessage;
|
||||||
import net.runelite.api.events.MenuOptionClicked;
|
import net.runelite.api.events.MenuOptionClicked;
|
||||||
|
import net.runelite.api.vars.InputType;
|
||||||
|
import net.runelite.client.callback.ClientThread;
|
||||||
import net.runelite.client.chat.ChatMessageManager;
|
import net.runelite.client.chat.ChatMessageManager;
|
||||||
import net.runelite.client.chat.QueuedMessage;
|
import net.runelite.client.chat.QueuedMessage;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
|
import net.runelite.client.input.KeyListener;
|
||||||
|
import net.runelite.client.input.KeyManager;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
name = "Chat History",
|
name = "Chat History",
|
||||||
description = "Retain your chat history when logging in/out or world hopping"
|
description = "Retain your chat history when logging in/out or world hopping",
|
||||||
|
tags = {"chat", "history", "retain", "cycle", "pm"}
|
||||||
)
|
)
|
||||||
public class ChatHistoryPlugin extends Plugin
|
public class ChatHistoryPlugin extends Plugin implements KeyListener
|
||||||
{
|
{
|
||||||
private static final String WELCOME_MESSAGE = "Welcome to Old School RuneScape.";
|
private static final String WELCOME_MESSAGE = "Welcome to Old School RuneScape.";
|
||||||
private static final String CLEAR_HISTORY = "Clear history";
|
private static final String CLEAR_HISTORY = "Clear history";
|
||||||
private static final String CLEAR_PRIVATE = "<col=ffff00>Private:";
|
private static final String CLEAR_PRIVATE = "<col=ffff00>Private:";
|
||||||
private static final Set<ChatMessageType> ALLOWED_HISTORY = Sets.newHashSet(
|
private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB;
|
||||||
ChatMessageType.PUBLIC,
|
|
||||||
ChatMessageType.PUBLIC_MOD,
|
|
||||||
ChatMessageType.CLANCHAT,
|
|
||||||
ChatMessageType.PRIVATE_MESSAGE_RECEIVED,
|
|
||||||
ChatMessageType.PRIVATE_MESSAGE_SENT,
|
|
||||||
ChatMessageType.PRIVATE_MESSAGE_RECEIVED_MOD,
|
|
||||||
ChatMessageType.GAME
|
|
||||||
);
|
|
||||||
|
|
||||||
private Queue<QueuedMessage> messageQueue;
|
private Queue<QueuedMessage> messageQueue;
|
||||||
|
private Deque<String> friends;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ClientThread clientThread;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ChatHistoryConfig config;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private KeyManager keyManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ChatMessageManager chatMessageManager;
|
private ChatMessageManager chatMessageManager;
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
ChatHistoryConfig getConfig(ConfigManager configManager)
|
||||||
|
{
|
||||||
|
return configManager.getConfig(ChatHistoryConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startUp()
|
protected void startUp()
|
||||||
{
|
{
|
||||||
messageQueue = EvictingQueue.create(100);
|
messageQueue = EvictingQueue.create(100);
|
||||||
|
friends = new ArrayDeque<>(5);
|
||||||
|
keyManager.registerKeyListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,6 +100,9 @@ public class ChatHistoryPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
messageQueue.clear();
|
messageQueue.clear();
|
||||||
messageQueue = null;
|
messageQueue = null;
|
||||||
|
friends.clear();
|
||||||
|
friends = null;
|
||||||
|
keyManager.unregisterKeyListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -82,6 +112,11 @@ public class ChatHistoryPlugin extends Plugin
|
|||||||
// of information that chat history was reset
|
// of information that chat history was reset
|
||||||
if (chatMessage.getMessage().equals(WELCOME_MESSAGE))
|
if (chatMessage.getMessage().equals(WELCOME_MESSAGE))
|
||||||
{
|
{
|
||||||
|
if (!config.retainChatHistory())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QueuedMessage queuedMessage;
|
QueuedMessage queuedMessage;
|
||||||
|
|
||||||
while ((queuedMessage = messageQueue.poll()) != null)
|
while ((queuedMessage = messageQueue.poll()) != null)
|
||||||
@@ -92,21 +127,33 @@ public class ChatHistoryPlugin extends Plugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ALLOWED_HISTORY.contains(chatMessage.getType()))
|
switch (chatMessage.getType())
|
||||||
{
|
{
|
||||||
final QueuedMessage queuedMessage = QueuedMessage.builder()
|
case PRIVATE_MESSAGE_SENT:
|
||||||
.type(chatMessage.getType())
|
case PRIVATE_MESSAGE_RECEIVED:
|
||||||
.name(chatMessage.getName())
|
case PRIVATE_MESSAGE_RECEIVED_MOD:
|
||||||
.sender(chatMessage.getSender())
|
final String name = Text.removeTags(chatMessage.getName());
|
||||||
.value(nbsp(chatMessage.getMessage()))
|
// Remove to ensure uniqueness & its place in history
|
||||||
.runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage()))
|
friends.remove(name);
|
||||||
.timestamp(chatMessage.getTimestamp())
|
friends.add(name);
|
||||||
.build();
|
// intentional fall-through
|
||||||
|
case PUBLIC:
|
||||||
|
case PUBLIC_MOD:
|
||||||
|
case CLANCHAT:
|
||||||
|
case GAME:
|
||||||
|
final QueuedMessage queuedMessage = QueuedMessage.builder()
|
||||||
|
.type(chatMessage.getType())
|
||||||
|
.name(chatMessage.getName())
|
||||||
|
.sender(chatMessage.getSender())
|
||||||
|
.value(nbsp(chatMessage.getMessage()))
|
||||||
|
.runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage()))
|
||||||
|
.timestamp(chatMessage.getTimestamp())
|
||||||
|
.build();
|
||||||
|
|
||||||
if (!messageQueue.contains(queuedMessage))
|
if (!messageQueue.contains(queuedMessage))
|
||||||
{
|
{
|
||||||
messageQueue.offer(queuedMessage);
|
messageQueue.offer(queuedMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,4 +190,64 @@ public class ChatHistoryPlugin extends Plugin
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e)
|
||||||
|
{
|
||||||
|
if (e.getKeyCode() != CYCLE_HOTKEY || !config.pmTargetCycling())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.getVar(VarClientInt.INPUT_TYPE) != InputType.PRIVATE_MESSAGE.getType())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientThread.invoke(() ->
|
||||||
|
{
|
||||||
|
final String target = findPreviousFriend();
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String currentMessage = client.getVar(VarClientStr.INPUT_TEXT);
|
||||||
|
|
||||||
|
client.runScript(ScriptID.OPEN_PRIVATE_MESSAGE_INTERFACE, target);
|
||||||
|
|
||||||
|
client.setVar(VarClientStr.INPUT_TEXT, currentMessage);
|
||||||
|
client.runScript(ScriptID.CHAT_TEXT_INPUT_REBUILD, "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyTyped(KeyEvent e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyReleased(KeyEvent e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private String findPreviousFriend()
|
||||||
|
{
|
||||||
|
final String currentTarget = client.getVar(VarClientStr.PRIVATE_MESSAGE_TARGET);
|
||||||
|
if (currentTarget == null || friends.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator<String> it = friends.descendingIterator(); it.hasNext(); )
|
||||||
|
{
|
||||||
|
String friend = it.next();
|
||||||
|
if (friend.equals(currentTarget))
|
||||||
|
{
|
||||||
|
return it.hasNext() ? it.next() : friends.getLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return friends.getLast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user