From 82559d10c65c23b829515bb13e55dd6915e9e606 Mon Sep 17 00:00:00 2001 From: Oskar Nordling Date: Thu, 6 Feb 2025 22:03:11 +0100 Subject: [PATCH 1/4] #7: make github workflows setup correct jdk versions --- .github/workflows/build.yml | 8 +++++--- .github/workflows/pre-release.yml | 8 +++++--- .github/workflows/tagged-release.yml | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4c03ef2..78a02fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,10 +23,12 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 - uses: actions/setup-java@v3 + - name: Set up JDK 8 and 17 + uses: actions/setup-java@v4 with: - java-version: '8' + java-version: | + 8 + 17 distribution: 'corretto' - name: Build with Gradle uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 620a7ff..517552a 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -12,10 +12,12 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 - uses: actions/setup-java@v3 + - name: Set up JDK 8 and 17 + uses: actions/setup-java@v4 with: - java-version: '8' + java-version: | + 8 + 17 distribution: 'corretto' - name: Build with Gradle uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 diff --git a/.github/workflows/tagged-release.yml b/.github/workflows/tagged-release.yml index 57f8977..cb011af 100644 --- a/.github/workflows/tagged-release.yml +++ b/.github/workflows/tagged-release.yml @@ -12,10 +12,12 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 - uses: actions/setup-java@v3 + - name: Set up JDK 8 and 17 + uses: actions/setup-java@v4 with: - java-version: '8' + java-version: | + 8 + 17 distribution: 'corretto' - name: Build with Gradle uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 From 23527c65a8f7b793e608dc9f9f57daf461eedb60 Mon Sep 17 00:00:00 2001 From: Oskar Nordling Date: Thu, 6 Feb 2025 21:34:44 +0100 Subject: [PATCH 2/4] #7: add velocity sourceset that builds with java 17 --- build.gradle.kts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 133152c..9718a45 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,12 +6,39 @@ plugins { group = "me.oskar3123" version = "SNAPSHOT" +// Main sourceSet remains on Java 8 java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + toolchain { languageVersion.set(JavaLanguageVersion.of(8)) } } +// Create a sourceSet for Velocity code that uses Java 17 +sourceSets { + create("velocity") { + java { + srcDir("src/velocity/java") + compileClasspath += sourceSets.main.get().output + sourceSets.main.get().compileClasspath + runtimeClasspath += sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath + } + } +} + +// Configure the automatically created Velocity compilation task to use Java 17 +tasks.named("compileVelocityJava") { + java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } + } +} + repositories { mavenCentral() maven { @@ -47,6 +74,8 @@ dependencies { tasks.shadowJar { relocate("org.bstats", "me.oskar3123.staffchat.bstats") + dependsOn("compileVelocityJava") + from(sourceSets["velocity"].output) } tasks.test { From 75874023a63fa5160284f8419f081cb56f7f3623 Mon Sep 17 00:00:00 2001 From: Oskar Nordling Date: Thu, 6 Feb 2025 21:35:18 +0100 Subject: [PATCH 3/4] #7: add velocity dependencies --- build.gradle.kts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 9718a45..45bdf97 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -57,6 +57,10 @@ repositories { maven { url = uri("https://nexus.scarsz.me/content/groups/public/") } + maven { + name = "papermc" + url = uri("https://repo.papermc.io/repository/maven-public/") + } } dependencies { @@ -64,9 +68,12 @@ dependencies { compileOnly("net.md-5:bungeecord-api:1.20-R0.2-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.11.1") compileOnly("com.discordsrv:discordsrv:1.25.1") + "velocityCompileOnly"("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") + "velocityAnnotationProcessor"("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") implementation("org.bstats:bstats-bukkit:3.0.2") implementation("org.bstats:bstats-bungeecord:3.0.2") + implementation("org.bstats:bstats-velocity:3.0.2") testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") From 9dd3047ced58f375a66ae80951fb0f4107108937 Mon Sep 17 00:00:00 2001 From: Oskar Nordling Date: Fri, 7 Feb 2025 00:03:55 +0100 Subject: [PATCH 4/4] #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()); + } + } +}