SpigotConversionUtil.getEntityMetadata(entity) fails to work on modern versions
Describe the bug
When I try to use the SpigotConversionUtil.getEntityMetadata(entity) method on modern versions it seems to poop an error out ("SpigotReflectionUtil.CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD" is null).
Software brand
- packetevents-spigot:2.9.4
- spigot build CraftBukkit version 4527-Spigot-7c52c66-4f0c392 (MC: 1.21.8) (Implementing API version 1.21.8-R0.1-SNAPSHOT)
Plugins
Just my custom plugin that shades PacketEvents.
How To Reproduce
- Spawn/get a bukkit an entity (in my case a ItemFrame)
- Set some meta data values (in my case facing direction & item)
- run SpigotConversionUtil.getEntityMetadata(entity);
- See error
Expected behavior I expected to get the list of entity data the entity should have so I can send it.
Context My Code:
private List<EntityData<?>> createMapIdMeta(int mapId, BlockFace facing) {
World world = Bukkit.getWorlds().get(0);
ItemFrame frame = world.spawn(new Location(world, 0, world.getMinHeight()-1000, 0), ItemFrame.class);
try {
frame.setFacingDirection(facing);
ItemStack itemStack = new ItemStack(Material.FILLED_MAP);
if (itemStack.getItemMeta() instanceof MapMeta meta) {
meta.setMapView(Bukkit.getMap(mapId));
itemStack.setItemMeta(meta);
}
frame.setItem(itemStack);
frame.setFixed(true);
frame.setInvulnerable(true);
frame.setSilent(true);
return SpigotConversionUtil.getEntityMetadata(frame);
} finally {
frame.remove();
}
}
Show us your main class.
Send the full stacktrace.
minimal plugin example:
package me.cookleplex.derp;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.ItemFrame;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
public final class Derp extends JavaPlugin implements Listener {
private final AtomicInteger nextEntityId = new AtomicInteger(2_000_000);
private boolean enabled;
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
PacketEvents.getAPI().load();
PacketEvents.getAPI().init();
enabled = true;
}
@Override
public void onDisable() {
if (!enabled) return;
enabled = false;
PacketEvents.getAPI().terminate();
}
@EventHandler
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
if (!event.isSneaking()) return;
var player = event.getPlayer();
Location playerLoc = player.getLocation();
Location frameLoc = playerLoc.clone().subtract(0.0, 1.0, 0.0);
List<EntityData<?>> metadata = createMapIdMeta(0, BlockFace.UP);
int entityId = nextEntityId.getAndIncrement();
UUID fakeUuid = UUID.randomUUID();
WrapperPlayServerSpawnEntity spawnPacket = new WrapperPlayServerSpawnEntity(
entityId,
fakeUuid,
EntityTypes.ITEM_FRAME,
SpigotConversionUtil.fromBukkitLocation(frameLoc),
frameLoc.getYaw(),
0,
null
);
WrapperPlayServerEntityMetadata metaPacket = new WrapperPlayServerEntityMetadata(entityId, metadata);
PacketEvents.getAPI().getPlayerManager().sendPacket(player, spawnPacket);
PacketEvents.getAPI().getPlayerManager().sendPacket(player, metaPacket);
}
private List<EntityData<?>> createMapIdMeta(int mapId, BlockFace facing) {
World world = Bukkit.getWorlds().get(0);
ItemFrame frame = world.spawn(new Location(world, 0, world.getMinHeight() - 1000, 0), ItemFrame.class);
try {
frame.setFacingDirection(facing);
ItemStack itemStack = new ItemStack(Material.FILLED_MAP);
if (itemStack.getItemMeta() instanceof MapMeta meta) {
meta.setMapView(Bukkit.getMap(mapId));
itemStack.setItemMeta(meta);
}
frame.setItem(itemStack);
frame.setFixed(true);
frame.setInvulnerable(true);
frame.setSilent(true);
return SpigotConversionUtil.getEntityMetadata(frame);
} finally {
frame.remove();
}
}
}
[21:50:21] [Server thread/ERROR]: Could not pass event PlayerToggleSneakEvent to Derp v1.0-SNAPSHOT
org.bukkit.event.EventException: null
at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot-api-1.21.8-R0.1-SNAPSHOT.jar:?]
at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[spigot-api-1.21.8-R0.1-SNAPSHOT.jar:?]
at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:601) ~[spigot-api-1.21.8-R0.1-SNAPSHOT.jar:?]
at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:588) ~[spigot-api-1.21.8-R0.1-SNAPSHOT.jar:?]
at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:493) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.network.protocol.game.PacketPlayInSteerVehicle.a(SourceFile:22) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.network.protocol.game.PacketPlayInSteerVehicle.a(SourceFile:9) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$ensureRunningOnSameThread$0(PlayerConnectionUtils.java:35) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.util.thread.IAsyncTaskHandler.d(SourceFile:164) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.d(SourceFile:23) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1290) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.d(MinecraftServer.java:209) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.util.thread.IAsyncTaskHandler.B(SourceFile:138) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.bv(MinecraftServer.java:1273) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.B(MinecraftServer.java:1266) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.util.thread.IAsyncTaskHandler.b(SourceFile:147) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1223) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.w_(MinecraftServer.java:1233) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1076) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:328) ~[spigot-1.21.8-R0.1-SNAPSHOT.jar:4530-Spigot-7c52c66-55f04da]
at java.base/java.lang.Thread.run(Thread.java:1583) [?:?]
Caused by: java.lang.RuntimeException: java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "me.cookleplex.shadow.packetevents.impl.util.SpigotReflectionUtil.CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD" is null
at me.cookleplex.shadow.packetevents.impl.util.SpigotReflectionUtil.getEntityMetadata(SpigotReflectionUtil.java:1237) ~[?:?]
at me.cookleplex.shadow.packetevents.impl.util.SpigotConversionUtil.getEntityMetadata(SpigotConversionUtil.java:250) ~[?:?]
at me.cookleplex.derp.Derp.createMapIdMeta(Derp.java:97) ~[?:?]
at me.cookleplex.derp.Derp.onPlayerToggleSneak(Derp.java:58) ~[?:?]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?]
at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot-api-1.21.8-R0.1-SNAPSHOT.jar:?]
... 21 more
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "me.cookleplex.shadow.packetevents.impl.util.SpigotReflectionUtil.CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD" is null
at me.cookleplex.shadow.packetevents.impl.util.SpigotReflectionUtil.getEntityMetadata(SpigotReflectionUtil.java:1232) ~[?:?]
at me.cookleplex.shadow.packetevents.impl.util.SpigotConversionUtil.getEntityMetadata(SpigotConversionUtil.java:250) ~[?:?]
at me.cookleplex.derp.Derp.createMapIdMeta(Derp.java:97) ~[?:?]
at me.cookleplex.derp.Derp.onPlayerToggleSneak(Derp.java:58) ~[?:?]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?]
at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot-api-1.21.8-R0.1-SNAPSHOT.jar:?]
... 21 more
>
It works on paper, I tested it, it is just spigot that has this problem. Kind of funny because it is called spigot utility.
Are you using 2.9.5 packetevents?