bukkit: Implement ItemStackArgument (#257)
Fully featured on 1.13+, falls back to Material parser on legacy versions. Also some general cleanup to the Bukkit impl
This commit is contained in:
parent
e5d6ce7b90
commit
e3cc7d43cb
20 changed files with 899 additions and 180 deletions
|
|
@ -4,4 +4,5 @@
|
|||
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||
<suppressions>
|
||||
<suppress checks="(?:(?:Member|Method)Name|DesignForExtension|Javadoc.*)" files=".*[\\/]mixin[\\/].*"/>
|
||||
<suppress checks="(?:Javadoc.*)" files=".*[\\/]CraftBukkitReflection.java"/>
|
||||
</suppressions>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
- JDA Role argument parser
|
||||
- Bukkit: Implement parser for ProtoItemStack ([#257](https://github.com/Incendo/cloud/pull/257))
|
||||
|
||||
### Changed
|
||||
- Use Command instead of TabCompleteEvent on Bukkit
|
||||
|
|
|
|||
|
|
@ -23,21 +23,25 @@
|
|||
//
|
||||
package cloud.commandframework.bukkit;
|
||||
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.arguments.standard.UUIDArgument;
|
||||
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.bukkit.parsers.location.Location2D;
|
||||
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
|
||||
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
|
||||
import cloud.commandframework.bukkit.parsers.ItemStackArgument;
|
||||
import cloud.commandframework.bukkit.parsers.location.Location2DArgument;
|
||||
import cloud.commandframework.bukkit.parsers.location.LocationArgument;
|
||||
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 com.mojang.brigadier.arguments.ArgumentType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import io.leangen.geantyref.GenericTypeReflector;
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
|
@ -46,14 +50,12 @@ import java.util.logging.Level;
|
|||
*
|
||||
* @param <C> Command sender type
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public final class BukkitBrigadierMapper<C> {
|
||||
|
||||
private static final int UUID_ARGUMENT_VERSION = 16;
|
||||
|
||||
private final BukkitCommandManager<C> commandManager;
|
||||
private final CloudBrigadierManager brigadierManager;
|
||||
private final String nmsVersion;
|
||||
private final CloudBrigadierManager<C, ?> brigadierManager;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -64,38 +66,48 @@ public final class BukkitBrigadierMapper<C> {
|
|||
*/
|
||||
public BukkitBrigadierMapper(
|
||||
final @NonNull BukkitCommandManager<C> commandManager,
|
||||
final @NonNull CloudBrigadierManager brigadierManager
|
||||
final @NonNull CloudBrigadierManager<C, ?> brigadierManager
|
||||
) {
|
||||
this.commandManager = commandManager;
|
||||
this.brigadierManager = brigadierManager;
|
||||
|
||||
/* Detect Minecraft Version Metadata */
|
||||
final String version = Bukkit.getServer().getClass().getPackage().getName();
|
||||
this.nmsVersion = version.substring(version.lastIndexOf(".") + 1);
|
||||
final int majorMinecraftVersion = Integer.parseInt(this.nmsVersion.split("_")[1]);
|
||||
if (!CraftBukkitReflection.craftBukkit()) {
|
||||
this.commandManager.getOwningPlugin().getLogger().warning(
|
||||
"Could not detect relocated CraftBukkit package, NMS brigadier mappings will not be enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.registerMappings();
|
||||
}
|
||||
|
||||
private void registerMappings() {
|
||||
/* UUID nms argument is a 1.16+ feature */
|
||||
if (majorMinecraftVersion >= UUID_ARGUMENT_VERSION) {
|
||||
if (CraftBukkitReflection.MAJOR_REVISION >= UUID_ARGUMENT_VERSION) {
|
||||
/* Map UUID */
|
||||
this.mapSimpleNMS(UUID.class, this.getNMSArgument("UUID").getConstructor());
|
||||
this.mapSimpleNMS(new TypeToken<UUIDArgument.UUIDParser<C>>() {
|
||||
}, "UUID");
|
||||
}
|
||||
/* Map Enchantment */
|
||||
this.mapSimpleNMS(Enchantment.class, this.getNMSArgument("Enchantment").getConstructor());
|
||||
this.mapSimpleNMS(new TypeToken<EnchantmentArgument.EnchantmentParser<C>>() {
|
||||
}, "Enchantment");
|
||||
/* Map ItemStackArgument */
|
||||
this.mapSimpleNMS(new TypeToken<ItemStackArgument.Parser<C>>() {
|
||||
}, "ItemStack");
|
||||
/* 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));
|
||||
this.mapNMS(new TypeToken<SingleEntitySelectorArgument.SingleEntitySelectorParser<C>>() {
|
||||
}, this.entitySelectorArgumentSupplier(true, false));
|
||||
this.mapNMS(new TypeToken<SinglePlayerSelectorArgument.SinglePlayerSelectorParser<C>>() {
|
||||
}, this.entitySelectorArgumentSupplier(true, true));
|
||||
this.mapNMS(new TypeToken<MultipleEntitySelectorArgument.MultipleEntitySelectorParser<C>>() {
|
||||
}, this.entitySelectorArgumentSupplier(false, false));
|
||||
this.mapNMS(new TypeToken<MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<C>>() {
|
||||
}, this.entitySelectorArgumentSupplier(false, true));
|
||||
/* Map Vec3 */
|
||||
this.mapComplexNMS(Location.class, this.getArgumentVec3());
|
||||
this.mapNMS(new TypeToken<LocationArgument.LocationParser<C>>() {
|
||||
}, this::argumentVec3);
|
||||
/* Map Vec2I */
|
||||
this.mapComplexNMS(Location2D.class, this.getArgumentVec2I());
|
||||
} catch (final Exception e) {
|
||||
this.commandManager.getOwningPlugin()
|
||||
.getLogger()
|
||||
.log(Level.WARNING, "Failed to map Bukkit types to NMS argument types", e);
|
||||
}
|
||||
this.mapNMS(new TypeToken<Location2DArgument.Location2DParser<C>>() {
|
||||
}, this::argumentVec2i);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -103,45 +115,39 @@ public final class BukkitBrigadierMapper<C> {
|
|||
* @param playersOnly Whether the selector is for players only (true), or for all entities (false)
|
||||
* @return The NMS ArgumentType
|
||||
*/
|
||||
private @NonNull Supplier<ArgumentType<?>> getEntitySelectorArgument(
|
||||
private @NonNull Supplier<ArgumentType<?>> entitySelectorArgumentSupplier(
|
||||
final boolean single,
|
||||
final boolean playersOnly
|
||||
) {
|
||||
return () -> {
|
||||
try {
|
||||
final Constructor<?> constructor = this.getNMSArgument("Entity").getDeclaredConstructors()[0];
|
||||
final Constructor<?> constructor = getNMSArgument("Entity").getDeclaredConstructors()[0];
|
||||
constructor.setAccessible(true);
|
||||
return (ArgumentType<?>) constructor.newInstance(single, playersOnly);
|
||||
} catch (final Exception e) {
|
||||
this.commandManager.getOwningPlugin().getLogger().log(Level.INFO, "Failed to retrieve Selector Argument", e);
|
||||
return null;
|
||||
return fallbackType();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryLambda")
|
||||
private @NonNull Supplier<ArgumentType<?>> getArgumentVec3() {
|
||||
return () -> {
|
||||
private @NonNull ArgumentType<?> argumentVec3() {
|
||||
try {
|
||||
return (ArgumentType<?>) this.getNMSArgument("Vec3").getDeclaredConstructor(boolean.class)
|
||||
return (ArgumentType<?>) getNMSArgument("Vec3").getDeclaredConstructor(boolean.class)
|
||||
.newInstance(true);
|
||||
} catch (final Exception e) {
|
||||
this.commandManager.getOwningPlugin().getLogger().log(Level.INFO, "Failed to retrieve Vec3D argument", e);
|
||||
return null;
|
||||
return fallbackType();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryLambda")
|
||||
private @NonNull Supplier<ArgumentType<?>> getArgumentVec2I() {
|
||||
return () -> {
|
||||
private @NonNull ArgumentType<?> argumentVec2i() {
|
||||
try {
|
||||
return (ArgumentType<?>) this.getNMSArgument("Vec2I").getDeclaredConstructor().newInstance();
|
||||
return (ArgumentType<?>) getNMSArgument("Vec2I").getDeclaredConstructor().newInstance();
|
||||
} catch (final Exception e) {
|
||||
this.commandManager.getOwningPlugin().getLogger().log(Level.INFO, "Failed to retrieve Vec2I argument", e);
|
||||
return null;
|
||||
return fallbackType();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -149,40 +155,52 @@ public final class BukkitBrigadierMapper<C> {
|
|||
*
|
||||
* @param argument Argument type name
|
||||
* @return Argument class
|
||||
* @throws Exception If the type cannot be retrieved
|
||||
* @throws RuntimeException when the class is not found
|
||||
*/
|
||||
@NonNull
|
||||
private Class<?> getNMSArgument(final @NonNull String argument) throws Exception {
|
||||
return Class.forName(String.format("net.minecraft.server.%s.Argument%s", this.nmsVersion, argument));
|
||||
private static @NonNull Class<?> getNMSArgument(final @NonNull String argument) throws RuntimeException {
|
||||
return CraftBukkitReflection.needNMSClass("Argument" + argument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register a mapping between a type and a NMS argument type
|
||||
* Attempt to register a mapping between a cloud argument parser type and an NMS brigadier argument type which
|
||||
* has a no-args constructor.
|
||||
*
|
||||
* @param type Type to map
|
||||
* @param constructor Constructor that construct the NMS argument type
|
||||
* @param <T> argument parser type
|
||||
* @param argumentName NMS Argument class name (without 'Argument' prefix)
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public void mapSimpleNMS(
|
||||
final @NonNull Class<?> type,
|
||||
final @NonNull Constructor<?> constructor
|
||||
public <T extends ArgumentParser<C, ?>> void mapSimpleNMS(
|
||||
final @NonNull TypeToken<T> type,
|
||||
final @NonNull String argumentName
|
||||
) {
|
||||
final Constructor<?> constructor;
|
||||
try {
|
||||
this.brigadierManager.registerDefaultArgumentTypeSupplier(type, () -> {
|
||||
final Class<?> nmsArgument = getNMSArgument(argumentName);
|
||||
constructor = nmsArgument.getConstructor();
|
||||
} catch (final RuntimeException | ReflectiveOperationException e) {
|
||||
this.commandManager.getOwningPlugin().getLogger().log(
|
||||
Level.WARNING,
|
||||
String.format("Failed to create mapping for NMS brigadier argument type '%s'.", argumentName),
|
||||
e
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.brigadierManager.registerMapping(type, builder -> builder.to(argument -> {
|
||||
try {
|
||||
return constructor.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
} catch (final Exception e) {
|
||||
this.commandManager.getOwningPlugin()
|
||||
.getLogger()
|
||||
.warning(String.format(
|
||||
"Failed to map '%s' to a Mojang serializable argument type",
|
||||
type.getCanonicalName()
|
||||
));
|
||||
return (ArgumentType<?>) constructor.newInstance();
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
this.commandManager.getOwningPlugin().getLogger().log(
|
||||
Level.WARNING,
|
||||
String.format(
|
||||
"Failed to create instance of brigadier argument type '%s'.",
|
||||
GenericTypeReflector.erase(type.getType()).getCanonicalName()
|
||||
),
|
||||
e
|
||||
);
|
||||
return fallbackType();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -190,21 +208,61 @@ public final class BukkitBrigadierMapper<C> {
|
|||
*
|
||||
* @param type Type to map
|
||||
* @param argumentTypeSupplier Supplier of the NMS argument type
|
||||
* @param <T> argument parser type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public <T extends ArgumentParser<C, ?>> void mapNMS(
|
||||
final @NonNull TypeToken<T> type,
|
||||
final @NonNull Supplier<ArgumentType<?>> argumentTypeSupplier
|
||||
) {
|
||||
this.brigadierManager.registerMapping(type, builder ->
|
||||
builder.to(argument -> argumentTypeSupplier.get())
|
||||
);
|
||||
}
|
||||
|
||||
private static @NonNull StringArgumentType fallbackType() {
|
||||
return StringArgumentType.word();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register a mapping between a type and a NMS argument type
|
||||
*
|
||||
* @param type Type to map
|
||||
* @param constructor Constructor that construct the NMS argument type
|
||||
* @deprecated use {@link #mapSimpleNMS(TypeToken, String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void mapSimpleNMS(
|
||||
final @NonNull Class<?> type,
|
||||
final @NonNull Constructor<?> constructor
|
||||
) {
|
||||
this.brigadierManager.registerDefaultArgumentTypeSupplier(type, () -> {
|
||||
try {
|
||||
return (ArgumentType<?>) constructor.newInstance();
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
this.commandManager.getOwningPlugin().getLogger().log(
|
||||
Level.WARNING,
|
||||
String.format("Failed to map brigadier argument type '%s'", type.getCanonicalName()),
|
||||
e
|
||||
);
|
||||
return fallbackType();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @deprecated use {@link #mapNMS(TypeToken, Supplier)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void mapComplexNMS(
|
||||
final @NonNull Class<?> type,
|
||||
final @NonNull Supplier<ArgumentType<?>> argumentTypeSupplier
|
||||
) {
|
||||
try {
|
||||
this.brigadierManager.registerDefaultArgumentTypeSupplier(type, argumentTypeSupplier);
|
||||
} catch (final Exception e) {
|
||||
this.commandManager.getOwningPlugin()
|
||||
.getLogger()
|
||||
.warning(String.format(
|
||||
"Failed to map '%s' to a Mojang serializable argument type",
|
||||
type.getCanonicalName()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2021 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.keys.CloudKey;
|
||||
import cloud.commandframework.keys.SimpleCloudKey;
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Bukkit related {@link cloud.commandframework.context.CommandContext} keys.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class BukkitCommandContextKeys {
|
||||
|
||||
/**
|
||||
* Key used to store the Bukkit native {@link CommandSender} in the {@link cloud.commandframework.context.CommandContext}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final CloudKey<CommandSender> BUKKIT_COMMAND_SENDER = SimpleCloudKey.of(
|
||||
"BukkitCommandSender",
|
||||
TypeToken.get(CommandSender.class)
|
||||
);
|
||||
|
||||
/**
|
||||
* Key used to store the active {@link CloudBukkitCapabilities} in the {@link cloud.commandframework.context.CommandContext}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final CloudKey<Set<CloudBukkitCapabilities>> CLOUD_BUKKIT_CAPABILITIES = SimpleCloudKey.of(
|
||||
"CloudBukkitCapabilities",
|
||||
new TypeToken<Set<CloudBukkitCapabilities>>() {
|
||||
}
|
||||
);
|
||||
|
||||
private BukkitCommandContextKeys() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,7 +31,10 @@ 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.data.ProtoItemStack;
|
||||
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
|
||||
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
|
||||
import cloud.commandframework.bukkit.parsers.ItemStackArgument;
|
||||
import cloud.commandframework.bukkit.parsers.MaterialArgument;
|
||||
import cloud.commandframework.bukkit.parsers.OfflinePlayerArgument;
|
||||
import cloud.commandframework.bukkit.parsers.PlayerArgument;
|
||||
|
|
@ -81,7 +84,7 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
|
|||
|
||||
private final Plugin owningPlugin;
|
||||
private final int minecraftVersion;
|
||||
private final boolean paper;
|
||||
private final boolean paper = CraftBukkitReflection.classExists("com.destroystokyo.paper.PaperConfig");
|
||||
|
||||
private final Function<CommandSender, C> commandSenderMapper;
|
||||
private final Function<C, CommandSender> backwardsCommandSenderMapper;
|
||||
|
|
@ -134,30 +137,7 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
|
|||
this.taskFactory = new TaskFactory(bukkitSynchronizer);
|
||||
|
||||
/* Try to determine the Minecraft version */
|
||||
int version = -1;
|
||||
try {
|
||||
final Matcher matcher = Pattern.compile("\\(MC: (\\d)\\.(\\d+)\\.?(\\d+?)?\\)")
|
||||
.matcher(Bukkit.getVersion());
|
||||
if (matcher.find()) {
|
||||
version = 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");
|
||||
}
|
||||
this.minecraftVersion = version;
|
||||
|
||||
boolean paper = false;
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.PaperConfig");
|
||||
paper = true;
|
||||
} catch (final Exception ignored) {
|
||||
// This is fine
|
||||
}
|
||||
this.paper = paper;
|
||||
this.minecraftVersion = this.getMinecraftVersion();
|
||||
|
||||
/* Register Bukkit Preprocessor */
|
||||
this.registerCommandPreProcessor(new BukkitCommandPreprocessor<>(this));
|
||||
|
|
@ -177,6 +157,8 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
|
|||
new LocationArgument.LocationParser<>());
|
||||
this.getParserRegistry().registerParserSupplier(TypeToken.get(Location2D.class), parserParameters ->
|
||||
new Location2DArgument.Location2DParser<>());
|
||||
this.getParserRegistry().registerParserSupplier(TypeToken.get(ProtoItemStack.class), parserParameters ->
|
||||
new ItemStackArgument.Parser<>());
|
||||
/* Register Entity Selector Parsers */
|
||||
this.getParserRegistry().registerParserSupplier(TypeToken.get(SingleEntitySelector.class), parserParameters ->
|
||||
new SingleEntitySelectorArgument.SingleEntitySelectorParser<>());
|
||||
|
|
@ -196,6 +178,19 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext
|
|||
import cloud.commandframework.execution.preprocessor.CommandPreprocessor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Command preprocessor which decorates incoming {@link cloud.commandframework.context.CommandContext}
|
||||
* with Bukkit specific objects
|
||||
|
|
@ -35,26 +37,29 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
*/
|
||||
final class BukkitCommandPreprocessor<C> implements CommandPreprocessor<C> {
|
||||
|
||||
private final BukkitCommandManager<C> mgr;
|
||||
private final BukkitCommandManager<C> commandManager;
|
||||
private final Set<CloudBukkitCapabilities> bukkitCapabilities;
|
||||
|
||||
/**
|
||||
* The Bukkit Command Preprocessor for storing Bukkit-specific contexts in the command contexts
|
||||
*
|
||||
* @param mgr The BukkitCommandManager
|
||||
* @param commandManager The BukkitCommandManager
|
||||
*/
|
||||
BukkitCommandPreprocessor(final @NonNull BukkitCommandManager<C> mgr) {
|
||||
this.mgr = mgr;
|
||||
BukkitCommandPreprocessor(final @NonNull BukkitCommandManager<C> commandManager) {
|
||||
this.commandManager = commandManager;
|
||||
this.bukkitCapabilities = commandManager.queryCapabilities();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(final @NonNull CommandPreprocessingContext<C> context) {
|
||||
context.getCommandContext().store("BukkitCommandSender", this.mgr.getBackwardsCommandSenderMapper().apply(
|
||||
context.getCommandContext().getSender()));
|
||||
context.getCommandContext().store("CloudBukkitCapabilities", this.mgr.queryCapabilities());
|
||||
context.getCommandContext().store(
|
||||
BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER,
|
||||
this.commandManager.getBackwardsCommandSenderMapper().apply(context.getCommandContext().getSender())
|
||||
);
|
||||
context.getCommandContext().store(
|
||||
BukkitCommandContextKeys.CLOUD_BUKKIT_CAPABILITIES,
|
||||
this.bukkitCapabilities
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ package cloud.commandframework.bukkit;
|
|||
|
||||
import cloud.commandframework.Command;
|
||||
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.permission.CommandPermission;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import me.lucko.commodore.Commodore;
|
||||
|
|
@ -36,13 +36,14 @@ import org.bukkit.command.CommandSender;
|
|||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
class CloudCommodoreManager<C> extends BukkitPluginRegistrationHandler<C> {
|
||||
|
||||
private final BukkitCommandManager<C> commandManager;
|
||||
private final CloudBrigadierManager brigadierManager;
|
||||
private final CloudBrigadierManager<C, Object> brigadierManager;
|
||||
private final Commodore commodore;
|
||||
|
||||
CloudCommodoreManager(final @NonNull BukkitCommandManager<C> commandManager)
|
||||
|
|
@ -53,17 +54,29 @@ class CloudCommodoreManager<C> extends BukkitPluginRegistrationHandler<C> {
|
|||
}
|
||||
this.commandManager = commandManager;
|
||||
this.commodore = CommodoreProvider.getCommodore(commandManager.getOwningPlugin());
|
||||
this.brigadierManager = new CloudBrigadierManager<>(commandManager, () ->
|
||||
new CommandContext<>(
|
||||
this.brigadierManager = new CloudBrigadierManager<>(commandManager, () -> new CommandContext<>(
|
||||
commandManager.getCommandSenderMapper().apply(Bukkit.getConsoleSender()),
|
||||
commandManager
|
||||
));
|
||||
this.brigadierManager.brigadierSenderMapper(
|
||||
sender -> this.commandManager.getCommandSenderMapper().apply(
|
||||
this.commodore.getBukkitSender(sender)
|
||||
)
|
||||
);
|
||||
|
||||
this.brigadierManager.brigadierSenderMapper(sender ->
|
||||
this.commandManager.getCommandSenderMapper().apply(this.commodore.getBukkitSender(sender)));
|
||||
|
||||
new BukkitBrigadierMapper<>(this.commandManager, this.brigadierManager);
|
||||
|
||||
if (!CraftBukkitReflection.craftBukkit()) {
|
||||
return;
|
||||
}
|
||||
final Class<?> vanillaCommandWrapperClass = CraftBukkitReflection.needOBCClass("command.VanillaCommandWrapper");
|
||||
final Method getListenerMethod = CraftBukkitReflection.needMethod(
|
||||
vanillaCommandWrapperClass, "getListener", CommandSender.class);
|
||||
this.brigadierManager.backwardsBrigadierSenderMapper(cloud -> {
|
||||
try {
|
||||
return getListenerMethod.invoke(null, this.commandManager.getBackwardsCommandSenderMapper().apply(cloud));
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -72,7 +85,7 @@ class CloudCommodoreManager<C> extends BukkitPluginRegistrationHandler<C> {
|
|||
final @NonNull Command<?> command,
|
||||
final @NonNull BukkitCommand<C> bukkitCommand
|
||||
) {
|
||||
this.registerWithCommodore(label, command);
|
||||
this.registerWithCommodore(label, (Command<C>) command);
|
||||
}
|
||||
|
||||
protected @NonNull CloudBrigadierManager brigadierManager() {
|
||||
|
|
@ -81,17 +94,13 @@ class CloudCommodoreManager<C> extends BukkitPluginRegistrationHandler<C> {
|
|||
|
||||
private void registerWithCommodore(
|
||||
final @NonNull String label,
|
||||
final @NonNull Command<?> command
|
||||
final @NonNull Command<C> command
|
||||
) {
|
||||
final com.mojang.brigadier.Command<?> cmd = o -> 1;
|
||||
final LiteralCommandNode<?> literalCommandNode = this.brigadierManager
|
||||
.createLiteralCommandNode(label, command, (o, p) -> {
|
||||
final CommandSender sender = this.commodore.getBukkitSender(o);
|
||||
return this.commandManager.hasPermission(
|
||||
this.commandManager.getCommandSenderMapper().apply(sender),
|
||||
(CommandPermission) p
|
||||
);
|
||||
}, false, cmd);
|
||||
return this.commandManager.hasPermission(this.commandManager.getCommandSenderMapper().apply(sender), p);
|
||||
}, false, o -> 1);
|
||||
final CommandNode existingNode = this.commodore.getDispatcher().findNode(Collections.singletonList(label));
|
||||
if (existingNode != null) {
|
||||
this.mergeChildren(existingNode, literalCommandNode);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2021 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.data;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Intermediary result for an argument which parses a {@link Material} and optional NBT data.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface ProtoItemStack {
|
||||
|
||||
/**
|
||||
* Get the {@link Material} of this {@link ProtoItemStack}.
|
||||
*
|
||||
* @return the {@link Material}
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@NonNull Material material();
|
||||
|
||||
/**
|
||||
* Get whether this {@link ProtoItemStack} contains extra data besides the {@link Material}.
|
||||
*
|
||||
* @return whether there is extra data
|
||||
*/
|
||||
boolean hasExtraData();
|
||||
|
||||
/**
|
||||
* Create a new {@link ItemStack} from the state of this {@link ProtoItemStack}.
|
||||
*
|
||||
* @param stackSize stack size
|
||||
* @param respectMaximumStackSize whether to respect the maximum stack size for the material
|
||||
* @return the created {@link ItemStack}
|
||||
* @throws IllegalArgumentException if the {@link ItemStack} could not be created, due to max stack size or other reasons
|
||||
*/
|
||||
@NonNull ItemStack createItemStack(int stackSize, boolean respectMaximumStackSize)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2021 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.
|
||||
//
|
||||
/**
|
||||
* cloud-bukkit data holders
|
||||
*/
|
||||
package cloud.commandframework.bukkit.data;
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2021 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.internal;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Utilities for doing reflection on CraftBukkit, used by the cloud implementation.
|
||||
*
|
||||
* <p>This is not API to any extent, and as such, may break, change, or be removed without any notice.</p>
|
||||
*/
|
||||
@Beta
|
||||
public final class CraftBukkitReflection {
|
||||
|
||||
private static final String PREFIX_NMS = "net.minecraft.server";
|
||||
private static final String PREFIX_CRAFTBUKKIT = "org.bukkit.craftbukkit";
|
||||
private static final String CRAFT_SERVER = "CraftServer";
|
||||
private static final String VERSION;
|
||||
public static final int MAJOR_REVISION;
|
||||
|
||||
static {
|
||||
final Class<?> serverClass = Bukkit.getServer().getClass();
|
||||
final String pkg = serverClass.getPackage().getName();
|
||||
final String nmsVersion = pkg.substring(pkg.lastIndexOf(".") + 1);
|
||||
if (!nmsVersion.contains("_")) {
|
||||
MAJOR_REVISION = -1;
|
||||
VERSION = null;
|
||||
} else {
|
||||
MAJOR_REVISION = Integer.parseInt(nmsVersion.split("_")[1]);
|
||||
String name = serverClass.getName();
|
||||
name = name.substring(PREFIX_CRAFTBUKKIT.length());
|
||||
name = name.substring(0, name.length() - CRAFT_SERVER.length());
|
||||
VERSION = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean craftBukkit() {
|
||||
return MAJOR_REVISION != -1 && VERSION != null;
|
||||
}
|
||||
|
||||
public static @NonNull Class<?> needNMSClass(final @NonNull String className) throws RuntimeException {
|
||||
return needClass(PREFIX_NMS + VERSION + className);
|
||||
}
|
||||
|
||||
public static @NonNull Class<?> needOBCClass(final @NonNull String className) throws RuntimeException {
|
||||
return needClass(PREFIX_CRAFTBUKKIT + VERSION + className);
|
||||
}
|
||||
|
||||
public static @NonNull Class<?> needClass(final @NonNull String className) throws RuntimeException {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (final ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable Class<?> findClass(final @NonNull String className) {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (final ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull Field needField(final @NonNull Class<?> holder, final @NonNull String name) throws RuntimeException {
|
||||
try {
|
||||
final Field field = holder.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean classExists(final @NonNull String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull Method needMethod(
|
||||
final @NonNull Class<?> holder,
|
||||
final @NonNull String name,
|
||||
final @NonNull Class<?>... params
|
||||
) throws RuntimeException {
|
||||
try {
|
||||
return holder.getMethod(name, params);
|
||||
} catch (final NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private CraftBukkitReflection() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2021 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.ArgumentDescription;
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
|
||||
import cloud.commandframework.bukkit.BukkitCommandManager;
|
||||
import cloud.commandframework.bukkit.data.ProtoItemStack;
|
||||
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Queue;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Argument type for parsing a {@link Material} and optional extra NBT data into a {@link ProtoItemStack}.
|
||||
*
|
||||
* <p>This argument type only provides basic suggestions by default. On Minecraft 1.13 and newer, enabling Brigadier
|
||||
* compatibility through {@link BukkitCommandManager#registerBrigadier()} will allow client side validation and
|
||||
* suggestions to be utilized.</p>
|
||||
*
|
||||
* @param <C> Command sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class ItemStackArgument<C> extends CommandArgument<C, ProtoItemStack> {
|
||||
|
||||
private ItemStackArgument(
|
||||
final boolean required,
|
||||
final @NonNull String name,
|
||||
final @NonNull String defaultValue,
|
||||
final @Nullable BiFunction<@NonNull CommandContext<C>, @NonNull String,
|
||||
@NonNull List<@NonNull String>> suggestionsProvider,
|
||||
final @NonNull ArgumentDescription defaultDescription
|
||||
) {
|
||||
super(required, name, new Parser<>(), defaultValue, ProtoItemStack.class, suggestionsProvider, defaultDescription);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Builder}.
|
||||
*
|
||||
* @param name Name of the argument
|
||||
* @param <C> Command sender type
|
||||
* @return Created builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> ItemStackArgument.@NonNull Builder<C> builder(final @NonNull String name) {
|
||||
return new ItemStackArgument.Builder<>(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required {@link ItemStackArgument}.
|
||||
*
|
||||
* @param name Argument name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull CommandArgument<C, ProtoItemStack> of(final @NonNull String name) {
|
||||
return ItemStackArgument.<C>builder(name).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional {@link ItemStackArgument}.
|
||||
*
|
||||
* @param name Argument name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull CommandArgument<C, ProtoItemStack> optional(final @NonNull String name) {
|
||||
return ItemStackArgument.<C>builder(name).asOptional().build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builder for {@link ItemStackArgument}.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class Builder<C> extends TypedBuilder<C, ProtoItemStack, Builder<C>> {
|
||||
|
||||
private Builder(final @NonNull String name) {
|
||||
super(ProtoItemStack.class, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStackArgument<C> build() {
|
||||
return new ItemStackArgument<>(
|
||||
this.isRequired(),
|
||||
this.getName(),
|
||||
this.getDefaultValue(),
|
||||
this.getSuggestionsProvider(),
|
||||
this.getDefaultDescription()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser for {@link ProtoItemStack}. Requires a CraftBukkit based server implementation.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class Parser<C> implements ArgumentParser<C, ProtoItemStack> {
|
||||
|
||||
private final ArgumentParser<C, ProtoItemStack> parser;
|
||||
|
||||
/**
|
||||
* Create a new {@link Parser}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public Parser() {
|
||||
if (!CraftBukkitReflection.craftBukkit()) {
|
||||
throw new UnsupportedOperationException("ItemStack parser requires CraftBukkit");
|
||||
}
|
||||
if (CraftBukkitReflection.MAJOR_REVISION >= 13) {
|
||||
this.parser = new ModernParser<>();
|
||||
} else {
|
||||
this.parser = new LegacyParser<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ArgumentParseResult<ProtoItemStack> parse(
|
||||
final @NonNull CommandContext<C> commandContext,
|
||||
final @NonNull Queue<@NonNull String> inputQueue
|
||||
) {
|
||||
return this.parser.parse(commandContext, inputQueue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<@NonNull String> suggestions(
|
||||
final @NonNull CommandContext<C> commandContext,
|
||||
final @NonNull String input
|
||||
) {
|
||||
return Arrays.stream(Material.values())
|
||||
.map(value -> value.name().toLowerCase(Locale.ROOT))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class ModernParser<C> implements ArgumentParser<C, ProtoItemStack> {
|
||||
|
||||
private static final Class<?> NMS_ITEM_STACK_CLASS = CraftBukkitReflection.needNMSClass("ItemStack");
|
||||
private static final Class<?> CRAFT_ITEM_STACK_CLASS =
|
||||
CraftBukkitReflection.needOBCClass("inventory.CraftItemStack");
|
||||
private static final Class<?> ARGUMENT_ITEM_STACK_CLASS =
|
||||
CraftBukkitReflection.needNMSClass("ArgumentItemStack");
|
||||
private static final Class<?> ARGUMENT_PREDICATE_ITEM_STACK_CLASS =
|
||||
CraftBukkitReflection.needNMSClass("ArgumentPredicateItemStack");
|
||||
private static final Class<?> NMS_ITEM_CLASS = CraftBukkitReflection.needNMSClass("Item");
|
||||
private static final Class<?> CRAFT_MAGIC_NUMBERS_CLASS =
|
||||
CraftBukkitReflection.needOBCClass("util.CraftMagicNumbers");
|
||||
private static final Method GET_MATERIAL_METHOD = CraftBukkitReflection
|
||||
.needMethod(CRAFT_MAGIC_NUMBERS_CLASS, "getMaterial", NMS_ITEM_CLASS);
|
||||
private static final Method CREATE_ITEM_STACK_METHOD = CraftBukkitReflection
|
||||
.needMethod(ARGUMENT_PREDICATE_ITEM_STACK_CLASS, "a", int.class, boolean.class);
|
||||
private static final Method AS_BUKKIT_COPY_METHOD = CraftBukkitReflection
|
||||
.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 COMPOUND_TAG_FIELD = CraftBukkitReflection.needField(ARGUMENT_PREDICATE_ITEM_STACK_CLASS, "c");
|
||||
|
||||
private final ArgumentParser<C, ProtoItemStack> parser;
|
||||
|
||||
ModernParser() {
|
||||
try {
|
||||
this.parser = this.createParser();
|
||||
} catch (final ReflectiveOperationException ex) {
|
||||
throw new RuntimeException("Failed to initialize modern ItemStack parser.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ArgumentParser<C, ProtoItemStack> createParser() throws ReflectiveOperationException {
|
||||
return new WrappedBrigadierParser<C, Object>(
|
||||
(ArgumentType<Object>) ARGUMENT_ITEM_STACK_CLASS.getConstructor().newInstance()
|
||||
).map((ctx, itemInput) -> ArgumentParseResult.success(new ModernProtoItemStack(itemInput)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ArgumentParseResult<@NonNull ProtoItemStack> parse(
|
||||
@NonNull final CommandContext<@NonNull C> commandContext,
|
||||
@NonNull final Queue<@NonNull String> inputQueue
|
||||
) {
|
||||
// Minecraft has a parser for this - just use it
|
||||
return this.parser.parse(commandContext, inputQueue);
|
||||
}
|
||||
|
||||
private static final class ModernProtoItemStack implements ProtoItemStack {
|
||||
|
||||
private final Object itemInput;
|
||||
private final Material material;
|
||||
private final @Nullable String snbt;
|
||||
|
||||
ModernProtoItemStack(final @NonNull Object itemInput) {
|
||||
this.itemInput = itemInput;
|
||||
try {
|
||||
this.material = (Material) GET_MATERIAL_METHOD.invoke(null, ITEM_FIELD.get(itemInput));
|
||||
final Object compoundTag = COMPOUND_TAG_FIELD.get(itemInput);
|
||||
if (compoundTag != null) {
|
||||
this.snbt = compoundTag.toString();
|
||||
} else {
|
||||
this.snbt = null;
|
||||
}
|
||||
} catch (final ReflectiveOperationException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Material material() {
|
||||
return this.material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExtraData() {
|
||||
return this.snbt != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack createItemStack(final int stackSize, final boolean respectMaximumStackSize) {
|
||||
try {
|
||||
return (ItemStack) AS_BUKKIT_COPY_METHOD.invoke(
|
||||
null,
|
||||
CREATE_ITEM_STACK_METHOD.invoke(this.itemInput, stackSize, respectMaximumStackSize)
|
||||
);
|
||||
} catch (final InvocationTargetException ex) {
|
||||
final Throwable cause = ex.getCause();
|
||||
if (cause instanceof CommandSyntaxException) {
|
||||
throw new IllegalArgumentException(cause.getMessage(), cause);
|
||||
}
|
||||
throw new RuntimeException(ex);
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class LegacyParser<C> implements ArgumentParser<C, ProtoItemStack> {
|
||||
|
||||
private final ArgumentParser<C, ProtoItemStack> parser = new MaterialArgument.MaterialParser<C>()
|
||||
.map((ctx, material) -> ArgumentParseResult.success(new LegacyProtoItemStack(material)));
|
||||
|
||||
@Override
|
||||
public @NonNull ArgumentParseResult<@NonNull ProtoItemStack> parse(
|
||||
@NonNull final CommandContext<@NonNull C> commandContext,
|
||||
@NonNull final Queue<@NonNull String> inputQueue
|
||||
) {
|
||||
return this.parser.parse(commandContext, inputQueue);
|
||||
}
|
||||
|
||||
private static final class LegacyProtoItemStack implements ProtoItemStack {
|
||||
|
||||
private final Material material;
|
||||
|
||||
private LegacyProtoItemStack(final @NonNull Material material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Material material() {
|
||||
return this.material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExtraData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack createItemStack(final int stackSize, final boolean respectMaximumStackSize)
|
||||
throws IllegalArgumentException {
|
||||
if (respectMaximumStackSize && stackSize > this.material.getMaxStackSize()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"The maximum stack size for %s is %d",
|
||||
this.material,
|
||||
this.material.getMaxStackSize()
|
||||
));
|
||||
}
|
||||
return new ItemStack(this.material, stackSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,12 +28,14 @@ import cloud.commandframework.arguments.CommandArgument;
|
|||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCaptionKeys;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.captions.CaptionVariable;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||
import cloud.commandframework.exceptions.parsing.ParserException;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
|
@ -177,6 +179,10 @@ public final class OfflinePlayerArgument<C> extends CommandArgument<C, OfflinePl
|
|||
List<String> output = new ArrayList<>();
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
final CommandSender bukkit = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
|
||||
if (bukkit instanceof Player && !((Player) bukkit).canSee(player)) {
|
||||
continue;
|
||||
}
|
||||
output.add(player.getName());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,13 @@ import cloud.commandframework.arguments.CommandArgument;
|
|||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCaptionKeys;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.captions.CaptionVariable;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||
import cloud.commandframework.exceptions.parsing.ParserException;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
|
@ -169,6 +171,10 @@ public final class PlayerArgument<C> extends CommandArgument<C, Player> {
|
|||
List<String> output = new ArrayList<>();
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
final CommandSender bukkit = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
|
||||
if (bukkit instanceof Player && !((Player) bukkit).canSee(player)) {
|
||||
continue;
|
||||
}
|
||||
output.add(player.getName());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import cloud.commandframework.ArgumentDescription;
|
|||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.bukkit.parsers.location.LocationArgument.LocationParseException;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
|
|
@ -183,7 +184,7 @@ public final class Location2DArgument<C> extends CommandArgument<C, Location2D>
|
|||
coordinates[i] = coordinate.getParsedValue().orElseThrow(NullPointerException::new);
|
||||
}
|
||||
final Location originalLocation;
|
||||
final CommandSender bukkitSender = commandContext.get("BukkitCommandSender");
|
||||
final CommandSender bukkitSender = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
|
||||
|
||||
if (bukkitSender instanceof BlockCommandSender) {
|
||||
originalLocation = ((BlockCommandSender) bukkitSender).getBlock().getLocation();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
|||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.arguments.standard.IntegerArgument;
|
||||
import cloud.commandframework.bukkit.BukkitCaptionKeys;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.captions.Caption;
|
||||
import cloud.commandframework.captions.CaptionVariable;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
|
|
@ -191,7 +192,7 @@ public final class LocationArgument<C> extends CommandArgument<C, Location> {
|
|||
coordinates[i] = coordinate.getParsedValue().orElseThrow(NullPointerException::new);
|
||||
}
|
||||
final Location originalLocation;
|
||||
final CommandSender bukkitSender = commandContext.get("BukkitCommandSender");
|
||||
final CommandSender bukkitSender = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
|
||||
|
||||
if (bukkitSender instanceof BlockCommandSender) {
|
||||
originalLocation = ((BlockCommandSender) bukkitSender).getBlock().getLocation();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import cloud.commandframework.ArgumentDescription;
|
|||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||
import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
|
|
@ -38,7 +39,6 @@ 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<C> extends CommandArgument<C, MultipleEntitySelector> {
|
||||
|
|
@ -133,7 +133,7 @@ public final class MultipleEntitySelectorArgument<C> extends CommandArgument<C,
|
|||
final @NonNull CommandContext<C> commandContext,
|
||||
final @NonNull Queue<@NonNull String> inputQueue
|
||||
) {
|
||||
if (!commandContext.<Set<CloudBukkitCapabilities>>get("CloudBukkitCapabilities").contains(
|
||||
if (!commandContext.get(BukkitCommandContextKeys.CLOUD_BUKKIT_CAPABILITIES).contains(
|
||||
CloudBukkitCapabilities.BRIGADIER)) {
|
||||
return ArgumentParseResult.failure(new SelectorParseException(
|
||||
"",
|
||||
|
|
@ -153,7 +153,7 @@ public final class MultipleEntitySelectorArgument<C> extends CommandArgument<C,
|
|||
|
||||
List<Entity> entities;
|
||||
try {
|
||||
entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input);
|
||||
entities = Bukkit.selectEntities(commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER), input);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ArgumentParseResult.failure(new SelectorParseException(
|
||||
input,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import cloud.commandframework.ArgumentDescription;
|
|||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||
import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector;
|
||||
import cloud.commandframework.bukkit.parsers.PlayerArgument;
|
||||
|
|
@ -34,6 +35,7 @@ import cloud.commandframework.context.CommandContext;
|
|||
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
|
@ -42,7 +44,6 @@ 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<C> extends CommandArgument<C, MultiplePlayerSelector> {
|
||||
|
|
@ -146,7 +147,7 @@ public final class MultiplePlayerSelectorArgument<C> extends CommandArgument<C,
|
|||
}
|
||||
inputQueue.remove();
|
||||
|
||||
if (!commandContext.<Set<CloudBukkitCapabilities>>get("CloudBukkitCapabilities").contains(
|
||||
if (!commandContext.get(BukkitCommandContextKeys.CLOUD_BUKKIT_CAPABILITIES).contains(
|
||||
CloudBukkitCapabilities.BRIGADIER)) {
|
||||
@SuppressWarnings("deprecation")
|
||||
Player player = Bukkit.getPlayer(input);
|
||||
|
|
@ -159,7 +160,7 @@ public final class MultiplePlayerSelectorArgument<C> extends CommandArgument<C,
|
|||
|
||||
List<Entity> entities;
|
||||
try {
|
||||
entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input);
|
||||
entities = Bukkit.selectEntities(commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER), input);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ArgumentParseResult.failure(new SelectorParseException(
|
||||
input,
|
||||
|
|
@ -191,6 +192,10 @@ public final class MultiplePlayerSelectorArgument<C> extends CommandArgument<C,
|
|||
List<String> output = new ArrayList<>();
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
final CommandSender bukkit = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
|
||||
if (bukkit instanceof Player && !((Player) bukkit).canSee(player)) {
|
||||
continue;
|
||||
}
|
||||
output.add(player.getName());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import cloud.commandframework.ArgumentDescription;
|
|||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
|
|
@ -38,7 +39,6 @@ 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<C> extends CommandArgument<C, SingleEntitySelector> {
|
||||
|
|
@ -139,7 +139,7 @@ public final class SingleEntitySelectorArgument<C> extends CommandArgument<C, Si
|
|||
final @NonNull CommandContext<C> commandContext,
|
||||
final @NonNull Queue<@NonNull String> inputQueue
|
||||
) {
|
||||
if (!commandContext.<Set<CloudBukkitCapabilities>>get("CloudBukkitCapabilities").contains(
|
||||
if (!commandContext.get(BukkitCommandContextKeys.CLOUD_BUKKIT_CAPABILITIES).contains(
|
||||
CloudBukkitCapabilities.BRIGADIER)) {
|
||||
return ArgumentParseResult.failure(new SelectorParseException(
|
||||
"",
|
||||
|
|
@ -159,7 +159,7 @@ public final class SingleEntitySelectorArgument<C> extends CommandArgument<C, Si
|
|||
|
||||
List<Entity> entities;
|
||||
try {
|
||||
entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input);
|
||||
entities = Bukkit.selectEntities(commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER), input);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ArgumentParseResult.failure(new SelectorParseException(
|
||||
input,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import cloud.commandframework.ArgumentDescription;
|
|||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.bukkit.BukkitCommandContextKeys;
|
||||
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||
import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector;
|
||||
import cloud.commandframework.bukkit.parsers.PlayerArgument;
|
||||
|
|
@ -34,6 +35,7 @@ import cloud.commandframework.context.CommandContext;
|
|||
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
|
@ -42,7 +44,6 @@ 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<C> extends CommandArgument<C, SinglePlayerSelector> {
|
||||
|
|
@ -152,7 +153,7 @@ public final class SinglePlayerSelectorArgument<C> extends CommandArgument<C, Si
|
|||
}
|
||||
inputQueue.remove();
|
||||
|
||||
if (!commandContext.<Set<CloudBukkitCapabilities>>get("CloudBukkitCapabilities").contains(
|
||||
if (!commandContext.get(BukkitCommandContextKeys.CLOUD_BUKKIT_CAPABILITIES).contains(
|
||||
CloudBukkitCapabilities.BRIGADIER)) {
|
||||
@SuppressWarnings("deprecation")
|
||||
Player player = Bukkit.getPlayer(input);
|
||||
|
|
@ -165,7 +166,7 @@ public final class SinglePlayerSelectorArgument<C> extends CommandArgument<C, Si
|
|||
|
||||
List<Entity> entities;
|
||||
try {
|
||||
entities = Bukkit.selectEntities(commandContext.get("BukkitCommandSender"), input);
|
||||
entities = Bukkit.selectEntities(commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER), input);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ArgumentParseResult.failure(new SelectorParseException(
|
||||
input,
|
||||
|
|
@ -205,6 +206,10 @@ public final class SinglePlayerSelectorArgument<C> extends CommandArgument<C, Si
|
|||
List<String> output = new ArrayList<>();
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
final CommandSender bukkit = commandContext.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
|
||||
if (bukkit instanceof Player && !((Player) bukkit).canSee(player)) {
|
||||
continue;
|
||||
}
|
||||
output.add(player.getName());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,15 +27,18 @@ import cloud.commandframework.CommandTree;
|
|||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||
import cloud.commandframework.bukkit.BukkitBrigadierMapper;
|
||||
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.permission.CommandPermission;
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginIdentifiableCommand;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
|
@ -46,18 +49,30 @@ class PaperBrigadierListener<C> implements Listener {
|
|||
|
||||
PaperBrigadierListener(final @NonNull PaperCommandManager<C> paperCommandManager) {
|
||||
this.paperCommandManager = paperCommandManager;
|
||||
this.brigadierManager = new CloudBrigadierManager<>(
|
||||
this.paperCommandManager,
|
||||
() -> new CommandContext<>(
|
||||
this.paperCommandManager.getCommandSenderMapper()
|
||||
.apply(Bukkit.getConsoleSender()),
|
||||
this.brigadierManager = new CloudBrigadierManager<>(this.paperCommandManager, () -> new CommandContext<>(
|
||||
this.paperCommandManager.getCommandSenderMapper().apply(Bukkit.getConsoleSender()),
|
||||
this.paperCommandManager
|
||||
)
|
||||
);
|
||||
this.brigadierManager.brigadierSenderMapper(
|
||||
sender -> this.paperCommandManager.getCommandSenderMapper().apply(sender.getBukkitSender())
|
||||
);
|
||||
));
|
||||
|
||||
this.brigadierManager.brigadierSenderMapper(sender ->
|
||||
this.paperCommandManager.getCommandSenderMapper().apply(sender.getBukkitSender()));
|
||||
|
||||
new BukkitBrigadierMapper<>(this.paperCommandManager, this.brigadierManager);
|
||||
|
||||
if (!CraftBukkitReflection.craftBukkit()) {
|
||||
return;
|
||||
}
|
||||
final Class<?> vanillaCommandWrapperClass = CraftBukkitReflection.needOBCClass("command.VanillaCommandWrapper");
|
||||
final Method getListenerMethod = CraftBukkitReflection.needMethod(
|
||||
vanillaCommandWrapperClass, "getListener", CommandSender.class);
|
||||
this.brigadierManager.backwardsBrigadierSenderMapper(cloud -> {
|
||||
try {
|
||||
return (BukkitBrigadierCommandSource) getListenerMethod
|
||||
.invoke(null, this.paperCommandManager.getBackwardsCommandSenderMapper().apply(cloud));
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected @NonNull CloudBrigadierManager<C, BukkitBrigadierCommandSource> brigadierManager() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue