network: only clear chunks when changing dimensions after respawn

This fixes missing chunks when the server does some dirty hacking with respawn packets
This commit is contained in:
Bixilon 2022-12-14 18:59:39 +01:00
parent 14588f55c4
commit d3c96e6c6e
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
8 changed files with 30 additions and 28 deletions

View File

@ -154,7 +154,7 @@ class WorldRenderer(
connection.events.listen<VisibilityGraphChangeEvent> { onFrustumChange() }
connection.events.listen<RespawnEvent> { unloadWorld() }
connection.events.listen<RespawnEvent> { if (it.dimensionChange) unloadWorld() }
connection.events.listen<ChunkDataChangeEvent> { queueChunk(it.chunkPosition, it.chunk) }
connection.events.listen<BlockSetEvent> {
val chunkPosition = it.blockPosition.chunkPosition

View File

@ -14,12 +14,9 @@ package de.bixilon.minosoft.modding.event.events
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.s2c.play.RespawnS2CP
@Deprecated("Observables")
class RespawnEvent(
connection: PlayConnection,
) : PlayConnectionEvent(connection) {
constructor(connection: PlayConnection, packet: RespawnS2CP) : this(connection)
}
val dimensionChange: Boolean,
) : PlayConnectionEvent(connection)

View File

@ -27,5 +27,5 @@ class ChunkDataChangeEvent(
val chunk: Chunk,
) : PlayConnectionEvent(connection) {
constructor(connection: PlayConnection, packet: ChunkS2CP) : this(connection, packet.chunkPosition, connection.world[packet.chunkPosition]!!)
constructor(connection: PlayConnection, packet: ChunkS2CP) : this(connection, packet.position, connection.world[packet.position]!!)
}

View File

@ -124,7 +124,6 @@ class ConnectionUtil(
}
fun prepareSpawn() {
connection.world.clear()
connection.player.velocity = Vec3d.EMPTY
connection.world.audioPlayer?.stopAllSounds()
connection.world.particleRenderer?.removeAllParticles()

View File

@ -146,6 +146,7 @@ class InitializeS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
override fun handle(connection: PlayConnection) {
connection.world.clear()
connection.util.prepareSpawn()
val playerEntity = connection.player
val previousGamemode = playerEntity.additional.gamemode

View File

@ -107,9 +107,13 @@ class RespawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
override fun handle(connection: PlayConnection) {
connection.util.prepareSpawn()
connection.player.additional.gamemode = gamemode
val dimensionChange = this.dimension != connection.world.dimension
if (dimensionChange) {
connection.world.clear()
}
connection.world.dimension = dimension
connection.state = PlayConnectionStates.SPAWNING
connection.fire(RespawnEvent(connection, this))
connection.fire(RespawnEvent(connection, dimensionChange))
}
override fun log(reducedLog: Boolean) {

View File

@ -50,9 +50,9 @@ import java.util.*
@LoadPacket(lowPriority = true)
class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
val chunkPosition: Vec2i
val chunkData: ChunkData = ChunkData()
var unloadChunk: Boolean = false
val position: Vec2i
val data: ChunkData = ChunkData()
var unload: Boolean = false
private set
var heightMap: Map<String, Any>? = null
private set
@ -61,7 +61,7 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
init {
val dimension = buffer.connection.world.dimension!!
chunkPosition = buffer.readChunkPosition()
position = buffer.readChunkPosition()
if (buffer.versionId < V_20W45A) {
isFullChunk = !buffer.readBoolean()
}
@ -77,9 +77,9 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
val chunkData = ChunkUtil.readChunkPacket(decompressed, dimension, sectionBitMask, addBitMask, !isFullChunk, dimension.hasSkyLight)
if (chunkData == null) {
unloadChunk = true
unload = true
} else {
this.chunkData.replace(chunkData)
this.data.replace(chunkData)
}
} else {
if (buffer.versionId in V_1_16_PRE7 until V_1_16_2_PRE2) {
@ -96,7 +96,7 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
heightMap = buffer.readNBT()?.toJsonObject()
}
if (!isFullChunk && buffer.versionId < V_21W37A) {
this.chunkData.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
this.data.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
}
readingData = ChunkReadingData(PlayInByteBuffer(buffer.readByteArray(), buffer.connection), dimension, sectionBitMask)
@ -109,7 +109,7 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
buffer.versionId < V_21W37A -> {
val blockEntities: MutableMap<Vec3i, BlockEntity> = mutableMapOf()
val positionOffset = Vec3i.of(chunkPosition, dimension.minSection, Vec3i.EMPTY)
val positionOffset = Vec3i.of(position, dimension.minSection, Vec3i.EMPTY)
for (i in 0 until buffer.readVarInt()) {
val nbt = buffer.readNBT().asJsonObject()
val position = Vec3i(nbt["x"]?.toInt() ?: continue, nbt["y"]?.toInt() ?: continue, nbt["z"]?.toInt() ?: continue) - positionOffset
@ -123,7 +123,7 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
entity.updateNBT(nbt)
blockEntities[position] = entity
}
this.chunkData.blockEntities = blockEntities
this.data.blockEntities = blockEntities
}
else -> {
@ -141,7 +141,7 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
blockEntities[Vec3i(xz shr 4, y, xz and 0x0F)] = entity
}
this.chunkData.blockEntities = blockEntities
this.data.blockEntities = blockEntities
}
}
@ -149,7 +149,7 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
if (StaticConfiguration.IGNORE_SERVER_LIGHT) {
buffer.pointer = buffer.size
} else {
this.chunkData.replace(ChunkLightS2CP(buffer, chunkPosition).chunkData)
this.data.replace(ChunkLightS2CP(buffer, position).chunkData)
}
}
}
@ -159,30 +159,30 @@ class ChunkS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
if (readingData.buffer.versionId < V_21W37A) {
val chunkData = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMask!!, null, !isFullChunk, dimension.hasSkyLight)
if (chunkData == null) {
unloadChunk = true
unload = true
} else {
this@ChunkS2CP.chunkData.replace(chunkData)
this@ChunkS2CP.data.replace(chunkData)
}
} else {
this@ChunkS2CP.chunkData.replace(ChunkUtil.readPaletteChunk(buffer, dimension, null, isFullChunk = true, containsSkyLight = false))
this@ChunkS2CP.data.replace(ChunkUtil.readPaletteChunk(buffer, dimension, null, isFullChunk = true, containsSkyLight = false))
}
}
override fun handle(connection: PlayConnection) {
if (unloadChunk) {
connection.world.unloadChunk(chunkPosition)
if (unload) {
connection.world.unloadChunk(position)
return
}
readingData.readChunkData()
val chunk = connection.world.getOrCreateChunk(chunkPosition)
chunk.setData(chunkData)
val chunk = connection.world.getOrCreateChunk(position)
chunk.setData(data)
}
override fun log(reducedLog: Boolean) {
if (reducedLog) {
return
}
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Chunk (chunkPosition=$chunkPosition)" }
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Chunk (chunkPosition=$position)" }
}
private data class ChunkReadingData(

View File

@ -225,6 +225,7 @@ object KUtil {
return null
}
@Deprecated("Kutil")
private inline fun String.checkInt(): Int? {
var first = true
for (point in codePoints()) {