Update paper plugin to MC 1.20.6
- Convert Brigadier command to use the new Brigadier/Paper API - EquipmentSlot now has BODY value for horses and wolves armor - ItemMeta’ canPlaceOn and canDestroy does not work anymore. Removed the related methods from ItemStackBuilder - Enchantment DURABILITY now has the proper vanilla name UNBREAKING - Pandalib-chat now uses Adventure’s TranslationArgument
This commit is contained in:
@@ -2,38 +2,26 @@ package fr.pandacube.lib.paper.commands;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.mojang.brigadier.tree.RootCommandNode;
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import fr.pandacube.lib.commands.BadCommandUsage;
|
||||
import fr.pandacube.lib.commands.BrigadierCommand;
|
||||
import fr.pandacube.lib.commands.SuggestionsSupplier;
|
||||
import fr.pandacube.lib.paper.permissions.PandalibPaperPermissions;
|
||||
import fr.pandacube.lib.paper.reflect.PandalibPaperReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftVector;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.BlockPosArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Commands;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ComponentArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Coordinates;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntityArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntitySelector;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Vec3Argument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.PaperAdventure;
|
||||
import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
|
||||
import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
|
||||
import fr.pandacube.lib.players.standalone.AbstractPlayerManager;
|
||||
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.util.log.Log;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
@@ -41,18 +29,10 @@ import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.defaults.BukkitCommand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
import org.bukkit.event.server.ServerLoadEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -64,7 +44,9 @@ import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
/**
|
||||
* Abstract class to hold a command to be integrated into a Paper server vanilla command dispatcher.
|
||||
*/
|
||||
public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBrigadierCommandSource> implements Listener {
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public abstract class PaperBrigadierCommand extends BrigadierCommand<CommandSourceStack> implements Listener {
|
||||
|
||||
|
||||
private static final Commands vanillaCommandDispatcher;
|
||||
private static final CommandDispatcher<BukkitBrigadierCommandSource> nmsDispatcher;
|
||||
@@ -91,6 +73,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
return;
|
||||
}
|
||||
Log.info("Removing Bukkit command /" + name + " (" + getCommandIdentity(bukkitCommand) + ")");
|
||||
Log.warning("[1.20.6 update] Please test that the bukkit command removal is actually working.");
|
||||
bukkitCmdMap.getKnownCommands().remove(name.toLowerCase(java.util.Locale.ENGLISH));
|
||||
bukkitCommand.unregister(bukkitCmdMap);
|
||||
|
||||
@@ -131,7 +114,13 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
/**
|
||||
* The command node of this command.
|
||||
*/
|
||||
protected final LiteralCommandNode<BukkitBrigadierCommandSource> commandNode;
|
||||
protected final LiteralCommandNode<CommandSourceStack> commandNode;
|
||||
/**
|
||||
* The command requested aliases.
|
||||
*/
|
||||
protected final String[] aliases;
|
||||
|
||||
protected final String description;
|
||||
|
||||
private final RegistrationPolicy registrationPolicy;
|
||||
|
||||
@@ -147,12 +136,14 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
plugin = pl;
|
||||
registrationPolicy = regPolicy;
|
||||
commandNode = buildCommand().build();
|
||||
String[] aliasesTmp = getAliases();
|
||||
aliases = aliasesTmp == null ? new String[0] : aliasesTmp;
|
||||
description = getDescription();
|
||||
postBuildCommand(commandNode);
|
||||
register();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
try {
|
||||
PandalibPaperPermissions.addPermissionMapping("minecraft.command." + commandNode.getLiteral().toLowerCase(), getTargetPermission().toLowerCase());
|
||||
} catch (NoClassDefFoundError ignored) { }
|
||||
//try {
|
||||
// PandalibPaperPermissions.addPermissionMapping("minecraft.command." + commandNode.getLiteral().toLowerCase(), getTargetPermission().toLowerCase());
|
||||
//} catch (NoClassDefFoundError ignored) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,130 +158,28 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
|
||||
|
||||
private void register() {
|
||||
plugin.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, event -> {
|
||||
|
||||
String[] aliases = getAliases();
|
||||
if (aliases == null)
|
||||
aliases = new String[0];
|
||||
registeredAliases = new HashSet<>(event.registrar().register(commandNode, description, List.of(aliases)));
|
||||
|
||||
String pluginName = plugin.getName().toLowerCase();
|
||||
if (registrationPolicy == RegistrationPolicy.ALL) {
|
||||
// enforce registration of aliases
|
||||
for (String alias : aliases) {
|
||||
if (!registeredAliases.contains(alias))
|
||||
registeredAliases.addAll(event.registrar().register(getAliasNode(alias), description));
|
||||
}
|
||||
}
|
||||
|
||||
registeredAliases = new HashSet<>();
|
||||
registerNode(commandNode, false);
|
||||
registerAlias(pluginName + ":" + commandNode.getLiteral(), true);
|
||||
|
||||
for (String alias : aliases) {
|
||||
registerAlias(alias, false);
|
||||
registerAlias(pluginName + ":" + alias, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void registerAlias(String alias, boolean prefixed) {
|
||||
LiteralCommandNode<BukkitBrigadierCommandSource> node = literal(alias)
|
||||
private LiteralCommandNode<CommandSourceStack> getAliasNode(String alias) {
|
||||
return literal(alias)
|
||||
.requires(commandNode.getRequirement())
|
||||
.executes(commandNode.getCommand())
|
||||
.redirect(commandNode)
|
||||
.build();
|
||||
registerNode(node, prefixed);
|
||||
}
|
||||
|
||||
|
||||
private void registerNode(LiteralCommandNode<BukkitBrigadierCommandSource> node, boolean prefixed) {
|
||||
RootCommandNode<BukkitBrigadierCommandSource> root = getRootNode();
|
||||
String name = node.getLiteral();
|
||||
boolean isAlias = node.getRedirect() == commandNode;
|
||||
boolean forceRegistration = switch (registrationPolicy) {
|
||||
case NONE -> false;
|
||||
case ONLY_BASE_COMMAND -> prefixed || !isAlias;
|
||||
case ALL -> true;
|
||||
};
|
||||
|
||||
// nmsDispatcher integration and conflit resolution
|
||||
boolean nmsRegister = false, nmsRegistered = false;
|
||||
CommandNode<BukkitBrigadierCommandSource> nmsConflicted = root.getChild(name);
|
||||
if (nmsConflicted != null) {
|
||||
|
||||
if (isFromThisCommand(nmsConflicted)) {
|
||||
// this command is already registered in NMS. Don’t need to register again
|
||||
nmsRegistered = true;
|
||||
}
|
||||
else if (forceRegistration) {
|
||||
nmsRegister = true;
|
||||
Log.info("Overwriting Brigadier command /" + name);
|
||||
}
|
||||
else if (prefixed || !isAlias) {
|
||||
Log.severe("/" + name + " already in NMS Brigadier instance."
|
||||
+ " Wont replace it because registration is not forced for prefixed or initial name of a command.");
|
||||
}
|
||||
else { // conflict, won't replace, not forced but only an alias anyway
|
||||
Log.info("/" + name + " already in NMS Brigadier instance."
|
||||
+ " Wont replace it because registration is not forced for a non-prefixed alias.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
nmsRegister = true;
|
||||
}
|
||||
|
||||
if (nmsRegister) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var rCommandNode = ReflectWrapper.wrapTyped(root, fr.pandacube.lib.paper.reflect.wrapper.brigadier.CommandNode.class);
|
||||
rCommandNode.removeCommand(name);
|
||||
root.addChild(node);
|
||||
nmsRegistered = true;
|
||||
}
|
||||
|
||||
if (!nmsRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
registeredAliases.add(name);
|
||||
|
||||
// bukkit dispatcher conflict resolution
|
||||
boolean bukkitRegister = false;
|
||||
CommandMap bukkitCmdMap = Bukkit.getCommandMap();
|
||||
Command bukkitConflicted = bukkitCmdMap.getCommand(name);
|
||||
if (bukkitConflicted != null) {
|
||||
if (!isFromThisCommand(bukkitConflicted)) {
|
||||
if (forceRegistration) {
|
||||
bukkitRegister = true;
|
||||
Log.info("Overwriting Bukkit command /" + name
|
||||
+ " (" + getCommandIdentity(bukkitConflicted) + ")");
|
||||
}
|
||||
else if (prefixed || !isAlias) {
|
||||
Log.severe("/" + name + " already in Bukkit dispatcher (" + getCommandIdentity(bukkitConflicted) + ")." +
|
||||
" Wont replace it because registration is not forced for prefixed or initial name of a command.");
|
||||
}
|
||||
else {
|
||||
Log.info("/" + name + " already in Bukkit dispatcher (" + getCommandIdentity(bukkitConflicted) + ")." +
|
||||
" Wont replace it because registration is not forced for a non-prefixed alias.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
bukkitRegister = true;
|
||||
}
|
||||
|
||||
if (bukkitRegister) {
|
||||
bukkitCmdMap.getKnownCommands().remove(name.toLowerCase());
|
||||
if (bukkitConflicted != null)
|
||||
bukkitConflicted.unregister(bukkitCmdMap);
|
||||
|
||||
Command newCommand = new VanillaCommandWrapper(vanillaCommandDispatcher, node).__getRuntimeInstance();
|
||||
bukkitCmdMap.getKnownCommands().put(name.toLowerCase(), newCommand);
|
||||
newCommand.register(bukkitCmdMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isFromThisCommand(CommandNode<BukkitBrigadierCommandSource> node) {
|
||||
return node == commandNode || node.getRedirect() == commandNode;
|
||||
}
|
||||
|
||||
private boolean isFromThisCommand(Command bukkitCmd) {
|
||||
if (VanillaCommandWrapper.REFLECT.get().isInstance(bukkitCmd)) {
|
||||
return isFromThisCommand(ReflectWrapper.wrapTyped((BukkitCommand) bukkitCmd, VanillaCommandWrapper.class).vanillaCommand());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getCommandIdentity(Command bukkitCmd) {
|
||||
@@ -305,25 +194,6 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Player command sender event handler.
|
||||
* @param event the event.
|
||||
*/
|
||||
@EventHandler
|
||||
public void onPlayerCommandSend(PlayerCommandSendEvent event) {
|
||||
event.getCommands().removeAll(registeredAliases.stream().map(s -> "minecraft:" + s).toList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Server load event handler.
|
||||
* @param event the event.
|
||||
*/
|
||||
@EventHandler
|
||||
public void onServerLoad(ServerLoadEvent event) {
|
||||
register();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -342,6 +212,15 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
*/
|
||||
protected abstract String getTargetPermission();
|
||||
|
||||
/**
|
||||
* Returns the permission that should be tested instead of "minecraft.command.cmdName". The conversion from the
|
||||
* minecraft prefixed permission node to the returned node is done by the {@code pandalib-paper-permissions} if it
|
||||
* is present in the classpath during runtime.
|
||||
* @return the permission that should be tested instead of "minecraft.command.cmdName".
|
||||
*/
|
||||
protected String getDescription() {
|
||||
return "A command from " + plugin.getName();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -355,13 +234,14 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
|
||||
|
||||
|
||||
public boolean isConsole(BukkitBrigadierCommandSource wrapper) {
|
||||
|
||||
public boolean isConsole(CommandSourceStack wrapper) {
|
||||
return isConsole(getCommandSender(wrapper));
|
||||
}
|
||||
public boolean isPlayer(BukkitBrigadierCommandSource wrapper) {
|
||||
public boolean isPlayer(CommandSourceStack wrapper) {
|
||||
return isPlayer(getCommandSender(wrapper));
|
||||
}
|
||||
public Predicate<BukkitBrigadierCommandSource> hasPermission(String permission) {
|
||||
public Predicate<CommandSourceStack> hasPermission(String permission) {
|
||||
return wrapper -> getCommandSender(wrapper).hasPermission(permission);
|
||||
}
|
||||
|
||||
@@ -395,7 +275,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
* @param context the command context from which to get the Bukkit command sender.
|
||||
* @return the Bukkit command sender.
|
||||
*/
|
||||
public static CommandSender getCommandSender(CommandContext<BukkitBrigadierCommandSource> context) {
|
||||
public static CommandSender getCommandSender(CommandContext<CommandSourceStack> context) {
|
||||
return getCommandSender(context.getSource());
|
||||
}
|
||||
|
||||
@@ -404,8 +284,8 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
* @param wrapper the wrapper from which to get the Bukkit command sender.
|
||||
* @return the Bukkit command sender.
|
||||
*/
|
||||
public static CommandSender getCommandSender(BukkitBrigadierCommandSource wrapper) {
|
||||
return wrapper.getBukkitSender();
|
||||
public static CommandSender getCommandSender(CommandSourceStack wrapper) {
|
||||
return wrapper.getSender();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,8 +293,8 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
* @param sender the command sender.
|
||||
* @return a new instance of a command sender wrapper for the provided command sender.
|
||||
*/
|
||||
public static BukkitBrigadierCommandSource getBrigadierCommandSource(CommandSender sender) {
|
||||
return VanillaCommandWrapper.getListener(sender);
|
||||
public static CommandSourceStack getBrigadierCommandSource(CommandSender sender) {
|
||||
throw new UnsupportedOperationException("The 1.20.6 Paper API update uses a different wrapper for Brigadier command sender.");
|
||||
}
|
||||
|
||||
|
||||
@@ -443,7 +323,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
* @param suggestions the suggestions to wrap.
|
||||
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
|
||||
*/
|
||||
public SuggestionProvider<BukkitBrigadierCommandSource> wrapSuggestions(SuggestionsSupplier<CommandSender> suggestions) {
|
||||
public SuggestionProvider<CommandSourceStack> wrapSuggestions(SuggestionsSupplier<CommandSender> suggestions) {
|
||||
return wrapSuggestions(suggestions, PaperBrigadierCommand::getCommandSender);
|
||||
}
|
||||
|
||||
@@ -456,7 +336,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
* @param cmd the command executor to wrap.
|
||||
* @return a wrapper command executor.
|
||||
*/
|
||||
protected static com.mojang.brigadier.Command<BukkitBrigadierCommandSource> wrapCommand(com.mojang.brigadier.Command<BukkitBrigadierCommandSource> cmd) {
|
||||
protected static com.mojang.brigadier.Command<CommandSourceStack> wrapCommand(com.mojang.brigadier.Command<CommandSourceStack> cmd) {
|
||||
return context -> {
|
||||
try {
|
||||
return cmd.run(context);
|
||||
@@ -485,181 +365,13 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Brigadier argument type {@code minecraft:entity}.
|
||||
* @param singleTarget if this argument takes only a single target.
|
||||
* @param playersOnly if this argument takes players only.
|
||||
* @return the {@code minecraft:entity} argument type with the specified parameters.
|
||||
*/
|
||||
public static ArgumentType<Object> argumentMinecraftEntity(boolean singleTarget, boolean playersOnly) {
|
||||
if (playersOnly) {
|
||||
return singleTarget ? EntityArgument.player() : EntityArgument.players();
|
||||
}
|
||||
else {
|
||||
return singleTarget ? EntityArgument.entity() : EntityArgument.entities();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:entity} (list of entities), from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @return the value of the argument, or null if not found.
|
||||
*/
|
||||
public List<Entity> tryGetMinecraftEntityArgument(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
||||
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
|
||||
if (es == null)
|
||||
return null;
|
||||
List<fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity> nmsEntityList = es.findEntities(context.getSource());
|
||||
List<Entity> entityList = new ArrayList<>(nmsEntityList.size());
|
||||
for (fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity nmsEntity : nmsEntityList) {
|
||||
entityList.add(nmsEntity.getBukkitEntity());
|
||||
}
|
||||
return entityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:entity} (list of players), from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @return the value of the argument, or null if not found.
|
||||
*/
|
||||
public List<Player> tryGetMinecraftEntityArgumentPlayers(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
||||
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
|
||||
if (es == null)
|
||||
return null;
|
||||
List<ServerPlayer> nmsPlayerList = es.findPlayers(context.getSource());
|
||||
List<Player> playerList = new ArrayList<>(nmsPlayerList.size());
|
||||
for (ServerPlayer nmsPlayer : nmsPlayerList) {
|
||||
playerList.add(nmsPlayer.getBukkitEntity());
|
||||
}
|
||||
return playerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:entity} (one entity), from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @return the value of the argument, or null if not found.
|
||||
*/
|
||||
public Entity tryGetMinecraftEntityArgumentOneEntity(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
||||
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
|
||||
if (es == null)
|
||||
return null;
|
||||
fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity nmsEntity = es.findSingleEntity(context.getSource());
|
||||
return nmsEntity == null ? null : nmsEntity.getBukkitEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:entity} (one player), from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @return the value of the argument, or null if not found.
|
||||
*/
|
||||
public Player tryGetMinecraftEntityArgumentOnePlayer(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
||||
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
|
||||
if (es == null)
|
||||
return null;
|
||||
ServerPlayer nmsPlayer = es.findSinglePlayer(context.getSource());
|
||||
return nmsPlayer == null ? null : nmsPlayer.getBukkitEntity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Brigadier argument type {@code minecraft:block_pos}.
|
||||
* @return the {@code minecraft:block_pos} argument type.
|
||||
*/
|
||||
public static ArgumentType<Object> argumentMinecraftBlockPosition() {
|
||||
return BlockPosArgument.blockPos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:block_pos}, from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @param deflt a default value if the argument is not found.
|
||||
* @return the value of the argument.
|
||||
*/
|
||||
public BlockVector tryGetMinecraftBlockPositionArgument(CommandContext<BukkitBrigadierCommandSource> context,
|
||||
String argument, BlockVector deflt) {
|
||||
return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(), nmsCoordinate -> {
|
||||
BlockPos bp = ReflectWrapper.wrap(nmsCoordinate, Coordinates.class).getBlockPos(context.getSource());
|
||||
return new BlockVector(bp.getX(), bp.getY(), bp.getZ());
|
||||
}, deflt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Brigadier argument type {@code minecraft:vec3}.
|
||||
* @return the {@code minecraft:vec3} argument type.
|
||||
*/
|
||||
public static ArgumentType<Object> argumentMinecraftVec3() {
|
||||
return Vec3Argument.vec3(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:vec3}, from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @param deflt a default value if the argument is not found.
|
||||
* @return the value of the argument.
|
||||
*/
|
||||
public Vector tryGetMinecraftVec3Argument(CommandContext<BukkitBrigadierCommandSource> context, String argument,
|
||||
Vector deflt) {
|
||||
return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(),
|
||||
nmsCoordinate -> CraftVector.toBukkit(
|
||||
ReflectWrapper.wrap(nmsCoordinate, Coordinates.class).getPosition(context.getSource())
|
||||
),
|
||||
deflt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Brigadier argument type {@code minecraft:component}.
|
||||
* @return the {@code minecraft:component} argument type.
|
||||
*/
|
||||
public static ArgumentType<Object> argumentMinecraftChatComponent() {
|
||||
return ComponentArgument.textComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the provided argument of type {@code minecraft:component}, from the provided context.
|
||||
* @param context the command execution context.
|
||||
* @param argument the argument name.
|
||||
* @param deflt a default value if the argument is not found.
|
||||
* @return the value of the argument.
|
||||
*/
|
||||
public Component tryGetMinecraftChatComponentArgument(CommandContext<BukkitBrigadierCommandSource> context,
|
||||
String argument, Component deflt) {
|
||||
return tryGetArgument(context, argument,
|
||||
fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component.MAPPING.runtimeClass(),
|
||||
nmsComp -> PaperAdventure.asAdventure(
|
||||
ReflectWrapper.wrap(nmsComp,
|
||||
fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component.class)
|
||||
),
|
||||
deflt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All possible choices on how to force the registration of a command, based on certain conditions.
|
||||
*/
|
||||
public enum RegistrationPolicy {
|
||||
/**
|
||||
* Do not force to register a command node or an alias if there is already a command with that name in the
|
||||
* vanilla Brigadier dispatcher.
|
||||
* Note that all plugin-name-prefixed aliases will be registered anyway.
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* Force only the base command (but not the aliases) to be registered, even if a command with that name already
|
||||
* exists in the vanilla Brigadier dispatcher.
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import com.destroystokyo.paper.Namespaced;
|
||||
import com.google.common.collect.Streams;
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -13,10 +12,8 @@ import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static fr.pandacube.lib.chat.ChatStatic.chatComponent;
|
||||
@@ -183,7 +180,7 @@ public class ItemStackBuilder {
|
||||
|
||||
public ItemStackBuilder fakeEnchant(boolean apply) {
|
||||
if (apply) {
|
||||
enchant(Enchantment.DURABILITY, 1);
|
||||
enchant(Enchantment.UNBREAKING, 1);
|
||||
return hideEnchants();
|
||||
}
|
||||
return this;
|
||||
@@ -196,22 +193,6 @@ public class ItemStackBuilder {
|
||||
public ItemStackBuilder unbreakable(boolean unbreakable) {
|
||||
return meta(m -> m.setUnbreakable(unbreakable));
|
||||
}
|
||||
|
||||
public ItemStackBuilder canDestroy(Set<Material> destroyable) {
|
||||
return canDestroy(destroyable.stream().map(m -> (Namespaced) m.getKey()).toList());
|
||||
}
|
||||
|
||||
public ItemStackBuilder canPlaceOn(Set<Material> placeOn) {
|
||||
return canPlaceOn(placeOn.stream().map(m -> (Namespaced) m.getKey()).toList());
|
||||
}
|
||||
|
||||
public ItemStackBuilder canDestroy(Collection<Namespaced> destroyable) {
|
||||
return meta(m -> m.setDestroyableKeys(destroyable));
|
||||
}
|
||||
|
||||
public ItemStackBuilder canPlaceOn(Collection<Namespaced> placeOn) {
|
||||
return meta(m -> m.setPlaceableKeys(placeOn));
|
||||
}
|
||||
|
||||
public ItemStackBuilder damage(int d) {
|
||||
return meta(m -> m.setDamage(d), Damageable.class);
|
||||
|
@@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
@@ -98,7 +99,7 @@ public record PlayerDataWrapper(CompoundTag data) {
|
||||
Inventory inv = Bukkit.createInventory(null, bukkitType);
|
||||
if (stacks.isEmpty())
|
||||
return inv;
|
||||
for (Map.Entry<Integer, ItemStack> is : stacks.entrySet()) {
|
||||
for (Entry<Integer, ItemStack> is : stacks.entrySet()) {
|
||||
inv.setItem(nbtToBukkitSlotConverter.applyAsInt(is.getKey()), is.getValue());
|
||||
}
|
||||
return inv;
|
||||
@@ -142,7 +143,7 @@ public record PlayerDataWrapper(CompoundTag data) {
|
||||
|
||||
private void setRawInventoryContent(String key, Map<Integer, ItemStack> stacks) {
|
||||
ListTag list = new ListTag();
|
||||
for (Map.Entry<Integer, ItemStack> is : stacks.entrySet()) {
|
||||
for (Entry<Integer, ItemStack> is : stacks.entrySet()) {
|
||||
ItemStack stack = filterStack(is.getValue());
|
||||
if (stack == null)
|
||||
continue;
|
||||
@@ -312,6 +313,7 @@ public record PlayerDataWrapper(CompoundTag data) {
|
||||
case LEGS -> Objects.requireNonNullElseGet(this.getLeggings(), () -> new ItemStack(Material.AIR));
|
||||
case CHEST -> Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(Material.AIR));
|
||||
case HEAD -> Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(Material.AIR));
|
||||
case BODY -> new ItemStack(Material.AIR); // for horses/wolves armor
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user