Implemented 0x30-ClientboundLightUpdatePacket
This commit is contained in:
4 files changed
+138
-4
No files matched your search
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/11
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.protocol.packet.play.clientbound
|
||||||
|
|
||||||
|
import cn.rtast.libmc.network.BytesBuffer
|
||||||
|
import cn.rtast.libmc.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.primitives.readVarInt
|
||||||
|
import cn.rtast.libmc.protocol.protocol.game.world.LightData
|
||||||
|
|
||||||
|
public data class ClientboundLightUpdatePacket(
|
||||||
|
/**
|
||||||
|
* Chunk coordinate (block coordinate divided by 16, rounded down)
|
||||||
|
*/
|
||||||
|
val chunkX: Int,
|
||||||
|
/**
|
||||||
|
* Chunk coordinate (block coordinate divided by 16, rounded down)
|
||||||
|
*/
|
||||||
|
val chunkZ: Int,
|
||||||
|
val data: LightData,
|
||||||
|
) : MinecraftPacket {
|
||||||
|
internal companion object Codec : PacketCodec<ClientboundLightUpdatePacket> {
|
||||||
|
override fun encode(buffer: BytesBuffer, value: ClientboundLightUpdatePacket) {}
|
||||||
|
override fun decode(buffer: BytesBuffer): ClientboundLightUpdatePacket {
|
||||||
|
val chunkX = buffer.readVarInt()
|
||||||
|
val chunkZ = buffer.readVarInt()
|
||||||
|
val data = LightData.decode(buffer)
|
||||||
|
return ClientboundLightUpdatePacket(chunkX, chunkZ, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/11
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.protocol.protocol.game.world
|
||||||
|
|
||||||
|
import cn.rtast.libmc.network.BytesBuffer
|
||||||
|
import cn.rtast.libmc.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.primitives.*
|
||||||
|
|
||||||
|
public data class LightData(
|
||||||
|
val skyLightMask: BitSet,
|
||||||
|
val blockLightMask: BitSet,
|
||||||
|
val emptySkyLightMask: BitSet,
|
||||||
|
val emptyBlockLightMask: BitSet,
|
||||||
|
val skyLightArrays: List<ByteArray>, // fixed 2048
|
||||||
|
val blockLightArrays: List<ByteArray>, // fixed 2048
|
||||||
|
) {
|
||||||
|
internal companion object Codec : PacketCodec<LightData> {
|
||||||
|
private const val LIGHT_ARRAY_SIZE = 2048
|
||||||
|
override fun encode(buffer: BytesBuffer, value: LightData) {
|
||||||
|
buffer.writeBitSet(value.skyLightMask)
|
||||||
|
buffer.writeBitSet(value.blockLightMask)
|
||||||
|
buffer.writeBitSet(value.emptySkyLightMask)
|
||||||
|
buffer.writeBitSet(value.emptyBlockLightMask)
|
||||||
|
buffer.writeVarInt(value.skyLightArrays.size)
|
||||||
|
buffer.writePrefixed(value.skyLightArrays) { array ->
|
||||||
|
require(array.size == LIGHT_ARRAY_SIZE)
|
||||||
|
writeVarInt(array.size)
|
||||||
|
writeBytes(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.writePrefixed(value.blockLightArrays) { array ->
|
||||||
|
require(array.size == LIGHT_ARRAY_SIZE)
|
||||||
|
writeVarInt(array.size)
|
||||||
|
writeBytes(array)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun decode(buffer: BytesBuffer): LightData {
|
||||||
|
val skyLightMask = buffer.readBitSet()
|
||||||
|
val blockLightMask = buffer.readBitSet()
|
||||||
|
val emptySkyLightMask = buffer.readBitSet()
|
||||||
|
val emptyBlockLightMask = buffer.readBitSet()
|
||||||
|
val skyLightArrays = buffer.readPrefixed {
|
||||||
|
val length = readVarInt()
|
||||||
|
require(length == LIGHT_ARRAY_SIZE)
|
||||||
|
readBytes(length)
|
||||||
|
}
|
||||||
|
val blockLightArrays = buffer.readPrefixed {
|
||||||
|
val length = readVarInt()
|
||||||
|
require(length == LIGHT_ARRAY_SIZE)
|
||||||
|
readBytes(length)
|
||||||
|
}
|
||||||
|
return LightData(
|
||||||
|
skyLightMask, blockLightMask, emptySkyLightMask,
|
||||||
|
emptyBlockLightMask, skyLightArrays, blockLightArrays
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun hasSkyLight(sectionY: Int, minSectionY: Int): Boolean {
|
||||||
|
val bitIndex = sectionY - (minSectionY - 1)
|
||||||
|
return skyLightMask.getBit(bitIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public fun hasBlockLight(sectionY: Int, minSectionY: Int): Boolean {
|
||||||
|
val bitIndex = sectionY - (minSectionY - 1)
|
||||||
|
return blockLightMask.getBit(bitIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other == null || this::class != other::class) return false
|
||||||
|
other as LightData
|
||||||
|
if (!skyLightMask.contentEquals(other.skyLightMask)) return false
|
||||||
|
if (!blockLightMask.contentEquals(other.blockLightMask)) return false
|
||||||
|
if (!emptySkyLightMask.contentEquals(other.emptySkyLightMask)) return false
|
||||||
|
if (!emptyBlockLightMask.contentEquals(other.emptyBlockLightMask)) return false
|
||||||
|
if (skyLightArrays != other.skyLightArrays) return false
|
||||||
|
if (blockLightArrays != other.blockLightArrays) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = skyLightMask.contentHashCode()
|
||||||
|
result = 31 * result + blockLightMask.contentHashCode()
|
||||||
|
result = 31 * result + emptySkyLightMask.contentHashCode()
|
||||||
|
result = 31 * result + emptyBlockLightMask.contentHashCode()
|
||||||
|
result = 31 * result + skyLightArrays.hashCode()
|
||||||
|
result = 31 * result + blockLightArrays.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -108,7 +108,7 @@ internal object GamePacketsProtocolRegistry {
|
|||||||
// register(0x2D, ClientboundLevelChunkUpdateWithLightPacket)
|
// register(0x2D, ClientboundLevelChunkUpdateWithLightPacket)
|
||||||
register(0x2E, ClientboundLevelEventPacket)
|
register(0x2E, ClientboundLevelEventPacket)
|
||||||
register(0x2F, ClientboundLevelParticlePacket)
|
register(0x2F, ClientboundLevelParticlePacket)
|
||||||
// register(0x30, ClientboundLightUpdatePacket)
|
register(0x30, ClientboundLightUpdatePacket)
|
||||||
register(0x31, ClientboundLoginPlayPacket)
|
register(0x31, ClientboundLoginPlayPacket)
|
||||||
register(0x32, ClientboundLowDiskSpaceWarningPacket)
|
register(0x32, ClientboundLowDiskSpaceWarningPacket)
|
||||||
register(0x33, ClientboundMapItemDataPacket)
|
register(0x33, ClientboundMapItemDataPacket)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import cn.rtast.libmc.crypto.AuthenticationProvider
|
|||||||
import cn.rtast.libmc.protocol.client.createMinecraftClient
|
import cn.rtast.libmc.protocol.client.createMinecraftClient
|
||||||
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundContainerSetSlotPacket
|
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundContainerSetSlotPacket
|
||||||
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundLevelParticlePacket
|
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundLevelParticlePacket
|
||||||
|
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundLightUpdatePacket
|
||||||
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayerChatMessagePacket
|
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayerChatMessagePacket
|
||||||
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundStepTickPacket
|
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundStepTickPacket
|
||||||
import cn.rtast.libmc.protocol.protocol.session.SessionEvent
|
import cn.rtast.libmc.protocol.protocol.session.SessionEvent
|
||||||
@@ -101,9 +102,8 @@ class TestClient {
|
|||||||
println(it)
|
println(it)
|
||||||
}
|
}
|
||||||
cli.onPacket<ClientboundPlayerChatMessagePacket> { chatTracker.onReceivePlayerChat(it.messageSignature) }
|
cli.onPacket<ClientboundPlayerChatMessagePacket> { chatTracker.onReceivePlayerChat(it.messageSignature) }
|
||||||
cli.onPacket<ClientboundContainerSetSlotPacket> { println(it) }
|
cli.onPacket<ClientboundLightUpdatePacket> { println(it) }
|
||||||
cli.onPacket<ClientboundLevelParticlePacket> { println(it) }
|
cli.on { packet, direction -> println("$direction -> $packet") }
|
||||||
// cli.on { packet, direction -> println("$direction -> $packet") }
|
|
||||||
cli.connect()
|
cli.connect()
|
||||||
|
|
||||||
// awaitCancellation()
|
// awaitCancellation()
|
||||||
|
|||||||
Reference in New Issue
Block a user