您好,我正在开发一个我的世界插件,使用 ProtocolLib 来修改玩家的姓名标签,以便当他们使用下界之星时,他们的姓名标签会发生变化。我的目标是暂时将玩家的姓名标签更改为紫色且粗体 2 分钟,然后将其重置回正常状态。但是,我在尝试修改数据包字段时遇到 FieldAccessException 错误。
package me.games.weapon;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import java.util.Collection;
import java.util.Collections;
public class SuperCharge implements Listener, CommandExecutor {
private final JavaPlugin plugin;
private final ProtocolManager protocolManager;
public SuperCharge(JavaPlugin plugin) {
this.plugin = plugin;
this.protocolManager = ProtocolLibrary.getProtocolManager();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender instanceof Player) {
Player player = (Player) sender;
// Create a new ItemStack for the Nether Star
ItemStack supercharge = new ItemStack(Material.NETHER_STAR);
// Give the player the Nether Star
player.getInventory().addItem(supercharge);
return true;
} else {
sender.sendMessage("You must be a player to use this command.");
return false;
}
}
@EventHandler
public void onPlayerUse(PlayerInteractEvent event) {
Player player = event.getPlayer();
ItemStack item = event.getItem();
if (item != null && item.getType() == Material.NETHER_STAR) {
// Apply the glowing effect for 2 minutes
player.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 2 * 60 * 20, 1));
// Change the player's name tag to purple and bold for 2 minutes
changePlayerNameTag(player);
// Schedule task to reset the player's name tag after 2 minutes (2400 ticks)
new BukkitRunnable() {
@Override
public void run() {
resetPlayerNameTag(player);
}
}.runTaskLater(plugin, 2 * 60 * 20);
// Remove the Nether Star from the player's inventory
player.getInventory().removeItem(new ItemStack(Material.NETHER_STAR, 1));
}
}
private void changePlayerNameTag(Player player) { // Currently isn't working and isn't coloring and bolding
PacketContainer nameTagPacket = protocolManager.createPacket(PacketType.Play.Server.PLAYER_INFO);
nameTagPacket.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
nameTagPacket.getPlayerInfoDataLists().write(0, Collections.singletonList(new PlayerInfoData(
WrappedGameProfile.fromPlayer(player),
1,
EnumWrappers.NativeGameMode.fromBukkit(player.getGameMode()),
WrappedChatComponent.fromText(ChatColor.BOLD + "" + ChatColor.LIGHT_PURPLE + player.getName())
)));
try {
protocolManager.sendServerPacket(player, nameTagPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
private void resetPlayerNameTag(Player player) {
PacketContainer nameTagPacket = protocolManager.createPacket(PacketType.Play.Server.PLAYER_INFO);
nameTagPacket.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME);
nameTagPacket.getPlayerInfoDataLists().write(0, Collections.singletonList(new PlayerInfoData(
WrappedGameProfile.fromPlayer(player),
1,
EnumWrappers.NativeGameMode.fromBukkit(player.getGameMode()),
WrappedChatComponent.fromText(player.getName()) // Original name without formatting
)));
try {
protocolManager.sendServerPacket(player, nameTagPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我尝试为团队使用 Spigot 的 API,但它只用一种颜色为玩家的姓名标签着色,并且不适用于在其顶部加粗等多种颜色。
现在我尝试使用 ProtocolLib 修改玩家的姓名标签,但我在服务器控制台中遇到此错误。我只是希望能够编辑玩家姓名标签并用多种颜色对其进行着色,无论什么方式都是可能的,但这些是我想到和尝试过的唯一方法。
[ERROR]: Could not pass event PlayerInteractEvent to Weapon v1.0-SNAPSHOT
com.comphenix.protocol.reflect.FieldAccessException: Field index 0 is out of bounds for length 0
at com.comphenix.protocol.reflect.FieldAccessException.fromFormat(FieldAccessException.java:49)
at com.comphenix.protocol.reflect.StructureModifier.write(StructureModifier.java:315)
at me.iplaygames.boostweapon.SuperCharge.changePlayerNameTag(SuperCharge.java:80)
at me.iplaygames.boostweapon.SuperCharge.onPlayerUse(SuperCharge.java:60)
...
自 Minecraft 1.19.3 起,一些有关玩家信息的数据包发生了变化。
现在,
PlayerInfo
数据包已重命名为PlayerInfoUpdate
(在ProtocolLib中,出于兼容性原因,它是相同的)。要删除,现在是PlayerInfoRemove
。
要添加内容,您应该使用
PlayerInfoUpdate
以及Players actions
中描述的一些特定选项。你应该像这样使用:
// create a new player info data
PlayerInfoData new_playerinfo = new PlayerInfoData(playerInfo.getProfileId(),
playerInfo.getLatency(), playerInfo.isListed(), playerInfo.getGameMode(),
playerInfo.getProfile(), new_tab_name, playerInfo.getProfileKeyData());
// write it into packet
nameTagPacket.getPlayerInfoDataLists().write(1, Collections.singletonList(new_playerinfo));