ProtocolLib

3M Downloads

PacketType.Play.Server.EXPLOSION generates java.lang.NullPointerException

antoningfors opened this issue ยท 6 comments

commented

I am trying to run example code provided on the ReadMe page. It does however generate a NullPointerException as soon as the PlayerInteractEvent in triggered.

public void onPlayerInteractEvent(PlayerInteractEvent e)
{
        ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
        PacketContainer fakeExplosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
        fakeExplosion.getDoubles().
                write(0, e.getPlayer().getLocation().getX()).
                write(1, e.getPlayer().getLocation().getY()).
                write(2, e.getPlayer().getLocation().getZ());
        fakeExplosion.getFloat().write(0, 3.0F);

        try {
            protocolManager.sendServerPacket(e.getPlayer(), fakeExplosion);
        } catch (InvocationTargetException e1) {
            throw new RuntimeException(
                    "Cannot send packet " + fakeExplosion, e1);
        }
}

Server Console

[17:07:15 ERROR]: java.lang.NullPointerException
[17:07:15 WARN]: java.lang.NullPointerException
[17:07:15 WARN]:        at net.minecraft.server.v1_15_R1.PacketPlayOutExplosion.b(SourceFile:72)
[17:07:15 WARN]:        at net.minecraft.server.v1_15_R1.PacketEncoder.encode(PacketEncoder.java:42)
[17:07:15 WARN]:        at net.minecraft.server.v1_15_R1.PacketEncoder.encode(PacketEncoder.java:12)
[17:07:15 WARN]:        at sun.reflect.GeneratedMethodAccessor8.invoke(Unknown Source)
[17:07:15 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
[17:07:15 WARN]:        at java.lang.reflect.Method.invoke(Unknown Source)
[17:07:15 WARN]:        at com.comphenix.protocol.injector.netty.ChannelInjector.encode(ChannelInjector.java:473)
[17:07:15 WARN]:        at com.comphenix.protocol.injector.netty.ChannelInjector.access$100(ChannelInjector.java:64)
[17:07:15 WARN]:        at com.comphenix.protocol.injector.netty.ChannelInjector$1.encode(ChannelInjector.java:243)
[17:07:15 WARN]:        at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107)
[17:07:15 WARN]:        at com.comphenix.protocol.injector.netty.ChannelInjector$1.write(ChannelInjector.java:249)
[17:07:15 WARN]:        at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
[17:07:15 WARN]:        at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:801)
[17:07:15 WARN]:        at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814)
[17:07:15 WARN]:        at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794)
[17:07:15 WARN]:        at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:831)
[17:07:15 WARN]:        at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1071)
[17:07:15 WARN]:        at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:300)
[17:07:15 WARN]:        at com.comphenix.protocol.injector.netty.ChannelProxy.writeAndFlush(ChannelProxy.java:327)
[17:07:15 WARN]:        at net.minecraft.server.v1_15_R1.NetworkManager.lambda$b$4(NetworkManager.java:205)
[17:07:15 WARN]:        at com.comphenix.protocol.injector.netty.ChannelInjector$3.lambda$onMessageScheduled$1(ChannelInjector.java:321)
[17:07:15 WARN]:        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
[17:07:15 WARN]:        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
[17:07:15 WARN]:        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:465)
[17:07:15 WARN]:        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
[17:07:15 WARN]:        at java.lang.Thread.run(Unknown Source)
[17:07:15 INFO]: KNAAAAAAAAAAS lost connection: Internal Exception: io.netty.handler.codec.EncoderException: java.lang.NullPointerException

Screenshots
Client side error when PlayerInteractEvent is triggered.
https://imgur.com/a/vsj6ezG

Server Console when PlayerInteractEvent is triggered.
https://imgur.com/a/3tnORnO

Expected behavior
I expect an Explosion where the player is standing.

Version Info
https://pastebin.com/pLLTaihv

commented

the packet looks way different nowadays. The readme examples are only a guide how to set fields using protocollib, they never get updated to new protocol versions since the protocol changes all the time and protocollib works on any protocol version.

take a look at the protocol documentation to see the new fields you need to set:
https://wiki.vg/Protocol#Explosion

commented

I'm working on making some new documentation on the wiki. Stay tuned.

commented

Some docs would be much appreciated. I tried to modify my code following the 1.15.1 standards. I do however run into problems here is what I got.

Code

@EventHandler
    public void onPlayerInteractEvent(PlayerInteractEvent e)
    {
        ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
        PacketContainer fakeExplosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
        fakeExplosion.getFloat().
                write(0, (float) e.getPlayer().getLocation().getX()). // X
                write(1, (float) e.getPlayer().getLocation().getY()). // Y
                write(2, (float) e.getPlayer().getLocation().getZ()). // Z
                write(3, 0F). // Radius
                write(4, 0F). // Player Motion X
                write(5, 0F). // Player Motion Y
                write(6, 0F); // Player Motion Z


        byte[] records = {0x00b, 0x00b, 0x00b};
        fakeExplosion.getIntegers().write(0, records.length); // Record Count
        fakeExplosion.getByteArrays().write(0, records ); // Records

        try {
            protocolManager.sendServerPacket(e.getPlayer(), fakeExplosion);
        } catch (InvocationTargetException e1) {
            throw new RuntimeException(
                    "Cannot send packet " + fakeExplosion, e1);
        }
}

The client does no longer crash but no explosion can be seen. The server however generates a Field index out of bounds.

Console Error

[16:43:02 ERROR]: Could not pass event PlayerInteractEvent to Survival v1.0-SNAPSHOT
com.comphenix.protocol.reflect.FieldAccessException: Field index out of bounds. (Index: 4, Size: 4)
        at com.comphenix.protocol.reflect.StructureModifier.writeInternal(StructureModifier.java:367) ~[?:?]
        at com.comphenix.protocol.reflect.StructureModifier.write(StructureModifier.java:343) ~[?:?]
        at org.mushroomcraft.items.ItemListener.onPlayerInteractEvent(ItemListener.java:35) ~[?:?]
        at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor19.execute(Unknown Source) ~[?:?]
        at org.bukkit.plugin.EventExecutor.lambda$create$1(EventExecutor.java:69) ~[patched_1.15.1.jar:git-Paper-25]
        at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[patched_1.15.1.jar:git-Paper-25]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[patched_1.15.1.jar:git-Paper-25]        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:545) ~[patched_1.15.1.jar:git-Paper-25]
        at org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:457) ~[patched_1.15.1.jar:git-Paper-25]
        at org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:424) ~[patched_1.15.1.jar:git-Paper-25]
        at org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:420) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.PlayerConnection.a(PlayerConnection.java:1858) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.PacketPlayInArmAnimation.a(SourceFile:31) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.PacketPlayInArmAnimation.a(SourceFile:9) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.PlayerConnectionUtils.lambda$ensureMainThread$0(PlayerConnectionUtils.java:23) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.TickTask.run(SourceFile:18) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.IAsyncTaskHandler.executeTask(IAsyncTaskHandler.java:136) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.IAsyncTaskHandlerReentrant.executeTask(SourceFile:23) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.IAsyncTaskHandler.executeNext(IAsyncTaskHandler.java:109) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.MinecraftServer.aZ(MinecraftServer.java:1037) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.MinecraftServer.executeNext(MinecraftServer.java:1030) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.IAsyncTaskHandler.awaitTasks(IAsyncTaskHandler.java:119) ~[patched_1.15.1.jar:git-Paper-25]
        at net.minecraft.server.v1_15_R1.MinecraftServer.a(MinecraftServer.java:1096) ~[patched_1.15.1.jar:git-Paper-25]        at net.minecraft.server.v1_15_R1.MinecraftServer.run(MinecraftServer.java:933) ~[patched_1.15.1.jar:git-Paper-25]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_221]
commented

wiki.vg is not correct, the type should be:

X | Double
Y | Double
Z | Double
Records | List of BlockPosition
Radius | Float
Player Motion X | Float
Player Motion Y | Float
Player Motion Z | Float

commented

no its right:

public void a(PacketDataSerializer var0) throws IOException {
        this.a = (double)var0.readFloat();
        this.b = (double)var0.readFloat();
        this.c = (double)var0.readFloat();
        this.d = var0.readFloat();
        int var1 = var0.readInt();
        this.e = Lists.newArrayListWithCapacity(var1);
        int var2 = (int)this.a;
        int var3 = (int)this.b;
        int var4 = (int)this.c;

        for(int var5 = 0; var5 < var1; ++var5) {
            int var6 = var0.readByte() + var2;
            int var7 = var0.readByte() + var3;
            int var8 = var0.readByte() + var4;
            this.e.add(new BlockPosition(var6, var7, var8));
        }

        this.f = var0.readFloat();
        this.g = var0.readFloat();
        this.h = var0.readFloat();
    }

wiki.vg documents the protocol, not the actual impl minecraft used.

in this case, the minecraft impl (the fields in the packet class) doesnt match with the actual format on the wire. using protocollib you write to the fields, not to the wire, so your format is applicable here.

commented

The correct solution for the BlockPos seems to be:
container.getBlockPositionCollectionModifier().writeDefaults();
In case you want to send the BlockPositions, you can of course use write(0, list);