bukkit: Check class presence for CloudBukkitCapabilities instead of using Minecraft version

This commit is contained in:
Jason Penilla 2021-06-27 17:07:58 -07:00 committed by Jason
parent b163dce3c1
commit ab0a9299e4
4 changed files with 45 additions and 70 deletions

View file

@ -74,13 +74,16 @@ public final class BukkitBrigadierMapper<C> {
this.registerMappings(); this.registerMappings();
} }
@SuppressWarnings("unused")
private void registerMappings() { private void registerMappings() {
/* UUID nms argument is a 1.16+ feature */ /* UUID nms argument is a 1.16+ feature */
final Class<? extends ArgumentType<?>> uuid = MinecraftArgumentTypes.getClassByKey(NamespacedKey.minecraft("uuid")); try {
if (uuid != null) { final Class<? extends ArgumentType<?>> uuid = MinecraftArgumentTypes.getClassByKey(NamespacedKey.minecraft("uuid"));
/* Map UUID */ /* Map UUID */
this.mapSimpleNMS(new TypeToken<UUIDArgument.UUIDParser<C>>() { this.mapSimpleNMS(new TypeToken<UUIDArgument.UUIDParser<C>>() {
}, "uuid"); }, "uuid");
} catch (final IllegalArgumentException ignore) {
// < 1.16
} }
/* Map Enchantment */ /* Map Enchantment */
this.mapSimpleNMS(new TypeToken<EnchantmentArgument.EnchantmentParser<C>>() { this.mapSimpleNMS(new TypeToken<EnchantmentArgument.EnchantmentParser<C>>() {

View file

@ -32,7 +32,6 @@ 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.data.ProtoItemStack; import cloud.commandframework.bukkit.data.ProtoItemStack;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument; import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
import cloud.commandframework.bukkit.parsers.EnchantmentArgument; import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
import cloud.commandframework.bukkit.parsers.ItemStackArgument; import cloud.commandframework.bukkit.parsers.ItemStackArgument;
@ -52,7 +51,6 @@ import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.tasks.TaskFactory; import cloud.commandframework.tasks.TaskFactory;
import cloud.commandframework.tasks.TaskRecipe; import cloud.commandframework.tasks.TaskRecipe;
import io.leangen.geantyref.TypeToken; import io.leangen.geantyref.TypeToken;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
@ -65,12 +63,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.EnumSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* Command manager for the Bukkit platform * Command manager for the Bukkit platform
@ -80,14 +75,7 @@ import java.util.regex.Pattern;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class BukkitCommandManager<C> extends CommandManager<C> implements BrigadierManagerHolder<C> { public class BukkitCommandManager<C> extends CommandManager<C> implements BrigadierManagerHolder<C> {
private static final int VERSION_RADIX = 10;
private static final int BRIGADIER_MINIMUM_VERSION = 13;
private static final int PAPER_BRIGADIER_VERSION = 15;
private static final int ASYNC_TAB_MINIMUM_VERSION = 12;
private final Plugin owningPlugin; private final Plugin owningPlugin;
private final int minecraftVersion;
private final boolean paper = CraftBukkitReflection.classExists("com.destroystokyo.paper.PaperConfig");
private final Function<CommandSender, C> commandSenderMapper; private final Function<CommandSender, C> commandSenderMapper;
private final Function<C, CommandSender> backwardsCommandSenderMapper; private final Function<C, CommandSender> backwardsCommandSenderMapper;
@ -139,9 +127,6 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
final BukkitSynchronizer bukkitSynchronizer = new BukkitSynchronizer(owningPlugin); final BukkitSynchronizer bukkitSynchronizer = new BukkitSynchronizer(owningPlugin);
this.taskFactory = new TaskFactory(bukkitSynchronizer); this.taskFactory = new TaskFactory(bukkitSynchronizer);
/* Try to determine the Minecraft version */
this.minecraftVersion = this.getMinecraftVersion();
/* Register Bukkit Preprocessor */ /* Register Bukkit Preprocessor */
this.registerCommandPreProcessor(new BukkitCommandPreprocessor<>(this)); this.registerCommandPreProcessor(new BukkitCommandPreprocessor<>(this));
@ -173,7 +158,7 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
new MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<>()); new MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<>());
/* Register MC 1.13+ parsers */ /* Register MC 1.13+ parsers */
if (this.minecraftVersion >= BRIGADIER_MINIMUM_VERSION) { if (this.queryCapability(CloudBukkitCapabilities.BRIGADIER)) {
this.registerParserSupplierFor(ItemStackPredicateArgument.class); this.registerParserSupplierFor(ItemStackPredicateArgument.class);
this.registerParserSupplierFor(BlockPredicateArgument.class); this.registerParserSupplierFor(BlockPredicateArgument.class);
} }
@ -187,19 +172,6 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
this.setCaptionRegistry(new BukkitCaptionRegistryFactory<C>().create()); this.setCaptionRegistry(new BukkitCaptionRegistryFactory<C>().create());
} }
private int getMinecraftVersion() {
try {
final Matcher matcher = Pattern.compile("\\(MC: (\\d)\\.(\\d+)\\.?(\\d+?)?\\)").matcher(Bukkit.getVersion());
if (matcher.find()) {
return Integer.parseInt(matcher.toMatchResult().group(2), VERSION_RADIX);
}
} catch (final Exception e) {
this.owningPlugin.getLogger()
.severe("Failed to determine Minecraft version for cloud Bukkit capability detection");
}
return -1;
}
/** /**
* Create a command manager using Bukkit's {@link CommandSender} as the sender type. * Create a command manager using Bukkit's {@link CommandSender} as the sender type.
* *
@ -288,7 +260,9 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
if (!this.queryCapability(CloudBukkitCapabilities.BRIGADIER)) { if (!this.queryCapability(CloudBukkitCapabilities.BRIGADIER)) {
throw new BrigadierFailureException( throw new BrigadierFailureException(
BrigadierFailureReason.VERSION_TOO_LOW, BrigadierFailureReason.VERSION_TOO_LOW,
new IllegalArgumentException("Version: " + this.minecraftVersion) new IllegalArgumentException(
"Brigadier does not appear to be present on the currently running server. This is usually due to "
+ "running too old a version of Minecraft (Brigadier is implemented in 1.13 and newer).")
); );
} }
} }
@ -300,7 +274,7 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
* @return {@code true} if the manager has the given capability, else {@code false} * @return {@code true} if the manager has the given capability, else {@code false}
*/ */
public final boolean queryCapability(final @NonNull CloudBukkitCapabilities capability) { public final boolean queryCapability(final @NonNull CloudBukkitCapabilities capability) {
return this.queryCapabilities().contains(capability); return capability.capable();
} }
/** /**
@ -309,33 +283,7 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
* @return A set containing all capabilities of the instance * @return A set containing all capabilities of the instance
*/ */
public final @NonNull Set<@NonNull CloudBukkitCapabilities> queryCapabilities() { public final @NonNull Set<@NonNull CloudBukkitCapabilities> queryCapabilities() {
if (this.paper) { return CloudBukkitCapabilities.CAPABLE;
if (this.minecraftVersion >= ASYNC_TAB_MINIMUM_VERSION) {
if (this.minecraftVersion >= PAPER_BRIGADIER_VERSION) {
return EnumSet.of(
CloudBukkitCapabilities.NATIVE_BRIGADIER,
CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION,
CloudBukkitCapabilities.BRIGADIER
);
} else if (this.minecraftVersion >= BRIGADIER_MINIMUM_VERSION) {
return EnumSet.of(
CloudBukkitCapabilities.COMMODORE_BRIGADIER,
CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION,
CloudBukkitCapabilities.BRIGADIER
);
} else {
return EnumSet.of(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION);
}
}
} else {
if (this.minecraftVersion >= BRIGADIER_MINIMUM_VERSION) {
return EnumSet.of(
CloudBukkitCapabilities.COMMODORE_BRIGADIER,
CloudBukkitCapabilities.BRIGADIER
);
}
}
return EnumSet.noneOf(CloudBukkitCapabilities.class);
} }
/** /**
@ -424,7 +372,7 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
} }
final void lockIfBrigadierCapable() { final void lockIfBrigadierCapable() {
if (this.minecraftVersion >= BRIGADIER_MINIMUM_VERSION) { if (this.queryCapability(CloudBukkitCapabilities.BRIGADIER)) {
this.lockRegistration(); this.lockRegistration();
} }
} }

View file

@ -23,12 +23,38 @@
// //
package cloud.commandframework.bukkit; package cloud.commandframework.bukkit;
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
/** /**
* Capabilities for the Bukkit module * Capabilities for the Bukkit module
*/ */
public enum CloudBukkitCapabilities { public enum CloudBukkitCapabilities {
BRIGADIER, BRIGADIER(CraftBukkitReflection.classExists("com.mojang.brigadier.tree.CommandNode")
COMMODORE_BRIGADIER, && CraftBukkitReflection.findOBCClass("command.BukkitCommandWrapper") != null),
NATIVE_BRIGADIER,
ASYNCHRONOUS_COMPLETION NATIVE_BRIGADIER(CraftBukkitReflection.classExists(
"com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent")),
COMMODORE_BRIGADIER(BRIGADIER.capable() && !NATIVE_BRIGADIER.capable()),
ASYNCHRONOUS_COMPLETION(CraftBukkitReflection.classExists(
"com.destroystokyo.paper.event.server.AsyncTabCompleteEvent"));
static final Set<CloudBukkitCapabilities> CAPABLE = Arrays.stream(values())
.filter(CloudBukkitCapabilities::capable)
.collect(Collectors.toSet());
private final boolean capable;
CloudBukkitCapabilities(final boolean capable) {
this.capable = capable;
}
boolean capable() {
return this.capable;
}
} }

View file

@ -44,10 +44,8 @@ import cloud.commandframework.arguments.standard.StringArrayArgument;
import cloud.commandframework.bukkit.BukkitCommandManager; import cloud.commandframework.bukkit.BukkitCommandManager;
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.data.BlockPredicate;
import cloud.commandframework.bukkit.data.ItemStackPredicate; import cloud.commandframework.bukkit.data.ItemStackPredicate;
import cloud.commandframework.bukkit.data.ProtoItemStack; import cloud.commandframework.bukkit.data.ProtoItemStack;
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
import cloud.commandframework.bukkit.parsers.EnchantmentArgument; import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
import cloud.commandframework.bukkit.parsers.ItemStackArgument; import cloud.commandframework.bukkit.parsers.ItemStackArgument;
import cloud.commandframework.bukkit.parsers.ItemStackPredicateArgument; import cloud.commandframework.bukkit.parsers.ItemStackPredicateArgument;
@ -83,8 +81,6 @@ import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -386,8 +382,9 @@ public final class ExamplePlugin extends JavaPlugin {
))) )))
); );
// MC 1.13+ commands // MC 1.13+ commands todo: move to separate class
if (this.manager.queryCapability(CloudBukkitCapabilities.BRIGADIER)) { if (this.manager.queryCapability(CloudBukkitCapabilities.BRIGADIER)) {
/*
this.manager.command(builder.literal("replace") this.manager.command(builder.literal("replace")
.senderType(Player.class) .senderType(Player.class)
.argument(BlockPredicateArgument.of("predicate")) .argument(BlockPredicateArgument.of("predicate"))
@ -415,6 +412,7 @@ public final class ExamplePlugin extends JavaPlugin {
} }
}).execute(); }).execute();
})); }));
*/
this.manager.command(builder.literal("test_item") this.manager.command(builder.literal("test_item")
.argument(ItemStackArgument.of("item")) .argument(ItemStackArgument.of("item"))
.literal("is") .literal("is")