Merge remote-tracking branch 'runelite/master'

This commit is contained in:
Owain van Brakel
2020-06-18 11:01:33 +02:00
92 changed files with 555 additions and 360 deletions

View File

@@ -74,7 +74,7 @@ import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.discord.DiscordService;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ExternalPluginsLoaded;
import net.runelite.client.game.ClanManager;
import net.runelite.client.game.FriendChatManager;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.LootManager;
import net.runelite.client.game.PlayerManager;
@@ -167,7 +167,7 @@ public class RuneLite
private Provider<OverlayRenderer> overlayRenderer;
@Inject
private Provider<ClanManager> clanManager;
private Provider<FriendChatManager> friendChatManager;
@Inject
private Provider<ChatMessageManager> chatMessageManager;
@@ -237,6 +237,7 @@ public class RuneLite
final OptionParser parser = new OptionParser();
parser.accepts("developer-mode", "Enable developer tools");
parser.accepts("debug", "Show extra debugging output");
parser.accepts("safe-mode", "Disables external plugins and the GPU plugin");
parser.accepts("no-splash", "Do not show the splash screen");
final ArgumentAcceptingOptionSpec<String> proxyInfo = parser
.accepts("proxy")
@@ -392,10 +393,15 @@ public class RuneLite
PROFILES_DIR.mkdirs();
log.info("OpenOSRS {} Runelite {} (launcher version {}) starting up, args: {}",
RuneLiteProperties.getPlusVersion(), RuneLiteProperties.getVersion(), RuneLiteProperties.getLauncherVersion() == null ? "unknown" : RuneLiteProperties.getLauncherVersion(),
args.length == 0 ? "none" : String.join(" ", args));
final long start = System.currentTimeMillis();
injector = Guice.createInjector(new RuneLiteModule(
clientLoader,
options.has("safe-mode"),
options.valueOf(configfile)));
injector.getInstance(RuneLite.class).start();
@@ -480,7 +486,7 @@ public class RuneLite
chatMessageManager.get().loadColors();
overlayRenderer.get();
clanManager.get();
friendChatManager.get();
itemManager.get();
menuManager.get();
chatMessageManager.get();
@@ -490,6 +496,7 @@ public class RuneLite
playerManager.get();
chatboxPanelManager.get();
partyService.get();
infoBoxOverlay.get();
eventBus.subscribe(GameStateChanged.class, this, hooks::onGameStateChanged);
eventBus.subscribe(ScriptCallbackEvent.class, this, hooks::onScriptCallbackEvent);

View File

@@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import javax.inject.Singleton;
import lombok.AllArgsConstructor;
import net.runelite.api.Client;
import net.runelite.api.hooks.Callbacks;
import net.runelite.client.account.SessionManager;
@@ -63,22 +64,19 @@ import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@AllArgsConstructor
public class RuneLiteModule extends AbstractModule
{
private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb
private final Supplier<Applet> clientLoader;
private final boolean safeMode;
private final File config;
public RuneLiteModule(final Supplier<Applet> clientLoader, File config)
{
this.clientLoader = clientLoader;
this.config = config;
}
@Override
protected void configure()
{
bindConstant().annotatedWith(Names.named("safeMode")).to(safeMode);
bind(File.class).annotatedWith(Names.named("config")).toInstance(config);
bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT.newBuilder()
.cache(new Cache(new File(RuneLite.CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE))

View File

@@ -128,7 +128,7 @@ public class ChatCommandManager
String message = chatboxInput.getValue();
if (message.startsWith("/"))
{
message = message.substring(1); // clan chat input
message = message.substring(1); // friends chat input
}
onInput(chatboxInput, message);

View File

@@ -140,11 +140,11 @@ public class ChatMessageManager
break;
}
case FRIENDSCHAT:
usernameColor = isChatboxTransparent ? chatColorConfig.transparentClanUsernames() : chatColorConfig.opaqueClanUsernames();
usernameColor = isChatboxTransparent ? chatColorConfig.transparentFriendsChatUsernames() : chatColorConfig.opaqueFriendsChatUsernames();
break;
}
senderColor = isChatboxTransparent ? chatColorConfig.transparentClanChannelName() : chatColorConfig.opaqueClanChannelName();
senderColor = isChatboxTransparent ? chatColorConfig.transparentFriendsChatChannelName() : chatColorConfig.opaqueFriendsChatChannelName();
if (usernameColor != null)
{
@@ -218,7 +218,7 @@ public class ChatMessageManager
case PRIVATECHAT:
return JagexColors.CHAT_PRIVATE_MESSAGE_TEXT_OPAQUE_BACKGROUND;
case FRIENDSCHAT:
return JagexColors.CHAT_CLAN_TEXT_OPAQUE_BACKGROUND;
return JagexColors.CHAT_FC_TEXT_OPAQUE_BACKGROUND;
case ITEM_EXAMINE:
case OBJECT_EXAMINE:
case NPC_EXAMINE:
@@ -238,7 +238,7 @@ public class ChatMessageManager
case PRIVATECHAT:
return JagexColors.CHAT_PRIVATE_MESSAGE_TEXT_TRANSPARENT_BACKGROUND;
case FRIENDSCHAT:
return JagexColors.CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND;
return JagexColors.CHAT_FC_TEXT_TRANSPARENT_BACKGROUND;
case ITEM_EXAMINE:
case OBJECT_EXAMINE:
case NPC_EXAMINE:
@@ -311,24 +311,24 @@ public class ChatMessageManager
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaquePrivateMessageReceivedHighlight(), false),
ChatMessageType.MODPRIVATECHAT);
}
if (chatColorConfig.opaqueClanChatInfo() != null)
if (chatColorConfig.opaqueFriendsChatInfo() != null)
{
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatInfo(), false),
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueFriendsChatInfo(), false),
ChatMessageType.FRIENDSCHATNOTIFICATION);
}
if (chatColorConfig.opaqueClanChatInfoHighlight() != null)
if (chatColorConfig.opaqueFriendsChatInfoHighlight() != null)
{
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatInfoHighlight(), false),
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueFriendsChatInfoHighlight(), false),
ChatMessageType.FRIENDSCHATNOTIFICATION);
}
if (chatColorConfig.opaqueClanChatMessage() != null)
if (chatColorConfig.opaqueFriendsChatMessage() != null)
{
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueClanChatMessage(), false),
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.opaqueFriendsChatMessage(), false),
ChatMessageType.FRIENDSCHAT);
}
if (chatColorConfig.opaqueClanChatMessageHighlight() != null)
if (chatColorConfig.opaqueFriendsChatMessageHighlight() != null)
{
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueClanChatMessageHighlight(), false),
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.opaqueFriendsChatMessageHighlight(), false),
ChatMessageType.FRIENDSCHAT);
}
if (chatColorConfig.opaqueAutochatMessage() != null)
@@ -444,24 +444,24 @@ public class ChatMessageManager
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentPrivateMessageReceivedHighlight(), true),
ChatMessageType.MODPRIVATECHAT);
}
if (chatColorConfig.transparentClanChatInfo() != null)
if (chatColorConfig.transparentFriendsChatInfo() != null)
{
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatInfo(), true),
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentFriendsChatInfo(), true),
ChatMessageType.FRIENDSCHATNOTIFICATION);
}
if (chatColorConfig.transparentClanChatInfoHighlight() != null)
if (chatColorConfig.transparentFriendsChatInfoHighlight() != null)
{
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatInfoHighlight(), true),
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentFriendsChatInfoHighlight(), true),
ChatMessageType.FRIENDSCHATNOTIFICATION);
}
if (chatColorConfig.transparentClanChatMessage() != null)
if (chatColorConfig.transparentFriendsChatMessage() != null)
{
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentClanChatMessage(), true),
cacheColor(new ChatColor(ChatColorType.NORMAL, chatColorConfig.transparentFriendsChatMessage(), true),
ChatMessageType.FRIENDSCHAT);
}
if (chatColorConfig.transparentClanChatMessageHighlight() != null)
if (chatColorConfig.transparentFriendsChatMessageHighlight() != null)
{
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentClanChatMessageHighlight(), true),
cacheColor(new ChatColor(ChatColorType.HIGHLIGHT, chatColorConfig.transparentFriendsChatMessageHighlight(), true),
ChatMessageType.FRIENDSCHAT);
}
if (chatColorConfig.transparentAutochatMessage() != null)

View File

@@ -118,11 +118,11 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 7,
keyName = "opaqueClanChatInfo",
name = "Clan chat info",
description = "Clan Chat Information (eg. when joining a channel)",
name = "Friends chat info",
description = "Friends Chat Information (eg. when joining a channel)",
titleSection = "opaqueTitle"
)
default Color opaqueClanChatInfo()
default Color opaqueFriendsChatInfo()
{
return JagexColors.CHAT_GAME_EXAMINE_TEXT_OPAQUE_BACKGROUND;
}
@@ -130,11 +130,11 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 8,
keyName = "opaqueClanChatInfoHighlight",
name = "Clan chat info highlight",
description = "Clan Chat Information highlight (used for the Raids plugin)",
name = "Friends chat info highlight",
description = "Friends Chat Information highlight (used for the Raids plugin)",
titleSection = "opaqueTitle"
)
default Color opaqueClanChatInfoHighlight()
default Color opaqueFriendsChatInfoHighlight()
{
return Color.RED;
}
@@ -142,20 +142,20 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 9,
keyName = "opaqueClanChatMessage",
name = "Clan chat message",
description = "Color of Clan Chat Messages",
name = "Friends chat message",
description = "Color of Friends chat messages",
titleSection = "opaqueTitle"
)
Color opaqueClanChatMessage();
Color opaqueFriendsChatMessage();
@ConfigItem(
position = 10,
keyName = "opaqueClanChatMessageHighlight",
name = "Clan chat message highlight",
description = "Color of highlights in Clan Chat Messages",
name = "Friends chat message highlight",
description = "Color of highlights in Friends Chat messages",
titleSection = "opaqueTitle"
)
default Color opaqueClanChatMessageHighlight()
default Color opaqueFriendsChatMessageHighlight()
{
return Color.decode("#000000");
}
@@ -295,20 +295,20 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 25,
keyName = "opaqueClanChannelName",
name = "Clan channel name",
description = "Color of Clan Channel Name",
name = "Friends chat channel name",
description = "Color of Friends chat channel name",
titleSection = "opaqueTitle"
)
Color opaqueClanChannelName();
Color opaqueFriendsChatChannelName();
@ConfigItem(
position = 26,
keyName = "opaqueClanUsernames",
name = "Clan usernames",
description = "Color of Usernames in Clan Chat",
name = "Friends chat usernames",
description = "Color of usernames in Friends chat",
titleSection = "opaqueTitle"
)
Color opaqueClanUsernames();
Color opaqueFriendsChatUsernames();
@ConfigItem(
position = 27,
@@ -385,11 +385,11 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 57,
keyName = "transparentClanChatInfo",
name = "Clan chat info (transparent)",
description = "Clan Chat Information (eg. when joining a channel) (transparent)",
name = "Friends chat info (transparent)",
description = "Friends chat information (eg. when joining a channel) (transparent)",
titleSection = "transparentTitle"
)
default Color transparentClanChatInfo()
default Color transparentFriendsChatInfo()
{
return JagexColors.CHAT_GAME_EXAMINE_TEXT_TRANSPARENT_BACKGROUND;
}
@@ -397,11 +397,11 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 58,
keyName = "transparentClanChatInfoHighlight",
name = "Clan chat info highlight (transparent)",
description = "Clan Chat Information highlight (used for the Raids plugin) (transparent)",
name = "Friends chat info highlight (transparent)",
description = "Friends chat information highlight (used for the Raids plugin) (transparent)",
titleSection = "transparentTitle"
)
default Color transparentClanChatInfoHighlight()
default Color transparentFriendsChatInfoHighlight()
{
return Color.RED;
}
@@ -409,20 +409,20 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 59,
keyName = "transparentClanChatMessage",
name = "Clan chat message (transparent)",
description = "Color of Clan Chat Messages (transparent)",
name = "Friends chat message (transparent)",
description = "Color of Friends chat messages (transparent)",
titleSection = "transparentTitle"
)
Color transparentClanChatMessage();
Color transparentFriendsChatMessage();
@ConfigItem(
position = 60,
keyName = "transparentClanChatMessageHighlight",
name = "Clan chat message highlight (transparent)",
description = "Color of highlights in Clan Chat Messages (transparent)",
name = "Friends chat message highlight (transparent)",
description = "Color of highlights in Friends chat messages (transparent)",
titleSection = "transparentTitle"
)
default Color transparentClanChatMessageHighlight()
default Color transparentFriendsChatMessageHighlight()
{
return Color.decode("#FFFFFF");
}
@@ -562,20 +562,20 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 75,
keyName = "transparentClanChannelName",
name = "Clan channel name (transparent)",
description = "Color of Clan Channel Name (transparent)",
name = "Friends chat channel name (transparent)",
description = "Color of Friends chat channel name (transparent)",
titleSection = "transparentTitle"
)
Color transparentClanChannelName();
Color transparentFriendsChatChannelName();
@ConfigItem(
position = 76,
keyName = "transparentClanUsernames",
name = "Clan usernames (transparent)",
description = "Color of Usernames in Clan Chat (transparent)",
name = "Friends chat usernames (transparent)",
description = "Color of usernames in Friends chat (transparent)",
titleSection = "transparentTitle"
)
Color transparentClanUsernames();
Color transparentFriendsChatUsernames();
@ConfigItem(
position = 77,

View File

@@ -40,7 +40,7 @@ class ConfigInvocationHandler implements InvocationHandler
private final ConfigManager manager;
private final Cache<Method, Object> cache = CacheBuilder.newBuilder()
.maximumSize(128)
.maximumSize(256)
.build();
ConfigInvocationHandler(ConfigManager manager)

View File

@@ -16,19 +16,19 @@ public class AttackStyleChanged implements Event
/**
* The player that changed styles.
*/
private final Player player;
Player player;
/**
* Can be Unknown(nullable)
*
* @see net.runelite.client.game.AttackStyle
*/
private final AttackStyle oldStyle;
AttackStyle oldStyle;
/**
* Can be Unknown(nullable)
*
* @see net.runelite.client.game.AttackStyle
*/
private final AttackStyle newStyle;
AttackStyle newStyle;
}

View File

@@ -37,7 +37,7 @@ import net.runelite.api.events.Event;
@Slf4j
public class ClientShutdown implements Event
{
private Queue<Future<?>> tasks = new ConcurrentLinkedQueue<>();
Queue<Future<?>> tasks = new ConcurrentLinkedQueue<>();
public void waitFor(Future<?> future)
{

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020, 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.events;
import lombok.Value;
import net.runelite.api.events.Event;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.infobox.InfoBox;
@Value
public class InfoBoxMenuClicked implements Event
{
OverlayMenuEntry entry;
InfoBox infoBox;
}

View File

@@ -31,5 +31,5 @@ import net.runelite.client.ui.NavigationButton;
@Value
public class NavigationButtonAdded implements Event
{
private NavigationButton button;
NavigationButton button;
}

View File

@@ -31,5 +31,5 @@ import net.runelite.client.ui.NavigationButton;
@Value
public class NavigationButtonRemoved implements Event
{
private NavigationButton button;
NavigationButton button;
}

View File

@@ -31,6 +31,6 @@ import net.runelite.api.events.Event;
@Value
public class NotificationFired implements Event
{
final String message;
final TrayIcon.MessageType type;
String message;
TrayIcon.MessageType type;
}

View File

@@ -33,6 +33,6 @@ import net.runelite.client.game.ItemStack;
@Value
public class NpcLootReceived implements Event
{
private final NPC npc;
private final Collection<ItemStack> items;
NPC npc;
Collection<ItemStack> items;
}

View File

@@ -39,4 +39,4 @@ public class OverlayMenuClicked implements Event
{
private OverlayMenuEntry entry;
private Overlay overlay;
}
}

View File

@@ -31,5 +31,5 @@ import net.runelite.api.events.Event;
@Value
public class PartyChanged implements Event
{
private final UUID partyId;
UUID partyId;
}

View File

@@ -33,6 +33,6 @@ import net.runelite.client.game.ItemStack;
@Value
public class PlayerLootReceived implements Event
{
private final Player player;
private final Collection<ItemStack> items;
Player player;
Collection<ItemStack> items;
}

View File

@@ -34,5 +34,5 @@ import net.runelite.http.api.worlds.WorldResult;
@Value
public class WorldsFetch implements Event
{
private final WorldResult worldResult;
WorldResult worldResult;
}

View File

@@ -171,13 +171,13 @@ public enum FishingSpot
MINNOW("Minnow", ItemID.MINNOW,
FISHING_SPOT_7730, FISHING_SPOT_7731, FISHING_SPOT_7732, FISHING_SPOT_7733
),
INFERNAL_EEL("Infernal Eel", "Leaping sturgeon", ItemID.INFERNAL_EEL,
INFERNAL_EEL("Infernal Eel", ItemID.INFERNAL_EEL,
ROD_FISHING_SPOT_7676
),
KARAMBWAN("Karambwan", "Karambwanji", ItemID.RAW_KARAMBWAN,
KARAMBWAN("Karambwan", ItemID.RAW_KARAMBWAN,
FISHING_SPOT_4712, FISHING_SPOT_4713
),
KARAMBWANJI("Karambwanji, Shrimp", ItemID.KARAMBWANJI,
KARAMBWANJI("Karambwanji, Shrimp", "Karambwanji", ItemID.KARAMBWANJI,
FISHING_SPOT_4710
),
SACRED_EEL("Sacred eel", ItemID.SACRED_EEL,

View File

@@ -36,118 +36,115 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.ClanMember;
import net.runelite.api.ClanMemberManager;
import net.runelite.api.ClanMemberRank;
import net.runelite.api.Client;
import net.runelite.api.FriendsChatManager;
import net.runelite.api.FriendsChatMember;
import net.runelite.api.FriendsChatRank;
import net.runelite.api.GameState;
import net.runelite.api.IndexedSprite;
import net.runelite.api.SpriteID;
import net.runelite.api.events.ClanChanged;
import net.runelite.api.events.FriendsChatChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.util.Text;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.util.ImageUtil;
@Singleton
public class ClanManager
public class FriendChatManager
{
private static final int[] CLANCHAT_IMAGES =
private static final int[] RANK_IMAGES =
{
SpriteID.CLAN_CHAT_RANK_SMILEY_FRIEND,
SpriteID.CLAN_CHAT_RANK_SINGLE_CHEVRON_RECRUIT,
SpriteID.CLAN_CHAT_RANK_DOUBLE_CHEVRON_CORPORAL,
SpriteID.CLAN_CHAT_RANK_TRIPLE_CHEVRON_SERGEANT,
SpriteID.CLAN_CHAT_RANK_BRONZE_STAR_LIEUTENANT,
SpriteID.CLAN_CHAT_RANK_SILVER_STAR_CAPTAIN,
SpriteID.CLAN_CHAT_RANK_GOLD_STAR_GENERAL,
SpriteID.CLAN_CHAT_RANK_KEY_CHANNEL_OWNER,
SpriteID.CLAN_CHAT_RANK_CROWN_JAGEX_MODERATOR,
SpriteID.FRIENDS_CHAT_RANK_SMILEY_FRIEND,
SpriteID.FRIENDS_CHAT_RANK_SINGLE_CHEVRON_RECRUIT,
SpriteID.FRIENDS_CHAT_RANK_DOUBLE_CHEVRON_CORPORAL,
SpriteID.FRIENDS_CHAT_RANK_TRIPLE_CHEVRON_SERGEANT,
SpriteID.FRIENDS_CHAT_RANK_BRONZE_STAR_LIEUTENANT,
SpriteID.FRIENDS_CHAT_RANK_SILVER_STAR_CAPTAIN,
SpriteID.FRIENDS_CHAT_RANK_GOLD_STAR_GENERAL,
SpriteID.FRIENDS_CHAT_RANK_KEY_CHANNEL_OWNER,
SpriteID.FRIENDS_CHAT_RANK_CROWN_JAGEX_MODERATOR,
};
private static final Dimension CLANCHAT_IMAGE_DIMENSION = new Dimension(11, 11);
private static final Color CLANCHAT_IMAGE_OUTLINE_COLOR = new Color(33, 33, 33);
private static final Dimension IMAGE_DIMENSION = new Dimension(11, 11);
private static final Color IMAGE_OUTLINE_COLOR = new Color(33, 33, 33);
private final Client client;
private final SpriteManager spriteManager;
private final BufferedImage[] clanChatImages = new BufferedImage[CLANCHAT_IMAGES.length];
private final BufferedImage[] rankImages = new BufferedImage[RANK_IMAGES.length];
private final LoadingCache<String, ClanMemberRank> clanRanksCache = CacheBuilder.newBuilder()
private final LoadingCache<String, FriendsChatRank> ranksCache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<String, ClanMemberRank>()
.build(new CacheLoader<>()
{
@Override
public ClanMemberRank load(@Nonnull String key)
public FriendsChatRank load(@Nonnull String key)
{
final ClanMemberManager clanMemberManager = client.getClanMemberManager();
if (clanMemberManager == null)
final FriendsChatManager friendsChatManager = client.getFriendsChatManager();
if (friendsChatManager == null)
{
return ClanMemberRank.UNRANKED;
return FriendsChatRank.UNRANKED;
}
ClanMember clanMember = clanMemberManager.findByName(sanitize(key));
return clanMember != null ? clanMember.getRank() : ClanMemberRank.UNRANKED;
FriendsChatMember friendsChatMember = friendsChatManager.findByName(sanitize(key));
return friendsChatMember != null ? friendsChatMember.getRank() : FriendsChatRank.UNRANKED;
}
});
private int offset;
@Inject
private ClanManager(
final Client client,
final SpriteManager spriteManager,
final EventBus eventbus
)
private FriendChatManager(final Client client,
final SpriteManager spriteManager,
final EventBus eventbus)
{
this.client = client;
this.spriteManager = spriteManager;
eventbus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
eventbus.subscribe(ClanChanged.class, this, this::onClanChanged);
eventbus.subscribe(FriendsChatChanged.class, this, this::onFriendsChatChanged);
}
public boolean isClanMember(String name)
public boolean isMember(String name)
{
ClanMemberManager clanMemberManager = client.getClanMemberManager();
return clanMemberManager != null && clanMemberManager.findByName(name) != null;
FriendsChatManager friendsChatManager = client.getFriendsChatManager();
return friendsChatManager != null && friendsChatManager.findByName(name) != null;
}
public ClanMemberRank getRank(String playerName)
public FriendsChatRank getRank(String playerName)
{
return clanRanksCache.getUnchecked(playerName);
return ranksCache.getUnchecked(playerName);
}
@Nullable
public BufferedImage getClanImage(final ClanMemberRank clanMemberRank)
public BufferedImage getRankImage(final FriendsChatRank friendsChatRank)
{
if (clanMemberRank == ClanMemberRank.UNRANKED)
if (friendsChatRank == FriendsChatRank.UNRANKED)
{
return null;
}
return clanChatImages[clanMemberRank.ordinal() - 1];
return rankImages[friendsChatRank.ordinal() - 1];
}
public int getIconNumber(final ClanMemberRank clanMemberRank)
public int getIconNumber(final FriendsChatRank friendsChatRank)
{
return offset + clanMemberRank.ordinal() - 1;
return offset + friendsChatRank.ordinal() - 1;
}
private void onGameStateChanged(GameStateChanged gameStateChanged)
{
if (gameStateChanged.getGameState() == GameState.LOGGED_IN && offset == 0)
{
loadClanChatIcons();
loadRankIcons();
}
}
private void onClanChanged(ClanChanged clanChanged)
public void onFriendsChatChanged(FriendsChatChanged friendsChatChanged)
{
clanRanksCache.invalidateAll();
ranksCache.invalidateAll();
}
private void loadClanChatIcons()
private void loadRankIcons()
{
{
IndexedSprite[] modIcons = client.getModIcons();
@@ -157,21 +154,21 @@ public class ClanManager
new BufferedImage(modIcons[0].getWidth(), modIcons[0].getHeight(), BufferedImage.TYPE_INT_ARGB),
client);
modIcons = Arrays.copyOf(modIcons, offset + CLANCHAT_IMAGES.length);
modIcons = Arrays.copyOf(modIcons, offset + RANK_IMAGES.length);
Arrays.fill(modIcons, offset, modIcons.length, blank);
client.setModIcons(modIcons);
}
for (int i = 0; i < CLANCHAT_IMAGES.length; i++)
for (int i = 0; i < RANK_IMAGES.length; i++)
{
final int fi = i;
spriteManager.getSpriteAsync(CLANCHAT_IMAGES[i], 0, sprite ->
spriteManager.getSpriteAsync(RANK_IMAGES[i], 0, sprite ->
{
IndexedSprite[] modIcons = client.getModIcons();
clanChatImages[fi] = clanChatImageFromSprite(sprite);
modIcons[offset + fi] = ImageUtil.getImageIndexedSprite(clanChatImages[fi], client);
rankImages[fi] = friendsChatImageFromSprite(sprite);
modIcons[offset + fi] = ImageUtil.getImageIndexedSprite(rankImages[fi], client);
});
}
}
@@ -182,9 +179,9 @@ public class ClanManager
return cleaned.replace('\u00A0', ' ');
}
private static BufferedImage clanChatImageFromSprite(final BufferedImage clanSprite)
private static BufferedImage friendsChatImageFromSprite(final BufferedImage sprite)
{
final BufferedImage clanChatCanvas = ImageUtil.resizeCanvas(clanSprite, CLANCHAT_IMAGE_DIMENSION.width, CLANCHAT_IMAGE_DIMENSION.height);
return ImageUtil.outlineImage(clanChatCanvas, CLANCHAT_IMAGE_OUTLINE_COLOR);
final BufferedImage canvas = ImageUtil.resizeCanvas(sprite, IMAGE_DIMENSION.width, IMAGE_DIMENSION.height);
return ImageUtil.outlineImage(canvas, IMAGE_OUTLINE_COLOR);
}
}

View File

@@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -423,4 +424,25 @@ public class LootManager
return new WorldPoint(x, y, worldLocation.getPlane());
}
/**
* Get the list of items present at the provided WorldPoint that spawned this tick.
*
* @param worldPoint the location in question
* @return the list of item stacks
*/
public Collection<ItemStack> getItemSpawns(WorldPoint worldPoint)
{
LocalPoint localPoint = LocalPoint.fromWorld(client, worldPoint);
if (localPoint == null)
{
return Collections.emptyList();
}
final int sceneX = localPoint.getSceneX();
final int sceneY = localPoint.getSceneY();
final int packed = sceneX << 8 | sceneY;
final List<ItemStack> itemStacks = itemSpawns.get(packed);
return Collections.unmodifiableList(itemStacks);
}
}

View File

@@ -44,7 +44,7 @@ public class PlayerManager
private final Client client;
private final ItemManager itemManager;
private final EventBus eventBus;
private final ClanManager clanManager;
private final FriendChatManager friendChatManager;
private final Map<String, PlayerContainer> playerMap = new ConcurrentHashMap<>();
private final Map<String, HiscoreResult> resultCache = new ConcurrentHashMap<>();
private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
@@ -54,13 +54,13 @@ public class PlayerManager
final Client client,
final EventBus eventBus,
final ItemManager itemManager,
final ClanManager clanManager
final FriendChatManager friendChatManager
)
{
this.client = client;
this.itemManager = itemManager;
this.eventBus = eventBus;
this.clanManager = clanManager;
this.friendChatManager = friendChatManager;
eventBus.subscribe(PlayerDespawned.class, this, this::onPlayerDespawned);
eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged);
eventBus.subscribe(PlayerAppearanceChanged.class, this, this::onAppearenceChanged);
@@ -211,7 +211,7 @@ public class PlayerManager
PlayerContainer player = playerMap.computeIfAbsent(event.getPlayer().getName(), s -> new PlayerContainer(event.getPlayer()));
update(player);
player.setFriend(client.isFriended(player.getName(), false));
player.setClan(clanManager.isClanMember(player.getName()));
player.setClan(friendChatManager.isMember(player.getName()));
}
private void onPlayerDespawned(PlayerDespawned event)

View File

@@ -54,6 +54,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.swing.JOptionPane;
import lombok.AccessLevel;
@@ -66,6 +67,7 @@ import net.runelite.client.RuneLiteProperties;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.events.ExternalPluginChanged;
@@ -112,9 +114,11 @@ public class ExternalPluginManager
@Getter(AccessLevel.PUBLIC)
private UpdateManager updateManager;
private final Set<PluginType> pluginTypes = Set.of(PluginType.values());
private final boolean safeMode;
@Inject
public ExternalPluginManager(
@Named("safeMode") final boolean safeMode,
PluginManager pluginManager,
OpenOSRSConfig openOSRSConfig,
EventBus eventBus,
@@ -122,6 +126,7 @@ public class ExternalPluginManager
ConfigManager configManager,
Groups groups)
{
this.safeMode = safeMode;
this.runelitePluginManager = pluginManager;
this.openOSRSConfig = openOSRSConfig;
this.eventBus = eventBus;
@@ -449,6 +454,14 @@ public class ExternalPluginManager
continue;
}
if (safeMode && !pluginDescriptor.loadInSafeMode())
{
log.debug("Disabling {} due to safe mode", clazz);
// also disable the plugin from autostarting later
configManager.unsetConfiguration(RuneLiteConfig.GROUP_NAME, clazz.getSimpleName().toLowerCase());
continue;
}
@SuppressWarnings("unchecked") Class<Plugin> pluginClass = (Class<Plugin>) clazz;
graph.addNode(pluginClass);
}

View File

@@ -58,4 +58,6 @@ public @interface PluginDescriptor
PluginType type() default PluginType.UNCATEGORIZED;
boolean enabledByDefault() default true;
boolean loadInSafeMode() default true;
}

View File

@@ -92,6 +92,7 @@ public class PluginManager
*/
private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins";
private final boolean safeMode;
private final EventBus eventBus;
private final Scheduler scheduler;
private final ExecutorService executorService;
@@ -112,6 +113,7 @@ public class PluginManager
@Inject
@VisibleForTesting
PluginManager(
@Named("safeMode") final boolean safeMode,
final EventBus eventBus,
final Scheduler scheduler,
final ExecutorService executorService,
@@ -120,6 +122,7 @@ public class PluginManager
final Groups groups,
final @Named("config") File config)
{
this.safeMode = safeMode;
this.eventBus = eventBus;
this.scheduler = scheduler;
this.executorService = executorService;
@@ -376,6 +379,14 @@ public class PluginManager
continue;
}
if (safeMode && !pluginDescriptor.loadInSafeMode())
{
log.debug("Disabling {} due to safe mode", clazz);
// also disable the plugin from autostarting later
configManager.unsetConfiguration(RuneLiteConfig.GROUP_NAME, clazz.getSimpleName().toLowerCase());
continue;
}
@SuppressWarnings("unchecked") Class<Plugin> pluginClass = (Class<Plugin>) clazz;
graph.addNode(pluginClass);
}

View File

@@ -537,7 +537,32 @@ public class ClientUI
if (clientBounds != null)
{
frame.setBounds(clientBounds);
frame.revalidateMinimumSize();
// frame.getGraphicsConfiguration().getBounds() returns the bounds for the primary display.
// We have to find the correct graphics configuration by using the intersection of the client boundaries.
GraphicsConfiguration gc = getIntersectingDisplay(clientBounds);
if (gc != null)
{
double scale = gc.getDefaultTransform().getScaleX();
// When Windows screen scaling is on, the position/bounds will be wrong when they are set.
// The bounds saved in shutdown are the full, non-scaled co-ordinates.
if (scale != 1)
{
clientBounds.setRect(
clientBounds.getX() / scale,
clientBounds.getY() / scale,
clientBounds.getWidth() / scale,
clientBounds.getHeight() / scale);
frame.setMinimumSize(clientBounds.getSize());
frame.setBounds(clientBounds);
}
}
else
{
frame.setLocationRelativeTo(frame.getOwner());
}
}
else
{
@@ -560,25 +585,13 @@ public class ClientUI
frame.setLocationRelativeTo(frame.getOwner());
}
// If the frame is well hidden (e.g. unplugged 2nd screen),
// we want to move it back to default position as it can be
// hard for the user to reposition it themselves otherwise.
Rectangle clientBounds = frame.getBounds();
Rectangle screenBounds = frame.getGraphicsConfiguration().getBounds();
if (clientBounds.x + clientBounds.width - CLIENT_WELL_HIDDEN_MARGIN < screenBounds.getX() ||
clientBounds.x + CLIENT_WELL_HIDDEN_MARGIN > screenBounds.getX() + screenBounds.getWidth() ||
clientBounds.y + CLIENT_WELL_HIDDEN_MARGIN_TOP < screenBounds.getY() ||
clientBounds.y + CLIENT_WELL_HIDDEN_MARGIN > screenBounds.getY() + screenBounds.getHeight())
{
frame.setLocationRelativeTo(frame.getOwner());
}
// Show frame
frame.setVisible(true);
frame.toFront();
requestFocus();
giveClientFocus();
log.info("Showing frame {}", frame);
frame.revalidateMinimumSize();
});
// Show out of date dialog if needed
@@ -591,6 +604,24 @@ public class ClientUI
}
}
private GraphicsConfiguration getIntersectingDisplay(final Rectangle bounds)
{
GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
for (GraphicsDevice gd : gds)
{
GraphicsConfiguration gc = gd.getDefaultConfiguration();
final Rectangle displayBounds = gc.getBounds();
if (displayBounds.intersects(bounds))
{
return gc;
}
}
return null;
}
private boolean showWarningOnExit()
{
if (config.warningOnExit() == WarningOnExit.ALWAYS)
@@ -1125,14 +1156,14 @@ public class ClientUI
private void saveClientBoundsConfig()
{
final Rectangle bounds = frame.getBounds();
if ((frame.getExtendedState() & JFrame.MAXIMIZED_BOTH) != 0)
{
configManager.setConfiguration(CONFIG_GROUP, CONFIG_CLIENT_BOUNDS, bounds);
configManager.setConfiguration(CONFIG_GROUP, CONFIG_CLIENT_MAXIMIZED, true);
}
else
{
final Rectangle bounds = frame.getBounds();
// Try to expand sidebar
if (!sidebarOpen)
{

View File

@@ -36,8 +36,8 @@ public class JagexColors
*/
public static final Color CHAT_PUBLIC_TEXT_OPAQUE_BACKGROUND = Color.BLUE;
public static final Color CHAT_PRIVATE_MESSAGE_TEXT_OPAQUE_BACKGROUND = Color.CYAN;
public static final Color CHAT_CLAN_TEXT_OPAQUE_BACKGROUND = new Color(127, 0, 0);
public static final Color CHAT_CLAN_NAME_OPAQUE_BACKGROUND = Color.BLUE;
public static final Color CHAT_FC_TEXT_OPAQUE_BACKGROUND = new Color(127, 0, 0);
public static final Color CHAT_FC_NAME_OPAQUE_BACKGROUND = Color.BLUE;
public static final Color CHAT_GAME_EXAMINE_TEXT_OPAQUE_BACKGROUND = Color.BLACK;
public static final Color CHAT_TYPED_TEXT_OPAQUE_BACKGROUND = Color.BLUE;
@@ -46,8 +46,8 @@ public class JagexColors
*/
public static final Color CHAT_PUBLIC_TEXT_TRANSPARENT_BACKGROUND = new Color(144, 144, 255);
public static final Color CHAT_PRIVATE_MESSAGE_TEXT_TRANSPARENT_BACKGROUND = Color.CYAN;
public static final Color CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND = new Color(239, 80, 80);
public static final Color CHAT_CLAN_NAME_TRANSPARENT_BACKGROUND = new Color(144, 112, 255);
public static final Color CHAT_FC_TEXT_TRANSPARENT_BACKGROUND = new Color(239, 80, 80);
public static final Color CHAT_FC_NAME_TRANSPARENT_BACKGROUND = new Color(144, 112, 255);
public static final Color CHAT_GAME_EXAMINE_TEXT_TRANSPARENT_BACKGROUND = Color.WHITE;
public static final Color CHAT_TYPED_TEXT_TRANSPARENT_BACKGROUND = new Color(144, 144, 255);

View File

@@ -137,17 +137,17 @@ public class OverlayManager
private void onMenuOptionClicked(MenuOptionClicked event)
{
if (event.getMenuOpcode() != MenuOpcode.RUNELITE_OVERLAY)
MenuOpcode menuOpcode = event.getMenuOpcode();
if (menuOpcode != MenuOpcode.RUNELITE_OVERLAY && menuOpcode != MenuOpcode.RUNELITE_OVERLAY_CONFIG)
{
return;
}
event.consume();
Optional<Overlay> optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getIdentifier()).findAny();
if (optionalOverlay.isPresent())
Overlay overlay = overlays.get(event.getIdentifier());
if (overlay != null)
{
Overlay overlay = optionalOverlay.get();
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
Optional<OverlayMenuEntry> optionalOverlayMenuEntry = menuEntries.stream()
.filter(me -> me.getOption().equals(event.getOption()))

View File

@@ -50,7 +50,6 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.MenuEntry;
import net.runelite.api.MenuOpcode;
import net.runelite.api.events.BeforeRender;
import net.runelite.api.events.ClientTick;
import net.runelite.api.events.FocusChanged;
@@ -818,6 +817,11 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
private MenuEntry[] createRightClickMenuEntries(Overlay overlay)
{
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
if (menuEntries.isEmpty())
{
return null;
}
final MenuEntry[] entries = new MenuEntry[menuEntries.size()];
// Add in reverse order so they display correctly in the right-click menu
@@ -828,7 +832,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
final MenuEntry entry = new MenuEntry();
entry.setOption(overlayMenuEntry.getOption());
entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET));
entry.setOpcode(MenuOpcode.RUNELITE_OVERLAY.getId());
entry.setOpcode(overlayMenuEntry.getMenuOpcode().getId());
entry.setIdentifier(overlayManager.getOverlays().indexOf(overlay)); // overlay id
entries[i] = entry;

View File

@@ -35,6 +35,7 @@ import java.awt.image.BufferedImage;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.infobox.InfoBox;
@Setter
public class InfoBoxComponent implements LayoutableRenderableEntity
@@ -54,6 +55,8 @@ public class InfoBoxComponent implements LayoutableRenderableEntity
private Color color = Color.WHITE;
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
private BufferedImage image;
@Getter
private InfoBox infoBox;
@Override
public Dimension render(Graphics2D graphics)

View File

@@ -26,11 +26,14 @@ package net.runelite.client.ui.overlay.infobox;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
public abstract class InfoBox
{
@@ -54,6 +57,10 @@ public abstract class InfoBox
@Setter
private String tooltip;
@Getter
@Setter
private List<OverlayMenuEntry> menuEntries = new ArrayList<>();
public InfoBox(BufferedImage image, @Nonnull Plugin plugin)
{
this.plugin = plugin;

View File

@@ -31,11 +31,17 @@ import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.MenuOpcode;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.InfoBoxMenuClicked;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPanel;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
@@ -54,18 +60,23 @@ public class InfoBoxOverlay extends OverlayPanel
private final TooltipManager tooltipManager;
private final Client client;
private final RuneLiteConfig config;
private final EventBus eventBus;
private InfoBoxComponent hoveredComponent;
@Inject
private InfoBoxOverlay(
InfoBoxManager infoboxManager,
TooltipManager tooltipManager,
Client client,
RuneLiteConfig config)
RuneLiteConfig config,
EventBus eventBus)
{
this.tooltipManager = tooltipManager;
this.infoboxManager = infoboxManager;
this.client = client;
this.config = config;
this.eventBus = eventBus;
setPosition(OverlayPosition.TOP_LEFT);
setClearChildren(false);
@@ -73,6 +84,8 @@ public class InfoBoxOverlay extends OverlayPanel
panelComponent.setBackgroundColor(null);
panelComponent.setBorder(new Rectangle());
panelComponent.setGap(new Point(GAP, GAP));
eventBus.subscribe(MenuOptionClicked.class, this, this::onMenuOptionClicked);
}
@Override
@@ -80,6 +93,12 @@ public class InfoBoxOverlay extends OverlayPanel
{
final List<InfoBox> infoBoxes = infoboxManager.getInfoBoxes();
final boolean menuOpen = client.isMenuOpen();
if (!menuOpen)
{
hoveredComponent = null;
}
if (infoBoxes.isEmpty())
{
return null;
@@ -112,6 +131,7 @@ public class InfoBoxOverlay extends OverlayPanel
infoBoxComponent.setTooltip(box.getTooltip());
infoBoxComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
infoBoxComponent.setBackgroundColor(config.overlayBackgroundColor());
infoBoxComponent.setInfoBox(box);
panelComponent.getChildren().add(infoBoxComponent);
}
@@ -122,25 +142,49 @@ public class InfoBoxOverlay extends OverlayPanel
for (final LayoutableRenderableEntity child : panelComponent.getChildren())
{
if (child instanceof InfoBoxComponent)
final InfoBoxComponent component = (InfoBoxComponent) child;
// Create intersection rectangle
final Rectangle intersectionRectangle = new Rectangle(component.getBounds());
intersectionRectangle.translate(getBounds().x, getBounds().y);
if (intersectionRectangle.contains(mouse))
{
final InfoBoxComponent component = (InfoBoxComponent) child;
if (!Strings.isNullOrEmpty(component.getTooltip()))
final String tooltip = component.getTooltip();
if (!Strings.isNullOrEmpty(tooltip))
{
// Create intersection rectangle
final Rectangle intersectionRectangle = new Rectangle(component.getBounds());
intersectionRectangle.translate(getBounds().x, getBounds().y);
if (intersectionRectangle.contains(mouse))
{
tooltipManager.add(new Tooltip(component.getTooltip()));
}
tooltipManager.add(new Tooltip(tooltip));
}
if (!menuOpen)
{
hoveredComponent = component;
}
break;
}
}
panelComponent.getChildren().clear();
return dimension;
}
@Override
public List<OverlayMenuEntry> getMenuEntries()
{
// we dynamically build the menu options based on which infobox is hovered
return hoveredComponent == null ? Collections.emptyList() : hoveredComponent.getInfoBox().getMenuEntries();
}
public void onMenuOptionClicked(MenuOptionClicked menuOptionClicked)
{
if (menuOptionClicked.getMenuOpcode() != MenuOpcode.RUNELITE_INFOBOX)
{
return;
}
InfoBox infoBox = hoveredComponent.getInfoBox();
infoBox.getMenuEntries().stream()
.filter(me -> me.getOption().equals(menuOptionClicked.getOption()))
.findAny().ifPresent(overlayMenuEntry -> eventBus.post(InfoBoxMenuClicked.class, new InfoBoxMenuClicked(overlayMenuEntry, infoBox)));
}
}

View File

@@ -39,8 +39,8 @@ import net.runelite.client.plugins.Plugin;
public class Timer extends InfoBox
{
private final Instant startTime;
private final Instant endTime;
private final Duration duration;
private Instant endTime;
private Duration duration;
public Timer(long period, ChronoUnit unit, BufferedImage image, Plugin plugin)
{
@@ -94,4 +94,9 @@ public class Timer extends InfoBox
return timeLeft.isZero() || timeLeft.isNegative();
}
public void setDuration(Duration duration)
{
this.duration = duration;
endTime = startTime.plus(duration);
}
}