TinyProtocol: If player joins directly at server start, NPE on PlayerLoginEvent is thrown and no packets are received
Olexorus opened this issue ยท 1 comments
I'm using TinyProtocol to listen to KeepAlive packets to calculate the player ping accurately (because the NMS ping seems a bit random, or at least unaccurate, not sure why).
Generally this works really well, however when a player joins while the server is still loading (happens all the time if there are short restarts since people will try to get back on as soon as possible), a NPE is thrown. On top of that, intercepting packets doesn't work for those players afterwards.
Error message:
[12:22:11 INFO]: UUID of player Olexorus is 9c18e988-1a7d-4a79-b0bd-fd731e6fe655
[12:22:11 ERROR]: Could not pass event PlayerLoginEvent to WitherAC v0.10.1
java.lang.NullPointerException: null
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source) ~[?:1.8.0_211]
at sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(Unknown Source) ~[?:1.8.0_211]
at java.lang.reflect.Field.get(Unknown Source) ~[?:1.8.0_211]
at com.comphenix.tinyprotocol.Reflection$1.get(Reflection.java:149) ~[?:?]
at com.comphenix.tinyprotocol.TinyProtocol.getChannel(TinyProtocol.java:397) ~[?:?]
at com.comphenix.tinyprotocol.TinyProtocol$5.onPlayerLogin(TinyProtocol.java:176) ~[?:?]
at com.destroystokyo.paper.event.executor.MethodHandleEventExecutor.execute(MethodHandleEventExecutor.java:37) ~[patched_1.14.3.jar:git-Paper-115]
at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[patched_1.14.3.jar:git-Paper-115]
at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[patched_1.14.3.jar:git-Paper-115]
at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:536) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.PlayerList.attemptLogin(PlayerList.java:545) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.LoginListener.c(LoginListener.java:149) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.LoginListener.tick(LoginListener.java:65) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.NetworkManager.a(NetworkManager.java:255) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.ServerConnection.c(ServerConnection.java:129) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.MinecraftServer.b(MinecraftServer.java:1216) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.DedicatedServer.b(DedicatedServer.java:420) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.MinecraftServer.a(MinecraftServer.java:1064) ~[patched_1.14.3.jar:git-Paper-115]
at net.minecraft.server.v1_14_R1.MinecraftServer.run(MinecraftServer.java:908) ~[patched_1.14.3.jar:git-Paper-115]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_211]
[12:22:11 INFO]: Olexorus[/127.0.0.1:52494] logged in with entity id 87 at ([world]119.1430354820524, 73.0, -178.06247045625403)
Relevant plugin code:
object : TinyProtocol(WitherAC.INSTANCE) {
private val KEEP_ALIVE_IN_CLASS = Reflection.getClass("{nms}.PacketPlayInKeepAlive")
private val KEEP_ALIVE_OUT_CLASS = Reflection.getClass("{nms}.PacketPlayOutKeepAlive")
override fun onPacketInAsync(player: Player?, channel: Channel?, packet: Any?): Any {
if (KEEP_ALIVE_IN_CLASS.isInstance(packet)) {
val data = DataManager.getGeneralData(player!!)
data.ping = timeSince(data.lastKeepAlive).toInt()
}
return super.onPacketInAsync(player, channel, packet)
}
override fun onPacketOutAsync(player: Player?, channel: Channel?, packet: Any?): Any {
if (KEEP_ALIVE_OUT_CLASS.isInstance(packet)) {
val data = DataManager.getGeneralData(player!!)
data.lastKeepAlive = System.currentTimeMillis()
}
return super.onPacketOutAsync(player, channel, packet)
}
}
This code is called in the constructor of a class which is created in the onEnable() method of my plugin. If it's a problem that this is Kotlin code, I can translate it into Java.
Server version: The error log is from Paper 1.14.3 build 115, but I also tested it on the latest Paper build (127) and on Spigot 1.13.2.
I am using the latest TinyProtocol and Reflection sources files, directly from this repository.
If my plugin is needed for testing it can be downloaded from Spigot, I can also provide the obfuscation mappings if necessary (even though I doubt it's related to my plugin since the stacktrace points to TinyProtocol's code).