From 62850b2e11d37916d3bc5f88a1ee568b3d569fbf Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Fri, 16 Oct 2026 11:07:05 +0200 Subject: [PATCH] Let moderators read all fight chats automatically /chat arenas join|leave lets moderators read the fight and team chats of every arena and event spectate server; the choice is saved across relogs. /chat leave excludes a single arena for the session. --- .../steamwar/messages/BungeeCore.properties | 3 ++ .../messages/BungeeCore_de.properties | 3 ++ .../velocitycore/chat/ChatManager.java | 48 ++++++++++++++++--- .../velocitycore/commands/ChatCommand.java | 5 ++ 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index 0dfd9688d..dc41683fc 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -618,6 +618,9 @@ CHAT_FIGHT_NO_TEAM = §cYou are not in a fight team. GLOBAL_USAGE = §8/§7global §8[§emessage§8] CHAT_USAGE = §8/§7chat §8[§echannel§8] [§ejoin§8|§eleave§8] CHAT_MSG_USAGE = §8/§7chat §8[§echannel§8] §7msg §8[§emessage§8] +CHAT_ARENAS_USAGE = §8/§7chat §7arenas §8[§ejoin§8|§eleave§8] +CHAT_ARENAS_JOINED = §7You now read the chats of all fights. +CHAT_ARENAS_LEFT = §7You no longer read the chats of all fights. CHAT_CHANNEL_UNKNOWN = §cUnknown chat channel. CHAT_CHANNEL_JOINED = §7You are reading §e{0} §7again. CHAT_CHANNEL_LEFT = §7You no longer read §e{0}§7. diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index 73c8273c1..b0c70a21c 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -583,6 +583,9 @@ CHAT_FIGHT_NO_TEAM = §cDu bist in keinem Kampfteam. GLOBAL_USAGE = §8/§7global §8[§eNachricht§8] CHAT_USAGE = §8/§7chat §8[§eKanal§8] [§ejoin§8|§eleave§8] CHAT_MSG_USAGE = §8/§7chat §8[§eKanal§8] §7msg §8[§eNachricht§8] +CHAT_ARENAS_USAGE = §8/§7chat §7arenas §8[§ejoin§8|§eleave§8] +CHAT_ARENAS_JOINED = §7Du liest jetzt die Chats aller Fights mit. +CHAT_ARENAS_LEFT = §7Du liest die Chats aller Fights nicht mehr mit. CHAT_CHANNEL_UNKNOWN = §cUnbekannter Chatkanal. CHAT_CHANNEL_JOINED = §7Du liest §e{0} §7wieder mit. CHAT_CHANNEL_LEFT = §7Du liest §e{0} §7nicht mehr mit. diff --git a/VelocityCore/src/de/steamwar/velocitycore/chat/ChatManager.java b/VelocityCore/src/de/steamwar/velocitycore/chat/ChatManager.java index 199cda661..76d758441 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/chat/ChatManager.java +++ b/VelocityCore/src/de/steamwar/velocitycore/chat/ChatManager.java @@ -57,6 +57,7 @@ public class ChatManager extends BasicListener { private static final String CONFIG_KEY = "chat.channel"; private static final String HIDDEN_KEY = "chat.hidden"; + private static final String ARENAS_KEY = "chat.arenas"; private static final long REFEREE_CACHE_MILLIS = 60_000; @Getter @@ -76,6 +77,8 @@ public class ChatManager extends BasicListener { private static final Set globalOnArena = ConcurrentHashMap.newKeySet(); private static final Set announced = ConcurrentHashMap.newKeySet(); private static final Map> spies = new ConcurrentHashMap<>(); + private static final Map allArenas = new ConcurrentHashMap<>(); + private static final Map> leftArenas = new ConcurrentHashMap<>(); private static final Map> hidden = new ConcurrentHashMap<>(); private static int refereeEvent = -1; @@ -159,16 +162,41 @@ public class ChatManager extends BasicListener { return !currentServer(player).map(ChatManager::isArena).orElse(false) || globalOnArena.contains(player.getUniqueId()); } + /** + * @return the moderators reading the fight chats of the server without being on it + */ static Stream spies(RegisteredServer server) { - return spies.entrySet().stream() - .filter(entry -> entry.getValue().contains(server)) - .map(entry -> VelocityCore.getProxy().getPlayer(entry.getKey()).orElse(null)) - .filter(Objects::nonNull) + return Chatter.allPlayers() .map(Chatter::of) + .filter(chatter -> !onServer(chatter, server)) .filter(chatter -> chatter.user().hasPerm(UserPerm.MODERATION)) + .filter(chatter -> readsArena(chatter.user().getUUID(), server)) .map(Chatter.class::cast); } + private static boolean readsArena(UUID uuid, RegisteredServer server) { + Set joined = spies.get(uuid); + if (joined != null && joined.contains(server)) return true; + + Set left = leftArenas.get(uuid); + return readsAllArenas(uuid) && (left == null || !left.contains(server)); + } + + private static boolean readsAllArenas(UUID uuid) { + return allArenas.computeIfAbsent(uuid, u -> "true".equals(UserConfig.getConfig(u, ARENAS_KEY))); + } + + /** + * Lets a moderator read the fight chats of every fight server automatically, saved across relogs. + */ + public static void setReadAllArenas(PlayerChatter player, boolean read) { + UUID uuid = player.user().getUUID(); + allArenas.put(uuid, read); + leftArenas.remove(uuid); + UserConfig.updatePlayerConfig(uuid, ARENAS_KEY, read ? "true" : null); + player.system(read ? "CHAT_ARENAS_JOINED" : "CHAT_ARENAS_LEFT"); + } + /** * @return true if the user is a referee of the event fight running on the server */ @@ -223,7 +251,10 @@ public class ChatManager extends BasicListener { public static void join(PlayerChatter player, ChatChannel channel) { UUID uuid = player.user().getUUID(); if (isForeignArena(player, channel)) { - spies.computeIfAbsent(uuid, u -> ConcurrentHashMap.newKeySet()).add(((LocalChannel) channel).getServer()); + RegisteredServer server = ((LocalChannel) channel).getServer(); + spies.computeIfAbsent(uuid, u -> ConcurrentHashMap.newKeySet()).add(server); + Set left = leftArenas.get(uuid); + if (left != null) left.remove(server); player.system("CHAT_CHANNEL_JOINED", channel.tag(player)); return; } @@ -237,8 +268,11 @@ public class ChatManager extends BasicListener { public static void leave(PlayerChatter player, ChatChannel channel) { UUID uuid = player.user().getUUID(); if (isForeignArena(player, channel)) { + RegisteredServer server = ((LocalChannel) channel).getServer(); Set servers = spies.get(uuid); - if (servers != null) servers.remove(((LocalChannel) channel).getServer()); + if (servers != null) servers.remove(server); + // Excludes the arena for this session while reading all arenas + leftArenas.computeIfAbsent(uuid, u -> ConcurrentHashMap.newKeySet()).add(server); player.system("CHAT_CHANNEL_LEFT", channel.tag(player)); return; } @@ -445,6 +479,8 @@ public class ChatManager extends BasicListener { globalOnArena.remove(uuid); announced.remove(uuid); spies.remove(uuid); + allArenas.remove(uuid); + leftArenas.remove(uuid); hidden.remove(uuid); directs.removeIf(channel -> channel.contains(uuid)); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/ChatCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/ChatCommand.java index 55fb5d9c1..106042f4a 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/ChatCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/ChatCommand.java @@ -61,6 +61,11 @@ public class ChatCommand extends SWCommand { } } + @Register(value = "arenas", description = "CHAT_ARENAS_USAGE") + public void arenas(@Validator("moderator") PlayerChatter sender, @StaticValue(value = {"leave", "join"}, allowISE = true) boolean join) { + ChatManager.setReadAllArenas(sender, join); + } + @Register(description = "CHAT_MSG_USAGE") public void msg(@Validator("moderator") PlayerChatter sender, ChatChannel channel, @StaticValue("msg") String msg, @ErrorMessage(value = "CHAT_MSG_USAGE", allowEAs = false) String... message) { channel.send(sender, String.join(" ", message));