diff --git a/runelite-api/src/main/java/net/runelite/api/clan/ClanSettings.java b/runelite-api/src/main/java/net/runelite/api/clan/ClanSettings.java index c24f6ec23f..5594f88700 100644 --- a/runelite-api/src/main/java/net/runelite/api/clan/ClanSettings.java +++ b/runelite-api/src/main/java/net/runelite/api/clan/ClanSettings.java @@ -58,5 +58,6 @@ public interface ClanSettings * @see ClanRank * @return */ + @Nullable ClanTitle titleForRank(ClanRank clanRank); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/ActivityType.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ActivityType.java similarity index 96% rename from runelite-client/src/main/java/net/runelite/client/plugins/friendschat/ActivityType.java rename to runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ActivityType.java index 242090392f..9e0a2ca204 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/ActivityType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ActivityType.java @@ -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.friendschat; +package net.runelite.client.plugins.chatchannel; enum ActivityType { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ChatChannelConfig.java similarity index 70% rename from runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatConfig.java rename to runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ChatChannelConfig.java index 0ff8362664..d8b4fede63 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ChatChannelConfig.java @@ -22,22 +22,58 @@ * (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.friendschat; +package net.runelite.client.plugins.chatchannel; import java.awt.Color; import net.runelite.api.FriendsChatRank; 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("clanchat") // group name from the old plugin -public interface FriendsChatConfig extends Config +@ConfigGroup(ChatChannelConfig.GROUP) +public interface ChatChannelConfig extends Config { + String GROUP = "clanchat"; // group name from the old plugin + + @ConfigSection( + name = "Friends Chat", + description = "Configuration for friends chat", + position = 10 + ) + String friendsChatSection = "friendsChat"; + + @ConfigSection( + name = "Clan Chat", + description = "Configuration for clan chat", + position = 20 + ) + String clanChatSection = "clanChat"; + + @ConfigSection( + name = "Guest Clan Chat", + description = "Configuration for guest clan chat", + position = 30 + ) + String guestClanChatSection = "guestClanChat"; + + @ConfigItem( + keyName = "joinLeaveTimeout", + name = "Join/Leave timeout", + description = "Set the timeout duration of join/leave messages. A value of 0 will make the messages permanent.", + position = 0 + ) + default int joinLeaveTimeout() + { + return 20; + } + @ConfigItem( keyName = "clanChatIcons", name = "Chat Icons", description = "Show rank icons next to friends chat members.", - position = 1 + position = 1, + section = friendsChatSection ) default boolean chatIcons() { @@ -48,7 +84,8 @@ public interface FriendsChatConfig extends Config keyName = "recentChats", name = "Recent Chats", description = "Show recent friends chats.", - position = 2 + position = 2, + section = friendsChatSection ) default boolean recentChats() { @@ -59,7 +96,8 @@ public interface FriendsChatConfig extends Config keyName = "clanCounter", name = "Members Counter", description = "Show the amount of friends chat members near you.", - position = 3 + position = 3, + section = friendsChatSection ) default boolean showCounter() { @@ -88,7 +126,8 @@ public interface FriendsChatConfig extends Config keyName = "showJoinLeave", name = "Show Join/Leave", description = "Adds a temporary message notifying when a member joins or leaves.", - position = 4 + position = 4, + section = friendsChatSection ) default boolean showJoinLeave() { @@ -99,29 +138,20 @@ public interface FriendsChatConfig extends Config keyName = "joinLeaveRank", name = "Join/Leave rank", description = "Only show join/leave messages for members at or above this rank.", - position = 5 + position = 5, + section = friendsChatSection ) default FriendsChatRank joinLeaveRank() { return FriendsChatRank.UNRANKED; } - @ConfigItem( - keyName = "joinLeaveTimeout", - name = "Join/Leave timeout", - description = "Set the timeout duration of join/leave messages. A value of 0 will make the messages permanent.", - position = 6 - ) - default int joinLeaveTimeout() - { - return 20; - } - @ConfigItem( keyName = "privateMessageIcons", name = "Private Message Icons", description = "Add rank icons to private messages received from members.", - position = 7 + position = 7, + section = friendsChatSection ) default boolean privateMessageIcons() { @@ -132,7 +162,8 @@ public interface FriendsChatConfig extends Config keyName = "publicChatIcons", name = "Public Chat Icons", description = "Add rank icons to public chat messages from members.", - position = 8 + position = 8, + section = friendsChatSection ) default boolean publicChatIcons() { @@ -143,7 +174,8 @@ public interface FriendsChatConfig extends Config keyName = "confirmKicks", name = "Confirm Kicks", description = "Shows a chat prompt to confirm kicks", - position = 10 + position = 10, + section = friendsChatSection ) default boolean confirmKicks() { @@ -154,7 +186,8 @@ public interface FriendsChatConfig extends Config keyName = "showIgnores", name = "Recolor ignored players", description = "Recolor members who are on your ignore list", - position = 11 + position = 11, + section = friendsChatSection ) default boolean showIgnores() { @@ -165,10 +198,35 @@ public interface FriendsChatConfig extends Config keyName = "showIgnoresColor", name = "Ignored color", description = "Allows you to change the color of the ignored players in your friends chat", - position = 12 + position = 12, + section = friendsChatSection ) default Color showIgnoresColor() { return Color.RED; } + + @ConfigItem( + keyName = "clanChatShowJoinLeave", + name = "Show Join/Leave", + description = "Adds a temporary message notifying when a member joins or leaves.", + position = 0, + section = clanChatSection + ) + default boolean clanChatShowJoinLeave() + { + return false; + } + + @ConfigItem( + keyName = "guestClanChatShowJoinLeave", + name = "Show Join/Leave", + description = "Adds a temporary message notifying when a member joins or leaves.", + position = 0, + section = guestClanChatSection + ) + default boolean guestClanChatShowJoinLeave() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ChatChannelPlugin.java similarity index 77% rename from runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java rename to runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ChatChannelPlugin.java index c7dc727b33..4d80810db8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/ChatChannelPlugin.java @@ -24,7 +24,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.friendschat; +package net.runelite.client.plugins.chatchannel; import com.google.common.base.MoreObjects; import com.google.common.base.Strings; @@ -36,13 +36,14 @@ import java.awt.image.BufferedImage; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; -import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import net.runelite.api.ChatLineBuffer; import net.runelite.api.ChatMessageType; +import net.runelite.api.ChatPlayer; import net.runelite.api.Client; import net.runelite.api.FriendsChatManager; import net.runelite.api.FriendsChatMember; @@ -56,7 +57,14 @@ 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; +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.api.events.ChatMessage; +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; @@ -89,11 +97,11 @@ import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.Text; @PluginDescriptor( - name = "Friends Chat", - description = "Add rank icons to users talking in friends chat", - tags = {"icons", "rank", "recent", "clan"} + name = "Chat Channels", + description = "Improvements for friends chat and clan chat.", + tags = {"icons", "rank", "recent", "clan", "friend", "channel"} ) -public class FriendsChatPlugin extends Plugin +public class ChatChannelPlugin extends Plugin { private static final int MAX_CHATS = 10; private static final String RECENT_TITLE = "Recent FCs"; @@ -106,7 +114,7 @@ public class FriendsChatPlugin extends Plugin private ChatIconManager chatIconManager; @Inject - private FriendsChatConfig config; + private ChatChannelConfig config; @Inject private InfoBoxManager infoBoxManager; @@ -123,22 +131,22 @@ public class FriendsChatPlugin extends Plugin @Inject private ChatColorConfig chatColorConfig; - private List chats = new ArrayList<>(); + private List chats; private final List members = new ArrayList<>(); private MembersIndicator membersIndicator; /** * queue of temporary messages added to the client */ private final Deque joinMessages = new ArrayDeque<>(); - private final Map activityBuffer = new HashMap<>(); + private final Map activityBuffer = new LinkedHashMap<>(); private int joinedTick; private boolean kickConfirmed = false; @Provides - FriendsChatConfig getConfig(ConfigManager configManager) + ChatChannelConfig getConfig(ConfigManager configManager) { - return configManager.getConfig(FriendsChatConfig.class); + return configManager.getConfig(ChatChannelConfig.class); } @Override @@ -155,6 +163,7 @@ public class FriendsChatPlugin extends Plugin @Override public void shutDown() { + chats = null; clientThread.invoke(() -> colorIgnoredPlayers(Color.WHITE)); members.clear(); resetCounter(); @@ -164,7 +173,7 @@ public class FriendsChatPlugin extends Plugin @Subscribe public void onConfigChanged(ConfigChanged configChanged) { - if (configChanged.getGroup().equals("clanchat")) + if (configChanged.getGroup().equals(ChatChannelConfig.GROUP)) { if (!config.recentChats()) { @@ -219,16 +228,7 @@ public class FriendsChatPlugin extends Plugin } // attempt to filter out world hopping joins - if (!activityBuffer.containsKey(member.getName())) - { - MemberActivity joinActivity = new MemberActivity(ActivityType.JOINED, - member, client.getTickCount()); - activityBuffer.put(member.getName(), joinActivity); - } - else - { - activityBuffer.remove(member.getName()); - } + queueJoin(member, MemberActivity.ChatType.FRIENDS_CHAT); } @Subscribe @@ -263,15 +263,75 @@ public class FriendsChatPlugin extends Plugin return; } - if (!activityBuffer.containsKey(member.getName())) + queueLeave(member, MemberActivity.ChatType.FRIENDS_CHAT); + } + + @Subscribe + public void onClanMemberJoined(ClanMemberJoined clanMemberJoined) + { + MemberActivity.ChatType chatType = clanChannelToChatType(clanMemberJoined.getClanChannel()); + if (chatType != null && clanChannelJoinLeaveEnabled(chatType)) { - MemberActivity leaveActivity = new MemberActivity(ActivityType.LEFT, + queueJoin(clanMemberJoined.getClanMember(), chatType); + } + } + + @Subscribe + public void onClanMemberLeft(ClanMemberLeft clanMemberLeft) + { + MemberActivity.ChatType chatType = clanChannelToChatType(clanMemberLeft.getClanChannel()); + if (chatType != null && clanChannelJoinLeaveEnabled(chatType)) + { + queueLeave(clanMemberLeft.getClanMember(), chatType); + } + } + + private MemberActivity.ChatType clanChannelToChatType(ClanChannel clanChannel) + { + return clanChannel == client.getClanChannel() ? MemberActivity.ChatType.CLAN_CHAT : + clanChannel == client.getGuestClanChannel() ? MemberActivity.ChatType.GUEST_CHAT : + null; + } + + private boolean clanChannelJoinLeaveEnabled(MemberActivity.ChatType chatType) + { + switch (chatType) + { + case CLAN_CHAT: + return config.clanChatShowJoinLeave(); + case GUEST_CHAT: + return config.guestClanChatShowJoinLeave(); + default: + return false; + } + } + + private void queueJoin(ChatPlayer member, MemberActivity.ChatType chatType) + { + // attempt to filter out world hopping joins + if (!activityBuffer.containsKey(member)) + { + MemberActivity joinActivity = new MemberActivity(ActivityType.JOINED, chatType, member, client.getTickCount()); - activityBuffer.put(member.getName(), leaveActivity); + activityBuffer.put(member, joinActivity); } else { - activityBuffer.remove(member.getName()); + activityBuffer.remove(member); + } + } + + private void queueLeave(ChatPlayer member, MemberActivity.ChatType chatType) + { + if (!activityBuffer.containsKey(member)) + { + MemberActivity leaveActivity = new MemberActivity(ActivityType.LEFT, chatType, + member, client.getTickCount()); + activityBuffer.put(member, leaveActivity); + } + else + { + activityBuffer.remove(member); } } @@ -334,7 +394,7 @@ public class FriendsChatPlugin extends Plugin // If this message has been reused since, it will get a different id if (joinMessage.getGetMessageId() == messageNode.getId()) { - ChatLineBuffer ccInfoBuffer = client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); + ChatLineBuffer ccInfoBuffer = client.getChatLineMap().get(messageNode.getType().getType()); if (ccInfoBuffer != null) { ccInfoBuffer.removeMessageNode(messageNode); @@ -357,8 +417,7 @@ public class FriendsChatPlugin extends Plugin private void addActivityMessages() { - FriendsChatManager friendsChatManager = client.getFriendsChatManager(); - if (friendsChatManager == null || activityBuffer.isEmpty()) + if (activityBuffer.isEmpty()) { return; } @@ -372,13 +431,28 @@ public class FriendsChatPlugin extends Plugin if (activity.getTick() < client.getTickCount() - MESSAGE_DELAY) { activityIt.remove(); - addActivityMessage(friendsChatManager, activity.getMember(), activity.getActivityType()); + switch (activity.getChatType()) + { + case FRIENDS_CHAT: + addActivityMessage((FriendsChatMember) activity.getMember(), activity.getActivityType()); + break; + case CLAN_CHAT: + case GUEST_CHAT: + addClanActivityMessage((ClanChannelMember) activity.getMember(), activity.getActivityType(), activity.getChatType()); + break; + } } } } - private void addActivityMessage(FriendsChatManager friendsChatManager, FriendsChatMember member, ActivityType activityType) + private void addActivityMessage(FriendsChatMember member, ActivityType activityType) { + final FriendsChatManager friendsChatManager = client.getFriendsChatManager(); + if (friendsChatManager == null) + { + return; + } + final String activityMessage = activityType == ActivityType.JOINED ? " has joined." : " has left."; final FriendsChatRank rank = member.getRank(); final Color textColor, channelColor; @@ -421,6 +495,55 @@ public class FriendsChatPlugin extends Plugin joinMessages.addLast(joinMessage); } + private void addClanActivityMessage(ClanChannelMember member, ActivityType activityType, MemberActivity.ChatType chatType) + { + ClanSettings clanSettings = chatType == MemberActivity.ChatType.CLAN_CHAT ? client.getClanSettings() : client.getGuestClanSettings(); + ClanRank rank = member.getRank(); + + if (rank == null || clanSettings == null) + { + return; + } + + ClanTitle clanTitle = clanSettings.titleForRank(rank); + int rankIcon = -1; + if (clanTitle != null) + { + // Clan ranks are always included in chat messages, so we'll just always include it in join messages. + rankIcon = chatIconManager.getIconNumber(clanTitle); + } + + final Color textColor; + // Use configured clan chat info colors if set, otherwise default to the jagex text and fc name colors + if (client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1) + { + textColor = MoreObjects.firstNonNull( + chatType == MemberActivity.ChatType.CLAN_CHAT ? chatColorConfig.transparentClanChatInfo() : chatColorConfig.transparentClanChatGuestInfo(), + CHAT_FC_TEXT_TRANSPARENT_BACKGROUND); + } + else + { + textColor = MoreObjects.firstNonNull( + chatType == MemberActivity.ChatType.CLAN_CHAT ? chatColorConfig.opaqueClanChatInfo() : chatColorConfig.opaqueClanChatGuestInfo(), + CHAT_FC_TEXT_OPAQUE_BACKGROUND); + } + + ChatMessageBuilder message = new ChatMessageBuilder(); + if (rankIcon > -1) + { + message.img(rankIcon); + } + message.append(textColor, member.getName() + (activityType == ActivityType.JOINED ? " has joined." : " has left.")); + + final String messageString = message.build(); + final MessageNode line = client.addChatMessage( + chatType == MemberActivity.ChatType.CLAN_CHAT ? ChatMessageType.CLAN_MESSAGE : ChatMessageType.CLAN_GUEST_MESSAGE, + "", messageString, ""); + + MemberJoinMessage joinMessage = new MemberJoinMessage(line, line.getId(), client.getTickCount()); + joinMessages.addLast(joinMessage); + } + @Subscribe public void onVarClientStrChanged(VarClientStrChanged strChanged) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MemberActivity.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MemberActivity.java similarity index 88% rename from runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MemberActivity.java rename to runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MemberActivity.java index 8e3135b99d..c71dce99f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MemberActivity.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MemberActivity.java @@ -22,17 +22,25 @@ * (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.friendschat; +package net.runelite.client.plugins.chatchannel; import lombok.AllArgsConstructor; import lombok.Value; -import net.runelite.api.FriendsChatMember; +import net.runelite.api.ChatPlayer; @Value @AllArgsConstructor class MemberActivity { + enum ChatType + { + FRIENDS_CHAT, + CLAN_CHAT, + GUEST_CHAT + } + private ActivityType activityType; - private FriendsChatMember member; + private ChatType chatType; + private ChatPlayer member; private Integer tick; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MemberJoinMessage.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MemberJoinMessage.java similarity index 96% rename from runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MemberJoinMessage.java rename to runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MemberJoinMessage.java index e90905d15c..adb7849593 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MemberJoinMessage.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MemberJoinMessage.java @@ -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.friendschat; +package net.runelite.client.plugins.chatchannel; import lombok.Value; import net.runelite.api.MessageNode; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MembersIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MembersIndicator.java similarity index 92% rename from runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MembersIndicator.java rename to runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MembersIndicator.java index 99b488fd90..a8d2b87775 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/MembersIndicator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatchannel/MembersIndicator.java @@ -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.friendschat; +package net.runelite.client.plugins.chatchannel; import java.awt.Color; import java.awt.image.BufferedImage; @@ -30,9 +30,9 @@ import net.runelite.client.ui.overlay.infobox.Counter; class MembersIndicator extends Counter { - private final FriendsChatPlugin plugin; + private final ChatChannelPlugin plugin; - MembersIndicator(BufferedImage image, FriendsChatPlugin plugin) + MembersIndicator(BufferedImage image, ChatChannelPlugin plugin) { super(image, plugin, plugin.getMembersSize()); this.plugin = plugin;