[1.20.2] RESPAWN packet error
ThomasMo54 opened this issue ยท 4 comments
- This issue is not solved in a development build
Describe the bug
Back in 1.19.4 I was using this piece of code to send a respawn packet to a player and it worked fine:
val respawnPacket = protocolManager.createPacket(PacketType.Play.Server.RESPAWN)
val dimensionType = respawnPacket.structures.read(0)
dimensionType.minecraftKeys.write(0, MinecraftKey("minecraft", "dimension_type"))
dimensionType.minecraftKeys.write(1, MinecraftKey("minecraft", "overworld"))
respawnPacket.structures.write(0, dimensionType)
respawnPacket.longs.write(0, 0L)
respawnPacket.worldKeys.write(0, player.world)
respawnPacket.gameModes.write(0, EnumWrappers.NativeGameMode.fromBukkit(player.gameMode))
respawnPacket.gameModes.write(1, EnumWrappers.NativeGameMode.fromBukkit(player.gameMode))
respawnPacket.booleans.write(0, false)
respawnPacket.booleans.write(1, false)
respawnPacket.booleans.writeSafely(2, false)
respawnPacket.getOptionals(Converters.passthrough(Object::class.java)).write(0, Optional.empty())
However since I updated my server to 1.20.2 this code does not work anymore, here's the thrown exception:
com.comphenix.protocol.reflect.FieldAccessException: Field index 0 is out of bounds for length 0
at com.comphenix.protocol.reflect.FieldAccessException.fromFormat(FieldAccessException.java:49) ~[ProtocolLib.jar:?]
at com.comphenix.protocol.reflect.StructureModifier.write(StructureModifier.java:316) ~[ProtocolLib.jar:?]
at com.mineofwar.minecraft.common.paper.core.player.InternalPlayer.updateSkin(InternalPlayer.kt:278) ~[lobby-local.jar:?]
at com.mineofwar.minecraft.common.paper.core.player.InternalPlayer.nick$lambda$19(InternalPlayer.kt:332) ~[lobby-local.jar:?]
at org.bukkit.craftbukkit.v1_20_R2.scheduler.CraftTask.run(CraftTask.java:101) ~[paper-1.20.2.jar:git-Paper-246]
at org.bukkit.craftbukkit.v1_20_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:480) ~[paper-1.20.2.jar:git-Paper-246]
at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1470) ~[paper-1.20.2.jar:git-Paper-246]
at net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:446) ~[paper-1.20.2.jar:git-Paper-246]
at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1379) ~[paper-1.20.2.jar:git-Paper-246]
at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1156) ~[paper-1.20.2.jar:git-Paper-246]
at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:315) ~[paper-1.20.2.jar:git-Paper-246]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
Note that InternalPlayer.kt:278
refers to the dimensionType.minecraftKeys.write(0, MinecraftKey("minecraft", "dimension_type"))
line.
I suppose that the packet structure changed in 1.20.x but i can't find the updated one.
Version Info
Version info.
After some investigations it seems like the packet structure has indeed changed. It now only contains a CommonPlayerSpawnInfo
object that contains all the previous packet data.
Can we expect that a support for this object will be added in the future? If not I would be glad to know how to make things work without it.
Here's what the packet structure looks like when I print it in the console :
net.minecraft.network.protocol.game.PacketPlayOutRespawn@4038b7b7[
d=CommonPlayerSpawnInfo[dimensionType=ResourceKey[minecraft:dimension_type / minecraft:overworld], dimension=ResourceKey[minecraft:dimension / minecraft:overworld], seed=6667425060927977019, gameType=SURVIVAL, previousGameType=CREATIVE, isDebug=false, isFlat=false, lastDeathLocation=Optional[ResourceKey[minecraft:dimension / minecraft:overworld] BlockPosition{x=2, y=66, z=6}], portalCooldown=0]
e=0
]
After some investigations it seems like the packet structure has indeed changed. It now only contains a
CommonPlayerSpawnInfo
object that contains all the previous packet data.Can we expect that a support for this object will be added in the future? If not I would be glad to know how to make things work without it.
Here's what the packet structure looks like when I print it in the console :
net.minecraft.network.protocol.game.PacketPlayOutRespawn@4038b7b7[ d=CommonPlayerSpawnInfo[dimensionType=ResourceKey[minecraft:dimension_type / minecraft:overworld], dimension=ResourceKey[minecraft:dimension / minecraft:overworld], seed=6667425060927977019, gameType=SURVIVAL, previousGameType=CREATIVE, isDebug=false, isFlat=false, lastDeathLocation=Optional[ResourceKey[minecraft:dimension / minecraft:overworld] BlockPosition{x=2, y=66, z=6}], portalCooldown=0] e=0 ]
Were you able to figure out a way to work around it?
After some investigations it seems like the packet structure has indeed changed. It now only contains a
CommonPlayerSpawnInfo
object that contains all the previous packet data.
Can we expect that a support for this object will be added in the future? If not I would be glad to know how to make things work without it.
Here's what the packet structure looks like when I print it in the console :net.minecraft.network.protocol.game.PacketPlayOutRespawn@4038b7b7[ d=CommonPlayerSpawnInfo[dimensionType=ResourceKey[minecraft:dimension_type / minecraft:overworld], dimension=ResourceKey[minecraft:dimension / minecraft:overworld], seed=6667425060927977019, gameType=SURVIVAL, previousGameType=CREATIVE, isDebug=false, isFlat=false, lastDeathLocation=Optional[ResourceKey[minecraft:dimension / minecraft:overworld] BlockPosition{x=2, y=66, z=6}], portalCooldown=0] e=0 ]
Were you able to figure out a way to work around it?
Yes! You just need to set all the fields inside a structure instead of the packet directly. Here's what I have :
val respawnPacket = protocolManager.createPacket(PacketType.Play.Server.RESPAWN)
val playerSpawnInfo = respawnPacket.structures.read(0)
playerSpawnInfo.dimensionTypes.writeSafely(0, player.world)
getDimensionType(player.world)?.let { playerSpawnInfo.modifier.write(0, it) }
playerSpawnInfo.longs.write(0, Hashing.sha256().hashLong(player.world.seed).asLong())
playerSpawnInfo.worldKeys.write(0, player.world)
playerSpawnInfo.gameModes.write(0, EnumWrappers.NativeGameMode.fromBukkit(player.gameMode))
playerSpawnInfo.gameModes.write(1, EnumWrappers.NativeGameMode.fromBukkit(player.gameMode))
playerSpawnInfo.booleans.write(0, false)
playerSpawnInfo.booleans.write(1, false)
playerSpawnInfo.booleans.writeSafely(2, false)
respawnPacket.structures.write(0, playerSpawnInfo)
Working perfectly.
After some investigations it seems like the packet structure has indeed changed. It now only contains a
CommonPlayerSpawnInfo
object that contains all the previous packet data.
Can we expect that a support for this object will be added in the future? If not I would be glad to know how to make things work without it.
Here's what the packet structure looks like when I print it in the console :net.minecraft.network.protocol.game.PacketPlayOutRespawn@4038b7b7[ d=CommonPlayerSpawnInfo[dimensionType=ResourceKey[minecraft:dimension_type / minecraft:overworld], dimension=ResourceKey[minecraft:dimension / minecraft:overworld], seed=6667425060927977019, gameType=SURVIVAL, previousGameType=CREATIVE, isDebug=false, isFlat=false, lastDeathLocation=Optional[ResourceKey[minecraft:dimension / minecraft:overworld] BlockPosition{x=2, y=66, z=6}], portalCooldown=0] e=0 ]
Were you able to figure out a way to work around it?
Yes! You just need to set all the fields inside a structure instead of the packet directly. Here's what I have :
val respawnPacket = protocolManager.createPacket(PacketType.Play.Server.RESPAWN) val playerSpawnInfo = respawnPacket.structures.read(0) playerSpawnInfo.dimensionTypes.writeSafely(0, player.world) getDimensionType(player.world)?.let { playerSpawnInfo.modifier.write(0, it) } playerSpawnInfo.longs.write(0, Hashing.sha256().hashLong(player.world.seed).asLong()) playerSpawnInfo.worldKeys.write(0, player.world) playerSpawnInfo.gameModes.write(0, EnumWrappers.NativeGameMode.fromBukkit(player.gameMode)) playerSpawnInfo.gameModes.write(1, EnumWrappers.NativeGameMode.fromBukkit(player.gameMode)) playerSpawnInfo.booleans.write(0, false) playerSpawnInfo.booleans.write(1, false) playerSpawnInfo.booleans.writeSafely(2, false) respawnPacket.structures.write(0, playerSpawnInfo)Working perfectly.
Sorry for reopening this thread, but how did you get the Dimension type? I cant find any resources online explaining this.