Created configurable chat channels

This commit is contained in:
Teriuihi 2021-08-05 11:40:42 +02:00
parent 9d9b8f0bf2
commit b9fae1cb35
8 changed files with 196 additions and 49 deletions

View File

@ -1,5 +1,6 @@
package com.alttd.chat.config; package com.alttd.chat.config;
import com.alttd.chat.objects.Channel;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
@ -14,9 +15,7 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public final class Config { public final class Config {
@ -238,9 +237,23 @@ public final class Config {
} }
public static List<String> CHATCHANNEL_CHANNELS = List.of("ac");
private static void chatChannels() { private static void chatChannels() {
CHATCHANNEL_CHANNELS = getList("chat-channels", CHATCHANNEL_CHANNELS); ConfigurationNode node = getNode("chat-channels");
if (node.isEmpty()) {
getString("chat-channels.ac.format", "<white><gray><sender></gray> <hover:show_text:on <server>><yellow>to <channel></yellow></hover><gray>: <message>");
getList("chat-channels.ac.servers", List.of("lobby"));
getBoolean("chat-channels.ac.proxy", false);
node = getNode("chat-channels");
}
for (ConfigurationNode configurationNode : node.getChildrenMap().values()) {
String channelName = Objects.requireNonNull(configurationNode.getKey()).toString();
String key = "chat-channels." + channelName + ".";
new Channel(channelName,
getString(key + "format", ""),
getList(key + "servers", Collections.EMPTY_LIST),
getBoolean(key + "proxy", false));
}
} }
public static String SERVERMUTEPERMISSION = "command.mute-server"; public static String SERVERMUTEPERMISSION = "command.mute-server";

View File

@ -0,0 +1,49 @@
package com.alttd.chat.objects;
import java.util.*;
public class Channel {
public static HashMap<String, Channel> channels = new HashMap<>();
private String permission;
private String channelName;
private String format;
private List<String> servers;
private boolean proxy;
public Channel(String channelName, String format, List<String> servers, boolean proxy) {
this.permission = "chat.channel." + channelName.toLowerCase();
this.channelName = channelName;
this.format = format;
this.servers = servers;
this.proxy = proxy;
channels.put(channelName.toLowerCase(), this);
}
public static Collection<Channel> getChannels() {
return channels.values();
}
public String getPermission() {
return permission;
}
public String getChannelName() {
return channelName;
}
public String getFormat() {
return format;
}
public List<String> getServers() {
return servers;
}
public boolean isProxy() {
return proxy;
}
public static Channel getChatChannel(String channelName) {
return channels.get(channelName.toLowerCase());
}
}

View File

@ -8,6 +8,7 @@ import com.alttd.chat.handler.ChatHandler;
import com.alttd.chat.listeners.ChatListener; import com.alttd.chat.listeners.ChatListener;
import com.alttd.chat.listeners.PlayerListener; import com.alttd.chat.listeners.PlayerListener;
import com.alttd.chat.listeners.PluginMessage; import com.alttd.chat.listeners.PluginMessage;
import com.alttd.chat.objects.Channel;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -15,7 +16,6 @@ import org.bukkit.command.PluginCommand;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.util.Collections;
import java.util.List; import java.util.List;
public class ChatPlugin extends JavaPlugin { public class ChatPlugin extends JavaPlugin {
@ -47,7 +47,9 @@ public class ChatPlugin extends JavaPlugin {
registerCommand("unignore", new Unignore()); registerCommand("unignore", new Unignore());
registerCommand("muteserver", new MuteServer()); registerCommand("muteserver", new MuteServer());
registerCommand("spy", new Spy()); registerCommand("spy", new Spy());
registerCommand("chatchannel", new ChatChannel(), Config.CHATCHANNEL_CHANNELS); for (Channel channel : Channel.getChannels()) {
this.getServer().getCommandMap().register(channel.getChannelName().toLowerCase(), new ChatChannel(channel));
}
messageChannel = Config.MESSAGECHANNEL; messageChannel = Config.MESSAGECHANNEL;
getServer().getMessenger().registerOutgoingPluginChannel(this, messageChannel); getServer().getMessenger().registerOutgoingPluginChannel(this, messageChannel);

View File

@ -1,17 +1,32 @@
package com.alttd.chat.commands; package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.ChatPlugin;
import net.kyori.adventure.text.minimessage.MiniMessage; import com.alttd.chat.objects.Channel;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class ChatChannel extends BukkitCommand {
Channel channel;
String command;
public ChatChannel(Channel channel) {
super(channel.getChannelName().toLowerCase());
this.channel = channel;
this.command = channel.getChannelName().toLowerCase();
this.description = "Chat channel named " + channel.getChannelName() + ".";
this.usageMessage = "/" + command + " <message>";
this.setAliases(Collections.emptyList());
}
public class ChatChannel implements CommandExecutor {
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean execute(@NotNull CommandSender sender, @NotNull String command, @NotNull String[] args) {
if(!(sender instanceof Player player)) { // must be a player if(!(sender instanceof Player player)) { // must be a player
return true; return true;
} }
@ -22,7 +37,7 @@ public class ChatChannel implements CommandExecutor {
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override
public void run() { public void run() {
ChatPlugin.getInstance().getChatHandler().chatChannel(player, label, message); ChatPlugin.getInstance().getChatHandler().chatChannel(player, channel, message);
} }
}.runTaskAsynchronously(ChatPlugin.getInstance()); }.runTaskAsynchronously(ChatPlugin.getInstance());

View File

@ -1,9 +1,11 @@
package com.alttd.chat.handler; package com.alttd.chat.handler;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.ChatPlugin;
import com.alttd.chat.commands.ChatChannel;
import com.alttd.chat.config.Config; import com.alttd.chat.config.Config;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.managers.RegexManager; import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.Channel;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.util.GalaxyUtility; import com.alttd.chat.util.GalaxyUtility;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
@ -117,13 +119,13 @@ public class ChatHandler {
sendPluginMessage(player, "globalchat", component); sendPluginMessage(player, "globalchat", component);
} }
public void chatChannel(Player player, String label, String message) { public void chatChannel(Player player, Channel channel, String message) {
if (!player.hasPermission("chat.channel." + label)) { if (!player.hasPermission(channel.getPermission())) {
player.sendMessage(MiniMessage.get().parse("<red>You don't have permission to use this channel.</red>")); player.sendMessage(MiniMessage.get().parse("<red>You don't have permission to use this channel.</red>"));
return; return;
} }
if (isMuted(player, message, "[" + StringUtils.capitalize(label) + " Muted] ")) return; if (isMuted(player, message, "[" + channel.getChannelName() + " Muted] ")) return;
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
Component senderName = user.getDisplayName(); Component senderName = user.getDisplayName();
@ -144,28 +146,24 @@ public class ChatHandler {
Template.of("sender", senderName), Template.of("sender", senderName),
Template.of("message", updatedMessage), Template.of("message", updatedMessage),
Template.of("server", Bukkit.getServerName()), Template.of("server", Bukkit.getServerName()),
Template.of("channel", channel.getChannelName()),
Template.of("[i]", itemComponent(player.getInventory().getItemInMainHand())))); Template.of("[i]", itemComponent(player.getInventory().getItemInMainHand()))));
Component component = miniMessage.parse(Config.GCFORMAT, templates); Component component = miniMessage.parse(channel.getFormat(), templates);
sendChatChannelMessage(player, label, "chatchannel", component);
if (channel.isProxy()) {
sendChatChannelMessage(player, channel.getChannelName(), "chatchannel", component);
} else {
sendChatChannelMessage(channel, component);
}
} }
private boolean isMuted(Player player, String message, String prefix) { private void sendChatChannelMessage(Channel chatChannel, Component component) {
if (Database.get().isPlayerMuted(player.getUniqueId(), null) || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission("chat.bypass-server-muted"))) { if (!chatChannel.getServers().contains(Bukkit.getServerName())) return;
MiniMessage miniMessage = MiniMessage.get();
Component blockedNotification = miniMessage.parse("<red>" + prefix
+ Utility.getDisplayName(player.getUniqueId(), player.getName())
+ " tried to say: "
+ message + "</red>");
Bukkit.getOnlinePlayers().forEach(a ->{ Bukkit.getServer().getOnlinePlayers().stream()
if (a.hasPermission("chat.alert-blocked")) { .filter(p -> p.hasPermission(chatChannel.getPermission()))
a.sendMessage(blockedNotification);//TODO make configurable (along with all the messages) .forEach(p -> p.sendMessage(component));
}
});
return true;
}
return false;
} }
private void sendPluginMessage(Player player, String channel, Component component) { private void sendPluginMessage(Player player, String channel, Component component) {
@ -185,15 +183,33 @@ public class ChatHandler {
player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray()); player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray());
} }
public void sendChatChannelMessage(Player player, String label, String channel, Component component) { public void sendChatChannelMessage(Player player, String chatChannelName, String channel, Component component) {
ByteArrayDataOutput out = ByteStreams.newDataOutput(); ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF(channel); out.writeUTF(channel);
out.writeUTF(label); out.writeUTF(chatChannelName);
out.writeUTF(GsonComponentSerializer.gson().serialize(component)); out.writeUTF(GsonComponentSerializer.gson().serialize(component));
player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray()); player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray());
} }
// Start - move these to util // Start - move these to util
private boolean isMuted(Player player, String message, String prefix) {
if (Database.get().isPlayerMuted(player.getUniqueId(), null) || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission("chat.bypass-server-muted"))) {
MiniMessage miniMessage = MiniMessage.get();
Component blockedNotification = miniMessage.parse("<red>" + prefix
+ Utility.getDisplayName(player.getUniqueId(), player.getName())
+ " tried to say: "
+ message + "</red>");
Bukkit.getOnlinePlayers().forEach(a ->{
if (a.hasPermission("chat.alert-blocked")) {
a.sendMessage(blockedNotification);//TODO make configurable (along with all the messages)
}
});
return true;
}
return false;
}
public static Component itemComponent(ItemStack item) { public static Component itemComponent(ItemStack item) {
Component component = Component.text("[i]", NamedTextColor.AQUA); Component component = Component.text("[i]", NamedTextColor.AQUA);
if(item.getType().equals(Material.AIR)) if(item.getType().equals(Material.AIR))

View File

@ -4,6 +4,7 @@ import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config; import com.alttd.chat.config.Config;
import com.alttd.chat.database.Queries; import com.alttd.chat.database.Queries;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.objects.Channel;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
@ -60,31 +61,58 @@ public class PluginMessage implements PluginMessageListener {
if(!chatUser.getIgnoredPlayers().contains(targetUUID)) { if(!chatUser.getIgnoredPlayers().contains(targetUUID)) {
chatUser.addIgnoredPlayers(targetUUID); chatUser.addIgnoredPlayers(targetUUID);
} }
break;
} }
case "unignore": { case "unignore": {
ChatUser chatUser = ChatUserManager.getChatUser(UUID.fromString(in.readUTF())); ChatUser chatUser = ChatUserManager.getChatUser(UUID.fromString(in.readUTF()));
chatUser.removeIgnoredPlayers(UUID.fromString(in.readUTF())); chatUser.removeIgnoredPlayers(UUID.fromString(in.readUTF()));
break;
} }
case "chatchannel": { case "chatchannel": {
if (ChatPlugin.getInstance().serverMuted()) break; if (ChatPlugin.getInstance().serverMuted()) break;
String chatChannel = in.readUTF(); chatChannel(in);
Component component = GsonComponentSerializer.gson().deserialize(in.readUTF());
new BukkitRunnable() {
@Override
public void run() {
Bukkit.getOnlinePlayers().stream()
.filter(p -> p.hasPermission("chat.channel." + chatChannel))
.forEach(p -> p.sendMessage(component));
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
} }
default: default:
break; break;
} }
} }
private void chatChannel(ByteArrayDataInput in) {
Channel chatChannel = null;
Component component = null;
try {
chatChannel = Channel.getChatChannel(in.readUTF());
component = GsonComponentSerializer.gson().deserialize(in.readUTF());
} catch (Exception e) { //Idk the exception for reading too far into in.readUTF()
e.printStackTrace();
}
if (chatChannel == null) {
ALogger.warn("Received ChatChannel message for non existent channel.");
return;
}
if (!chatChannel.getServers().contains(Bukkit.getServerName())) {
ALogger.warn("Received ChatChannel message for the wrong server.");
return;
}
if (component == null) {
ALogger.warn("Didn't receive a valid message for ChatChannel " + chatChannel.getChannelName() + ".");
}
final Channel finalChatChannel = chatChannel;
final Component finalComponent = component;
new BukkitRunnable() {
@Override
public void run() {
Bukkit.getOnlinePlayers().stream()
.filter(p -> p.hasPermission(finalChatChannel.getPermission()))
.forEach(p -> p.sendMessage(finalComponent));
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}
} }
/* // todo implement AdvancedChatFilter for this like this /* // todo implement AdvancedChatFilter for this like this
// send pluginmessage to backend server and return a shatteredcomponent to be reparsed by proxy // send pluginmessage to backend server and return a shatteredcomponent to be reparsed by proxy

View File

@ -26,6 +26,4 @@ commands:
muteserver: muteserver:
permission: command.mute-server permission: command.mute-server
spy: spy:
permission: command.togglespy permission: command.togglespy
chatchannel:
permission: chat.channel.chatchannel

View File

@ -1,14 +1,21 @@
package com.alttd.chat.listeners; package com.alttd.chat.listeners;
import com.alttd.chat.VelocityChat; import com.alttd.chat.VelocityChat;
import com.alttd.chat.objects.Channel;
import com.alttd.chat.util.ALogger;
import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class PluginMessageListener { public class PluginMessageListener {
@ -43,8 +50,27 @@ public class PluginMessageListener {
case "privatemessage": // TODO redirect this to the server that player is on case "privatemessage": // TODO redirect this to the server that player is on
VelocityChat.getPlugin().getChatHandler().privateMessage(in.readUTF(), in.readUTF(), in.readUTF()); VelocityChat.getPlugin().getChatHandler().privateMessage(in.readUTF(), in.readUTF(), in.readUTF());
break; break;
case "chatchannel": {
String channelName = in.readUTF();
Channel chatChannel = Channel.getChatChannel(channelName);
if (chatChannel == null) {
ALogger.warn("Received non existent channel" + channelName +".");
break;
}
ProxyServer proxy = VelocityChat.getPlugin().getProxy();
chatChannel.getServers().forEach(server -> proxy.getServer(server).ifPresent(registeredServer ->
registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData())));
break;
}
default: default:
VelocityChat.getPlugin().getLogger().info("server " + event.getSource()); VelocityChat.getPlugin().getLogger().info("server " + event.getSource());
ProxyServer proxy = VelocityChat.getPlugin().getProxy();
for (RegisteredServer registeredServer : proxy.getAllServers()) {
registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData());
}
break; break;
} }
} }