packetevents icon indicating copy to clipboard operation
packetevents copied to clipboard

SpigotConversionUtil.getEntityMetadata(entity) fails to work on modern versions

Open Cookleplex opened this issue 4 months ago • 5 comments

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

  1. Spawn/get a bukkit an entity (in my case a ItemFrame)
  2. Set some meta data values (in my case facing direction & item)
  3. run SpigotConversionUtil.getEntityMetadata(entity);
  4. 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();
            }
        }

Cookleplex avatar Aug 12 '25 23:08 Cookleplex

Show us your main class.

retrooper avatar Aug 15 '25 09:08 retrooper

Send the full stacktrace.

retrooper avatar Aug 15 '25 09:08 retrooper

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.

Cookleplex avatar Sep 13 '25 04:09 Cookleplex

Are you using 2.9.5 packetevents?

retrooper avatar Sep 13 '25 09:09 retrooper

Image Just tried it, now am, so yes.

Cookleplex avatar Sep 17 '25 00:09 Cookleplex