diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 3b15e61d..7d22cdc9 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -21,6 +21,7 @@ object Versions { const val adventurePlatform = "4.0.0-SNAPSHOT" const val paperApi = "1.15.2-R0.1-SNAPSHOT" const val velocityApi = "1.1.0" + const val spongeApi7 = "7.3.0" const val jetbrainsAnnotations = "20.1.0" const val guava = "21.0-jre" diff --git a/cloud-minecraft/cloud-sponge7/build.gradle.kts b/cloud-minecraft/cloud-sponge7/build.gradle.kts new file mode 100644 index 00000000..46f3a4c1 --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/build.gradle.kts @@ -0,0 +1,4 @@ +dependencies { + api(project(":cloud-core")) + compileOnly("org.spongepowered", "spongeapi", Versions.spongeApi7) +} diff --git a/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/CloudCommandCallable.java b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/CloudCommandCallable.java new file mode 100644 index 00000000..d6ca5139 --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/CloudCommandCallable.java @@ -0,0 +1,206 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// +package cloud.commandframework.sponge7; + +import cloud.commandframework.Command; +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.exceptions.ArgumentParseException; +import cloud.commandframework.exceptions.CommandExecutionException; +import cloud.commandframework.exceptions.InvalidCommandSenderException; +import cloud.commandframework.exceptions.InvalidSyntaxException; +import cloud.commandframework.exceptions.NoPermissionException; +import cloud.commandframework.exceptions.NoSuchCommandException; +import cloud.commandframework.meta.CommandMeta; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.command.CommandCallable; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.text.Text; +import org.spongepowered.api.text.format.TextColors; +import org.spongepowered.api.util.TextMessageException; +import org.spongepowered.api.world.Location; +import org.spongepowered.api.world.World; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletionException; + +final class CloudCommandCallable implements CommandCallable { + + private static final Text MESSAGE_INTERNAL_ERROR = Text.of(TextColors.RED, + "An internal error occurred while attempting to perform this command."); + private static final Text MESSAGE_NO_PERMS = Text.of(TextColors.RED, + "I'm sorry, but you do not have permission to perform this command. " + + "Please contact the server administrators if you believe that this is in error."); + private static final Text MESSAGE_UNKNOWN_COMMAND = Text.of("Unknown command. Type \"/help\" for help."); + + private final CommandArgument command; + private final Command cloudCommand; + private final SpongeCommandManager manager; + + CloudCommandCallable( + final CommandArgument command, + final Command cloudCommand, + final SpongeCommandManager manager + ) { + this.command = command; + this.cloudCommand = cloudCommand; + this.manager = manager; + } + + @Override + public CommandResult process(final @NonNull CommandSource source, final @NonNull String arguments) { + final C cloudSender = this.manager.getCommandSourceMapper().apply(source); + + this.manager.executeCommand(cloudSender, this.formatCommand(arguments)) + .whenComplete((result, throwable) -> { + if (throwable != null) { + if (throwable instanceof CompletionException) { + throwable = throwable.getCause(); + } + final Throwable finalThrowable = throwable; + if (throwable instanceof InvalidSyntaxException) { + this.manager.handleException(cloudSender, + InvalidSyntaxException.class, + (InvalidSyntaxException) throwable, (c, e) -> + source.sendMessage(Text.of(TextColors.RED, + "Invalid Command Syntax. Correct command syntax is: ", + Text.of(TextColors.GRAY, ((InvalidSyntaxException) finalThrowable).getCorrectSyntax()))) + ); + } else if (throwable instanceof InvalidCommandSenderException) { + this.manager.handleException(cloudSender, + InvalidCommandSenderException.class, + (InvalidCommandSenderException) throwable, (c, e) -> + source.sendMessage(Text.of(TextColors.RED, finalThrowable.getMessage())) + ); + } else if (throwable instanceof NoPermissionException) { + this.manager.handleException(cloudSender, + NoPermissionException.class, + (NoPermissionException) throwable, (c, e) -> + source.sendMessage(MESSAGE_NO_PERMS) + ); + } else if (throwable instanceof NoSuchCommandException) { + this.manager.handleException(cloudSender, + NoSuchCommandException.class, + (NoSuchCommandException) throwable, (c, e) -> + source.sendMessage(MESSAGE_UNKNOWN_COMMAND) + ); + } else if (throwable instanceof ArgumentParseException) { + this.manager.handleException(cloudSender, + ArgumentParseException.class, + (ArgumentParseException) throwable, (c, e) -> + source.sendMessage(Text.of("Invalid Command Argument: ", + this.formatMessage(finalThrowable.getCause()))) + ); + } else if (throwable instanceof CommandExecutionException) { + this.manager.handleException(cloudSender, + CommandExecutionException.class, + (CommandExecutionException) throwable, (c, e) -> { + source.sendMessage(MESSAGE_INTERNAL_ERROR); + this.manager.getOwningPlugin().getLogger().error( + "Exception executing command handler", + finalThrowable.getCause() + ); + } + ); + } else { + source.sendMessage(MESSAGE_INTERNAL_ERROR); + this.manager.getOwningPlugin().getLogger().error( + "An unhandled exception was thrown during command execution", + throwable + ); + } + } + }); + return CommandResult.success(); + } + + private Text formatMessage(final Throwable exc) { + if (exc instanceof TextMessageException) { + final Text response = ((TextMessageException) exc).getText(); + if (response == null) { + return Text.of(TextColors.GRAY, "null"); + } else if (response.getColor() == TextColors.NONE) { + return response.toBuilder().color(TextColors.GRAY).build(); + } else { + return response; + } + } else { + return Text.of(TextColors.GRAY, exc.getMessage()); + } + } + + @Override + public List getSuggestions( + final @NonNull CommandSource source, + final @NonNull String arguments, + final @Nullable Location targetPosition + ) { + return this.manager.suggest(this.manager.getCommandSourceMapper().apply(source), this.formatCommand(arguments)); + } + + private String formatCommand(final String arguments) { + if (arguments.isEmpty()) { + return this.command.getName(); + } else { + return this.command.getName() + " " + arguments; + } + } + + @Override + public boolean testPermission(final @NonNull CommandSource source) { + return this.manager.hasPermission(this.manager.getCommandSourceMapper().apply(source), this.cloudCommand.getCommandPermission()); + } + + @Override + public @NonNull Optional getShortDescription(final @NonNull CommandSource source) { + final Optional richDesc = this.cloudCommand.getCommandMeta().get(SpongeMetaKeys.RICH_DESCRIPTION); + if (richDesc.isPresent()) { + return richDesc; + } + + return this.cloudCommand.getCommandMeta().get(CommandMeta.DESCRIPTION).map(Text::of); + } + + @Override + public @NonNull Optional getHelp(final @NonNull CommandSource source) { + final Optional richLongDesc = this.cloudCommand.getCommandMeta().get(SpongeMetaKeys.RICH_LONG_DESCRIPTION); + if (richLongDesc.isPresent()) { + return richLongDesc; + } + + return this.cloudCommand.getCommandMeta().get(CommandMeta.LONG_DESCRIPTION).map(Text::of); + } + + @Override + public Text getUsage(final @NonNull CommandSource source) { + return Text.of(this.manager.getCommandSyntaxFormatter().apply( + Collections.emptyList(), + this.manager.getCommandTree().getNamedNode(this.command.getName()) + )); + } + +} diff --git a/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/CloudInjectionModule.java b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/CloudInjectionModule.java new file mode 100644 index 00000000..32c003e2 --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/CloudInjectionModule.java @@ -0,0 +1,95 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// +package cloud.commandframework.sponge7; + +import cloud.commandframework.CommandTree; +import cloud.commandframework.execution.CommandExecutionCoordinator; +import com.google.inject.AbstractModule; +import com.google.inject.Key; +import com.google.inject.util.Types; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.command.CommandSource; + +import java.lang.reflect.Type; +import java.util.function.Function; + +/** + * Injection module that allows for {@link SpongeCommandManager} to be injectable + * + * @param Command sender type + * @since 1.1.0 + */ +public final class CloudInjectionModule extends AbstractModule { + + private final Class commandSenderType; + private final Function<@NonNull CommandTree, @NonNull CommandExecutionCoordinator> commandExecutionCoordinator; + private final Function<@NonNull CommandSource, @NonNull C> commandSenderMapper; + private final Function<@NonNull C, @NonNull CommandSource> backwardsCommandSenderMapper; + + /** + * Create a new child injection module + * + * @param commandSenderType Your command sender type + * @param commandExecutionCoordinator Command execution coordinator + * @param commandSenderMapper Mapper from command source to the custom command sender type + * @param backwardsCommandSenderMapper Mapper from the custom command sender type to a velocity command source + */ + public CloudInjectionModule( + final @NonNull Class commandSenderType, + final @NonNull Function<@NonNull CommandTree, @NonNull CommandExecutionCoordinator> commandExecutionCoordinator, + final @NonNull Function<@NonNull CommandSource, @NonNull C> commandSenderMapper, + final @NonNull Function<@NonNull C, @NonNull CommandSource> backwardsCommandSenderMapper + ) { + this.commandSenderType = commandSenderType; + this.commandExecutionCoordinator = commandExecutionCoordinator; + this.commandSenderMapper = commandSenderMapper; + this.backwardsCommandSenderMapper = backwardsCommandSenderMapper; + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + protected void configure() { + final Type commandTreeType = Types.newParameterizedType(CommandTree.class, this.commandSenderType); + final Type commandExecutionCoordinatorType = Types.newParameterizedType( + CommandExecutionCoordinator.class, + this.commandSenderType + ); + final Type executorFunction = Types.newParameterizedType(Function.class, commandTreeType, + commandExecutionCoordinatorType + ); + final Key executorFunctionKey = Key.get(executorFunction); + this.bind(executorFunctionKey).toInstance(this.commandExecutionCoordinator); + final Type commandSenderMapperFunction = Types.newParameterizedType(Function.class, CommandSource.class, + this.commandSenderType + ); + final Key commandSenderMapperFunctionKey = Key.get(commandSenderMapperFunction); + this.bind(commandSenderMapperFunctionKey).toInstance(this.commandSenderMapper); + final Type backwardsCommandSenderMapperFunction = Types.newParameterizedType(Function.class, this.commandSenderType, + CommandSource.class + ); + final Key backwardsCommandSenderMapperFunctionKey = Key.get(backwardsCommandSenderMapperFunction); + this.bind(backwardsCommandSenderMapperFunctionKey).toInstance(this.backwardsCommandSenderMapper); + } + +} diff --git a/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongeCommandManager.java b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongeCommandManager.java new file mode 100644 index 00000000..4cc86ad4 --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongeCommandManager.java @@ -0,0 +1,117 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// +package cloud.commandframework.sponge7; + +import cloud.commandframework.CommandManager; +import cloud.commandframework.CommandTree; +import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; +import cloud.commandframework.execution.CommandExecutionCoordinator; +import cloud.commandframework.meta.CommandMeta; +import cloud.commandframework.meta.SimpleCommandMeta; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.plugin.PluginContainer; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.function.Function; + +import static java.util.Objects.requireNonNull; + +/** + * A command manager for SpongeAPI 7. + * + * @param the command source type + * @since 1.4.0 + */ +@Singleton +public class SpongeCommandManager extends CommandManager { + + private final PluginContainer owningPlugin; + private final Function forwardMapper; + private final Function reverseMapper; + + /** + * Create a new command manager instance. + * + * @param container The plugin that owns this command manager + * @param commandExecutionCoordinator Execution coordinator instance. The coordinator is in charge of executing incoming + * commands. Some considerations must be made when picking a suitable execution coordinator + * for your platform. For example, an entirely asynchronous coordinator is not suitable + * when the parsers used in that particular platform are not thread safe. If you have + * commands that perform blocking operations, however, it might not be a good idea to + * use a synchronous execution coordinator. In most cases you will want to pick between + * {@link CommandExecutionCoordinator#simpleCoordinator()} and + * {@link AsynchronousCommandExecutionCoordinator} + * @param forwardMapper A function converting from a native {@link CommandSource} to this manager's sender type + * @param reverseMapper A function converting from this manager's sender type to a native {@link CommandSource} + */ + @Inject + @SuppressWarnings("unchecked") + public SpongeCommandManager( + final @NonNull PluginContainer container, + final @NonNull Function, CommandExecutionCoordinator> commandExecutionCoordinator, + final Function forwardMapper, + final Function reverseMapper + ) { + super(commandExecutionCoordinator, new SpongePluginRegistrationHandler<>()); + this.owningPlugin = requireNonNull(container, "container"); + this.forwardMapper = requireNonNull(forwardMapper, "forwardMapper"); + this.reverseMapper = requireNonNull(reverseMapper, "reverseMapper"); + ((SpongePluginRegistrationHandler) this.getCommandRegistrationHandler()).initialize(this); + } + + @Override + public final boolean hasPermission(final @NonNull C sender, final @NonNull String permission) { + return this.reverseMapper.apply(sender).hasPermission(permission); + } + + @Override + public final @NonNull CommandMeta createDefaultCommandMeta() { + return SimpleCommandMeta.empty(); + } + + /** + * Get a mapper from a Sponge {@link CommandSource} to this manager's command source type. + * + * @return the command source mapper + */ + public @NonNull Function getCommandSourceMapper() { + return this.forwardMapper; + } + + /** + * Get a mapper from this manager's command source type back to Sponge's {@link CommandSource}. + * + * @return the command source mapper + */ + public final @NonNull Function getReverseCommandSourceMapper() { + return this.reverseMapper; + } + + final PluginContainer getOwningPlugin() { + return this.owningPlugin; + } + +} diff --git a/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongeMetaKeys.java b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongeMetaKeys.java new file mode 100644 index 00000000..e60303d3 --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongeMetaKeys.java @@ -0,0 +1,52 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// +package cloud.commandframework.sponge7; + +import cloud.commandframework.meta.CommandMeta; +import org.spongepowered.api.text.Text; + +/** + * Metadata keys used when registering commands targeting Sponge. + * + * @since 1.4.0 + */ +public final class SpongeMetaKeys { + + private SpongeMetaKeys() { + } + + /** + * A rich short description for commands. + */ + public static final CommandMeta.Key RICH_DESCRIPTION = CommandMeta.Key.of(Text.class, "cloud:sponge7/rich_description"); + + /** + * A rich long description for commands. + */ + public static final CommandMeta.Key RICH_LONG_DESCRIPTION = CommandMeta.Key.of( + Text.class, + "cloud:sponge7/rich_long_description" + ); + +} diff --git a/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongePluginRegistrationHandler.java b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongePluginRegistrationHandler.java new file mode 100644 index 00000000..dcbe27a8 --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/SpongePluginRegistrationHandler.java @@ -0,0 +1,68 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// +package cloud.commandframework.sponge7; + +import cloud.commandframework.Command; +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.StaticArgument; +import cloud.commandframework.internal.CommandRegistrationHandler; +import com.google.common.collect.ImmutableList; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.Sponge; + +import java.util.HashMap; +import java.util.Map; + +final class SpongePluginRegistrationHandler implements CommandRegistrationHandler { + + private @MonotonicNonNull SpongeCommandManager manager; + private final Map, CloudCommandCallable> registeredCommands = new HashMap<>(); + + void initialize(final SpongeCommandManager manager) { + this.manager = manager; + } + + @Override + @SuppressWarnings("unchecked") + public boolean registerCommand(final @NonNull Command command) { + final StaticArgument commandArgument = (StaticArgument) command.getArguments().get(0); + if (this.registeredCommands.containsKey(commandArgument)) { + return false; + } + + final CloudCommandCallable callable = new CloudCommandCallable<>( + commandArgument, + (Command) command, + this.manager); + this.registeredCommands.put(commandArgument, callable); + + return Sponge.getGame().getCommandManager().register( + this.manager.getOwningPlugin(), + callable, + ImmutableList.copyOf(commandArgument.getAliases()) + ).isPresent(); + } + +} diff --git a/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/package-info.java b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/package-info.java new file mode 100644 index 00000000..77de8a1b --- /dev/null +++ b/cloud-minecraft/cloud-sponge7/src/main/java/cloud/commandframework/sponge7/package-info.java @@ -0,0 +1,28 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// + +/** + * SpongeAPI version 7 platform support + */ +package cloud.commandframework.sponge7; diff --git a/settings.gradle.kts b/settings.gradle.kts index 16e61d4c..63bbc266 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ setupMinecraftModule("cloud-bukkit") setupMinecraftModule("cloud-paper") setupMinecraftModule("cloud-velocity") setupMinecraftModule("cloud-sponge") +setupMinecraftModule("cloud-sponge7") setupMinecraftModule("cloud-bungee") setupMinecraftModule("cloud-cloudburst") setupMinecraftModule("cloud-minecraft-extras")