Merge branch 'master' of https://github.com/runelite/runelite into upstream-2122021

 Conflicts:
	cache-client/pom.xml
	cache-updater/pom.xml
	cache/pom.xml
	http-api/pom.xml
	http-service/pom.xml
	pom.xml
	runelite-api/pom.xml
	runelite-api/src/main/java/net/runelite/api/MenuAction.java
	runelite-client/pom.xml
	runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
	runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java
	runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java
	runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java
	runelite-jshell/pom.xml
	runelite-script-assembler-plugin/pom.xml
This commit is contained in:
Justin
2021-12-02 09:06:51 +11:00
32 changed files with 1251 additions and 1010 deletions

View File

@@ -179,6 +179,8 @@ public enum ChatMessageType
CLAN_GIM_FORM_GROUP(111), CLAN_GIM_FORM_GROUP(111),
CLAN_GIM_GROUP_WITH(112), CLAN_GIM_GROUP_WITH(112),
CLAN_GIM_CHAT(-1),
CLAN_GIM_MESSAGE(-1),
/** /**
* An unknown message type. * An unknown message type.
*/ */
@@ -192,7 +194,10 @@ public enum ChatMessageType
{ {
for (ChatMessageType chatMessageType : values()) for (ChatMessageType chatMessageType : values())
{ {
CHAT_MESSAGE_TYPES.put(chatMessageType.type, chatMessageType); if (chatMessageType.type != -1)
{
CHAT_MESSAGE_TYPES.put(chatMessageType.type, chatMessageType);
}
} }
} }

View File

@@ -233,6 +233,11 @@ public enum MenuAction
*/ */
SPELL_CAST_ON_WIDGET(58), SPELL_CAST_ON_WIDGET(58),
/**
* Menu action for high priority runelite options
*/
RUNELITE_HIGH_PRIORITY(999),
/** /**
* Sub 1000 so it doesn't get sorted down in the list * Sub 1000 so it doesn't get sorted down in the list
*/ */

View File

@@ -100,6 +100,7 @@ public class ChatCommandManager implements ChatboxInputListener
case PRIVATECHATOUT: case PRIVATECHATOUT:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
break; break;
default: default:
return; return;

View File

@@ -24,6 +24,7 @@
*/ */
package net.runelite.client.chat; package net.runelite.client.chat;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
@@ -44,7 +45,6 @@ import net.runelite.api.Client;
import net.runelite.api.MessageNode; import net.runelite.api.MessageNode;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.Varbits; import net.runelite.api.Varbits;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ResizeableChanged; import net.runelite.api.events.ResizeableChanged;
import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
@@ -111,15 +111,23 @@ public class ChatMessageManager
} }
} }
@Subscribe(priority = -1) // run after all plugins @VisibleForTesting
public void onChatMessage(ChatMessage chatMessage) void colorChatMessage()
{ {
MessageNode messageNode = chatMessage.getMessageNode(); final String[] stringStack = client.getStringStack();
ChatMessageType chatMessageType = chatMessage.getType(); final int size = client.getStringStackSize();
final int uid = client.getIntStack()[client.getIntStackSize() - 1];
boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1; final MessageNode messageNode = client.getMessages().get(uid);
assert messageNode != null : "chat message build for unknown message";
final String username = stringStack[size - 3];
final String channel = stringStack[size - 4];
final ChatMessageType chatMessageType = messageNode.getType();
final boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1;
Color usernameColor = null; Color usernameColor = null;
Color senderColor = null; Color channelColor = null;
switch (chatMessageType) switch (chatMessageType)
{ {
@@ -130,7 +138,7 @@ public class ChatMessageManager
case PUBLICCHAT: case PUBLICCHAT:
case MODCHAT: case MODCHAT:
{ {
String sanitizedUsername = Text.removeTags(chatMessage.getName()).replace('\u00A0', ' '); String sanitizedUsername = Text.removeTags(username).replace('\u00A0', ' ');
if (client.getLocalPlayer().getName().equals(sanitizedUsername)) if (client.getLocalPlayer().getName().equals(sanitizedUsername))
{ {
@@ -149,29 +157,30 @@ public class ChatMessageManager
case FRIENDSCHAT: case FRIENDSCHAT:
case FRIENDSCHATNOTIFICATION: case FRIENDSCHATNOTIFICATION:
usernameColor = isChatboxTransparent ? chatColorConfig.transparentFriendsChatUsernames() : chatColorConfig.opaqueFriendsChatUsernames(); usernameColor = isChatboxTransparent ? chatColorConfig.transparentFriendsChatUsernames() : chatColorConfig.opaqueFriendsChatUsernames();
senderColor = isChatboxTransparent ? chatColorConfig.transparentFriendsChatChannelName() : chatColorConfig.opaqueFriendsChatChannelName(); channelColor = isChatboxTransparent ? chatColorConfig.transparentFriendsChatChannelName() : chatColorConfig.opaqueFriendsChatChannelName();
break; break;
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_MESSAGE: case CLAN_MESSAGE:
case CLAN_GIM_CHAT:
case CLAN_GIM_MESSAGE:
usernameColor = isChatboxTransparent ? chatColorConfig.transparentClanChatUsernames() : chatColorConfig.opaqueClanChatUsernames(); usernameColor = isChatboxTransparent ? chatColorConfig.transparentClanChatUsernames() : chatColorConfig.opaqueClanChatUsernames();
senderColor = isChatboxTransparent ? chatColorConfig.transparentClanChannelName() : chatColorConfig.opaqueClanChannelName(); channelColor = isChatboxTransparent ? chatColorConfig.transparentClanChannelName() : chatColorConfig.opaqueClanChannelName();
break; break;
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GUEST_MESSAGE: case CLAN_GUEST_MESSAGE:
usernameColor = isChatboxTransparent ? chatColorConfig.transparentClanChatGuestUsernames() : chatColorConfig.opaqueClanChatGuestUsernames(); usernameColor = isChatboxTransparent ? chatColorConfig.transparentClanChatGuestUsernames() : chatColorConfig.opaqueClanChatGuestUsernames();
senderColor = isChatboxTransparent ? chatColorConfig.transparentClanChannelGuestName() : chatColorConfig.opaqueClanGuestChatChannelName(); channelColor = isChatboxTransparent ? chatColorConfig.transparentClanChannelGuestName() : chatColorConfig.opaqueClanGuestChatChannelName();
break; break;
} }
if (usernameColor != null) if (usernameColor != null)
{ {
messageNode.setName(ColorUtil.wrapWithColorTag(messageNode.getName(), usernameColor)); stringStack[size - 3] = ColorUtil.wrapWithColorTag(username, usernameColor);
} }
String sender = messageNode.getSender(); if (channelColor != null && !Strings.isNullOrEmpty(channel))
if (senderColor != null && !Strings.isNullOrEmpty(sender))
{ {
messageNode.setSender(ColorUtil.wrapWithColorTag(sender, senderColor)); stringStack[size - 4] = ColorUtil.wrapWithColorTag(channel, channelColor);
} }
final Collection<ChatColor> chatColors = colorCache.get(chatMessageType); final Collection<ChatColor> chatColors = colorCache.get(chatMessageType);
@@ -184,9 +193,9 @@ public class ChatMessageManager
// Replace </col> tags in the message with the new color so embedded </col> won't reset the color // Replace </col> tags in the message with the new color so embedded </col> won't reset the color
final Color color = chatColor.getColor(); final Color color = chatColor.getColor();
messageNode.setValue(ColorUtil.wrapWithColorTag( stringStack[size - 2] = ColorUtil.wrapWithColorTag(
messageNode.getValue().replace(ColorUtil.CLOSING_COLOR_TAG, ColorUtil.colorTag(color)), stringStack[size - 2].replace(ColorUtil.CLOSING_COLOR_TAG, ColorUtil.colorTag(color)),
color)); color);
break; break;
} }
} }
@@ -205,6 +214,9 @@ public class ChatMessageManager
case "privChatUsername": case "privChatUsername":
wrap = true; wrap = true;
break; break;
case "chatMessageBuilding":
colorChatMessage();
return;
default: default:
return; return;
} }
@@ -247,6 +259,7 @@ public class ChatMessageManager
case FRIENDSCHAT: case FRIENDSCHAT:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
return JagexColors.CHAT_FC_TEXT_OPAQUE_BACKGROUND; return JagexColors.CHAT_FC_TEXT_OPAQUE_BACKGROUND;
case ITEM_EXAMINE: case ITEM_EXAMINE:
case OBJECT_EXAMINE: case OBJECT_EXAMINE:
@@ -255,6 +268,7 @@ public class ChatMessageManager
case FRIENDSCHATNOTIFICATION: case FRIENDSCHATNOTIFICATION:
case CLAN_MESSAGE: case CLAN_MESSAGE:
case CLAN_GUEST_MESSAGE: case CLAN_GUEST_MESSAGE:
case CLAN_GIM_MESSAGE:
return JagexColors.CHAT_GAME_EXAMINE_TEXT_OPAQUE_BACKGROUND; return JagexColors.CHAT_GAME_EXAMINE_TEXT_OPAQUE_BACKGROUND;
} }
} }
@@ -272,6 +286,7 @@ public class ChatMessageManager
case FRIENDSCHAT: case FRIENDSCHAT:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
return JagexColors.CHAT_FC_TEXT_TRANSPARENT_BACKGROUND; return JagexColors.CHAT_FC_TEXT_TRANSPARENT_BACKGROUND;
case ITEM_EXAMINE: case ITEM_EXAMINE:
case OBJECT_EXAMINE: case OBJECT_EXAMINE:
@@ -280,6 +295,7 @@ public class ChatMessageManager
case FRIENDSCHATNOTIFICATION: case FRIENDSCHATNOTIFICATION:
case CLAN_MESSAGE: case CLAN_MESSAGE:
case CLAN_GUEST_MESSAGE: case CLAN_GUEST_MESSAGE:
case CLAN_GIM_MESSAGE:
return JagexColors.CHAT_GAME_EXAMINE_TEXT_TRANSPARENT_BACKGROUND; return JagexColors.CHAT_GAME_EXAMINE_TEXT_TRANSPARENT_BACKGROUND;
} }
} }
@@ -373,21 +389,29 @@ public class ChatMessageManager
{ {
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatInfo(), false), cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatInfo(), false),
ChatMessageType.CLAN_MESSAGE); ChatMessageType.CLAN_MESSAGE);
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatInfo(), false),
ChatMessageType.CLAN_GIM_MESSAGE);
} }
if (chatColorConfig.opaqueClanChatInfoHighlight() != null) if (chatColorConfig.opaqueClanChatInfoHighlight() != null)
{ {
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatInfoHighlight(), false), cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatInfoHighlight(), false),
ChatMessageType.CLAN_MESSAGE); ChatMessageType.CLAN_MESSAGE);
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatInfoHighlight(), false),
ChatMessageType.CLAN_GIM_MESSAGE);
} }
if (chatColorConfig.opaqueClanChatMessage() != null) if (chatColorConfig.opaqueClanChatMessage() != null)
{ {
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatMessage(), false), cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatMessage(), false),
ChatMessageType.CLAN_CHAT); ChatMessageType.CLAN_CHAT);
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatMessage(), false),
ChatMessageType.CLAN_GIM_CHAT);
} }
if (chatColorConfig.opaqueClanChatMessageHighlight() != null) if (chatColorConfig.opaqueClanChatMessageHighlight() != null)
{ {
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatMessageHighlight(), false), cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatMessageHighlight(), false),
ChatMessageType.CLAN_CHAT); ChatMessageType.CLAN_CHAT);
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatMessageHighlight(), false),
ChatMessageType.CLAN_GIM_CHAT);
} }
if (chatColorConfig.opaqueClanChatGuestInfo() != null) if (chatColorConfig.opaqueClanChatGuestInfo() != null)
@@ -555,21 +579,29 @@ public class ChatMessageManager
{ {
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatInfo(), true), cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatInfo(), true),
ChatMessageType.CLAN_MESSAGE); ChatMessageType.CLAN_MESSAGE);
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatInfo(), true),
ChatMessageType.CLAN_GIM_MESSAGE);
} }
if (chatColorConfig.transparentClanChatInfoHighlight() != null) if (chatColorConfig.transparentClanChatInfoHighlight() != null)
{ {
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatInfoHighlight(), true), cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatInfoHighlight(), true),
ChatMessageType.CLAN_MESSAGE); ChatMessageType.CLAN_MESSAGE);
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatInfoHighlight(), true),
ChatMessageType.CLAN_GIM_MESSAGE);
} }
if (chatColorConfig.transparentClanChatMessage() != null) if (chatColorConfig.transparentClanChatMessage() != null)
{ {
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatMessage(), true), cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatMessage(), true),
ChatMessageType.CLAN_CHAT); ChatMessageType.CLAN_CHAT);
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatMessage(), true),
ChatMessageType.CLAN_GIM_CHAT);
} }
if (chatColorConfig.transparentClanChatMessageHighlight() != null) if (chatColorConfig.transparentClanChatMessageHighlight() != null)
{ {
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatMessageHighlight(), true), cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatMessageHighlight(), true),
ChatMessageType.CLAN_CHAT); ChatMessageType.CLAN_CHAT);
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatMessageHighlight(), true),
ChatMessageType.CLAN_GIM_CHAT);
} }
if (chatColorConfig.transparentClanChatGuestInfo() != null) if (chatColorConfig.transparentClanChatGuestInfo() != null)

View File

@@ -99,11 +99,9 @@ class ConfigInvocationHandler implements InvocationHandler
} }
// Convert value to return type // Convert value to return type
Class<?> returnType = method.getReturnType();
try try
{ {
Object objectValue = ConfigManager.stringToObject(value, returnType); Object objectValue = manager.stringToObject(value, method.getGenericReturnType());
cache.put(method, objectValue == null ? NULL : objectValue); cache.put(method, objectValue == null ? NULL : objectValue);
return objectValue; return objectValue;
} }
@@ -155,7 +153,7 @@ class ConfigInvocationHandler implements InvocationHandler
} }
else else
{ {
String newValueStr = ConfigManager.objectToString(newValue); String newValueStr = manager.objectToString(newValue);
manager.setConfiguration(group.value(), item.keyName(), newValueStr); manager.setConfiguration(group.value(), item.keyName(), newValueStr);
} }
return null; return null;

View File

@@ -24,13 +24,14 @@
*/ */
package net.runelite.client.config; package net.runelite.client.config;
import java.lang.reflect.Type;
import lombok.Value; import lombok.Value;
@Value @Value
public class ConfigItemDescriptor implements ConfigObject public class ConfigItemDescriptor implements ConfigObject
{ {
private final ConfigItem item; private final ConfigItem item;
private final Class<?> type; private final Type type;
private final Range range; private final Range range;
private final Alpha alpha; private final Alpha alpha;
private final Units units; private final Units units;

View File

@@ -30,6 +30,7 @@ import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.hash.Hasher; import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing; import com.google.common.hash.Hashing;
import com.google.gson.Gson;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Point; import java.awt.Point;
@@ -44,7 +45,9 @@ import java.io.OutputStreamWriter;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.AtomicMoveNotSupportedException;
@@ -128,6 +131,7 @@ public class ConfigManager
private final File settingsFileInput; private final File settingsFileInput;
private final EventBus eventBus; private final EventBus eventBus;
private final OkHttpClient okHttpClient; private final OkHttpClient okHttpClient;
private final Gson gson;
private AccountSession session; private AccountSession session;
private ConfigClient configClient; private ConfigClient configClient;
@@ -152,13 +156,15 @@ public class ConfigManager
ScheduledExecutorService scheduledExecutorService, ScheduledExecutorService scheduledExecutorService,
EventBus eventBus, EventBus eventBus,
OkHttpClient okHttpClient, OkHttpClient okHttpClient,
@Nullable Client client) @Nullable Client client,
Gson gson)
{ {
this.settingsFileInput = config; this.settingsFileInput = config;
this.eventBus = eventBus; this.eventBus = eventBus;
this.okHttpClient = okHttpClient; this.okHttpClient = okHttpClient;
this.client = client; this.client = client;
this.propertiesFile = getPropertiesFile(); this.propertiesFile = getPropertiesFile();
this.gson = gson;
scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS); scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
} }
@@ -412,12 +418,12 @@ public class ConfigManager
return properties.getProperty(getWholeKey(groupName, profile, key)); return properties.getProperty(getWholeKey(groupName, profile, key));
} }
public <T> T getConfiguration(String groupName, String key, Class<T> clazz) public <T> T getConfiguration(String groupName, String key, Type clazz)
{ {
return getConfiguration(groupName, null, key, clazz); return getConfiguration(groupName, null, key, clazz);
} }
public <T> T getRSProfileConfiguration(String groupName, String key, Class<T> clazz) public <T> T getRSProfileConfiguration(String groupName, String key, Type clazz)
{ {
String rsProfileKey = this.rsProfileKey; String rsProfileKey = this.rsProfileKey;
if (rsProfileKey == null) if (rsProfileKey == null)
@@ -428,14 +434,14 @@ public class ConfigManager
return getConfiguration(groupName, rsProfileKey, key, clazz); return getConfiguration(groupName, rsProfileKey, key, clazz);
} }
public <T> T getConfiguration(String groupName, String profile, String key, Class<T> clazz) public <T> T getConfiguration(String groupName, String profile, String key, Type type)
{ {
String value = getConfiguration(groupName, profile, key); String value = getConfiguration(groupName, profile, key);
if (!Strings.isNullOrEmpty(value)) if (!Strings.isNullOrEmpty(value))
{ {
try try
{ {
return (T) stringToObject(value, clazz); return (T) stringToObject(value, type);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -488,12 +494,12 @@ public class ConfigManager
eventBus.post(configChanged); eventBus.post(configChanged);
} }
public void setConfiguration(String groupName, String profile, String key, Object value) public <T> void setConfiguration(String groupName, String profile, String key, T value)
{ {
setConfiguration(groupName, profile, key, objectToString(value)); setConfiguration(groupName, profile, key, objectToString(value));
} }
public void setConfiguration(String groupName, String key, Object value) public <T> void setConfiguration(String groupName, String key, T value)
{ {
// do not save consumers for buttons, they cannot be changed anyway // do not save consumers for buttons, they cannot be changed anyway
if (value instanceof Consumer) if (value instanceof Consumer)
@@ -504,7 +510,7 @@ public class ConfigManager
setConfiguration(groupName, null, key, value); setConfiguration(groupName, null, key, value);
} }
public void setRSProfileConfiguration(String groupName, String key, Object value) public <T> void setRSProfileConfiguration(String groupName, String key, T value)
{ {
String rsProfileKey = this.rsProfileKey; String rsProfileKey = this.rsProfileKey;
if (rsProfileKey == null) if (rsProfileKey == null)
@@ -650,7 +656,7 @@ public class ConfigManager
.filter(m -> m.getParameterCount() == 0 && m.isAnnotationPresent(ConfigItem.class)) .filter(m -> m.getParameterCount() == 0 && m.isAnnotationPresent(ConfigItem.class))
.map(m -> new ConfigItemDescriptor( .map(m -> new ConfigItemDescriptor(
m.getDeclaredAnnotation(ConfigItem.class), m.getDeclaredAnnotation(ConfigItem.class),
m.getReturnType(), m.getGenericReturnType(),
m.getDeclaredAnnotation(Range.class), m.getDeclaredAnnotation(Range.class),
m.getDeclaredAnnotation(Alpha.class), m.getDeclaredAnnotation(Alpha.class),
m.getDeclaredAnnotation(Units.class) m.getDeclaredAnnotation(Units.class)
@@ -721,16 +727,16 @@ public class ConfigManager
continue; continue;
} }
if (!override) if (!override)
{
// This checks if it is set and is also unmarshallable to the correct type; so
// we will overwrite invalid config values with the default
Object current = getConfiguration(group.value(), item.keyName(), method.getGenericReturnType());
if (current != null)
{ {
// This checks if it is set and is also unmarshallable to the correct type; so continue; // something else is already set
// we will overwrite invalid config values with the default
Object current = getConfiguration(group.value(), item.keyName(), method.getReturnType());
if (current != null)
{
continue; // something else is already set
}
} }
}
Object defaultValue; Object defaultValue;
try try
@@ -760,7 +766,7 @@ public class ConfigManager
} }
} }
static Object stringToObject(String str, Class<?> type) Object stringToObject(String str, Type type)
{ {
if (type == boolean.class || type == Boolean.class) if (type == boolean.class || type == Boolean.class)
{ {
@@ -801,7 +807,7 @@ public class ConfigManager
int height = Integer.parseInt(splitStr[3]); int height = Integer.parseInt(splitStr[3]);
return new Rectangle(x, y, width, height); return new Rectangle(x, y, width, height);
} }
if (type.isEnum()) if (type instanceof Class && ((Class<?>) type).isEnum())
{ {
return Enum.valueOf((Class<? extends Enum>) type, str); return Enum.valueOf((Class<? extends Enum>) type, str);
} }
@@ -836,6 +842,14 @@ public class ConfigManager
{ {
return Base64.getUrlDecoder().decode(str); return Base64.getUrlDecoder().decode(str);
} }
if (type instanceof ParameterizedType)
{
ParameterizedType parameterizedType = (ParameterizedType) type;
if (parameterizedType.getRawType() == Set.class)
{
return gson.fromJson(str, parameterizedType);
}
}
if (type == EnumSet.class) if (type == EnumSet.class)
{ {
try try
@@ -875,7 +889,7 @@ public class ConfigManager
} }
@Nullable @Nullable
static String objectToString(Object object) String objectToString(Object object)
{ {
if (object instanceof Color) if (object instanceof Color)
{ {
@@ -922,6 +936,10 @@ public class ConfigManager
{ {
return Base64.getUrlEncoder().encodeToString((byte[]) object); return Base64.getUrlEncoder().encodeToString((byte[]) object);
} }
if (object instanceof Set)
{
return gson.toJson(object, Set.class);
}
if (object instanceof EnumSet) if (object instanceof EnumSet)
{ {
if (((EnumSet) object).size() == 0) if (((EnumSet) object).size() == 0)

View File

@@ -188,6 +188,7 @@ public class ChatFilterPlugin extends Plugin
case FRIENDSCHAT: case FRIENDSCHAT:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
if (shouldFilterPlayerMessage(Text.removeTags(name))) if (shouldFilterPlayerMessage(Text.removeTags(name)))
{ {
message = censorMessage(name, message); message = censorMessage(name, message);

View File

@@ -28,7 +28,6 @@ package net.runelite.client.plugins.chathistory;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.EvictingQueue; import com.google.common.collect.EvictingQueue;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.awt.Color;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@@ -63,7 +62,6 @@ import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager; 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.ColorUtil;
import net.runelite.client.util.Text; import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -176,7 +174,11 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener
case MODCHAT: case MODCHAT:
case FRIENDSCHAT: case FRIENDSCHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GUEST_MESSAGE:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_MESSAGE:
case CLAN_GIM_CHAT:
case CLAN_GIM_MESSAGE:
case CONSOLE: case CONSOLE:
messageQueue.offer(chatMessage.getMessageNode()); messageQueue.offer(chatMessage.getMessageNode());
} }
@@ -266,35 +268,37 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener
@Subscribe @Subscribe
public void onMenuEntryAdded(MenuEntryAdded entry) public void onMenuEntryAdded(MenuEntryAdded entry)
{ {
final ChatboxTab tab = ChatboxTab.of(entry.getParam1()); if (entry.getType() != MenuAction.CC_OP.getId())
{
return;
}
if (tab == null || tab.getAfter() == null || !config.clearHistory() || !Text.removeTags(entry.getOption()).equals(tab.getAfter())) ChatboxTab tab = ChatboxTab.of(entry.getActionParam1());
if (tab == null || tab.getAfter() == null || !config.clearHistory() || !entry.getOption().endsWith(tab.getAfter()))
{ {
return; return;
} }
final MenuEntry clearEntry = new MenuEntry(); final MenuEntry clearEntry = new MenuEntry();
clearEntry.setTarget(""); clearEntry.setTarget("");
clearEntry.setType(MenuAction.RUNELITE.getId()); clearEntry.setType(MenuAction.RUNELITE_HIGH_PRIORITY.getId());
clearEntry.setParam0(entry.getActionParam0()); clearEntry.setParam0(entry.getActionParam0());
clearEntry.setParam1(entry.getParam1()); clearEntry.setParam1(entry.getActionParam1());
if (tab == ChatboxTab.GAME)
{
// keep type as the original CC_OP to correctly group "Game: Clear history" with
// other tab "Game: *" options.
clearEntry.setType(entry.getType());
}
final StringBuilder messageBuilder = new StringBuilder();
final StringBuilder optionBuilder = new StringBuilder();
if (tab != ChatboxTab.ALL) if (tab != ChatboxTab.ALL)
{ {
messageBuilder.append(ColorUtil.wrapWithColorTag(tab.getName() + ": ", Color.YELLOW)); // Pull tab name from menu since Trade/Group is variable
String option = entry.getOption();
int idx = option.indexOf(':');
if (idx != -1)
{
optionBuilder.append(option, 0, idx).append(":</col> ");
}
} }
messageBuilder.append(CLEAR_HISTORY); optionBuilder.append(CLEAR_HISTORY);
clearEntry.setOption(messageBuilder.toString()); clearEntry.setOption(optionBuilder.toString());
final MenuEntry[] menuEntries = client.getMenuEntries(); final MenuEntry[] menuEntries = client.getMenuEntries();
client.setMenuEntries(ArrayUtils.insert(menuEntries.length - 1, menuEntries, clearEntry)); client.setMenuEntries(ArrayUtils.insert(menuEntries.length - 1, menuEntries, clearEntry));

View File

@@ -35,46 +35,47 @@ import net.runelite.api.widgets.WidgetInfo;
enum ChatboxTab enum ChatboxTab
{ {
ALL("All", "Switch tab", WidgetInfo.CHATBOX_TAB_ALL, ALL("Switch tab", WidgetInfo.CHATBOX_TAB_ALL,
ChatMessageType.values()), ChatMessageType.values()),
// null 'after' var since we're not adding to menu // null 'after' var since we're not adding to menu
PRIVATE("Private", null, WidgetInfo.CHATBOX_TAB_PRIVATE, PRIVATE(null, WidgetInfo.CHATBOX_TAB_PRIVATE,
ChatMessageType.PRIVATECHAT, ChatMessageType.PRIVATECHATOUT, ChatMessageType.MODPRIVATECHAT, ChatMessageType.PRIVATECHAT, ChatMessageType.PRIVATECHATOUT, ChatMessageType.MODPRIVATECHAT,
ChatMessageType.LOGINLOGOUTNOTIFICATION), ChatMessageType.LOGINLOGOUTNOTIFICATION),
// null 'after' var since we're not adding to menu // null 'after' var since we're not adding to menu
PUBLIC("Public", null, WidgetInfo.CHATBOX_TAB_PUBLIC, PUBLIC(null, WidgetInfo.CHATBOX_TAB_PUBLIC,
ChatMessageType.PUBLICCHAT, ChatMessageType.AUTOTYPER, ChatMessageType.MODCHAT, ChatMessageType.MODAUTOTYPER), ChatMessageType.PUBLICCHAT, ChatMessageType.AUTOTYPER, ChatMessageType.MODCHAT, ChatMessageType.MODAUTOTYPER),
GAME("Game", "Game: Filter", WidgetInfo.CHATBOX_TAB_GAME, GAME("Filter", WidgetInfo.CHATBOX_TAB_GAME,
ChatMessageType.GAMEMESSAGE, ChatMessageType.ENGINE, ChatMessageType.BROADCAST, ChatMessageType.GAMEMESSAGE, ChatMessageType.ENGINE, ChatMessageType.BROADCAST,
ChatMessageType.SNAPSHOTFEEDBACK, ChatMessageType.ITEM_EXAMINE, ChatMessageType.NPC_EXAMINE, ChatMessageType.SNAPSHOTFEEDBACK, ChatMessageType.ITEM_EXAMINE, ChatMessageType.NPC_EXAMINE,
ChatMessageType.OBJECT_EXAMINE, ChatMessageType.FRIENDNOTIFICATION, ChatMessageType.IGNORENOTIFICATION, ChatMessageType.OBJECT_EXAMINE, ChatMessageType.FRIENDNOTIFICATION, ChatMessageType.IGNORENOTIFICATION,
ChatMessageType.CONSOLE, ChatMessageType.SPAM, ChatMessageType.PLAYERRELATED, ChatMessageType.TENSECTIMEOUT, ChatMessageType.CONSOLE, ChatMessageType.SPAM, ChatMessageType.PLAYERRELATED, ChatMessageType.TENSECTIMEOUT,
ChatMessageType.WELCOME, ChatMessageType.UNKNOWN), ChatMessageType.WELCOME, ChatMessageType.UNKNOWN),
CHANNEL("Channel", null, WidgetInfo.CHATBOX_TAB_CHANNEL, CHANNEL(null, WidgetInfo.CHATBOX_TAB_CHANNEL,
ChatMessageType.FRIENDSCHATNOTIFICATION, ChatMessageType.FRIENDSCHAT, ChatMessageType.CHALREQ_FRIENDSCHAT), ChatMessageType.FRIENDSCHATNOTIFICATION, ChatMessageType.FRIENDSCHAT, ChatMessageType.CHALREQ_FRIENDSCHAT),
CLAN("Clan", null, WidgetInfo.CHATBOX_TAB_CLAN, CLAN(null, WidgetInfo.CHATBOX_TAB_CLAN,
ChatMessageType.CLAN_CHAT, ChatMessageType.CLAN_MESSAGE, ChatMessageType.CLAN_GUEST_CHAT, ChatMessageType.CLAN_GUEST_MESSAGE), ChatMessageType.CLAN_CHAT, ChatMessageType.CLAN_MESSAGE,
ChatMessageType.CLAN_GUEST_CHAT, ChatMessageType.CLAN_GUEST_MESSAGE),
TRADE("Trade", "Trade: Show none", WidgetInfo.CHATBOX_TAB_TRADE, // Group has its own Clear option, but Trade does not
ChatMessageType.TRADE_SENT, ChatMessageType.TRADEREQ, ChatMessageType.TRADE, ChatMessageType.CHALREQ_TRADE), TRADE_GROUP("Trade:</col> Show none", WidgetInfo.CHATBOX_TAB_TRADE,
ChatMessageType.TRADE_SENT, ChatMessageType.TRADEREQ, ChatMessageType.TRADE, ChatMessageType.CHALREQ_TRADE,
ChatMessageType.CLAN_GIM_CHAT, ChatMessageType.CLAN_GIM_MESSAGE),
; ;
private static final Map<Integer, ChatboxTab> TAB_MESSAGE_TYPES; private static final Map<Integer, ChatboxTab> TAB_MESSAGE_TYPES;
private final String name;
@Nullable @Nullable
private final String after; private final String after;
private final int widgetId; private final int widgetId;
private final ChatMessageType[] messageTypes; private final ChatMessageType[] messageTypes;
ChatboxTab(String name, String after, WidgetInfo widgetId, ChatMessageType... messageTypes) ChatboxTab(String after, WidgetInfo widgetId, ChatMessageType... messageTypes)
{ {
this.name = name;
this.after = after; this.after = after;
this.widgetId = widgetId.getId(); this.widgetId = widgetId.getId();
this.messageTypes = messageTypes; this.messageTypes = messageTypes;

View File

@@ -211,6 +211,7 @@ public class ChatNotificationsPlugin extends Plugin
case FRIENDSCHAT: case FRIENDSCHAT:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
case AUTOTYPER: case AUTOTYPER:
case MODAUTOTYPER: case MODAUTOTYPER:
if (client.getLocalPlayer() != null && Text.toJagexName(Text.removeTags(chatMessage.getName())).equals(client.getLocalPlayer().getName())) if (client.getLocalPlayer() != null && Text.toJagexName(Text.removeTags(chatMessage.getName())).equals(client.getLocalPlayer().getName()))

View File

@@ -25,8 +25,10 @@
package net.runelite.client.plugins.config; package net.runelite.client.plugins.config;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain; import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.BorderLayout; import java.awt.BorderLayout;
@@ -48,9 +50,12 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.inject.Inject; import javax.inject.Inject;
@@ -62,6 +67,7 @@ import javax.swing.JCheckBox;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import javax.swing.JFormattedTextField; import javax.swing.JFormattedTextField;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
@@ -72,6 +78,8 @@ import javax.swing.JSlider;
import javax.swing.JSpinner; import javax.swing.JSpinner;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants; import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerModel; import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel; import javax.swing.SpinnerNumberModel;
@@ -124,6 +132,7 @@ import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.LinkBrowser; import net.runelite.client.util.LinkBrowser;
import net.runelite.client.util.SwingUtil; import net.runelite.client.util.SwingUtil;
import net.runelite.client.util.Text; import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
@Slf4j @Slf4j
class ConfigPanel extends PluginPanel class ConfigPanel extends PluginPanel
@@ -464,434 +473,55 @@ class ConfigPanel extends PluginPanel
item.add(configEntryName, BorderLayout.CENTER); item.add(configEntryName, BorderLayout.CENTER);
item.setName(cid.getItem().keyName()); item.setName(cid.getItem().keyName());
if (cid.getType() == Button.class)
{
try
{
ConfigItem cidItem = cid.getItem();
JButton button = new JButton(cidItem.name());
button.addActionListener((e) ->
{
ConfigButtonClicked event = new ConfigButtonClicked();
event.setGroup(cd.getGroup().value());
event.setKey(cid.getItem().keyName());
eventBus.post(event);
});
item.add(button);
}
catch (Exception ex)
{
log.error("Adding action listener failed: {}", ex.getMessage());
ex.printStackTrace();
}
}
if (cid.getType() == boolean.class) if (cid.getType() == boolean.class)
{ {
JCheckBox checkbox = new ToggleButton(); item.add(createCheckbox(cd, cid), BorderLayout.EAST);
checkbox.setPreferredSize(new Dimension(26, 25));
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())));
checkbox.addActionListener(ae -> changeConfiguration(checkbox, cd, cid));
item.add(checkbox, BorderLayout.EAST);
} }
else if (cid.getType() == int.class)
if (cid.getType().isAssignableFrom(Consumer.class))
{ {
item.remove(configEntryName); item.add(createIntSpinner(cd, cid), BorderLayout.EAST);
JButton button = new JButton(cid.getItem().name());
button.addActionListener((e) ->
{
log.debug("Running consumer: {}.{}", cd.getGroup().value(), cid.getItem().keyName());
configManager.getConsumer(cd.getGroup().value(), cid.getItem().keyName()).accept(pluginConfig.getPlugin());
});
item.add(button, BorderLayout.CENTER);
} }
if (cid.getType() == int.class)
{
int value = Integer.parseInt(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
Units units = cid.getUnits();
Range range = cid.getRange();
int min = 0, max = Integer.MAX_VALUE;
if (range != null)
{
min = range.min();
max = range.max();
}
// Config may previously have been out of range
value = Ints.constrainToRange(value, min, max);
if (max < Integer.MAX_VALUE)
{
JLabel sliderValueLabel = new JLabel();
JSlider slider = new JSlider(min, max, value);
slider.setBackground(ColorScheme.DARK_GRAY_COLOR);
if (units != null)
{
sliderValueLabel.setText(slider.getValue() + units.value());
}
else
{
sliderValueLabel.setText(String.valueOf(slider.getValue()));
}
slider.setPreferredSize(new Dimension(80, 25));
slider.addChangeListener((l) ->
{
if (units != null)
{
sliderValueLabel.setText(slider.getValue() + units.value());
}
else
{
sliderValueLabel.setText(String.valueOf(slider.getValue()));
}
if (!slider.getValueIsAdjusting())
{
changeConfiguration(slider, cd, cid);
}
}
);
SpinnerModel model = new SpinnerNumberModel(value, min, max, 1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(SPINNER_FIELD_WIDTH);
spinner.setUI(new BasicSpinnerUI()
{
protected Component createNextButton()
{
return null;
}
protected Component createPreviousButton()
{
return null;
}
});
JPanel subPanel = new JPanel();
subPanel.setPreferredSize(new Dimension(110, 25));
subPanel.setLayout(new BorderLayout());
spinner.addChangeListener((ce) ->
{
changeConfiguration(spinner, cd, cid);
if (units != null)
{
sliderValueLabel.setText(spinner.getValue() + units.value());
}
else
{
sliderValueLabel.setText(String.valueOf(spinner.getValue()));
}
slider.setValue((Integer) spinner.getValue());
subPanel.add(sliderValueLabel, BorderLayout.WEST);
subPanel.add(slider, BorderLayout.EAST);
subPanel.remove(spinner);
validate();
repaint();
});
sliderValueLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
spinner.setValue(slider.getValue());
subPanel.remove(sliderValueLabel);
subPanel.remove(slider);
subPanel.add(spinner, BorderLayout.EAST);
validate();
repaint();
final JTextField tf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
tf.requestFocusInWindow();
SwingUtilities.invokeLater(tf::selectAll);
}
});
subPanel.add(sliderValueLabel, BorderLayout.WEST);
subPanel.add(slider, BorderLayout.EAST);
item.add(subPanel, BorderLayout.EAST);
}
else
{
SpinnerModel model = new SpinnerNumberModel(value, min, max, 1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(SPINNER_FIELD_WIDTH);
spinner.addChangeListener(ce -> changeConfiguration(spinner, cd, cid));
if (units != null)
{
spinnerTextField.setFormatterFactory(new UnitFormatterFactory(units));
}
item.add(spinner, BorderLayout.EAST);
}
}
else if (cid.getType() == double.class) else if (cid.getType() == double.class)
{ {
double value = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName(), double.class); item.add(createDoubleSpinner(cd, cid), BorderLayout.EAST);
SpinnerModel model = new SpinnerNumberModel(value, 0, Double.MAX_VALUE, 0.1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(SPINNER_FIELD_WIDTH);
spinner.addChangeListener(ce -> changeConfiguration(spinner, cd, cid));
item.add(spinner, BorderLayout.EAST);
} }
else if (cid.getType() == String.class)
if (cid.getType() == String.class)
{ {
JTextComponent textField; item.add(createTextField(cd, cid), BorderLayout.SOUTH);
if (cid.getItem().secret())
{
textField = new JPasswordField();
}
else
{
final JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textField = textArea;
}
textField.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
textField.setText(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
textField.addFocusListener(new FocusAdapter()
{
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(textField, cd, cid);
}
});
if (cid.getItem().parse())
{
JLabel parsingLabel = new JLabel();
parsingLabel.setHorizontalAlignment(SwingConstants.CENTER);
parsingLabel.setPreferredSize(new Dimension(PANEL_WIDTH, 15));
DeferredDocumentChangedListener listener = new DeferredDocumentChangedListener();
listener.addChangeListener(e ->
{
if (cid.getItem().parse())
{
parseLabel(cid.getItem(), parsingLabel, textField.getText());
}
});
textField.getDocument().addDocumentListener(listener);
item.add(configEntryName, BorderLayout.NORTH);
item.add(textField, BorderLayout.CENTER);
parseLabel(cid.getItem(), parsingLabel, textField.getText());
item.add(parsingLabel, BorderLayout.SOUTH);
}
else
{
item.add(textField, BorderLayout.SOUTH);
}
} }
else if (cid.getType() == Color.class)
if (cid.getType() == Color.class)
{ {
Color existing = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName(), Color.class); item.add(createColorPicker(cd, cid), BorderLayout.EAST);
ColorJButton colorPickerBtn;
boolean alphaHidden = cid.getAlpha() == null;
if (existing == null)
{
colorPickerBtn = new ColorJButton("Pick a color", Color.BLACK);
}
else
{
String colorHex = "#" + (alphaHidden ? ColorUtil.colorToHexCode(existing) : ColorUtil.colorToAlphaHexCode(existing)).toUpperCase();
colorPickerBtn = new ColorJButton(colorHex, existing);
}
colorPickerBtn.setFocusable(false);
colorPickerBtn.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
RuneliteColorPicker colorPicker = colorPickerManager.create(
SwingUtilities.windowForComponent(ConfigPanel.this),
colorPickerBtn.getColor(),
cid.getItem().name(),
alphaHidden);
colorPicker.setLocation(getLocationOnScreen());
colorPicker.setOnColorChange(c ->
{
colorPickerBtn.setColor(c);
colorPickerBtn.setText("#" + (alphaHidden ? ColorUtil.colorToHexCode(c) : ColorUtil.colorToAlphaHexCode(c)).toUpperCase());
});
colorPicker.setOnClose(c -> changeConfiguration(colorPicker, cd, cid));
colorPicker.setVisible(true);
}
});
item.add(colorPickerBtn, BorderLayout.EAST);
} }
else if (cid.getType() == Dimension.class)
if (cid.getType() == Dimension.class)
{ {
JPanel dimensionPanel = new JPanel(); item.add(createDimension(cd, cid), BorderLayout.EAST);
dimensionPanel.setLayout(new BorderLayout());
String str = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName());
String[] splitStr = str.split("x");
int width = Integer.parseInt(splitStr[0]);
int height = Integer.parseInt(splitStr[1]);
SpinnerModel widthModel = new SpinnerNumberModel(width, 0, Integer.MAX_VALUE, 1);
JSpinner widthSpinner = new JSpinner(widthModel);
Component widthEditor = widthSpinner.getEditor();
JFormattedTextField widthSpinnerTextField = ((JSpinner.DefaultEditor) widthEditor).getTextField();
widthSpinnerTextField.setColumns(4);
SpinnerModel heightModel = new SpinnerNumberModel(height, 0, Integer.MAX_VALUE, 1);
JSpinner heightSpinner = new JSpinner(heightModel);
Component heightEditor = heightSpinner.getEditor();
JFormattedTextField heightSpinnerTextField = ((JSpinner.DefaultEditor) heightEditor).getTextField();
heightSpinnerTextField.setColumns(4);
ChangeListener listener = e ->
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue());
widthSpinner.addChangeListener(listener);
heightSpinner.addChangeListener(listener);
dimensionPanel.add(widthSpinner, BorderLayout.WEST);
dimensionPanel.add(new JLabel(" x "), BorderLayout.CENTER);
dimensionPanel.add(heightSpinner, BorderLayout.EAST);
item.add(dimensionPanel, BorderLayout.EAST);
} }
else if (cid.getType() instanceof Class && ((Class<?>) cid.getType()).isEnum())
if (cid.getType().isEnum())
{ {
Class<? extends Enum> type = (Class<? extends Enum>) cid.getType(); item.add(createComboBox(cd, cid), BorderLayout.EAST);
JComboBox<Enum<?>> box = new JComboBox<Enum<?>>(type.getEnumConstants()); // NOPMD: UseDiamondOperator
// set renderer prior to calling box.getPreferredSize(), since it will invoke the renderer
// to build components for each combobox element in order to compute the display size of the
// combobox
box.setRenderer(new ComboBoxListRenderer<>());
box.setPreferredSize(new Dimension(box.getPreferredSize().width, 25));
box.setForeground(Color.WHITE);
box.setFocusable(false);
try
{
Enum<?> selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
box.setSelectedItem(selectedItem);
box.setToolTipText(Text.titleCase(selectedItem));
}
catch (IllegalArgumentException ex)
{
log.debug("invalid seleced item", ex);
}
box.addItemListener(e ->
{
if (e.getStateChange() == ItemEvent.SELECTED)
{
changeConfiguration(box, cd, cid);
box.setToolTipText(Text.titleCase((Enum<?>) box.getSelectedItem()));
}
});
item.add(box, BorderLayout.EAST);
} }
else if (cid.getType() == Keybind.class || cid.getType() == ModifierlessKeybind.class)
if (cid.getType() == Keybind.class || cid.getType() == ModifierlessKeybind.class)
{ {
Keybind startingValue = configManager.getConfiguration(cd.getGroup().value(), item.add(createKeybind(cd, cid), BorderLayout.EAST);
cid.getItem().keyName(),
(Class<? extends Keybind>) cid.getType());
HotkeyButton button = new HotkeyButton(startingValue, cid.getType() == ModifierlessKeybind.class);
button.addFocusListener(new FocusAdapter()
{
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(button, cd, cid);
}
});
item.add(button, BorderLayout.EAST);
} }
else if (cid.getType() instanceof ParameterizedType)
if (cid.getType() == EnumSet.class)
{ {
Class enumType = cid.getItem().enumClass(); ParameterizedType parameterizedType = (ParameterizedType) cid.getType();
if (parameterizedType.getRawType() == Set.class)
EnumSet enumSet = configManager.getConfiguration(cd.getGroup().value(),
cid.getItem().keyName(), EnumSet.class);
if (enumSet == null || enumSet.contains(null))
{ {
enumSet = EnumSet.noneOf(enumType); item.add(createList(cd, cid), BorderLayout.EAST);
} }
JPanel enumsetLayout = new JPanel(new GridLayout(0, 2));
List<JCheckBox> jcheckboxes = new ArrayList<>();
for (Object obj : enumType.getEnumConstants())
{
String option = String.valueOf(obj).toLowerCase().replace("_", " ");
JCheckBox checkbox = new ToggleButton(option);
checkbox.setBackground(ColorScheme.DARK_GRAY_COLOR);
checkbox.setSelected(enumSet.contains(obj));
jcheckboxes.add(checkbox);
enumsetLayout.add(checkbox);
}
jcheckboxes.forEach(checkbox -> checkbox.addActionListener(ae -> changeConfiguration(jcheckboxes, cd, cid)));
item.add(enumsetLayout, BorderLayout.SOUTH);
} }
JPanel section = sectionWidgets.get(cid.getItem().section()); JPanel section = sectionWidgets.get(cid.getItem().section());
JPanel title = titleWidgets.get(cid.getItem().title()); if (section == null)
if (section != null)
{ {
section.add(item); topLevelPanels.put(cid, item);
}
else if (title != null)
{
title.add(item);
} }
else else
{ {
topLevelPanels.put(cid, item); section.add(item);
} }
} }
@@ -927,6 +557,251 @@ class ConfigPanel extends PluginPanel
revalidate(); revalidate();
} }
private JCheckBox createCheckbox(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
JCheckBox checkbox = new JCheckBox();
checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR);
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())));
checkbox.addActionListener(ae -> changeConfiguration(checkbox, cd, cid));
return checkbox;
}
private JSpinner createIntSpinner(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
int value = Integer.parseInt(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
Range range = cid.getRange();
int min = 0, max = Integer.MAX_VALUE;
if (range != null)
{
min = range.min();
max = range.max();
}
// Config may previously have been out of range
value = Ints.constrainToRange(value, min, max);
SpinnerModel model = new SpinnerNumberModel(value, min, max, 1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(SPINNER_FIELD_WIDTH);
spinner.addChangeListener(ce -> changeConfiguration(spinner, cd, cid));
Units units = cid.getUnits();
if (units != null)
{
spinnerTextField.setFormatterFactory(new UnitFormatterFactory(units));
}
return spinner;
}
private JSpinner createDoubleSpinner(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
double value = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName(), double.class);
SpinnerModel model = new SpinnerNumberModel(value, 0, Double.MAX_VALUE, 0.1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(SPINNER_FIELD_WIDTH);
spinner.addChangeListener(ce -> changeConfiguration(spinner, cd, cid));
return spinner;
}
private JTextComponent createTextField(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
JTextComponent textField;
if (cid.getItem().secret())
{
textField = new JPasswordField();
}
else
{
final JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textField = textArea;
}
textField.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
textField.setText(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
textField.addFocusListener(new FocusAdapter()
{
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(textField, cd, cid);
}
});
return textField;
}
private ColorJButton createColorPicker(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
Color existing = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName(), Color.class);
ColorJButton colorPickerBtn;
boolean alphaHidden = cid.getAlpha() == null;
if (existing == null)
{
colorPickerBtn = new ColorJButton("Pick a color", Color.BLACK);
}
else
{
String colorHex = "#" + (alphaHidden ? ColorUtil.colorToHexCode(existing) : ColorUtil.colorToAlphaHexCode(existing)).toUpperCase();
colorPickerBtn = new ColorJButton(colorHex, existing);
}
colorPickerBtn.setFocusable(false);
colorPickerBtn.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
RuneliteColorPicker colorPicker = colorPickerManager.create(
SwingUtilities.windowForComponent(ConfigPanel.this),
colorPickerBtn.getColor(),
cid.getItem().name(),
alphaHidden);
colorPicker.setLocation(getLocationOnScreen());
colorPicker.setOnColorChange(c ->
{
colorPickerBtn.setColor(c);
colorPickerBtn.setText("#" + (alphaHidden ? ColorUtil.colorToHexCode(c) : ColorUtil.colorToAlphaHexCode(c)).toUpperCase());
});
colorPicker.setOnClose(c -> changeConfiguration(colorPicker, cd, cid));
colorPicker.setVisible(true);
}
});
return colorPickerBtn;
}
private JPanel createDimension(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
JPanel dimensionPanel = new JPanel();
dimensionPanel.setLayout(new BorderLayout());
String str = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName());
String[] splitStr = str.split("x");
int width = Integer.parseInt(splitStr[0]);
int height = Integer.parseInt(splitStr[1]);
SpinnerModel widthModel = new SpinnerNumberModel(width, 0, Integer.MAX_VALUE, 1);
JSpinner widthSpinner = new JSpinner(widthModel);
Component widthEditor = widthSpinner.getEditor();
JFormattedTextField widthSpinnerTextField = ((JSpinner.DefaultEditor) widthEditor).getTextField();
widthSpinnerTextField.setColumns(4);
SpinnerModel heightModel = new SpinnerNumberModel(height, 0, Integer.MAX_VALUE, 1);
JSpinner heightSpinner = new JSpinner(heightModel);
Component heightEditor = heightSpinner.getEditor();
JFormattedTextField heightSpinnerTextField = ((JSpinner.DefaultEditor) heightEditor).getTextField();
heightSpinnerTextField.setColumns(4);
ChangeListener listener = e ->
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue());
widthSpinner.addChangeListener(listener);
heightSpinner.addChangeListener(listener);
dimensionPanel.add(widthSpinner, BorderLayout.WEST);
dimensionPanel.add(new JLabel(" x "), BorderLayout.CENTER);
dimensionPanel.add(heightSpinner, BorderLayout.EAST);
return dimensionPanel;
}
private JComboBox<Enum<?>> createComboBox(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
Class<? extends Enum> type = (Class<? extends Enum>) cid.getType();
JComboBox<Enum<?>> box = new JComboBox<Enum<?>>(type.getEnumConstants()); // NOPMD: UseDiamondOperator
// set renderer prior to calling box.getPreferredSize(), since it will invoke the renderer
// to build components for each combobox element in order to compute the display size of the
// combobox
box.setRenderer(listCellRenderer);
box.setPreferredSize(new Dimension(box.getPreferredSize().width, 25));
box.setForeground(Color.WHITE);
box.setFocusable(false);
try
{
Enum<?> selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
box.setSelectedItem(selectedItem);
box.setToolTipText(Text.titleCase(selectedItem));
}
catch (IllegalArgumentException ex)
{
log.debug("invalid selected item", ex);
}
box.addItemListener(e ->
{
if (e.getStateChange() == ItemEvent.SELECTED)
{
changeConfiguration(box, cd, cid);
box.setToolTipText(Text.titleCase((Enum<?>) box.getSelectedItem()));
}
});
return box;
}
private HotkeyButton createKeybind(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
Keybind startingValue = configManager.getConfiguration(cd.getGroup().value(),
cid.getItem().keyName(),
(Class<? extends Keybind>) cid.getType());
HotkeyButton button = new HotkeyButton(startingValue, cid.getType() == ModifierlessKeybind.class);
button.addFocusListener(new FocusAdapter()
{
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(button, cd, cid);
}
});
return button;
}
private JList<Enum<?>> createList(ConfigDescriptor cd, ConfigItemDescriptor cid)
{
ParameterizedType parameterizedType = (ParameterizedType) cid.getType();
Class<? extends Enum> type = (Class<? extends Enum>) parameterizedType.getActualTypeArguments()[0];
Set<? extends Enum> set = configManager.getConfiguration(cd.getGroup().value(), null,
cid.getItem().keyName(), parameterizedType);
JList<Enum<?>> list = new JList<Enum<?>>(type.getEnumConstants()); // NOPMD: UseDiamondOperator
list.setCellRenderer(listCellRenderer);
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.VERTICAL);
list.setSelectedIndices(
MoreObjects.firstNonNull(set, Collections.emptySet())
.stream()
.mapToInt(e -> ArrayUtils.indexOf(type.getEnumConstants(), e))
.toArray());
list.addFocusListener(new FocusAdapter()
{
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(list, cd, cid);
}
});
return list;
}
private Boolean parse(ConfigItem item, String value) private Boolean parse(ConfigItem item, String value)
{ {
try try
@@ -1044,6 +919,13 @@ class ConfigPanel extends PluginPanel
HotkeyButton hotkeyButton = (HotkeyButton) component; HotkeyButton hotkeyButton = (HotkeyButton) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), hotkeyButton.getValue()); configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), hotkeyButton.getValue());
} }
else if (component instanceof JList)
{
JList<?> list = (JList<?>) component;
List<?> selectedValues = list.getSelectedValuesList();
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), Sets.newHashSet(selectedValues));
}
enableDisable(component, cid); enableDisable(component, cid);
rebuild(); rebuild();

View File

@@ -126,6 +126,7 @@ public class EmojiPlugin extends Plugin
case FRIENDSCHAT: case FRIENDSCHAT:
case CLAN_CHAT: case CLAN_CHAT:
case CLAN_GUEST_CHAT: case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
case PRIVATECHAT: case PRIVATECHAT:
case PRIVATECHATOUT: case PRIVATECHATOUT:
case MODPRIVATECHAT: case MODPRIVATECHAT:

View File

@@ -43,6 +43,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
@@ -145,10 +146,7 @@ public class HiscorePanel extends PluginPanel
this.nameAutocompleter = nameAutocompleter; this.nameAutocompleter = nameAutocompleter;
this.hiscoreClient = new HiscoreClient(okHttpClient); this.hiscoreClient = new HiscoreClient(okHttpClient);
// The layout seems to be ignoring the top margin and only gives it setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
// a 2-3 pixel margin, so I set the value to 18 to compensate
// TODO: Figure out why this layout is ignoring most of the top margin
setBorder(new EmptyBorder(18, 10, 0, 10));
setBackground(ColorScheme.DARK_GRAY_COLOR); setBackground(ColorScheme.DARK_GRAY_COLOR);
setLayout(new GridBagLayout()); setLayout(new GridBagLayout());

View File

@@ -188,7 +188,7 @@ public class HiscorePlugin extends Plugin
&& event.getMenuOption().equals(LOOKUP)) && event.getMenuOption().equals(LOOKUP))
{ {
final String target; final String target;
HiscoreEndpoint endpoint = HiscoreEndpoint.NORMAL; HiscoreEndpoint endpoint;
if (event.getMenuAction() == MenuAction.RUNELITE_PLAYER) if (event.getMenuAction() == MenuAction.RUNELITE_PLAYER)
{ {
// The player id is included in the event, so we can use that to get the player name, // The player id is included in the event, so we can use that to get the player name,
@@ -199,6 +199,7 @@ public class HiscorePlugin extends Plugin
return; return;
} }
endpoint = getWorldEndpoint();
target = player.getName(); target = player.getName();
} }
else else

View File

@@ -32,7 +32,7 @@ import java.awt.Image;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import javax.inject.Inject; import javax.inject.Inject;
import static net.runelite.api.widgets.WidgetID.GRAVESTONE_GROUP_ID; import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetItem; import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.WidgetItemOverlay; import net.runelite.client.ui.overlay.WidgetItemOverlay;
@@ -54,7 +54,12 @@ public class InventoryTagsOverlay extends WidgetItemOverlay
this.config = config; this.config = config;
showOnEquipment(); showOnEquipment();
showOnInventory(); showOnInventory();
showOnInterfaces(GRAVESTONE_GROUP_ID); showOnInterfaces(
WidgetID.CHAMBERS_OF_XERIC_STORAGE_UNIT_INVENTORY_GROUP_ID,
WidgetID.CHAMBERS_OF_XERIC_STORAGE_UNIT_PRIVATE_GROUP_ID,
WidgetID.CHAMBERS_OF_XERIC_STORAGE_UNIT_SHARED_GROUP_ID,
WidgetID.GRAVESTONE_GROUP_ID
);
fillCache = CacheBuilder.newBuilder() fillCache = CacheBuilder.newBuilder()
.concurrencyLevel(1) .concurrencyLevel(1)
.maximumSize(32) .maximumSize(32)

View File

@@ -113,6 +113,18 @@ public interface MenuEntrySwapperConfig extends Config
KALPHITE_CAVE, KALPHITE_CAVE,
} }
@ConfigItem(
position = -3,
keyName = "leftClickCustomization",
name = "Customizable left-click",
description = "Allows customization of left-clicks on items",
section = itemSection
)
default boolean leftClickCustomization()
{
return true;
}
@ConfigItem( @ConfigItem(
position = -2, position = -2,
keyName = "shiftClickCustomization", keyName = "shiftClickCustomization",

View File

@@ -29,6 +29,7 @@ package net.runelite.client.plugins.menuentryswapper;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import static com.google.common.base.Predicates.alwaysTrue; import static com.google.common.base.Predicates.alwaysTrue;
import static com.google.common.base.Predicates.equalTo; import static com.google.common.base.Predicates.equalTo;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
@@ -43,7 +44,6 @@ import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.ItemComposition; import net.runelite.api.ItemComposition;
@@ -88,28 +88,43 @@ public class MenuEntrySwapperPlugin extends Plugin
private static final String CONFIGURE = "Configure"; private static final String CONFIGURE = "Configure";
private static final String SAVE = "Save"; private static final String SAVE = "Save";
private static final String RESET = "Reset"; private static final String RESET = "Reset";
private static final String MENU_TARGET = "Shift-click"; private static final String LEFT_CLICK_MENU_TARGET = "Left-click";
private static final String SHIFT_CLICK_MENU_TARGET = "Shift-click";
private static final String SHIFTCLICK_CONFIG_GROUP = "shiftclick"; private static final String SHIFTCLICK_CONFIG_GROUP = "shiftclick";
private static final String ITEM_KEY_PREFIX = "item_"; private static final String ITEM_KEY_PREFIX = "item_";
private static final WidgetMenuOption FIXED_INVENTORY_TAB_CONFIGURE = new WidgetMenuOption(CONFIGURE, // Shift click
MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB); private static final WidgetMenuOption FIXED_INVENTORY_TAB_CONFIGURE_SC = new WidgetMenuOption(CONFIGURE,
SHIFT_CLICK_MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption FIXED_INVENTORY_TAB_SAVE_SC = new WidgetMenuOption(SAVE,
SHIFT_CLICK_MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption FIXED_INVENTORY_TAB_SAVE = new WidgetMenuOption(SAVE, private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_CONFIGURE_SC = new WidgetMenuOption(CONFIGURE,
MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB); SHIFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_SAVE_SC = new WidgetMenuOption(SAVE,
SHIFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_CONFIGURE = new WidgetMenuOption(CONFIGURE, private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE_SC = new WidgetMenuOption(CONFIGURE,
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB); SHIFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE_SC = new WidgetMenuOption(SAVE,
SHIFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_SAVE = new WidgetMenuOption(SAVE, // Left click
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB); private static final WidgetMenuOption FIXED_INVENTORY_TAB_CONFIGURE_LC = new WidgetMenuOption(CONFIGURE,
LEFT_CLICK_MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption FIXED_INVENTORY_TAB_SAVE_LC = new WidgetMenuOption(SAVE,
LEFT_CLICK_MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE = new WidgetMenuOption(CONFIGURE, private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_CONFIGURE_LC = new WidgetMenuOption(CONFIGURE,
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB); LEFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_SAVE_LC = new WidgetMenuOption(SAVE,
LEFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE = new WidgetMenuOption(SAVE, private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE_LC = new WidgetMenuOption(CONFIGURE,
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB); LEFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB);
private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE_LC = new WidgetMenuOption(SAVE,
LEFT_CLICK_MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB);
private static final Set<MenuAction> ITEM_MENU_TYPES = ImmutableSet.of( private static final Set<MenuAction> ITEM_MENU_TYPES = ImmutableSet.of(
MenuAction.ITEM_FIRST_OPTION, MenuAction.ITEM_FIRST_OPTION,
@@ -162,8 +177,8 @@ public class MenuEntrySwapperPlugin extends Plugin
@Inject @Inject
private ItemManager itemManager; private ItemManager itemManager;
@Getter
private boolean configuringShiftClick = false; private boolean configuringShiftClick = false;
private boolean configuringLeftClick = false;
private final Multimap<String, Swap> swaps = Multimaps.synchronizedSetMultimap(LinkedHashMultimap.create()); private final Multimap<String, Swap> swaps = Multimaps.synchronizedSetMultimap(LinkedHashMultimap.create());
private final ArrayListMultimap<String, Integer> optionIndexes = ArrayListMultimap.create(); private final ArrayListMultimap<String, Integer> optionIndexes = ArrayListMultimap.create();
@@ -177,11 +192,7 @@ public class MenuEntrySwapperPlugin extends Plugin
@Override @Override
public void startUp() public void startUp()
{ {
if (config.shiftClickCustomization()) enableCustomization();
{
enableCustomization();
}
setupSwaps(); setupSwaps();
} }
@@ -450,16 +461,10 @@ public class MenuEntrySwapperPlugin extends Plugin
@Subscribe @Subscribe
public void onConfigChanged(ConfigChanged event) public void onConfigChanged(ConfigChanged event)
{ {
if (event.getGroup().equals(MenuEntrySwapperConfig.GROUP) && event.getKey().equals("shiftClickCustomization")) if (event.getGroup().equals(MenuEntrySwapperConfig.GROUP)
&& (event.getKey().equals("shiftClickCustomization") || event.getKey().equals("leftClickCustomization")))
{ {
if (config.shiftClickCustomization()) enableCustomization();
{
enableCustomization();
}
else
{
disableCustomization();
}
} }
else if (event.getGroup().equals(SHIFTCLICK_CONFIG_GROUP) && event.getKey().startsWith(ITEM_KEY_PREFIX)) else if (event.getGroup().equals(SHIFTCLICK_CONFIG_GROUP) && event.getKey().startsWith(ITEM_KEY_PREFIX))
{ {
@@ -472,10 +477,10 @@ public class MenuEntrySwapperPlugin extends Plugin
client.getItemCompositionCache().reset(); client.getItemCompositionCache().reset();
} }
private Integer getSwapConfig(int itemId) private Integer getSwapConfig(boolean shift, int itemId)
{ {
itemId = ItemVariationMapping.map(itemId); itemId = ItemVariationMapping.map(itemId);
String config = configManager.getConfiguration(SHIFTCLICK_CONFIG_GROUP, ITEM_KEY_PREFIX + itemId); String config = configManager.getConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId);
if (config == null || config.isEmpty()) if (config == null || config.isEmpty())
{ {
return null; return null;
@@ -484,29 +489,29 @@ public class MenuEntrySwapperPlugin extends Plugin
return Integer.parseInt(config); return Integer.parseInt(config);
} }
private void setSwapConfig(int itemId, int index) private void setSwapConfig(boolean shift, int itemId, int index)
{ {
itemId = ItemVariationMapping.map(itemId); itemId = ItemVariationMapping.map(itemId);
configManager.setConfiguration(SHIFTCLICK_CONFIG_GROUP, ITEM_KEY_PREFIX + itemId, index); configManager.setConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId, index);
} }
private void unsetSwapConfig(int itemId) private void unsetSwapConfig(boolean shift, int itemId)
{ {
itemId = ItemVariationMapping.map(itemId); itemId = ItemVariationMapping.map(itemId);
configManager.unsetConfiguration(SHIFTCLICK_CONFIG_GROUP, ITEM_KEY_PREFIX + itemId); configManager.unsetConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId);
} }
private void enableCustomization() private void enableCustomization()
{ {
refreshShiftClickCustomizationMenus(); rebuildCustomizationMenus();
// set shift click action index on the item compositions // set shift click action index on the item compositions
clientThread.invoke(this::resetItemCompositionCache); clientThread.invoke(this::resetItemCompositionCache);
} }
private void disableCustomization() private void disableCustomization()
{ {
removeShiftClickCustomizationMenus(); removeCusomizationMenus();
configuringShiftClick = false; configuringShiftClick = configuringLeftClick = false;
// flush item compositions to reset the shift click action index // flush item compositions to reset the shift click action index
clientThread.invoke(this::resetItemCompositionCache); clientThread.invoke(this::resetItemCompositionCache);
} }
@@ -518,15 +523,21 @@ public class MenuEntrySwapperPlugin extends Plugin
|| event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB
|| event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB) || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB)
{ {
configuringShiftClick = event.getMenuOption().equals(CONFIGURE) && Text.removeTags(event.getMenuTarget()).equals(MENU_TARGET); String option = event.getMenuOption();
refreshShiftClickCustomizationMenus(); String target = Text.removeTags(event.getMenuTarget());
if ((option.equals(CONFIGURE) || option.equals(SAVE)) && (target.equals(LEFT_CLICK_MENU_TARGET) || target.equals(SHIFT_CLICK_MENU_TARGET)))
{
configuringShiftClick = option.equals(CONFIGURE) && target.equals(SHIFT_CLICK_MENU_TARGET);
configuringLeftClick = option.equals(CONFIGURE) && target.equals(LEFT_CLICK_MENU_TARGET);
rebuildCustomizationMenus();
}
} }
} }
@Subscribe @Subscribe
public void onMenuOpened(MenuOpened event) public void onMenuOpened(MenuOpened event)
{ {
if (!configuringShiftClick) if (!configuringShiftClick && !configuringLeftClick)
{ {
return; return;
} }
@@ -549,13 +560,41 @@ public class MenuEntrySwapperPlugin extends Plugin
return; return;
} }
ItemComposition itemComposition = itemManager.getItemComposition(itemId); MenuAction activeAction = MenuAction.ITEM_USE;
MenuAction shiftClickAction = MenuAction.ITEM_USE; final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
final int shiftClickActionIndex = itemComposition.getShiftClickActionIndex();
if (shiftClickActionIndex >= 0) if (configuringShiftClick)
{ {
shiftClickAction = MenuAction.of(MenuAction.ITEM_FIRST_OPTION.getId() + shiftClickActionIndex); // For shift-click read the active action off of the item composition, since it may be set by
// that even if we have no existing config for it
final int shiftClickActionIndex = itemComposition.getShiftClickActionIndex();
if (shiftClickActionIndex >= 0)
{
activeAction = MenuAction.of(MenuAction.ITEM_FIRST_OPTION.getId() + shiftClickActionIndex);
}
}
else
{
// The default left click on items is the highest priority action 0-2, and otherwise is use.
final String[] actions = itemComposition.getInventoryActions();
for (int i = 0; i <= 2; ++i)
{
if (!Strings.isNullOrEmpty(actions[i]))
{
activeAction = MenuAction.of(MenuAction.ITEM_FIRST_OPTION.getId() + i);
break;
}
}
// Apply left click action from configuration
Integer config = getSwapConfig(false, itemId);
if (config != null)
{
activeAction = config >= 0
? MenuAction.of(MenuAction.ITEM_FIRST_OPTION.getId() + config)
: MenuAction.ITEM_USE;
}
} }
MenuEntry[] entries = event.getMenuEntries(); MenuEntry[] entries = event.getMenuEntries();
@@ -568,7 +607,7 @@ public class MenuEntrySwapperPlugin extends Plugin
{ {
entry.setType(MenuAction.RUNELITE.getId()); entry.setType(MenuAction.RUNELITE.getId());
if (shiftClickAction == menuAction) if (activeAction == menuAction)
{ {
entry.setOption("* " + entry.getOption()); entry.setOption("* " + entry.getOption());
} }
@@ -577,7 +616,7 @@ public class MenuEntrySwapperPlugin extends Plugin
final MenuEntry resetShiftClickEntry = new MenuEntry(); final MenuEntry resetShiftClickEntry = new MenuEntry();
resetShiftClickEntry.setOption(RESET); resetShiftClickEntry.setOption(RESET);
resetShiftClickEntry.setTarget(MENU_TARGET); resetShiftClickEntry.setTarget(configuringShiftClick ? SHIFT_CLICK_MENU_TARGET : LEFT_CLICK_MENU_TARGET);
resetShiftClickEntry.setIdentifier(itemId); resetShiftClickEntry.setIdentifier(itemId);
resetShiftClickEntry.setParam1(widgetId); resetShiftClickEntry.setParam1(widgetId);
resetShiftClickEntry.setType(MenuAction.RUNELITE.getId()); resetShiftClickEntry.setType(MenuAction.RUNELITE.getId());
@@ -674,9 +713,14 @@ public class MenuEntrySwapperPlugin extends Plugin
String target = event.getMenuTarget(); String target = event.getMenuTarget();
ItemComposition itemComposition = itemManager.getItemComposition(itemId); ItemComposition itemComposition = itemManager.getItemComposition(itemId);
if (option.equals(RESET) && target.equals(MENU_TARGET)) if (option.equals(RESET) && target.equals(SHIFT_CLICK_MENU_TARGET))
{ {
unsetSwapConfig(itemId); unsetSwapConfig(true, itemId);
return;
}
if (option.equals(RESET) && target.equals(LEFT_CLICK_MENU_TARGET))
{
unsetSwapConfig(false, itemId);
return; return;
} }
@@ -687,7 +731,7 @@ public class MenuEntrySwapperPlugin extends Plugin
if (option.equals("Use")) //because "Use" is not in inventoryActions if (option.equals("Use")) //because "Use" is not in inventoryActions
{ {
setSwapConfig(itemId, -1); setSwapConfig(configuringShiftClick, itemId, -1);
} }
else else
{ {
@@ -697,14 +741,14 @@ public class MenuEntrySwapperPlugin extends Plugin
{ {
if (option.equals(inventoryActions[index])) if (option.equals(inventoryActions[index]))
{ {
setSwapConfig(itemId, index); setSwapConfig(configuringShiftClick, itemId, index);
break; break;
} }
} }
} }
} }
private void swapMenuEntry(int index, MenuEntry menuEntry) private void swapMenuEntry(MenuEntry[] menuEntries, int index, MenuEntry menuEntry)
{ {
final int eventId = menuEntry.getIdentifier(); final int eventId = menuEntry.getIdentifier();
final MenuAction menuAction = MenuAction.of(menuEntry.getType()); final MenuAction menuAction = MenuAction.of(menuEntry.getType());
@@ -712,6 +756,7 @@ public class MenuEntrySwapperPlugin extends Plugin
final String target = Text.removeTags(menuEntry.getTarget()).toLowerCase(); final String target = Text.removeTags(menuEntry.getTarget()).toLowerCase();
final NPC hintArrowNpc = client.getHintArrowNpc(); final NPC hintArrowNpc = client.getHintArrowNpc();
// Don't swap on hint arrow npcs, usually they need "Talk-to" for clues.
if (hintArrowNpc != null if (hintArrowNpc != null
&& hintArrowNpc.getIndex() == eventId && hintArrowNpc.getIndex() == eventId
&& NPC_MENU_TYPES.contains(menuAction)) && NPC_MENU_TYPES.contains(menuAction))
@@ -719,22 +764,23 @@ public class MenuEntrySwapperPlugin extends Plugin
return; return;
} }
if (shiftModifier() && (menuAction == MenuAction.ITEM_FIRST_OPTION final boolean itemOp = menuAction == MenuAction.ITEM_FIRST_OPTION
|| menuAction == MenuAction.ITEM_SECOND_OPTION || menuAction == MenuAction.ITEM_SECOND_OPTION
|| menuAction == MenuAction.ITEM_THIRD_OPTION || menuAction == MenuAction.ITEM_THIRD_OPTION
|| menuAction == MenuAction.ITEM_FOURTH_OPTION || menuAction == MenuAction.ITEM_FOURTH_OPTION
|| menuAction == MenuAction.ITEM_FIFTH_OPTION || menuAction == MenuAction.ITEM_FIFTH_OPTION
|| menuAction == MenuAction.ITEM_USE)) || menuAction == MenuAction.ITEM_USE;
if (shiftModifier() && itemOp)
{ {
// Special case use shift click due to items not actually containing a "Use" option, making // Special case use shift click due to items not actually containing a "Use" option, making
// the client unable to perform the swap itself. // the client unable to perform the swap itself.
if (config.shiftClickCustomization() && !option.equals("use")) if (config.shiftClickCustomization() && !option.equals("use"))
{ {
Integer customOption = getSwapConfig(eventId); Integer customOption = getSwapConfig(true, eventId);
if (customOption != null && customOption == -1) if (customOption != null && customOption == -1)
{ {
swap("use", target, index, true); swap(menuEntries, "use", target, index, true);
} }
} }
@@ -743,12 +789,31 @@ public class MenuEntrySwapperPlugin extends Plugin
return; return;
} }
// Custom left-click item swap
if (itemOp)
{
Integer swapIndex = getSwapConfig(false, eventId);
if (swapIndex != null && index < menuEntries.length - 1)
{
MenuAction swapAction = swapIndex >= 0
? MenuAction.of(MenuAction.ITEM_FIRST_OPTION.getId() + swapIndex)
: MenuAction.ITEM_USE;
if (menuAction == swapAction)
{
swap(optionIndexes, menuEntries, index, menuEntries.length - 1);
return;
}
}
}
// Built-in swaps
Collection<Swap> swaps = this.swaps.get(option); Collection<Swap> swaps = this.swaps.get(option);
for (Swap swap : swaps) for (Swap swap : swaps)
{ {
if (swap.getTargetPredicate().test(target) && swap.getEnabled().get()) if (swap.getTargetPredicate().test(target) && swap.getEnabled().get())
{ {
if (swap(swap.getSwappedOption(), target, index, swap.isStrict())) if (swap(menuEntries, swap.getSwappedOption(), target, index, swap.isStrict()))
{ {
break; break;
} }
@@ -781,7 +846,7 @@ public class MenuEntrySwapperPlugin extends Plugin
idx = 0; idx = 0;
for (MenuEntry entry : menuEntries) for (MenuEntry entry : menuEntries)
{ {
swapMenuEntry(idx++, entry); swapMenuEntry(menuEntries, idx++, entry);
} }
} }
@@ -796,7 +861,7 @@ public class MenuEntrySwapperPlugin extends Plugin
} }
ItemComposition itemComposition = event.getItemComposition(); ItemComposition itemComposition = event.getItemComposition();
Integer option = getSwapConfig(itemComposition.getId()); Integer option = getSwapConfig(true, itemComposition.getId());
if (option != null) if (option != null)
{ {
@@ -804,10 +869,8 @@ public class MenuEntrySwapperPlugin extends Plugin
} }
} }
private boolean swap(String option, String target, int index, boolean strict) private boolean swap(MenuEntry[] menuEntries, String option, String target, int index, boolean strict)
{ {
MenuEntry[] menuEntries = client.getMenuEntries();
// find option to swap with // find option to swap with
int optionIdx = findIndex(menuEntries, index, option, target, strict); int optionIdx = findIndex(menuEntries, index, option, target, strict);
@@ -892,30 +955,55 @@ public class MenuEntrySwapperPlugin extends Plugin
list.add(idx < 0 ? -idx - 1 : idx, value); list.add(idx < 0 ? -idx - 1 : idx, value);
} }
private void removeShiftClickCustomizationMenus() private void removeCusomizationMenus()
{ {
menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE); // Shift click
menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE); menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE_SC);
menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE); menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE_SC);
menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE); menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE_SC);
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE); menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE_SC);
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE); menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE_SC);
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE_SC);
// Left click
menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE_LC);
menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE_LC);
menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE_LC);
menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE_LC);
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE_LC);
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE_LC);
} }
private void refreshShiftClickCustomizationMenus() private void rebuildCustomizationMenus()
{ {
removeShiftClickCustomizationMenus(); removeCusomizationMenus();
if (configuringShiftClick) if (configuringLeftClick)
{ {
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE); menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE_LC);
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE); menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE_LC);
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE); menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE_LC);
}
else if (configuringShiftClick)
{
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE_SC);
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE_SC);
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE_SC);
} }
else else
{ {
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE); // Left click
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE); if (config.leftClickCustomization())
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE); {
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE_LC);
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE_LC);
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE_LC);
}
// Shift click
if (config.shiftClickCustomization())
{
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE_SC);
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE_SC);
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE_SC);
}
} }
} }

View File

@@ -24,16 +24,13 @@
*/ */
package net.runelite.client.plugins.worldhopper; package net.runelite.client.plugins.worldhopper;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor;
import net.runelite.http.api.worlds.WorldRegion; import net.runelite.http.api.worlds.WorldRegion;
@NoArgsConstructor @RequiredArgsConstructor
@AllArgsConstructor enum RegionFilterMode
public enum RegionFilterMode
{ {
NONE,
AUSTRALIA(WorldRegion.AUSTRALIA), AUSTRALIA(WorldRegion.AUSTRALIA),
GERMANY(WorldRegion.GERMANY), GERMANY(WorldRegion.GERMANY),
UNITED_KINGDOM(WorldRegion.UNITED_KINGDOM) UNITED_KINGDOM(WorldRegion.UNITED_KINGDOM)
@@ -54,5 +51,22 @@ public enum RegionFilterMode
}; };
@Getter @Getter
private WorldRegion region; private final WorldRegion region;
static RegionFilterMode of(WorldRegion region)
{
switch (region)
{
case UNITED_STATES_OF_AMERICA:
return UNITED_STATES;
case UNITED_KINGDOM:
return UNITED_KINGDOM;
case AUSTRALIA:
return AUSTRALIA;
case GERMANY:
return GERMANY;
default:
throw new IllegalStateException();
}
}
} }

View File

@@ -27,6 +27,8 @@ package net.runelite.client.plugins.worldhopper;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.Collections;
import java.util.Set;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
@@ -76,9 +78,9 @@ public interface WorldHopperConfig extends Config
description = "Limit quick-hopping to worlds of a specific region", description = "Limit quick-hopping to worlds of a specific region",
position = 3 position = 3
) )
default RegionFilterMode quickHopRegionFilter() default Set<RegionFilterMode> quickHopRegionFilter()
{ {
return RegionFilterMode.NONE; return Collections.emptySet();
} }
@ConfigItem( @ConfigItem(
@@ -142,9 +144,9 @@ public interface WorldHopperConfig extends Config
description = "Restrict sidebar worlds to one region", description = "Restrict sidebar worlds to one region",
position = 8 position = 8
) )
default RegionFilterMode regionFilter() default Set<RegionFilterMode> regionFilter()
{ {
return RegionFilterMode.NONE; return Collections.emptySet();
} }
@ConfigItem( @ConfigItem(

View File

@@ -36,6 +36,7 @@ import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
@@ -533,6 +534,8 @@ public class WorldHopperPlugin extends Plugin
int worldIdx = worlds.indexOf(currentWorld); int worldIdx = worlds.indexOf(currentWorld);
int totalLevel = client.getTotalLevel(); int totalLevel = client.getTotalLevel();
final Set<RegionFilterMode> regionFilter = config.quickHopRegionFilter();
World world; World world;
do do
{ {
@@ -564,7 +567,7 @@ public class WorldHopperPlugin extends Plugin
world = worlds.get(worldIdx); world = worlds.get(worldIdx);
// Check world region if filter is enabled // Check world region if filter is enabled
if (config.quickHopRegionFilter() != RegionFilterMode.NONE && world.getRegion() != config.quickHopRegionFilter().getRegion()) if (!regionFilter.isEmpty() && !regionFilter.contains(RegionFilterMode.of(world.getRegion())))
{ {
continue; continue;
} }

View File

@@ -34,6 +34,7 @@ import java.awt.event.MouseEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@@ -68,7 +69,7 @@ class WorldSwitcherPanel extends PluginPanel
@Setter(AccessLevel.PACKAGE) @Setter(AccessLevel.PACKAGE)
private SubscriptionFilterMode subscriptionFilterMode; private SubscriptionFilterMode subscriptionFilterMode;
@Setter(AccessLevel.PACKAGE) @Setter(AccessLevel.PACKAGE)
private RegionFilterMode regionFilterMode; private Set<RegionFilterMode> regionFilterMode;
WorldSwitcherPanel(WorldHopperPlugin plugin) WorldSwitcherPanel(WorldHopperPlugin plugin)
{ {
@@ -249,7 +250,7 @@ class WorldSwitcherPanel extends PluginPanel
break; break;
} }
if (regionFilterMode.getRegion() != null && !regionFilterMode.getRegion().equals(world.getRegion())) if (!regionFilterMode.isEmpty() && !regionFilterMode.contains(RegionFilterMode.of(world.getRegion())))
{ {
continue; continue;
} }

View File

@@ -59,9 +59,9 @@ public final class ComboBoxListRenderer<T> extends JLabel implements ListCellRen
setBorder(new EmptyBorder(5, 5, 5, 0)); setBorder(new EmptyBorder(5, 5, 5, 0));
String text; String text;
if (o instanceof Enum) if (o instanceof Enum<?>)
{ {
text = Text.titleCase((Enum) o); text = Text.titleCase((Enum<?>) o);
} }
else else
{ {

View File

@@ -67,6 +67,10 @@ public class ObsidianSkin extends SubstanceSkin
activeScheme, enabledScheme, enabledScheme); activeScheme, enabledScheme, enabledScheme);
// Selected and rollover
defaultSchemeBundle.registerHighlightColorScheme(schemes.get("RuneLite Highlight"),
ComponentState.SELECTED, ComponentState.ROLLOVER_SELECTED, ComponentState.ROLLOVER_UNSELECTED);
// borders // borders
final SubstanceColorScheme borderDisabledSelectedScheme = schemes final SubstanceColorScheme borderDisabledSelectedScheme = schemes
.get("RuneLite Selected Disabled Border"); .get("RuneLite Selected Disabled Border");

View File

@@ -89,14 +89,14 @@ RuneLite Mark Active {
} }
RuneLite Highlight { RuneLite Highlight {
kind=Light kind=Dark
colorUltraLight=#C6C6C6 colorUltraLight=#525252
colorExtraLight=#C6C6C6 colorExtraLight=#525252
colorLight=#C6C6C6 colorLight=#525252
colorMid=#C6C6C6 colorMid=#525252
colorDark=#C6C6C6 colorDark=#525252
colorUltraDark=#C6C6C6 colorUltraDark=#525252
colorForeground=#191919 colorForeground=#FFFFFF
} }
RuneLite Watermark { RuneLite Watermark {

View File

@@ -440,11 +440,17 @@ LABEL391:
jump LABEL1721 jump LABEL1721
LABEL405: LABEL405:
iload 10 ; message uid iload 10 ; message uid
sload 17 ; message channel
sload 16 ; message name
sload 18 ; message
sload 21 ; message timestamp sload 21 ; message timestamp
sconst "chatMessageBuilding" sconst "chatMessageBuilding"
runelite_callback runelite_callback
pop_int ; pop uid pop_int ; pop uid
sstore 21 ; message timestamp sstore 21 ; message timestamp
sstore 18 ; message
sstore 16 ; message name
sstore 17 ; message channel
iload 11 iload 11
switch switch
1: LABEL408 1: LABEL408

View File

@@ -1 +1 @@
BF6EEA4353A596E6389BC0CCDB654CC28D11E809F92A59C0301557F6185690CD 6FB26238E2041A40DE52A7E797AD54BF8633BE93FD3B0C244F1313B53CC0A922

View File

@@ -33,71 +33,101 @@ LABEL23:
iload 3 iload 3
iconst -1 iconst -1
if_icmpne LABEL27 if_icmpne LABEL27
jump LABEL33 jump LABEL60
LABEL27: LABEL27:
iload 3 iload 3
iconst 4 iconst 4
if_icmple LABEL31 if_icmple LABEL31
jump LABEL33 jump LABEL60
LABEL31: LABEL31:
iload 3
get_varc_int 945
if_icmpne LABEL35
jump LABEL60
LABEL35:
iload 3 iload 3
set_varc_int 945 set_varc_int 945
LABEL33: iload 3
iconst 0
if_icmpne LABEL41
jump LABEL51
LABEL41:
sconst "Your chatbox mode is now set to "
iconst 105
iconst 115
iconst 4070
iload 3
enum
sconst " chat, to reset your mode type /@p"
join_string 3
mes
jump LABEL60
LABEL51:
sconst "Your chatbox mode has been reset to "
iconst 105
iconst 115
iconst 4070
iload 3
enum
sconst " chat."
join_string 3
mes
LABEL60:
iload 2 iload 2
iconst 1 iconst 1
if_icmpeq LABEL37 if_icmpeq LABEL64
jump LABEL75 jump LABEL102
LABEL37: LABEL64:
get_varc_int 945 get_varc_int 945
switch switch
1: LABEL40 1: LABEL67
2: LABEL61 2: LABEL88
3: LABEL66 3: LABEL93
4: LABEL71 4: LABEL98
jump LABEL75 jump LABEL102
LABEL40: LABEL67:
iconst 2 iconst 2
istore 0 istore 0
sload 0 sload 0
string_length string_length
iconst 0 iconst 0
if_icmpgt LABEL47 if_icmpgt LABEL74
jump LABEL60 jump LABEL87
LABEL47: LABEL74:
sload 0 sload 0
iconst 0 iconst 0
iconst 1 iconst 1
substring substring
sconst "/" sconst "/"
compare compare
iconst 1 iconst 0 ;
if_icmpeq LABEL56 if_icmpne LABEL83
jump LABEL60 jump LABEL87
LABEL56: LABEL83:
sconst "/" sconst "/"
sload 0 sload 0
append append
sstore 0 sstore 0
LABEL60: LABEL87:
jump LABEL75 jump LABEL102
LABEL61: LABEL88:
iconst 3 iconst 3
iconst 0 iconst 0
istore 1 istore 1
istore 0 istore 0
jump LABEL75 jump LABEL102
LABEL66: LABEL93:
iconst 4 iconst 4
iconst 0 iconst 0
istore 1 istore 1
istore 0 istore 0
jump LABEL75 jump LABEL102
LABEL71: LABEL98:
iconst 3 iconst 3
iconst 1 iconst 1
istore 1 istore 1
istore 0 istore 0
LABEL75: LABEL102:
sload 0 ; load input sload 0 ; load input
iload 0 ; load chat type iload 0 ; load chat type
iload 1 ; load clan target iload 1 ; load clan target
@@ -114,46 +144,74 @@ CONTINUE:
sstore 1 sstore 1
iload 0 iload 0
iconst 2 iconst 2
if_icmpeq LABEL87 if_icmpeq LABEL114
iload 0 iload 0
iconst 3 iconst 3
if_icmpeq LABEL87 if_icmpeq LABEL114
iload 0 iload 0
iconst 4 iconst 4
if_icmpeq LABEL87 if_icmpeq LABEL114
jump LABEL109 jump LABEL154
LABEL87: LABEL114:
sload 0 sload 0
invoke 5501 invoke 5501
iconst 1 iconst 1
if_icmpeq LABEL92 if_icmpeq LABEL119
jump LABEL96 jump LABEL123
LABEL92: LABEL119:
sload 0 sload 0
invoke 632 invoke 632
sstore 0 sstore 0
sstore 1 sstore 1
LABEL96: LABEL123:
iload 1 iload 1
iconst 1 iconst 1
if_icmpeq LABEL100 if_icmpeq LABEL127
jump LABEL104 jump LABEL143
LABEL100: LABEL127:
sload 0
iconst 0
iconst 1
substring
4122
sload 0
iconst 1
sload 0
string_length
substring
append
sstore 0
sconst "|" sconst "|"
sload 0 sload 0
append append
sstore 0 sstore 0
LABEL104: LABEL143:
sload 0
string_length
iconst 0
if_icmple LABEL148
jump LABEL149
LABEL148:
return
LABEL149:
sload 0 sload 0
iload 0 iload 0
iload 1 iload 1
chat_sendclan chat_sendclan
jump LABEL112 jump LABEL163
LABEL109: LABEL154:
sload 0
string_length
iconst 0
if_icmple LABEL159
jump LABEL160
LABEL159:
return
LABEL160:
sload 0 sload 0
iload 0 iload 0
chat_sendpublic chat_sendpublic
LABEL112: LABEL163:
clientclock clientclock
set_varc_int 61 set_varc_int 61
return return

View File

@@ -413,11 +413,17 @@ CHAT_FILTER:
jump LABEL562 jump LABEL562
LABEL368: LABEL368:
iload 12 ; message uid iload 12 ; message uid
sload 2 ; message timestamp sconst "" ; message channel
sload 1 ; message name
sload 0 ; message
sload 2 ; message timestamp
sconst "chatMessageBuilding" sconst "chatMessageBuilding"
runelite_callback runelite_callback
pop_int pop_int ; uid
sstore 2 ; message timestamp sstore 2 ; message timestamp
sstore 0 ; message
sstore 1 ; message name
pop_string ; message channel
iload 18 iload 18
switch switch
3: LABEL371 3: LABEL371

View File

@@ -1 +1 @@
725BA34A3D0891309D6CC3A6E7AD9AEAB331BC08E1E312606E846C607F820519 690BCC4CE42FE670B31A14E214FECD3B27CEB013D6413713DB4A587D1CC38974

File diff suppressed because it is too large Load Diff

View File

@@ -31,14 +31,16 @@ import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.awt.Color; import java.awt.Color;
import net.runelite.api.ChatMessageType; import net.runelite.api.ChatMessageType;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.IterableHashTable;
import net.runelite.api.MessageNode; import net.runelite.api.MessageNode;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.ChatColorConfig;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import static org.junit.Assert.assertEquals;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.anyLong;
import org.mockito.Mock; import org.mockito.Mock;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -59,12 +61,39 @@ public class ChatMessageManagerTest
@Inject @Inject
private ChatMessageManager chatMessageManager; private ChatMessageManager chatMessageManager;
private String[] sstack;
private int[] istack;
@Before @Before
public void before() public void before()
{ {
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
} }
private void setupVm(ChatMessageType type, String name, String message)
{
MessageNode messageNode = mock(MessageNode.class);
when(messageNode.getType()).thenReturn(type);
IterableHashTable<MessageNode> tbl = mock(IterableHashTable.class);
when(tbl.get(anyLong())).thenReturn(messageNode);
when(client.getMessages()).thenReturn(tbl);
sstack = new String[]{
"",
name,
message,
""
};
istack = new int[]{
1
};
when(client.getStringStack()).thenReturn(sstack);
when(client.getStringStackSize()).thenReturn(sstack.length);
when(client.getIntStack()).thenReturn(istack);
when(client.getIntStackSize()).thenReturn(istack.length);
}
@Test @Test
public void testMessageRecoloring() public void testMessageRecoloring()
{ {
@@ -75,16 +104,10 @@ public class ChatMessageManagerTest
configChanged.setGroup("textrecolor"); configChanged.setGroup("textrecolor");
chatMessageManager.onConfigChanged(configChanged); chatMessageManager.onConfigChanged(configChanged);
ChatMessage chatMessage = new ChatMessage(); setupVm(ChatMessageType.GAMEMESSAGE, "", "Your dodgy necklace protects you. It has <col=ff0000>1</col> charge left.");
chatMessage.setType(ChatMessageType.GAMEMESSAGE); chatMessageManager.colorChatMessage();
MessageNode messageNode = mock(MessageNode.class); assertEquals("<col=b20000>Your dodgy necklace protects you. It has <col=ff0000>1<col=b20000> charge left.</col>", sstack[2]);
chatMessage.setMessageNode(messageNode);
when(messageNode.getValue()).thenReturn("Your dodgy necklace protects you. It has <col=ff0000>1</col> charge left.");
chatMessageManager.onChatMessage(chatMessage);
verify(messageNode).setValue("<col=b20000>Your dodgy necklace protects you. It has <col=ff0000>1<col=b20000> charge left.</col>");
} }
@Test @Test
@@ -95,14 +118,7 @@ public class ChatMessageManagerTest
when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000")); when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000"));
// Setup message setupVm(ChatMessageType.PUBLICCHAT, friendName, "");
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType(ChatMessageType.PUBLICCHAT);
chatMessage.setName(friendName);
MessageNode messageNode = mock(MessageNode.class);
chatMessage.setMessageNode(messageNode);
when(messageNode.getName()).thenReturn(friendName);
// Setup friend checking // Setup friend checking
Player localPlayer = mock(Player.class); Player localPlayer = mock(Player.class);
@@ -111,9 +127,9 @@ public class ChatMessageManagerTest
when(client.getLocalPlayer()).thenReturn(localPlayer); when(client.getLocalPlayer()).thenReturn(localPlayer);
when(localPlayer.getName()).thenReturn(localPlayerName); when(localPlayer.getName()).thenReturn(localPlayerName);
chatMessageManager.onChatMessage(chatMessage); chatMessageManager.colorChatMessage();
verify(messageNode).setName("<col=b20000>" + friendName + "</col>"); assertEquals("<col=b20000>" + friendName + "</col>", sstack[1]);
} }
@Test @Test
@@ -125,14 +141,7 @@ public class ChatMessageManagerTest
when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000")); when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000"));
// Setup message setupVm(ChatMessageType.PUBLICCHAT, friendName, "");
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType(ChatMessageType.PUBLICCHAT);
chatMessage.setName(friendName);
MessageNode messageNode = mock(MessageNode.class);
chatMessage.setMessageNode(messageNode);
when(messageNode.getName()).thenReturn(friendName);
// Setup friend checking // Setup friend checking
Player localPlayer = mock(Player.class); Player localPlayer = mock(Player.class);
@@ -141,9 +150,9 @@ public class ChatMessageManagerTest
when(client.getLocalPlayer()).thenReturn(localPlayer); when(client.getLocalPlayer()).thenReturn(localPlayer);
when(localPlayer.getName()).thenReturn(localPlayerName); when(localPlayer.getName()).thenReturn(localPlayerName);
chatMessageManager.onChatMessage(chatMessage); chatMessageManager.colorChatMessage();
verify(messageNode).setName("<col=b20000>" + friendName + "</col>"); assertEquals("<col=b20000>" + friendName + "</col>", sstack[1]);
} }
@Test @Test