Merge remote-tracking branch 'upstream/master' into master

This commit is contained in:
ThatGamerBlue
2021-06-02 21:24:52 +01:00
21 changed files with 879 additions and 362 deletions

View File

@@ -85,6 +85,7 @@ import net.runelite.http.api.worlds.World;
import net.runelite.http.api.worlds.WorldResult;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.slf4j.LoggerFactory;
@Singleton
@@ -261,8 +262,8 @@ public class RuneLite
OpenOSRS.preload();
OkHttpClient.Builder okHttpClientBuilder = RuneLiteAPI.CLIENT.newBuilder()
.cache(new Cache(new File(CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE));
OkHttpClient.Builder okHttpClientBuilder = RuneLiteAPI.CLIENT.newBuilder();
setupCache(okHttpClientBuilder, new File(CACHE_DIR, "okhttp"));
final boolean insecureSkipTlsVerification = options.has("insecure-skip-tls-verification");
if (insecureSkipTlsVerification || RuneLiteProperties.isInsecureSkipTlsVerification())
@@ -496,6 +497,25 @@ public class RuneLite
}
}
@VisibleForTesting
static void setupCache(OkHttpClient.Builder builder, File cacheDir)
{
builder.cache(new Cache(cacheDir, MAX_OKHTTP_CACHE_SIZE))
.addNetworkInterceptor(chain ->
{
// This has to be a network interceptor so it gets hit before the cache tries to store stuff
Response res = chain.proceed(chain.request());
if (res.code() >= 400 && "GET".equals(res.request().method()))
{
// if the request 404'd we don't want to cache it because its probably temporary
res = res.newBuilder()
.header("Cache-Control", "no-store")
.build();
}
return res;
});
}
private static void setupInsecureTrustManager(OkHttpClient.Builder okHttpClientBuilder)
{
try

View File

@@ -26,12 +26,12 @@ package net.runelite.client.game;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.inject.Inject;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@@ -48,20 +48,23 @@ import net.runelite.client.util.ImageUtil;
@Singleton
public class SpriteManager
{
@Inject
private Client client;
private final Client client;
private final ClientThread clientThread;
private final InfoBoxManager infoBoxManager;
@Inject
private ClientThread clientThread;
@Inject
private InfoBoxManager infoBoxManager;
public Cache<Long, BufferedImage> cache = CacheBuilder.newBuilder()
private final Cache<Long, BufferedImage> cache = CacheBuilder.newBuilder()
.maximumSize(128L)
.expireAfterAccess(1, TimeUnit.HOURS)
.build();
@Inject
private SpriteManager(Client client, ClientThread clientThread, InfoBoxManager infoBoxManager)
{
this.client = client;
this.clientThread = clientThread;
this.infoBoxManager = infoBoxManager;
}
@Nullable
public BufferedImage getSprite(int archive, int file)
{

View File

@@ -367,15 +367,23 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener
@Subscribe
private void onScriptPreFired(ScriptPreFired ev)
{
if (ev.getScriptId() == ScriptID.SETTINGS_SLIDER_CHOOSE_ONOP)
switch (ev.getScriptId())
{
int arg = client.getIntStackSize() - 7;
int[] is = client.getIntStack();
if (is[arg] == SettingID.CAMERA_ZOOM)
case ScriptID.SETTINGS_SLIDER_CHOOSE_ONOP:
{
addZoomTooltip(client.getScriptActiveWidget());
int arg = client.getIntStackSize() - 7;
int[] is = client.getIntStack();
if (is[arg] == SettingID.CAMERA_ZOOM)
{
addZoomTooltip(client.getScriptActiveWidget());
}
break;
}
case ScriptID.ZOOM_SLIDER_ONDRAG:
case ScriptID.SETTINGS_ZOOM_SLIDER_ONDRAG:
sliderTooltip = makeSliderTooltip();
break;
}
}
@@ -390,12 +398,14 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener
private void addZoomTooltip(Widget w)
{
w.setOnMouseRepeatListener((JavaScriptCallback) ev ->
{
int value = client.getVar(VarClientInt.CAMERA_ZOOM_RESIZABLE_VIEWPORT);
int max = config.innerLimit() ? config.INNER_ZOOM_LIMIT : CameraPlugin.DEFAULT_INNER_ZOOM_LIMIT;
sliderTooltip = new Tooltip("Camera Zoom: " + value + " / " + max);
});
w.setOnMouseRepeatListener((JavaScriptCallback) ev -> sliderTooltip = makeSliderTooltip());
}
private Tooltip makeSliderTooltip()
{
int value = client.getVar(VarClientInt.CAMERA_ZOOM_RESIZABLE_VIEWPORT);
int max = config.innerLimit() ? config.INNER_ZOOM_LIMIT : CameraPlugin.DEFAULT_INNER_ZOOM_LIMIT;
return new Tooltip("Camera Zoom: " + value + " / " + max);
}
@Subscribe

View File

@@ -92,18 +92,6 @@ public interface ChatChannelConfig extends Config
return true;
}
@ConfigItem(
keyName = "clanCounter",
name = "Members Counter",
description = "Show the amount of friends chat members near you.",
position = 3,
section = friendsChatSection
)
default boolean showCounter()
{
return false;
}
@ConfigItem(
keyName = "chatsData",
name = "",
@@ -129,7 +117,7 @@ public interface ChatChannelConfig extends Config
position = 4,
section = friendsChatSection
)
default boolean showJoinLeave()
default boolean showFriendsChatJoinLeave()
{
return false;
}

View File

@@ -32,7 +32,6 @@ import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Runnables;
import com.google.inject.Provides;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
@@ -53,9 +52,7 @@ import net.runelite.api.GameState;
import net.runelite.api.Ignore;
import net.runelite.api.MessageNode;
import net.runelite.api.NameableContainer;
import net.runelite.api.Player;
import net.runelite.api.ScriptID;
import net.runelite.api.SpriteID;
import net.runelite.api.VarClientStr;
import net.runelite.api.Varbits;
import net.runelite.api.clan.ClanChannel;
@@ -71,8 +68,6 @@ import net.runelite.api.events.FriendsChatMemberJoined;
import net.runelite.api.events.FriendsChatMemberLeft;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.PlayerDespawned;
import net.runelite.api.events.PlayerSpawned;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.ScriptPostFired;
import net.runelite.api.events.VarClientStrChanged;
@@ -88,7 +83,6 @@ import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.game.ChatIconManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@@ -96,7 +90,6 @@ import static net.runelite.client.ui.JagexColors.CHAT_FC_NAME_OPAQUE_BACKGROUND;
import static net.runelite.client.ui.JagexColors.CHAT_FC_NAME_TRANSPARENT_BACKGROUND;
import static net.runelite.client.ui.JagexColors.CHAT_FC_TEXT_OPAQUE_BACKGROUND;
import static net.runelite.client.ui.JagexColors.CHAT_FC_TEXT_TRANSPARENT_BACKGROUND;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
@PluginDescriptor(
@@ -119,12 +112,6 @@ public class ChatChannelPlugin extends Plugin
@Inject
private ChatChannelConfig config;
@Inject
private InfoBoxManager infoBoxManager;
@Inject
private SpriteManager spriteManager;
@Inject
private ClientThread clientThread;
@@ -138,8 +125,6 @@ public class ChatChannelPlugin extends Plugin
private ChatMessageManager chatMessageManager;
private List<String> chats;
private final List<Player> members = new ArrayList<>();
private MembersIndicator membersIndicator;
/**
* queue of temporary messages added to the client
*/
@@ -186,8 +171,6 @@ public class ChatChannelPlugin extends Plugin
{
chats = null;
clientThread.invoke(() -> colorIgnoredPlayers(Color.WHITE));
members.clear();
resetCounter();
rebuildFriendsChat();
inputMode = null;
}
@@ -202,15 +185,6 @@ public class ChatChannelPlugin extends Plugin
rebuildFriendsChat();
}
if (config.showCounter())
{
clientThread.invoke(this::addCounter);
}
else
{
resetCounter();
}
Color ignoreColor = config.showIgnores() ? config.showIgnoresColor() : Color.WHITE;
clientThread.invoke(() -> colorIgnoredPlayers(ignoreColor));
}
@@ -221,29 +195,13 @@ public class ChatChannelPlugin extends Plugin
{
final FriendsChatMember member = event.getMember();
if (member.getWorld() == client.getWorld())
{
final Player local = client.getLocalPlayer();
final String memberName = Text.toJagexName(member.getName());
for (final Player player : client.getPlayers())
{
if (player != null && player != local && memberName.equals(Text.toJagexName(player.getName())))
{
members.add(player);
addCounter();
break;
}
}
}
// members getting initialized isn't relevant
if (joinedTick == client.getTickCount())
{
return;
}
if (!config.showJoinLeave() ||
if (!config.showFriendsChatJoinLeave() ||
member.getRank().getValue() < config.joinLeaveRank().getValue())
{
return;
@@ -258,28 +216,7 @@ public class ChatChannelPlugin extends Plugin
{
final FriendsChatMember member = event.getMember();
if (member.getWorld() == client.getWorld())
{
final String memberName = Text.toJagexName(member.getName());
final Iterator<Player> each = members.iterator();
while (each.hasNext())
{
if (memberName.equals(Text.toJagexName(each.next().getName())))
{
each.remove();
if (members.isEmpty())
{
resetCounter();
}
break;
}
}
}
if (!config.showJoinLeave() ||
if (!config.showFriendsChatJoinLeave() ||
member.getRank().getValue() < config.joinLeaveRank().getValue())
{
return;
@@ -378,11 +315,6 @@ public class ChatChannelPlugin extends Plugin
}
}
if (!config.showJoinLeave())
{
return;
}
timeoutMessages();
addActivityMessages();
@@ -625,35 +557,10 @@ public class ChatChannelPlugin extends Plugin
if (gameState == GameState.LOGIN_SCREEN || gameState == GameState.CONNECTION_LOST || gameState == GameState.HOPPING)
{
members.clear();
resetCounter();
joinMessages.clear();
}
}
@Subscribe
public void onPlayerSpawned(PlayerSpawned event)
{
final Player local = client.getLocalPlayer();
final Player player = event.getPlayer();
if (player != local && player.isFriendsChatMember())
{
members.add(player);
addCounter();
}
}
@Subscribe
public void onPlayerDespawned(PlayerDespawned event)
{
if (members.remove(event.getPlayer()) && members.isEmpty())
{
resetCounter();
}
}
@Subscribe
public void onFriendsChatChanged(FriendsChatChanged event)
{
@@ -661,11 +568,6 @@ public class ChatChannelPlugin extends Plugin
{
joinedTick = client.getTickCount();
}
else
{
members.clear();
resetCounter();
}
activityBuffer.clear();
}
@@ -779,14 +681,9 @@ public class ChatChannelPlugin extends Plugin
}
}
int getMembersSize()
{
return members.size();
}
private void insertRankIcon(final ChatMessage message)
{
final FriendsChatRank rank = getRank(message.getName());
final FriendsChatRank rank = getRank(Text.removeTags(message.getName()));
if (rank != null && rank != FriendsChatRank.UNRANKED)
{
@@ -879,24 +776,6 @@ public class ChatChannelPlugin extends Plugin
config.chatsData(Text.toCSV(chats));
}
private void resetCounter()
{
infoBoxManager.removeInfoBox(membersIndicator);
membersIndicator = null;
}
private void addCounter()
{
if (!config.showCounter() || membersIndicator != null || members.isEmpty())
{
return;
}
final BufferedImage image = spriteManager.getSprite(SpriteID.TAB_FRIENDS_CHAT, 0);
membersIndicator = new MembersIndicator(image, this);
infoBoxManager.addInfoBox(membersIndicator);
}
private void confirmKickPlayer(final String kickPlayerName)
{
chatboxPanelManager.openTextMenuInput("Attempting to kick: " + kickPlayerName)

View File

@@ -55,6 +55,7 @@ import net.runelite.api.MessageNode;
import net.runelite.api.Player;
import net.runelite.api.clan.ClanChannel;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.OverheadTextChanged;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.client.config.ConfigManager;
@@ -139,6 +140,19 @@ public class ChatFilterPlugin extends Plugin
client.refreshChat();
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{
switch (gameStateChanged.getGameState())
{
// Login drops references to all messages and also resets the global message id counter.
// Invalidate the message id so it doesn't collide later when rebuilding the chatfilter.
case HOPPING:
case LOGGING_IN:
duplicateChatCache.values().forEach(d -> d.messageId = -1);
}
}
@Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent event)
{
@@ -205,7 +219,10 @@ public class ChatFilterPlugin extends Plugin
if (!blockMessage && shouldCollapse)
{
Duplicate duplicateCacheEntry = duplicateChatCache.get(name + ":" + message);
if (duplicateCacheEntry != null)
// If messageId is -1 then this is a replayed message, which we can't easily collapse since we don't know
// the most recent message. This is only for public chat since it is the only thing both replayed and also
// collapsed. Just allow uncollapsed playback.
if (duplicateCacheEntry != null && duplicateCacheEntry.messageId != -1)
{
blockMessage = duplicateCacheEntry.messageId != messageId ||
((chatMessageType == PUBLICCHAT || chatMessageType == MODCHAT) &&

View File

@@ -38,6 +38,7 @@ import net.runelite.api.clan.ClanChannelMember;
import net.runelite.api.clan.ClanRank;
import net.runelite.api.clan.ClanSettings;
import net.runelite.api.clan.ClanTitle;
import net.runelite.client.util.Text;
@Singleton
public class PlayerIndicatorsService
@@ -130,7 +131,7 @@ public class PlayerIndicatorsService
return FriendsChatRank.UNRANKED;
}
FriendsChatMember friendsChatMember = friendsChatManager.findByName(player.getName());
FriendsChatMember friendsChatMember = friendsChatManager.findByName(Text.removeTags(player.getName()));
return friendsChatMember != null ? friendsChatMember.getRank() : FriendsChatRank.UNRANKED;
}
}

View File

@@ -22,32 +22,18 @@
* (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.chatchannel;
package net.runelite.client.plugins.team;
import java.awt.Color;
import java.awt.image.BufferedImage;
import net.runelite.client.ui.overlay.infobox.Counter;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.InfoBox;
class MembersIndicator extends Counter
abstract class MembersIndicator extends InfoBox
{
private final ChatChannelPlugin plugin;
MembersIndicator(BufferedImage image, ChatChannelPlugin plugin)
MembersIndicator(BufferedImage image, Plugin plugin)
{
super(image, plugin, plugin.getMembersSize());
this.plugin = plugin;
}
@Override
public int getCount()
{
return plugin.getMembersSize();
}
@Override
public String getTooltip()
{
return plugin.getMembersSize() + " friends chat member(s) near you";
super(image, plugin);
}
@Override

View File

@@ -22,7 +22,7 @@
* (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.teamcapes;
package net.runelite.client.plugins.team;
import java.awt.Dimension;
import java.awt.Graphics2D;
@@ -41,12 +41,12 @@ import net.runelite.client.ui.overlay.components.ImageComponent;
class TeamCapesOverlay extends OverlayPanel
{
private final TeamCapesPlugin plugin;
private final TeamCapesConfig config;
private final TeamPlugin plugin;
private final TeamConfig config;
private final ItemManager manager;
@Inject
private TeamCapesOverlay(TeamCapesPlugin plugin, TeamCapesConfig config, ItemManager manager)
private TeamCapesOverlay(TeamPlugin plugin, TeamConfig config, ItemManager manager)
{
super(plugin);
setPosition(OverlayPosition.TOP_LEFT);
@@ -63,7 +63,7 @@ class TeamCapesOverlay extends OverlayPanel
public Dimension render(Graphics2D graphics)
{
Map<Integer, Integer> teams = plugin.getTeams();
if (teams.isEmpty())
if (teams.isEmpty() || !config.teamCapesOverlay())
{
return null;
}

View File

@@ -22,23 +22,84 @@
* (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.teamcapes;
package net.runelite.client.plugins.team;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigSection;
@ConfigGroup("teamCapes")
public interface TeamCapesConfig extends Config
@ConfigGroup(TeamConfig.GROUP)
public interface TeamConfig extends Config
{
String GROUP = "teamCapes";
@ConfigSection(
name = "Team",
description = "Configuration for teams",
position = 10
)
String teamSection = "teamSection";
@ConfigSection(
name = "Friends Chat",
description = "Configuration for friends chat",
position = 20
)
String friendsChatSection = "friendsChatSection";
@ConfigSection(
name = "Clan Chat",
description = "Configuration for clan chat",
position = 30
)
String clanChatSection = "clanChatSection";
@ConfigItem(
keyName = "teamCapesOverlay",
name = "Team cape overlay",
description = "Configures whether to show the team cape overlay.",
position = 0,
section = teamSection
)
default boolean teamCapesOverlay()
{
return false;
}
@ConfigItem(
keyName = "minimumCapeCount",
name = "Minimum Cape Count",
description = "Configures the minimum number of team capes which must be present before being displayed.",
position = 0
position = 1,
section = teamSection
)
default int getMinimumCapeCount()
{
return 1;
}
@ConfigItem(
keyName = "friendsChatMemberCounter",
name = "Friends Chat Members Counter",
description = "Show the amount of friends chat members near you.",
position = 0,
section = friendsChatSection
)
default boolean friendsChatMemberCounter()
{
return false;
}
@ConfigItem(
keyName = "clanChatMemberCounter",
name = "Clan Chat Members Counter",
description = "Show the amount of clan chat members near you.",
position = 0,
section = clanChatSection
)
default boolean clanChatMemberCounter()
{
return false;
}
}

View File

@@ -0,0 +1,458 @@
/*
* Copyright (c) 2017, Devin French <https://github.com/devinfrench>
* Copyright (c) 2021, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.team;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.inject.Provides;
import java.awt.image.BufferedImage;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.FriendsChatMember;
import net.runelite.api.GameState;
import net.runelite.api.Player;
import net.runelite.api.SpriteID;
import net.runelite.api.clan.ClanChannel;
import net.runelite.api.clan.ClanChannelMember;
import net.runelite.api.events.ClanChannelChanged;
import net.runelite.api.events.ClanMemberJoined;
import net.runelite.api.events.ClanMemberLeft;
import net.runelite.api.events.FriendsChatChanged;
import net.runelite.api.events.FriendsChatMemberJoined;
import net.runelite.api.events.FriendsChatMemberLeft;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.PlayerChanged;
import net.runelite.api.events.PlayerDespawned;
import net.runelite.api.events.PlayerSpawned;
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.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
@PluginDescriptor(
name = "Team",
description = "Shows how many team and clan mates are nearby",
tags = {"overlay", "players", "cape", "clan", "friend"},
configName = "TeamCapesPlugin", // the old plugin's name
enabledByDefault = false
)
@Slf4j
public class TeamPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private ClientThread clientThread;
@Inject
private OverlayManager overlayManager;
@Inject
private TeamConfig config;
@Inject
private TeamCapesOverlay overlay;
@Inject
private SpriteManager spriteManager;
@Inject
private InfoBoxManager infoBoxManager;
// Team number -> Number of players
@Getter(AccessLevel.PACKAGE)
private Map<Integer, Integer> teams = new LinkedHashMap<>();
// Player -> Team number
private final Map<Player, Integer> playerTeam = new HashMap<>();
private final BiMap<String, Player> players = HashBiMap.create();
private int friendsChatCount;
private int clanChatCount;
private MembersIndicator friendsChatIndicator;
private MembersIndicator clanChatIndicator;
@Provides
TeamConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(TeamConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
clientThread.invokeLater(() -> client.getPlayers().forEach(this::updateTeam));
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
teams.clear();
playerTeam.clear();
players.clear();
removeFriendsChatCounter();
removeClanChatCounter();
friendsChatCount = 0;
clanChatCount = 0;
}
@Subscribe
public void onConfigChanged(ConfigChanged configChanged)
{
if (configChanged.getGroup().equals(TeamConfig.GROUP))
{
if (config.friendsChatMemberCounter())
{
clientThread.invoke(this::addFriendsChatCounter);
}
else
{
removeFriendsChatCounter();
}
if (config.clanChatMemberCounter())
{
clientThread.invoke(this::addClanChatCounter);
}
else
{
removeClanChatCounter();
}
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged state)
{
GameState gameState = state.getGameState();
if (gameState == GameState.LOGIN_SCREEN || gameState == GameState.CONNECTION_LOST || gameState == GameState.HOPPING)
{
players.clear();
removeFriendsChatCounter();
removeClanChatCounter();
}
}
@Subscribe
public void onPlayerSpawned(PlayerSpawned event)
{
final Player local = client.getLocalPlayer();
final Player player = event.getPlayer();
if (player != local)
{
players.put(Text.removeTags(player.getName()), player);
if (player.isFriendsChatMember())
{
++friendsChatCount;
addFriendsChatCounter();
}
if (player.isClanMember())
{
++clanChatCount;
addClanChatCounter();
}
}
}
@Subscribe
public void onPlayerDespawned(PlayerDespawned playerDespawned)
{
Player player = playerDespawned.getPlayer();
Integer team = playerTeam.remove(player);
if (team != null)
{
teams.computeIfPresent(team, (key, value) -> value > 1 ? value - 1 : null);
sortTeams();
}
players.inverse().remove(player);
if (player.isFriendsChatMember())
{
if (friendsChatCount > 0)
{
if (--friendsChatCount == 0)
{
removeFriendsChatCounter();
}
}
}
if (player.isClanMember())
{
if (clanChatCount > 0)
{
if (--clanChatCount == 0)
{
removeClanChatCounter();
}
}
}
}
@Subscribe
public void onPlayerChanged(PlayerChanged playerChanged)
{
Player player = playerChanged.getPlayer();
updateTeam(player);
}
private void updateTeam(Player player)
{
int oldTeam = playerTeam.getOrDefault(player, 0);
if (oldTeam == player.getTeam())
{
return;
}
log.debug("{} has changed teams: {} -> {}", player.getName(), oldTeam, player.getTeam());
if (oldTeam > 0)
{
teams.computeIfPresent(oldTeam, (key, value) -> value > 1 ? value - 1 : null);
playerTeam.remove(player);
}
if (player.getTeam() > 0)
{
teams.merge(player.getTeam(), 1, Integer::sum);
playerTeam.put(player, player.getTeam());
}
sortTeams();
}
private void sortTeams()
{
// Sort teams by value in descending order and then by key in ascending order, limited to 5 entries
teams = teams.entrySet().stream()
.sorted(
Comparator.comparing(Map.Entry<Integer, Integer>::getValue, Comparator.reverseOrder())
.thenComparingInt(Map.Entry::getKey)
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
@Subscribe
public void onFriendsChatChanged(FriendsChatChanged event)
{
if (!event.isJoined())
{
removeFriendsChatCounter();
friendsChatCount = 0;
}
}
@Subscribe
public void onClanChannelChanged(ClanChannelChanged event)
{
if (!event.isGuest())
{
removeClanChatCounter();
clanChatCount = 0;
ClanChannel clanChannel = event.getClanChannel();
if (clanChannel != null)
{
for (ClanChannelMember member : clanChannel.getMembers())
{
final String memberName = Text.toJagexName(member.getName());
final Player player = players.get(memberName);
if (player != null)
{
++clanChatCount;
}
}
addClanChatCounter();
}
}
}
@Subscribe
public void onFriendsChatMemberJoined(FriendsChatMemberJoined event)
{
final FriendsChatMember member = event.getMember();
if (member.getWorld() == client.getWorld())
{
final String memberName = Text.toJagexName(member.getName());
final Player player = players.get(memberName);
if (player != null)
{
++friendsChatCount;
addFriendsChatCounter();
}
}
}
@Subscribe
public void onFriendsChatMemberLeft(FriendsChatMemberLeft event)
{
final FriendsChatMember member = event.getMember();
if (member.getWorld() == client.getWorld())
{
final String memberName = Text.toJagexName(member.getName());
final Player player = players.get(memberName);
if (player != null)
{
if (friendsChatCount > 0)
{
if (--friendsChatCount == 0)
{
removeFriendsChatCounter();
}
}
}
}
}
@Subscribe
public void onClanMemberJoined(ClanMemberJoined clanMemberJoined)
{
final ClanChannelMember member = clanMemberJoined.getClanMember();
if (member.getWorld() == client.getWorld())
{
final String memberName = Text.toJagexName(member.getName());
final Player player = players.get(memberName);
if (player != null)
{
++clanChatCount;
addClanChatCounter();
}
}
}
@Subscribe
public void onClanMemberLeft(ClanMemberLeft clanMemberLeft)
{
final ClanChannelMember member = clanMemberLeft.getClanMember();
if (member.getWorld() == client.getWorld())
{
final String memberName = Text.toJagexName(member.getName());
final Player player = players.get(memberName);
if (player != null)
{
if (clanChatCount > 0)
{
if (--clanChatCount == 0)
{
removeClanChatCounter();
}
}
}
}
}
private void addFriendsChatCounter()
{
if (!config.friendsChatMemberCounter() || friendsChatIndicator != null || friendsChatCount == 0)
{
return;
}
final BufferedImage image = spriteManager.getSprite(SpriteID.TAB_FRIENDS_CHAT, 0);
friendsChatIndicator = new MembersIndicator(image, this)
{
@Override
public String getText()
{
return Integer.toString(friendsChatCount);
}
@Override
public String getTooltip()
{
return friendsChatCount + " friends chat member(s) near you";
}
};
infoBoxManager.addInfoBox(friendsChatIndicator);
}
private void removeFriendsChatCounter()
{
infoBoxManager.removeInfoBox(friendsChatIndicator);
friendsChatIndicator = null;
}
private void addClanChatCounter()
{
if (!config.clanChatMemberCounter() || clanChatIndicator != null || clanChatCount == 0)
{
return;
}
final BufferedImage image = spriteManager.getSprite(SpriteID.TAB_CLAN_CHAT, 0);
clanChatIndicator = new MembersIndicator(image, this)
{
@Override
public String getText()
{
return Integer.toString(clanChatCount);
}
@Override
public String getTooltip()
{
return clanChatCount + " clan chat member(s) near you";
}
};
infoBoxManager.addInfoBox(clanChatIndicator);
}
private void removeClanChatCounter()
{
infoBoxManager.removeInfoBox(clanChatIndicator);
clanChatIndicator = null;
}
}

View File

@@ -1,151 +0,0 @@
/*
* Copyright (c) 2017, Devin French <https://github.com/devinfrench>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.teamcapes;
import com.google.inject.Provides;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.events.PlayerChanged;
import net.runelite.api.events.PlayerDespawned;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Team Capes",
description = "Show the different team capes in your area and the amount of each",
tags = {"overlay", "players"},
enabledByDefault = false
)
@Slf4j
public class TeamCapesPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private ClientThread clientThread;
@Inject
private OverlayManager overlayManager;
@Inject
private TeamCapesOverlay overlay;
// Team number -> Number of players
@Getter(AccessLevel.PACKAGE)
private Map<Integer, Integer> teams = new LinkedHashMap<>();
// Player -> Team number
private final Map<Player, Integer> playerTeam = new HashMap<>();
@Provides
TeamCapesConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(TeamCapesConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
clientThread.invokeLater(() -> client.getPlayers().forEach(this::update));
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
teams.clear();
playerTeam.clear();
}
@Subscribe
public void onPlayerChanged(PlayerChanged playerChanged)
{
Player player = playerChanged.getPlayer();
update(player);
}
private void update(Player player)
{
int oldTeam = playerTeam.getOrDefault(player, 0);
if (oldTeam == player.getTeam())
{
return;
}
log.debug("{} has changed teams: {} -> {}", player.getName(), oldTeam, player.getTeam());
if (oldTeam > 0)
{
teams.computeIfPresent(oldTeam, (key, value) -> value > 1 ? value - 1 : null);
playerTeam.remove(player);
}
if (player.getTeam() > 0)
{
teams.merge(player.getTeam(), 1, Integer::sum);
playerTeam.put(player, player.getTeam());
}
sort();
}
@Subscribe
public void onPlayerDespawned(PlayerDespawned playerDespawned)
{
Player player = playerDespawned.getPlayer();
Integer team = playerTeam.remove(player);
if (team != null)
{
teams.computeIfPresent(team, (key, value) -> value > 1 ? value - 1 : null);
sort();
}
}
private void sort()
{
// Sort teams by value in descending order and then by key in ascending order, limited to 5 entries
teams = teams.entrySet().stream()
.sorted(
Comparator.comparing(Map.Entry<Integer, Integer>::getValue, Comparator.reverseOrder())
.thenComparingInt(Map.Entry::getKey)
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
}

View File

@@ -29,6 +29,7 @@ package net.runelite.client.plugins.xptracker;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.ArrayList;
@@ -53,7 +54,6 @@ import net.runelite.api.Skill;
import net.runelite.api.WorldType;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.DynamicGridLayout;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.SkillColor;
import net.runelite.client.ui.components.MouseDragEventForwarder;
@@ -190,7 +190,7 @@ class XpInfoBox extends JPanel
headerPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
headerPanel.setLayout(new BorderLayout());
statsPanel.setLayout(new DynamicGridLayout(2, 2));
statsPanel.setLayout(new GridLayout(2, 2));
statsPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
statsPanel.setBorder(new EmptyBorder(9, 2, 9, 2));

View File

@@ -24,10 +24,10 @@
*/
package net.runelite.client.ui.components;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.Collections;
import java.util.List;
import javax.swing.JLabel;
@@ -53,7 +53,7 @@ public class ProgressBar extends DimmableJPanel
public ProgressBar()
{
setLayout(new BorderLayout());
setLayout(new GridLayout(1, 3));
// The background color should be overridden
setBackground(Color.GREEN.darker());
setForeground(Color.GREEN.brighter());
@@ -66,6 +66,7 @@ public class ProgressBar extends DimmableJPanel
rightLabel.setFont(FontManager.getRunescapeSmallFont());
rightLabel.setForeground(Color.WHITE);
rightLabel.setHorizontalAlignment(SwingConstants.RIGHT);
rightLabel.setBorder(new EmptyBorder(2, 0, 0, 5));
centerLabel.setFont(FontManager.getRunescapeSmallFont());
@@ -74,9 +75,9 @@ public class ProgressBar extends DimmableJPanel
centerLabel.setBorder(new EmptyBorder(2, 0, 0, 0));
// Adds components to be automatically redrawn when paintComponents is called
add(leftLabel, BorderLayout.WEST);
add(centerLabel, BorderLayout.CENTER);
add(rightLabel, BorderLayout.EAST);
add(leftLabel);
add(centerLabel);
add(rightLabel);
}
@Override