diff --git a/cloud-minecraft/cloud-bukkit/build.gradle b/cloud-minecraft/cloud-bukkit/build.gradle index 75b66264..93cce3ec 100644 --- a/cloud-minecraft/cloud-bukkit/build.gradle +++ b/cloud-minecraft/cloud-bukkit/build.gradle @@ -1,6 +1,6 @@ dependencies { api project(':cloud-core') api project(':cloud-brigadier') - compileOnly 'org.bukkit:bukkit:1.8.8-R0.1-SNAPSHOT' + compileOnly 'org.bukkit:bukkit:1.13.2-R0.1-SNAPSHOT' compileOnly 'me.lucko:commodore:1.9' } diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandManager.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandManager.java index cd97b820..03ae082c 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandManager.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandManager.java @@ -25,10 +25,18 @@ package cloud.commandframework.bukkit; import cloud.commandframework.CommandManager; import cloud.commandframework.CommandTree; +import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector; +import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector; +import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector; +import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector; import cloud.commandframework.bukkit.parsers.MaterialArgument; import cloud.commandframework.bukkit.parsers.OfflinePlayerArgument; import cloud.commandframework.bukkit.parsers.PlayerArgument; import cloud.commandframework.bukkit.parsers.WorldArgument; +import cloud.commandframework.bukkit.parsers.selector.MultipleEntitySelectorArgument; +import cloud.commandframework.bukkit.parsers.selector.MultiplePlayerSelectorArgument; +import cloud.commandframework.bukkit.parsers.selector.SingleEntitySelectorArgument; +import cloud.commandframework.bukkit.parsers.selector.SinglePlayerSelectorArgument; import cloud.commandframework.execution.CommandExecutionCoordinator; import io.leangen.geantyref.TypeToken; import org.bukkit.Bukkit; @@ -87,16 +95,6 @@ public class BukkitCommandManager extends CommandManager { this.commandSenderMapper = commandSenderMapper; this.backwardsCommandSenderMapper = backwardsCommandSenderMapper; - /* Register Bukkit parsers */ - this.getParserRegistry().registerParserSupplier(TypeToken.get(World.class), params -> new WorldArgument.WorldParser<>()); - this.getParserRegistry().registerParserSupplier(TypeToken.get(Material.class), - params -> new MaterialArgument.MaterialParser<>()); - this.getParserRegistry() - .registerParserSupplier(TypeToken.get(Player.class), params -> new PlayerArgument.PlayerParser<>()); - this.getParserRegistry() - .registerParserSupplier(TypeToken.get(OfflinePlayer.class), - params -> new OfflinePlayerArgument.OfflinePlayerParser<>()); - /* Try to determine the Minecraft version */ int version = -1; try { @@ -119,6 +117,28 @@ public class BukkitCommandManager extends CommandManager { } catch (final Exception ignored) { } this.paper = paper; + + /* Register Bukkit Preprocessor */ + this.registerCommandPreProcessor(new BukkitCommandPreprocessor<>(this)); + + /* Register Bukkit Parsers */ + this.getParserRegistry().registerParserSupplier(TypeToken.get(World.class), params -> new WorldArgument.WorldParser<>()); + this.getParserRegistry().registerParserSupplier(TypeToken.get(Material.class), + params -> new MaterialArgument.MaterialParser<>()); + this.getParserRegistry() + .registerParserSupplier(TypeToken.get(Player.class), params -> new PlayerArgument.PlayerParser<>()); + this.getParserRegistry() + .registerParserSupplier(TypeToken.get(OfflinePlayer.class), + params -> new OfflinePlayerArgument.OfflinePlayerParser<>()); + /* Register Entity Selector Parsers */ + this.getParserRegistry().registerParserSupplier(TypeToken.get(SingleEntitySelector.class), parserParameters -> + new SingleEntitySelectorArgument.SingleEntitySelectorParser<>()); + this.getParserRegistry().registerParserSupplier(TypeToken.get(SinglePlayerSelector.class), parserParameters -> + new SinglePlayerSelectorArgument.SinglePlayerSelectorParser<>()); + this.getParserRegistry().registerParserSupplier(TypeToken.get(MultipleEntitySelector.class), parserParameters -> + new MultipleEntitySelectorArgument.MultipleEntitySelectorParser<>()); + this.getParserRegistry().registerParserSupplier(TypeToken.get(MultiplePlayerSelector.class), parserParameters -> + new MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<>()); } /** diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandPreprocessor.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandPreprocessor.java new file mode 100644 index 00000000..cf237beb --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/BukkitCommandPreprocessor.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.bukkit; + +import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext; +import cloud.commandframework.execution.preprocessor.CommandPreprocessor; +import org.checkerframework.checker.nullness.qual.NonNull; + +public class BukkitCommandPreprocessor implements CommandPreprocessor { + private final BukkitCommandManager mgr; + + /** + * The Bukkit Command Preprocessor for storing Bukkit-specific contexts in the command contexts + * + * @param mgr The BukkitCommandManager + */ + public BukkitCommandPreprocessor(final BukkitCommandManager mgr) { + this.mgr = mgr; + } + + /** + * Stores the sender mapped to {@link org.bukkit.command.CommandSender} in the context with the key "BukkitCommandSender", + * and a {@link java.util.Set} of {@link CloudBukkitCapabilities} with the key "CloudBukkitCapabilities" + */ + @Override + public void accept(@NonNull final CommandPreprocessingContext context) { + context.getCommandContext().store("BukkitCommandSender", mgr.getBackwardsCommandSenderMapper().apply( + context.getCommandContext().getSender())); + context.getCommandContext().store("CloudBukkitCapabilities", mgr.queryCapabilities()); + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/EntitySelector.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/EntitySelector.java new file mode 100644 index 00000000..d76ddf6c --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/EntitySelector.java @@ -0,0 +1,49 @@ +// +// 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.bukkit.arguments.selector; + +import org.bukkit.entity.Entity; + +import java.util.List; + +/** + * A class to represent the result of parsing a Minecraft Entity/Target Selector argument + */ +public abstract class EntitySelector { + private final List entities; + + /** + * @param entities The List of Bukkit {@link Entity}s to construct the {@link EntitySelector} from + */ + public EntitySelector(final List entities) { + this.entities = entities; + } + + /** + * @return The list of Entities resulting from parsing the entity selector + */ + public final List getEntities() { + return entities; + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/MultipleEntitySelector.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/MultipleEntitySelector.java new file mode 100644 index 00000000..bb4d1db6 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/MultipleEntitySelector.java @@ -0,0 +1,37 @@ +// +// 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.bukkit.arguments.selector; + +import org.bukkit.entity.Entity; + +import java.util.List; + +public class MultipleEntitySelector extends EntitySelector { + /** + * @param entities The List of Bukkit {@link Entity}s to construct the {@link EntitySelector} from + */ + public MultipleEntitySelector(final List entities) { + super(entities); + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/MultiplePlayerSelector.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/MultiplePlayerSelector.java new file mode 100644 index 00000000..d4f47cba --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/MultiplePlayerSelector.java @@ -0,0 +1,56 @@ +// +// 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.bukkit.arguments.selector; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class MultiplePlayerSelector extends MultipleEntitySelector { + private final List players = new ArrayList<>(); + + /** + * @param entities The List of Bukkit {@link Entity}s to construct the {@link EntitySelector} from + */ + public MultiplePlayerSelector(final List entities) { + super(entities); + entities.forEach(e -> { + if (e.getType() != EntityType.PLAYER) { + throw new IllegalArgumentException("Non-players selected in player selector."); + } else { + players.add((Player) e); + } + }); + } + + /** + * @return The list of Bukkit Players parsed from the selector + */ + public final List getPlayers() { + return players; + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/SingleEntitySelector.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/SingleEntitySelector.java new file mode 100644 index 00000000..d7bd395c --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/SingleEntitySelector.java @@ -0,0 +1,47 @@ +// +// 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.bukkit.arguments.selector; + +import org.bukkit.entity.Entity; + +import java.util.List; + +public final class SingleEntitySelector extends MultipleEntitySelector { + /** + * @param entities The List of Bukkit {@link Entity}s to construct the {@link EntitySelector} from + */ + public SingleEntitySelector(final List entities) { + super(entities); + if (entities.size() > 1) { + throw new IllegalArgumentException("More than 1 entity selected in single entity selector."); + } + } + + /** + * @return Gets the single Bukkit Entity parsed by the selector + */ + public Entity getEntity() { + return this.getEntities().get(0); + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/SinglePlayerSelector.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/SinglePlayerSelector.java new file mode 100644 index 00000000..9c010a1f --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/SinglePlayerSelector.java @@ -0,0 +1,48 @@ +// +// 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.bukkit.arguments.selector; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import java.util.List; + +public final class SinglePlayerSelector extends MultiplePlayerSelector { + /** + * @param entities The List of Bukkit {@link Entity}s to construct the {@link EntitySelector} from + */ + public SinglePlayerSelector(final List entities) { + super(entities); + if (getPlayers().size() > 1) { + throw new IllegalArgumentException("More than 1 player selected in single player selector."); + } + } + + /** + * @return Gets the single player parsed by the selector + */ + public Player getPlayer() { + return this.getPlayers().get(0); + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/package-info.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/package-info.java new file mode 100644 index 00000000..a3527516 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/arguments/selector/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. +// + +/** + * Entity Selector argument types + */ +package cloud.commandframework.bukkit.arguments.selector; diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/MultipleEntitySelectorArgument.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/MultipleEntitySelectorArgument.java new file mode 100644 index 00000000..532664a7 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/MultipleEntitySelectorArgument.java @@ -0,0 +1,145 @@ +// +// 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.bukkit.parsers.selector; + +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.parser.ArgumentParseResult; +import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.bukkit.CloudBukkitCapabilities; +import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector; +import cloud.commandframework.context.CommandContext; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.BiFunction; + +public final class MultipleEntitySelectorArgument extends CommandArgument { + private MultipleEntitySelectorArgument(final boolean required, + @NonNull final String name, + @NonNull final String defaultValue, + @Nullable final BiFunction<@NonNull CommandContext, @NonNull String, + @NonNull List<@NonNull String>> suggestionsProvider) { + super(required, name, new MultipleEntitySelectorParser<>(), defaultValue, MultipleEntitySelector.class, + suggestionsProvider); + } + + /** + * Create a new builder + * + * @param name Name of the argument + * @param Command sender type + * @return Created builder + */ + public static MultipleEntitySelectorArgument.Builder newBuilder(@NonNull final String name) { + return new MultipleEntitySelectorArgument.Builder<>(name); + } + + /** + * Create a new required command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument of(@NonNull final String name) { + return MultipleEntitySelectorArgument.newBuilder(name).asRequired().build(); + } + + /** + * Create a new optional command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name) { + return MultipleEntitySelectorArgument.newBuilder(name).asOptional().build(); + } + + /** + * Create a new required command argument with a default value + * + * @param name Argument name + * @param defaultEntitySelector Default player + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name, + @NonNull final String defaultEntitySelector) { + return MultipleEntitySelectorArgument.newBuilder(name).asOptionalWithDefault(defaultEntitySelector).build(); + } + + + public static final class Builder extends CommandArgument.Builder { + + protected Builder(@NonNull final String name) { + super(MultipleEntitySelector.class, name); + } + + /** + * Builder a new argument + * + * @return Constructed argument + */ + @Override + public @NonNull MultipleEntitySelectorArgument build() { + return new MultipleEntitySelectorArgument<>(this.isRequired(), this.getName(), this.getDefaultValue(), + this.getSuggestionsProvider()); + } + + } + + + public static final class MultipleEntitySelectorParser implements ArgumentParser { + + @Override + public @NonNull ArgumentParseResult parse(@NonNull final CommandContext commandContext, + @NonNull final Queue<@NonNull String> inputQueue) { + if (!((Set) commandContext.get("CloudBukkitCapabilities")).contains( + CloudBukkitCapabilities.BRIGADIER)) { + return ArgumentParseResult.failure( + new IllegalArgumentException("Entity selector argument type not supported below Minecraft 1.13.")); + } + final String input = inputQueue.peek(); + if (input == null) { + return ArgumentParseResult.failure(new NullPointerException("No input was provided")); + } + inputQueue.remove(); + + List entities; + try { + entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input); + } catch (IllegalArgumentException e) { + return ArgumentParseResult.failure(new SelectorParseException(input)); + } + + return ArgumentParseResult.success(new MultipleEntitySelector(entities)); + } + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/MultiplePlayerSelectorArgument.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/MultiplePlayerSelectorArgument.java new file mode 100644 index 00000000..c7847c94 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/MultiplePlayerSelectorArgument.java @@ -0,0 +1,172 @@ +// +// 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.bukkit.parsers.selector; + +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.parser.ArgumentParseResult; +import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.bukkit.CloudBukkitCapabilities; +import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector; +import cloud.commandframework.bukkit.parsers.PlayerArgument; +import cloud.commandframework.context.CommandContext; +import com.google.common.collect.ImmutableList; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.BiFunction; + +public final class MultiplePlayerSelectorArgument extends CommandArgument { + private MultiplePlayerSelectorArgument(final boolean required, + @NonNull final String name, + @NonNull final String defaultValue, + @Nullable final BiFunction<@NonNull CommandContext, @NonNull String, + @NonNull List<@NonNull String>> suggestionsProvider) { + super(required, name, new MultiplePlayerSelectorParser<>(), defaultValue, MultiplePlayerSelector.class, + suggestionsProvider); + } + + /** + * Create a new builder + * + * @param name Name of the argument + * @param Command sender type + * @return Created builder + */ + public static MultiplePlayerSelectorArgument.Builder newBuilder(@NonNull final String name) { + return new MultiplePlayerSelectorArgument.Builder<>(name); + } + + /** + * Create a new required command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument of(@NonNull final String name) { + return MultiplePlayerSelectorArgument.newBuilder(name).asRequired().build(); + } + + /** + * Create a new optional command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name) { + return MultiplePlayerSelectorArgument.newBuilder(name).asOptional().build(); + } + + /** + * Create a new required command argument with a default value + * + * @param name Argument name + * @param defaultEntitySelector Default player + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name, + @NonNull final String defaultEntitySelector) { + return MultiplePlayerSelectorArgument.newBuilder(name).asOptionalWithDefault(defaultEntitySelector).build(); + } + + + public static final class Builder extends CommandArgument.Builder { + + protected Builder(@NonNull final String name) { + super(MultiplePlayerSelector.class, name); + } + + /** + * Builder a new argument + * + * @return Constructed argument + */ + @Override + public @NonNull MultiplePlayerSelectorArgument build() { + return new MultiplePlayerSelectorArgument<>(this.isRequired(), this.getName(), this.getDefaultValue(), + this.getSuggestionsProvider()); + } + + } + + + public static final class MultiplePlayerSelectorParser implements ArgumentParser { + + @Override + public @NonNull ArgumentParseResult parse(@NonNull final CommandContext commandContext, + @NonNull final Queue<@NonNull String> inputQueue) { + final String input = inputQueue.peek(); + if (input == null) { + return ArgumentParseResult.failure(new NullPointerException("No input was provided")); + } + inputQueue.remove(); + + if (!((Set) commandContext.get("CloudBukkitCapabilities")).contains( + CloudBukkitCapabilities.BRIGADIER)) { + Player player = Bukkit.getPlayer(input); + + if (player == null) { + return ArgumentParseResult.failure(new PlayerArgument.PlayerParseException(input)); + } + return ArgumentParseResult.success(new MultiplePlayerSelector(ImmutableList.of(player))); + } + + List entities; + try { + entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input); + } catch (IllegalArgumentException e) { + return ArgumentParseResult.failure(new SelectorParseException(input)); + } + + for (Entity e : entities) { + if (!(e instanceof Player)) { + return ArgumentParseResult.failure(new IllegalArgumentException("Non-players selected in player selector.")); + } + } + + return ArgumentParseResult.success(new MultiplePlayerSelector(entities)); + } + + @Override + public @NonNull List<@NonNull String> suggestions(@NonNull final CommandContext commandContext, + @NonNull final String input) { + List output = new ArrayList<>(); + + for (Player player : Bukkit.getOnlinePlayers()) { + output.add(player.getName()); + } + + return output; + } + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SelectorParseException.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SelectorParseException.java new file mode 100644 index 00000000..582fce1c --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SelectorParseException.java @@ -0,0 +1,57 @@ +// +// 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.bukkit.parsers.selector; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * EntitySelector parse exception + */ +public final class SelectorParseException extends IllegalArgumentException { + + private final String input; + + /** + * Construct a new EntitySelector parse exception + * + * @param input String input + */ + public SelectorParseException(@NonNull final String input) { + this.input = input; + } + + /** + * Get the supplied input + * + * @return String value + */ + public @NonNull String getInput() { + return input; + } + + @Override + public String getMessage() { + return String.format("Selector '%s' is malformed.", input); + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SingleEntitySelectorArgument.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SingleEntitySelectorArgument.java new file mode 100644 index 00000000..f5999d39 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SingleEntitySelectorArgument.java @@ -0,0 +1,149 @@ +// +// 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.bukkit.parsers.selector; + +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.parser.ArgumentParseResult; +import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.bukkit.CloudBukkitCapabilities; +import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector; +import cloud.commandframework.context.CommandContext; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.BiFunction; + +public final class SingleEntitySelectorArgument extends CommandArgument { + private SingleEntitySelectorArgument(final boolean required, + @NonNull final String name, + @NonNull final String defaultValue, + @Nullable final BiFunction<@NonNull CommandContext, @NonNull String, + @NonNull List<@NonNull String>> suggestionsProvider) { + super(required, name, new SingleEntitySelectorParser<>(), defaultValue, SingleEntitySelector.class, suggestionsProvider); + } + + /** + * Create a new builder + * + * @param name Name of the argument + * @param Command sender type + * @return Created builder + */ + public static SingleEntitySelectorArgument.Builder newBuilder(@NonNull final String name) { + return new SingleEntitySelectorArgument.Builder<>(name); + } + + /** + * Create a new required command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument of(@NonNull final String name) { + return SingleEntitySelectorArgument.newBuilder(name).asRequired().build(); + } + + /** + * Create a new optional command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name) { + return SingleEntitySelectorArgument.newBuilder(name).asOptional().build(); + } + + /** + * Create a new required command argument with a default value + * + * @param name Argument name + * @param defaultEntitySelector Default player + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name, + @NonNull final String defaultEntitySelector) { + return SingleEntitySelectorArgument.newBuilder(name).asOptionalWithDefault(defaultEntitySelector).build(); + } + + + public static final class Builder extends CommandArgument.Builder { + + protected Builder(@NonNull final String name) { + super(SingleEntitySelector.class, name); + } + + /** + * Builder a new argument + * + * @return Constructed argument + */ + @Override + public @NonNull SingleEntitySelectorArgument build() { + return new SingleEntitySelectorArgument<>(this.isRequired(), this.getName(), this.getDefaultValue(), + this.getSuggestionsProvider()); + } + + } + + + public static final class SingleEntitySelectorParser implements ArgumentParser { + + @Override + public @NonNull ArgumentParseResult parse(@NonNull final CommandContext commandContext, + @NonNull final Queue<@NonNull String> inputQueue) { + if (!((Set) commandContext.get("CloudBukkitCapabilities")).contains( + CloudBukkitCapabilities.BRIGADIER)) { + return ArgumentParseResult.failure( + new IllegalArgumentException("Entity selector argument type not supported below Minecraft 1.13.")); + } + final String input = inputQueue.peek(); + if (input == null) { + return ArgumentParseResult.failure(new NullPointerException("No input was provided")); + } + inputQueue.remove(); + + List entities; + try { + entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input); + } catch (IllegalArgumentException e) { + return ArgumentParseResult.failure(new SelectorParseException(input)); + } + + if (entities.size() > 1) { + return ArgumentParseResult.failure( + new IllegalArgumentException("More than 1 entity selected in single entity selector.")); + } + + return ArgumentParseResult.success(new SingleEntitySelector(entities)); + } + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SinglePlayerSelectorArgument.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SinglePlayerSelectorArgument.java new file mode 100644 index 00000000..0d3f5f05 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/SinglePlayerSelectorArgument.java @@ -0,0 +1,175 @@ +// +// 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.bukkit.parsers.selector; + +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.parser.ArgumentParseResult; +import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.bukkit.CloudBukkitCapabilities; +import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector; +import cloud.commandframework.bukkit.parsers.PlayerArgument; +import cloud.commandframework.context.CommandContext; +import com.google.common.collect.ImmutableList; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.BiFunction; + +public final class SinglePlayerSelectorArgument extends CommandArgument { + private SinglePlayerSelectorArgument(final boolean required, + @NonNull final String name, + @NonNull final String defaultValue, + @Nullable final BiFunction<@NonNull CommandContext, @NonNull String, + @NonNull List<@NonNull String>> suggestionsProvider) { + super(required, name, new SinglePlayerSelectorParser<>(), defaultValue, SinglePlayerSelector.class, suggestionsProvider); + } + + /** + * Create a new builder + * + * @param name Name of the argument + * @param Command sender type + * @return Created builder + */ + public static SinglePlayerSelectorArgument.Builder newBuilder(@NonNull final String name) { + return new SinglePlayerSelectorArgument.Builder<>(name); + } + + /** + * Create a new required command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument of(@NonNull final String name) { + return SinglePlayerSelectorArgument.newBuilder(name).asRequired().build(); + } + + /** + * Create a new optional command argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name) { + return SinglePlayerSelectorArgument.newBuilder(name).asOptional().build(); + } + + /** + * Create a new required command argument with a default value + * + * @param name Argument name + * @param defaultEntitySelector Default player + * @param Command sender type + * @return Created argument + */ + public static @NonNull CommandArgument optional(@NonNull final String name, + @NonNull final String defaultEntitySelector) { + return SinglePlayerSelectorArgument.newBuilder(name).asOptionalWithDefault(defaultEntitySelector).build(); + } + + + public static final class Builder extends CommandArgument.Builder { + + protected Builder(@NonNull final String name) { + super(SinglePlayerSelector.class, name); + } + + /** + * Builder a new argument + * + * @return Constructed argument + */ + @Override + public @NonNull SinglePlayerSelectorArgument build() { + return new SinglePlayerSelectorArgument<>(this.isRequired(), this.getName(), this.getDefaultValue(), + this.getSuggestionsProvider()); + } + + } + + + public static final class SinglePlayerSelectorParser implements ArgumentParser { + + @Override + public @NonNull ArgumentParseResult parse(@NonNull final CommandContext commandContext, + @NonNull final Queue<@NonNull String> inputQueue) { + final String input = inputQueue.peek(); + if (input == null) { + return ArgumentParseResult.failure(new NullPointerException("No input was provided")); + } + inputQueue.remove(); + + if (!((Set) commandContext.get("CloudBukkitCapabilities")).contains( + CloudBukkitCapabilities.BRIGADIER)) { + Player player = Bukkit.getPlayer(input); + + if (player == null) { + return ArgumentParseResult.failure(new PlayerArgument.PlayerParseException(input)); + } + return ArgumentParseResult.success(new SinglePlayerSelector(ImmutableList.of(player))); + } + + List entities; + try { + entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input); + } catch (IllegalArgumentException e) { + return ArgumentParseResult.failure(new SelectorParseException(input)); + } + + for (Entity e : entities) { + if (!(e instanceof Player)) { + return ArgumentParseResult.failure(new IllegalArgumentException("Non-players selected in player selector.")); + } + } + if (entities.size() > 1) { + return ArgumentParseResult.failure( + new IllegalArgumentException("More than 1 player selected in single player selector")); + } + + return ArgumentParseResult.success(new SinglePlayerSelector(entities)); + } + + @Override + public @NonNull List<@NonNull String> suggestions(@NonNull final CommandContext commandContext, + @NonNull final String input) { + List output = new ArrayList<>(); + + for (Player player : Bukkit.getOnlinePlayers()) { + output.add(player.getName()); + } + + return output; + } + } +} diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/package-info.java b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/package-info.java new file mode 100644 index 00000000..34c0cda7 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/cloud/commandframework/bukkit/parsers/selector/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. +// + +/** + * Entity Selector parsers + */ +package cloud.commandframework.bukkit.parsers.selector; diff --git a/cloud-minecraft/cloud-paper/src/main/java/cloud/commandframework/paper/PaperBrigadierListener.java b/cloud-minecraft/cloud-paper/src/main/java/cloud/commandframework/paper/PaperBrigadierListener.java index 78048042..38c4da63 100644 --- a/cloud-minecraft/cloud-paper/src/main/java/cloud/commandframework/paper/PaperBrigadierListener.java +++ b/cloud-minecraft/cloud-paper/src/main/java/cloud/commandframework/paper/PaperBrigadierListener.java @@ -23,13 +23,17 @@ // package cloud.commandframework.paper; -import cloud.commandframework.brigadier.CloudBrigadierManager; -import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; -import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent; import cloud.commandframework.CommandTree; import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.brigadier.CloudBrigadierManager; +import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector; +import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector; +import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector; +import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector; import cloud.commandframework.context.CommandContext; import cloud.commandframework.permission.CommandPermission; +import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; +import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent; import com.mojang.brigadier.arguments.ArgumentType; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -43,6 +47,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.UUID; import java.util.function.BiPredicate; +import java.util.function.Supplier; import java.util.logging.Level; class PaperBrigadierListener implements Listener { @@ -75,6 +80,11 @@ class PaperBrigadierListener implements Listener { this.mapSimpleNMS(EntityType.class, this.getNMSArgument("EntitySummon").getConstructor()); /* Map Material */ this.mapSimpleNMS(Material.class, this.getNMSArgument("ItemStack").getConstructor()); + /* Map Entity Selectors */ + this.mapComplexNMS(SingleEntitySelector.class, this.getEntitySelectorArgument(true, false)); + this.mapComplexNMS(SinglePlayerSelector.class, this.getEntitySelectorArgument(true, true)); + this.mapComplexNMS(MultipleEntitySelector.class, this.getEntitySelectorArgument(false, false)); + this.mapComplexNMS(MultiplePlayerSelector.class, this.getEntitySelectorArgument(false, true)); } catch (final Exception e) { this.paperCommandManager.getOwningPlugin() .getLogger() @@ -82,6 +92,24 @@ class PaperBrigadierListener implements Listener { } } + /** + * @param single Whether the selector is for a single entity only (true), or for multiple entities (false) + * @param playersOnly Whether the selector is for players only (true), or for all entities (false) + * @return The NMS ArgumentType + */ + private Supplier> getEntitySelectorArgument(final boolean single, final boolean playersOnly) { + return () -> { + try { + Constructor constructor = this.getNMSArgument("Entity").getDeclaredConstructors()[0]; + constructor.setAccessible(true); + return (ArgumentType) constructor.newInstance(single, playersOnly); + } catch (Exception e) { + this.paperCommandManager.getOwningPlugin().getLogger().log(Level.INFO, "Failed to retrieve Selector Argument", e); + return null; + } + }; + } + /** * Attempt to retrieve an NMS argument type * @@ -119,6 +147,24 @@ class PaperBrigadierListener implements Listener { } } + /** + * Attempt to register a mapping between a type and a NMS argument type + * + * @param type Type to map + * @param argumentTypeSupplier Supplier of the NMS argument type + */ + public void mapComplexNMS(@Nonnull final Class type, + @Nonnull final Supplier> argumentTypeSupplier) { + try { + this.brigadierManager.registerDefaultArgumentTypeSupplier(type, argumentTypeSupplier); + } catch (final Exception e) { + this.paperCommandManager.getOwningPlugin() + .getLogger() + .warning(String.format("Failed to map '%s' to a Mojang serializable argument type", + type.getCanonicalName())); + } + } + @EventHandler public void onCommandRegister(@Nonnull final CommandRegisteredEvent event) { final CommandTree commandTree = this.paperCommandManager.getCommandTree();