Complete all serverbound packets at PLAY state

This commit is contained in:
2026-09-06 01:18:32 +08:00
parent 94cca61df1
commit 52917e9425
153 files changed
+3636 -131

No files matched your search

+8 -2
View File
@@ -5,7 +5,11 @@ plugins {
allprojects {
group = "cn.rtast.libmc"
version = providers.gradleProperty("libVersion").get()
val libVersion = getProperty("libVersion")
version = when (name) {
"protocol" -> "${getProperty("protocolVersion")}-$libVersion"
else -> libVersion
}
repositories {
mavenCentral()
@@ -29,4 +33,6 @@ subprojects {
}
}
}
}
}
fun getProperty(name: String): String = providers.gradleProperty(name).get()
+2 -1
View File
@@ -4,4 +4,5 @@ kotlin.native.enableKlibsCrossCompilation=true
kotlin.daemon.jvmargs=-Xmx2048M
org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8
libVersion=0.1.0
libVersion=0.1.0
protocolVersion=26.2
@@ -56,9 +56,52 @@ public fun BytesBuffer.readUuid(): Uuid {
public fun BytesBuffer.writeVarInt(value: Int): Unit = VarIntCodec.encode(this, value)
public fun BytesBuffer.readVarInt(): Int = VarIntCodec.decode(this)
public fun BytesBuffer.writeVarLong(value: Long): Unit = VarLongCodec.encode(this, value)
public fun BytesBuffer.readVarLong(): Long = VarLongCodec.decode(this)
public fun BytesBuffer.writeMcString(value: String): Unit = McStringCodec.encode(this, value)
public fun BytesBuffer.readMcString(): String = McStringCodec.decode(this)
public fun BytesBuffer.readPrefixedByteArray(): ByteArray {
val length = this.readVarInt()
val data = this.readBytes(length)
return data
}
public fun BytesBuffer.writePrefixedByteArray(data: ByteArray) {
this.writeVarInt(data.size)
this.writeBytes(data)
}
public fun BytesBuffer.readPrefixedVarIntArray(): List<Int> {
val length = readVarInt()
val list = ArrayList<Int>(length)
repeat(length) { list.add(readVarInt()) }
return list
}
public fun BytesBuffer.writePrefixedVarIntArray(value: List<Int>) {
writeVarInt(value.size)
for (item in value) writeVarInt(item)
}
public fun BytesBuffer.readPrefixedStringArray(): List<String> {
val length = readVarInt()
val list = ArrayList<String>(length)
repeat(length) { list.add(readMcString()) }
return list
}
public fun BytesBuffer.writePrefixedStringArray(value: List<String>) {
writeVarInt(value.size)
for (item in value) writeMcString(item)
}
public inline fun <T> BytesBuffer.writePrefixedArray(value: List<T>, writeItem: BytesBuffer.(T) -> Unit) {
writeVarInt(value.size)
for (item in value) writeItem(item)
}
public fun ReadChannel.readPacketFrame(): BytesBuffer {
val length = this.readVarInt()
return this.readBytes(length).wrap()
@@ -34,6 +34,34 @@ public object VarIntCodec : PacketCodec<Int> {
}
}
public object VarLongCodec : PacketCodec<Long> {
override fun encode(buffer: BytesBuffer, value: Long) {
var v = value
while (true) {
if ((v and 0x7FL.inv()) == 0L) {
buffer.writeByte(v.toByte())
return
}
buffer.writeByte(((v and 0x7F) or 0x80).toByte())
v = v ushr 7
}
}
override fun decode(buffer: BytesBuffer): Long {
var numRead = 0
var result = 0L
var read: Byte
do {
read = buffer.readByte()
val value = (read.toLong() and 0x7F)
result = result or (value shl (7 * numRead))
numRead++
if (numRead > 10) throw IllegalArgumentException("VarLong is too big")
} while ((read.toInt() and 0x80) != 0)
return result
}
}
public object McStringCodec : PacketCodec<String> {
override fun encode(buffer: BytesBuffer, value: String) {
val bytes = value.encodeToByteArray()
@@ -79,10 +79,7 @@ public fun NBTInput.readRootCompound(): NBTCompound {
public fun NBTInput.readNetworkCompound(): NBTCompound {
return when (val type = NBTType.fromId(readByte().toInt() and 0xFF)) {
NBTType.Compound -> NBTCompound("", readCompoundTag())
NBTType.String -> NBTCompound(
"", NBTTag.CompoundTag(linkedMapOf("text" to NBTTag.StringTag(readStringTag())))
)
NBTType.String -> NBTCompound("", NBTTag.CompoundTag(linkedMapOf("text" to NBTTag.StringTag(readStringTag()))))
else -> throw UnsupportedOperationException("Unsupported network nbt tag 0x${type.id.toString(16).uppercase()}")
}
}
@@ -62,3 +62,10 @@ public fun NBTOutput.writeRootNBTCompound(name: String = ""): ByteArray {
writeTagPayload(root)
return toByteArray()
}
public fun NBTOutput.writeNetworkCompound(compound: NBTCompound) {
val compoundTag = compound.element as? NBTTag.CompoundTag
?: throw IllegalArgumentException("NBTCompound element must be an NBTTag.CompoundTag")
writeByte(NBTType.Compound.id)
writeTagPayload(compoundTag)
}
@@ -0,0 +1,19 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.block
public enum class EnchantmentButton(public val id: Int) {
TOPMOST(0),
MIDDLE(1),
BOTTOM(2);
public companion object {
public fun fromID(id: Int): EnchantmentButton =
requireNotNull(entries.firstOrNull { it.id == id }) { "Unknown enchantment button id $id" }
}
}
@@ -0,0 +1,21 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.block
public enum class LecternButton(public val id: Int) {
PREVIOUS_PAGE(1),
NEXT_PAGE(2),
TAKE_BOOK(3);
public companion object {
public fun fromID(id: Int): LecternButton =
requireNotNull(entries.firstOrNull { it.id == id }) { "Unknown lectern button id $id" }
public fun specificPage(page: Int): Int = 100 + page
}
}
@@ -8,9 +8,41 @@
package cn.rtast.libmc.protocol.client
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.packet.configuration.*
import cn.rtast.libmc.protocol.packet.login.*
import cn.rtast.libmc.protocol.packet.play.*
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundCookieRequestPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundCustomPayloadPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundDisconnectConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundKeepAliveConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundPingConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.clientbound.ClientboundSelectKnownPacksPacket
import cn.rtast.libmc.protocol.packet.configuration.serverbound.ServerboundAckFinishConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.serverbound.ServerboundKeepAliveConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.serverbound.ServerboundPongConfigurationPacket
import cn.rtast.libmc.protocol.packet.configuration.serverbound.ServerboundSelectKnownPacksPacket
import cn.rtast.libmc.protocol.packet.login.clientbound.ClientboundDisconnectLoginPacket
import cn.rtast.libmc.protocol.packet.login.clientbound.ClientboundLoginPacket
import cn.rtast.libmc.protocol.packet.login.clientbound.ClientboundLoginSuccessPacket
import cn.rtast.libmc.protocol.packet.login.clientbound.ClientboundSetCompressionPacket
import cn.rtast.libmc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundAcknowledgeBlockChangePacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundAwardStatisticsPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundBlockDestructionPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundBlockEntityDataPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundDelimiterPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundDisconnectPlayPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundEntityAnimationPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundKeepAlivePlayPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundLoginPlayPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPingPlayPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayerChatMessagePacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundSpawnEntityPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundStartConfigurationPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundSystemChatMessagePacket
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundConfigurationAcknowledgedPacket
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundKeepAlivePlayPacket
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundPongPlayPacket
import cn.rtast.libmc.protocol.protocol.state.ProtocolState
internal class InternalPacketDispatcher(private val client: MinecraftClient) {
@@ -90,6 +122,13 @@ internal class InternalPacketDispatcher(private val client: MinecraftClient) {
}
is ClientboundSystemChatMessagePacket -> {}
is ClientboundAcknowledgeBlockChangePacket -> {}
is ClientboundAwardStatisticsPacket -> {}
is ClientboundBlockDestructionPacket -> {}
is ClientboundBlockEntityDataPacket -> {}
ClientboundDelimiterPacket -> {}
is ClientboundEntityAnimationPacket -> {}
is ClientboundSpawnEntityPacket -> {}
}
}
}
@@ -10,9 +10,10 @@ import cn.rtast.libmc.common.LibMCContext
import cn.rtast.libmc.protocol.event.PacketEventDispatcher
import cn.rtast.libmc.protocol.network.NetworkChannel
import cn.rtast.libmc.protocol.packet.handshake.ServerboundHandshakePacket
import cn.rtast.libmc.protocol.packet.login.ServerboundLoginStartPacket
import cn.rtast.libmc.protocol.packet.login.serverbound.ServerboundLoginStartPacket
import cn.rtast.libmc.protocol.protocol.state.HandshakeIntent
import cn.rtast.libmc.protocol.protocol.state.ProtocolState
import cn.rtast.libmc.protocol.session.TransactionIdManager
import cn.rtast.libmc.protocol.util.generateOfflineUuid
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
@@ -35,6 +36,8 @@ public class MinecraftClient internal constructor(
private val clientJob = SupervisorJob(parentJob)
private var listenJob: Job? = null
public val transactionManager: TransactionIdManager = TransactionIdManager()
override val coroutineContext: CoroutineContext
get() = clientJob + ioDispatcher + CoroutineName("LibMC-MinecraftClient-$username")
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.packet.MinecraftPacket
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,12 +5,13 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
public data class ClientboundSelectKnownPacksPacket(val knownPacks: List<KnownPacks>) : ClientboundConfigurationPacket {
public companion object Codec : PacketCodec<ClientboundSelectKnownPacksPacket> {
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,15 +5,13 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
public data class ServerboundCookieResponsePacket(val key: Identifier, val payload: ByteArray?) : MinecraftPacket {
@@ -24,20 +22,11 @@ public data class ServerboundCookieResponsePacket(val key: Identifier, val paylo
buffer.writeBoolean(true)
buffer.writeVarInt(value.payload.size)
buffer.writeBytes(value.payload)
} else {
buffer.writeBoolean(false)
}
} else buffer.writeBoolean(false)
}
override fun decode(buffer: BytesBuffer): ServerboundCookieResponsePacket {
val key = buffer.readIdentifier()
val hasPayload = buffer.readBoolean()
val payload = if (hasPayload) {
val length = buffer.readVarInt()
buffer.readBytes(length)
} else null
return ServerboundCookieResponsePacket(key, payload)
}
override fun decode(buffer: BytesBuffer): ServerboundCookieResponsePacket =
throw UnsupportedOperationException()
}
override fun equals(other: Any?): Boolean {
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,13 +5,14 @@
*/
package cn.rtast.libmc.protocol.packet.configuration
package cn.rtast.libmc.protocol.packet.configuration.serverbound
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
public data class ServerboundSelectKnownPacksPacket(val knownPacks: List<KnownPacks>) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSelectKnownPacksPacket> {
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.login
package cn.rtast.libmc.protocol.packet.login.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.login
package cn.rtast.libmc.protocol.packet.login.clientbound
import cn.rtast.libmc.common.packet.MinecraftPacket
@@ -5,12 +5,12 @@
*/
package cn.rtast.libmc.protocol.packet.login
package cn.rtast.libmc.protocol.packet.login.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readUuid
import cn.rtast.libmc.protocol.profile.GameProfile
import cn.rtast.libmc.protocol.session.GameProfile
import kotlin.uuid.Uuid
public data class ClientboundLoginSuccessPacket(val gameProfile: GameProfile, val sessionId: Uuid) :
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.login
package cn.rtast.libmc.protocol.packet.login.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.login
package cn.rtast.libmc.protocol.packet.login.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.login
package cn.rtast.libmc.protocol.packet.login.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -1,34 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.protocol.packet.play
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
import kotlin.time.Clock
public data class ServerboundChatMessagePacket(
val message: String,
val timestamp: Long = Clock.System.now().toEpochMilliseconds(),
val salt: Long = 0L,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChatMessagePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChatMessagePacket) {
buffer.writeMcString(value.message)
buffer.writeLong(value.timestamp)
buffer.writeLong(value.salt)
buffer.writeBoolean(false) // has signature
buffer.writeVarInt(0) // message count
buffer.writeBytes(byteArrayOf(0, 0, 0))
}
override fun decode(buffer: BytesBuffer): ServerboundChatMessagePacket = throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Acknowledge_Block_Change
*/
public data class ClientboundAcknowledgeBlockChangePacket(val sequenceId: Int) : ClientboundPlayPacket {
public companion object Codec : PacketCodec<ClientboundAcknowledgeBlockChangePacket> {
override fun encode(buffer: BytesBuffer, value: ClientboundAcknowledgeBlockChangePacket) {}
override fun decode(buffer: BytesBuffer): ClientboundAcknowledgeBlockChangePacket {
return ClientboundAcknowledgeBlockChangePacket(buffer.readVarInt())
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.protocol.game.StatisticsEntry
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Award_Statistics
*/
public data class ClientboundAwardStatisticsPacket(val stats: List<StatisticsEntry>) : ClientboundPlayPacket {
public companion object Codec : PacketCodec<ClientboundAwardStatisticsPacket> {
override fun encode(buffer: BytesBuffer, value: ClientboundAwardStatisticsPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundAwardStatisticsPacket {
val count = buffer.readVarInt()
val stats = List(count) { StatisticsEntry.decode(buffer) }
return ClientboundAwardStatisticsPacket(stats)
}
}
}
@@ -0,0 +1,34 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.protocol.game.block.BlockDestroyStage
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Set_Block_Destroy_Stage
*/
public data class ClientboundBlockDestructionPacket(
val entityId: Int,
val location: BlockPos,
val stage: BlockDestroyStage,
) : ClientboundPlayPacket {
public companion object Codec : PacketCodec<ClientboundBlockDestructionPacket> {
override fun encode(buffer: BytesBuffer, value: ClientboundBlockDestructionPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundBlockDestructionPacket {
val entityId = buffer.readVarInt()
val location = buffer.readBlockPos()
val stage = buffer.readByte()
return ClientboundBlockDestructionPacket(entityId, location, BlockDestroyStage(stage))
}
}
}
@@ -0,0 +1,29 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundBlockEntityDataPacket(val location: BlockPos, val type: Int, val data: NBTCompound) :
ClientboundPlayPacket {
public companion object Codec : PacketCodec<ClientboundBlockEntityDataPacket> {
override fun encode(buffer: BytesBuffer, value: ClientboundBlockEntityDataPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundBlockEntityDataPacket {
val location = buffer.readBlockPos()
val type = buffer.readVarInt()
val data = buffer.readNetworkNBTCompound()
return ClientboundBlockEntityDataPacket(location, type, data)
}
}
}
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,12 +5,12 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.types.Animations
import cn.rtast.libmc.protocol.protocol.game.Animations
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Entity_Animation
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,12 +5,14 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.protocol.game.*
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
public data class ClientboundLoginPlayPacket(
val entityId: Int,
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.packet.MinecraftPacket
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.*
import cn.rtast.libmc.nbt.NBTCompound
@@ -5,16 +5,16 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readUuid
import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.types.Angle
import cn.rtast.libmc.protocol.types.LpVec3
import cn.rtast.libmc.protocol.types.readAngle
import cn.rtast.libmc.protocol.types.readLpVec3
import cn.rtast.libmc.protocol.protocol.game.math.Angle
import cn.rtast.libmc.protocol.protocol.game.math.LpVec3
import cn.rtast.libmc.protocol.protocol.game.math.readAngle
import cn.rtast.libmc.protocol.protocol.game.math.readLpVec3
import kotlin.uuid.Uuid
/**
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundAcceptTeleportationPacket(val teleportId: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundAcceptTeleportationPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundAcceptTeleportationPacket) {
buffer.writeVarInt(value.teleportId)
}
override fun decode(buffer: BytesBuffer): ServerboundAcceptTeleportationPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundAcknowledgeChatMessagePacket(val messageCount: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundAcknowledgeChatMessagePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundAcknowledgeChatMessagePacket) {
buffer.writeVarInt(value.messageCount)
}
override fun decode(buffer: BytesBuffer): ServerboundAcknowledgeChatMessagePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundAttackActionPacket(val entityId: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundAttackActionPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundAttackActionPacket) {
buffer.writeVarInt(value.entityId)
}
override fun decode(buffer: BytesBuffer): ServerboundAttackActionPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,25 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundBundleItemSelectedPacket(val slotOfBundle: Int, val slotInBundle: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundBundleItemSelectedPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundBundleItemSelectedPacket) {
buffer.writeVarInt(value.slotOfBundle)
buffer.writeVarInt(value.slotInBundle)
}
override fun decode(buffer: BytesBuffer): ServerboundBundleItemSelectedPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,27 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundChangeContainerSlotStatePacket(val slotId: Int, val windowId: Int, val state: Boolean) :
MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChangeContainerSlotStatePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChangeContainerSlotStatePacket) {
buffer.writeVarInt(value.slotId)
buffer.writeVarInt(value.windowId)
buffer.writeBoolean(value.state)
}
override fun decode(buffer: BytesBuffer): ServerboundChangeContainerSlotStatePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.registry.GameDifficulty
public data class ServerboundChangeDifficultyPacket(val newDifficulty: GameDifficulty) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChangeDifficultyPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChangeDifficultyPacket) {
buffer.writeByte(value.newDifficulty.id)
}
override fun decode(buffer: BytesBuffer): ServerboundChangeDifficultyPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,26 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.GameMode
public data class ServerboundChangeGameModePacket(val gameMode: GameMode) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChangeGameModePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChangeGameModePacket) {
require(value.gameMode != GameMode.Unknown && value.gameMode != GameMode.Undefined)
buffer.writeVarInt(value.gameMode.id.toInt())
}
override fun decode(buffer: BytesBuffer): ServerboundChangeGameModePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
public data class ServerboundChatCommandPacket(val command: String) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChatCommandPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChatCommandPacket) {
buffer.writeMcString(value.command.removePrefix("/"))
}
override fun decode(buffer: BytesBuffer): ServerboundChatCommandPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,69 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundChatMessagePacket(
val message: String,
val timestamp: Long,
val salt: Long,
val signature: ByteArray?,
val messageCount: Int,
val acknowledged: ByteArray,
val checksum: Byte,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChatMessagePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChatMessagePacket) {
buffer.writeMcString(value.message)
buffer.writeLong(value.timestamp)
buffer.writeLong(value.salt)
val hasSignature = value.signature != null
buffer.writeBoolean(hasSignature)
if (hasSignature) buffer.writeBytes(value.signature)
buffer.writeVarInt(value.messageCount)
buffer.writeBytes(value.acknowledged)
buffer.writeByte(value.checksum)
}
override fun decode(buffer: BytesBuffer): ServerboundChatMessagePacket =
throw UnsupportedOperationException()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as ServerboundChatMessagePacket
if (timestamp != other.timestamp) return false
if (salt != other.salt) return false
if (messageCount != other.messageCount) return false
if (checksum != other.checksum) return false
if (message != other.message) return false
if (!signature.contentEquals(other.signature)) return false
if (!acknowledged.contentEquals(other.acknowledged)) return false
return true
}
override fun hashCode(): Int {
var result = timestamp.hashCode()
result = 31 * result + salt.hashCode()
result = 31 * result + messageCount
result = 31 * result + checksum
result = 31 * result + message.hashCode()
result = 31 * result + (signature?.contentHashCode() ?: 0)
result = 31 * result + acknowledged.contentHashCode()
return result
}
}
@@ -0,0 +1,23 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data class ServerboundChunkBatchReceivedPacket(val chunksPerTick: Float) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundChunkBatchReceivedPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundChunkBatchReceivedPacket) {
buffer.writeFloat(value.chunksPerTick)
}
override fun decode(buffer: BytesBuffer): ServerboundChunkBatchReceivedPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,25 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.registry.ClientAction
public data class ServerboundClientActionPacket(val action: ClientAction) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundClientActionPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundClientActionPacket) {
buffer.writeVarInt(value.action.actionID)
}
override fun decode(buffer: BytesBuffer): ServerboundClientActionPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,25 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.player.PlayerActionStatus
public data class ServerboundClientCommandPacket(val action: PlayerActionStatus) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundClientCommandPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundClientCommandPacket) {
buffer.writeVarInt(value.action.id)
}
override fun decode(buffer: BytesBuffer): ServerboundClientCommandPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,67 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.ChatMode
import cn.rtast.libmc.protocol.protocol.game.player.MainHand
import cn.rtast.libmc.protocol.protocol.game.player.skin.ParticleStatus
import cn.rtast.libmc.protocol.protocol.game.player.skin.SkinPartFlag
import cn.rtast.libmc.protocol.protocol.game.player.skin.SkinPartFlags
public data class ServerboundClientInformationPacket(
val locale: String,
/**
* real type is [Byte]
*/
val viewDistance: Int,
val chatMode: ChatMode,
/**
* Colors multiplayer setting. The vanilla server stores this value but does nothing with it (see MC-64867).
* Some third-party servers disable all coloring in chat and system messages when it is false.
*/
val chatColors: Boolean,
/**
* see [SkinPartFlags]
*/
val displayedSkinParts: SkinPartFlag,
val mainHand: MainHand,
/**
* Enables filtering of text on signs and written book titles.
* The vanilla client sets this according to the profanityFilterPreferences.profanityFilterOn
* account attribute indicated by the Mojang API endpoint for player attributes.
* In offline mode, it is always false.
*/
val enableTextFiltering: Boolean,
/**
* Servers usually list online players; this option should let you not show up in that list.
*/
val allowServerListings: Boolean,
val particleStatus: ParticleStatus,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundClientInformationPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundClientInformationPacket) {
buffer.writeMcString(value.locale)
buffer.writeByte(value.viewDistance.toByte())
buffer.writeVarInt(value.chatMode.id)
buffer.writeBoolean(value.chatColors)
buffer.writeByte(value.displayedSkinParts.toByte())
buffer.writeVarInt(value.mainHand.id)
buffer.writeBoolean(value.enableTextFiltering)
buffer.writeBoolean(value.allowServerListings)
buffer.writeVarInt(value.particleStatus.id)
}
override fun decode(buffer: BytesBuffer): ServerboundClientInformationPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,17 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data object ServerboundClientTickEndPacket : MinecraftPacket, PacketCodec<ServerboundClientTickEndPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundClientTickEndPacket) {}
override fun decode(buffer: BytesBuffer): ServerboundClientTickEndPacket = throw UnsupportedOperationException()
}
@@ -0,0 +1,35 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundCommandSuggestionRequestPacket(
/**
* to get transaction id, use `MinecraftClient.transactionManager.nextCommandSuggestionId`
*/
val transactionId: Int,
/**
* All the text behind the cursor including the / (e.g. to the left of the cursor in left-to-right languages like English).
*/
val text: String,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundCommandSuggestionRequestPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundCommandSuggestionRequestPacket) {
buffer.writeVarInt(value.transactionId)
buffer.writeMcString(value.text)
}
override fun decode(buffer: BytesBuffer): ServerboundCommandSuggestionRequestPacket =
throw UnsupportedOperationException()
}
}
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -0,0 +1,30 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.block.EnchantmentButton
import cn.rtast.libmc.protocol.block.LecternButton
public data class ServerboundContainerClickButtonPacket(val windowId: Int, val buttonId: Int) : MinecraftPacket {
public constructor(windowId: Int, button: EnchantmentButton) : this(windowId, button.id)
public constructor(windowId: Int, button: LecternButton) : this(windowId, button.id)
public companion object Codec : PacketCodec<ServerboundContainerClickButtonPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundContainerClickButtonPacket) {
buffer.writeVarInt(value.windowId)
buffer.writeVarInt(value.buttonId)
}
override fun decode(buffer: BytesBuffer): ServerboundContainerClickButtonPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,73 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.container.ContainerButton
import cn.rtast.libmc.protocol.protocol.game.inventory.ChangedSlot
import cn.rtast.libmc.protocol.protocol.game.inventory.HashedSlot
import cn.rtast.libmc.protocol.protocol.game.inventory.InventoryClickType
public data class ServerboundContainerClickPacket(
val windowId: Int,
val stateId: Int,
val slot: Short,
val button: Byte,
val mode: Int,
val changedSlots: List<ChangedSlot>,
val carriedItem: HashedSlot,
) : MinecraftPacket {
public constructor(
windowId: Int,
stateId: Int,
slot: Short,
mouseButton: ContainerButton.Mouse,
changedSlots: List<ChangedSlot>,
carriedItem: HashedSlot,
) : this(
windowId = windowId,
stateId = stateId,
slot = slot,
button = mouseButton.id,
mode = InventoryClickType.PICKUP.id,
changedSlots = changedSlots,
carriedItem = carriedItem
)
public constructor(
windowId: Int,
stateId: Int,
slot: Short,
swapButton: ContainerButton.Swap,
changedSlots: List<ChangedSlot>,
carriedItem: HashedSlot,
) : this(
windowId = windowId,
stateId = stateId,
slot = slot,
button = swapButton.id,
mode = InventoryClickType.SWAP.id,
changedSlots = changedSlots,
carriedItem = carriedItem
)
public companion object Codec : PacketCodec<ServerboundContainerClickPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundContainerClickPacket) {
buffer.writeVarInt(value.windowId)
buffer.writeVarInt(value.stateId)
buffer.writeShort(value.slot)
buffer.writeByte(value.button)
}
override fun decode(buffer: BytesBuffer): ServerboundContainerClickPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundContainerClosePacket(val windowId: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundContainerClosePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundContainerClosePacket) {
buffer.writeVarInt(value.windowId)
}
override fun decode(buffer: BytesBuffer): ServerboundContainerClosePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,37 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
import cn.rtast.libmc.protocol.protocol.util.writeNetworkNBTCompound
public data class ServerboundCustomClickActionPacket(
val id: Identifier,
/**
* payload size, bytes
*/
val size: Int,
val payload: NBTCompound,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundCustomClickActionPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundCustomClickActionPacket) {
buffer.writeIdentifier(value.id)
buffer.writeVarInt(value.size)
buffer.writeNetworkNBTCompound(value.payload)
}
override fun decode(buffer: BytesBuffer): ServerboundCustomClickActionPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,44 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
public data class ServerboundCustomPayloadPacket(val channel: Identifier, val data: ByteArray) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundCustomPayloadPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundCustomPayloadPacket) {
buffer.writeIdentifier(value.channel)
buffer.writeBytes(value.data) // ?
}
override fun decode(buffer: BytesBuffer): ServerboundCustomPayloadPacket =
throw UnsupportedOperationException()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as ServerboundCustomPayloadPacket
if (channel != other.channel) return false
if (!data.contentEquals(other.data)) return false
return true
}
override fun hashCode(): Int {
var result = channel.hashCode()
result = 31 * result + data.contentHashCode()
return result
}
}
@@ -0,0 +1,26 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writePrefixedVarIntArray
import cn.rtast.libmc.protocol.protocol.game.debug.DebugSubscriptionType
public data class ServerboundDebugSubscriptionRequestPacket(val subscriptions: List<DebugSubscriptionType>) :
MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundDebugSubscriptionRequestPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundDebugSubscriptionRequestPacket) {
buffer.writePrefixedVarIntArray(value.subscriptions.map { it.id })
}
override fun decode(buffer: BytesBuffer): ServerboundDebugSubscriptionRequestPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,27 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.*
import cn.rtast.libmc.common.packet.MinecraftPacket
public data class ServerboundEditBookPacket(val slot: Int, val entries: List<String>, val title: String?) :
MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundEditBookPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundEditBookPacket) {
buffer.writeVarInt(value.slot)
buffer.writePrefixedStringArray(value.entries)
val hasTitle = value.title != null
buffer.writeBoolean(hasTitle)
if (hasTitle) buffer.writeMcString(value.title)
}
override fun decode(buffer: BytesBuffer): ServerboundEditBookPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,35 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.math.LpVec3
import cn.rtast.libmc.protocol.protocol.game.math.writeLpVec3
import cn.rtast.libmc.protocol.protocol.game.player.Hand
public data class ServerboundInteractPacket(
val entityId: Int,
val hand: Hand,
val targetOffset: LpVec3,
val isSneaking: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundInteractPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundInteractPacket) {
buffer.writeVarInt(value.entityId)
buffer.writeVarInt(value.hand.id)
buffer.writeLpVec3(value.targetOffset)
buffer.writeBoolean(value.isSneaking)
}
override fun decode(buffer: BytesBuffer): ServerboundInteractPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,35 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.writeBlockPos
public data class ServerboundJigsawGeneratePacket(
val location: BlockPos,
/**
* Value of the levels slider/max depth to generate.
*/
val levels: Int,
val keepJigsaw: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundJigsawGeneratePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundJigsawGeneratePacket) {
buffer.writeBlockPos(value.location)
buffer.writeVarInt(value.levels)
buffer.writeBoolean(value.keepJigsaw)
}
override fun decode(buffer: BytesBuffer): ServerboundJigsawGeneratePacket =
throw UnsupportedOperationException()
}
}
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -0,0 +1,28 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
/**
* Must have at least op level 2 to use.
* Appears to only be used on singleplayer; the difficulty buttons are still disabled in multiplayer.
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Lock_Difficulty
*/
public data class ServerboundLockDifficultyPacket(val locked: Boolean) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundLockDifficultyPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundLockDifficultyPacket) {
buffer.writeBoolean(value.locked)
}
override fun decode(buffer: BytesBuffer): ServerboundLockDifficultyPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,37 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Move_Vehicle_(serverbound)
* onGround does not seem to exist
*/
public data class ServerboundMoveVehiclePacket(
val x: Double,
val y: Double,
val z: Double,
val yaw: Float,
val pitch: Float,
// val onGround: Boolean
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundMoveVehiclePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundMoveVehiclePacket) {
buffer.writeDouble(value.x)
buffer.writeDouble(value.y)
buffer.writeDouble(value.z)
buffer.writeFloat(value.yaw)
buffer.writeFloat(value.pitch)
}
override fun decode(buffer: BytesBuffer): ServerboundMoveVehiclePacket = throw UnsupportedOperationException()
}
}
@@ -0,0 +1,36 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
/**
* Used to visually update whether boat paddles are turning.
* The server will update the Boat entity metadata to match the values here.
*
* Right paddle turning is set to true when the left button or forward button is held,
* left paddle turning is set to true when the right button or forward button is held.
*
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Paddle_Boat
*/
public data class ServerboundPaddleBoatPacket(
val leftPaddleTurning: Boolean,
val rightPaddleTurning: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPaddleBoatPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPaddleBoatPacket) {
buffer.writeBoolean(value.leftPaddleTurning)
buffer.writeBoolean(value.rightPaddleTurning)
}
override fun decode(buffer: BytesBuffer): ServerboundPaddleBoatPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,33 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.writeBlockPos
public data class ServerboundPickItemFromBlockPacket(
val location: BlockPos,
/**
* Used to tell the server to include block data in the new stack,
* works only if in creative mode.
*/
val includeData: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPickItemFromBlockPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPickItemFromBlockPacket) {
buffer.writeBlockPos(value.location)
buffer.writeBoolean(value.includeData)
}
override fun decode(buffer: BytesBuffer): ServerboundPickItemFromBlockPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,31 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundPickItemFromEntityPacket(
val entityId: Int,
/**
* Unused by the vanilla server.
*/
val includeData: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPickItemFromEntityPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPickItemFromEntityPacket) {
buffer.writeVarInt(value.entityId)
buffer.writeBoolean(value.includeData)
}
override fun decode(buffer: BytesBuffer): ServerboundPickItemFromEntityPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,30 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundPlaceRecipePacket(
val windowId: Int,
val recipeId: Int,
val makeAll: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPlaceRecipePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPlaceRecipePacket) {
buffer.writeVarInt(value.windowId)
buffer.writeVarInt(value.recipeId)
buffer.writeBoolean(value.makeAll)
}
override fun decode(buffer: BytesBuffer): ServerboundPlaceRecipePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.player.PlayerAbilities
public data class ServerboundPlayerAbilitiesPacket(val flags: PlayerAbilities) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPlayerAbilitiesPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPlayerAbilitiesPacket) {
buffer.writeByte(value.flags.flag)
}
override fun decode(buffer: BytesBuffer): ServerboundPlayerAbilitiesPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,43 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.block.BlockFace
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.writeBlockPos
import cn.rtast.libmc.protocol.protocol.game.player.PlayerActionStatus
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Player_Action
*/
public data class ServerboundPlayerActionPacket(
val status: PlayerActionStatus,
val location: BlockPos,
val blockFace: BlockFace,
/**
* Block change sequence number
* see [cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundAcknowledgeBlockChangePacket]
*/
val sequence: Int,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPlayerActionPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPlayerActionPacket) {
buffer.writeVarInt(value.status.id)
buffer.writeBlockPos(value.location)
buffer.writeByte(value.blockFace.id)
buffer.writeVarInt(value.sequence)
}
override fun decode(buffer: BytesBuffer): ServerboundPlayerActionPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,35 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.player.PlayerCommandAction
public data class ServerboundPlayerCommandPacket(
val entityId: Int,
val action: PlayerCommandAction,
/**
* Only used by the start jump with horse action,
* in which case it ranges from 0 to 100. In all other cases it is 0
*/
val jumpBoost: Int,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPlayerCommandPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPlayerCommandPacket) {
buffer.writeVarInt(value.entityId)
buffer.writeVarInt(value.action.id)
buffer.writeVarInt(value.jumpBoost)
}
override fun decode(buffer: BytesBuffer): ServerboundPlayerCommandPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,47 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data class ServerboundPlayerInputPacket(
val forward: Boolean,
val backward: Boolean,
val left: Boolean,
val right: Boolean,
val jump: Boolean,
val sneak: Boolean,
val sprint: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundPlayerInputPacket> {
private const val FLAG_FORWARD = 0x01
private const val FLAG_BACKWARD = 0x02
private const val FLAG_LEFT = 0x04
private const val FLAG_RIGHT = 0x08
private const val FLAG_JUMP = 0x10
private const val FLAG_SNEAK = 0x20
private const val FLAG_SPRINT = 0x40
override fun encode(buffer: BytesBuffer, value: ServerboundPlayerInputPacket) {
var flags = 0
if (value.forward) flags = flags or FLAG_FORWARD
if (value.backward) flags = flags or FLAG_BACKWARD
if (value.left) flags = flags or FLAG_LEFT
if (value.right) flags = flags or FLAG_RIGHT
if (value.jump) flags = flags or FLAG_JUMP
if (value.sneak) flags = flags or FLAG_SNEAK
if (value.sprint) flags = flags or FLAG_SPRINT
buffer.writeByte(flags.toByte())
}
override fun decode(buffer: BytesBuffer): ServerboundPlayerInputPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,17 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data object ServerboundPlayerLoadedPacket : MinecraftPacket, PacketCodec<ServerboundPlayerLoadedPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundPlayerLoadedPacket) {}
override fun decode(buffer: BytesBuffer): ServerboundPlayerLoadedPacket = throw UnsupportedOperationException()
}
@@ -4,7 +4,7 @@
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
@@ -16,8 +16,7 @@ public data class ServerboundPongPlayPacket(val id: Int) : MinecraftPacket {
buffer.writeInt(value.id)
}
override fun decode(buffer: BytesBuffer): ServerboundPongPlayPacket {
return ServerboundPongPlayPacket(id = buffer.readInt())
}
override fun decode(buffer: BytesBuffer): ServerboundPongPlayPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,29 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
/**
* to get a transaction id, use `MinecraftClient.transactionManager.nextQueryId`
*/
public data class ServerboundQueryBlockEntityTagPacket(val transactionId: Int, val location: BlockPos) :
MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundQueryBlockEntityTagPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundQueryBlockEntityTagPacket) {
buffer.writeVarInt(value.transactionId)
}
override fun decode(buffer: BytesBuffer): ServerboundQueryBlockEntityTagPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,31 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundQueryEntityTagPacket(
/**
* to get a transaction id, use `MinecraftClient.transactionManager.nextQueryEntitytagId`
*/
val transactionId: Int,
val entityId: Int,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundQueryEntityTagPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundQueryEntityTagPacket) {
buffer.writeVarInt(value.transactionId)
buffer.writeVarInt(value.entityId)
}
override fun decode(buffer: BytesBuffer): ServerboundQueryEntityTagPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,31 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.item.RecipeBookType
public data class ServerboundRecipeBookChangeSettingsPacket(
val bookId: RecipeBookType,
val bookOpen: Boolean,
val filterActive: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundRecipeBookChangeSettingsPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundRecipeBookChangeSettingsPacket) {
buffer.writeVarInt(value.bookId.id)
buffer.writeBoolean(value.bookOpen)
buffer.writeBoolean(value.filterActive)
}
override fun decode(buffer: BytesBuffer): ServerboundRecipeBookChangeSettingsPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundRecipeBookSeenRecipePacket(val recipeId: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundRecipeBookSeenRecipePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundRecipeBookSeenRecipePacket) {
buffer.writeVarInt(value.recipeId)
}
override fun decode(buffer: BytesBuffer): ServerboundRecipeBookSeenRecipePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,25 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
public data class ServerboundRenameItemPacket(val itemName: String) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundRenameItemPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundRenameItemPacket) {
require(value.itemName.length < 50)
buffer.writeMcString(value.itemName)
}
override fun decode(buffer: BytesBuffer): ServerboundRenameItemPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,31 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeUuid
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.resources.ResourcePackResult
import kotlin.uuid.Uuid
public data class ServerboundResourcePackResponsePacket(
val uuid: Uuid,
val result: ResourcePackResult,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundResourcePackResponsePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundResourcePackResponsePacket) {
buffer.writeUuid(value.uuid)
buffer.writeVarInt(value.result.id)
}
override fun decode(buffer: BytesBuffer): ServerboundResourcePackResponsePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,32 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.advancement.AdvancementAction
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
public data class ServerboundSeenAdvancementsPacket(val action: AdvancementAction, val tabId: Identifier?) :
MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSeenAdvancementsPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSeenAdvancementsPacket) {
buffer.writeVarInt(value.action.id)
if (value.action == AdvancementAction.OPENED_TAB) {
requireNotNull(value.tabId) { "tabId must not be null when action is OPENED_TAB" }
buffer.writeIdentifier(value.tabId)
} else require(value.tabId == null) { "tabId must be null when action is CLOSED_SCREEN" }
}
override fun decode(buffer: BytesBuffer): ServerboundSeenAdvancementsPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundSelectTradePacket(val selectedSlot: Int) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSelectTradePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSelectTradePacket) {
buffer.writeVarInt(value.selectedSlot)
}
override fun decode(buffer: BytesBuffer): ServerboundSelectTradePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,30 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeVarInt
/**
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Set_Beacon_Effect
*/
public data class ServerboundSetBeaconPacket(val primaryEffect: Int?, val secondaryEffect: Int?) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetBeaconPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetBeaconPacket) {
buffer.writeBoolean(value.primaryEffect != null)
if (value.primaryEffect != null) buffer.writeVarInt(value.primaryEffect)
buffer.writeBoolean(value.secondaryEffect != null)
if (value.secondaryEffect != null) buffer.writeVarInt(value.secondaryEffect)
}
override fun decode(buffer: BytesBuffer): ServerboundSetBeaconPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,26 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data class ServerboundSetCarriedItemPacket(val slot: Short) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetCarriedItemPacket> {
private const val MIN_SLOT: Short = 0
private const val MAX_SLOT: Short = 8
override fun encode(buffer: BytesBuffer, value: ServerboundSetCarriedItemPacket) {
require(value.slot in MIN_SLOT..MAX_SLOT) { "Carried item slot ${value.slot} must be between $MIN_SLOT and $MAX_SLOT" }
buffer.writeShort(value.slot)
}
override fun decode(buffer: BytesBuffer): ServerboundSetCarriedItemPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,46 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.CommandBlockMode
import cn.rtast.libmc.protocol.protocol.game.block.writeBlockPos
public data class ServerboundSetCommandBlockPacket(
val location: BlockPos,
val command: String,
val mode: CommandBlockMode,
val trackOutput: Boolean,
val conditional: Boolean,
val automatic: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetCommandBlockPacket> {
private const val FLAG_TRACK_OUTPUT = 0x01
private const val FLAG_CONDITIONAL = 0x02
private const val FLAG_AUTOMATIC = 0x04
override fun encode(buffer: BytesBuffer, value: ServerboundSetCommandBlockPacket) {
var flags = 0
if (value.trackOutput) flags = flags or FLAG_TRACK_OUTPUT
if (value.conditional) flags = flags or FLAG_CONDITIONAL
if (value.automatic) flags = flags or FLAG_AUTOMATIC
buffer.writeBlockPos(value.location)
buffer.writeMcString(value.command)
buffer.writeVarInt(value.mode.id)
buffer.writeByte(flags.toByte())
}
override fun decode(buffer: BytesBuffer): ServerboundSetCommandBlockPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,34 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundSetCommandMinecartPacket(
val entityId: Int,
val command: String,
/**
* If false, the output of the previous command will not be stored within the command block.
*/
val trackOutput: Boolean,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetCommandMinecartPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetCommandMinecartPacket) {
buffer.writeVarInt(value.entityId)
buffer.writeMcString(value.command)
buffer.writeBoolean(value.trackOutput)
}
override fun decode(buffer: BytesBuffer): ServerboundSetCommandMinecartPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,26 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.inventory.Slot
import cn.rtast.libmc.protocol.protocol.game.inventory.writeSlot
public data class ServerboundSetCreativeModeSlotPacket(val slot: Short, val clickedItem: Slot) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetCreativeModeSlotPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetCreativeModeSlotPacket) {
buffer.writeShort(value.slot)
buffer.writeSlot(value.clickedItem)
}
override fun decode(buffer: BytesBuffer): ServerboundSetCreativeModeSlotPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,29 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writePrefixedArray
import cn.rtast.libmc.protocol.protocol.game.gamerule.GameRuleEntry
public data class ServerboundSetGameRulePacket(val rules: List<GameRuleEntry>) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetGameRulePacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetGameRulePacket) {
buffer.writePrefixedArray(value.rules) { rule ->
writeMcString(rule.name)
writeMcString(rule.value)
}
}
override fun decode(buffer: BytesBuffer): ServerboundSetGameRulePacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,45 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/6
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.common.writeMcString
import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
import cn.rtast.libmc.protocol.protocol.game.block.writeBlockPos
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
public data class ServerboundSetJigsawBlockPacket(
val location: BlockPos,
val name: Identifier,
val target: Identifier,
val pool: Identifier,
val finalState: String,
val jointType: String,
val selectionPriority: Int,
val placementPriority: Int,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetJigsawBlockPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetJigsawBlockPacket) {
buffer.writeBlockPos(value.location)
buffer.writeIdentifier(value.name)
buffer.writeIdentifier(value.target)
buffer.writeIdentifier(value.pool)
buffer.writeMcString(value.finalState)
buffer.writeMcString(value.jointType)
buffer.writeVarInt(value.selectionPriority)
buffer.writeVarInt(value.placementPriority)
}
override fun decode(buffer: BytesBuffer): ServerboundSetJigsawBlockPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,24 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.player.PlayerPositionFlag
public data class ServerboundSetPlayerMovementFlagPacket(val flags: PlayerPositionFlag) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetPlayerMovementFlagPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetPlayerMovementFlagPacket) {
buffer.writeByte(value.flags.flag)
}
override fun decode(buffer: BytesBuffer): ServerboundSetPlayerMovementFlagPacket =
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,45 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.protocol.packet.play.serverbound
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.player.PlayerPositionFlag
public data class ServerboundSetPlayerPositionAndRotationPacket(
val x: Double,
/**
* Absolute feet position, normally Head Y - 1.62.
*/
val feetY: Double,
val z: Double,
/**
* Absolute rotation on the X Axis, in degrees.
*/
val yaw: Float,
/**
* Absolute rotation on the Y Axis, in degrees.
*/
val pitch: Float,
val flags: PlayerPositionFlag,
) : MinecraftPacket {
public companion object Codec : PacketCodec<ServerboundSetPlayerPositionAndRotationPacket> {
override fun encode(buffer: BytesBuffer, value: ServerboundSetPlayerPositionAndRotationPacket) {
buffer.writeDouble(value.x)
buffer.writeDouble(value.feetY)
buffer.writeDouble(value.z)
buffer.writeFloat(value.yaw)
buffer.writeFloat(value.pitch)
buffer.writeByte(value.flags.flag)
}
override fun decode(buffer: BytesBuffer): ServerboundSetPlayerPositionAndRotationPacket =
throw UnsupportedOperationException()
}
}
Loaded 100 of 153 files, more files were not shown because too many files have changed in this diff. Show more