bukkit: Update Minecraft Brigadier argument types to work on Mojang-mapped servers (#267)

This commit is contained in:
Jason 2021-06-24 15:03:52 -07:00
parent db2c3f1724
commit 04e697cca6
9 changed files with 150 additions and 101 deletions

View file

@ -26,7 +26,6 @@ package cloud.commandframework.bukkit;
import cloud.commandframework.arguments.parser.ArgumentParser; import cloud.commandframework.arguments.parser.ArgumentParser;
import cloud.commandframework.arguments.standard.UUIDArgument; import cloud.commandframework.arguments.standard.UUIDArgument;
import cloud.commandframework.brigadier.CloudBrigadierManager; import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes; import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes;
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument; import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
import cloud.commandframework.bukkit.parsers.EnchantmentArgument; import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
@ -56,8 +55,6 @@ import java.util.logging.Level;
*/ */
public final class BukkitBrigadierMapper<C> { public final class BukkitBrigadierMapper<C> {
private static final int UUID_ARGUMENT_VERSION = 16;
private final BukkitCommandManager<C> commandManager; private final BukkitCommandManager<C> commandManager;
private final CloudBrigadierManager<C, ?> brigadierManager; private final CloudBrigadierManager<C, ?> brigadierManager;
@ -74,18 +71,13 @@ public final class BukkitBrigadierMapper<C> {
this.commandManager = commandManager; this.commandManager = commandManager;
this.brigadierManager = brigadierManager; this.brigadierManager = brigadierManager;
if (!CraftBukkitReflection.craftBukkit()) {
this.commandManager.getOwningPlugin().getLogger().warning(
"Could not detect relocated CraftBukkit package, NMS brigadier mappings will not be enabled.");
return;
}
this.registerMappings(); this.registerMappings();
} }
private void registerMappings() { private void registerMappings() {
/* UUID nms argument is a 1.16+ feature */ /* UUID nms argument is a 1.16+ feature */
if (CraftBukkitReflection.MAJOR_REVISION >= UUID_ARGUMENT_VERSION) { final Class<? extends ArgumentType<?>> uuid = MinecraftArgumentTypes.getClassByKey(NamespacedKey.minecraft("uuid"));
if (uuid != null) {
/* Map UUID */ /* Map UUID */
this.mapSimpleNMS(new TypeToken<UUIDArgument.UUIDParser<C>>() { this.mapSimpleNMS(new TypeToken<UUIDArgument.UUIDParser<C>>() {
}, "uuid"); }, "uuid");

View file

@ -25,7 +25,6 @@ package cloud.commandframework.bukkit;
import cloud.commandframework.brigadier.argument.WrappedBrigadierParser; import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
import cloud.commandframework.bukkit.internal.BukkitBackwardsBrigadierSenderMapper; import cloud.commandframework.bukkit.internal.BukkitBackwardsBrigadierSenderMapper;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext; import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext;
import cloud.commandframework.execution.preprocessor.CommandPreprocessor; import cloud.commandframework.execution.preprocessor.CommandPreprocessor;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -53,7 +52,7 @@ final class BukkitCommandPreprocessor<C> implements CommandPreprocessor<C> {
BukkitCommandPreprocessor(final @NonNull BukkitCommandManager<C> commandManager) { BukkitCommandPreprocessor(final @NonNull BukkitCommandManager<C> commandManager) {
this.commandManager = commandManager; this.commandManager = commandManager;
this.bukkitCapabilities = commandManager.queryCapabilities(); this.bukkitCapabilities = commandManager.queryCapabilities();
if (this.bukkitCapabilities.contains(CloudBukkitCapabilities.BRIGADIER) && CraftBukkitReflection.craftBukkit()) { if (this.bukkitCapabilities.contains(CloudBukkitCapabilities.BRIGADIER)) {
this.mapper = new BukkitBackwardsBrigadierSenderMapper<>(this.commandManager); this.mapper = new BukkitBackwardsBrigadierSenderMapper<>(this.commandManager);
} else { } else {
this.mapper = null; this.mapper = null;

View file

@ -26,7 +26,6 @@ package cloud.commandframework.bukkit;
import cloud.commandframework.Command; import cloud.commandframework.Command;
import cloud.commandframework.brigadier.CloudBrigadierManager; import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.internal.BukkitBackwardsBrigadierSenderMapper; import cloud.commandframework.bukkit.internal.BukkitBackwardsBrigadierSenderMapper;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
@ -64,10 +63,8 @@ class CloudCommodoreManager<C> extends BukkitPluginRegistrationHandler<C> {
new BukkitBrigadierMapper<>(this.commandManager, this.brigadierManager); new BukkitBrigadierMapper<>(this.commandManager, this.brigadierManager);
if (CraftBukkitReflection.craftBukkit()) {
this.brigadierManager.backwardsBrigadierSenderMapper(new BukkitBackwardsBrigadierSenderMapper<>(this.commandManager)); this.brigadierManager.backwardsBrigadierSenderMapper(new BukkitBackwardsBrigadierSenderMapper<>(this.commandManager));
} }
}
@Override @Override
protected void registerExternal( protected void registerExternal(

View file

@ -32,6 +32,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.Supplier;
/** /**
* Utilities for doing reflection on CraftBukkit, used by the cloud implementation. * Utilities for doing reflection on CraftBukkit, used by the cloud implementation.
@ -45,7 +46,7 @@ public final class CraftBukkitReflection {
private static final String PREFIX_MC = "net.minecraft."; private static final String PREFIX_MC = "net.minecraft.";
private static final String PREFIX_CRAFTBUKKIT = "org.bukkit.craftbukkit"; private static final String PREFIX_CRAFTBUKKIT = "org.bukkit.craftbukkit";
private static final String CRAFT_SERVER = "CraftServer"; private static final String CRAFT_SERVER = "CraftServer";
private static final String VERSION; private static final String CB_PKG_VERSION;
public static final int MAJOR_REVISION; public static final int MAJOR_REVISION;
static { static {
@ -54,18 +55,26 @@ public final class CraftBukkitReflection {
final String nmsVersion = pkg.substring(pkg.lastIndexOf(".") + 1); final String nmsVersion = pkg.substring(pkg.lastIndexOf(".") + 1);
if (!nmsVersion.contains("_")) { if (!nmsVersion.contains("_")) {
MAJOR_REVISION = -1; MAJOR_REVISION = -1;
VERSION = null;
} else { } else {
MAJOR_REVISION = Integer.parseInt(nmsVersion.split("_")[1]); MAJOR_REVISION = Integer.parseInt(nmsVersion.split("_")[1]);
}
String name = serverClass.getName(); String name = serverClass.getName();
name = name.substring(PREFIX_CRAFTBUKKIT.length()); name = name.substring(PREFIX_CRAFTBUKKIT.length());
name = name.substring(0, name.length() - CRAFT_SERVER.length()); name = name.substring(0, name.length() - CRAFT_SERVER.length());
VERSION = name; CB_PKG_VERSION = name;
}
} }
public static boolean craftBukkit() { @SafeVarargs
return MAJOR_REVISION != -1 && VERSION != null; public static <T> @NonNull T firstNonNullOrThrow(
final @NonNull Supplier<@NonNull String> errorMessage,
final @Nullable T @NonNull... elements
) {
for (final T element : elements) {
if (element != null) {
return element;
}
}
throw new IllegalArgumentException(errorMessage.get());
} }
public static @NonNull Class<?> needNMSClassOrElse( public static @NonNull Class<?> needNMSClassOrElse(
@ -76,17 +85,12 @@ public final class CraftBukkitReflection {
if (nmsClass != null) { if (nmsClass != null) {
return nmsClass; return nmsClass;
} }
for (final String name : classNames) { return firstNonNullOrThrow(
final Class<?> maybe = findClass(name); () -> "Couldn't find a class! NMS: '%s' or '%s'.",
if (maybe != null) { Arrays.stream(classNames)
return maybe; .map(CraftBukkitReflection::findClass)
} .toArray(Class[]::new)
} );
throw new IllegalStateException(String.format(
"Couldn't find a class! NMS: '%s' or '%s'.",
nms,
Arrays.toString(classNames)
));
} }
public static @NonNull Class<?> needMCClass(final @NonNull String name) throws RuntimeException { public static @NonNull Class<?> needMCClass(final @NonNull String name) throws RuntimeException {
@ -94,11 +98,11 @@ public final class CraftBukkitReflection {
} }
public static @NonNull Class<?> needNMSClass(final @NonNull String className) throws RuntimeException { public static @NonNull Class<?> needNMSClass(final @NonNull String className) throws RuntimeException {
return needClass(PREFIX_NMS + VERSION + className); return needClass(PREFIX_NMS + CB_PKG_VERSION + className);
} }
public static @NonNull Class<?> needOBCClass(final @NonNull String className) throws RuntimeException { public static @NonNull Class<?> needOBCClass(final @NonNull String className) throws RuntimeException {
return needClass(PREFIX_CRAFTBUKKIT + VERSION + className); return needClass(PREFIX_CRAFTBUKKIT + CB_PKG_VERSION + className);
} }
public static @Nullable Class<?> findMCClass(final @NonNull String name) throws RuntimeException { public static @Nullable Class<?> findMCClass(final @NonNull String name) throws RuntimeException {
@ -106,11 +110,11 @@ public final class CraftBukkitReflection {
} }
public static @Nullable Class<?> findNMSClass(final @NonNull String className) throws RuntimeException { public static @Nullable Class<?> findNMSClass(final @NonNull String className) throws RuntimeException {
return findClass(PREFIX_NMS + VERSION + className); return findClass(PREFIX_NMS + CB_PKG_VERSION + className);
} }
public static @Nullable Class<?> findOBCClass(final @NonNull String className) throws RuntimeException { public static @Nullable Class<?> findOBCClass(final @NonNull String className) throws RuntimeException {
return findClass(PREFIX_CRAFTBUKKIT + VERSION + className); return findClass(PREFIX_CRAFTBUKKIT + CB_PKG_VERSION + className);
} }
public static @NonNull Class<?> needClass(final @NonNull String className) throws RuntimeException { public static @NonNull Class<?> needClass(final @NonNull String className) throws RuntimeException {
@ -139,6 +143,14 @@ public final class CraftBukkitReflection {
} }
} }
public static @Nullable Field findField(final @NonNull Class<?> holder, final @NonNull String name) throws RuntimeException {
try {
return needField(holder, name);
} catch (final RuntimeException e) {
return null;
}
}
public static @NonNull Constructor<?> needConstructor(final @NonNull Class<?> holder, final @NonNull Class<?>... parameters) { public static @NonNull Constructor<?> needConstructor(final @NonNull Class<?> holder, final @NonNull Class<?>... parameters) {
try { try {
return holder.getDeclaredConstructor(parameters); return holder.getDeclaredConstructor(parameters);
@ -151,6 +163,18 @@ public final class CraftBukkitReflection {
return findClass(className) != null; return findClass(className) != null;
} }
public static @Nullable Method findMethod(
final @NonNull Class<?> holder,
final @NonNull String name,
final @NonNull Class<?>... params
) throws RuntimeException {
try {
return holder.getMethod(name, params);
} catch (final NoSuchMethodException e) {
return null;
}
}
public static @NonNull Method needMethod( public static @NonNull Method needMethod(
final @NonNull Class<?> holder, final @NonNull Class<?> holder,
final @NonNull String name, final @NonNull String name,

View file

@ -78,12 +78,15 @@ public final class MinecraftArgumentTypes {
if (CraftBukkitReflection.findMCClass("resources.ResourceLocation") != null) { if (CraftBukkitReflection.findMCClass("resources.ResourceLocation") != null) {
minecraftKey = CraftBukkitReflection.needMCClass("resources.ResourceLocation"); minecraftKey = CraftBukkitReflection.needMCClass("resources.ResourceLocation");
argumentRegistry = CraftBukkitReflection.needMCClass("commands.synchronization.ArgumentTypes"); argumentRegistry = CraftBukkitReflection.needMCClass("commands.synchronization.ArgumentTypes");
} else if (CraftBukkitReflection.MAJOR_REVISION > 16) {
minecraftKey = CraftBukkitReflection.needMCClass("resources.MinecraftKey");
argumentRegistry = CraftBukkitReflection.needMCClass("commands.synchronization.ArgumentRegistry");
} else { } else {
minecraftKey = CraftBukkitReflection.needNMSClass("MinecraftKey"); minecraftKey = CraftBukkitReflection.needNMSClassOrElse(
argumentRegistry = CraftBukkitReflection.needNMSClass("ArgumentRegistry"); "MinecraftKey",
"net.minecraft.resources.MinecraftKey"
);
argumentRegistry = CraftBukkitReflection.needNMSClassOrElse(
"ArgumentRegistry",
"commands.synchronization.ArgumentRegistry"
);
} }
MINECRAFT_KEY_CONSTRUCTOR = minecraftKey.getConstructor(String.class, String.class); MINECRAFT_KEY_CONSTRUCTOR = minecraftKey.getConstructor(String.class, String.class);

View file

@ -31,9 +31,11 @@ import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
import cloud.commandframework.bukkit.BukkitCommandManager; import cloud.commandframework.bukkit.BukkitCommandManager;
import cloud.commandframework.bukkit.data.BlockPredicate; import cloud.commandframework.bukkit.data.BlockPredicate;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection; import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import io.leangen.geantyref.TypeToken; import io.leangen.geantyref.TypeToken;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block; import org.bukkit.block.Block;
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;
@ -142,13 +144,15 @@ public final class BlockPredicateArgument<C> extends CommandArgument<C, BlockPre
private static final Class<?> TAG_REGISTRY_CLASS; private static final Class<?> TAG_REGISTRY_CLASS;
static { static {
if (CraftBukkitReflection.MAJOR_REVISION >= 16) { if (CraftBukkitReflection.MAJOR_REVISION > 12 && CraftBukkitReflection.MAJOR_REVISION < 16) {
TAG_REGISTRY_CLASS = CraftBukkitReflection.needNMSClassOrElse(
"ITagRegistry",
"net.minecraft.tags.ITagRegistry"
);
} else {
TAG_REGISTRY_CLASS = CraftBukkitReflection.needNMSClass("TagRegistry"); TAG_REGISTRY_CLASS = CraftBukkitReflection.needNMSClass("TagRegistry");
} else {
TAG_REGISTRY_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
() -> "Couldn't find TagContainer class",
CraftBukkitReflection.findNMSClass("ITagRegistry"),
CraftBukkitReflection.findMCClass("tags.ITagRegistry"),
CraftBukkitReflection.findMCClass("tags.TagContainer")
);
} }
} }
@ -157,42 +161,52 @@ public final class BlockPredicateArgument<C> extends CommandArgument<C, BlockPre
"MinecraftServer", "MinecraftServer",
"net.minecraft.server.MinecraftServer" "net.minecraft.server.MinecraftServer"
); );
private static final Class<?> COMMAND_LISTENER_WRAPPER_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> COMMAND_LISTENER_WRAPPER_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
"CommandListenerWrapper", () -> "Couldn't find CommandSourceStack class",
"net.minecraft.commands.CommandListenerWrapper" CraftBukkitReflection.findNMSClass("CommandListenerWrapper"),
CraftBukkitReflection.findMCClass("commands.CommandListenerWrapper"),
CraftBukkitReflection.findMCClass("commands.CommandSourceStack")
); );
private static final Class<?> ARGUMENT_BLOCK_PREDICATE_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> ARGUMENT_BLOCK_PREDICATE_CLASS =
"ArgumentBlockPredicate", MinecraftArgumentTypes.getClassByKey(NamespacedKey.minecraft("block_predicate"));
"net.minecraft.commands.arguments.blocks.ArgumentBlockPredicate" private static final Class<?> ARGUMENT_BLOCK_PREDICATE_RESULT_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
() -> "Couldn't find BlockPredicateArgument$Result class",
CraftBukkitReflection.findNMSClass("ArgumentBlockPredicate$b"),
CraftBukkitReflection.findMCClass("commands.arguments.blocks.ArgumentBlockPredicate$b"),
CraftBukkitReflection.findMCClass("commands.arguments.blocks.BlockPredicateArgument$Result")
); );
private static final Class<?> ARGUMENT_BLOCK_PREDICATE_RESULT_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> SHAPE_DETECTOR_BLOCK_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
"ArgumentBlockPredicate$b", () -> "Couldn't find BlockInWorld class",
"net.minecraft.commands.arguments.blocks.ArgumentBlockPredicate$b" CraftBukkitReflection.findNMSClass("ShapeDetectorBlock"),
CraftBukkitReflection.findMCClass("world.level.block.state.pattern.ShapeDetectorBlock"),
CraftBukkitReflection.findMCClass("world.level.block.state.pattern.BlockInWorld")
); );
// BlockInWorld private static final Class<?> LEVEL_READER_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
private static final Class<?> SHAPE_DETECTOR_BLOCK_CLASS = CraftBukkitReflection.needNMSClassOrElse( () -> "Couldn't find LevelReader class",
"ShapeDetectorBlock", CraftBukkitReflection.findNMSClass("IWorldReader"),
"net.minecraft.world.level.block.state.pattern.ShapeDetectorBlock" CraftBukkitReflection.findMCClass("world.level.IWorldReader"),
CraftBukkitReflection.findMCClass("world.level.LevelReader")
); );
private static final Class<?> I_WORLD_READER_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> BLOCK_POSITION_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
"IWorldReader", () -> "Couldn't find BlockPos class",
"net.minecraft.world.level.IWorldReader" CraftBukkitReflection.findNMSClass("BlockPosition"),
); CraftBukkitReflection.findMCClass("core.BlockPosition"),
private static final Class<?> BLOCK_POSITION_CLASS = CraftBukkitReflection.needNMSClassOrElse( CraftBukkitReflection.findMCClass("core.BlockPos")
"BlockPosition",
"net.minecraft.core.BlockPosition"
); );
private static final Constructor<?> BLOCK_POSITION_CTR = private static final Constructor<?> BLOCK_POSITION_CTR =
CraftBukkitReflection.needConstructor(BLOCK_POSITION_CLASS, int.class, int.class, int.class); CraftBukkitReflection.needConstructor(BLOCK_POSITION_CLASS, int.class, int.class, int.class);
private static final Constructor<?> SHAPE_DETECTOR_BLOCK_CTR = CraftBukkitReflection private static final Constructor<?> SHAPE_DETECTOR_BLOCK_CTR = CraftBukkitReflection
.needConstructor(SHAPE_DETECTOR_BLOCK_CLASS, I_WORLD_READER_CLASS, BLOCK_POSITION_CLASS, boolean.class); .needConstructor(SHAPE_DETECTOR_BLOCK_CLASS, LEVEL_READER_CLASS, BLOCK_POSITION_CLASS, boolean.class);
private static final Method GET_HANDLE_METHOD = CraftBukkitReflection.needMethod(CRAFT_WORLD_CLASS, "getHandle"); private static final Method GET_HANDLE_METHOD = CraftBukkitReflection.needMethod(CRAFT_WORLD_CLASS, "getHandle");
private static final Method CREATE_PREDICATE_METHOD = private static final Method CREATE_PREDICATE_METHOD =
CraftBukkitReflection.needMethod(ARGUMENT_BLOCK_PREDICATE_RESULT_CLASS, "create", TAG_REGISTRY_CLASS); CraftBukkitReflection.needMethod(ARGUMENT_BLOCK_PREDICATE_RESULT_CLASS, "create", TAG_REGISTRY_CLASS);
private static final Method GET_SERVER_METHOD = private static final Method GET_SERVER_METHOD =
CraftBukkitReflection.needMethod(COMMAND_LISTENER_WRAPPER_CLASS, "getServer"); CraftBukkitReflection.needMethod(COMMAND_LISTENER_WRAPPER_CLASS, "getServer");
private static final Method GET_TAG_REGISTRY_METHOD = private static final Method GET_TAG_REGISTRY_METHOD = CraftBukkitReflection.firstNonNullOrThrow(
CraftBukkitReflection.needMethod(MINECRAFT_SERVER_CLASS, "getTagRegistry"); () -> "getTags method on MinecraftServer",
CraftBukkitReflection.findMethod(MINECRAFT_SERVER_CLASS, "getTagRegistry"),
CraftBukkitReflection.findMethod(MINECRAFT_SERVER_CLASS, "getTags")
);
private final ArgumentParser<C, BlockPredicate> parser; private final ArgumentParser<C, BlockPredicate> parser;

View file

@ -31,10 +31,12 @@ import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
import cloud.commandframework.bukkit.BukkitCommandManager; import cloud.commandframework.bukkit.BukkitCommandManager;
import cloud.commandframework.bukkit.data.ProtoItemStack; import cloud.commandframework.bukkit.data.ProtoItemStack;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection; import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
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;
@ -49,6 +51,8 @@ import java.util.Queue;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/** /**
* Argument type for parsing a {@link Material} and optional extra NBT data into a {@link ProtoItemStack}. * Argument type for parsing a {@link Material} and optional extra NBT data into a {@link ProtoItemStack}.
* *
@ -150,10 +154,7 @@ public final class ItemStackArgument<C> extends CommandArgument<C, ProtoItemStac
* @since 1.5.0 * @since 1.5.0
*/ */
public Parser() { public Parser() {
if (!CraftBukkitReflection.craftBukkit()) { if (findItemInputClass() != null) {
throw new UnsupportedOperationException("ItemStack parser requires CraftBukkit");
}
if (CraftBukkitReflection.MAJOR_REVISION >= 13) {
this.parser = new ModernParser<>(); this.parser = new ModernParser<>();
} else { } else {
this.parser = new LegacyParser<>(); this.parser = new LegacyParser<>();
@ -178,6 +179,20 @@ public final class ItemStackArgument<C> extends CommandArgument<C, ProtoItemStac
} }
private static @Nullable Class<?> findItemInputClass() {
final Class<?>[] classes = new Class<?>[] {
CraftBukkitReflection.findNMSClass("ArgumentPredicateItemStack"),
CraftBukkitReflection.findMCClass("commands.arguments.item.ArgumentPredicateItemStack"),
CraftBukkitReflection.findMCClass("commands.arguments.item.ItemInput")
};
for (final Class<?> clazz : classes) {
if (clazz != null) {
return clazz;
}
}
return null;
}
private static final class ModernParser<C> implements ArgumentParser<C, ProtoItemStack> { private static final class ModernParser<C> implements ArgumentParser<C, ProtoItemStack> {
private static final Class<?> NMS_ITEM_STACK_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> NMS_ITEM_STACK_CLASS = CraftBukkitReflection.needNMSClassOrElse(
@ -186,14 +201,9 @@ public final class ItemStackArgument<C> extends CommandArgument<C, ProtoItemStac
); );
private static final Class<?> CRAFT_ITEM_STACK_CLASS = private static final Class<?> CRAFT_ITEM_STACK_CLASS =
CraftBukkitReflection.needOBCClass("inventory.CraftItemStack"); CraftBukkitReflection.needOBCClass("inventory.CraftItemStack");
private static final Class<?> ARGUMENT_ITEM_STACK_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> ARGUMENT_ITEM_STACK_CLASS =
"ArgumentItemStack", MinecraftArgumentTypes.getClassByKey(NamespacedKey.minecraft("item_stack"));
"net.minecraft.commands.arguments.item.ArgumentItemStack" private static final Class<?> ITEM_INPUT_CLASS = requireNonNull(findItemInputClass(), "ItemInput class");
);
private static final Class<?> ARGUMENT_PREDICATE_ITEM_STACK_CLASS = CraftBukkitReflection.needNMSClassOrElse(
"ArgumentPredicateItemStack",
"net.minecraft.commands.arguments.item.ArgumentPredicateItemStack"
);
private static final Class<?> NMS_ITEM_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> NMS_ITEM_CLASS = CraftBukkitReflection.needNMSClassOrElse(
"Item", "Item",
"net.minecraft.world.item.Item" "net.minecraft.world.item.Item"
@ -202,12 +212,23 @@ public final class ItemStackArgument<C> extends CommandArgument<C, ProtoItemStac
CraftBukkitReflection.needOBCClass("util.CraftMagicNumbers"); CraftBukkitReflection.needOBCClass("util.CraftMagicNumbers");
private static final Method GET_MATERIAL_METHOD = CraftBukkitReflection private static final Method GET_MATERIAL_METHOD = CraftBukkitReflection
.needMethod(CRAFT_MAGIC_NUMBERS_CLASS, "getMaterial", NMS_ITEM_CLASS); .needMethod(CRAFT_MAGIC_NUMBERS_CLASS, "getMaterial", NMS_ITEM_CLASS);
private static final Method CREATE_ITEM_STACK_METHOD = CraftBukkitReflection private static final Method CREATE_ITEM_STACK_METHOD = CraftBukkitReflection.firstNonNullOrThrow(
.needMethod(ARGUMENT_PREDICATE_ITEM_STACK_CLASS, "a", int.class, boolean.class); () -> "Couldn't find createItemStack method on ItemInput",
CraftBukkitReflection.findMethod(ITEM_INPUT_CLASS, "a", int.class, boolean.class),
CraftBukkitReflection.findMethod(ITEM_INPUT_CLASS, "createItemStack", int.class, boolean.class)
);
private static final Method AS_BUKKIT_COPY_METHOD = CraftBukkitReflection private static final Method AS_BUKKIT_COPY_METHOD = CraftBukkitReflection
.needMethod(CRAFT_ITEM_STACK_CLASS, "asBukkitCopy", NMS_ITEM_STACK_CLASS); .needMethod(CRAFT_ITEM_STACK_CLASS, "asBukkitCopy", NMS_ITEM_STACK_CLASS);
private static final Field ITEM_FIELD = CraftBukkitReflection.needField(ARGUMENT_PREDICATE_ITEM_STACK_CLASS, "b"); private static final Field ITEM_FIELD = CraftBukkitReflection.firstNonNullOrThrow(
private static final Field COMPOUND_TAG_FIELD = CraftBukkitReflection.needField(ARGUMENT_PREDICATE_ITEM_STACK_CLASS, "c"); () -> "Couldn't find item field on ItemInput",
CraftBukkitReflection.findField(ITEM_INPUT_CLASS, "b"),
CraftBukkitReflection.findField(ITEM_INPUT_CLASS, "item")
);
private static final Field COMPOUND_TAG_FIELD = CraftBukkitReflection.firstNonNullOrThrow(
() -> "Couldn't find tag field on ItemInput",
CraftBukkitReflection.findField(ITEM_INPUT_CLASS, "c"),
CraftBukkitReflection.findField(ITEM_INPUT_CLASS, "tag")
);
private final ArgumentParser<C, ProtoItemStack> parser; private final ArgumentParser<C, ProtoItemStack> parser;

View file

@ -31,10 +31,12 @@ import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
import cloud.commandframework.bukkit.BukkitCommandManager; import cloud.commandframework.bukkit.BukkitCommandManager;
import cloud.commandframework.bukkit.data.ItemStackPredicate; import cloud.commandframework.bukkit.data.ItemStackPredicate;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection; import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.StringRange; import com.mojang.brigadier.context.StringRange;
import io.leangen.geantyref.TypeToken; import io.leangen.geantyref.TypeToken;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
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;
@ -142,13 +144,13 @@ public final class ItemStackPredicateArgument<C> extends CommandArgument<C, Item
private static final Class<?> CRAFT_ITEM_STACK_CLASS = private static final Class<?> CRAFT_ITEM_STACK_CLASS =
CraftBukkitReflection.needOBCClass("inventory.CraftItemStack"); CraftBukkitReflection.needOBCClass("inventory.CraftItemStack");
private static final Class<?> ARGUMENT_ITEM_PREDICATE_CLASS = CraftBukkitReflection.needNMSClassOrElse( private static final Class<?> ARGUMENT_ITEM_PREDICATE_CLASS =
"ArgumentItemPredicate", MinecraftArgumentTypes.getClassByKey(NamespacedKey.minecraft("item_predicate"));
"net.minecraft.commands.arguments.item.ArgumentItemPredicate" private static final Class<?> ARGUMENT_ITEM_PREDICATE_RESULT_CLASS = CraftBukkitReflection.firstNonNullOrThrow(
); () -> "Couldn't find ItemPredicateArgument$Result class",
private static final Class<?> ARGUMENT_ITEM_PREDICATE_RESULT_CLASS = CraftBukkitReflection.needNMSClassOrElse( CraftBukkitReflection.findNMSClass("ArgumentItemPredicate$b"),
"ArgumentItemPredicate$b", CraftBukkitReflection.findMCClass("commands.arguments.item.ArgumentItemPredicate$b"),
"net.minecraft.commands.arguments.item.ArgumentItemPredicate$b" CraftBukkitReflection.findMCClass("commands.arguments.item.ItemPredicateArgument$Result")
); );
private static final Method CREATE_PREDICATE_METHOD = CraftBukkitReflection.needMethod( private static final Method CREATE_PREDICATE_METHOD = CraftBukkitReflection.needMethod(
ARGUMENT_ITEM_PREDICATE_RESULT_CLASS, ARGUMENT_ITEM_PREDICATE_RESULT_CLASS,

View file

@ -28,7 +28,6 @@ import cloud.commandframework.arguments.CommandArgument;
import cloud.commandframework.brigadier.CloudBrigadierManager; import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.BukkitBrigadierMapper; import cloud.commandframework.bukkit.BukkitBrigadierMapper;
import cloud.commandframework.bukkit.internal.BukkitBackwardsBrigadierSenderMapper; import cloud.commandframework.bukkit.internal.BukkitBackwardsBrigadierSenderMapper;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
import cloud.commandframework.permission.CommandPermission; import cloud.commandframework.permission.CommandPermission;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
@ -58,11 +57,9 @@ class PaperBrigadierListener<C> implements Listener {
new BukkitBrigadierMapper<>(this.paperCommandManager, this.brigadierManager); new BukkitBrigadierMapper<>(this.paperCommandManager, this.brigadierManager);
if (CraftBukkitReflection.craftBukkit()) {
this.brigadierManager this.brigadierManager
.backwardsBrigadierSenderMapper(new BukkitBackwardsBrigadierSenderMapper<>(this.paperCommandManager)); .backwardsBrigadierSenderMapper(new BukkitBackwardsBrigadierSenderMapper<>(this.paperCommandManager));
} }
}
protected @NonNull CloudBrigadierManager<C, BukkitBrigadierCommandSource> brigadierManager() { protected @NonNull CloudBrigadierManager<C, BukkitBrigadierCommandSource> brigadierManager() {
return this.brigadierManager; return this.brigadierManager;