From e0ac486d6124cbf7f15bb57fb11d42c8de5dfbe5 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Oct 2023 13:51:08 -0500 Subject: [PATCH 1/3] feat: Initial Sponge support --- core/build.gradle.kts | 30 +++-- .../epicguard/core/utils/Constants.java.peb | 16 +++ .../me/xneox/epicguard/core/EpicGuard.java | 4 +- .../core/command/CommandHandler.java | 4 +- .../core/command/sub/HelpCommand.java | 22 ++-- .../core/task/UpdateCheckerTask.java | 3 +- .../xneox/epicguard/core/util/LogUtils.java | 2 +- .../epicguard/core/util/VersionUtils.java | 100 +++++++-------- gradle/libs.versions.toml | 5 +- .../xneox/epicguard/paper/LibraryLoader.java | 22 ++-- settings.gradle.kts | 3 +- sponge/build.gradle.kts | 54 ++++++++ .../epicguard/sponge/EpicGuardSponge.java | 116 ++++++++++++++++++ .../me/xneox/epicguard/sponge/Libraries.java | 7 ++ .../sponge/listener/DisconnectListener.java | 41 +++++++ .../listener/PlayerSettingsListener.java | 39 ++++++ .../sponge/listener/PostLoginListener.java | 40 ++++++ .../sponge/listener/PreLoginListener.java | 44 +++++++ .../sponge/listener/ServerPingListener.java | 39 ++++++ .../sponge/listener/SpongeListener.java | 8 ++ .../epicguard/velocity/EpicGuardVelocity.java | 4 +- .../xneox/epicguard/velocity/Libraries.java | 24 ++-- .../velocity/listener/PreLoginListener.java | 13 +- .../waterfall/EpicGuardWaterfall.java | 5 +- 24 files changed, 525 insertions(+), 120 deletions(-) create mode 100644 core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb create mode 100644 sponge/build.gradle.kts create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/listener/DisconnectListener.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/listener/PlayerSettingsListener.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/listener/PostLoginListener.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/listener/PreLoginListener.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/listener/ServerPingListener.java create mode 100644 sponge/src/main/java/me/xneox/epicguard/sponge/listener/SpongeListener.java diff --git a/core/build.gradle.kts b/core/build.gradle.kts index fbb6f097..e483fb86 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,4 +1,5 @@ plugins { + alias(libs.plugins.idea.ext) alias(libs.plugins.blossom) `maven-publish` signing @@ -41,18 +42,23 @@ java { withJavadocJar() } -blossom { - replaceTokenIn("src/main/java/me/xneox/epicguard/core/util/VersionUtils.java") - replaceToken("{version}", project.version) - replaceToken("{hikari}", libs.versions.hikaricp.get()) - replaceToken("{configurate}", libs.versions.configurate.get()) - replaceToken("{caffeine}", libs.versions.caffeine.get()) - replaceToken("{common-compress}", libs.versions.commons.compress.get()) - replaceToken("{common-text}", libs.versions.commons.text.get()) - replaceToken("{geoip}", libs.versions.geoip.get()) - replaceToken("{jackson}", libs.versions.jackson.get()) - replaceToken("{maxmind-db}", libs.versions.maxmind.db.get()) - replaceToken("{fuzzywuzzy}", libs.versions.fuzzywuzzy.get()) +sourceSets { + main { + blossom { + javaSources { + property("version", project.version.toString()) + property("hikari", libs.versions.hikaricp.get()) + property("configurate", libs.versions.configurate.get()) + property("caffeine", libs.versions.caffeine.get()) + property("compress", libs.versions.commons.compress.get()) + property("text", libs.versions.commons.text.get()) + property("geoip", libs.versions.geoip.get()) + property("jackson", libs.versions.jackson.get()) + property("maxminddb", libs.versions.maxmind.db.get()) + property("fuzzywuzzy", libs.versions.fuzzywuzzy.get()) + } + } + } } // Publish to Maven Central diff --git a/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb b/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb new file mode 100644 index 00000000..a7b9dc9f --- /dev/null +++ b/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb @@ -0,0 +1,16 @@ +package me.xneox.epicguard.core.util; + +public final class Constants { + private Constants() {} + // replaced by the blossom task. + public static final String CURRENT_VERSION = "{{ version }}"; + public static final String HIKARI = "{{ hikari }}"; + public static final String CONFIGURATE = "{{ configurate }}"; + public static final String CAFFEINE = "{{ caffeine }}"; + public static final String COMMONS_TEXT = "{{ text }}"; + public static final String COMMANDS_COMPRESS = "{{ compress }}"; + public static final String GEOIP = "{{ geoip }}"; + public static final String JACKSON = "{{ jackson }}"; + public static final String FUZZYWUZZY = "{{ fuzzywuzzy }}"; + public static final String MAXMIND_DB = "{{ maxminddb }}"; +} \ No newline at end of file diff --git a/core/src/main/java/me/xneox/epicguard/core/EpicGuard.java b/core/src/main/java/me/xneox/epicguard/core/EpicGuard.java index aee3f5d5..31706584 100644 --- a/core/src/main/java/me/xneox/epicguard/core/EpicGuard.java +++ b/core/src/main/java/me/xneox/epicguard/core/EpicGuard.java @@ -23,8 +23,8 @@ import me.xneox.epicguard.core.config.migration.MiniMessageMigration; import me.xneox.epicguard.core.proxy.ProxyService; import me.xneox.epicguard.core.proxy.ProxyServiceSerializer; +import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.core.util.LogUtils; -import me.xneox.epicguard.core.util.VersionUtils; import me.xneox.epicguard.core.util.logging.LogFilter; import me.xneox.epicguard.core.manager.AttackManager; import me.xneox.epicguard.core.manager.GeoManager; @@ -89,7 +89,7 @@ private void startup() { this.platform.scheduleRepeatingTask(new AttackResetTask(this), this.config.misc().attackResetInterval()); this.platform.scheduleRepeatingTask(new DataSaveTask(this), TimeUnit.MINUTES.toSeconds(this.config.misc().autoSaveInterval())); - logger().info("Startup completed successfully. Welcome to EpicGuard v" + VersionUtils.CURRENT_VERSION); + logger().info("Startup completed successfully. Welcome to EpicGuard v" + Constants.CURRENT_VERSION); } public void loadConfigurations() { diff --git a/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java b/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java index 9ee97373..b9010e34 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java @@ -26,8 +26,8 @@ import me.xneox.epicguard.core.command.sub.SaveCommand; import me.xneox.epicguard.core.command.sub.StatusCommand; import me.xneox.epicguard.core.command.sub.WhitelistCommand; +import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.core.util.TextUtils; -import me.xneox.epicguard.core.util.VersionUtils; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; @@ -57,7 +57,7 @@ public CommandHandler(EpicGuard epicGuard) { public void handleCommand(@NotNull String[] args, @NotNull Audience audience) { // No arguments provided - send the version message. if (args.length < 1) { - audience.sendMessage(Component.text("You are running EpicGuard v" + VersionUtils.CURRENT_VERSION + + audience.sendMessage(Component.text("You are running EpicGuard v" + Constants.CURRENT_VERSION + " on " + this.epicGuard.platform().platformVersion(), TextColor.color(0x99ff00))); audience.sendMessage(TextUtils.cachedComponent("<#99ff00> Run /guard help to see available commands and statistics")); return; diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java index 1d778667..8c830dcc 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java @@ -18,21 +18,21 @@ import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.storage.AddressMeta; +import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.core.util.TextUtils; -import me.xneox.epicguard.core.util.VersionUtils; import net.kyori.adventure.audience.Audience; import org.jetbrains.annotations.NotNull; public class HelpCommand implements SubCommand { - @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - for (String line : epicGuard.messages().command().mainCommand()) { - audience.sendMessage(TextUtils.component(line - .replace("{VERSION}", VersionUtils.CURRENT_VERSION) - .replace("{BLACKLISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::blacklisted).size())) - .replace("{WHITELISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::whitelisted).size())) - .replace("{CPS}", Integer.toString(epicGuard.attackManager().connectionCounter())) - .replace("{ATTACK}", epicGuard.attackManager().isUnderAttack() ? "✔" : "✖"))); + @Override + public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { + for (String line : epicGuard.messages().command().mainCommand()) { + audience.sendMessage(TextUtils.component(line + .replace("{VERSION}", Constants.CURRENT_VERSION) + .replace("{BLACKLISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::blacklisted).size())) + .replace("{WHITELISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::whitelisted).size())) + .replace("{CPS}", Integer.toString(epicGuard.attackManager().connectionCounter())) + .replace("{ATTACK}", epicGuard.attackManager().isUnderAttack() ? "✔" : "✖"))); + } } - } } diff --git a/core/src/main/java/me/xneox/epicguard/core/task/UpdateCheckerTask.java b/core/src/main/java/me/xneox/epicguard/core/task/UpdateCheckerTask.java index f716108b..a681f351 100644 --- a/core/src/main/java/me/xneox/epicguard/core/task/UpdateCheckerTask.java +++ b/core/src/main/java/me/xneox/epicguard/core/task/UpdateCheckerTask.java @@ -16,6 +16,7 @@ package me.xneox.epicguard.core.task; import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.core.util.VersionUtils; /** @@ -32,6 +33,6 @@ public void run() { VersionUtils.checkForUpdates(latest -> this.epicGuard.logger().info(this.epicGuard.messages().updateAvailable() .replace("{NEWVER}", latest) - .replace("{OLDVER}", VersionUtils.CURRENT_VERSION))); + .replace("{OLDVER}", Constants.CURRENT_VERSION))); } } diff --git a/core/src/main/java/me/xneox/epicguard/core/util/LogUtils.java b/core/src/main/java/me/xneox/epicguard/core/util/LogUtils.java index adc8dc42..460db392 100644 --- a/core/src/main/java/me/xneox/epicguard/core/util/LogUtils.java +++ b/core/src/main/java/me/xneox/epicguard/core/util/LogUtils.java @@ -34,7 +34,7 @@ public final class LogUtils { * @param throwable the caught exception */ public static void catchException(@NotNull String details, @NotNull Throwable throwable) { - LOGGER.error("An error occurred in EpicGuard v" + VersionUtils.CURRENT_VERSION); + LOGGER.error("An error occurred in EpicGuard v" + Constants.CURRENT_VERSION); if (VersionUtils.isUpdateAvailable()) { LOGGER.error(" (!) Your version is outdated. Update before sending bug report!"); } diff --git a/core/src/main/java/me/xneox/epicguard/core/util/VersionUtils.java b/core/src/main/java/me/xneox/epicguard/core/util/VersionUtils.java index 8c3804ab..0afe2478 100644 --- a/core/src/main/java/me/xneox/epicguard/core/util/VersionUtils.java +++ b/core/src/main/java/me/xneox/epicguard/core/util/VersionUtils.java @@ -16,6 +16,7 @@ package me.xneox.epicguard.core.util; import java.util.function.Consumer; + import org.checkerframework.checker.nullness.qual.NonNull; import org.jetbrains.annotations.NotNull; @@ -23,69 +24,60 @@ * This util holds current EpicGuard version and checks for the latest available version. */ public final class VersionUtils { - public static final String CURRENT_VERSION = "{version}"; // replaced by the blossom task. - public static final String HIKARI = "{hikari}"; - public static final String CONFIGURATE = "{configurate}"; - public static final String CAFFEINE = "{caffeine}"; - public static final String COMMONS_TEXT = "{common-text}"; - public static final String COMMANDS_COMPRESS = "{common-compress}"; - public static final String GEOIP = "{geoip}"; - public static final String JACKSON = "{jackson}"; - public static final String FUZZYWUZZY = "{fuzzywuzzy}"; - public static final String MAXMIND_DB = "{maxmind-db}"; - private static final String CHECK_URL = "https://raw.githubusercontent.com/4drian3d/EpicGuard/master/VERSION.txt"; + private static final String CHECK_URL = "https://raw.githubusercontent.com/4drian3d/EpicGuard/master/VERSION.txt"; - private static boolean updateAvailable; + private static boolean updateAvailable; - /** - * Checks the latest version to see if there's any update available. - * @param action Action to run when there's an update available. - */ - public static void checkForUpdates(@NotNull Consumer action) { - String latest = URLUtils.readString(CHECK_URL); - if (latest == null) { - return; // a warning will be thrown by the URLUtils anyway. - } + /** + * Checks the latest version to see if there's any update available. + * + * @param action Action to run when there's an update available. + */ + public static void checkForUpdates(@NotNull Consumer action) { + String latest = URLUtils.readString(CHECK_URL); + if (latest == null) { + return; // a warning will be thrown by the URLUtils anyway. + } - var latestVersion = new Version(latest); - var currentVersion = new Version(CURRENT_VERSION); + var latestVersion = new Version(latest); + var currentVersion = new Version(Constants.CURRENT_VERSION); - // 1 means outdated, 0 means up-to-date, -1 means newer than released. - if (latestVersion.compareTo(currentVersion) > 0) { - updateAvailable = true; - action.accept(latest); + // 1 means outdated, 0 means up-to-date, -1 means newer than released. + if (latestVersion.compareTo(currentVersion) > 0) { + updateAvailable = true; + action.accept(latest); + } } - } - public static boolean isUpdateAvailable() { - return updateAvailable; - } + public static boolean isUpdateAvailable() { + return updateAvailable; + } - /* - @author brianguertin (https://gist.github.com/brianguertin/ada4b65c6d1c4f6d3eee3c12b6ce021b) - */ - public static class Version implements Comparable { - public final int[] numbers; + /* + @author brianguertin (https://gist.github.com/brianguertin/ada4b65c6d1c4f6d3eee3c12b6ce021b) + */ + public static class Version implements Comparable { + public final int[] numbers; - public Version(@NonNull String version) { - var split = version.split("-")[0].split("\\."); - numbers = new int[split.length]; - for (int i = 0; i < split.length; i++) { - numbers[i] = Integer.parseInt(split[i]); - } - } + public Version(@NonNull String version) { + var split = version.split("-")[0].split("\\."); + numbers = new int[split.length]; + for (int i = 0; i < split.length; i++) { + numbers[i] = Integer.parseInt(split[i]); + } + } - @Override - public int compareTo(@NonNull Version another) { - int maxLength = Math.max(numbers.length, another.numbers.length); - for (int i = 0; i < maxLength; i++) { - int left = i < numbers.length ? numbers[i] : 0; - int right = i < another.numbers.length ? another.numbers[i] : 0; - if (left != right) { - return left < right ? -1 : 1; + @Override + public int compareTo(@NonNull Version another) { + int maxLength = Math.max(numbers.length, another.numbers.length); + for (int i = 0; i < maxLength; i++) { + int left = i < numbers.length ? numbers[i] : 0; + int right = i < another.numbers.length ? another.numbers[i] : 0; + if (left != right) { + return left < right ? -1 : 1; + } + } + return 0; } - } - return 0; } - } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5d5d24e1..8de29720 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ configurate = "4.1.2" miniplaceholders = "2.2.1" # Plugins -blossom = "1.3.1" +blossom = "2.1.0" shadow = "8.1.1" runtask = "2.2.0" plugin-yml = "0.6.0" @@ -61,6 +61,7 @@ miniplaceholders = { group = "io.github.miniplaceholders", name = "miniplacehold # Included Dependencies libby-velocity = { group = "net.byteflux", name = "libby-velocity", version.ref = "libby" } +libby-sponge = { group = "net.byteflux", name = "libby-sponge", version.ref = "libby" } # Loggers slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } @@ -96,3 +97,5 @@ runwaterfall = { id = "xyz.jpenilla.run-waterfall", version.ref = "runtask" } pluginyml-bungee = { id = "net.minecrell.plugin-yml.bungee", version.ref = "plugin-yml" } pluginyml-bukkit = { id = "net.minecrell.plugin-yml.bukkit", version.ref = "plugin-yml" } + +idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version = "1.1.7" } diff --git a/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java b/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java index b0bc1238..c766b9a5 100644 --- a/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java +++ b/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java @@ -3,7 +3,7 @@ import io.papermc.paper.plugin.loader.PluginClasspathBuilder; import io.papermc.paper.plugin.loader.PluginLoader; import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver; -import me.xneox.epicguard.core.util.VersionUtils; +import me.xneox.epicguard.core.util.Constants; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.repository.RemoteRepository; @@ -23,16 +23,16 @@ public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) { resolver.addRepository(mavenCentral); Stream.of( - "com.zaxxer:HikariCP:" + VersionUtils.HIKARI, - "com.github.ben-manes.caffeine:caffeine:" + VersionUtils.CAFFEINE, - "org.apache.commons:commons-compress:" + VersionUtils.COMMANDS_COMPRESS, - "org.apache.commons:commons-text:" + VersionUtils.COMMONS_TEXT, - "com.maxmind.geoip2:geoip2:" + VersionUtils.GEOIP, - "com.maxmind.db:maxmind-db:" + VersionUtils.MAXMIND_DB, - "com.fasterxml.jackson.core:jackson-annotations:" + VersionUtils.JACKSON, - "com.fasterxml.jackson.core:jackson-core:" + VersionUtils.JACKSON, - "com.fasterxml.jackson.core:jackson-databind:" + VersionUtils.JACKSON, - "me.xdrop:fuzzywuzzy:" + VersionUtils.FUZZYWUZZY + "com.zaxxer:HikariCP:" + Constants.HIKARI, + "com.github.ben-manes.caffeine:caffeine:" + Constants.CAFFEINE, + "org.apache.commons:commons-compress:" + Constants.COMMANDS_COMPRESS, + "org.apache.commons:commons-text:" + Constants.COMMONS_TEXT, + "com.maxmind.geoip2:geoip2:" + Constants.GEOIP, + "com.maxmind.db:maxmind-db:" + Constants.MAXMIND_DB, + "com.fasterxml.jackson.core:jackson-annotations:" + Constants.JACKSON, + "com.fasterxml.jackson.core:jackson-core:" + Constants.JACKSON, + "com.fasterxml.jackson.core:jackson-databind:" + Constants.JACKSON, + "me.xdrop:fuzzywuzzy:" + Constants.FUZZYWUZZY ) .map(artifact -> new Dependency(new DefaultArtifact(artifact), null)) .forEach(resolver::addDependency); diff --git a/settings.gradle.kts b/settings.gradle.kts index be8ff5ee..a9c24aae 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,6 +12,7 @@ dependencyResolutionManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" + id("org.spongepowered.gradle.plugin") version "2.2.0" } -include("core", "paper", "velocity", "waterfall") \ No newline at end of file +include("core", "paper", "velocity", "waterfall", "sponge") \ No newline at end of file diff --git a/sponge/build.gradle.kts b/sponge/build.gradle.kts new file mode 100644 index 00000000..82db811c --- /dev/null +++ b/sponge/build.gradle.kts @@ -0,0 +1,54 @@ +import org.spongepowered.gradle.plugin.config.PluginLoaders +import org.spongepowered.plugin.metadata.model.PluginDependency + +plugins { + id("org.spongepowered.gradle.plugin") +} + +dependencies { + implementation(projects.core) + implementation(libs.libby.sponge) + compileOnly(libs.slf4j) +} + +sponge { + apiVersion("10.0.0") + license("GPL-3") + loader { + name(PluginLoaders.JAVA_PLAIN) + version("1.0") + } + plugin("epicguard") { + displayName("EpicGuard") + entrypoint("me.xneox.epicguard.sponge.EpicGuard") + description(project.description) + links { + homepage("https://github.com/4drian3d/EpicGuard") + source("https://github.com/4drian3d/EpicGuard") + issues("https://github.com/4drian3d/EpicGuard/issues") + } + contributor("4drian3d") { + description("Lead Developer") + } + dependency("spongeapi") { + loadOrder(PluginDependency.LoadOrder.AFTER) + optional(false) + } + } +} + +tasks { + shadowJar { + relocate("net.byteflux.libby", "me.xneox.epicguard.velocity.libby") + relocate("org.spongepowered", "me.xneox.epicguard.libs.org.spongepowered") + relocate("io.leangen.geantyref", "me.xneox.epicguard.libs.io.leangen.geantyref") + relocate("com.zaxxer.hikari", "me.xneox.epicguard.libs.com.zaxxer.hikari") + relocate("com.mysql.cj", "me.xneox.epicguard.libs.mysql") + relocate("org.xerial", "me.xneox.epicguard.libs.org.xerial") + relocate("org.apache.commons", "me.xneox.epicguard.libs.commons") + relocate("me.xdrop.fuzzywuzzy", "me.xneox.epicguard.libs.fuzzywuzzy") + } + build { + dependsOn(shadowJar) + } +} \ No newline at end of file diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java b/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java new file mode 100644 index 00000000..8fcecb25 --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java @@ -0,0 +1,116 @@ +package me.xneox.epicguard.sponge; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.Platform; +import me.xneox.epicguard.core.placeholder.Placeholders; +import me.xneox.epicguard.sponge.listener.*; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongepowered.api.Game; +import org.spongepowered.api.MinecraftVersion; +import org.spongepowered.api.Server; +import org.spongepowered.api.config.DefaultConfig; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.StartedEngineEvent; +import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; +import org.spongepowered.api.plugin.PluginManager; +import org.spongepowered.api.scheduler.Task; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; + +import java.nio.file.Path; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +@Plugin("epicguard") +public final class EpicGuardSponge implements Platform { + private static final Logger LOGGER = LoggerFactory.getLogger("EpicGuard"); + @Inject + private MinecraftVersion version; + @Inject + private Game game; + @Inject + private PluginManager pluginManager; + @Inject + @DefaultConfig(sharedRoot = false) + private Path configFilePath; + @Inject + private PluginContainer pluginContainer; + @Inject + private Injector injector; + + private EpicGuard epicGuard; + + @Listener + public void onServerInitialization(StartedEngineEvent event) { + this.injector.getInstance(Libraries.class).register(); + this.epicGuard = new EpicGuard(this, configFilePath); + this.injector = injector.createChildInjector( + binder -> binder.bind(EpicGuard.class).toInstance(epicGuard) + ); + + // TODO: Cloud Command + //this.injector.getInstance(VelocityCommandHandler.class).register(); + Stream.of( + PostLoginListener.class, + PreLoginListener.class, + DisconnectListener.class, + ServerPingListener.class, + PlayerSettingsListener.class + ).map(injector::getInstance).forEach(SpongeListener::register); + + if (this.pluginManager.plugin("miniplaceholders").isPresent()) { + Placeholders.register(); + } + } + + @Listener + public void onServerShutdown(final StoppingEngineEvent event) { + this.epicGuard.shutdown(); + } + + @Override + public @NotNull String platformVersion() { + return version.name(); + } + + @Override + public @NotNull Logger logger() { + return LOGGER; + } + + @Override + public @Nullable Audience audience(@NotNull UUID uuid) { + return game.server().player(uuid).orElse(null); + } + + @Override + public void disconnectUser(@NotNull UUID uuid, @NotNull Component message) { + game.server().player(uuid).ifPresent(player -> player.kick(message)); + } + + @Override + public void runTaskLater(@NotNull Runnable task, long seconds) { + game.server().scheduler().submit(Task.builder() + .plugin(pluginContainer) + .execute(task) + .delay(seconds, TimeUnit.SECONDS) + .build()); + } + + @Override + public void scheduleRepeatingTask(@NotNull Runnable task, long seconds) { + game.server().scheduler().submit(Task.builder() + .plugin(pluginContainer) + .execute(task) + .interval(seconds, TimeUnit.SECONDS) + .build()); + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java b/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java new file mode 100644 index 00000000..d9ce0643 --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java @@ -0,0 +1,7 @@ +package me.xneox.epicguard.sponge; + +public class Libraries { + public void register() { + + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/listener/DisconnectListener.java b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/DisconnectListener.java new file mode 100644 index 00000000..43cd0d44 --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/DisconnectListener.java @@ -0,0 +1,41 @@ +package me.xneox.epicguard.sponge.listener; + +import com.google.inject.Inject; +import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.handler.DisconnectHandler; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.EventListenerRegistration; +import org.spongepowered.api.event.EventManager; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.network.ServerSideConnectionEvent; +import org.spongepowered.plugin.PluginContainer; + +public final class DisconnectListener extends DisconnectHandler implements SpongeListener { + @Inject + private EventManager eventManager; + @Inject + private PluginContainer pluginContainer; + + @Inject + public DisconnectListener(final EpicGuard epicGuard) { + super(epicGuard); + } + + @Override + public void register() { + this.eventManager.registerListener( + EventListenerRegistration + .builder(ServerSideConnectionEvent.Disconnect.class) + .plugin(pluginContainer) + .listener(this) + .order(Order.DEFAULT) + .build() + ); + } + + @Override + public void handle(final ServerSideConnectionEvent.Disconnect event) { + final ServerPlayer player = event.player(); + this.onDisconnect(player.uniqueId()); + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PlayerSettingsListener.java b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PlayerSettingsListener.java new file mode 100644 index 00000000..2b8b99fe --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PlayerSettingsListener.java @@ -0,0 +1,39 @@ +package me.xneox.epicguard.sponge.listener; + +import com.google.inject.Inject; +import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.handler.SettingsHandler; +import org.spongepowered.api.event.EventListenerRegistration; +import org.spongepowered.api.event.EventManager; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.entity.living.player.PlayerChangeClientSettingsEvent; +import org.spongepowered.plugin.PluginContainer; + +public final class PlayerSettingsListener extends SettingsHandler implements SpongeListener { + @Inject + private EventManager eventManager; + @Inject + private PluginContainer pluginContainer; + + @Inject + public PlayerSettingsListener(final EpicGuard epicGuard) { + super(epicGuard); + } + + @Override + public void register() { + this.eventManager.registerListener( + EventListenerRegistration + .builder(PlayerChangeClientSettingsEvent.class) + .plugin(pluginContainer) + .listener(this) + .order(Order.DEFAULT) + .build() + ); + } + + @Override + public void handle(final PlayerChangeClientSettingsEvent event) { + this.onSettingsChanged(event.player().uniqueId()); + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PostLoginListener.java b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PostLoginListener.java new file mode 100644 index 00000000..a974d4e5 --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PostLoginListener.java @@ -0,0 +1,40 @@ +package me.xneox.epicguard.sponge.listener; + +import com.google.inject.Inject; +import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.handler.PostLoginHandler; +import org.spongepowered.api.event.EventListenerRegistration; +import org.spongepowered.api.event.EventManager; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.network.ServerSideConnectionEvent; +import org.spongepowered.api.network.ServerSideConnection; +import org.spongepowered.plugin.PluginContainer; + +public final class PostLoginListener extends PostLoginHandler implements SpongeListener { + @Inject + private EventManager eventManager; + @Inject + private PluginContainer pluginContainer; + + public PostLoginListener(final EpicGuard epicGuard) { + super(epicGuard); + } + + @Override + public void register() { + this.eventManager.registerListener( + EventListenerRegistration + .builder(ServerSideConnectionEvent.Login.class) + .plugin(pluginContainer) + .listener(this) + .order(Order.DEFAULT) + .build() + ); + } + + @Override + public void handle(final ServerSideConnectionEvent.Login event) { + final ServerSideConnection connection = event.connection(); + this.onPostLogin(connection.profile().uuid(), connection.address().getAddress().getHostAddress()); + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PreLoginListener.java b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PreLoginListener.java new file mode 100644 index 00000000..8e1bc227 --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/PreLoginListener.java @@ -0,0 +1,44 @@ +package me.xneox.epicguard.sponge.listener; + +import com.google.inject.Inject; +import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.handler.PreLoginHandler; +import org.spongepowered.api.event.EventListenerRegistration; +import org.spongepowered.api.event.EventManager; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.network.ServerSideConnectionEvent; +import org.spongepowered.api.network.ServerSideConnection; +import org.spongepowered.plugin.PluginContainer; + +public final class PreLoginListener extends PreLoginHandler implements SpongeListener { + @Inject + private EventManager eventManager; + @Inject + private PluginContainer pluginContainer; + + @Inject + public PreLoginListener(final EpicGuard epicGuard) { + super(epicGuard); + } + + @Override + public void register() { + this.eventManager.registerListener( + EventListenerRegistration + .builder(ServerSideConnectionEvent.Handshake.class) + .plugin(pluginContainer) + .listener(this) + .order(Order.DEFAULT) + .build() + ); + } + + @Override + public void handle(final ServerSideConnectionEvent.Handshake event) { + final ServerSideConnection connection = event.connection(); + final String address = connection.address().getAddress().getHostAddress(); + final String nickname = connection.profile().name().orElse(""); + this.onPreLogin(address, nickname) + .ifPresent(result -> event.connection().close(result)); + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/listener/ServerPingListener.java b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/ServerPingListener.java new file mode 100644 index 00000000..c52b21cf --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/ServerPingListener.java @@ -0,0 +1,39 @@ +package me.xneox.epicguard.sponge.listener; + +import com.google.inject.Inject; +import me.xneox.epicguard.core.EpicGuard; +import me.xneox.epicguard.core.handler.PingHandler; +import org.spongepowered.api.event.EventListenerRegistration; +import org.spongepowered.api.event.EventManager; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.server.ClientPingServerEvent; +import org.spongepowered.plugin.PluginContainer; + +public final class ServerPingListener extends PingHandler implements SpongeListener { + @Inject + private EventManager eventManager; + @Inject + private PluginContainer pluginContainer; + + @Inject + public ServerPingListener(final EpicGuard epicGuard) { + super(epicGuard); + } + + @Override + public void register() { + this.eventManager.registerListener( + EventListenerRegistration + .builder(ClientPingServerEvent.class) + .plugin(pluginContainer) + .listener(this) + .order(Order.DEFAULT) + .build() + ); + } + + @Override + public void handle(final ClientPingServerEvent event) { + this.onPing(event.client().address().getAddress().getHostAddress()); + } +} diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/listener/SpongeListener.java b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/SpongeListener.java new file mode 100644 index 00000000..1daeccbe --- /dev/null +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/listener/SpongeListener.java @@ -0,0 +1,8 @@ +package me.xneox.epicguard.sponge.listener; + +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.EventListener; + +public interface SpongeListener extends EventListener { + void register(); +} diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java b/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java index bfca4a7e..1c1dbe5d 100644 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java +++ b/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java @@ -27,7 +27,7 @@ import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.Platform; import me.xneox.epicguard.core.placeholder.Placeholders; -import me.xneox.epicguard.core.util.VersionUtils; +import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.velocity.listener.*; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; @@ -42,7 +42,7 @@ @Plugin( id = "epicguard", name = "EpicGuard", - version = VersionUtils.CURRENT_VERSION, + version = Constants.CURRENT_VERSION, description = "Bot protection system for Minecraft servers.", url = "https://github.com/4drian3d/EpicGuard", authors = {"neox", "4drian3d"}) diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java b/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java index bd56c161..aafe5a97 100644 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java +++ b/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java @@ -3,7 +3,7 @@ import com.google.inject.Inject; import com.velocitypowered.api.plugin.PluginManager; import com.velocitypowered.api.plugin.annotation.DataDirectory; -import me.xneox.epicguard.core.util.VersionUtils; +import me.xneox.epicguard.core.util.Constants; import net.byteflux.libby.Library; import net.byteflux.libby.VelocityLibraryManager; import net.byteflux.libby.relocation.Relocation; @@ -51,7 +51,7 @@ void register() { final Library CONFIGURATE_HOCON = Library.builder() .groupId("org{}spongepowered") .artifactId("configurate-hocon") - .version(VersionUtils.CONFIGURATE) + .version(Constants.CONFIGURATE) .id("configurate-hocon") .relocate(configurateRelocation) .relocate(geantyrefRelocation) @@ -59,7 +59,7 @@ void register() { final Library CONFIGURATE_CORE = Library.builder() .groupId("org{}spongepowered") .artifactId("configurate-core") - .version(VersionUtils.CONFIGURATE) + .version(Constants.CONFIGURATE) .id("configurate-core") .relocate(configurateRelocation) .relocate(geantyrefRelocation) @@ -75,7 +75,7 @@ void register() { final Library HIKARI = Library.builder() .groupId("com{}zaxxer") .artifactId("HikariCP") - .version(VersionUtils.HIKARI) + .version(Constants.HIKARI) .id("hikari") .relocate("com{}zaxxer{}hikari", "me{}xneox{}epicguard{}libs{}com{}zaxxer{}hikari") .build(); @@ -86,45 +86,45 @@ void register() { final Library COMMONS_COMPRESS = Library.builder() .groupId("org{}apache{}commons") .artifactId("commons-compress") - .version(VersionUtils.COMMANDS_COMPRESS) + .version(Constants.COMMANDS_COMPRESS) .id("commons-compress") .relocate(commonsRelocation) .build(); final Library COMMONS_TEXT = Library.builder() .groupId("org{}apache{}commons") .artifactId("commons-text") - .version(VersionUtils.COMMONS_TEXT) + .version(Constants.COMMONS_TEXT) .id("commons-text") .relocate(commonsRelocation) .build(); final Library MAXMIND_GEOIP = Library.builder() .groupId("com.maxmind.geoip2") .artifactId("geoip2") - .version(VersionUtils.GEOIP) + .version(Constants.GEOIP) .id("geoip2") .build(); final Library MAXMIND_DB = Library.builder() .groupId("com.maxmind.db") .artifactId("maxmind-db") - .version(VersionUtils.MAXMIND_DB) + .version(Constants.MAXMIND_DB) .id("maxmind-db") .build(); final Library JACKSON_ANNOTATIONS = Library.builder() .groupId("com.fasterxml.jackson.core") .artifactId("jackson-annotations") - .version(VersionUtils.JACKSON) + .version(Constants.JACKSON) .id("jackson-annotations") .build(); final Library JACKSON_CORE = Library.builder() .groupId("com.fasterxml.jackson.core") .artifactId("jackson-core") - .version(VersionUtils.JACKSON) + .version(Constants.JACKSON) .id("jackson-core") .build(); final Library JACKSON_DATABIND = Library.builder() .groupId("com.fasterxml.jackson.core") .artifactId("jackson-databind") - .version(VersionUtils.JACKSON) + .version(Constants.JACKSON) .id("jackson-databind") .build(); final Relocation fuzzywuzzyRelocator = new Relocation( @@ -134,7 +134,7 @@ void register() { final Library FUZZYWUZZY = Library.builder() .groupId("me.xdrop") .artifactId("fuzzywuzzy") - .version(VersionUtils.FUZZYWUZZY) + .version(Constants.FUZZYWUZZY) .id("fuzzywuzzy") .relocate(fuzzywuzzyRelocator) .build(); diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/listener/PreLoginListener.java b/velocity/src/main/java/me/xneox/epicguard/velocity/listener/PreLoginListener.java index 8d45306c..96fa207c 100644 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/listener/PreLoginListener.java +++ b/velocity/src/main/java/me/xneox/epicguard/velocity/listener/PreLoginListener.java @@ -43,12 +43,11 @@ public void register() { @Override public EventTask executeAsync(PreLoginEvent event) { return EventTask.withContinuation((continuation) -> { - final String address = event.getConnection().getRemoteAddress().getAddress().getHostAddress(); - final String nickname = event.getUsername(); - this.onPreLogin(address, nickname) - .ifPresent(result -> event.setResult(PreLoginEvent.PreLoginComponentResult.denied(result))); - continuation.resume(); - } - ); + final String address = event.getConnection().getRemoteAddress().getAddress().getHostAddress(); + final String nickname = event.getUsername(); + this.onPreLogin(address, nickname) + .ifPresent(result -> event.setResult(PreLoginEvent.PreLoginComponentResult.denied(result))); + continuation.resume(); + }); } } diff --git a/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java b/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java index e338f20f..261205d9 100644 --- a/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java +++ b/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java @@ -25,7 +25,6 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; -import java.util.Random; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -48,8 +47,7 @@ public void onEnable() { pluginManager.registerCommand(this, new BungeeCommandHandler(this)); - if (new Random().nextBoolean()) - this.logger.warn(""" + this.logger.warn(""" --------------------------------------- This version of EpicGuard for Waterfall is deprecated and will stop working in a future update. @@ -63,6 +61,7 @@ public void onEnable() { Download it from: https://papermc.io/software/velocity --------------------------------------- """); + } @Override From 2214f7c5bc4ad56dd6a349618a5c11efd3850870 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 3 Nov 2023 20:39:33 -0500 Subject: [PATCH 2/3] feat: Disabled Sponge module and implemented Cloud commands --- core/build.gradle.kts | 1 + .../core/command/CommandHandler.java | 88 ++++-------- .../epicguard/core/command/SubCommand.java | 29 +--- .../core/command/sub/AnalyzeCommand.java | 107 ++++++++------ .../core/command/sub/BlacklistCommand.java | 120 ++++++++++------ .../core/command/sub/HelpCommand.java | 26 ++-- .../core/command/sub/ReloadCommand.java | 16 ++- .../core/command/sub/SaveCommand.java | 29 ++-- .../core/command/sub/StatusCommand.java | 31 ++-- .../core/command/sub/WhitelistCommand.java | 121 ++++++++++------ gradle/libs.versions.toml | 10 +- paper/build.gradle.kts | 1 + .../xneox/epicguard/paper/EpicGuardPaper.java | 22 ++- .../epicguard/paper/PaperCommandHandler.java | 68 --------- settings.gradle.kts | 9 +- sponge/build.gradle.kts | 18 ++- .../epicguard/sponge/EpicGuardSponge.java | 34 ++++- .../me/xneox/epicguard/sponge/Libraries.java | 136 ++++++++++++++++++ velocity/build.gradle.kts | 1 + .../epicguard/velocity/EpicGuardVelocity.java | 16 ++- .../velocity/VelocityCommandHandler.java | 62 -------- waterfall/build.gradle.kts | 2 + .../waterfall/BungeeCommandHandler.java | 44 ------ .../waterfall/EpicGuardWaterfall.java | 43 ++++-- 24 files changed, 575 insertions(+), 459 deletions(-) delete mode 100644 paper/src/main/java/me/xneox/epicguard/paper/PaperCommandHandler.java delete mode 100644 velocity/src/main/java/me/xneox/epicguard/velocity/VelocityCommandHandler.java delete mode 100644 waterfall/src/main/java/me/xneox/epicguard/waterfall/BungeeCommandHandler.java diff --git a/core/build.gradle.kts b/core/build.gradle.kts index e483fb86..08707ac0 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { compileOnly(libs.annotations) compileOnly(libs.fuzzywuzzy) + compileOnly(libs.cloud.core) } tasks { diff --git a/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java b/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java index b9010e34..5b9e2e65 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/CommandHandler.java @@ -15,78 +15,52 @@ package me.xneox.epicguard.core.command; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; +import cloud.commandframework.Command; +import cloud.commandframework.CommandManager; import me.xneox.epicguard.core.EpicGuard; -import me.xneox.epicguard.core.command.sub.AnalyzeCommand; -import me.xneox.epicguard.core.command.sub.BlacklistCommand; -import me.xneox.epicguard.core.command.sub.HelpCommand; -import me.xneox.epicguard.core.command.sub.ReloadCommand; -import me.xneox.epicguard.core.command.sub.SaveCommand; -import me.xneox.epicguard.core.command.sub.StatusCommand; -import me.xneox.epicguard.core.command.sub.WhitelistCommand; +import me.xneox.epicguard.core.command.sub.*; import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; -import org.jetbrains.annotations.NotNull; + /** * This class holds all registered subcommands, and handles the user command/tab suggestion input. */ -public class CommandHandler { - private final Map commandMap; - private final EpicGuard epicGuard; - - public CommandHandler(EpicGuard epicGuard) { - this.epicGuard = epicGuard; - - this.commandMap = Map.of( - "analyze", new AnalyzeCommand(), - "blacklist", new BlacklistCommand(), - "help", new HelpCommand(), - "reload", new ReloadCommand(), - "status", new StatusCommand(), - "whitelist", new WhitelistCommand(), - "save", new SaveCommand() - ); - } +public final class CommandHandler { + private final EpicGuard epicGuard; + private final CommandManager commandManager; - public void handleCommand(@NotNull String[] args, @NotNull Audience audience) { - // No arguments provided - send the version message. - if (args.length < 1) { - audience.sendMessage(Component.text("You are running EpicGuard v" + Constants.CURRENT_VERSION + - " on " + this.epicGuard.platform().platformVersion(), TextColor.color(0x99ff00))); - audience.sendMessage(TextUtils.cachedComponent("<#99ff00> Run /guard help to see available commands and statistics")); - return; + public CommandHandler(final EpicGuard epicGuard, final CommandManager commandManager) { + this.epicGuard = epicGuard; + this.commandManager = commandManager; } - var subCommand = this.commandMap.get(args[0]); - if (subCommand == null) { - audience.sendMessage(TextUtils.cachedComponent(this.epicGuard.messages().command().prefix() + this.epicGuard.messages().command().unknownCommand())); - return; - } - - subCommand.execute(audience, args, this.epicGuard); - } + public void register() { + commandManager.command(builder() + .handler(ctx -> { + ctx.getSender().sendMessage(Component.text("You are running EpicGuard v" + Constants.CURRENT_VERSION + + " on " + this.epicGuard.platform().platformVersion(), TextColor.color(0x99ff00))); + ctx.getSender().sendMessage(TextUtils.cachedComponent("<#99ff00> Run /guard help to see available commands and statistics")); + })); - @NotNull - public Collection handleSuggestions(@NotNull String[] args) { - // If no argument is specified, send all available subcommands. - if (args.length <= 1) { - return this.commandMap.keySet(); + final SubCommand[] subCommands = { + new AnalyzeCommand(), + new BlacklistCommand(), + new HelpCommand(), + new ReloadCommand(), + new StatusCommand(), + new WhitelistCommand(), + new SaveCommand() + }; + for (final SubCommand subCommand : subCommands) { + subCommand.register(commandManager, epicGuard); + } } - // Handle argument completions. - // "rel" will be completed to "reload" - for (var entry : this.commandMap.entrySet()) { - if (entry.getKey().startsWith(args[0])) { - return entry.getValue().suggest(args, this.epicGuard); - } + private Command.Builder builder() { + return commandManager.commandBuilder("epicguard").permission("epicguard.admin"); } - - return Collections.emptyList(); - } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/SubCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/SubCommand.java index 5724bd0c..100b6dc9 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/SubCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/SubCommand.java @@ -15,37 +15,18 @@ package me.xneox.epicguard.core.command; -import java.util.Collection; -import java.util.Collections; - +import cloud.commandframework.Command; +import cloud.commandframework.CommandManager; import me.xneox.epicguard.core.EpicGuard; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; /** * A subcommand of the /epicguard command. */ public interface SubCommand { + void register(CommandManager commandManager, EpicGuard epicGuard); - /** - * Handles the execution of this subcommand - * - * @param audience the executor of this subcommand - * @param args arguments provided by the executor - * @param epicGuard instance of {@link EpicGuard} - */ - void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard); - - /** - * Handles the tab-completion of this subcommand. - * Returns available suggestions if possible. - * - * @param args arguments provided by the executor - * @param epicGuard instance of {@link EpicGuard} - * @return available suggestions, or an empty ArrayList - */ - @NotNull - default Collection suggest(@NotNull String[] args, @NotNull EpicGuard epicGuard) { - return Collections.emptyList(); + default Command.Builder builder(CommandManager commandManager) { + return commandManager.commandBuilder("epicguard").permission("epicguard.admin"); } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/AnalyzeCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/AnalyzeCommand.java index bd810999..edb85619 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/AnalyzeCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/AnalyzeCommand.java @@ -15,65 +15,78 @@ package me.xneox.epicguard.core.command.sub; +import cloud.commandframework.CommandManager; +import cloud.commandframework.arguments.standard.StringArgument; import com.google.common.net.InetAddresses; -import java.util.Collection; -import java.util.Collections; - import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; -public class AnalyzeCommand implements SubCommand { +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; - @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - var config = epicGuard.messages().command(); +public final class AnalyzeCommand implements SubCommand { - if (args.length != 2) { - audience.sendMessage(TextUtils.component(config.prefix() + - config.usage().replace("{USAGE}", "/guard analyze "))); - return; - } + @Override + public void register(CommandManager commandManager, EpicGuard epicGuard) { + final StringArgument addressArgument = StringArgument.builder("address") + .single() + .withSuggestionsProvider((ctx, a) -> { + if (epicGuard.config().misc().disableIPTabCompletion()) { + return Collections.emptyList(); + } - var meta = epicGuard.storageManager().resolveAddressMeta(args[1]); - if (meta == null) { - audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); - return; - } + final List addresses = new ArrayList<>(); + epicGuard.storageManager().addresses().asMap().forEach((k, v) -> addresses.add(k)); + return addresses; + }) + .build(); + commandManager.command( + builder(commandManager) + .literal("analyze") + .argument(addressArgument) + .handler(ctx -> { + final var config = epicGuard.messages().command(); + final var audience = ctx.getSender(); + var optionalAddress = ctx.getOptional(addressArgument); + if (optionalAddress.isEmpty()) { + audience.sendMessage(TextUtils.component(config.prefix() + + config.usage().replace("{USAGE}", "/guard analyze "))); + return; + } + // Assume that executor provided an address as the argument. + var address = optionalAddress.get(); - // Assume that executor provided an address as the argument. - String address = args[1]; + var meta = epicGuard.storageManager().resolveAddressMeta(address); + if (meta == null) { + ctx.getSender().sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); + return; + } - // If executor provided nickname as the argument instead, we have to find their IP address. - if (!InetAddresses.isInetAddress(args[1])) { - for (var entry : epicGuard.storageManager().addresses().asMap().entrySet()) { - if (entry.getValue().equals(meta)) { - address = entry.getKey(); - break; - } - } - } + // If executor provided nickname as the argument instead, we have to find their IP address. + if (!InetAddresses.isInetAddress(address)) { + for (var entry : epicGuard.storageManager().addresses().asMap().entrySet()) { + if (entry.getValue().equals(meta)) { + address = entry.getKey(); + break; + } + } + } - for (String line : config.analyzeCommand()) { - audience.sendMessage(TextUtils.component(line - .replace("{ADDRESS}", address) - .replace("{COUNTRY}", epicGuard.geoManager().countryCode(address)) - .replace("{CITY}", epicGuard.geoManager().city(address)) - .replace("{WHITELISTED}", meta.whitelisted() ? "✔" : "✖") - .replace("{BLACKLISTED}", meta.blacklisted() ? "✔" : "✖") - .replace("{ACCOUNT-AMOUNT}", Integer.toString(meta.nicknames().size())) - .replace("{NICKNAMES}", String.join(", ", meta.nicknames())))); - } - } + for (final String line : config.analyzeCommand()) { + audience.sendMessage(TextUtils.component(line + .replace("{ADDRESS}", address) + .replace("{COUNTRY}", epicGuard.geoManager().countryCode(address)) + .replace("{CITY}", epicGuard.geoManager().city(address)) + .replace("{WHITELISTED}", meta.whitelisted() ? "✔" : "✖") + .replace("{BLACKLISTED}", meta.blacklisted() ? "✔" : "✖") + .replace("{ACCOUNT-AMOUNT}", Integer.toString(meta.nicknames().size())) + .replace("{NICKNAMES}", String.join(", ", meta.nicknames())))); + } + }) + ); - @Override - public @NotNull Collection suggest(@NotNull String[] args, @NotNull EpicGuard epicGuard) { - if (epicGuard.config().misc().disableIPTabCompletion()) { - return Collections.emptyList(); } - - return epicGuard.storageManager().addresses().asMap().keySet(); - } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/BlacklistCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/BlacklistCommand.java index 3a6ee44c..29dadc50 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/BlacklistCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/BlacklistCommand.java @@ -15,63 +15,89 @@ package me.xneox.epicguard.core.command.sub; +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.CommandManager; +import cloud.commandframework.arguments.standard.StringArgument; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.storage.AddressMeta; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.Collections; import java.util.List; public class BlacklistCommand implements SubCommand { - @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - var config = epicGuard.messages().command(); + @Override + public void register(CommandManager commandManager, EpicGuard epicGuard) { + final var removeArgument = StringArgument.builder("subject") + .single() + .withDefaultDescription(ArgumentDescription.of("NickName or Address")) + .withSuggestionsProvider((ctx, st) -> { + if (!epicGuard.config().misc().disableIPTabCompletion()) { + return epicGuard.storageManager().viewAddresses(AddressMeta::blacklisted); + } else { + return List.of(); + } + }) + .build(); + final var addArgument = StringArgument.builder("subject") + .single() + .withDefaultDescription(ArgumentDescription.of("NickName or Address")) + .build(); + commandManager.command( + builder(commandManager) + .literal("blacklist") + .handler(ctx -> { + var config = epicGuard.messages().command(); + ctx.getSender().sendMessage(TextUtils.component(config.prefix() + config.usage() + .replace("{USAGE}", "/guard blacklist "))); + }) + ); + commandManager.command( + builder(commandManager) + .literal("blacklist") + .literal("remove") + .argument(removeArgument) + .handler(ctx -> { + var config = epicGuard.messages().command(); + var audience = ctx.getSender(); + var argumentString = ctx.get(removeArgument); + var meta = epicGuard.storageManager().resolveAddressMeta(argumentString); + if (meta == null) { + audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); + return; + } + if (!meta.blacklisted()) { + audience.sendMessage(TextUtils.component(config.prefix() + config.notBlacklisted().replace("{USER}", argumentString))); + return; + } + meta.blacklisted(false); + audience.sendMessage(TextUtils.component(config.prefix() + config.blacklistRemove().replace("{USER}", argumentString))); + }) + ); - if (args.length != 3) { - audience.sendMessage(TextUtils.component(config.prefix() + config.usage() - .replace("{USAGE}", "/guard blacklist "))); - return; - } - - var meta = epicGuard.storageManager().resolveAddressMeta(args[2]); - if (meta == null) { - audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); - return; - } - - if (args[1].equalsIgnoreCase("add")) { - if (meta.blacklisted()) { - audience.sendMessage(TextUtils.component(config.prefix() + config.alreadyBlacklisted().replace("{USER}", args[2]))); - return; - } - - meta.blacklisted(true); - audience.sendMessage(TextUtils.component(config.prefix() + config.blacklistAdd().replace("{USER}", args[2]))); - } else if (args[1].equalsIgnoreCase("remove")) { - if (!meta.blacklisted()) { - audience.sendMessage(TextUtils.component(config.prefix() + config.notBlacklisted().replace("{USER}", args[2]))); - return; - } - - meta.blacklisted(false); - audience.sendMessage(TextUtils.component(config.prefix() + config.blacklistRemove().replace("{USER}", args[2]))); - } - } - - @Override - public @NotNull Collection suggest(@NotNull String[] args, @NotNull EpicGuard epicGuard) { - if (args.length == 2) { - return List.of("add", "remove"); - } + commandManager.command( + builder(commandManager) + .literal("blacklist") + .literal("add") + .argument(addArgument) + .handler(ctx -> { + var config = epicGuard.messages().command(); + var audience = ctx.getSender(); + var argumentString = ctx.get(addArgument); + var meta = epicGuard.storageManager().resolveAddressMeta(argumentString); + if (meta == null) { + audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); + return; + } + if (meta.blacklisted()) { + audience.sendMessage(TextUtils.component(config.prefix() + config.alreadyBlacklisted().replace("{USER}", argumentString))); + return; + } - if (args[1].equalsIgnoreCase("remove") - && !epicGuard.config().misc().disableIPTabCompletion()) { - return epicGuard.storageManager().viewAddresses(AddressMeta::blacklisted); + meta.blacklisted(true); + audience.sendMessage(TextUtils.component(config.prefix() + config.blacklistAdd().replace("{USER}", argumentString))); + }) + ); } - return Collections.emptyList(); - } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java index 8c830dcc..d34d4c7e 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/HelpCommand.java @@ -15,24 +15,30 @@ package me.xneox.epicguard.core.command.sub; +import cloud.commandframework.CommandManager; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.storage.AddressMeta; import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; public class HelpCommand implements SubCommand { @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - for (String line : epicGuard.messages().command().mainCommand()) { - audience.sendMessage(TextUtils.component(line - .replace("{VERSION}", Constants.CURRENT_VERSION) - .replace("{BLACKLISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::blacklisted).size())) - .replace("{WHITELISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::whitelisted).size())) - .replace("{CPS}", Integer.toString(epicGuard.attackManager().connectionCounter())) - .replace("{ATTACK}", epicGuard.attackManager().isUnderAttack() ? "✔" : "✖"))); - } + public void register(CommandManager commandManager, EpicGuard epicGuard) { + commandManager.command( + builder(commandManager) + .literal("help") + .handler(ctx -> { + for (String line : epicGuard.messages().command().mainCommand()) { + ctx.getSender().sendMessage(TextUtils.component(line + .replace("{VERSION}", Constants.CURRENT_VERSION) + .replace("{BLACKLISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::blacklisted).size())) + .replace("{WHITELISTED-IPS}", Integer.toString(epicGuard.storageManager().viewAddresses(AddressMeta::whitelisted).size())) + .replace("{CPS}", Integer.toString(epicGuard.attackManager().connectionCounter())) + .replace("{ATTACK}", epicGuard.attackManager().isUnderAttack() ? "✔" : "✖"))); + } + }) + ); } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/ReloadCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/ReloadCommand.java index 05e3b376..c5bacb5a 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/ReloadCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/ReloadCommand.java @@ -15,18 +15,24 @@ package me.xneox.epicguard.core.command.sub; +import cloud.commandframework.CommandManager; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; public class ReloadCommand implements SubCommand { @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - var config = epicGuard.messages().command(); + public void register(CommandManager commandManager, EpicGuard epicGuard) { + commandManager.command( + builder(commandManager) + .literal("reload") + .handler(ctx -> { + var config = epicGuard.messages().command(); - epicGuard.loadConfigurations(); - audience.sendMessage(TextUtils.component(config.prefix() + config.reloaded())); + epicGuard.loadConfigurations(); + ctx.getSender().sendMessage(TextUtils.component(config.prefix() + config.reloaded())); + }) + ); } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/SaveCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/SaveCommand.java index 66200664..3b870b3c 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/SaveCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/SaveCommand.java @@ -15,24 +15,31 @@ package me.xneox.epicguard.core.command.sub; -import java.sql.SQLException; +import cloud.commandframework.CommandManager; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.util.LogUtils; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; + +import java.sql.SQLException; public class SaveCommand implements SubCommand { @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - try { - epicGuard.storageManager().database().save(); - audience.sendMessage(TextUtils.component(epicGuard.messages().command().prefix() + "Data has been saved successfully.")); - } catch (SQLException ex) { - audience.sendMessage(TextUtils.component(epicGuard.messages().command().prefix() + - "An exception occurred when saving data. See console for details.")); - LogUtils.catchException("Could not save data to the SQL database (command-induced)", ex); - } + public void register(CommandManager commandManager, EpicGuard epicGuard) { + commandManager.command( + builder(commandManager) + .literal("save") + .handler(ctx -> { + try { + epicGuard.storageManager().database().save(); + ctx.getSender().sendMessage(TextUtils.component(epicGuard.messages().command().prefix() + "Data has been saved successfully.")); + } catch (SQLException ex) { + ctx.getSender().sendMessage(TextUtils.component(epicGuard.messages().command().prefix() + + "An exception occurred when saving data. See console for details.")); + LogUtils.catchException("Could not save data to the SQL database (command-induced)", ex); + } + }) + ); } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/StatusCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/StatusCommand.java index ab44bbfc..e311b044 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/StatusCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/StatusCommand.java @@ -15,27 +15,30 @@ package me.xneox.epicguard.core.command.sub; -import java.util.Optional; -import java.util.UUID; +import cloud.commandframework.CommandManager; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.user.OnlineUser; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.identity.Identity; -import org.jetbrains.annotations.NotNull; public class StatusCommand implements SubCommand { - @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - var config = epicGuard.messages().command(); + @Override + public void register(CommandManager commandManager, EpicGuard epicGuard) { + commandManager.command( + builder(commandManager) + .literal("status") + .handler(ctx -> { + var config = epicGuard.messages().command(); - Optional uuidOptional = audience.pointers().get(Identity.UUID); - uuidOptional.ifPresent(uuid -> { - // UUID is present, enable notifications. - OnlineUser onlineUser = epicGuard.userManager().getOrCreate(uuid); - onlineUser.notifications(!onlineUser.notifications()); - audience.sendMessage(TextUtils.component(config.prefix() + config.toggleStatus())); - }); - } + ctx.getSender().get(Identity.UUID).ifPresent(uuid -> { + // UUID is present, enable notifications. + OnlineUser onlineUser = epicGuard.userManager().getOrCreate(uuid); + onlineUser.notifications(!onlineUser.notifications()); + ctx.getSender().sendMessage(TextUtils.component(config.prefix() + config.toggleStatus())); + }); + }) + ); + } } diff --git a/core/src/main/java/me/xneox/epicguard/core/command/sub/WhitelistCommand.java b/core/src/main/java/me/xneox/epicguard/core/command/sub/WhitelistCommand.java index 388f92c1..448d8083 100644 --- a/core/src/main/java/me/xneox/epicguard/core/command/sub/WhitelistCommand.java +++ b/core/src/main/java/me/xneox/epicguard/core/command/sub/WhitelistCommand.java @@ -15,64 +15,91 @@ package me.xneox.epicguard.core.command.sub; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.CommandManager; +import cloud.commandframework.arguments.standard.StringArgument; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.command.SubCommand; import me.xneox.epicguard.core.storage.AddressMeta; import me.xneox.epicguard.core.util.TextUtils; import net.kyori.adventure.audience.Audience; -import org.jetbrains.annotations.NotNull; + +import java.util.List; public class WhitelistCommand implements SubCommand { @Override - public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) { - var config = epicGuard.messages().command(); - - if (args.length != 3) { - audience.sendMessage(TextUtils.component(config.prefix() + config.usage() - .replace("{USAGE}", "/guard whitelist "))); - return; - } + public void register(CommandManager commandManager, EpicGuard epicGuard) { + final var removeArgument = StringArgument.builder("subject") + .single() + .withDefaultDescription(ArgumentDescription.of("NickName or Address")) + .withSuggestionsProvider((ctx, st) -> { + if (!epicGuard.config().misc().disableIPTabCompletion()) { + return epicGuard.storageManager().viewAddresses(AddressMeta::whitelisted); + } else { + return List.of(); + } + }) + .build(); + final var addArgument = StringArgument.builder("subject") + .single() + .withDefaultDescription(ArgumentDescription.of("NickName or Address")) + .build(); + commandManager.command( + builder(commandManager) + .literal("whitelist") + .handler(ctx -> { + var config = epicGuard.messages().command(); + ctx.getSender().sendMessage(TextUtils.component(config.prefix() + config.usage() + .replace("{USAGE}", "/guard whitelist "))); + }) + ); + commandManager.command( + builder(commandManager) + .literal("whitelist") + .literal("remove") + .argument(removeArgument) + .handler(ctx -> { + var config = epicGuard.messages().command(); + var audience = ctx.getSender(); + var argumentString = ctx.get(removeArgument); + var meta = epicGuard.storageManager().resolveAddressMeta(argumentString); + if (meta == null) { + audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); + return; + } + if (!meta.whitelisted()) { + audience.sendMessage(TextUtils.component(config.prefix() + config.notWhitelisted().replace("{USER}", argumentString))); + return; + } - var meta = epicGuard.storageManager().resolveAddressMeta(args[2]); - if (meta == null) { - audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); - return; - } + meta.whitelisted(false); + audience.sendMessage(TextUtils.component(config.prefix() + config.whitelistRemove().replace("{USER}", argumentString))); + }) + ); - if (args[1].equalsIgnoreCase("add")) { - if (meta.whitelisted()) { - audience.sendMessage(TextUtils.component(config.prefix() + config.alreadyWhitelisted().replace("{USER}", args[2]))); - return; - } + commandManager.command( + builder(commandManager) + .literal("whitelist") + .literal("add") + .argument(addArgument) + .handler(ctx -> { + var config = epicGuard.messages().command(); + var audience = ctx.getSender(); + var argumentString = ctx.get(addArgument); + var meta = epicGuard.storageManager().resolveAddressMeta(argumentString); + if (meta == null) { + audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument())); + return; + } + if (meta.whitelisted()) { + audience.sendMessage(TextUtils.component(config.prefix() + config.alreadyWhitelisted().replace("{USER}", argumentString))); + return; + } - meta.whitelisted(true); - audience.sendMessage(TextUtils.component(config.prefix() + config.whitelistAdd().replace("{USER}", args[2]))); - } else if (args[1].equalsIgnoreCase("remove")) { - if (!meta.whitelisted()) { - audience.sendMessage(TextUtils.component(config.prefix() + config.notWhitelisted().replace("{USER}", args[2]))); - return; - } - - meta.whitelisted(false); - audience.sendMessage(TextUtils.component(config.prefix() + config.whitelistRemove().replace("{USER}", args[2]))); - } + meta.whitelisted(true); + audience.sendMessage(TextUtils.component(config.prefix() + config.whitelistAdd().replace("{USER}", argumentString))); + }) + ); } - @Override - public @NotNull Collection suggest(@NotNull String[] args, @NotNull EpicGuard epicGuard) { - if (args.length == 2) { - return List.of("add", "remove"); - } - - if (args[1].equalsIgnoreCase("remove") - && !epicGuard.config().misc().disableIPTabCompletion()) { - return epicGuard.storageManager().viewAddresses(AddressMeta::whitelisted); - } - - return Collections.emptyList(); - } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8de29720..e1160b12 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,7 @@ waterfall="1.19-R0.1-SNAPSHOT" paper = "1.20.1-R0.1-SNAPSHOT" libby = "1.3.0" +cloud = "1.8.4" configurate = "4.1.2" miniplaceholders = "2.2.1" @@ -27,7 +28,7 @@ adventure-platform = "4.3.1" annotations = "24.0.1" -sqlite = "3.43.2.0" +sqlite = "3.43.2.1" hikaricp = "5.0.1" guava = "32.1.3-jre" @@ -49,6 +50,12 @@ adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "ad adventure-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure-api" } adventure-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure-api" } +cloud-core = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" } +cloud-velocity = { group = "cloud.commandframework", name = "cloud-velocity", version.ref = "cloud" } +cloud-bungee = { group = "cloud.commandframework", name = "cloud-bungee", version.ref = "cloud" } +cloud-paper = { group = "cloud.commandframework", name = "cloud-paper", version.ref = "cloud" } +cloud-sponge = { group = "cloud.commandframework", name = "cloud-sponge", version = "1.8.0-SNAPSHOT" } + annotations = { module = "org.jetbrains:annotations", version.ref = "annotations" } # Platform Compile Only Dependencies @@ -68,6 +75,7 @@ slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } log4j2 = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j2" } sqlite = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" } +mysql = { group = "com.mysql", name = "mysql-connector-j", version = "8.0.32" } hikaricp = { module = "com.zaxxer:HikariCP", version.ref = "hikaricp" } guava = { module = "com.google.guava:guava", version.ref = "guava" } diff --git a/paper/build.gradle.kts b/paper/build.gradle.kts index 2e7332f7..84212c15 100644 --- a/paper/build.gradle.kts +++ b/paper/build.gradle.kts @@ -6,6 +6,7 @@ dependencies { implementation(projects.core) implementation(libs.configurate) compileOnly(libs.paper) + implementation(libs.cloud.paper) } tasks { diff --git a/paper/src/main/java/me/xneox/epicguard/paper/EpicGuardPaper.java b/paper/src/main/java/me/xneox/epicguard/paper/EpicGuardPaper.java index c8e2ccc3..05d359ff 100644 --- a/paper/src/main/java/me/xneox/epicguard/paper/EpicGuardPaper.java +++ b/paper/src/main/java/me/xneox/epicguard/paper/EpicGuardPaper.java @@ -15,12 +15,16 @@ package me.xneox.epicguard.paper; +import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; +import cloud.commandframework.paper.PaperCommandManager; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.Platform; +import me.xneox.epicguard.core.command.CommandHandler; import me.xneox.epicguard.core.placeholder.Placeholders; import me.xneox.epicguard.paper.listener.*; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,9 +32,11 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Stream; -public class EpicGuardPaper extends JavaPlugin implements Platform { +@SuppressWarnings("unused") +public final class EpicGuardPaper extends JavaPlugin implements Platform { private EpicGuard epicGuard; private final Logger logger = this.getSLF4JLogger(); @@ -55,8 +61,18 @@ public void onEnable() { handler.ignoreCancelled() )); - this.getServer().getCommandMap() - .register("epicguard", new PaperCommandHandler(this.epicGuard, this)); + try { + final PaperCommandManager commandManager = new PaperCommandManager<>( + this, + AsynchronousCommandExecutionCoordinator.simpleCoordinator(), + Function.identity(), + Function.identity() + ); + commandManager.registerBrigadier(); + new CommandHandler<>(epicGuard, commandManager).register(); + } catch (Exception e) { + throw new RuntimeException(e); + } if (this.getServer().getPluginManager().isPluginEnabled("MiniPlaceholders")) { Placeholders.register(); diff --git a/paper/src/main/java/me/xneox/epicguard/paper/PaperCommandHandler.java b/paper/src/main/java/me/xneox/epicguard/paper/PaperCommandHandler.java deleted file mode 100644 index 53c52c67..00000000 --- a/paper/src/main/java/me/xneox/epicguard/paper/PaperCommandHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * EpicGuard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * EpicGuard is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - */ - -package me.xneox.epicguard.paper; - -import me.xneox.epicguard.core.EpicGuard; -import me.xneox.epicguard.core.command.CommandHandler; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.PluginIdentifiableCommand; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -public final class PaperCommandHandler extends Command implements PluginIdentifiableCommand { - private final CommandHandler HANDLER; - private final EpicGuardPaper plugin; - public PaperCommandHandler(EpicGuard epicGuard, EpicGuardPaper plugin) { - super("epicguard", "Main plugin command.", "", - List.of("guard", "epicguardpaper", "guardpaper")); - this.setPermission("epicguard.admin"); - this.plugin = plugin; - this.HANDLER = new CommandHandler(epicGuard); - } - - private static final String[] EMPTY_ARRAY = new String[0]; - - @Override - public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) { - HANDLER.handleCommand(args, sender); - return false; - } - - @Override - public @NotNull List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { - if (args.length == 0) { - return new ArrayList<>(HANDLER.handleSuggestions(EMPTY_ARRAY)); - } - - final String command = args[0].toLowerCase(Locale.ROOT); - - if (command.equals("guard") || command.equals("epicguardpaper") || command.equals("guardpaper")) { - return new ArrayList<>(HANDLER.handleSuggestions(Arrays.copyOfRange(args, 1, args.length))); - } - return List.of(); - } - - @Override - public @NotNull Plugin getPlugin() { - return this.plugin; - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a9c24aae..08e913dd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,6 +7,7 @@ dependencyResolutionManagement { repositories { maven("https://papermc.io/repo/repository/maven-public/") maven("https://repo.alessiodp.com/releases/") + maven("https://repo.jpenilla.xyz/snapshots/") } } @@ -15,4 +16,10 @@ plugins { id("org.spongepowered.gradle.plugin") version "2.2.0" } -include("core", "paper", "velocity", "waterfall", "sponge") \ No newline at end of file +include( + "core", + "paper", + "velocity", + "waterfall" + // "sponge" +) \ No newline at end of file diff --git a/sponge/build.gradle.kts b/sponge/build.gradle.kts index 82db811c..94d28662 100644 --- a/sponge/build.gradle.kts +++ b/sponge/build.gradle.kts @@ -8,6 +8,18 @@ plugins { dependencies { implementation(projects.core) implementation(libs.libby.sponge) + implementation(libs.cloud.sponge) + implementation(libs.commons.text) + implementation(libs.commons.compress) + implementation(libs.fuzzywuzzy) + implementation(libs.geoip) + implementation(libs.hikaricp) + implementation(libs.jackson.core) + implementation(libs.jackson.annotations) + implementation(libs.jackson.databind) + implementation(libs.maxmind.db) + implementation(libs.sqlite) + implementation(libs.mysql) compileOnly(libs.slf4j) } @@ -20,7 +32,7 @@ sponge { } plugin("epicguard") { displayName("EpicGuard") - entrypoint("me.xneox.epicguard.sponge.EpicGuard") + entrypoint("me.xneox.epicguard.sponge.EpicGuardSponge") description(project.description) links { homepage("https://github.com/4drian3d/EpicGuard") @@ -40,13 +52,13 @@ sponge { tasks { shadowJar { relocate("net.byteflux.libby", "me.xneox.epicguard.velocity.libby") - relocate("org.spongepowered", "me.xneox.epicguard.libs.org.spongepowered") - relocate("io.leangen.geantyref", "me.xneox.epicguard.libs.io.leangen.geantyref") relocate("com.zaxxer.hikari", "me.xneox.epicguard.libs.com.zaxxer.hikari") relocate("com.mysql.cj", "me.xneox.epicguard.libs.mysql") relocate("org.xerial", "me.xneox.epicguard.libs.org.xerial") relocate("org.apache.commons", "me.xneox.epicguard.libs.commons") relocate("me.xdrop.fuzzywuzzy", "me.xneox.epicguard.libs.fuzzywuzzy") + relocate("cloud.commandframework", "me.xneox.epicguard.libs.cloud") + exclude("io/leangen/geantyref/**") } build { dependsOn(shadowJar) diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java b/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java index 8fcecb25..a312700c 100644 --- a/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/EpicGuardSponge.java @@ -1,12 +1,16 @@ package me.xneox.epicguard.sponge; +import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; +import cloud.commandframework.sponge.SpongeCommandManager; import com.google.inject.Inject; import com.google.inject.Injector; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.Platform; +import me.xneox.epicguard.core.command.CommandHandler; import me.xneox.epicguard.core.placeholder.Placeholders; import me.xneox.epicguard.sponge.listener.*; import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,8 +19,11 @@ import org.spongepowered.api.Game; import org.spongepowered.api.MinecraftVersion; import org.spongepowered.api.Server; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.config.DefaultConfig; import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; import org.spongepowered.api.event.lifecycle.StartedEngineEvent; import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; import org.spongepowered.api.plugin.PluginManager; @@ -27,6 +34,7 @@ import java.nio.file.Path; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; @Plugin("epicguard") @@ -50,7 +58,7 @@ public final class EpicGuardSponge implements Platform { @Listener public void onServerInitialization(StartedEngineEvent event) { - this.injector.getInstance(Libraries.class).register(); + //this.injector.getInstance(Libraries.class).register(); this.epicGuard = new EpicGuard(this, configFilePath); this.injector = injector.createChildInjector( binder -> binder.bind(EpicGuard.class).toInstance(epicGuard) @@ -71,6 +79,8 @@ public void onServerInitialization(StartedEngineEvent event) { } } + + @Listener public void onServerShutdown(final StoppingEngineEvent event) { this.epicGuard.shutdown(); @@ -113,4 +123,26 @@ public void scheduleRepeatingTask(@NotNull Runnable task, long seconds) { .interval(seconds, TimeUnit.SECONDS) .build()); } + + private final AtomicInteger registration = new AtomicInteger(0); + @Listener + public void onCommandRegister(final RegisterCommandEvent event) { + if (registration.getAndIncrement() == 0) { + final SpongeCommandManager commandManager = new SpongeCommandManager<>( + pluginContainer, + AsynchronousCommandExecutionCoordinator.simpleCoordinator(), + AudienceHolder::cause, + AudienceHolder::new + ); + new CommandHandler<>(epicGuard, commandManager).register(); + } + } + + record AudienceHolder(@NotNull CommandCause cause) implements ForwardingAudience.Single { + + @Override + public @NotNull Audience audience() { + return cause.audience(); + } + } } diff --git a/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java b/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java index d9ce0643..bfec52ae 100644 --- a/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java +++ b/sponge/src/main/java/me/xneox/epicguard/sponge/Libraries.java @@ -1,7 +1,143 @@ package me.xneox.epicguard.sponge; +import com.google.inject.Inject; +import me.xneox.epicguard.core.util.Constants; +import net.byteflux.libby.Library; +import net.byteflux.libby.SpongeLibraryManager; +import net.byteflux.libby.relocation.Relocation; + public class Libraries { + @Inject + private SpongeLibraryManager manager; public void register() { + final Library MYSQL = Library.builder() + .groupId("com{}mysql") + .artifactId("mysql-connector-j") + .version("8.0.32") + .id("mysql") + .relocate("com{}mysql{}cj", "me{}xneox{}epicguard{}libs{}mysql") + .build(); + final Library SQLITE = Library.builder() + .groupId("org{}xerial") + .artifactId("sqlite-jdbc") + .version("3.40.1.0") + .id("sqlite") + .relocate("org{}xerial", "me{}xneox{}epicguard{}libs{}org{}xerial") + .build(); + + final Relocation configurateRelocation = new Relocation( + "org{}spongepowered", + "me{}xneox{}epicguard{}libs{}org{}spongepowered" + ); + final Relocation geantyrefRelocation = new Relocation( + "io{}leangen{}geantyref", + "me{}xneox{}epicguard{}libs{}io{}leangen{}geantyref" + ); + final Library CONFIGURATE_HOCON = Library.builder() + .groupId("org{}spongepowered") + .artifactId("configurate-hocon") + .version(Constants.CONFIGURATE) + .id("configurate-hocon") + .relocate(configurateRelocation) + .relocate(geantyrefRelocation) + .build(); + final Library CONFIGURATE_CORE = Library.builder() + .groupId("org{}spongepowered") + .artifactId("configurate-core") + .version(Constants.CONFIGURATE) + .id("configurate-core") + .relocate(configurateRelocation) + .relocate(geantyrefRelocation) + .build(); + final Library GEANTYREF = Library.builder() + .groupId("io{}leangen{}geantyref") + .artifactId("geantyref") + .version("1.3.13") + .id("geantyref") + .relocate(configurateRelocation) + .relocate(geantyrefRelocation) + .build(); + final Library HIKARI = Library.builder() + .groupId("com{}zaxxer") + .artifactId("HikariCP") + .version(Constants.HIKARI) + .id("hikari") + .relocate("com{}zaxxer{}hikari", "me{}xneox{}epicguard{}libs{}com{}zaxxer{}hikari") + .build(); + final Relocation commonsRelocation = new Relocation( + "org{}apache{}commons", + "me{}xneox{}epicguard{}libs{}commons" + ); + final Library COMMONS_COMPRESS = Library.builder() + .groupId("org{}apache{}commons") + .artifactId("commons-compress") + .version(Constants.COMMANDS_COMPRESS) + .id("commons-compress") + .relocate(commonsRelocation) + .build(); + final Library COMMONS_TEXT = Library.builder() + .groupId("org{}apache{}commons") + .artifactId("commons-text") + .version(Constants.COMMONS_TEXT) + .id("commons-text") + .relocate(commonsRelocation) + .build(); + final Library MAXMIND_GEOIP = Library.builder() + .groupId("com.maxmind.geoip2") + .artifactId("geoip2") + .version(Constants.GEOIP) + .id("geoip2") + .build(); + final Library MAXMIND_DB = Library.builder() + .groupId("com.maxmind.db") + .artifactId("maxmind-db") + .version(Constants.MAXMIND_DB) + .id("maxmind-db") + .build(); + final Library JACKSON_ANNOTATIONS = Library.builder() + .groupId("com.fasterxml.jackson.core") + .artifactId("jackson-annotations") + .version(Constants.JACKSON) + .id("jackson-annotations") + .build(); + final Library JACKSON_CORE = Library.builder() + .groupId("com.fasterxml.jackson.core") + .artifactId("jackson-core") + .version(Constants.JACKSON) + .id("jackson-core") + .build(); + final Library JACKSON_DATABIND = Library.builder() + .groupId("com.fasterxml.jackson.core") + .artifactId("jackson-databind") + .version(Constants.JACKSON) + .id("jackson-databind") + .build(); + final Relocation fuzzywuzzyRelocator = new Relocation( + "me{}xdrop{}fuzzywuzzy", + "me{}xneox{}epicguard{}libs{}fuzzywuzzy" + ); + final Library FUZZYWUZZY = Library.builder() + .groupId("me.xdrop") + .artifactId("fuzzywuzzy") + .version(Constants.FUZZYWUZZY) + .id("fuzzywuzzy") + .relocate(fuzzywuzzyRelocator) + .build(); + manager.addMavenCentral(); + manager.loadLibrary(SQLITE); + manager.loadLibrary(MYSQL); + manager.loadLibrary(GEANTYREF); + manager.loadLibrary(CONFIGURATE_CORE); + manager.loadLibrary(CONFIGURATE_HOCON); + manager.loadLibrary(HIKARI); + manager.loadLibrary(COMMONS_COMPRESS); + manager.loadLibrary(COMMONS_TEXT); + manager.loadLibrary(MAXMIND_GEOIP); + manager.loadLibrary(MAXMIND_DB); + manager.loadLibrary(JACKSON_ANNOTATIONS); + manager.loadLibrary(JACKSON_CORE); + manager.loadLibrary(JACKSON_DATABIND); + manager.loadLibrary(FUZZYWUZZY); } } diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 149ecf92..8d0e842e 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { implementation(projects.core) implementation(libs.libby.velocity) + implementation(libs.cloud.velocity) compileOnly(libs.velocity) annotationProcessor(libs.velocity) diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java b/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java index 1c1dbe5d..060404bb 100644 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java +++ b/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java @@ -15,8 +15,14 @@ package me.xneox.epicguard.velocity; +import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; +import cloud.commandframework.velocity.CloudInjectionModule; +import cloud.commandframework.velocity.VelocityCommandManager; import com.google.inject.Inject; import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; @@ -26,6 +32,7 @@ import com.velocitypowered.api.proxy.ProxyServer; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.Platform; +import me.xneox.epicguard.core.command.CommandHandler; import me.xneox.epicguard.core.placeholder.Placeholders; import me.xneox.epicguard.core.util.Constants; import me.xneox.epicguard.velocity.listener.*; @@ -65,10 +72,15 @@ public void onEnable(ProxyInitializeEvent e) { this.injector.getInstance(Libraries.class).register(); this.epicGuard = new EpicGuard(this, dataFolder); this.injector = injector.createChildInjector( - binder -> binder.bind(EpicGuard.class).toInstance(epicGuard) + binder -> binder.bind(EpicGuard.class).toInstance(epicGuard), + CloudInjectionModule.createNative(AsynchronousCommandExecutionCoordinator.simpleCoordinator()) ); - this.injector.getInstance(VelocityCommandHandler.class).register(); + final VelocityCommandManager commandManager + = injector.getInstance(Key.get(new TypeLiteral<>(){})); + + new CommandHandler<>(epicGuard, commandManager).register(); + Stream.of( PostLoginListener.class, PreLoginListener.class, diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/VelocityCommandHandler.java b/velocity/src/main/java/me/xneox/epicguard/velocity/VelocityCommandHandler.java deleted file mode 100644 index 2e2d0328..00000000 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/VelocityCommandHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * EpicGuard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * EpicGuard is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - */ - -package me.xneox.epicguard.velocity; - -import com.google.inject.Inject; -import com.velocitypowered.api.command.CommandManager; -import com.velocitypowered.api.command.SimpleCommand; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import me.xneox.epicguard.core.EpicGuard; -import me.xneox.epicguard.core.command.CommandHandler; - -public final class VelocityCommandHandler extends CommandHandler implements SimpleCommand { - @Inject - private CommandManager commandManager; - @Inject - private EpicGuardVelocity plugin; - @Inject - public VelocityCommandHandler(EpicGuard epicGuard) { - super(epicGuard); - } - - @Override - public void execute(Invocation invocation) { - this.handleCommand(invocation.arguments(), invocation.source()); - } - - @Override - public CompletableFuture> suggestAsync(Invocation invocation) { - return CompletableFuture.supplyAsync(() -> - new ArrayList<>(this.handleSuggestions(invocation.arguments()))); - } - - @Override - public boolean hasPermission(Invocation invocation) { - return invocation.source().hasPermission("epicguard.admin"); - } - - void register() { - final var meta = commandManager - .metaBuilder("epicguard") - .aliases("guard", "epicguardvelocity", "guardvelocity") - .plugin(plugin) - .build(); - commandManager.register(meta, this); - } -} diff --git a/waterfall/build.gradle.kts b/waterfall/build.gradle.kts index 5f223375..2716cde5 100644 --- a/waterfall/build.gradle.kts +++ b/waterfall/build.gradle.kts @@ -7,6 +7,7 @@ dependencies { implementation(projects.core) compileOnly(libs.adventure.platform.bungeecord) compileOnly(libs.waterfall) + compileOnly(libs.cloud.bungee) } tasks { @@ -39,6 +40,7 @@ bungee { libs.jackson.annotations to libs.versions.jackson, libs.adventure.minimessage to libs.versions.adventure.api, libs.fuzzywuzzy to libs.versions.fuzzywuzzy, + libs.cloud.bungee to libs.versions.cloud ).map { "${it.first.get().module}:${it.second.get()}" } } diff --git a/waterfall/src/main/java/me/xneox/epicguard/waterfall/BungeeCommandHandler.java b/waterfall/src/main/java/me/xneox/epicguard/waterfall/BungeeCommandHandler.java deleted file mode 100644 index cfeee25c..00000000 --- a/waterfall/src/main/java/me/xneox/epicguard/waterfall/BungeeCommandHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * EpicGuard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * EpicGuard is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - */ - -package me.xneox.epicguard.waterfall; - -import me.xneox.epicguard.core.command.CommandHandler; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.plugin.Command; -import net.md_5.bungee.api.plugin.TabExecutor; - -// why bungee... why Command is an abstract class? -public class BungeeCommandHandler extends Command implements TabExecutor { - private final CommandHandler commandHandler; - private final EpicGuardWaterfall plugin; - - public BungeeCommandHandler(EpicGuardWaterfall plugin) { - super("epicguard", "epicguard.admin", "guard", "epicguardbungee", "guardbungee"); - this.plugin = plugin; - this.commandHandler = new CommandHandler(plugin.epicGuard()); - } - - @Override - public void execute(CommandSender sender, String[] args) { - //noinspection resource - this.commandHandler.handleCommand(args, this.plugin.adventure().sender(sender)); - } - - @Override - public Iterable onTabComplete(CommandSender sender, String[] args) { - return this.commandHandler.handleSuggestions(args); - } -} diff --git a/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java b/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java index 261205d9..c591a0dc 100644 --- a/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java +++ b/waterfall/src/main/java/me/xneox/epicguard/waterfall/EpicGuardWaterfall.java @@ -15,12 +15,17 @@ package me.xneox.epicguard.waterfall; +import cloud.commandframework.bungee.BungeeCommandManager; +import cloud.commandframework.execution.CommandExecutionCoordinator; import me.xneox.epicguard.core.EpicGuard; import me.xneox.epicguard.core.Platform; +import me.xneox.epicguard.core.command.CommandHandler; import me.xneox.epicguard.waterfall.listener.*; import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.kyori.adventure.text.Component; +import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -28,7 +33,8 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; -public class EpicGuardWaterfall extends Plugin implements Platform { +@SuppressWarnings("unused") +public final class EpicGuardWaterfall extends Plugin implements Platform { private EpicGuard epicGuard; private BungeeAudiences adventure; private final Logger logger = this.getSLF4JLogger(); @@ -45,7 +51,13 @@ public void onEnable() { pluginManager.registerListener(this, new ServerPingListener(this.epicGuard)); pluginManager.registerListener(this, new PlayerSettingsListener(this.epicGuard)); - pluginManager.registerCommand(this, new BungeeCommandHandler(this)); + final BungeeCommandManager commandManager = new BungeeCommandManager<>( + this, + CommandExecutionCoordinator.simpleCoordinator(), + LegacyAudienceHolder::new, + LegacyAudienceHolder::sender + ); + new CommandHandler<>(epicGuard, commandManager).register(); this.logger.warn(""" --------------------------------------- @@ -64,6 +76,23 @@ public void onEnable() { } + private final class LegacyAudienceHolder implements ForwardingAudience.Single { + private final CommandSender sender; + + private LegacyAudienceHolder(CommandSender sender) { + this.sender = sender; + } + + @Override + public @NotNull Audience audience() { + return adventure.sender(sender); + } + + CommandSender sender() { + return this.sender; + } + } + @Override public void onDisable() { this.epicGuard.shutdown(); @@ -104,14 +133,4 @@ public void runTaskLater(@NotNull Runnable task, long seconds) { public void scheduleRepeatingTask(@NotNull Runnable task, long seconds) { this.getProxy().getScheduler().schedule(this, task, seconds, seconds, TimeUnit.SECONDS); } - - @NotNull - public BungeeAudiences adventure() { - return this.adventure; - } - - @NotNull - public EpicGuard epicGuard() { - return this.epicGuard; - } } From d6c554a93455ec6a30e6709251abaf99a6d39f62 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 3 Nov 2023 21:21:02 -0500 Subject: [PATCH 3/3] feat: Implement Cloud runtime downloader --- core/build.gradle.kts | 1 + .../epicguard/core/utils/Constants.java.peb | 1 + gradle/libs.versions.toml | 2 +- paper/build.gradle.kts | 2 +- .../xneox/epicguard/paper/LibraryLoader.java | 3 +- velocity/build.gradle.kts | 3 +- .../epicguard/velocity/EpicGuardVelocity.java | 31 +++++-- .../xneox/epicguard/velocity/Libraries.java | 85 ++++++++++++++++--- 8 files changed, 101 insertions(+), 27 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 08707ac0..156a8323 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -57,6 +57,7 @@ sourceSets { property("jackson", libs.versions.jackson.get()) property("maxminddb", libs.versions.maxmind.db.get()) property("fuzzywuzzy", libs.versions.fuzzywuzzy.get()) + property("cloud", libs.versions.cloud.get()) } } } diff --git a/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb b/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb index a7b9dc9f..b542af96 100644 --- a/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb +++ b/core/src/main/java-templates/me/xneox/epicguard/core/utils/Constants.java.peb @@ -13,4 +13,5 @@ public final class Constants { public static final String JACKSON = "{{ jackson }}"; public static final String FUZZYWUZZY = "{{ fuzzywuzzy }}"; public static final String MAXMIND_DB = "{{ maxminddb }}"; + public static final String CLOUD = "{{ cloud }}"; } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e1160b12..c34c45ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ metadata.format.version = "1.1" # Compile only velocity = "3.2.0-SNAPSHOT" waterfall="1.19-R0.1-SNAPSHOT" -paper = "1.20.1-R0.1-SNAPSHOT" +paper = "1.20.2-R0.1-SNAPSHOT" libby = "1.3.0" cloud = "1.8.4" diff --git a/paper/build.gradle.kts b/paper/build.gradle.kts index 84212c15..36445411 100644 --- a/paper/build.gradle.kts +++ b/paper/build.gradle.kts @@ -6,7 +6,7 @@ dependencies { implementation(projects.core) implementation(libs.configurate) compileOnly(libs.paper) - implementation(libs.cloud.paper) + compileOnly(libs.cloud.paper) } tasks { diff --git a/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java b/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java index c766b9a5..c9b2b5f9 100644 --- a/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java +++ b/paper/src/main/java/me/xneox/epicguard/paper/LibraryLoader.java @@ -32,7 +32,8 @@ public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) { "com.fasterxml.jackson.core:jackson-annotations:" + Constants.JACKSON, "com.fasterxml.jackson.core:jackson-core:" + Constants.JACKSON, "com.fasterxml.jackson.core:jackson-databind:" + Constants.JACKSON, - "me.xdrop:fuzzywuzzy:" + Constants.FUZZYWUZZY + "me.xdrop:fuzzywuzzy:" + Constants.FUZZYWUZZY, + "cloud.commandframework:cloud-paper:" + Constants.CLOUD ) .map(artifact -> new Dependency(new DefaultArtifact(artifact), null)) .forEach(resolver::addDependency); diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 8d0e842e..7a201de9 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -5,7 +5,7 @@ plugins { dependencies { implementation(projects.core) implementation(libs.libby.velocity) - implementation(libs.cloud.velocity) + compileOnly(libs.cloud.velocity) compileOnly(libs.velocity) annotationProcessor(libs.velocity) @@ -21,6 +21,7 @@ tasks { relocate("org.xerial", "me.xneox.epicguard.libs.org.xerial") relocate("org.apache.commons", "me.xneox.epicguard.libs.commons") relocate("me.xdrop.fuzzywuzzy", "me.xneox.epicguard.libs.fuzzywuzzy") + relocate("cloud.commandframework", "me.xneox.epicguard.libs.cloud") } build { dependsOn(shadowJar) diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java b/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java index 060404bb..5fe88d1a 100644 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java +++ b/velocity/src/main/java/me/xneox/epicguard/velocity/EpicGuardVelocity.java @@ -16,17 +16,15 @@ package me.xneox.epicguard.velocity; import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; -import cloud.commandframework.velocity.CloudInjectionModule; import cloud.commandframework.velocity.VelocityCommandManager; import com.google.inject.Inject; import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.TypeLiteral; import com.velocitypowered.api.command.CommandSource; 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.PluginContainer; import com.velocitypowered.api.plugin.PluginManager; import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.ProxyServer; @@ -44,6 +42,7 @@ import java.nio.file.Path; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Stream; @Plugin( @@ -72,14 +71,10 @@ public void onEnable(ProxyInitializeEvent e) { this.injector.getInstance(Libraries.class).register(); this.epicGuard = new EpicGuard(this, dataFolder); this.injector = injector.createChildInjector( - binder -> binder.bind(EpicGuard.class).toInstance(epicGuard), - CloudInjectionModule.createNative(AsynchronousCommandExecutionCoordinator.simpleCoordinator()) + binder -> binder.bind(EpicGuard.class).toInstance(epicGuard) ); - final VelocityCommandManager commandManager - = injector.getInstance(Key.get(new TypeLiteral<>(){})); - - new CommandHandler<>(epicGuard, commandManager).register(); + this.injector.getInstance(CommandRegister.class).register(); Stream.of( PostLoginListener.class, @@ -128,4 +123,22 @@ public void runTaskLater(@NotNull Runnable task, long seconds) { public void scheduleRepeatingTask(@NotNull Runnable task, long seconds) { this.server.getScheduler().buildTask(this, task).repeat(seconds, TimeUnit.SECONDS).schedule(); } + + + private record CommandRegister(PluginContainer pluginContainer, ProxyServer proxyServer, EpicGuard epicGuard) { + @Inject + private CommandRegister {} + + private void register() { + final VelocityCommandManager commandManager = new VelocityCommandManager<>( + pluginContainer, + proxyServer, + AsynchronousCommandExecutionCoordinator.simpleCoordinator(), + Function.identity(), + Function.identity() + ); + + new CommandHandler<>(epicGuard, commandManager).register(); + } + } } diff --git a/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java b/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java index aafe5a97..2d46eeda 100644 --- a/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java +++ b/velocity/src/main/java/me/xneox/epicguard/velocity/Libraries.java @@ -138,22 +138,79 @@ void register() { .id("fuzzywuzzy") .relocate(fuzzywuzzyRelocator) .build(); + final Relocation cloudRelocation = + new Relocation( + "cloud{}commandframework", + "me.xneox.epicguard{}libs{}cloud"); + final Library cloudVelocity = Library.builder() + .groupId("cloud{}commandframework") + .artifactId("cloud-velocity") + .version(Constants.CLOUD) + .id("cloudVelocity") + .relocate(geantyrefRelocation) + .relocate(cloudRelocation) + .build(); + final Library cloudBrigadier = Library.builder() + .groupId("cloud{}commandframework") + .artifactId("cloud-brigadier") + .version(Constants.CLOUD) + .id("cloudBrigadier") + .relocate(geantyrefRelocation) + .relocate(cloudRelocation) + .build(); + final Library cloudCore = Library.builder() + .groupId("cloud{}commandframework") + .artifactId("cloud-core") + .version(Constants.CLOUD) + .id("cloudCore") + .relocate(geantyrefRelocation) + .relocate(cloudRelocation) + .build(); + final Library cloudServices = Library.builder() + .groupId("cloud{}commandframework") + .artifactId("cloud-services") + .version(Constants.CLOUD) + .id("cloudServices") + .relocate(geantyrefRelocation) + .relocate(cloudRelocation) + .build(); + final Library apiGuardian = Library.builder() + .groupId("org.apiguardian") + .artifactId("apiguardian-api") + .version("1.1.2") + .id("apiguardian") + .build(); manager.addMavenCentral(); - manager.loadLibrary(SQLITE); - manager.loadLibrary(MYSQL); - manager.loadLibrary(GEANTYREF); - manager.loadLibrary(CONFIGURATE_CORE); - manager.loadLibrary(CONFIGURATE_HOCON); - manager.loadLibrary(HIKARI); - manager.loadLibrary(COMMONS_COMPRESS); - manager.loadLibrary(COMMONS_TEXT); - manager.loadLibrary(MAXMIND_GEOIP); - manager.loadLibrary(MAXMIND_DB); - manager.loadLibrary(JACKSON_ANNOTATIONS); - manager.loadLibrary(JACKSON_CORE); - manager.loadLibrary(JACKSON_DATABIND); - manager.loadLibrary(FUZZYWUZZY); + loadLibraries( + manager, + SQLITE, + MYSQL, + GEANTYREF, + CONFIGURATE_CORE, + CONFIGURATE_HOCON, + HIKARI, + COMMONS_COMPRESS, + COMMONS_TEXT, + MAXMIND_GEOIP, + MAXMIND_DB, + JACKSON_ANNOTATIONS, + JACKSON_CORE, + JACKSON_DATABIND, + FUZZYWUZZY, + cloudCore, + cloudBrigadier, + cloudServices, + cloudVelocity, + apiGuardian + ); + + } + + private void loadLibraries(VelocityLibraryManager manager, Library... libraries) { + for (final Library library : libraries) { + manager.loadLibrary(library); + } } }