From 9dd3047ced58f375a66ae80951fb0f4107108937 Mon Sep 17 00:00:00 2001 From: Oskar Nordling Date: Fri, 7 Feb 2025 00:03:55 +0100 Subject: [PATCH] #7: implement velocity version of staffchat --- src/main/resources/config.yml | 1 + .../staffchat/velocity/VelocityStaffChat.java | 117 +++++++++++++++++ .../command/VelocityStaffChatCommand.java | 122 ++++++++++++++++++ .../handler/VelocityStaffChatHandler.java | 55 ++++++++ .../listener/VelocityStaffChatListener.java | 30 +++++ 5 files changed, 325 insertions(+) create mode 100644 src/velocity/java/me/oskar3123/staffchat/velocity/VelocityStaffChat.java create mode 100644 src/velocity/java/me/oskar3123/staffchat/velocity/command/VelocityStaffChatCommand.java create mode 100644 src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java create mode 100644 src/velocity/java/me/oskar3123/staffchat/velocity/listener/VelocityStaffChatListener.java diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 98f7b19..c6b320a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -8,6 +8,7 @@ messages: nopermission: '&cYou don''t have permission to do that' playeronly: '&cPlayer only command' reloaded: 'Reloaded the config file' + reload-failed: '&cFailed to reload the config file' toggled: 'You toggled auto staffchat %s' onstring: 'on' offstring: 'off' diff --git a/src/velocity/java/me/oskar3123/staffchat/velocity/VelocityStaffChat.java b/src/velocity/java/me/oskar3123/staffchat/velocity/VelocityStaffChat.java new file mode 100644 index 0000000..ba5fc08 --- /dev/null +++ b/src/velocity/java/me/oskar3123/staffchat/velocity/VelocityStaffChat.java @@ -0,0 +1,117 @@ +package me.oskar3123.staffchat.velocity; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; +import com.velocitypowered.api.plugin.Plugin; +import com.velocitypowered.api.plugin.annotation.DataDirectory; +import com.velocitypowered.api.proxy.ProxyServer; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import me.oskar3123.staffchat.velocity.command.VelocityStaffChatCommand; +import me.oskar3123.staffchat.velocity.handler.VelocityStaffChatHandler; +import me.oskar3123.staffchat.velocity.listener.VelocityStaffChatListener; +import org.bstats.velocity.Metrics; +import org.slf4j.Logger; +import org.spongepowered.configurate.CommentedConfigurationNode; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; + +@Plugin( + id = "staffchat", + name = "StaffChat", + version = VelocityStaffChat.PLUGIN_VERSION, + description = "A staff chat plugin", + authors = {"oskar3123"}) +public class VelocityStaffChat { + + public static final String PLUGIN_VERSION = "SNAPSHOT"; + + private static final int BSTATS_PLUGIN_ID = 24679; + + private final ProxyServer server; + private final Logger logger; + private final Path dataDirectory; + private final Metrics.Factory metricsFactory; + private VelocityStaffChatHandler staffChatHandler; + private CommentedConfigurationNode config; + + @Inject + public VelocityStaffChat( + ProxyServer server, + Logger logger, + @DataDirectory Path dataDirectory, + Metrics.Factory metricsFactory) { + this.server = server; + this.logger = logger; + this.dataDirectory = dataDirectory; + this.metricsFactory = metricsFactory; + } + + @Subscribe + public void onProxyInitialization(ProxyInitializeEvent event) { + try { + config = loadConfig(); + + // Initialize metrics + metricsFactory.make(this, BSTATS_PLUGIN_ID); + + // Initialize handler + staffChatHandler = new VelocityStaffChatHandler(this); + + // Register commands + server + .getCommandManager() + .register( + server.getCommandManager().metaBuilder("staffchat").build(), + new VelocityStaffChatCommand(this)); + + // Register listeners + server.getEventManager().register(this, new VelocityStaffChatListener(this)); + + logger.info("StaffChat has been enabled!"); + } catch (IOException e) { + logger.error("Failed to start StaffChat!", e); + } + } + + @Subscribe + public void onProxyShutdown(ProxyShutdownEvent event) { + logger.info("StaffChat has been disabled!"); + } + + public VelocityStaffChatHandler getStaffChatHandler() { + return staffChatHandler; + } + + public ProxyServer getServer() { + return server; + } + + public void reloadConfig() throws IOException { + config = loadConfig(); + } + + public CommentedConfigurationNode getConfig() { + return config; + } + + private CommentedConfigurationNode loadConfig() throws IOException { + if (Files.notExists(dataDirectory)) { + Files.createDirectory(dataDirectory); + } + Path config = dataDirectory.resolve("config.yml"); + if (Files.notExists(config)) { + try (InputStream stream = getClass().getClassLoader().getResourceAsStream("config.yml")) { + if (stream == null) { + throw new IOException("no default config.yml"); + } + Files.copy(stream, config); + } + } + YamlConfigurationLoader loader = YamlConfigurationLoader.builder().path(config).build(); + return loader.load(); + } +} diff --git a/src/velocity/java/me/oskar3123/staffchat/velocity/command/VelocityStaffChatCommand.java b/src/velocity/java/me/oskar3123/staffchat/velocity/command/VelocityStaffChatCommand.java new file mode 100644 index 0000000..44c3fd2 --- /dev/null +++ b/src/velocity/java/me/oskar3123/staffchat/velocity/command/VelocityStaffChatCommand.java @@ -0,0 +1,122 @@ +package me.oskar3123.staffchat.velocity.command; + +import com.velocitypowered.api.command.CommandSource; +import com.velocitypowered.api.command.SimpleCommand; +import com.velocitypowered.api.proxy.Player; +import java.io.IOException; +import me.oskar3123.staffchat.velocity.VelocityStaffChat; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.configurate.CommentedConfigurationNode; + +public class VelocityStaffChatCommand implements SimpleCommand { + + private final VelocityStaffChat plugin; + private CommentedConfigurationNode config; + + public VelocityStaffChatCommand(VelocityStaffChat plugin) { + this.plugin = plugin; + config = plugin.getConfig(); + } + + @Override + public void execute(Invocation invocation) { + CommandSource sender = invocation.source(); + String label = invocation.alias(); + String[] args = invocation.arguments(); + + Component noPerm = + txt( + config.node("messages", "prefix").getString() + + config.node("messages", "nopermission").getString()); + if (!sender.hasPermission("staffchat.command")) { + sender.sendMessage(noPerm); + return; + } + if (args.length < 1) { + help(sender, label); + return; + } + if (args[0].equalsIgnoreCase("reload")) { + if (sender.hasPermission("staffchat.reload")) { + reload(sender); + } else { + sender.sendMessage(noPerm); + } + return; + } else if (args[0].equalsIgnoreCase("toggle")) { + if (sender.hasPermission("staffchat.use")) { + toggle(sender); + } else { + sender.sendMessage(noPerm); + } + return; + } + help(sender, label); + } + + @Override + public boolean hasPermission(Invocation invocation) { + return invocation.source().hasPermission("staffchat.command"); + } + + private void playerOnly(@NotNull CommandSource sender) { + sender.sendMessage( + txt( + config.node("messages", "prefix").getString() + + config.node("messages", "playeronly").getString())); + } + + private void help(@NotNull CommandSource sender, String label) { + String prefix = config.node("messages", "prefix").getString(); + sender.sendMessage( + txt(prefix + "Version " + VelocityStaffChat.PLUGIN_VERSION + ", made by oskar3123")); + if (sender.hasPermission("staffchat.use")) { + sender.sendMessage( + txt(prefix + "Message prefix: " + config.node("settings", "character").getString())); + sender.sendMessage(txt(prefix + "/" + label + " toggle - Toggles auto staffchat")); + } + if (sender.hasPermission("staffchat.reload")) { + sender.sendMessage(txt(prefix + "/" + label + " reload - Reloads the config file")); + } + } + + private void reload(@NotNull CommandSource sender) { + try { + plugin.reloadConfig(); + config = plugin.getConfig(); + sender.sendMessage( + txt( + config.node("messages", "prefix").getString() + + config.node("messages", "reloaded").getString())); + } catch (IOException e) { + sender.sendMessage( + txt( + config.node("messages", "prefix").getString() + + config + .node("messages", "reload-failed") + .getString("Failed to reload the config file"))); + } + } + + private void toggle(@NotNull CommandSource sender) { + if (!(sender instanceof Player player)) { + playerOnly(sender); + return; + } + boolean toggled = plugin.getStaffChatHandler().togglePlayer(player.getUniqueId()); + String state = + toggled + ? config.node("messages", "onstring").getString() + : config.node("messages", "offstring").getString(); + sender.sendMessage( + txt( + config.node("messages", "prefix").getString() + + String.format(config.node("messages", "toggled").getString(""), state))); + } + + private @NotNull Component txt(@NotNull String text) { + return LegacyComponentSerializer.legacyAmpersand().deserialize(text); + } +} diff --git a/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java b/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java new file mode 100644 index 0000000..579ed65 --- /dev/null +++ b/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java @@ -0,0 +1,55 @@ +package me.oskar3123.staffchat.velocity.handler; + +import com.velocitypowered.api.proxy.Player; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.function.Function; +import me.oskar3123.staffchat.util.FormatUtils; +import me.oskar3123.staffchat.velocity.VelocityStaffChat; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +public class VelocityStaffChatHandler { + + private static final String DEFAULT_FORMAT = "&b{NAME}: {MESSAGE}"; + + private final VelocityStaffChat plugin; + private final Set toggledPlayers; + + public VelocityStaffChatHandler(VelocityStaffChat plugin) { + this.plugin = plugin; + this.toggledPlayers = new HashSet<>(); + } + + public boolean isToggled(UUID uuid) { + return toggledPlayers.contains(uuid); + } + + public boolean togglePlayer(UUID uuid) { + if (toggledPlayers.contains(uuid)) { + toggledPlayers.remove(uuid); + return false; + } else { + toggledPlayers.add(uuid); + return true; + } + } + + public void broadcastStaffMessage(Player sender, String message) { + if (message.isEmpty()) { + return; + } + + String formattedMessage = + FormatUtils.replacePlaceholders( + DEFAULT_FORMAT, Function.identity(), sender::getUsername, message); + + TextComponent component = + LegacyComponentSerializer.legacyAmpersand().deserialize(formattedMessage); + plugin.getServer().getAllPlayers().stream() + .filter(p -> p.hasPermission("staffchat.see")) + .forEach(p -> p.sendMessage(component)); + plugin.getServer().getConsoleCommandSource().sendMessage(component); + } +} diff --git a/src/velocity/java/me/oskar3123/staffchat/velocity/listener/VelocityStaffChatListener.java b/src/velocity/java/me/oskar3123/staffchat/velocity/listener/VelocityStaffChatListener.java new file mode 100644 index 0000000..8a0c51c --- /dev/null +++ b/src/velocity/java/me/oskar3123/staffchat/velocity/listener/VelocityStaffChatListener.java @@ -0,0 +1,30 @@ +package me.oskar3123.staffchat.velocity.listener; + +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.player.PlayerChatEvent; +import com.velocitypowered.api.proxy.Player; +import me.oskar3123.staffchat.velocity.VelocityStaffChat; + +public class VelocityStaffChatListener { + + private final VelocityStaffChat plugin; + + public VelocityStaffChatListener(VelocityStaffChat plugin) { + this.plugin = plugin; + } + + @Subscribe + public void onPlayerChat(PlayerChatEvent event) { + String character = plugin.getConfig().node("settings", "character").getString("@"); + Player player = event.getPlayer(); + String message = event.getMessage(); + boolean toggled = plugin.getStaffChatHandler().isToggled(player.getUniqueId()); + + // Check if player has staff chat toggled on or message starts with @ + if ((toggled || message.startsWith(character)) && player.hasPermission("staffchat.use")) { + String staffMessage = toggled ? message : message.substring(character.length()).trim(); + plugin.getStaffChatHandler().broadcastStaffMessage(player, staffMessage); + event.setResult(PlayerChatEvent.ChatResult.denied()); + } + } +}