Even more javadoc
This commit is contained in:
parent
54bc8ab99a
commit
b6fc3c2b61
@ -5,6 +5,9 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|||||||
|
|
||||||
import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
|
import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents any player on a Bungeecord proxy, either offline or online.
|
||||||
|
*/
|
||||||
public interface BungeeOffPlayer extends AbstractOffPlayer {
|
public interface BungeeOffPlayer extends AbstractOffPlayer {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -12,8 +15,8 @@ public interface BungeeOffPlayer extends AbstractOffPlayer {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return l'instance Bungee du joueur en ligne, ou null si il n'est pas en
|
* Returns the {@link ProxiedPlayer} instance of this player, or null if not available (offline).
|
||||||
* ligne
|
* @return the {@link ProxiedPlayer} instance of this player, or null if not available (offline).
|
||||||
*/
|
*/
|
||||||
default ProxiedPlayer getBungeeProxiedPlayer() {
|
default ProxiedPlayer getBungeeProxiedPlayer() {
|
||||||
return ProxyServer.getInstance().getPlayer(getUniqueId());
|
return ProxyServer.getInstance().getPlayer(getUniqueId());
|
||||||
|
@ -23,6 +23,9 @@ import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
|
|||||||
import fr.pandacube.lib.reflect.Reflect;
|
import fr.pandacube.lib.reflect.Reflect;
|
||||||
import fr.pandacube.lib.util.MinecraftVersion;
|
import fr.pandacube.lib.util.MinecraftVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents any online player on a Bungeecord proxy.
|
||||||
|
*/
|
||||||
public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlayer {
|
public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlayer {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -41,24 +44,24 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
|
|||||||
return getServer().getInfo().getName();
|
return getServer().getInfo().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the server on which the player is.
|
||||||
|
* @return the server on which the player is.
|
||||||
|
*/
|
||||||
default Server getServer() {
|
default Server getServer() {
|
||||||
return getBungeeProxiedPlayer().getServer();
|
return getBungeeProxiedPlayer().getServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minecraft version of this player’s client.
|
||||||
|
* @return the minecraft version of this player’s client.
|
||||||
|
*/
|
||||||
default MinecraftVersion getMinecraftVersion() {
|
default MinecraftVersion getMinecraftVersion() {
|
||||||
return MinecraftVersion.getVersion(getBungeeProxiedPlayer().getPendingConnection().getVersion());
|
return MinecraftVersion.getVersion(getBungeeProxiedPlayer().getPendingConnection().getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Related class instances
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
ProxiedPlayer getBungeeProxiedPlayer();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -95,11 +98,17 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void sendMessage(Component message, Identified sender) {
|
default void sendMessage(Component message, Identified sender) {
|
||||||
getBungeeProxiedPlayer().sendMessage(sender.identity().uuid(), Chat.toBungee(message));
|
getBungeeProxiedPlayer().sendMessage(sender == null ? null : sender.identity().uuid(), Chat.toBungee(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the provided message in the player’s chat, if they allows to display CHAT messages.
|
||||||
|
* @param message the message to send.
|
||||||
|
* @param sender the player causing the send of this message. Client side filtering may occur. May be null if we
|
||||||
|
* don’t want client filtering, but still consider the message as CHAT message.
|
||||||
|
*/
|
||||||
default void sendMessage(ComponentLike message, ProxiedPlayer sender) {
|
default void sendMessage(ComponentLike message, ProxiedPlayer sender) {
|
||||||
getBungeeProxiedPlayer().sendMessage(sender.getUniqueId(), Chat.toBungee(message.asComponent()));
|
getBungeeProxiedPlayer().sendMessage(sender == null ? null : sender.getUniqueId(), Chat.toBungee(message.asComponent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,9 +143,17 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
|
|||||||
return new BungeeClientOptions(this);
|
return new BungeeClientOptions(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides various configuration values of the Minecraft client.
|
||||||
|
*/
|
||||||
class BungeeClientOptions implements AbstractOnlinePlayer.ClientOptions {
|
class BungeeClientOptions implements AbstractOnlinePlayer.ClientOptions {
|
||||||
|
|
||||||
private final BungeeOnlinePlayer op;
|
private final BungeeOnlinePlayer op;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of {@link BungeeClientOptions}.
|
||||||
|
* @param op the {@link BungeeOnlinePlayer} instance.
|
||||||
|
*/
|
||||||
public BungeeClientOptions(BungeeOnlinePlayer op) {
|
public BungeeClientOptions(BungeeOnlinePlayer op) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
}
|
}
|
||||||
@ -155,6 +172,10 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
|
|||||||
return op.getBungeeProxiedPlayer().hasChatColors();
|
return op.getBungeeProxiedPlayer().hasChatColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the chat visibility configuration.
|
||||||
|
* @return the chat visibility configuration.
|
||||||
|
*/
|
||||||
public ChatMode getChatMode() {
|
public ChatMode getChatMode() {
|
||||||
return op.getBungeeProxiedPlayer().getChatMode();
|
return op.getBungeeProxiedPlayer().getChatMode();
|
||||||
}
|
}
|
||||||
@ -185,6 +206,10 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
|
|||||||
return op.getBungeeProxiedPlayer().getViewDistance();
|
return op.getBungeeProxiedPlayer().getViewDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player’s main hand.
|
||||||
|
* @return the player’s main hand.
|
||||||
|
*/
|
||||||
public MainHand getMainHand() {
|
public MainHand getMainHand() {
|
||||||
return op.getBungeeProxiedPlayer().getMainHand();
|
return op.getBungeeProxiedPlayer().getMainHand();
|
||||||
}
|
}
|
||||||
@ -211,6 +236,10 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
|
|||||||
return settings != null && settings.isAllowServerListing();
|
return settings != null && settings.isAllowServerListing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player’s skin configuration.
|
||||||
|
* @return the player’s skin configuration.
|
||||||
|
*/
|
||||||
public SkinConfiguration getSkinParts() {
|
public SkinConfiguration getSkinParts() {
|
||||||
return op.getBungeeProxiedPlayer().getSkinParts();
|
return op.getBungeeProxiedPlayer().getSkinParts();
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,13 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>fr.pandacube.lib</groupId>
|
||||||
|
<artifactId>pandalib-paper-permissions</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Paper -->
|
<!-- Paper -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.papermc.paper</groupId>
|
<groupId>io.papermc.paper</groupId>
|
||||||
|
@ -2,12 +2,9 @@ package fr.pandacube.lib.paper.commands;
|
|||||||
|
|
||||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.mojang.brigadier.LiteralMessage;
|
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.context.ParsedCommandNode;
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
|
||||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
import com.mojang.brigadier.tree.CommandNode;
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
@ -15,7 +12,7 @@ import com.mojang.brigadier.tree.RootCommandNode;
|
|||||||
import fr.pandacube.lib.chat.Chat;
|
import fr.pandacube.lib.chat.Chat;
|
||||||
import fr.pandacube.lib.commands.BrigadierCommand;
|
import fr.pandacube.lib.commands.BrigadierCommand;
|
||||||
import fr.pandacube.lib.commands.SuggestionsSupplier;
|
import fr.pandacube.lib.commands.SuggestionsSupplier;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftNamespacedKey;
|
import fr.pandacube.lib.paper.permissions.PandalibPaperPermissions;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer;
|
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.CraftVector;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper;
|
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper;
|
||||||
@ -25,18 +22,14 @@ import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ComponentArgume
|
|||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Coordinates;
|
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.EntityArgument;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntitySelector;
|
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntitySelector;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.GameProfileArgument;
|
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ResourceLocationArgument;
|
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Vec3Argument;
|
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.core.BlockPos;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.resources.ResourceLocation;
|
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
|
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
|
||||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.PaperAdventure;
|
import fr.pandacube.lib.paper.reflect.wrapper.paper.PaperAdventure;
|
||||||
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
|
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
|
||||||
import fr.pandacube.lib.util.Log;
|
import fr.pandacube.lib.util.Log;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandMap;
|
import org.bukkit.command.CommandMap;
|
||||||
@ -55,200 +48,283 @@ import org.bukkit.util.BlockVector;
|
|||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBrigadierCommandSource> implements Listener {
|
||||||
|
|
||||||
protected static final Commands vanillaCommandDispatcher;
|
private static final Commands vanillaCommandDispatcher;
|
||||||
private static final CommandDispatcher<BukkitBrigadierCommandSource> nmsDispatcher;
|
private static final CommandDispatcher<BukkitBrigadierCommandSource> nmsDispatcher;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
vanillaCommandDispatcher = ReflectWrapper.wrapTyped(Bukkit.getServer(), CraftServer.class)
|
vanillaCommandDispatcher = ReflectWrapper.wrapTyped(Bukkit.getServer(), CraftServer.class)
|
||||||
.getServer()
|
.getServer()
|
||||||
.vanillaCommandDispatcher();
|
.vanillaCommandDispatcher();
|
||||||
nmsDispatcher = vanillaCommandDispatcher.dispatcher();
|
nmsDispatcher = vanillaCommandDispatcher.dispatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a plugin command that overrides a vanilla command, so the vanilla command functionnalities are fully
|
||||||
|
* restored (so, not only the usage, but also the suggestions and the command structure sent to the client).
|
||||||
|
* @param name the name of the command to restore.
|
||||||
|
*/
|
||||||
|
public static void restoreVanillaCommand(String name) {
|
||||||
|
CommandMap bukkitCmdMap = Bukkit.getCommandMap();
|
||||||
|
Command bukkitCommand = bukkitCmdMap.getCommand(name);
|
||||||
|
if (bukkitCommand != null) {
|
||||||
|
if (VanillaCommandWrapper.REFLECT.get().isInstance(bukkitCommand)) {
|
||||||
|
Log.info("Command /" + name + " is already a vanilla command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log.info("Removing Bukkit command /" + name + " (" + getCommandIdentity(bukkitCommand) + ")");
|
||||||
|
bukkitCmdMap.getKnownCommands().remove(name.toLowerCase(java.util.Locale.ENGLISH));
|
||||||
|
bukkitCommand.unregister(bukkitCmdMap);
|
||||||
|
|
||||||
|
LiteralCommandNode<BukkitBrigadierCommandSource> node = (LiteralCommandNode<BukkitBrigadierCommandSource>) getRootNode().getChild(name);
|
||||||
|
Command newCommand = new VanillaCommandWrapper(vanillaCommandDispatcher, node).__getRuntimeInstance();
|
||||||
|
bukkitCmdMap.getKnownCommands().put(name.toLowerCase(), newCommand);
|
||||||
|
newCommand.register(bukkitCmdMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static CommandDispatcher<BukkitBrigadierCommandSource> getNMSDispatcher() {
|
/**
|
||||||
return nmsDispatcher;
|
* Returns the vanilla instance of the Brigadier dispatcher.
|
||||||
}
|
* @return the vanilla instance of the Brigadier dispatcher.
|
||||||
|
*/
|
||||||
|
public static CommandDispatcher<BukkitBrigadierCommandSource> getNMSDispatcher() {
|
||||||
|
return nmsDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
protected static RootCommandNode<BukkitBrigadierCommandSource> getRootNode() {
|
/**
|
||||||
return nmsDispatcher.getRoot();
|
* Returns the root command node of the Brigadier dispatcher.
|
||||||
}
|
* @return the root command node of the Brigadier dispatcher.
|
||||||
|
*/
|
||||||
protected Plugin plugin;
|
protected static RootCommandNode<BukkitBrigadierCommandSource> getRootNode() {
|
||||||
|
return nmsDispatcher.getRoot();
|
||||||
protected LiteralCommandNode<BukkitBrigadierCommandSource> commandNode;
|
}
|
||||||
|
|
||||||
private Set<String> allAliases;
|
|
||||||
|
|
||||||
public PaperBrigadierCommand(Plugin pl) {
|
|
||||||
plugin = pl;
|
|
||||||
commandNode = buildCommand().build();
|
|
||||||
postBuildCommand(commandNode);
|
|
||||||
register();
|
|
||||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void register() {
|
|
||||||
|
|
||||||
String[] aliases = getAliases();
|
|
||||||
if (aliases == null)
|
|
||||||
aliases = new String[0];
|
|
||||||
|
|
||||||
String pluginName = plugin.getName().toLowerCase();
|
|
||||||
|
|
||||||
allAliases = 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)
|
|
||||||
.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 = true;//prefixed || !isAlias;
|
|
||||||
|
|
||||||
// nmsDispatcher integration and conflit resolution
|
|
||||||
boolean nmsRegister = false, nmsRegistered = false;
|
|
||||||
CommandNode<BukkitBrigadierCommandSource> nmsConflited = root.getChild(name);
|
|
||||||
if (nmsConflited != null) {
|
|
||||||
|
|
||||||
if (isFromThisCommand(nmsConflited)) {
|
|
||||||
// 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 {
|
|
||||||
Log.severe("/" + name + " already in NMS Brigadier instance."
|
|
||||||
+ " Wont replace it because registration is not forced.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
allAliases.add(name);
|
|
||||||
|
|
||||||
// bukkit dispatcher conflict resolution
|
|
||||||
boolean bukkitRegister = false;
|
|
||||||
CommandMap bukkitCmdMap = Bukkit.getCommandMap();
|
|
||||||
Command bukkitConflicted = bukkitCmdMap.getCommand(name);
|
|
||||||
if (bukkitConflicted != null) {
|
|
||||||
if (isFromThisCommand(bukkitConflicted)) {
|
|
||||||
// nothing to do, already good
|
|
||||||
}
|
|
||||||
else if (forceRegistration) {
|
|
||||||
bukkitRegister = true;
|
|
||||||
Log.info("Overwriting Bukkit command /" + name
|
|
||||||
+ " (" + getCommandIdentity(bukkitConflicted) + ")");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log.severe("/" + name + " already in Bukkit"
|
|
||||||
+ " dispatcher (" + getCommandIdentity(bukkitConflicted)
|
|
||||||
+ "). Wont replace it because registration is not forced.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static String getCommandIdentity(Command bukkitCmd) {
|
|
||||||
if (bukkitCmd instanceof PluginCommand cmd) {
|
|
||||||
return "Bukkit command: /" + cmd.getName() + " from plugin " + cmd.getPlugin().getName();
|
|
||||||
}
|
|
||||||
else if (VanillaCommandWrapper.REFLECT.get().isInstance(bukkitCmd)) {
|
|
||||||
return "Vanilla command: /" + bukkitCmd.getName();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return bukkitCmd.getClass().getName() + ": /" + bukkitCmd.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerCommandSend(PlayerCommandSendEvent event) {
|
|
||||||
event.getCommands().removeAll(allAliases.stream().map(s -> "minecraft:" + s).toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onServerLoad(ServerLoadEvent event) {
|
|
||||||
register();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The permission that should be tested instead of "minecraft.command.cmdName".
|
|
||||||
*/
|
|
||||||
protected abstract String getTargetPermission();
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command node of this command.
|
||||||
|
*/
|
||||||
|
protected final LiteralCommandNode<BukkitBrigadierCommandSource> commandNode;
|
||||||
|
|
||||||
|
private final RegistrationPolicy registrationPolicy;
|
||||||
|
|
||||||
|
private Set<String> registeredAliases;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instanciate this command isntance.
|
||||||
|
*
|
||||||
|
* @param pl the plugin instance.
|
||||||
|
* @param regPolicy the registration policy for this command.
|
||||||
|
*/
|
||||||
|
public PaperBrigadierCommand(Plugin pl, RegistrationPolicy regPolicy) {
|
||||||
|
plugin = pl;
|
||||||
|
registrationPolicy = regPolicy;
|
||||||
|
commandNode = buildCommand().build();
|
||||||
|
postBuildCommand(commandNode);
|
||||||
|
register();
|
||||||
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
|
try {
|
||||||
|
PandalibPaperPermissions.addPermissionMapping("minecraft.command." + commandNode.getLiteral().toLowerCase(), getTargetPermission().toLowerCase());
|
||||||
|
} catch (NoClassDefFoundError ignored) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instanciate this command isntance with a registration policy of {@link RegistrationPolicy#ONLY_BASE_COMMAND}.
|
||||||
|
* @param pl the plugin instance.
|
||||||
|
*/
|
||||||
|
public PaperBrigadierCommand(Plugin pl) {
|
||||||
|
this(pl, RegistrationPolicy.ONLY_BASE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void register() {
|
||||||
|
|
||||||
|
String[] aliases = getAliases();
|
||||||
|
if (aliases == null)
|
||||||
|
aliases = new String[0];
|
||||||
|
|
||||||
|
String pluginName = plugin.getName().toLowerCase();
|
||||||
|
|
||||||
|
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)
|
||||||
|
.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> nmsConflited = root.getChild(name);
|
||||||
|
if (nmsConflited != null) {
|
||||||
|
|
||||||
|
if (isFromThisCommand(nmsConflited)) {
|
||||||
|
// 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 {
|
||||||
|
Log.severe("/" + name + " already in NMS Brigadier instance."
|
||||||
|
+ " Wont replace it because registration is not forced.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
Log.severe("/" + name + " already in Bukkit"
|
||||||
|
+ " dispatcher (" + getCommandIdentity(bukkitConflicted)
|
||||||
|
+ "). Wont replace it because registration is not forced.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
if (bukkitCmd instanceof PluginCommand cmd) {
|
||||||
|
return "Bukkit command: /" + cmd.getName() + " from plugin " + cmd.getPlugin().getName();
|
||||||
|
}
|
||||||
|
else if (VanillaCommandWrapper.REFLECT.get().isInstance(bukkitCmd)) {
|
||||||
|
return "Vanilla command: /" + bukkitCmd.getName();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return bukkitCmd.getClass().getName() + ": /" + bukkitCmd.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 abstract String getTargetPermission();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -263,198 +339,304 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isConsole(BukkitBrigadierCommandSource wrapper) {
|
public boolean isConsole(BukkitBrigadierCommandSource wrapper) {
|
||||||
return isConsole(getCommandSender(wrapper));
|
return isConsole(getCommandSender(wrapper));
|
||||||
}
|
}
|
||||||
public boolean isPlayer(BukkitBrigadierCommandSource wrapper) {
|
public boolean isPlayer(BukkitBrigadierCommandSource wrapper) {
|
||||||
return isPlayer(getCommandSender(wrapper));
|
return isPlayer(getCommandSender(wrapper));
|
||||||
}
|
}
|
||||||
public Predicate<BukkitBrigadierCommandSource> hasPermission(String permission) {
|
public Predicate<BukkitBrigadierCommandSource> hasPermission(String permission) {
|
||||||
return wrapper -> getCommandSender(wrapper).hasPermission(permission);
|
return wrapper -> getCommandSender(wrapper).hasPermission(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isConsole(CommandSender sender) {
|
|
||||||
return sender instanceof ConsoleCommandSender;
|
|
||||||
}
|
|
||||||
public boolean isPlayer(CommandSender sender) {
|
|
||||||
return sender instanceof Player;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static CommandSender getCommandSender(CommandContext<BukkitBrigadierCommandSource> context) {
|
|
||||||
return getCommandSender(context.getSource());
|
|
||||||
}
|
|
||||||
public static CommandSender getCommandSender(BukkitBrigadierCommandSource wrapper) {
|
|
||||||
return wrapper.getBukkitSender();
|
|
||||||
}
|
|
||||||
public static BukkitBrigadierCommandSource getBrigadierCommandSource(CommandSender sender) {
|
|
||||||
return VanillaCommandWrapper.getListener(sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final SuggestionsSupplier<CommandSender> TAB_WORLDS = (s, ti, token, a) -> SuggestionsSupplier.collectFilteredStream(Bukkit.getWorlds().stream().map(World::getName), token);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected SuggestionProvider<BukkitBrigadierCommandSource> wrapSuggestions(SuggestionsSupplier<CommandSender> suggestions) {
|
|
||||||
return wrapSuggestions(suggestions, PaperBrigadierCommand::getCommandSender);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected static com.mojang.brigadier.Command<BukkitBrigadierCommandSource> wrapCommand(com.mojang.brigadier.Command<BukkitBrigadierCommandSource> cmd) {
|
|
||||||
return context -> {
|
|
||||||
try {
|
|
||||||
return cmd.run(context);
|
|
||||||
} catch(CommandSyntaxException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.severe(t);
|
|
||||||
getCommandSender(context).sendMessage(Chat.failureText("Error while using the command: " + t));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Minecraft argument type
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public static ArgumentType<Object> argumentMinecraftEntity(boolean singleTarget, boolean playersOnly) {
|
|
||||||
if (playersOnly) {
|
|
||||||
return singleTarget ? EntityArgument.player() : EntityArgument.players();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return singleTarget ? EntityArgument.entity() : EntityArgument.entities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ArgumentType<Object> argumentMinecraftGameProfile() {
|
|
||||||
return GameProfileArgument.gameProfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ArgumentType<Object> argumentMinecraftResourceLocation() {
|
|
||||||
return ResourceLocationArgument.id();
|
|
||||||
}
|
|
||||||
public NamespacedKey tryGetMinecraftResourceLocationArgument(CommandContext<BukkitBrigadierCommandSource> context, String argument, NamespacedKey deflt) {
|
|
||||||
return tryGetArgument(context, argument, ResourceLocation.MAPPING.runtimeClass(),
|
|
||||||
nmsKey -> CraftNamespacedKey.fromMinecraft(ReflectWrapper.wrap(nmsKey, ResourceLocation.class)),
|
|
||||||
deflt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ArgumentType<Object> argumentMinecraftBlockPosition() {
|
/**
|
||||||
return BlockPosArgument.blockPos();
|
* Tells if the provided command sender is the console.
|
||||||
}
|
* @param sender the sender to test if it’s the console or not.
|
||||||
public BlockVector tryGetMinecraftBlockPositionArgument(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
* @return true if the sender is the console, false otherwise.
|
||||||
Coordinates coord = ReflectWrapper.wrap(tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass()), Coordinates.class);
|
*/
|
||||||
if (coord == null)
|
public boolean isConsole(CommandSender sender) {
|
||||||
return null;
|
return sender instanceof ConsoleCommandSender;
|
||||||
BlockPos bp = coord.getBlockPos(context.getSource());
|
}
|
||||||
return new BlockVector(bp.getX(), bp.getY(), bp.getZ());
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Tells if the provided command sender is a player.
|
||||||
|
* @param sender the sender to test if it’s a player or not.
|
||||||
|
* @return true if the sender is a player, false otherwise.
|
||||||
|
*/
|
||||||
public static ArgumentType<Object> argumentMinecraftVec3() {
|
public boolean isPlayer(CommandSender sender) {
|
||||||
return Vec3Argument.vec3(true);
|
return sender instanceof Player;
|
||||||
}
|
}
|
||||||
public Vector tryGetMinecraftVec3Argument(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
|
||||||
Coordinates coord = ReflectWrapper.wrap(tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass()), Coordinates.class);
|
|
||||||
return coord == null ? null : CraftVector.toBukkit(coord.getPosition(context.getSource()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Bukkit command sender from the provided context.
|
||||||
|
* @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) {
|
||||||
|
return getCommandSender(context.getSource());
|
||||||
|
}
|
||||||
|
|
||||||
public static ArgumentType<Object> argumentMinecraftChatComponent() {
|
/**
|
||||||
return ComponentArgument.textComponent();
|
* Gets the Bukkit command sender from the provided wrapper.
|
||||||
}
|
* @param wrapper the wrapper from which to get the Bukkit command sender.
|
||||||
public Component tryGetMinecraftChatComponentArgument(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
|
* @return the Bukkit command sender.
|
||||||
var nmsComponent = ReflectWrapper.wrap(
|
*/
|
||||||
tryGetArgument(context, argument, fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component.MAPPING.runtimeClass()),
|
public static CommandSender getCommandSender(BukkitBrigadierCommandSource wrapper) {
|
||||||
fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component.class
|
return wrapper.getBukkitSender();
|
||||||
);
|
}
|
||||||
return nmsComponent == null ? null : PaperAdventure.asAdventure(nmsComponent);
|
|
||||||
}
|
/**
|
||||||
|
* Gets a new instance of a command sender wrapper for the provided command sender.
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A suggestions supplier that suggests the names of the worlds currently loaded on this server.
|
||||||
|
*/
|
||||||
|
public static final SuggestionsSupplier<CommandSender> TAB_WORLDS = SuggestionsSupplier.fromStreamSupplier(() -> Bukkit.getWorlds().stream().map(World::getName));
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps the provided {@link SuggestionsSupplier} into a Brigadier’s {@link SuggestionProvider}.
|
||||||
|
* @param suggestions the suggestions to wrap.
|
||||||
|
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
|
||||||
|
*/
|
||||||
|
protected SuggestionProvider<BukkitBrigadierCommandSource> wrapSuggestions(SuggestionsSupplier<CommandSender> suggestions) {
|
||||||
|
return wrapSuggestions(suggestions, PaperBrigadierCommand::getCommandSender);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps the provided brigadier command executor in another one that logs eventual throw exceptions and informs the
|
||||||
|
* player.
|
||||||
|
* The default behaviour of the vanilla instance of the Brigadier dispatcher is to ignore any unchecked exception
|
||||||
|
* thrown by a command executor.
|
||||||
|
* @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) {
|
||||||
|
return context -> {
|
||||||
|
try {
|
||||||
|
return cmd.run(context);
|
||||||
|
} catch(CommandSyntaxException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.severe(t);
|
||||||
|
getCommandSender(context).sendMessage(Chat.failureText("Error while executing the command: " + t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minecraft argument type
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 defualt 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(), nmsCoord -> {
|
||||||
|
BlockPos bp = ReflectWrapper.wrap(nmsCoord, 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 defualt 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(),
|
||||||
|
nmsCoord -> CraftVector.toBukkit(
|
||||||
|
ReflectWrapper.wrap(nmsCoord, 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 defualt 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.
|
||||||
|
*/
|
||||||
|
ONLY_BASE_COMMAND,
|
||||||
|
/**
|
||||||
|
* Force the command and all of its aliases to be registered, even if a command with the same name or alias
|
||||||
|
* already exists in the vanilla Brigadier dispatcher.
|
||||||
|
*/
|
||||||
|
ALL
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ import org.bukkit.scoreboard.Team;
|
|||||||
|
|
||||||
import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
|
import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents any player on a paper server, either offline or online.
|
||||||
|
*/
|
||||||
public interface PaperOffPlayer extends AbstractOffPlayer {
|
public interface PaperOffPlayer extends AbstractOffPlayer {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -15,7 +18,7 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default boolean isOnline() {
|
default boolean isOnline() {
|
||||||
return (getBukkitPlayer() != null);
|
return getBukkitPlayer() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +32,8 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
|
|||||||
PaperOnlinePlayer getOnlineInstance();
|
PaperOnlinePlayer getOnlineInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return l'instance Bukkit du joueur en ligne, ou null si il n'est pas en
|
* Returns the Bukkit online {@link Player} instance of this player, or null if not available (offline).
|
||||||
* ligne
|
* @return the Bukkit online {@link Player} instance of this player, or null if not available (offline).
|
||||||
*/
|
*/
|
||||||
default Player getBukkitPlayer() {
|
default Player getBukkitPlayer() {
|
||||||
return Bukkit.getPlayer(getUniqueId());
|
return Bukkit.getPlayer(getUniqueId());
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package fr.pandacub.lib.paper.players;
|
package fr.pandacub.lib.paper.players;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.destroystokyo.paper.ClientOption;
|
import com.destroystokyo.paper.ClientOption;
|
||||||
import com.destroystokyo.paper.ClientOption.ChatVisibility;
|
import com.destroystokyo.paper.ClientOption.ChatVisibility;
|
||||||
import com.destroystokyo.paper.SkinParts;
|
import com.destroystokyo.paper.SkinParts;
|
||||||
|
import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
|
||||||
import net.kyori.adventure.audience.MessageType;
|
import net.kyori.adventure.audience.MessageType;
|
||||||
import net.kyori.adventure.identity.Identified;
|
import net.kyori.adventure.identity.Identified;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
@ -18,11 +16,14 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.MainHand;
|
import org.bukkit.inventory.MainHand;
|
||||||
|
|
||||||
import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents any online player on a paper server.
|
||||||
|
*/
|
||||||
public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer {
|
public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -46,12 +47,6 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
* Related class instances
|
* Related class instances
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @return l'instance Bukkit du joueur en ligne, ou null si il n'est pas en
|
|
||||||
* ligne
|
|
||||||
*/
|
|
||||||
Player getBukkitPlayer();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default OfflinePlayer getBukkitOfflinePlayer() {
|
default OfflinePlayer getBukkitOfflinePlayer() {
|
||||||
return getBukkitPlayer();
|
return getBukkitPlayer();
|
||||||
@ -100,10 +95,23 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
getBukkitPlayer().showTitle(Title.title(title, subtitle, Times.times(Ticks.duration(fadeIn), Ticks.duration(stay), Ticks.duration(fadeOut))));
|
getBukkitPlayer().showTitle(Title.title(title, subtitle, Times.times(Ticks.duration(fadeIn), Ticks.duration(stay), Ticks.duration(fadeOut))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play a sound on this player’s client, sourced at this player’s location.
|
||||||
|
* @param sound the sound to play
|
||||||
|
* @param volume the volume of the sound.
|
||||||
|
* @param pitch the pich in which the sound is played.
|
||||||
|
*/
|
||||||
default void playSound(Sound sound, float volume, float pitch) {
|
default void playSound(Sound sound, float volume, float pitch) {
|
||||||
playSound(sound, getBukkitPlayer().getLocation(), volume, pitch);
|
playSound(sound, getBukkitPlayer().getLocation(), volume, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play a sound on this player’s client.
|
||||||
|
* @param sound the sound to play
|
||||||
|
* @param location the source location of the sound.
|
||||||
|
* @param volume the volume of the sound.
|
||||||
|
* @param pitch the pich in which the sound is played.
|
||||||
|
*/
|
||||||
default void playSound(Sound sound, Location location, float volume, float pitch) {
|
default void playSound(Sound sound, Location location, float volume, float pitch) {
|
||||||
getBukkitPlayer().playSound(location, sound, volume, pitch);
|
getBukkitPlayer().playSound(location, sound, volume, pitch);
|
||||||
}
|
}
|
||||||
@ -119,11 +127,18 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
@Override
|
@Override
|
||||||
PaperClientOptions getClientOptions();
|
PaperClientOptions getClientOptions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides various configuration values of the Minecraft client.
|
||||||
|
*/
|
||||||
abstract class PaperClientOptions implements AbstractOnlinePlayer.ClientOptions {
|
abstract class PaperClientOptions implements AbstractOnlinePlayer.ClientOptions {
|
||||||
|
|
||||||
private final PaperOnlinePlayer op;
|
private final PaperOnlinePlayer op;
|
||||||
|
|
||||||
public PaperClientOptions(PaperOnlinePlayer op) {
|
/**
|
||||||
|
* Create a new instance of {@link PaperClientOptions}.
|
||||||
|
* @param op the {@link PaperOnlinePlayer} instance.
|
||||||
|
*/
|
||||||
|
protected PaperClientOptions(PaperOnlinePlayer op) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +147,10 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
return op.getBukkitPlayer().getClientOption(ClientOption.CHAT_COLORS_ENABLED);
|
return op.getBukkitPlayer().getClientOption(ClientOption.CHAT_COLORS_ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the chat visibility configuration.
|
||||||
|
* @return the chat visibility configuration.
|
||||||
|
*/
|
||||||
public ChatVisibility getChatVisibility() {
|
public ChatVisibility getChatVisibility() {
|
||||||
return op.getBukkitPlayer().getClientOption(ClientOption.CHAT_VISIBILITY);
|
return op.getBukkitPlayer().getClientOption(ClientOption.CHAT_VISIBILITY);
|
||||||
}
|
}
|
||||||
@ -162,6 +181,10 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
return op.getBukkitPlayer().getClientViewDistance();
|
return op.getBukkitPlayer().getClientViewDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player’s main hand.
|
||||||
|
* @return the player’s main hand.
|
||||||
|
*/
|
||||||
public MainHand getMainHand() {
|
public MainHand getMainHand() {
|
||||||
return op.getBukkitPlayer().getMainHand();
|
return op.getBukkitPlayer().getMainHand();
|
||||||
}
|
}
|
||||||
@ -177,13 +200,19 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract boolean isTextFilteringEnabled(); // needs reflection
|
public boolean isTextFilteringEnabled() { // needs reflection to get the actual value
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean allowsServerListing() {
|
public boolean allowsServerListing() {
|
||||||
return op.getBukkitPlayer().isAllowingServerListings();
|
return op.getBukkitPlayer().isAllowingServerListings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player’s skin configuration.
|
||||||
|
* @return the player’s skin configuration.
|
||||||
|
*/
|
||||||
public SkinParts getSkinParts() {
|
public SkinParts getSkinParts() {
|
||||||
return op.getBukkitPlayer().getClientOption(ClientOption.SKIN_PARTS);
|
return op.getBukkitPlayer().getClientOption(ClientOption.SKIN_PARTS);
|
||||||
}
|
}
|
||||||
@ -231,10 +260,19 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
* Custom damage
|
* Custom damage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals damages to this player.
|
||||||
|
* @param amount the amount of damage to deal.
|
||||||
|
*/
|
||||||
default void damage(double amount) {
|
default void damage(double amount) {
|
||||||
getBukkitPlayer().damage(amount); // uses DamageSource.GENERIC
|
getBukkitPlayer().damage(amount); // uses DamageSource.GENERIC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals damages to this player, from the provided entity.
|
||||||
|
* @param amount the amount of damage to deal.
|
||||||
|
* @param source the entity from which the damage comes from.
|
||||||
|
*/
|
||||||
default void damage(double amount, LivingEntity source) {
|
default void damage(double amount, LivingEntity source) {
|
||||||
getBukkitPlayer().damage(amount, source); // uses appropriate DamageSource according to provided player or entity
|
getBukkitPlayer().damage(amount, source); // uses appropriate DamageSource according to provided player or entity
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user