diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java index baec20c3..48b29cba 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java @@ -25,7 +25,9 @@ package com.intellectualsites.commands; import com.google.common.reflect.TypeToken; import com.intellectualsites.commands.execution.CommandExecutionCoordinator; +import com.intellectualsites.commands.parsers.MaterialArgument; import com.intellectualsites.commands.parsers.WorldArgument; +import org.bukkit.Material; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; @@ -70,6 +72,8 @@ public class BukkitCommandManager /* Register Bukkit parsers */ this.getParserRegistry().registerParserSupplier(TypeToken.of(World.class), params -> new WorldArgument.WorldParser<>()); + this.getParserRegistry().registerParserSupplier(TypeToken.of(Material.class), + params -> new MaterialArgument.MaterialParser<>()); } /** diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/parsers/MaterialArgument.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/parsers/MaterialArgument.java new file mode 100644 index 00000000..3b389fdb --- /dev/null +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/parsers/MaterialArgument.java @@ -0,0 +1,162 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg +// +// 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 com.intellectualsites.commands.parsers; + +import com.intellectualsites.commands.arguments.CommandArgument; +import com.intellectualsites.commands.arguments.parser.ArgumentParseResult; +import com.intellectualsites.commands.arguments.parser.ArgumentParser; +import com.intellectualsites.commands.context.CommandContext; +import org.bukkit.Material; + +import javax.annotation.Nonnull; +import java.util.EnumSet; +import java.util.Queue; +import java.util.stream.Collectors; + +/** + * cloud argument type that parses Bukkit {@link Material materials} + * + * @param Command sender type + */ +public class MaterialArgument extends CommandArgument { + + protected MaterialArgument(final boolean required, + @Nonnull final String name, + @Nonnull final String defaultValue) { + super(required, name, new MaterialParser<>(), defaultValue, Material.class); + } + + /** + * Create a new builder + * + * @param name Name of the argument + * @param Command sender type + * @return Created builder + */ + @Nonnull + public static MaterialArgument.Builder newBuilder(@Nonnull final String name) { + return new MaterialArgument.Builder<>(name); + } + + /** + * Create a new required argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + @Nonnull + public static CommandArgument required(@Nonnull final String name) { + return MaterialArgument.newBuilder(name).asRequired().build(); + } + + /** + * Create a new optional argument + * + * @param name Argument name + * @param Command sender type + * @return Created argument + */ + @Nonnull + public static CommandArgument optional(@Nonnull final String name) { + return MaterialArgument.newBuilder(name).asOptional().build(); + } + + /** + * Create a new optional argument with a default value + * + * @param name Argument name + * @param material Default value + * @param Command sender type + * @return Created argument + */ + @Nonnull + public static CommandArgument optional(@Nonnull final String name, + @Nonnull final Material material) { + return MaterialArgument.newBuilder(name).asOptionalWithDefault(material.name().toLowerCase()).build(); + } + + public static final class Builder extends CommandArgument.Builder { + + protected Builder(@Nonnull final String name) { + super(Material.class, name); + } + + } + + + public static final class MaterialParser implements ArgumentParser { + + @Nonnull + @Override + public ArgumentParseResult parse(@Nonnull final CommandContext commandContext, + @Nonnull final Queue inputQueue) { + final String input = inputQueue.peek(); + if (input == null) { + return ArgumentParseResult.failure(new NullPointerException("No input was provided")); + } + + try { + final Material material = Material.valueOf(input.replace("minecraft:", "").toUpperCase()); + inputQueue.remove(); + return ArgumentParseResult.success(material); + } catch (final IllegalArgumentException exception) { + return ArgumentParseResult.failure(new MaterialParseException(input)); + } + } + + } + + + public static final class MaterialParseException extends IllegalArgumentException { + + private final String input; + + /** + * Construct a new MaterialParseException + * + * @param input Input + */ + public MaterialParseException(@Nonnull final String input) { + this.input = input; + } + + /** + * Get the input + * + * @return Input + */ + @Nonnull + public String getInput() { + return this.input; + } + + @Override + public String getMessage() { + return EnumSet.allOf(Material.class).stream().map(Material::name).map(String::toLowerCase) + .collect(Collectors.joining(", ")); + } + } + +}