ProtocolLib

3M Downloads

Error when sometimes sending packet in response to PacketType.Login.Client.START

kyngs opened this issue ยท 3 comments

commented
  • This issue is not solved in a development build

Describe the bug
Sometimes (very irregular appearance, cannot find a real way to replicate) when using ProtocolManager#sendServerPacket in response to the PacketType.Login.Client.START packet, protocol lib throws the following exception. Firstly I thought this was an issue on my side, however, the stack trace indicates that protocol lib ducks something up internally.

To Reproduce
Steps to reproduce the behavior:

  1. Listen to the "PacketType.Login.Client.START" packet
  2. Respond with a valid packet of your choice.
  3. Be unlucky enough
  4. Observe

Expected behavior
The packet should send.

Screenshots
Not applicable

Version Info
dump-2023-07-28_18.36.56.txt

Additional context
Stack trace:

[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: java.lang.UnsupportedOperationException: The method getUniqueId is not supported for temporary players.
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.temporary.TemporaryPlayerFactory$1.delegate(TemporaryPlayerFactory.java:138)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.temporary.TemporaryPlayerInvocationHandler.getUniqueId(Unknown Source)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.BukkitUnwrapper.lambda$getProxyUnwrapper$0(BukkitUnwrapper.java:232)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.BukkitUnwrapper.unwrapItem(BukkitUnwrapper.java:125)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.utility.MinecraftFields.getNetworkManager(MinecraftFields.java:31)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.netty.channel.InjectionFactory.fromPlayer(InjectionFactory.java:96)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.netty.manager.NetworkManagerPlayerInjector.sendServerPacket(NetworkManagerPlayerInjector.java:59)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.PacketFilterManager.sendServerPacket(PacketFilterManager.java:183)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.PacketFilterManager.sendServerPacket(PacketFilterManager.java:157)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.injector.PacketFilterManager.sendServerPacket(PacketFilterManager.java:152)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at <redacted>.jar//<redacted>
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at <redacted>.jar//<redacted>
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.async.AsyncListenerHandler.processPacket(AsyncListenerHandler.java:622)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.async.AsyncListenerHandler.listenerLoop(AsyncListenerHandler.java:576)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.async.AsyncListenerHandler.access$100(AsyncListenerHandler.java:49)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.async.AsyncListenerHandler$1.run(AsyncListenerHandler.java:221)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at ProtocolLib.jar//com.comphenix.protocol.async.AsyncListenerHandler.lambda$start$1(AsyncListenerHandler.java:290)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at org.bukkit.craftbukkit.v1_20_R1.scheduler.CraftTask.run()
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at org.bukkit.craftbukkit.v1_20_R1.scheduler.CraftAsyncTask.run()
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run()
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[16:15:48] [Protocol Worker #2 - <redacted> /WARN]: 	at java.base/java.lang.Thread.run(Thread.java:833)

commented

The Player object from Bukkit is not available when the Login Start Event is received, so ProtocolLib provides a temporary Player instance. So you essentially try to send a packet to a player that is not (yet) online.

This could be a way to send a response packet:

@Override
public void onPacketReceiving(PacketEvent event) {
    PacketContainer container = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Login.Server.SUCCESS);
    if(event.isPlayerTemporary()) {
        MinimalInjector injector = TemporaryPlayerFactory.getInjectorFromPlayer(event.getPlayer());
        injector.sendServerPacket(container.getHandle(), null, false);
    } else {
        ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), container, false);
    }
}
commented

The Player object from Bukkit is not available when the Login Start Event is received, so ProtocolLib provides a temporary Player instance. So you essentially try to send a packet to a player that is not (yet) online.

This could be a way to send a response packet:

@Override
public void onPacketReceiving(PacketEvent event) {
    PacketContainer container = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Login.Server.SUCCESS);
    if(event.isPlayerTemporary()) {
        MinimalInjector injector = TemporaryPlayerFactory.getInjectorFromPlayer(event.getPlayer());
        injector.sendServerPacket(container.getHandle(), null, false);
    } else {
        ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), container, false);
    }
}

I find that this sometimes does not happen at all. Logically, this should happen every time, because there's no way the Player object could've been initialized at this point.

However, I think that such a check should be added inside the ProtocolManager#sendServerPacket, to make protocol lib easier to use.

commented

I had a closer look into the code and it looks like that ProtocolLib internally does exactly the same check internally. So I assume that there is a bug somewhere else.