diff --git a/.gitmodules b/.gitmodules index 074c6a2c..f04fc7a9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "core/src/main/resources/languages"] path = core/src/main/resources/languages url = https://github.com/GeyserMC/languages - branch = l10n_floodgate + branch = floodgate \ No newline at end of file diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 4418b61a..70579bbc 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -1,3 +1,5 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + dependencies { api("org.geysermc.geyser", "common", Versions.geyserVersion) api("org.geysermc.cumulus", "cumulus", Versions.cumulusVersion) @@ -5,3 +7,12 @@ dependencies { compileOnly("io.netty", "netty-transport", Versions.nettyVersion) } + +tasks { + named("jar") { + archiveClassifier.set("") + } + named("shadowJar") { + archiveClassifier.set("shaded") + } +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 00000000..30499ad2 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "build-logic" \ No newline at end of file diff --git a/build-logic/src/main/kotlin/Versions.kt b/build-logic/src/main/kotlin/Versions.kt index 612f8b36..183655f4 100644 --- a/build-logic/src/main/kotlin/Versions.kt +++ b/build-logic/src/main/kotlin/Versions.kt @@ -30,11 +30,11 @@ object Versions { const val configUtilsVersion = "1.0-SNAPSHOT" const val spigotVersion = "1.19.4-R0.1-SNAPSHOT" const val fastutilVersion = "8.5.3" - const val guiceVersion = "5.1.0" + const val guiceVersion = "6.0.0" const val nettyVersion = "4.1.49.Final" const val snakeyamlVersion = "1.28" - const val cloudVersion = "1.5.0" - const val bstatsVersion = "d2fbbd6823" + const val cloudVersion = "2.0.0-beta.2" + const val bstatsVersion = "3.0.2" const val javaWebsocketVersion = "1.5.2" diff --git a/build-logic/src/main/kotlin/floodgate.publish-conventions.gradle.kts b/build-logic/src/main/kotlin/floodgate.publish-conventions.gradle.kts index 0f7b7618..75c054f8 100644 --- a/build-logic/src/main/kotlin/floodgate.publish-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/floodgate.publish-conventions.gradle.kts @@ -12,4 +12,10 @@ indra { publishSnapshotsTo("geysermc", "https://repo.opencollab.dev/maven-snapshots") publishReleasesTo("geysermc", "https://repo.opencollab.dev/maven-releases") +} + +publishing { + // skip shadow jar from publishing. Workaround for https://github.com/johnrengelman/shadow/issues/651 + val javaComponent = project.components["java"] as AdhocComponentWithVariants + javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { skip() } } \ No newline at end of file diff --git a/bungee/build.gradle.kts b/bungee/build.gradle.kts index 0d228850..69ab1120 100644 --- a/bungee/build.gradle.kts +++ b/bungee/build.gradle.kts @@ -4,12 +4,12 @@ var guavaVersion = "21.0" dependencies { api(projects.core) - implementation("cloud.commandframework", "cloud-bungee", Versions.cloudVersion) + implementation("org.incendo", "cloud-bungee", Versions.cloudVersion) } relocate("com.google.inject") relocate("net.kyori") -relocate("cloud.commandframework") +relocate("org.incendo.cloud") // used in cloud relocate("io.leangen.geantyref") // since 1.20 diff --git a/bungee/src/main/java/org/geysermc/floodgate/module/BungeePlatformModule.java b/bungee/src/main/java/org/geysermc/floodgate/module/BungeePlatformModule.java index 4943d88c..ec256d69 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/module/BungeePlatformModule.java +++ b/bungee/src/main/java/org/geysermc/floodgate/module/BungeePlatformModule.java @@ -25,9 +25,6 @@ package org.geysermc.floodgate.module; -import cloud.commandframework.CommandManager; -import cloud.commandframework.bungee.BungeeCommandManager; -import cloud.commandframework.execution.CommandExecutionCoordinator; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.Singleton; @@ -35,7 +32,6 @@ import com.google.inject.name.Names; import java.util.logging.Logger; import lombok.RequiredArgsConstructor; -import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.api.plugin.Plugin; import org.geysermc.floodgate.BungeePlugin; @@ -51,6 +47,7 @@ import org.geysermc.floodgate.platform.util.PlatformUtils; import org.geysermc.floodgate.player.FloodgateCommandPreprocessor; import org.geysermc.floodgate.player.UserAudience; +import org.geysermc.floodgate.player.audience.FloodgateSenderMapper; import org.geysermc.floodgate.pluginmessage.BungeePluginMessageRegistration; import org.geysermc.floodgate.pluginmessage.BungeePluginMessageUtils; import org.geysermc.floodgate.pluginmessage.BungeeSkinApplier; @@ -60,6 +57,9 @@ import org.geysermc.floodgate.util.BungeeCommandUtil; import org.geysermc.floodgate.util.BungeePlatformUtils; import org.geysermc.floodgate.util.LanguageManager; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.bungee.BungeeCommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; @RequiredArgsConstructor public final class BungeePlatformModule extends AbstractModule { @@ -88,9 +88,8 @@ public Plugin bungeePlugin() { public CommandManager commandManager(CommandUtil commandUtil) { CommandManager commandManager = new BungeeCommandManager<>( plugin, - CommandExecutionCoordinator.simpleCoordinator(), - commandUtil::getUserAudience, - audience -> (CommandSender) audience.source() + ExecutionCoordinator.simpleCoordinator(), + new FloodgateSenderMapper<>(commandUtil) ); commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil)); return commandManager; diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 1df4ae95..7d3d4632 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,3 +1,5 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + plugins { id("floodgate.generate-templates") } @@ -13,10 +15,8 @@ dependencies { api("com.nukkitx.fastutil", "fastutil-short-object-maps", Versions.fastutilVersion) api("com.nukkitx.fastutil", "fastutil-int-object-maps", Versions.fastutilVersion) api("org.java-websocket", "Java-WebSocket", Versions.javaWebsocketVersion) - api("cloud.commandframework", "cloud-core", Versions.cloudVersion) - - //todo use official dependency once https://github.com/Bastian/bstats-metrics/pull/118 is merged - api("com.github.Konicai.bstats-metrics", "bstats-base", Versions.bstatsVersion) + api("org.incendo", "cloud-core", Versions.cloudVersion) + api("org.bstats", "bstats-base", Versions.bstatsVersion) } // present on all platforms @@ -31,4 +31,10 @@ tasks { replaceToken("branch", branchName()) replaceToken("buildNumber", buildNumber()) } -} + named("jar") { + archiveClassifier.set("") + } + named("shadowJar") { + archiveClassifier.set("shaded") + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java b/core/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java index fe8695fd..7c06429d 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java @@ -26,12 +26,8 @@ package org.geysermc.floodgate.command; import static org.geysermc.floodgate.command.CommonCommandMessage.CHECK_CONSOLE; +import static org.incendo.cloud.parser.standard.StringParser.stringParser; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.Command; -import cloud.commandframework.CommandManager; -import cloud.commandframework.arguments.standard.StringArgument; -import cloud.commandframework.context.CommandContext; import com.google.inject.Inject; import lombok.Getter; import lombok.NoArgsConstructor; @@ -46,9 +42,13 @@ import org.geysermc.floodgate.platform.command.TranslatableMessage; import org.geysermc.floodgate.player.UserAudience; import org.geysermc.floodgate.player.UserAudience.PlayerAudience; +import org.geysermc.floodgate.player.audience.PlayerAudienceArgument; import org.geysermc.floodgate.player.audience.ProfileAudience; -import org.geysermc.floodgate.player.audience.ProfileAudienceArgument; import org.geysermc.floodgate.util.Constants; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.description.Description; @NoArgsConstructor public final class LinkAccountCommand implements FloodgateCommand { @@ -56,20 +56,19 @@ public final class LinkAccountCommand implements FloodgateCommand { @Inject private FloodgateLogger logger; @Override - public Command buildCommand(CommandManager commandManager) { + public Command buildCommand(CommandManager commandManager) { return commandManager.commandBuilder("linkaccount", - ArgumentDescription.of("Link your Java account with your Bedrock account")) + Description.of("Link your Java account with your Bedrock account")) .senderType(PlayerAudience.class) .permission(Permission.COMMAND_LINK.get()) - .argument(ProfileAudienceArgument.of("player", true)) - .argument(StringArgument.optional("code")) + .argument(PlayerAudienceArgument.ofAnyUsernameBoth("player")) + .optional("code", stringParser()) .handler(this::execute) .build(); } - @Override - public void execute(CommandContext context) { - UserAudience sender = context.getSender(); + public void execute(CommandContext context) { + UserAudience sender = context.sender(); PlayerLink link = api.getPlayerLink(); diff --git a/core/src/main/java/org/geysermc/floodgate/command/TestCommand.java b/core/src/main/java/org/geysermc/floodgate/command/TestCommand.java index f950da04..10213c78 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/TestCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/TestCommand.java @@ -25,14 +25,14 @@ package org.geysermc.floodgate.command; -import cloud.commandframework.Command; -import cloud.commandframework.CommandManager; -import cloud.commandframework.context.CommandContext; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.platform.command.FloodgateCommand; import org.geysermc.floodgate.player.UserAudience; import org.geysermc.floodgate.util.Constants; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; public class TestCommand implements FloodgateCommand { @Override @@ -43,10 +43,9 @@ public Command buildCommand(CommandManager commandMa .build(); } - @Override public void execute(CommandContext context) { int players = FloodgateApi.getInstance().getPlayers().size(); - context.getSender().sendMessage(String.valueOf(players)); + context.sender().sendMessage(String.valueOf(players)); } @Override diff --git a/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java b/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java index 1c5b0444..3ba4682b 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java @@ -27,10 +27,6 @@ import static org.geysermc.floodgate.command.CommonCommandMessage.CHECK_CONSOLE; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.Command; -import cloud.commandframework.CommandManager; -import cloud.commandframework.context.CommandContext; import com.google.inject.Inject; import lombok.Getter; import lombok.NoArgsConstructor; @@ -44,24 +40,27 @@ import org.geysermc.floodgate.player.UserAudience.PlayerAudience; import org.geysermc.floodgate.util.Constants; import org.geysermc.floodgate.command.util.Permission; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.description.Description; @NoArgsConstructor public final class UnlinkAccountCommand implements FloodgateCommand { @Inject private FloodgateApi api; @Override - public Command buildCommand(CommandManager commandManager) { + public Command buildCommand(CommandManager commandManager) { return commandManager.commandBuilder("unlinkaccount", - ArgumentDescription.of("Unlink your Java account from your Bedrock account")) + Description.of("Unlink your Java account from your Bedrock account")) .senderType(PlayerAudience.class) .permission(Permission.COMMAND_UNLINK.get()) .handler(this::execute) .build(); } - @Override - public void execute(CommandContext context) { - UserAudience sender = context.getSender(); + public void execute(CommandContext context) { + UserAudience sender = context.sender(); PlayerLink link = api.getPlayerLink(); diff --git a/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java b/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java index b87a20ee..54c5efcb 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java @@ -27,10 +27,6 @@ import static org.geysermc.floodgate.command.CommonCommandMessage.CHECK_CONSOLE; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.Command; -import cloud.commandframework.CommandManager; -import cloud.commandframework.context.CommandContext; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.inject.Inject; @@ -46,10 +42,14 @@ import org.geysermc.floodgate.platform.command.TranslatableMessage; import org.geysermc.floodgate.platform.util.PlayerType; import org.geysermc.floodgate.player.UserAudience; +import org.geysermc.floodgate.player.audience.PlayerAudienceArgument; import org.geysermc.floodgate.player.audience.ProfileAudience; -import org.geysermc.floodgate.player.audience.ProfileAudienceArgument; import org.geysermc.floodgate.util.Constants; import org.geysermc.floodgate.util.HttpClient; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.description.Description; public class WhitelistCommand implements FloodgateCommand { @Inject private FloodgateConfig config; @@ -59,23 +59,23 @@ public class WhitelistCommand implements FloodgateCommand { @Override public Command buildCommand(CommandManager commandManager) { Command.Builder builder = commandManager.commandBuilder("fwhitelist", - ArgumentDescription.of("Easy way to whitelist Bedrock players")) + Description.of("Easy way to whitelist Bedrock players")) .permission(Permission.COMMAND_WHITELIST.get()); commandManager.command(builder .literal("add", "a") - .argument(ProfileAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK)) + .argument(PlayerAudienceArgument.ofAnyIdentifierBedrock("player")) .handler(context -> performCommand(context, true))); return builder .literal("remove", "r") - .argument(ProfileAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK)) + .argument(PlayerAudienceArgument.ofAnyIdentifierBedrock("player")) .handler(context -> performCommand(context, false)) .build(); } public void performCommand(CommandContext context, boolean add) { - UserAudience sender = context.getSender(); + UserAudience sender = context.sender(); ProfileAudience profile = context.get("player"); UUID uuid = profile.uuid(); String name = profile.username(); @@ -114,7 +114,7 @@ public void performCommand(CommandContext context, boolean add) { name = name.substring(config.getUsernamePrefix().length()); } - if (name.length() < 1 || name.length() > 16) { + if (name.isEmpty() || name.length() > 16) { sender.sendMessage(Message.INVALID_USERNAME); return; } @@ -181,11 +181,6 @@ public void performCommand(CommandContext context, boolean add) { }); } - @Override - public void execute(CommandContext context) { - // ignored, all the logic is in the other method - } - @Override public boolean shouldRegister(FloodgateConfig config) { // currently only Spigot (our only non-Proxy platform) has a whitelist build-in. diff --git a/core/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java b/core/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java index 6fa989f5..be64d92a 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java @@ -27,7 +27,6 @@ import static org.geysermc.floodgate.util.Constants.COLOR_CHAR; -import cloud.commandframework.context.CommandContext; import com.google.gson.JsonElement; import com.google.inject.Inject; import it.unimi.dsi.fastutil.Pair; @@ -41,6 +40,7 @@ import org.geysermc.floodgate.util.HttpClient; import org.geysermc.floodgate.util.HttpClient.HttpResponse; import org.geysermc.floodgate.util.Utils; +import org.incendo.cloud.context.CommandContext; final class FirewallCheckSubcommand extends FloodgateSubCommand { @Inject @@ -63,7 +63,7 @@ public Permission permission() { @Override public void execute(CommandContext context) { - UserAudience sender = context.getSender(); + UserAudience sender = context.sender(); executeChecks( globalApiCheck(sender) ).whenComplete((response, $) -> diff --git a/core/src/main/java/org/geysermc/floodgate/command/main/MainCommand.java b/core/src/main/java/org/geysermc/floodgate/command/main/MainCommand.java index 446e8106..801676e4 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/main/MainCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/main/MainCommand.java @@ -27,17 +27,17 @@ import static org.geysermc.floodgate.util.Constants.COLOR_CHAR; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.Command; -import cloud.commandframework.Command.Builder; -import cloud.commandframework.CommandManager; -import cloud.commandframework.context.CommandContext; import java.util.Locale; import org.geysermc.floodgate.command.util.Permission; import org.geysermc.floodgate.platform.command.FloodgateCommand; import org.geysermc.floodgate.platform.command.FloodgateSubCommand; import org.geysermc.floodgate.platform.command.SubCommands; import org.geysermc.floodgate.player.UserAudience; +import org.incendo.cloud.Command; +import org.incendo.cloud.Command.Builder; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.description.Description; public final class MainCommand extends SubCommands implements FloodgateCommand { public MainCommand() { @@ -49,14 +49,14 @@ public MainCommand() { public Command buildCommand(CommandManager commandManager) { Builder builder = commandManager.commandBuilder( "floodgate", - ArgumentDescription.of("A set of Floodgate related actions in one command")) + Description.of("A set of Floodgate related actions in one command")) .senderType(UserAudience.class) .permission(Permission.COMMAND_MAIN.get()) .handler(this::execute); for (FloodgateSubCommand subCommand : subCommands()) { commandManager.command(builder - .literal(subCommand.name().toLowerCase(Locale.ROOT), subCommand.description()) + .literal(subCommand.name().toLowerCase(Locale.ROOT), Description.of(subCommand.description())) .permission(subCommand.permission().get()) .handler(subCommand::execute) ); @@ -66,12 +66,11 @@ public Command buildCommand(CommandManager commandMa return builder.build(); } - @Override public void execute(CommandContext context) { StringBuilder helpMessage = new StringBuilder("Available subcommands are:\n"); for (FloodgateSubCommand subCommand : subCommands()) { - if (context.getSender().hasPermission(subCommand.permission().get())) { + if (context.sender().hasPermission(subCommand.permission().get())) { helpMessage.append('\n').append(COLOR_CHAR).append('b') .append(subCommand.name().toLowerCase(Locale.ROOT)) .append(COLOR_CHAR).append("f - ").append(COLOR_CHAR).append('7') @@ -79,6 +78,6 @@ public void execute(CommandContext context) { } } - context.getSender().sendMessage(helpMessage.toString()); + context.sender().sendMessage(helpMessage.toString()); } } diff --git a/core/src/main/java/org/geysermc/floodgate/command/main/VersionSubcommand.java b/core/src/main/java/org/geysermc/floodgate/command/main/VersionSubcommand.java index 985c47c1..961c1735 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/main/VersionSubcommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/main/VersionSubcommand.java @@ -27,7 +27,6 @@ import static org.geysermc.floodgate.util.Constants.COLOR_CHAR; -import cloud.commandframework.context.CommandContext; import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.name.Named; @@ -38,6 +37,7 @@ import org.geysermc.floodgate.player.UserAudience; import org.geysermc.floodgate.util.Constants; import org.geysermc.floodgate.util.HttpClient; +import org.incendo.cloud.context.CommandContext; public class VersionSubcommand extends FloodgateSubCommand { @Inject @@ -67,7 +67,7 @@ public Permission permission() { @Override public void execute(CommandContext context) { - UserAudience sender = context.getSender(); + UserAudience sender = context.sender(); sender.sendMessage(String.format( COLOR_CHAR + "7You're currently on " + COLOR_CHAR + "b%s" + COLOR_CHAR + "7 (branch: " + COLOR_CHAR + "b%s" + COLOR_CHAR + "7)\n" + diff --git a/core/src/main/java/org/geysermc/floodgate/platform/command/CommandUtil.java b/core/src/main/java/org/geysermc/floodgate/platform/command/CommandUtil.java index d159a29e..17bf555b 100644 --- a/core/src/main/java/org/geysermc/floodgate/platform/command/CommandUtil.java +++ b/core/src/main/java/org/geysermc/floodgate/platform/command/CommandUtil.java @@ -112,11 +112,6 @@ public abstract class CommandUtil { return usernames; } - /** - * - * @param uuid - * @return - */ public abstract Object getPlayerByUuid(@NonNull UUID uuid); public Object getPlayerByUuid(@NonNull UUID uuid, PlayerType limitTo) { @@ -125,15 +120,15 @@ public Object getPlayerByUuid(@NonNull UUID uuid, PlayerType limitTo) { public abstract Object getPlayerByUsername(@NonNull String username); - public Object getPlayerByUsername(@NonNull String username, PlayerType limitTo) { - return applyPlayerTypeFilter(getPlayerByUsername(username), limitTo, username); + public Object getPlayerByUsername(@NonNull String username, PlayerType filter) { + return applyPlayerTypeFilter(getPlayerByUsername(username), filter, username); } protected Object applyPlayerTypeFilter(Object player, PlayerType filter, Object fallback) { if (filter == ALL_PLAYERS || player instanceof String || player instanceof UUID) { return player; } - return (filter == ONLY_BEDROCK) == api.isFloodgatePlayer(getUuidFromSource(player)) + return (filter == ONLY_BEDROCK) == api.isFloodgateId(getUuidFromSource(player)) ? player : fallback; } diff --git a/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateCommand.java b/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateCommand.java index f61c336e..80a115da 100644 --- a/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateCommand.java @@ -25,11 +25,10 @@ package org.geysermc.floodgate.platform.command; -import cloud.commandframework.Command; -import cloud.commandframework.CommandManager; -import cloud.commandframework.context.CommandContext; import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.player.UserAudience; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; /** The base class for every Floodgate command. */ public interface FloodgateCommand { @@ -39,14 +38,7 @@ public interface FloodgateCommand { * @param commandManager the manager to create a command * @return the command to register */ - Command buildCommand(CommandManager commandManager); - - /** - * Called when the command created in {@link #buildCommand(CommandManager)} is executed. - * - * @param context the context of the executed command - */ - void execute(CommandContext context); + Command buildCommand(CommandManager commandManager); /** * Called by the CommandRegister to check if the command should be added given the config. diff --git a/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateSubCommand.java b/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateSubCommand.java index 25515ddc..fcf4b905 100644 --- a/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateSubCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/platform/command/FloodgateSubCommand.java @@ -25,9 +25,9 @@ package org.geysermc.floodgate.platform.command; -import cloud.commandframework.context.CommandContext; import org.geysermc.floodgate.command.util.Permission; import org.geysermc.floodgate.player.UserAudience; +import org.incendo.cloud.context.CommandContext; public abstract class FloodgateSubCommand { public abstract String name(); diff --git a/core/src/main/java/org/geysermc/floodgate/player/FloodgateCommandPreprocessor.java b/core/src/main/java/org/geysermc/floodgate/player/FloodgateCommandPreprocessor.java index 104516de..54e68079 100644 --- a/core/src/main/java/org/geysermc/floodgate/player/FloodgateCommandPreprocessor.java +++ b/core/src/main/java/org/geysermc/floodgate/player/FloodgateCommandPreprocessor.java @@ -25,14 +25,14 @@ package org.geysermc.floodgate.player; -import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext; -import cloud.commandframework.execution.preprocessor.CommandPreprocessor; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.floodgate.platform.command.CommandUtil; +import org.incendo.cloud.execution.preprocessor.CommandPreprocessingContext; +import org.incendo.cloud.execution.preprocessor.CommandPreprocessor; /** - * Command preprocessor which decorated incoming {@link cloud.commandframework.context.CommandContext} + * Command preprocessor which decorated incoming {@link org.incendo.cloud.context.CommandContext} * with Floodgate specific objects * * @param Command sender type @@ -44,6 +44,6 @@ public final class FloodgateCommandPreprocessor implements CommandPreprocesso @Override public void accept(@NonNull CommandPreprocessingContext context) { - context.getCommandContext().store("CommandUtil", commandUtil); + context.commandContext().store("CommandUtil", commandUtil); } } diff --git a/core/src/main/java/org/geysermc/floodgate/player/audience/FloodgateSenderMapper.java b/core/src/main/java/org/geysermc/floodgate/player/audience/FloodgateSenderMapper.java new file mode 100644 index 00000000..632ae5aa --- /dev/null +++ b/core/src/main/java/org/geysermc/floodgate/player/audience/FloodgateSenderMapper.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.player.audience; + + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.floodgate.platform.command.CommandUtil; +import org.geysermc.floodgate.player.UserAudience; +import org.incendo.cloud.SenderMapper; + +public class FloodgateSenderMapper implements SenderMapper { + + private final CommandUtil commandUtil; + + public FloodgateSenderMapper(CommandUtil commandUtil) { + this.commandUtil = commandUtil; + } + + @Override + public @NonNull UserAudience map(@NonNull T base) { + return this.commandUtil.getUserAudience(base); + } + + @SuppressWarnings("unchecked") + @Override + public @NonNull T reverse(@NonNull UserAudience mapped) { + return (T) mapped.source(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/floodgate/player/audience/InvalidPlayerIdentifierException.java b/core/src/main/java/org/geysermc/floodgate/player/audience/InvalidPlayerIdentifierException.java new file mode 100644 index 00000000..d6692680 --- /dev/null +++ b/core/src/main/java/org/geysermc/floodgate/player/audience/InvalidPlayerIdentifierException.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.player.audience; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class InvalidPlayerIdentifierException extends IllegalArgumentException { + + public InvalidPlayerIdentifierException(@NonNull String message) { + super(message); + } + + @Override + public @NonNull Throwable fillInStackTrace() { + return this; + } +} diff --git a/core/src/main/java/org/geysermc/floodgate/player/audience/PlayerAudienceArgument.java b/core/src/main/java/org/geysermc/floodgate/player/audience/PlayerAudienceArgument.java new file mode 100644 index 00000000..3829db3a --- /dev/null +++ b/core/src/main/java/org/geysermc/floodgate/player/audience/PlayerAudienceArgument.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.player.audience; + +import static org.incendo.cloud.parser.standard.StringParser.quotedStringParser; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import org.geysermc.floodgate.platform.command.CommandUtil; +import org.geysermc.floodgate.platform.util.PlayerType; +import org.geysermc.floodgate.player.UserAudience; +import org.geysermc.floodgate.util.BrigadierUtils; +import org.incendo.cloud.component.CommandComponent; +import org.incendo.cloud.parser.ArgumentParseResult; +import org.incendo.cloud.suggestion.Suggestion; + +public class PlayerAudienceArgument { + + public static CommandComponent.Builder ofAnyIdentifierBedrock(String name) { + return of(name, true, true, PlayerType.ONLY_BEDROCK); + } + + public static CommandComponent.Builder ofAnyUsernameBoth(String name) { + return of(name, false, true, PlayerType.ALL_PLAYERS); + } + + private static CommandComponent.Builder of(String name, boolean allowUuid, boolean allowOffline, PlayerType limitTo) { + return CommandComponent.builder() + .name(name) + .parser(quotedStringParser().flatMapSuccess(ProfileAudience.class, + (context, input) -> { + CommandUtil commandUtil = context.get("CommandUtil"); + + ProfileAudience profileAudience; + if (input.length() > 16) { + // This must be a UUID. + if (!allowUuid) { + return ArgumentParseResult.failureFuture( + new InvalidPlayerIdentifierException( + "UUID is not allowed here")); + } + + if (input.length() != 32 && input.length() != 36) { + // Neither UUID without dashes nor with dashes. + return ArgumentParseResult.failureFuture( + new InvalidPlayerIdentifierException( + "Expected player name/UUID")); + } + + try { + // We only want to make sure the UUID is valid here. + Object player = commandUtil.getPlayerByUuid( + UUID.fromString(input), limitTo); + profileAudience = commandUtil.getProfileAudience(player, + allowOffline); + } catch (final IllegalArgumentException ignored) { + return ArgumentParseResult.failureFuture( + new InvalidPlayerIdentifierException( + "Invalid UUID '" + input + "'")); + } + } else { + // This is a username. + Object player = commandUtil.getPlayerByUsername(input, limitTo); + profileAudience = commandUtil.getProfileAudience(player, + allowOffline); + } + + if (profileAudience == null) { + return ArgumentParseResult.failureFuture( + new InvalidPlayerIdentifierException( + "Invalid player '" + input + "'")); + } + + return ArgumentParseResult.successFuture(profileAudience); + })) + .suggestionProvider((context, input) -> { + CommandUtil commandUtil = context.get("CommandUtil"); + + boolean quoted = input.remainingInput().startsWith("\""); + List suggestions = new ArrayList(); + for (final String player : commandUtil.getOnlineUsernames(limitTo)) { + suggestions.add( + Suggestion.simple(BrigadierUtils.escapeIfRequired(player, quoted))); + } + return CompletableFuture.completedFuture(suggestions); + }); + } +} diff --git a/core/src/main/java/org/geysermc/floodgate/player/audience/ProfileAudienceArgument.java b/core/src/main/java/org/geysermc/floodgate/player/audience/ProfileAudienceArgument.java deleted file mode 100644 index 9c425637..00000000 --- a/core/src/main/java/org/geysermc/floodgate/player/audience/ProfileAudienceArgument.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Floodgate - */ - -package org.geysermc.floodgate.player.audience; - -import cloud.commandframework.arguments.CommandArgument; -import cloud.commandframework.arguments.parser.ArgumentParseResult; -import cloud.commandframework.arguments.parser.ArgumentParser; -import cloud.commandframework.context.CommandContext; -import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.Locale; -import java.util.Queue; -import java.util.UUID; -import lombok.RequiredArgsConstructor; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.floodgate.platform.command.CommandUtil; -import org.geysermc.floodgate.platform.util.PlayerType; -import org.geysermc.floodgate.player.UserAudience; - -public class ProfileAudienceArgument extends CommandArgument { - private ProfileAudienceArgument(@NonNull String name, ProfileAudienceParser parser) { - super(true, name, parser, ProfileAudience.class); - } - - public static ProfileAudienceArgument of( - String name, - boolean allowUuid, - boolean allowOffline, - PlayerType limitTo) { - return new ProfileAudienceArgument(name, - new ProfileAudienceParser(allowUuid, allowOffline, limitTo)); - } - - public static ProfileAudienceArgument of( - String name, - boolean allowOffline, - PlayerType limitTo) { - return of(name, false, allowOffline, limitTo); - } - - public static ProfileAudienceArgument ofOnline(String name, PlayerType limitTo) { - return of(name, false, false, limitTo); - } - - public static ProfileAudienceArgument ofOnline(String name, boolean allowUuid) { - return of(name, allowUuid, false, PlayerType.ALL_PLAYERS); - } - - public static CommandArgument ofOnline(String name) { - return of(name, false, false, PlayerType.ALL_PLAYERS); - } - - public static ProfileAudienceArgument of(String name, boolean allowOffline) { - return of(name, false, allowOffline, PlayerType.ALL_PLAYERS); - } - - @RequiredArgsConstructor - public static final class ProfileAudienceParser - implements ArgumentParser { - - private final boolean allowUuid; - private final boolean allowOffline; - private final PlayerType limitTo; - - @Override - public @NonNull ArgumentParseResult parse( - @NonNull CommandContext<@NonNull UserAudience> commandContext, - @NonNull Queue<@NonNull String> inputQueue) { - CommandUtil commandUtil = commandContext.get("CommandUtil"); - - String input = inputQueue.poll(); - if (input == null || input.length() < 3) { - return ArgumentParseResult.failure( - new NullPointerException("Expected player name/UUID")); - } - - if (input.startsWith("\"")) { - if (input.endsWith("\"")) { - // Remove quotes from both sides of this string - input = input.substring(1); - input = input.substring(0, input.length() - 1); - } else { - // Multi-line - StringBuilder builder = new StringBuilder(input); - while (!inputQueue.isEmpty()) { - String string = inputQueue.remove(); - builder.append(' ').append(string); - if (string.endsWith("\"")) { - break; - } - } - - if (builder.lastIndexOf("\"") != builder.length() - 1) { - return ArgumentParseResult.failure( - new InvalidPlayerIdentifierException("Malformed string provided; " + - "no end quotes found!")); - } - - builder.deleteCharAt(0); - builder.deleteCharAt(builder.length() - 1); - input = builder.toString(); - } - } - - ProfileAudience profileAudience; - - if (input.length() > 16) { - // This must be a UUID. - if (!allowUuid) { - return ArgumentParseResult.failure( - new InvalidPlayerIdentifierException("UUID is not allowed here")); - } - - if (input.length() != 32 && input.length() != 36) { - // Neither UUID without dashes nor with dashes. - return ArgumentParseResult.failure( - new InvalidPlayerIdentifierException("Expected player name/UUID")); - } - - try { - // We only want to make sure the UUID is valid here. - Object player = commandUtil.getPlayerByUuid(UUID.fromString(input), limitTo); - profileAudience = commandUtil.getProfileAudience(player, allowOffline); - } catch (final IllegalArgumentException ignored) { - return ArgumentParseResult.failure( - new InvalidPlayerIdentifierException("Invalid UUID '" + input + "'")); - } - } else { - // This is a username. - Object player = commandUtil.getPlayerByUsername(input, limitTo); - profileAudience = commandUtil.getProfileAudience(player, allowOffline); - } - - if (profileAudience == null) { - return ArgumentParseResult.failure( - new InvalidPlayerIdentifierException("Invalid player '" + input + "'")); - } - - return ArgumentParseResult.success(profileAudience); - } - - @Override - public @NonNull List suggestions( - @NonNull CommandContext commandContext, - @NonNull String input) { - CommandUtil commandUtil = commandContext.get("CommandUtil"); - String trimmedInput = input.trim(); - - if (trimmedInput.isEmpty()) { - return ImmutableList.copyOf(commandUtil.getOnlineUsernames(limitTo)); - } - - String lowercaseInput = input.toLowerCase(Locale.ROOT); - ImmutableList.Builder builder = ImmutableList.builder(); - - for (final String player : commandUtil.getOnlineUsernames(limitTo)) { - if (player.toLowerCase(Locale.ROOT).startsWith(lowercaseInput)) { - builder.add(player); - } - } - - return builder.build(); - } - - @Override - public boolean isContextFree() { - return true; - } - } - - public static final class InvalidPlayerIdentifierException extends IllegalArgumentException { - private static final long serialVersionUID = -6500019324607183855L; - - public InvalidPlayerIdentifierException(@NonNull String message) { - super(message); - } - - @Override - public @NonNull Throwable fillInStackTrace() { - return this; - } - } -} diff --git a/core/src/main/java/org/geysermc/floodgate/register/CommandRegister.java b/core/src/main/java/org/geysermc/floodgate/register/CommandRegister.java index 2eed7d26..11ebd0fe 100644 --- a/core/src/main/java/org/geysermc/floodgate/register/CommandRegister.java +++ b/core/src/main/java/org/geysermc/floodgate/register/CommandRegister.java @@ -25,7 +25,6 @@ package org.geysermc.floodgate.register; -import cloud.commandframework.CommandManager; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; @@ -33,6 +32,7 @@ import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.platform.command.FloodgateCommand; import org.geysermc.floodgate.player.UserAudience; +import org.incendo.cloud.CommandManager; /** * This class is responsible for registering commands to the command register of the platform that diff --git a/core/src/main/java/org/geysermc/floodgate/util/BrigadierUtils.java b/core/src/main/java/org/geysermc/floodgate/util/BrigadierUtils.java new file mode 100644 index 00000000..50c1eb5d --- /dev/null +++ b/core/src/main/java/org/geysermc/floodgate/util/BrigadierUtils.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.util; + +/* +Code taken from Brigadier's StringArgumentType and StringReader + */ +public final class BrigadierUtils { + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public static boolean isAllowedInUnquotedString(char c) { + return c >= '0' && c <= '9' || + c >= 'A' && c <= 'Z' || + c >= 'a' && c <= 'z' || + c == '_' || c == '-' || + c == '.' || c == '+'; + } + + public static String escapeIfRequired(String input, boolean quoted) { + if (quoted) { + return escape(input); + } + + for (final char c : input.toCharArray()) { + if (!isAllowedInUnquotedString(c)) { + return "\"" + input + "\""; + } + } + return input; + } + + private static String escape(final String input) { + final StringBuilder result = new StringBuilder("\""); + + for (int i = 0; i < input.length(); i++) { + final char c = input.charAt(i); + if (c == '\\' || c == '"') { + result.append('\\'); + } + result.append(c); + } + + result.append("\""); + return result.toString(); + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index af961a84..8e836211 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.configureondemand=true org.gradle.caching=true org.gradle.parallel=true -version=2.2.2-SNAPSHOT \ No newline at end of file +version=2.2.3-SNAPSHOT \ No newline at end of file diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index c0dad7af..193fc27e 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -13,7 +13,9 @@ indra { dependencies { api(projects.core) - implementation("cloud.commandframework", "cloud-bukkit", Versions.cloudVersion) + // TODO move to release once cloud-paper releases for 1.20.5 + // https://repo.papermc.io/#browse/browse:maven-public:org%2Fincendo%2Fcloud-paper%2F2.0.0-SNAPSHOT%2F2.0.0-20240427.220226-58 + implementation("org.incendo", "cloud-paper", "2.0.0-20240427.220226-58") // hack to make pre 1.12 work implementation("com.google.guava", "guava", guavaVersion) @@ -26,7 +28,7 @@ dependencies { relocate("com.google.inject") relocate("net.kyori") -relocate("cloud.commandframework") +relocate("org.incendo.cloud") relocate("io.leangen.geantyref") // used in cloud // hack to make pre 1.12 work relocate("com.google.common") diff --git a/spigot/src/main/java/org/geysermc/floodgate/module/SpigotCommandModule.java b/spigot/src/main/java/org/geysermc/floodgate/module/SpigotCommandModule.java index 4db0c9f6..959c4ac0 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/module/SpigotCommandModule.java +++ b/spigot/src/main/java/org/geysermc/floodgate/module/SpigotCommandModule.java @@ -25,15 +25,11 @@ package org.geysermc.floodgate.module; -import cloud.commandframework.CommandManager; -import cloud.commandframework.bukkit.BukkitCommandManager; -import cloud.commandframework.execution.CommandExecutionCoordinator; import com.google.inject.Provides; import com.google.inject.Singleton; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; import org.geysermc.floodgate.SpigotPlugin; @@ -41,6 +37,10 @@ import org.geysermc.floodgate.platform.command.CommandUtil; import org.geysermc.floodgate.player.FloodgateCommandPreprocessor; import org.geysermc.floodgate.player.UserAudience; +import org.geysermc.floodgate.player.audience.FloodgateSenderMapper; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.paper.PaperCommandManager; @RequiredArgsConstructor public final class SpigotCommandModule extends CommandModule { @@ -56,11 +56,10 @@ protected void configure() { @Singleton @SneakyThrows public CommandManager commandManager(CommandUtil commandUtil) { - CommandManager commandManager = new BukkitCommandManager<>( + CommandManager commandManager = new PaperCommandManager<>( plugin, - CommandExecutionCoordinator.simpleCoordinator(), - commandUtil::getUserAudience, - audience -> (CommandSender) audience.source() + ExecutionCoordinator.simpleCoordinator(), + new FloodgateSenderMapper<>(commandUtil) ); commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil)); return commandManager; diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 934ca10c..dd2d8b5b 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -12,10 +12,10 @@ indra { dependencies { api(projects.core) - implementation("cloud.commandframework", "cloud-velocity", Versions.cloudVersion) + implementation("org.incendo", "cloud-velocity", Versions.cloudVersion) } -relocate("cloud.commandframework") +relocate("org.incendo.cloud") // used in cloud relocate("io.leangen.geantyref") diff --git a/velocity/src/main/java/org/geysermc/floodgate/module/VelocityPlatformModule.java b/velocity/src/main/java/org/geysermc/floodgate/module/VelocityPlatformModule.java index fb412b47..91ced577 100644 --- a/velocity/src/main/java/org/geysermc/floodgate/module/VelocityPlatformModule.java +++ b/velocity/src/main/java/org/geysermc/floodgate/module/VelocityPlatformModule.java @@ -25,17 +25,12 @@ package org.geysermc.floodgate.module; -import cloud.commandframework.CommandManager; -import cloud.commandframework.execution.CommandExecutionCoordinator; -import cloud.commandframework.velocity.CloudInjectionModule; -import cloud.commandframework.velocity.VelocityCommandManager; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.name.Named; -import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.event.EventManager; import com.velocitypowered.api.proxy.ProxyServer; import lombok.RequiredArgsConstructor; @@ -51,6 +46,7 @@ import org.geysermc.floodgate.platform.util.PlatformUtils; import org.geysermc.floodgate.player.FloodgateCommandPreprocessor; import org.geysermc.floodgate.player.UserAudience; +import org.geysermc.floodgate.player.audience.FloodgateSenderMapper; import org.geysermc.floodgate.pluginmessage.PluginMessageManager; import org.geysermc.floodgate.pluginmessage.PluginMessageRegistration; import org.geysermc.floodgate.pluginmessage.VelocityPluginMessageRegistration; @@ -59,6 +55,10 @@ import org.geysermc.floodgate.util.VelocityCommandUtil; import org.geysermc.floodgate.util.VelocityPlatformUtils; import org.geysermc.floodgate.util.VelocitySkinApplier; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.velocity.CloudInjectionModule; +import org.incendo.cloud.velocity.VelocityCommandManager; @RequiredArgsConstructor public final class VelocityPlatformModule extends AbstractModule { @@ -77,9 +77,8 @@ protected void configure() { public CommandManager commandManager(CommandUtil commandUtil) { Injector child = guice.createChildInjector(new CloudInjectionModule<>( UserAudience.class, - CommandExecutionCoordinator.simpleCoordinator(), - commandUtil::getUserAudience, - audience -> (CommandSource) audience.source() + ExecutionCoordinator.simpleCoordinator(), + new FloodgateSenderMapper<>(commandUtil) )); CommandManager commandManager =