Merge pull request #28 from oskar3123/7-velocity-support

Support for Velocity
This commit is contained in:
2025-02-07 22:29:19 +01:00
committed by GitHub
9 changed files with 376 additions and 9 deletions
+5 -3
View File
@@ -23,10 +23,12 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up JDK 8 - name: Set up JDK 8 and 17
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
java-version: '8' java-version: |
8
17
distribution: 'corretto' distribution: 'corretto'
- name: Build with Gradle - name: Build with Gradle
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
+5 -3
View File
@@ -12,10 +12,12 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up JDK 8 - name: Set up JDK 8 and 17
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
java-version: '8' java-version: |
8
17
distribution: 'corretto' distribution: 'corretto'
- name: Build with Gradle - name: Build with Gradle
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
+5 -3
View File
@@ -12,10 +12,12 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up JDK 8 - name: Set up JDK 8 and 17
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
java-version: '8' java-version: |
8
17
distribution: 'corretto' distribution: 'corretto'
- name: Build with Gradle - name: Build with Gradle
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
+36
View File
@@ -6,12 +6,39 @@ plugins {
group = "me.oskar3123" group = "me.oskar3123"
version = "SNAPSHOT" version = "SNAPSHOT"
// Main sourceSet remains on Java 8
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
toolchain { toolchain {
languageVersion.set(JavaLanguageVersion.of(8)) 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<JavaCompile>("compileVelocityJava") {
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
}
repositories { repositories {
mavenCentral() mavenCentral()
maven { maven {
@@ -30,6 +57,10 @@ repositories {
maven { maven {
url = uri("https://nexus.scarsz.me/content/groups/public/") url = uri("https://nexus.scarsz.me/content/groups/public/")
} }
maven {
name = "papermc"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
} }
dependencies { dependencies {
@@ -37,9 +68,12 @@ dependencies {
compileOnly("net.md-5:bungeecord-api:1.20-R0.2-SNAPSHOT") compileOnly("net.md-5:bungeecord-api:1.20-R0.2-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.1") compileOnly("me.clip:placeholderapi:2.11.1")
compileOnly("com.discordsrv:discordsrv:1.25.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-bukkit:3.0.2")
implementation("org.bstats:bstats-bungeecord: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(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
@@ -47,6 +81,8 @@ dependencies {
tasks.shadowJar { tasks.shadowJar {
relocate("org.bstats", "me.oskar3123.staffchat.bstats") relocate("org.bstats", "me.oskar3123.staffchat.bstats")
dependsOn("compileVelocityJava")
from(sourceSets["velocity"].output)
} }
tasks.test { tasks.test {
+1
View File
@@ -8,6 +8,7 @@ messages:
nopermission: '&cYou don''t have permission to do that' nopermission: '&cYou don''t have permission to do that'
playeronly: '&cPlayer only command' playeronly: '&cPlayer only command'
reloaded: 'Reloaded the config file' reloaded: 'Reloaded the config file'
reload-failed: '&cFailed to reload the config file'
toggled: 'You toggled auto staffchat %s' toggled: 'You toggled auto staffchat %s'
onstring: 'on' onstring: 'on'
offstring: 'off' offstring: 'off'
@@ -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();
}
}
@@ -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);
}
}
@@ -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<UUID> 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);
}
}
@@ -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());
}
}
}