Implement EnchantmentArgument, remove inaccurate brig mappings.

This commit is contained in:
jmp 2020-10-09 15:19:13 -07:00 committed by Alexander Söderberg
parent 1f3c3f2bd9
commit c3d679d5ec
7 changed files with 244 additions and 34 deletions

View file

@ -30,9 +30,7 @@ import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector; import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -81,10 +79,6 @@ public final class BukkitBrigadierMapper<C> {
} }
/* Map Enchantment */ /* Map Enchantment */
this.mapSimpleNMS(Enchantment.class, this.getNMSArgument("Enchantment").getConstructor()); this.mapSimpleNMS(Enchantment.class, this.getNMSArgument("Enchantment").getConstructor());
/* Map EntityType */
this.mapSimpleNMS(EntityType.class, this.getNMSArgument("EntitySummon").getConstructor());
/* Map Material */
this.mapSimpleNMS(Material.class, this.getNMSArgument("ItemStack").getConstructor());
/* Map Entity Selectors */ /* Map Entity Selectors */
this.mapComplexNMS(SingleEntitySelector.class, this.getEntitySelectorArgument(true, false)); this.mapComplexNMS(SingleEntitySelector.class, this.getEntitySelectorArgument(true, false));
this.mapComplexNMS(SinglePlayerSelector.class, this.getEntitySelectorArgument(true, true)); this.mapComplexNMS(SinglePlayerSelector.class, this.getEntitySelectorArgument(true, true));

View file

@ -29,6 +29,7 @@ import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector;
import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector; import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector;
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector; import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector; import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector;
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
import cloud.commandframework.bukkit.parsers.MaterialArgument; import cloud.commandframework.bukkit.parsers.MaterialArgument;
import cloud.commandframework.bukkit.parsers.OfflinePlayerArgument; import cloud.commandframework.bukkit.parsers.OfflinePlayerArgument;
import cloud.commandframework.bukkit.parsers.PlayerArgument; import cloud.commandframework.bukkit.parsers.PlayerArgument;
@ -46,6 +47,7 @@ import org.bukkit.Material;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -135,18 +137,16 @@ public class BukkitCommandManager<C> extends CommandManager<C> {
this.registerCommandPreProcessor(new BukkitCommandPreprocessor<>(this)); this.registerCommandPreProcessor(new BukkitCommandPreprocessor<>(this));
/* Register Bukkit Parsers */ /* Register Bukkit Parsers */
this.getParserRegistry().registerParserSupplier(TypeToken.get(World.class), params -> new WorldArgument.WorldParser<>()); this.getParserRegistry().registerParserSupplier(TypeToken.get(World.class), parserParameters ->
this.getParserRegistry().registerParserSupplier( new WorldArgument.WorldParser<>());
TypeToken.get(Material.class), this.getParserRegistry().registerParserSupplier(TypeToken.get(Material.class), parserParameters ->
params -> new MaterialArgument.MaterialParser<>() new MaterialArgument.MaterialParser<>());
); this.getParserRegistry().registerParserSupplier(TypeToken.get(Player.class), parserParameters ->
this.getParserRegistry() new PlayerArgument.PlayerParser<>());
.registerParserSupplier(TypeToken.get(Player.class), params -> new PlayerArgument.PlayerParser<>()); this.getParserRegistry().registerParserSupplier(TypeToken.get(OfflinePlayer.class), parserParameters ->
this.getParserRegistry() new OfflinePlayerArgument.OfflinePlayerParser<>());
.registerParserSupplier( this.getParserRegistry().registerParserSupplier(TypeToken.get(Enchantment.class), parserParameters ->
TypeToken.get(OfflinePlayer.class), new EnchantmentArgument.EnchantmentParser<>());
params -> new OfflinePlayerArgument.OfflinePlayerParser<>()
);
/* Register Entity Selector Parsers */ /* Register Entity Selector Parsers */
this.getParserRegistry().registerParserSupplier(TypeToken.get(SingleEntitySelector.class), parserParameters -> this.getParserRegistry().registerParserSupplier(TypeToken.get(SingleEntitySelector.class), parserParameters ->
new SingleEntitySelectorArgument.SingleEntitySelectorParser<>()); new SingleEntitySelectorArgument.SingleEntitySelectorParser<>());

View file

@ -0,0 +1,190 @@
//
// 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;
import cloud.commandframework.arguments.CommandArgument;
import cloud.commandframework.arguments.parser.ArgumentParseResult;
import cloud.commandframework.arguments.parser.ArgumentParser;
import cloud.commandframework.context.CommandContext;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
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.function.BiFunction;
/**
* cloud argument type that parses Bukkit {@link Enchantment enchantments}
*
* @param <C> Command sender type
*/
public class EnchantmentArgument<C> extends CommandArgument<C, Enchantment> {
protected EnchantmentArgument(
final boolean required,
final @NonNull String name,
final @NonNull String defaultValue,
final @Nullable BiFunction<@NonNull CommandContext<C>, @NonNull String,
@NonNull List<@NonNull String>> suggestionsProvider
) {
super(required, name, new EnchantmentParser<>(), defaultValue, Enchantment.class, suggestionsProvider);
}
/**
* Create a new builder
*
* @param name Name of the argument
* @param <C> Command sender type
* @return Created builder
*/
public static <C> EnchantmentArgument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
return new EnchantmentArgument.Builder<>(name);
}
/**
* Create a new required argument
*
* @param name Argument name
* @param <C> Command sender type
* @return Created argument
*/
public static <C> @NonNull CommandArgument<C, Enchantment> of(final @NonNull String name) {
return EnchantmentArgument.<C>newBuilder(name).asRequired().build();
}
/**
* Create a new optional argument
*
* @param name Argument name
* @param <C> Command sender type
* @return Created argument
*/
public static <C> @NonNull CommandArgument<C, Enchantment> optional(final @NonNull String name) {
return EnchantmentArgument.<C>newBuilder(name).asOptional().build();
}
/**
* Create a new optional argument with a default value
*
* @param name Argument name
* @param enchantment Default value
* @param <C> Command sender type
* @return Created argument
*/
public static <C> @NonNull CommandArgument<C, Enchantment> optional(
final @NonNull String name,
final @NonNull Enchantment enchantment
) {
return EnchantmentArgument.<C>newBuilder(name).asOptionalWithDefault(enchantment.getKey().toString()).build();
}
public static final class Builder<C> extends CommandArgument.Builder<C, Enchantment> {
protected Builder(final @NonNull String name) {
super(Enchantment.class, name);
}
}
public static final class EnchantmentParser<C> implements ArgumentParser<C, Enchantment> {
@Override
public @NonNull ArgumentParseResult<Enchantment> parse(
final @NonNull CommandContext<C> commandContext,
final @NonNull Queue<@NonNull String> inputQueue
) {
final String input = inputQueue.peek();
if (input == null) {
return ArgumentParseResult.failure(new NullPointerException("No input was provided"));
}
final NamespacedKey key;
if (input.contains(":")) {
final String[] splitInput = input.split(":");
//noinspection deprecation
key = new NamespacedKey(splitInput[0], splitInput[1]);
} else {
key = NamespacedKey.minecraft(input);
}
final Enchantment enchantment = Enchantment.getByKey(key);
if (enchantment == null) {
return ArgumentParseResult.failure(new EnchantmentParseException(input));
}
inputQueue.remove();
return ArgumentParseResult.success(enchantment);
}
@Override
public @NonNull List<@NonNull String> suggestions(
final @NonNull CommandContext<C> commandContext,
final @NonNull String input
) {
final List<String> completions = new ArrayList<>();
for (Enchantment value : Enchantment.values()) {
if (value.getKey().getNamespace().equals(NamespacedKey.MINECRAFT)) {
completions.add(value.getKey().getKey());
} else {
completions.add(value.getKey().toString());
}
}
return completions;
}
}
public static final class EnchantmentParseException extends IllegalArgumentException {
private final String input;
/**
* Construct a new EnchantmentParseException
*
* @param input Input
*/
public EnchantmentParseException(final @NonNull String input) {
this.input = input;
}
/**
* Get the input
*
* @return Input
*/
public @NonNull String getInput() {
return this.input;
}
@Override
public String getMessage() {
return String.format("'%s' is not a valid enchantment", this.input);
}
}
}

View file

@ -31,6 +31,7 @@ import org.bukkit.Material;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@ -108,7 +109,6 @@ public class MaterialArgument<C> extends CommandArgument<C, Material> {
} }
public static final class MaterialParser<C> implements ArgumentParser<C, Material> { public static final class MaterialParser<C> implements ArgumentParser<C, Material> {
@Override @Override
@ -121,21 +121,27 @@ public class MaterialArgument<C> extends CommandArgument<C, Material> {
return ArgumentParseResult.failure(new NullPointerException("No input was provided")); return ArgumentParseResult.failure(new NullPointerException("No input was provided"));
} }
/* Pre-process input */
if (input.contains("minecraft:")) {
input = input.substring("minecraft:".length());
}
input = input.toUpperCase();
try { try {
final Material material = Material.valueOf(input); final Material material = Material.valueOf(input.toUpperCase());
inputQueue.remove(); inputQueue.remove();
return ArgumentParseResult.success(material); return ArgumentParseResult.success(material);
} catch (final IllegalArgumentException exception) { } catch (final IllegalArgumentException exception) {
return ArgumentParseResult.failure(new MaterialParseException(inputQueue.peek())); return ArgumentParseResult.failure(new MaterialParseException(input));
} }
} }
@Override
public @NonNull List<@NonNull String> suggestions(
final @NonNull CommandContext<C> commandContext,
final @NonNull String input
) {
final List<String> completions = new ArrayList<>();
for (Material value : Material.values()) {
completions.add(value.name().toLowerCase());
}
return completions;
}
} }

View file

@ -1,5 +1,4 @@
dependencies { dependencies {
api 'net.kyori:adventure-api:4.0.0-SNAPSHOT'
api project(':cloud-core') api project(':cloud-core')
api 'net.kyori:adventure-text-minimessage:4.0.0-SNAPSHOT' api 'net.kyori:adventure-api:4.0.0-SNAPSHOT'
} }

View file

@ -56,10 +56,8 @@ public class PaperCommandManager<C> extends BukkitCommandManager<C> {
CommandExecutionCoordinator<C>> commandExecutionCoordinator, CommandExecutionCoordinator<C>> commandExecutionCoordinator,
final @NonNull Function<CommandSender, C> commandSenderMapper, final @NonNull Function<CommandSender, C> commandSenderMapper,
final @NonNull Function<C, CommandSender> backwardsCommandSenderMapper final @NonNull Function<C, CommandSender> backwardsCommandSenderMapper
) throws ) throws Exception {
Exception {
super(owningPlugin, commandExecutionCoordinator, commandSenderMapper, backwardsCommandSenderMapper); super(owningPlugin, commandExecutionCoordinator, commandSenderMapper, backwardsCommandSenderMapper);
} }
/** /**

View file

@ -49,6 +49,8 @@ import cloud.commandframework.bukkit.BukkitCommandManager;
import cloud.commandframework.bukkit.BukkitCommandMetaBuilder; import cloud.commandframework.bukkit.BukkitCommandMetaBuilder;
import cloud.commandframework.bukkit.CloudBukkitCapabilities; import cloud.commandframework.bukkit.CloudBukkitCapabilities;
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector; import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
import cloud.commandframework.bukkit.parsers.MaterialArgument;
import cloud.commandframework.bukkit.parsers.WorldArgument; import cloud.commandframework.bukkit.parsers.WorldArgument;
import cloud.commandframework.bukkit.parsers.selector.SingleEntitySelectorArgument; import cloud.commandframework.bukkit.parsers.selector.SingleEntitySelectorArgument;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
@ -71,6 +73,8 @@ import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@ -287,7 +291,7 @@ public final class ExamplePlugin extends JavaPlugin {
)); ));
manager.command(manager.commandBuilder("give") manager.command(manager.commandBuilder("give")
.senderType(Player.class) .senderType(Player.class)
.argument(EnumArgument.of(Material.class, "material")) .argument(MaterialArgument.of("material"))
.argument(IntegerArgument.of("amount")) .argument(IntegerArgument.of("amount"))
.handler(c -> { .handler(c -> {
final Material material = c.get("material"); final Material material = c.get("material");
@ -296,6 +300,21 @@ public final class ExamplePlugin extends JavaPlugin {
((Player) c.getSender()).getInventory().addItem(itemStack); ((Player) c.getSender()).getInventory().addItem(itemStack);
c.getSender().sendMessage("You've been given stuff, bro."); c.getSender().sendMessage("You've been given stuff, bro.");
})); }));
manager.command(builder.literal("summon")
.senderType(Player.class)
.argument(EnumArgument.of(EntityType.class, "type"))
.handler(c -> manager.taskRecipe().begin(c).synchronous(ctx -> {
final Location loc = ((Player) ctx.getSender()).getLocation();
loc.getWorld().spawnEntity(loc, ctx.get("type"));
}).execute()));
manager.command(builder.literal("enchant")
.senderType(Player.class)
.argument(EnchantmentArgument.of("enchant"))
.argument(IntegerArgument.of("level"))
.handler(c -> manager.taskRecipe().begin(c).synchronous(ctx -> {
final Player player = ((Player) ctx.getSender());
player.getInventory().getItemInHand().addEnchantment(ctx.get("enchant"), ctx.get("level"));
}).execute()));
// //
// An Argument Parser for TextColor that accepts NamedTextColor names or RGB colors in the format 'RRGGBB' // An Argument Parser for TextColor that accepts NamedTextColor names or RGB colors in the format 'RRGGBB'
@ -419,7 +438,8 @@ public final class ExamplePlugin extends JavaPlugin {
final @NonNull Player player, final @NonNull Player player,
final @NonNull @Argument("material") Material material, final @NonNull @Argument("material") Material material,
final @Argument("amount") int number, final @Argument("amount") int number,
final @Nullable @Flag("color") ChatColor nameColor final @Nullable @Flag("color") ChatColor nameColor,
final @Nullable @Flag("enchant") Enchantment enchant
) { ) {
final ItemStack itemStack = new ItemStack(material, number); final ItemStack itemStack = new ItemStack(material, number);
String itemName = String.format( String itemName = String.format(
@ -437,6 +457,9 @@ public final class ExamplePlugin extends JavaPlugin {
meta.setDisplayName(itemName); meta.setDisplayName(itemName);
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);
} }
if (enchant != null) {
itemStack.addUnsafeEnchantment(enchant, 10);
}
player.getInventory().addItem(itemStack); player.getInventory().addItem(itemStack);
player.sendMessage(ChatColor.GREEN + String.format("You have been given %d x %s", number, material)); player.sendMessage(ChatColor.GREEN + String.format("You have been given %d x %s", number, material));
} }