friendicons: add note icon in friends/ignore list

Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
ThatGamerBlue
2020-03-13 17:50:54 +00:00
committed by Adam
parent 51f562b547
commit 7b4e8c2848
8 changed files with 304 additions and 1 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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),

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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