friendicons: add note icon in friends/ignore list
Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
@@ -233,4 +233,36 @@ public final class ScriptID
|
||||
*/
|
||||
@ScriptArguments(integer = 2)
|
||||
public static final int TOPLEVEL_RESIZE = 909;
|
||||
|
||||
/**
|
||||
* Called when the friends list is updated
|
||||
* <ul>
|
||||
* <li> int (WidgetID) Friends list "full container" </li>
|
||||
* <li> int (WidgetID) Friends list sort by name button </li>
|
||||
* <li> int (WidgetID) Friends list sort by last world change button </li>
|
||||
* <li> int (WidgetID) Friends list sort by world button </li>
|
||||
* <li> int (WidgetID) Friends list legacy sort button </li>
|
||||
* <li> int (WidgetID) Friends list names container </li>
|
||||
* <li> int (WidgetID) Friends list scroll bar </li>
|
||||
* <li> int (WidgetID) Friends list "loading please wait" text </li>
|
||||
* <li> int (WidgetID) Friends list player previous name holder </li>
|
||||
* </ul>
|
||||
*/
|
||||
@ScriptArguments(integer = 9)
|
||||
public static final int FRIENDS_UPDATE = 631;
|
||||
|
||||
/**
|
||||
* Called when the ignore list is updated
|
||||
* <ul>
|
||||
* <li> int (WidgetID) Ignore list "full container" </li>
|
||||
* <li> int (WidgetID) Ignore list sort by name button </li>
|
||||
* <li> int (WidgetID) Ignore list legacy sort button </li>
|
||||
* <li> int (WidgetID) Ignore list names container </li>
|
||||
* <li> int (WidgetID) Ignore list scroll bar </li>
|
||||
* <li> int (WidgetID) Ignore list "loading please wait" text </li>
|
||||
* <li> int (WidgetID) Ignore list player previous name holder </li>
|
||||
* </ul>
|
||||
*/
|
||||
@ScriptArguments(integer = 7)
|
||||
public static final int IGNORE_UPDATE = 630;
|
||||
}
|
||||
|
||||
@@ -215,11 +215,27 @@ public class WidgetID
|
||||
static class FriendList
|
||||
{
|
||||
static final int TITLE = 3;
|
||||
static final int FULL_CONTAINER = 5;
|
||||
static final int SORT_BY_NAME_BUTTON = 7;
|
||||
static final int SORT_BY_LAST_WORLD_CHANGE_BUTTON = 8;
|
||||
static final int SORT_BY_WORLD_BUTTON = 9;
|
||||
static final int LEGACY_SORT_BUTTON = 10;
|
||||
static final int NAMES_CONTAINER = 11;
|
||||
static final int SCROLL_BAR = 12;
|
||||
static final int LOADING_TEXT = 13;
|
||||
static final int PREVIOUS_NAME_HOLDER = 18;
|
||||
}
|
||||
|
||||
static class IgnoreList
|
||||
{
|
||||
static final int TITLE = 3;
|
||||
static final int FULL_CONTAINER = 5;
|
||||
static final int SORT_BY_NAME_BUTTON = 7;
|
||||
static final int LEGACY_SORT_BUTTON = 8;
|
||||
static final int NAMES_CONTAINER = 9;
|
||||
static final int SCROLL_BAR = 10;
|
||||
static final int LOADING_TEXT = 11;
|
||||
static final int PREVIOUS_NAME_HOLDER = 16;
|
||||
}
|
||||
|
||||
static class ClanChat
|
||||
|
||||
@@ -104,8 +104,24 @@ public enum WidgetInfo
|
||||
VOLCANIC_MINE_VENT_C_STATUS(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_C_STATUS),
|
||||
|
||||
FRIEND_CHAT_TITLE(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.TITLE),
|
||||
FRIEND_LIST_FULL_CONTAINER(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.FULL_CONTAINER),
|
||||
FRIEND_LIST_SORT_BY_NAME_BUTTON(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.SORT_BY_NAME_BUTTON),
|
||||
FRIEND_LIST_SORT_BY_LAST_WORLD_CHANGE_BUTTON(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.SORT_BY_LAST_WORLD_CHANGE_BUTTON),
|
||||
FRIEND_LIST_SORT_BY_WORLD_BUTTON(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.SORT_BY_WORLD_BUTTON),
|
||||
FRIEND_LIST_LEGACY_SORT_BUTTON(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.LEGACY_SORT_BUTTON),
|
||||
FRIEND_LIST_NAMES_CONTAINER(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.NAMES_CONTAINER),
|
||||
FRIEND_LIST_SCROLL_BAR(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.SCROLL_BAR),
|
||||
FRIEND_LIST_LOADING_TEXT(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.LOADING_TEXT),
|
||||
FRIEND_LIST_PREVIOUS_NAME_HOLDER(WidgetID.FRIENDS_LIST_GROUP_ID, WidgetID.FriendList.PREVIOUS_NAME_HOLDER),
|
||||
|
||||
IGNORE_TITLE(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.TITLE),
|
||||
IGNORE_FULL_CONTAINER(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.FULL_CONTAINER),
|
||||
IGNORE_SORT_BY_NAME_BUTTON(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.SORT_BY_NAME_BUTTON),
|
||||
IGNORE_LEGACY_SORT_BUTTON(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.LEGACY_SORT_BUTTON),
|
||||
IGNORE_NAMES_CONTAINER(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.NAMES_CONTAINER),
|
||||
IGNORE_SCROLL_BAR(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.SCROLL_BAR),
|
||||
IGNORE_LOADING_TEXT(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.LOADING_TEXT),
|
||||
IGNORE_PREVIOUS_NAME_HOLDER(WidgetID.IGNORE_LIST_GROUP_ID, WidgetID.IgnoreList.PREVIOUS_NAME_HOLDER),
|
||||
|
||||
EXPLORERS_RING_ALCH_INVENTORY(WidgetID.EXPLORERS_RING_ALCH_GROUP_ID, WidgetID.ExplorersRing.INVENTORY),
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ThatGamerBlue <https://github.com/ThatGamerBlue>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
package net.runelite.client.plugins.friendnotes;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(FriendNotesPlugin.CONFIG_GROUP)
|
||||
public interface FriendNotesConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showIcons",
|
||||
name = "Show Icons",
|
||||
description = "Show icons on friend or ignore list",
|
||||
position = 1
|
||||
)
|
||||
default boolean showIcons()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -29,29 +29,40 @@ package net.runelite.client.plugins.friendnotes;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Friend;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Ignore;
|
||||
import net.runelite.api.IndexedSprite;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.Nameable;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NameableNameChanged;
|
||||
import net.runelite.api.events.RemovedFriend;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Slf4j
|
||||
@@ -61,13 +72,15 @@ import net.runelite.client.util.Text;
|
||||
)
|
||||
public class FriendNotesPlugin extends Plugin
|
||||
{
|
||||
private static final String CONFIG_GROUP = "friendNotes";
|
||||
static final String CONFIG_GROUP = "friendNotes";
|
||||
private static final int CHARACTER_LIMIT = 128;
|
||||
private static final String KEY_PREFIX = "note_";
|
||||
private static final String ADD_NOTE = "Add Note";
|
||||
private static final String EDIT_NOTE = "Edit Note";
|
||||
private static final String NOTE_PROMPT_FORMAT = "%s's Notes<br>" +
|
||||
ColorUtil.prependColorTag("(Limit %s Characters)", new Color(0, 0, 170));
|
||||
private static final int ICON_WIDTH = 14;
|
||||
private static final int ICON_HEIGHT = 12;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@@ -84,19 +97,74 @@ public class FriendNotesPlugin extends Plugin
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private FriendNotesConfig config;
|
||||
|
||||
@Getter
|
||||
private HoveredFriend hoveredFriend = null;
|
||||
|
||||
private int iconIdx = -1;
|
||||
private String currentlyLayouting;
|
||||
|
||||
@Provides
|
||||
private FriendNotesConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(FriendNotesConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
clientThread.invoke(this::loadIcon);
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
loadIcon();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!event.getGroup().equals(CONFIG_GROUP))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getKey())
|
||||
{
|
||||
case "showIcons":
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,6 +180,11 @@ public class FriendNotesPlugin extends Plugin
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, KEY_PREFIX + displayName, note);
|
||||
}
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,4 +331,104 @@ public class FriendNotesPlugin extends Plugin
|
||||
log.debug("Remove friend: '{}'", displayName);
|
||||
setFriendNote(displayName, null);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
{
|
||||
if (!config.showIcons() || iconIdx == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getEventName())
|
||||
{
|
||||
case "friend_cc_settext":
|
||||
case "ignore_cc_settext":
|
||||
String[] stringStack = client.getStringStack();
|
||||
int stringStackSize = client.getStringStackSize();
|
||||
final String rsn = stringStack[stringStackSize - 1];
|
||||
final String sanitized = Text.toJagexName(Text.removeTags(rsn));
|
||||
currentlyLayouting = sanitized;
|
||||
if (getFriendNote(sanitized) != null)
|
||||
{
|
||||
stringStack[stringStackSize - 1] = rsn + " <img=" + iconIdx + ">";
|
||||
}
|
||||
break;
|
||||
case "friend_cc_setposition":
|
||||
case "ignore_cc_setposition":
|
||||
if (currentlyLayouting == null || getFriendNote(currentlyLayouting) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int[] intStack = client.getIntStack();
|
||||
int intStackSize = client.getIntStackSize();
|
||||
int xpos = intStack[intStackSize - 4];
|
||||
xpos += ICON_WIDTH + 1;
|
||||
intStack[intStackSize - 4] = xpos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildFriendsList()
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
log.debug("Rebuilding friends list");
|
||||
client.runScript(
|
||||
ScriptID.FRIENDS_UPDATE,
|
||||
WidgetInfo.FRIEND_LIST_FULL_CONTAINER.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SORT_BY_NAME_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SORT_BY_LAST_WORLD_CHANGE_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SORT_BY_WORLD_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_LEGACY_SORT_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_NAMES_CONTAINER.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SCROLL_BAR.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_LOADING_TEXT.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_PREVIOUS_NAME_HOLDER.getPackedId()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void rebuildIgnoreList()
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
log.debug("Rebuilding ignore list");
|
||||
client.runScript(
|
||||
ScriptID.IGNORE_UPDATE,
|
||||
WidgetInfo.IGNORE_FULL_CONTAINER.getPackedId(),
|
||||
WidgetInfo.IGNORE_SORT_BY_NAME_BUTTON.getPackedId(),
|
||||
WidgetInfo.IGNORE_LEGACY_SORT_BUTTON.getPackedId(),
|
||||
WidgetInfo.IGNORE_NAMES_CONTAINER.getPackedId(),
|
||||
WidgetInfo.IGNORE_SCROLL_BAR.getPackedId(),
|
||||
WidgetInfo.IGNORE_LOADING_TEXT.getPackedId(),
|
||||
WidgetInfo.IGNORE_PREVIOUS_NAME_HOLDER.getPackedId()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void loadIcon()
|
||||
{
|
||||
final IndexedSprite[] modIcons = client.getModIcons();
|
||||
if (iconIdx != -1 || modIcons == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final BufferedImage iconImg = ImageUtil.getResourceStreamFromClass(getClass(), "note_icon.png");
|
||||
if (iconImg == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final BufferedImage resized = ImageUtil.resizeImage(iconImg, ICON_WIDTH, ICON_HEIGHT);
|
||||
|
||||
final IndexedSprite[] newIcons = Arrays.copyOf(modIcons, modIcons.length + 1);
|
||||
newIcons[newIcons.length - 1] = ImageUtil.getImageIndexedSprite(resized, client);
|
||||
|
||||
iconIdx = newIcons.length - 1;
|
||||
client.setModIcons(newIcons);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 931 B |
@@ -3,6 +3,12 @@
|
||||
.string_stack_count 0
|
||||
.int_var_count 16
|
||||
.string_var_count 2
|
||||
; callback "friend_cc_settext"
|
||||
; Fired just before the client pops the name off the stack
|
||||
; Modified by the friendnotes plugin to show the icon
|
||||
; callback "friend_cc_setposition"
|
||||
; Fired just before the client sets the position of "friend changed their name" icon
|
||||
; Modified by the friendnotes plugin to offset the name changed icon
|
||||
iload 1
|
||||
iconst 2
|
||||
iconst 3
|
||||
@@ -276,6 +282,8 @@ LABEL218:
|
||||
add
|
||||
istore 10
|
||||
sload 0
|
||||
sconst "friend_cc_settext"
|
||||
runelite_callback
|
||||
cc_settext
|
||||
iconst 0
|
||||
iload 13
|
||||
@@ -356,6 +364,8 @@ LABEL277:
|
||||
add
|
||||
iconst 0
|
||||
iconst 0
|
||||
sconst "friend_cc_setposition"
|
||||
runelite_callback
|
||||
cc_setposition 1
|
||||
iconst 1093
|
||||
cc_setgraphic 1
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
.string_stack_count 0
|
||||
.int_var_count 13
|
||||
.string_var_count 2
|
||||
; callback "ignore_cc_settext"
|
||||
; Fired just before the client pops the name off the stack
|
||||
; Modified by the friendnotes plugin to show the icon
|
||||
; callback "ignore_cc_setposition"
|
||||
; Fired just before the client sets the position of "ignored person changed their name" icon
|
||||
; Modified by the friendnotes plugin to offset the name changed icon
|
||||
iload 1
|
||||
iconst 2
|
||||
iconst 3
|
||||
@@ -133,6 +139,8 @@ LABEL101:
|
||||
add
|
||||
istore 8
|
||||
sload 0
|
||||
sconst "ignore_cc_settext"
|
||||
runelite_callback
|
||||
cc_settext
|
||||
iconst 0
|
||||
iload 10
|
||||
@@ -190,6 +198,8 @@ LABEL101:
|
||||
add
|
||||
iconst 0
|
||||
iconst 0
|
||||
sconst "ignore_cc_setposition"
|
||||
runelite_callback
|
||||
cc_setposition 1
|
||||
iconst 1093
|
||||
cc_setgraphic 1
|
||||
|
||||
Reference in New Issue
Block a user