diff --git a/README.md b/README.md
index 889339e..a54e44a 100644
--- a/README.md
+++ b/README.md
@@ -1,98 +1,371 @@
# libmc
-A lightweight minecraft related library, such as rcon client, motd ping and more for kotlin multiplatform and java, no
-dependencies in `jvm` target except `kotlin-stdlib`
-
-native platforms required `ktor-network` and `kotlinx-io`
+A lightweight minecraft client-side protocol library and related library, including `rcon client`, `motd ping`,
+`nbt parser`. All module require `kotlin-stdlib`, `libmc-protocol` require `kotlin-stdlib` and `kotlinx-coroutines`
# Supported targets
-- jvm 1.8
-- mingwX64
-- linuxArm64
-- liunxX64
+- JVM 1.8
+- MingwX64
+- LinuxArm64
+- LinuxX64
- iosArm64
- iosSimulatorArm64
-- macosArm64
+- MacosArm64
-# Get started
+# libmc-protocol
-[Use mcping module](https://repo.rtast.cn/packages/-/cn.rtast.libmc:mcping/)
+---
-[Use rconlib module](https://repo.rtast.cn/packages/-/cn.rtast.libmc:rconlib/)
+# Minecraft Protocol Library Status & Roadmap
-# MC Ping
+## Unimplemented features
-## Kotlin example
+- [ ] **Online Mode Authentication & Encryption**: Full Mojang/Microsoft auth pipeline, JoinServer request, and AES-CFB8
+ stream cipher stream wrapper.
+- [ ] **Structured `TextComponent` Parser**: Rich Chat Component AST decoder (currently falling back to raw
+ `NBTCompound`).
+- [ ] **Command Tree Parser (0x10)**: Full binary graph decoder for brigadier nodes, argument types, and suggestions.
+- [ ] **Recipe Book & Recipe Data (0x3F, 0x4A, 0x4B, 0x4C, 0x85)**: Recipe layout declarations and client-side recipe
+ settings.
+- [ ] **Chunk & World Data (0x2D)**: Level Chunk Data with Light decoder (Bitsets, Paletted Containers, Direct/Indirect
+ Palettes).
+- [ ] **Light Engine Update (0x30)**: Sky & Block light nibble array parser.
+- [ ] **Explosion Event Decoder (0x24)**: Knockback vectors and destroyed block offsets array.
+- [ ] **Debug Packets Parsing (0x1A - 0x1E)**: Debug subs, block/entity states, and game performance sample events.
+- [ ] **Particle parsing**
-```kotlin
-fun main() {
- val sm = SelectorManager(Dispatchers.IO)
- // context is not required, if not passed, default context will be used
- // ping java server
- val response: PingResponse =
- mcping(host = "org.mc-complex.com", port = 25565, type = ServerType.Java, context = LibMCContext(sm))
- println(response.content)
- println(response.latency)
+---
- // ping bedrock
- val response = mcping("play.wildnetwork.net", 19132, ServerType.Bedrock)
- println(response.toBedrockResponse())
-}
-```
+## Protocol Packet Codecs Mapping
-## Java example
+
+Click to expand
-```java
-void main() {
- // ping java server
- String testJavaHost = "org.mc-complex.com";
- PingResponse javaResponse = McPing.mcping(testJavaHost, 25565);
+### 1. Status Stage
- // ping bedrock server
- String testBedrockHost = "play.wildnetwork.net";
- PingResponse bedrockResponse = McPing.mcping(testBedrockHost, 19132, ServerType.Bedrock);
- System.out.println(bedrockResponse.toBedrockResponse());
-}
-```
+#### Clientbound
-> java consumers should not manually pass the context parameter
+- [x] `0x00` Status Response (`ClientboundStatusResponsePacket`)
+- [x] `0x01` Pong Response (`ClientboundPongResponsePacket`)
-## Other resources
+#### Serverbound
-> An example of java ping json response can be found at [ping-response-example](example/java-ping-response.json)
-> (Formatted),
-> a raw response of bedrock ping response can be found
-> at [bedrock-pinng-raw-response](example/bedrock-pinng-raw-response.txt)
+- [x] `0x00` Status Request (`ServerboundStatusRequestPacket`)
+- [x] `0x01` Ping Request (`ServerboundPingRequestPacket`)
-# rcon client
+---
-```kotlin
-fun main() {
- val host = "127.0.0.1"
- val port = 25575
- val client = rconClient(host, port)
- val authed = client.connect("123456")
- if (authed) println(client.command("list")) else throw IllegalArgumentException("incorrect password")
-}
-```
+### 2. Handshake Stage
-> also supports java
+#### Serverbound
-```java
-void main() {
- String host = "127.0.0.1";
- int port = 25575;
- String password = "123456";
- RCONClient rconClient = Rconlib.rconClient(host, port);
- boolean authed = rconClient.connect(password);
- if (authed) {
- System.out.println(rconClient.command("list"));
- } else {
- throw new IllegalStateException("incorrect password");
- }
-}
-```
+- [x] `0x00` Handshake (`ServerboundHandshakePacket`)
+
+---
+
+### 3. Login Stage
+
+#### Clientbound
+
+- [x] `0x00` Disconnect (`ClientboundDisconnectLoginPacket`)
+- [x] `0x01` Encryption Request (`ClientboundHelloPacket`)
+- [x] `0x02` Login Success (`ClientboundLoginSuccessPacket`)
+- [x] `0x03` Set Compression (`ClientboundSetCompressionPacket`)
+- [x] `0x04` Login Plugin Request (`ClientboundCustomQueryPacket`)
+- [x] `0x05` Cookie Request (`ClientboundCookieRequestPacket`)
+
+#### Serverbound
+
+- [x] `0x00` Login Start (`ServerboundLoginStartPacket`)
+- [x] `0x01` Encryption Response (`ServerboundKeyPacket`)
+- [x] `0x02` Login Plugin Response (`ServerboundCustomQueryAnswerPacket`)
+- [x] `0x03` Login Acknowledged (`ServerboundLoginAcknowledgedPacket`)
+- [x] `0x04` Cookie Response (`ServerboundCookieResponsePacket`)
+
+---
+
+### 4. Configuration Stage
+
+#### Clientbound
+
+- [x] `0x00` Cookie Request (`ClientboundCookieRequestPacket`)
+- [x] `0x01` Custom Payload (`ClientboundCustomPayloadPacket`)
+- [x] `0x02` Disconnect (`ClientboundDisconnectConfigurationPacket`)
+- [x] `0x03` Finish Configuration (`ClientboundFinishConfigurationPacket`)
+- [x] `0x04` Keep Alive (`ClientboundKeepAliveConfigurationPacket`)
+- [x] `0x05` Ping (`ClientboundPingConfigurationPacket`)
+- [x] `0x06` Reset Chat (`ClientboundResetChatPacket`)
+- [x] `0x07` Registry Data (`ClientboundRegistryDataPacket`)
+- [x] `0x08` Remove Resource Pack (`ClientboundRemoveResourcePackPacket`)
+- [x] `0x09` Add Resource Pack (`ClientboundAddResourcePackPacket`)
+- [x] `0x0A` Store Cookie (`ClientboundStoreCookiePacket`)
+- [x] `0x0B` Transfer (`ClientboundTransferPacket`)
+- [x] `0x0C` Update Enabled Features (`ClientboundUpdateEnabledFeaturesPacket`)
+- [x] `0x0D` Update Tags (`ClientboundUpdateTagsPacket`)
+- [x] `0x0E` Select Known Packs (`ClientboundSelectKnownPacksPacket`)
+- [x] `0x0F` Custom Report Details (`ClientboundCustomReportDetailsPacket`)
+- [x] `0x10` Server Links (`ClientboundServerLinksPacket`)
+- [x] `0x11` Clear Dialog (`ClientboundClearDialogPacket`)
+- [x] `0x12` Show Dialog (`ClientboundConfigurationShowDialogPacket`)
+- [x] `0x13` Code Of Conduct (`ClientboundCodeOfConductPacket`)
+
+#### Serverbound
+
+- [x] `0x00` Client Information (`ServerboundCookieResponsePacket`)
+- [x] `0x01` Cookie Response (`ServerboundCookieResponsePacket`)
+- [x] `0x02` Plugin Message (`ServerboundCustomPayloadPacket`)
+- [x] `0x03` Finish Configuration Acknowledged (`ServerboundAckFinishConfigurationPacket`)
+- [x] `0x04` Keep Alive Response (`ServerboundKeepAliveConfigurationPacket`)
+- [x] `0x05` Pong Response (`ServerboundPongConfigurationPacket`)
+- [x] `0x07` Select Known Packs (`ServerboundSelectKnownPacksPacket`)
+- [x] `0x08` Custom Click Action (`ServerboundCustomClickActionPacket`)
+- [x] `0x09` Accept Code Of Conduct (`ServerboundAcceptCodeOfConductPacket`)
+
+---
+
+### 5. Play Stage
+
+#### Clientbound
+
+- [x] `0x00` Delimiter (`ClientboundDelimiterPacket`)
+- [x] `0x01` Spawn Entity (`ClientboundSpawnEntityPacket`)
+- [x] `0x02` Entity Animation (`ClientboundEntityAnimationPacket`)
+- [x] `0x03` Award Statistics (`ClientboundAwardStatisticsPacket`)
+- [x] `0x04` Acknowledge Block Change (`ClientboundAcknowledgeBlockChangePacket`)
+- [x] `0x05` Block Destruction (`ClientboundBlockDestructionPacket`)
+- [x] `0x06` Block Entity Data (`ClientboundBlockEntityDataPacket`)
+- [x] `0x07` Block Event (`ClientboundBlockEventPacket`)
+- [x] `0x08` Block Update (`ClientboundBlockUpdatePacket`)
+- [x] `0x09` Boss Event (`ClientboundBossEventPacket`)
+- [x] `0x0A` Change Difficulty (`ClientboundChangeDifficultyPacket`)
+- [x] `0x0B` Chunk Batch Finished (`ClientboundChunkBatchFinishedPacket`)
+- [x] `0x0C` Chunk Batch Start (`ClientboundChunkBatchStartPacket`)
+- [x] `0x0D` Chunks Biomes (`ClientboundChunksBiomesPacket`)
+- [x] `0x0E` Clear Titles (`ClientboundClearTitlesPacket`)
+- [x] `0x0F` Command Suggestions (`ClientboundCommandSuggestionsPacket`)
+- [ ] `0x10` Commands (`ClientboundCommandsPacket`)
+- [x] `0x11` Container Close (`ClientboundContainerClosePacket`)
+- [x] `0x12` Container Set Content (`ClientboundContainerSetContentPacket`)
+- [x] `0x13` Container Set Data (`ClientboundContainerSetDataPacket`)
+- [x] `0x14` Container Set Slot (`ClientboundContainerSetSlotPacket`)
+- [x] `0x15` Cookie Request (`ClientboundCookieRequestPacket`)
+- [x] `0x16` Cooldown (`ClientboundCooldownPacket`)
+- [x] `0x17` Custom Chat Completions (`ClientboundCustomChatCompletionsPacket`)
+- [x] `0x18` Custom Payload (`ClientboundCustomPayloadPacket`)
+- [x] `0x19` Damage Event (`ClientboundDamageEventPacket`)
+- [ ] `0x1A` Debug Block Value (`ClientboundDebugBlockValuePacket`)
+- [ ] `0x1B` Debug Chunk Value (`ClientboundDebugChunkValuePacket`)
+- [ ] `0x1C` Debug Entity Value (`ClientboundDebugEntityValuePacket`)
+- [ ] `0x1D` Debug Event (`ClientboundDebugEventPacket`)
+- [ ] `0x1E` Debug Sample (`ClientboundDebugSamplePacket`)
+- [x] `0x1F` Delete Chat (`ClientboundDeleteChatPacket`)
+- [x] `0x20` Disconnect (`ClientboundDisconnectPlayPacket`)
+- [x] `0x21` Disguised Chat Message (`ClientboundDisguisedChatMessagePacket`)
+- [x] `0x22` Entity Event (`ClientboundEntityEventPacket`)
+- [x] `0x23` Teleport Entity (`ClientboundTeleportEntityPacket`)
+- [ ] `0x24` Explode (`ClientboundExplodePacket`)
+- [x] `0x25` Unload Chunk (`ClientboundUnloadChunkPacket`)
+- [x] `0x26` Game Event (`ClientboundGameEventPacket`)
+- [x] `0x27` Game Rule Values (`ClientboundGameRuleValuesPacket`)
+- [x] `0x28` Test Highlight Position (`ClientboundTestHighlightPositionPacket`)
+- [x] `0x29` Open Horse Screen (`ClientboundOpenHorseScreenPacket`)
+- [x] `0x2A` Hurt Animation (`ClientboundHurtAnimationPacket`)
+- [x] `0x2B` Initialize World Border (`ClientboundInitializeWorldBorderPacket`)
+- [x] `0x2C` Keep Alive (`ClientboundKeepAlivePlayPacket`)
+- [ ] `0x2D` Level Chunk Update With Light (`ClientboundLevelChunkUpdateWithLightPacket`)
+- [x] `0x2E` Level Event (`ClientboundLevelEventPacket`)
+- [ ] `0x2F` Particle (`ClientboundParticlePacket`)
+- [ ] `0x30` Light Update (`ClientboundLightUpdatePacket`)
+- [x] `0x31` Login Play (`ClientboundLoginPlayPacket`)
+- [x] `0x32` Low Disk Space Warning (`ClientboundLowDiskSpaceWarningPacket`)
+- [ ] `0x33` Map Item Data (`ClientboundMapItemDataPacket`)
+- [ ] `0x34` Merchant Offers (`ClientboundMerchantOffersPacket`)
+- [x] `0x35` Update Entity Position (`ClientboundUpdateEntityPositionPacket`)
+- [x] `0x36` Update Entity Position and Rotation (`ClientboundUpdateEntityPositionAndRotationPacket`)
+- [x] `0x37` Move Minecart Along Track (`ClientboundMoveMinecartAlongTrackPacket`)
+- [x] `0x38` Update Entity Rotation (`ClientboundUpdateEntityRotationPacket`)
+- [x] `0x39` Move Vehicle (`ClientboundMoveVehiclePacket`)
+- [x] `0x3A` Open Book (`ClientboundOpenBookPacket`)
+- [x] `0x3B` Open Screen (`ClientboundOpenScreenPacket`)
+- [x] `0x3C` Open Sign Editor (`ClientboundOpenSignEditorPacket`)
+- [x] `0x3D` Ping (`ClientboundPingPacket`)
+- [x] `0x3E` Pong Response (`ClientboundPongResponsePacket`)
+- [ ] `0x3F` Place Ghost Recipe (`ClientboundPlaceGhostRecipePacket`)
+- [x] `0x40` Player Abilities (`ClientboundPlayerAbilitiesPacket`)
+- [x] `0x41` Player Chat Message (`ClientboundPlayerChatMessagePacket`)
+- [x] `0x42` Player End Combat (`ClientboundPlayerEndCombatPacket`)
+- [x] `0x43` Player Enter Combat (`ClientboundPlayerEnterCombatPacket`)
+- [x] `0x44` Player Combat Death (`ClientboundPlayerCombatDeathPacket`)
+- [x] `0x45` Player Info Remove (`ClientboundPlayerInfoRemovePacket`)
+- [ ] `0x46` Player Info Update (`ClientboundPlayerInfoUpdatePacket`)
+- [x] `0x47` Player Look At (`ClientboundPlayerLookAtPacket`)
+- [x] `0x48` Synchronize Player Position (`ClientboundSynchronizePlayerPositionPacket`)
+- [x] `0x49` Player Rotation (`ClientboundPlayerRotationPacket`)
+- [ ] `0x4A` Recipe Book Add (`ClientboundRecipeBookAddPacket`)
+- [ ] `0x4B` Recipe Book Remove (`ClientboundRecipeBookRemovePacket`)
+- [ ] `0x4C` Recipe Book Settings (`ClientboundRecipeBookSettingsPacket`)
+- [x] `0x4D` Remove Entities (`ClientboundRemoveEntitiesPacket`)
+- [x] `0x4E` Remove Entity Effect (`ClientboundRemoveEntityEffectPacket`)
+- [x] `0x4F` Reset Score (`ClientboundResetScorePacket`)
+- [x] `0x50` Remove Resource Pack (`ClientboundRemoveResourcePackPacket`)
+- [x] `0x51` Add Resource Pack (`ClientboundAddResourcePackPacket`)
+- [x] `0x52` Respawn (`ClientboundRespawnPacket`)
+- [x] `0x53` Set Head Rotation (`ClientboundSetHeadRotationPacket`)
+- [x] `0x54` Update Section Block (`ClientboundUpdateSectionBlockPacket`)
+- [x] `0x55` Select Advancements Tab (`ClientboundSelectAdvancementsTabPacket`)
+- [x] `0x56` Server Data (`ClientboundServerDataPacket`)
+- [x] `0x57` Set Action Bar Text (`ClientboundSetActionBarTextPacket`)
+- [x] `0x58` Set Border Center (`ClientboundSetBorderCenterPacket`)
+- [x] `0x59` Set Border Leap Size (`ClientboundSetBorderLeapSizePacket`)
+- [x] `0x5A` Set Border Size (`ClientboundSetBorderSizePacket`)
+- [x] `0x5B` Set Border Warning Delay (`ClientboundSetBorderWarningDelayPacket`)
+- [x] `0x5C` Set Border Warning Distance (`ClientboundSetBorderWarningDistancePacket`)
+- [x] `0x5D` Set Camera (`ClientboundSetCameraPacket`)
+- [x] `0x5E` Set Center Chunk (`ClientboundSetCenterChunkPacket`)
+- [x] `0x5F` Set Render Distance (`ClientboundSetRenderDistancePacket`)
+- [x] `0x60` Set Cursor Item (`ClientboundSetCursorItemPacket`)
+- [x] `0x61` Set Default Spawn Position (`ClientboundSetDefaultSpawnPositionPacket`)
+- [x] `0x62` Set Display Objective (`ClientboundSetDisplayObjectivePacket`)
+- [ ] `0x63` Set Entity Metadata (`ClientboundSetEntityMetadataPacket`)
+- [x] `0x64` Link Entities (`ClientboundLinkEntitiesPacket`)
+- [x] `0x65` Set Entity Velocity (`ClientboundSetEntityVelocityPacket`)
+- [x] `0x66` Set Equipment (`ClientboundSetEquipmentPacket`)
+- [x] `0x67` Set Experience (`ClientboundSetExperiencePacket`)
+- [x] `0x68` Set Health (`ClientboundSetHealthPacket`)
+- [x] `0x69` Set Carried Item (`ClientboundSetCarriedItemPacket`)
+- [x] `0x6A` Update Objective (`ClientboundUpdateObjectivePacket`)
+- [x] `0x6B` Set Passengers (`ClientboundSetPassengersPacket`)
+- [x] `0x6C` Set Player Inventory Slot (`ClientboundSetPlayerInventorySlotPacket`)
+- [ ] `0x6D` Set Player Team (`ClientboundSetPlayerTeamPacket`)
+- [x] `0x6E` Update Score (`ClientboundUpdateScorePacket`)
+- [x] `0x6F` Set Simulation Distance (`ClientboundSetSimulationDistancePacket`)
+- [x] `0x70` Set Subtitle Text (`ClientboundSetSubtitleTextPacket`)
+- [x] `0x71` Set Time (`ClientboundSetTimePacket`)
+- [x] `0x72` Set Title Text (`ClientboundSetTitleTextPacket`)
+- [x] `0x73` Set Title Animation Times (`ClientboundSetTitleAnimationTimesPacket`)
+- [x] `0x74` Entity Sound Effect (`ClientboundEntitySoundEffectPacket`)
+- [x] `0x75` Sound Effect (`ClientboundSoundEffectPacket`)
+- [x] `0x76` Start Configuration (`ClientboundStartConfigurationPacket`)
+- [x] `0x77` Stop Sound (`ClientboundStopSoundPacket`)
+- [x] `0x78` Store Cookie (`ClientboundStoreCookiePacket`)
+- [x] `0x79` System Chat Message (`ClientboundSystemChatMessagePacket`)
+- [x] `0x7A` Set Tab List Header And Footer (`ClientboundSetTabListHeaderAndFooterPacket`)
+- [x] `0x7B` Tag Query Response (`ClientboundTagQueryResponsePacket`)
+- [x] `0x7C` Pickup Item (`ClientboundPickupItemPacket`)
+- [x] `0x7D` Synchronize Vehicle Position (`ClientboundSynchronizeVehiclePositionPacket`)
+- [x] `0x7E` Test Instance Block Status (`ClientboundTestInstanceBlockStatusPacket`)
+- [x] `0x7F` Set Ticking State (`ClientboundSetTickingStatePacket`)
+- [x] `0x80` Step Tick (`ClientboundStepTickPacket`)
+- [x] `0x81` Transfer (`ClientboundTransferPacket`)
+- [ ] `0x82` Update Advancements (`ClientboundUpdateAdvancementsPacket`)
+- [x] `0x83` Update Attributes (`ClientboundUpdateAttributesPacket`)
+- [x] `0x84` Entity Effect (`ClientboundEntityEffectPacket`)
+- [ ] `0x85` Update Recipes (`ClientboundUpdateRecipesPacket`)
+- [x] `0x86` Update Tags (`ClientboundUpdateTagsPacket`)
+- [x] `0x87` Projectile Power (`ClientboundProjectilePowerPacket`)
+- [x] `0x88` Custom Report Details (`ClientboundCustomReportDetailsPacket`)
+- [x] `0x89` Server Links (`ClientboundServerLinksPacket`)
+- [ ] `0x8A` Waypoint (`ClientboundWaypointPacket`)
+- [x] `0x8B` Clear Dialog (`ClientboundClearDialogPacket`)
+- [x] `0x8C` Show Dialog (`ClientboundShowDialogPacket`)
+
+#### Serverbound
+
+- [x] `0x00` Accept Teleportation (`ServerboundAcceptTeleportationPacket`)
+- [x] `0x01` Attack Action (`ServerboundAttackActionPacket`)
+- [x] `0x02` Query Block Entity Tag (`ServerboundQueryBlockEntityTagPacket`)
+- [x] `0x03` Bundle Item Selected (`ServerboundBundleItemSelectedPacket`)
+- [x] `0x04` Change Difficulty (`ServerboundChangeDifficultyPacket`)
+- [x] `0x05` Change Game Mode (`ServerboundChangeGameModePacket`)
+- [x] `0x06` Acknowledge Chat Message (`ServerboundAcknowledgeChatMessagePacket`)
+- [x] `0x07` Chat Command (`ServerboundChatCommandPacket`)
+- [x] `0x08` Signed Chat Command (`ServerboundSignedChatCommandPacket`)
+- [x] `0x09` Chat Message (`ServerboundChatMessagePacket`)
+- [x] `0x0A` Update Chat Session (`ServerboundUpdateChatSessionPacket`)
+- [x] `0x0B` Chunk Batch Received (`ServerboundChunkBatchReceivedPacket`)
+- [x] `0x0C` Client Command (`ServerboundClientCommandPacket`)
+- [x] `0x0D` Client Tick End (`ServerboundClientTickEndPacket`)
+- [x] `0x0E` Client Information (`ServerboundClientInformationPacket`)
+- [x] `0x0F` Command Suggestion Request (`ServerboundCommandSuggestionRequestPacket`)
+- [x] `0x10` Configuration Acknowledged (`ServerboundConfigurationAcknowledgedPacket`)
+- [x] `0x11` Container Click Button (`ServerboundContainerClickButtonPacket`)
+- [x] `0x12` Container Click (`ServerboundContainerClickPacket`)
+- [x] `0x13` Container Close (`ServerboundContainerClosePacket`)
+- [x] `0x14` Change Container Slot State (`ServerboundChangeContainerSlotStatePacket`)
+- [x] `0x15` Cookie Response (`ServerboundCookieResponsePacket`)
+- [x] `0x16` Custom Payload (`ServerboundCustomPayloadPacket`)
+- [ ] `0x17` Debug Subscription Request (`ServerboundDebugSubscriptionRequestPacket`)
+- [x] `0x18` Edit Book (`ServerboundEditBookPacket`)
+- [x] `0x19` Query Entity Tag (`ServerboundQueryEntityTagPacket`)
+- [x] `0x1A` Interact (`ServerboundInteractPacket`)
+- [x] `0x1B` Jigsaw Generate (`ServerboundJigsawGeneratePacket`)
+- [x] `0x1C` Keep Alive (`ServerboundKeepAlivePlayPacket`)
+- [x] `0x1D` Lock Difficulty (`ServerboundLockDifficultyPacket`)
+- [x] `0x1E` Set Player Position (`ServerboundSetPlayerPositionPacket`)
+- [x] `0x1F` Set Player Position and Rotation (`ServerboundSetPlayerPositionAndRotationPacket`)
+- [x] `0x20` Set Player Rotation (`ServerboundSetPlayerRotationPacket`)
+- [x] `0x21` Set Player Movement Flag (`ServerboundSetPlayerMovementFlagPacket`)
+- [x] `0x22` Move Vehicle (`ServerboundMoveVehiclePacket`)
+- [x] `0x23` Paddle Boat (`ServerboundPaddleBoatPacket`)
+- [x] `0x24` Pick Item From Block (`ServerboundPickItemFromBlockPacket`)
+- [x] `0x25` Pick Item From Entity (`ServerboundPickItemFromEntityPacket`)
+- [x] `0x26` Ping Request (`ServerboundPingRequestPacket`)
+- [x] `0x27` Place Recipe (`ServerboundPlaceRecipePacket`)
+- [x] `0x28` Player Abilities (`ServerboundPlayerAbilitiesPacket`)
+- [x] `0x29` Player Action (`ServerboundPlayerActionPacket`)
+- [x] `0x2A` Player Command (`ServerboundPlayerCommandPacket`)
+- [x] `0x2B` Player Input (`ServerboundPlayerInputPacket`)
+- [x] `0x2C` Player Loaded (`ServerboundPlayerLoadedPacket`)
+- [x] `0x2D` Pong (`ServerboundPongPlayPacket`)
+- [x] `0x2E` Recipe Book Change Settings (`ServerboundRecipeBookChangeSettingsPacket`)
+- [x] `0x2F` Recipe Book Seen Recipe (`ServerboundRecipeBookSeenRecipePacket`)
+- [x] `0x30` Rename Item (`ServerboundRenameItemPacket`)
+- [x] `0x31` Resource Pack Response (`ServerboundResourcePackResponsePacket`)
+- [x] `0x32` Seen Advancements (`ServerboundSeenAdvancementsPacket`)
+- [x] `0x33` Select Trade (`ServerboundSelectTradePacket`)
+- [x] `0x34` Set Beacon (`ServerboundSetBeaconPacket`)
+- [x] `0x35` Set Carried Item (`ServerboundSetCarriedItemPacket`)
+- [x] `0x36` Set Command Block (`ServerboundSetCommandBlockPacket`)
+- [x] `0x37` Set Command Minecart (`ServerboundSetCommandMinecartPacket`)
+- [x] `0x38` Set Creative Mode Slot (`ServerboundSetCreativeModeSlotPacket`)
+- [x] `0x39` Set Game Rule (`ServerboundSetGameRulePacket`)
+- [x] `0x3A` Set Jigsaw Block (`ServerboundSetJigsawBlockPacket`)
+- [x] `0x3B` Set Structure Block (`ServerboundSetStructureBlockPacket`)
+- [x] `0x3C` Set Test Block (`ServerboundSetTestBlockPacket`)
+- [x] `0x3D` Sign Update (`ServerboundSignUpdatePacket`)
+- [x] `0x3E` Spectator Action (`ServerboundSpectatorActionPacket`)
+- [x] `0x3F` Swing (`ServerboundSwingPacket`)
+- [x] `0x40` Teleport To Entity (`ServerboundTeleportToEntityPacket`)
+- [x] `0x41` Test Instance Block Action (`ServerboundTestInstanceBlockActionPacket`)
+- [x] `0x42` Use Item On (`ServerboundUseItemOnPacket`)
+- [x] `0x43` Use Item (`ServerboundUseItemPacket`)
+- [x] `0x44` Custom Click Action (`ServerboundCustomClickActionPacket`)
+
+
+
+
+---
+
+# libmc-mcping
+
+A lightweight module to query Minecraft Java and Bedrock server status, MOTD, and latency
+
+[Use mcping](https://repo.rtast.cn/packages/-/cn.rtast.libmc:mcping)
+
+# libmc-rconlib
+
+Send Command via rcon protocol
+
+[Use rconlib](https://repo.rtast.cn/packages/-/cn.rtast.libmc:rconlib)
+
+# libmc-nbt
+
+NBT reader and writer, compat with network NBT
+
+# libmc-snbt
+
+> Not completed
# Open Source
diff --git a/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/buffer.kt b/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/buffer.kt
index d5c7b94..cc4d8d3 100644
--- a/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/buffer.kt
+++ b/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/buffer.kt
@@ -21,6 +21,7 @@ public expect class BytesBuffer {
public fun writeBoolean(value: Boolean)
public fun readByte(): Byte
+ public fun readUByte(): UByte
public fun readShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short
public fun readInt(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Int
public fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long
diff --git a/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/codec.kt b/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/codec.kt
index b2cef5c..3dd118a 100644
--- a/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/codec.kt
+++ b/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/codec.kt
@@ -9,18 +9,10 @@ package cn.rtast.libmc.common
public interface Encoder {
public fun encode(buffer: BytesBuffer, value: T)
-
- public fun encodeToByteArray(value: T): ByteArray {
- val buf = BytesBuffer()
- encode(buf, value)
- return buf.toByteArray()
- }
}
public interface Decoder {
public fun decode(buffer: BytesBuffer): T
-
- public fun decodeFromByteArray(bytes: ByteArray): T = decode(bytes.wrap())
}
public interface PacketCodec : Encoder, Decoder
diff --git a/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/mc_primitives.kt b/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/mc_primitives.kt
index 73d4df7..8cbb5b4 100644
--- a/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/mc_primitives.kt
+++ b/libmc-common/src/commonMain/kotlin/cn/rtast/libmc/common/mc_primitives.kt
@@ -130,14 +130,6 @@ public fun BytesBuffer.writePrefixedByteArray(data: ByteArray) {
this.writeBytes(data)
}
-public fun BytesBuffer.readOptionalPrefixedByteArray(): ByteArray? {
- val isPresent = this.readBoolean()
- return if (isPresent) {
- val length = this.readVarInt()
- this.readBytes(length)
- } else null
-}
-
public fun BytesBuffer.writeOptionalPrefixedByteArray(data: ByteArray?) {
if (data != null) {
this.writeBoolean(true)
@@ -146,18 +138,6 @@ public fun BytesBuffer.writeOptionalPrefixedByteArray(data: ByteArray?) {
} else this.writeBoolean(false)
}
-public fun BytesBuffer.readPrefixedVarIntArray(): List {
- val length = readVarInt()
- val list = ArrayList(length)
- repeat(length) { list.add(readVarInt()) }
- return list
-}
-
-public fun BytesBuffer.writePrefixedVarIntArray(value: List) {
- writeVarInt(value.size)
- for (item in value) writeVarInt(item)
-}
-
public fun BytesBuffer.readPrefixedStringArray(): List {
val length = readVarInt()
val list = ArrayList(length)
@@ -170,7 +150,83 @@ public fun BytesBuffer.writePrefixedStringArray(value: List) {
for (item in value) writeMcString(item)
}
-public inline fun BytesBuffer.writePrefixedArray(value: List, writeItem: BytesBuffer.(T) -> Unit) {
- writeVarInt(value.size)
- for (item in value) writeItem(item)
+public inline fun BytesBuffer.readOptional(block: BytesBuffer.() -> T): T? {
+ val hasData = this.readBoolean()
+ return if (hasData) block.invoke(this) else null
+}
+
+/**
+ * buffer.writeOptional(value.someValue) { writeBlockPos(it) }
+ */
+public inline fun BytesBuffer.writeOptional(value: T?, block: BytesBuffer.(T) -> Unit) {
+ if (value != null) {
+ this.writeBoolean(true)
+ block.invoke(this, value)
+ } else this.writeBoolean(false)
+}
+
+public inline fun BytesBuffer.readPrefixed(reader: BytesBuffer.() -> T): List {
+ val count = this.readVarInt()
+ val list = ArrayList(count)
+ repeat(count) { _ -> list.add(this.reader()) }
+ return list
+}
+
+public inline fun BytesBuffer.writePrefixed(list: List, writer: BytesBuffer.(T) -> Unit) {
+ this.writeVarInt(list.size)
+ for (item in list) this.writer(item)
+}
+
+public fun BytesBuffer.readBitSet(): LongArray {
+ val count = this.readVarInt()
+ return LongArray(count) { this.readLong() }
+}
+
+public fun BytesBuffer.writeBitSet(data: LongArray) {
+ this.writeVarInt(data.size)
+ for (i in data.indices) this.writeLong(data[i])
+}
+
+public fun LongArray.countSetBits(): Int {
+ var count = 0
+ for (i in indices) count += this[i].countOneBits()
+ return count
+}
+
+public fun LongArray.getBit(bitIndex: Int): Boolean {
+ val longIndex = bitIndex shr 6
+ if (longIndex !in this.indices) return false
+ val bitOffset = bitIndex and 63
+ return (this[longIndex] and (1L shl bitOffset)) != 0L
+}
+
+public sealed interface IdSet {
+ public data class Tag(val tagName: String) : IdSet
+ public data class Entries(val ids: List) : IdSet
+}
+
+public fun BytesBuffer.readIdSet(): IdSet {
+ val type = this.readVarInt()
+ return if (type == 0) {
+ IdSet.Tag(tagName = this.readMcString())
+ } else {
+ val count = type - 1
+ val ids = ArrayList(count)
+ (0 until count).forEach { _ -> ids.add(this.readVarInt()) }
+ IdSet.Entries(ids)
+ }
+}
+
+public fun BytesBuffer.writeIdSet(idSet: IdSet) {
+ when (idSet) {
+ is IdSet.Tag -> {
+ this.writeVarInt(0)
+ this.writeMcString(idSet.tagName)
+ }
+
+ is IdSet.Entries -> {
+ this.writeVarInt(idSet.ids.size + 1)
+ for (id in idSet.ids) this.writeVarInt(id)
+ }
+ }
}
\ No newline at end of file
diff --git a/libmc-common/src/jvmMain/kotlin/cn/rtast/libmc/common/buffer.jvm.kt b/libmc-common/src/jvmMain/kotlin/cn/rtast/libmc/common/buffer.jvm.kt
index 0f8e000..ddd7401 100644
--- a/libmc-common/src/jvmMain/kotlin/cn/rtast/libmc/common/buffer.jvm.kt
+++ b/libmc-common/src/jvmMain/kotlin/cn/rtast/libmc/common/buffer.jvm.kt
@@ -90,6 +90,7 @@ public actual class BytesBuffer {
return array[readOffset++]
}
+ public actual fun readUByte(): UByte = this.readByte().toUByte()
public actual fun readShort(endian: ByteOrder): Short = readBytes(2).toShort(endian)
public actual fun readInt(endian: ByteOrder): Int = readBytes(4).toInt(endian)
public actual fun readLong(endian: ByteOrder): Long = readBytes(8).toLong(endian)
diff --git a/libmc-common/src/nativeMain/kotlin/cn/rtast/libmc/common/buffer.native.kt b/libmc-common/src/nativeMain/kotlin/cn/rtast/libmc/common/buffer.native.kt
index 92ea372..9a80c17 100644
--- a/libmc-common/src/nativeMain/kotlin/cn/rtast/libmc/common/buffer.native.kt
+++ b/libmc-common/src/nativeMain/kotlin/cn/rtast/libmc/common/buffer.native.kt
@@ -47,6 +47,7 @@ public actual class BytesBuffer {
public actual fun writeBoolean(value: Boolean): Unit = _delegateBuf.writeByte(if (value) 0x01 else 0x00)
public actual fun readByte(): Byte = _delegateBuf.readByte()
+ public actual fun readUByte(): UByte = this.readByte().toUByte()
public actual fun readShort(endian: ByteOrder): Short =
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readShort() else _delegateBuf.readShortLe()
diff --git a/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTReader.kt b/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTReader.kt
index a1e081a..2208bfe 100644
--- a/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTReader.kt
+++ b/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTReader.kt
@@ -15,7 +15,7 @@ public fun NBTInput.readStringTag(): String {
public fun NBTInput.readListTag(): NBTTag.ListTag {
val elementTypeId = readByte().toInt() and 0xFF
- val elementType = NBTType.fromId(elementTypeId)
+ val elementType = NBTType.fromID(elementTypeId)
val length = readInt()
val list = ArrayList(length)
repeat(length) { list += readTagPayload(elementType) }
@@ -28,7 +28,7 @@ public fun NBTInput.readCompoundTag(): NBTTag.CompoundTag {
val typeId = readByte().toInt() and 0xFF
if (typeId == 0) break // TAG_End
val name = readStringTag()
- val type = NBTType.fromId(typeId)
+ val type = NBTType.fromID(typeId)
val payload = readTagPayload(type)
map[name] = payload
}
@@ -56,7 +56,7 @@ public fun NBTInput.readCompound(): NBTTag {
val map = LinkedHashMap()
while (true) {
val typeId = readByte().toInt()
- val type = NBTType.fromId(typeId)
+ val type = NBTType.fromID(typeId)
if (type == NBTType.End) break
val nameLen = readShort().toInt() and 0xFFFF
val nameBytes = readBytes(nameLen)
@@ -68,7 +68,7 @@ public fun NBTInput.readCompound(): NBTTag {
}
public fun NBTInput.readRootCompound(): NBTCompound {
- val rootType = NBTType.fromId(readByte().toInt())
+ val rootType = NBTType.fromID(readByte().toInt())
require(rootType == NBTType.Compound) { "Root tag must be TAG_Compound" }
val nameLen = readShort().toInt() and 0xFFFF
val name = readBytes(nameLen).decodeToString()
@@ -77,7 +77,7 @@ public fun NBTInput.readRootCompound(): NBTCompound {
}
public fun NBTInput.readNetworkCompound(): NBTCompound {
- return when (val type = NBTType.fromId(readByte().toInt() and 0xFF)) {
+ 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()))))
else -> throw UnsupportedOperationException("Unsupported network nbt tag 0x${type.id.toString(16).uppercase()}")
diff --git a/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTType.kt b/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTType.kt
index 3564ada..137f955 100644
--- a/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTType.kt
+++ b/libmc-nbt/src/commonMain/kotlin/cn/rtast/libmc/nbt/NBTType.kt
@@ -14,7 +14,7 @@ public enum class NBTType(public val id: Byte) {
IntArray(11), LongArray(12);
public companion object {
- public fun fromId(id: Int): NBTType =
+ public fun fromID(id: Int): NBTType =
entries.firstOrNull { it.id.toInt() == id } ?: error("Unknown NBT type id: $id")
}
}
\ No newline at end of file
diff --git a/libmc-protocol/build.gradle.kts b/libmc-protocol/build.gradle.kts
index 7090571..b877846 100644
--- a/libmc-protocol/build.gradle.kts
+++ b/libmc-protocol/build.gradle.kts
@@ -20,8 +20,6 @@ kotlin {
commonMain.dependencies {
api(project(":common"))
api(project(":nbt"))
- api(libs.kotlinx.serialization.core)
- api(libs.kotlinx.serialization.json)
api(libs.kotlinx.coroutines)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/event/InternalPacketDispatcher.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/event/InternalPacketDispatcher.kt
index 6f6664d..b80ad3b 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/event/InternalPacketDispatcher.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/event/InternalPacketDispatcher.kt
@@ -124,6 +124,15 @@ internal class InternalPacketDispatcher(private val client: MinecraftClient) {
is ClientboundEntityAnimationPacket -> {}
is ClientboundSpawnEntityPacket -> {}
is ClientboundShowDialogPacket -> {}
+ is ClientboundBlockEventPacket -> TODO()
+ is ClientboundBlockUpdatePacket -> TODO()
+ is ClientboundBossEventPacket -> TODO()
+ is ClientboundChangeDifficultyPacket -> TODO()
+ is ClientboundChunkBatchFinishedPacket -> TODO()
+ ClientboundChunkBatchStartPacket -> TODO()
+ is ClientboundChunksBiomesPacket -> TODO()
+ is ClientboundClearTitlesPacket -> TODO()
+ is ClientboundCommandSuggestionsPacket -> TODO()
}
}
}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/KnownPacks.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/KnownPacks.kt
index c15f0cd..beabec9 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/KnownPacks.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/KnownPacks.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.common.readMcString
import cn.rtast.libmc.common.writeMcString
public data class KnownPacks(val namespace: String, val id: String, val version: String) {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: KnownPacks) {
buffer.writeMcString(value.namespace)
buffer.writeMcString(value.id)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundAddResourcePackPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundAddResourcePackPacket.kt
index 568ead6..b49f373 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundAddResourcePackPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundAddResourcePackPacket.kt
@@ -19,7 +19,7 @@ public data class ClientboundAddResourcePackPacket(
val forced: Boolean,
val prompt: NBTCompound,
) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundAddResourcePackPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundAddResourcePackPacket {
val uuid = buffer.readUuid()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCodeOfConductPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCodeOfConductPacket.kt
index 5b15f9e..2bc7d36 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCodeOfConductPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCodeOfConductPacket.kt
@@ -12,7 +12,7 @@ import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readMcString
public data class ClientboundCodeOfConductPacket(val codeOfConduct: String) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundCodeOfConductPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundCodeOfConductPacket {
return ClientboundCodeOfConductPacket(buffer.readMcString())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundConfigurationShowDialogPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundConfigurationShowDialogPacket.kt
index 5696a43..09bdf86 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundConfigurationShowDialogPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundConfigurationShowDialogPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundConfigurationShowDialogPacket(val dialog: NBTCompound) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundConfigurationShowDialogPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundConfigurationShowDialogPacket {
return ClientboundConfigurationShowDialogPacket(buffer.readNetworkNBTCompound())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCookieRequestPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCookieRequestPacket.kt
index 9ff7f3e..71c3c00 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCookieRequestPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCookieRequestPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
public data class ClientboundCookieRequestPacket(val key: Identifier) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundCookieRequestPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundCookieRequestPacket {
return ClientboundCookieRequestPacket(key = buffer.readIdentifier())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomPayloadPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomPayloadPacket.kt
index 9454ba1..077bdfc 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomPayloadPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomPayloadPacket.kt
@@ -9,14 +9,15 @@ 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.packet.MinecraftPacket
import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
public data class ClientboundCustomPayloadPacket(
val channel: Identifier,
val data: ByteArray,
-) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundCustomPayloadPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundCustomPayloadPacket {
val channel = buffer.readIdentifier()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomReportDetailsPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomReportDetailsPacket.kt
index a8b128b..1971836 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomReportDetailsPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundCustomReportDetailsPacket.kt
@@ -8,13 +8,11 @@
package cn.rtast.libmc.protocol.packet.configuration.clientbound
import cn.rtast.libmc.common.*
-import kotlinx.serialization.Serializable
public data class ClientboundCustomReportDetailsPacket(val details: List) :
ClientboundConfigurationPacket {
- @Serializable
public data class ReportDetail(val title: String, val description: String) {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ReportDetail) {
buffer.writeMcString(value.title)
buffer.writeMcString(value.description)
@@ -28,7 +26,7 @@ public data class ClientboundCustomReportDetailsPacket(val details: List {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundCustomReportDetailsPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundCustomReportDetailsPacket {
val detailCount = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundDisconnectConfigurationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundDisconnectConfigurationPacket.kt
index 3d4e5b4..66258c8 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundDisconnectConfigurationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundDisconnectConfigurationPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundDisconnectConfigurationPacket(val reason: NBTCompound) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectConfigurationPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundDisconnectConfigurationPacket {
return ClientboundDisconnectConfigurationPacket(reason = buffer.readNetworkNBTCompound())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundKeepAliveConfigurationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundKeepAliveConfigurationPacket.kt
index e98fd2c..98f98a4 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundKeepAliveConfigurationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundKeepAliveConfigurationPacket.kt
@@ -11,7 +11,7 @@ import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
public data class ClientboundKeepAliveConfigurationPacket(val id: Long) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundKeepAliveConfigurationPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundKeepAliveConfigurationPacket {
return ClientboundKeepAliveConfigurationPacket(buffer.readLong())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundPingConfigurationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundPingConfigurationPacket.kt
index 0acf98f..dbfb432 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundPingConfigurationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundPingConfigurationPacket.kt
@@ -11,7 +11,7 @@ import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
public data class ClientboundPingConfigurationPacket(val id: Int) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundPingConfigurationPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundPingConfigurationPacket {
return ClientboundPingConfigurationPacket(id = buffer.readInt())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.kt
index aa3f4ea..a6e22f7 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.kt
@@ -21,7 +21,7 @@ public data class ClientboundRegistryDataPacket(
val registryId: Identifier,
val entries: List,
) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundRegistryDataPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundRegistryDataPacket {
val id = buffer.readIdentifier()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRemoveResourcePackPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRemoveResourcePackPacket.kt
index 66abf2c..73a3879 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRemoveResourcePackPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundRemoveResourcePackPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.common.readUuid
import kotlin.uuid.Uuid
public data class ClientboundRemoveResourcePackPacket(val uuid: Uuid) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundRemoveResourcePackPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundRemoveResourcePackPacket {
val uuid = buffer.readUuid()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacksPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacksPacket.kt
index 59a682a..e7e3219 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacksPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacksPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
public data class ClientboundSelectKnownPacksPacket(val knownPacks: List) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundSelectKnownPacksPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundSelectKnownPacksPacket {
val packsCount = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundServerLinksPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundServerLinksPacket.kt
index bad6dcd..9c8d89a 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundServerLinksPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundServerLinksPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.protocol.registry.report.ServerLink
public data class ClientboundServerLinksPacket(val links: List) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundServerLinksPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundServerLinksPacket {
val count = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundStoreCookiePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundStoreCookiePacket.kt
index c8ca865..814558f 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundStoreCookiePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundStoreCookiePacket.kt
@@ -20,7 +20,7 @@ public data class ClientboundStoreCookiePacket(
*/
val payload: ByteArray,
) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundStoreCookiePacket) {}
override fun decode(buffer: BytesBuffer): ClientboundStoreCookiePacket {
val key = buffer.readIdentifier()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundTransferPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundTransferPacket.kt
index 2bd8015..bde3a52 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundTransferPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundTransferPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.common.readMcString
import cn.rtast.libmc.common.readVarInt
public data class ClientboundTransferPacket(val host: String, val port: Int) : ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundTransferPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundTransferPacket {
val host = buffer.readMcString()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateEnabledFeaturesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateEnabledFeaturesPacket.kt
index cc48207..16a4006 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateEnabledFeaturesPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateEnabledFeaturesPacket.kt
@@ -15,7 +15,7 @@ import cn.rtast.libmc.protocol.protocol.game.readIdentifier
public data class ClientboundUpdateEnabledFeaturesPacket(val features: List) :
ClientboundConfigurationPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundUpdateEnabledFeaturesPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundUpdateEnabledFeaturesPacket {
val featureCount = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateTagsPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateTagsPacket.kt
index e4b95e4..57ef2f4 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateTagsPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/clientbound/ClientboundUpdateTagsPacket.kt
@@ -14,12 +14,10 @@ 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
-import kotlinx.serialization.Serializable
public data class ClientboundUpdateTagsPacket(val registries: List) : ClientboundConfigurationPacket {
- @Serializable
public data class TaggedRegistry(val registryId: Identifier, val tags: List) {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: TaggedRegistry) {
buffer.writeIdentifier(value.registryId)
buffer.writeVarInt(value.tags.size)
@@ -36,9 +34,8 @@ public data class ClientboundUpdateTagsPacket(val registries: List {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: Tag) {
buffer.writeIdentifier(value.name)
buffer.writeVarInt(value.entries.size)
@@ -70,7 +67,7 @@ public data class ClientboundUpdateTagsPacket(val registries: List {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundUpdateTagsPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundUpdateTagsPacket {
val registryCount = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundCookieResponsePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundCookieResponsePacket.kt
index 09b3df0..0bc6c86 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundCookieResponsePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundCookieResponsePacket.kt
@@ -15,7 +15,7 @@ import cn.rtast.libmc.protocol.protocol.game.Identifier
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
public data class ServerboundCookieResponsePacket(val key: Identifier, val payload: ByteArray?) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundCookieResponsePacket) {
buffer.writeIdentifier(value.key)
if (value.payload != null) {
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundKeepAliveConfigurationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundKeepAliveConfigurationPacket.kt
index 0db9c94..82c1ded 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundKeepAliveConfigurationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundKeepAliveConfigurationPacket.kt
@@ -12,7 +12,7 @@ import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data class ServerboundKeepAliveConfigurationPacket(val id: Long) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundKeepAliveConfigurationPacket) {
buffer.writeLong(value.id)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundPongConfigurationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundPongConfigurationPacket.kt
index 98c9eef..18003a8 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundPongConfigurationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundPongConfigurationPacket.kt
@@ -12,7 +12,7 @@ import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
public data class ServerboundPongConfigurationPacket(val id: Int) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundPongConfigurationPacket) {
buffer.writeInt(value.id)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacksPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacksPacket.kt
index f88d32f..b5260fe 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacksPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacksPacket.kt
@@ -14,7 +14,7 @@ import cn.rtast.libmc.common.writeVarInt
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
public data class ServerboundSelectKnownPacksPacket(val knownPacks: List) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundSelectKnownPacksPacket) {
buffer.writeVarInt(value.knownPacks.size)
value.knownPacks.forEach { KnownPacks.encode(buffer, it) }
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/handshake/ServerboundHandshakePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/handshake/ServerboundHandshakePacket.kt
index a8b1832..9184ad0 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/handshake/ServerboundHandshakePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/handshake/ServerboundHandshakePacket.kt
@@ -20,7 +20,7 @@ public data class ServerboundHandshakePacket(
val serverPort: UShort,
val intent: HandshakeIntent,
) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundHandshakePacket) {
buffer.writeVarInt(value.protocolVersion)
buffer.writeMcString(value.serverAddress)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundCustomQueryPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundCustomQueryPacket.kt
index 70e40d3..2860b75 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundCustomQueryPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundCustomQueryPacket.kt
@@ -18,7 +18,7 @@ public data class ClientboundCustomQueryPacket(
val channel: Identifier,
val data: ByteArray,
) : ClientboundLoginPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundCustomQueryPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundCustomQueryPacket {
val messageId = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundDisconnectLoginPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundDisconnectLoginPacket.kt
index 57dcac7..0f6d01a 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundDisconnectLoginPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundDisconnectLoginPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundDisconnectLoginPacket(val reason: NBTCompound) : ClientboundLoginPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectLoginPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundDisconnectLoginPacket {
return ClientboundDisconnectLoginPacket(reason = buffer.readNetworkNBTCompound())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundHelloPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundHelloPacket.kt
index e24dfee..f3c37d6 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundHelloPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundHelloPacket.kt
@@ -25,7 +25,7 @@ public data class ClientboundHelloPacket(
*/
val shouldAuthenticate: Boolean,
) : ClientboundLoginPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundHelloPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundHelloPacket {
val serverId = buffer.readMcString()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundLoginSuccessPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundLoginSuccessPacket.kt
index d23e599..b7726ab 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundLoginSuccessPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundLoginSuccessPacket.kt
@@ -15,7 +15,7 @@ import kotlin.uuid.Uuid
public data class ClientboundLoginSuccessPacket(val gameProfile: GameProfile, val sessionId: Uuid) :
ClientboundLoginPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundLoginSuccessPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundLoginSuccessPacket {
val gameProfile = GameProfile.decode(buffer)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundSetCompressionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundSetCompressionPacket.kt
index 528b4fa..a8d7446 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundSetCompressionPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/clientbound/ClientboundSetCompressionPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.common.readVarInt
import cn.rtast.libmc.common.writeVarInt
public data class ClientboundSetCompressionPacket(val threshold: Int) : ClientboundLoginPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundSetCompressionPacket) {
buffer.writeVarInt(value.threshold)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundCustomQueryAnswerPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundCustomQueryAnswerPacket.kt
index a4ea2e4..e997e34 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundCustomQueryAnswerPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundCustomQueryAnswerPacket.kt
@@ -14,7 +14,7 @@ import cn.rtast.libmc.common.writeOptionalPrefixedByteArray
import cn.rtast.libmc.common.writeVarInt
public data class ServerboundCustomQueryAnswerPacket(val messageId: Int, val data: ByteArray?) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundCustomQueryAnswerPacket) {
buffer.writeVarInt(value.messageId)
buffer.writeOptionalPrefixedByteArray(value.data)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundKeyPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundKeyPacket.kt
index 76ea1bb..1a29ac4 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundKeyPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundKeyPacket.kt
@@ -16,7 +16,7 @@ import cn.rtast.libmc.common.writePrefixedByteArray
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Encryption
*/
public data class ServerboundKeyPacket(val sharedSecret: ByteArray, val verifyToken: ByteArray) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundKeyPacket) {
buffer.writePrefixedByteArray(value.sharedSecret)
buffer.writePrefixedByteArray(value.verifyToken)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundLoginStartPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundLoginStartPacket.kt
index f16b8a6..d1bc22c 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundLoginStartPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/login/serverbound/ServerboundLoginStartPacket.kt
@@ -15,7 +15,7 @@ import cn.rtast.libmc.common.writeUuid
import kotlin.uuid.Uuid
public data class ServerboundLoginStartPacket(val username: String, val playerUuid: Uuid) : MinecraftPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundLoginStartPacket) {
buffer.writeMcString(value.username)
buffer.writeUuid(value.playerUuid)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAcknowledgeBlockChangePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAcknowledgeBlockChangePacket.kt
index 10ae3a6..352eeed 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAcknowledgeBlockChangePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAcknowledgeBlockChangePacket.kt
@@ -15,7 +15,7 @@ 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 {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundAcknowledgeBlockChangePacket) {}
override fun decode(buffer: BytesBuffer): ClientboundAcknowledgeBlockChangePacket {
return ClientboundAcknowledgeBlockChangePacket(buffer.readVarInt())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAwardStatisticsPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAwardStatisticsPacket.kt
index ebcfc7b..326a02e 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAwardStatisticsPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundAwardStatisticsPacket.kt
@@ -16,7 +16,7 @@ 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) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundAwardStatisticsPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundAwardStatisticsPacket {
val count = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockDestructionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockDestructionPacket.kt
index 4225ab3..2afdeda 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockDestructionPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockDestructionPacket.kt
@@ -22,7 +22,7 @@ public data class ClientboundBlockDestructionPacket(
val location: BlockPos,
val stage: BlockDestroyStage,
) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundBlockDestructionPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundBlockDestructionPacket {
val entityId = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEntityDataPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEntityDataPacket.kt
index 3989d5c..ddc043f 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEntityDataPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEntityDataPacket.kt
@@ -17,7 +17,7 @@ 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 {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundBlockEntityDataPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundBlockEntityDataPacket {
val location = buffer.readBlockPos()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEventPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEventPacket.kt
new file mode 100644
index 0000000..d56cae0
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockEventPacket.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.BlockPos
+import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
+
+public data class ClientboundBlockEventPacket(
+ val location: BlockPos,
+ /**
+ * ref: https://minecraft.wiki/w/Java_Edition_protocol/Block_actions
+ */
+ val actionId: UByte,
+ /**
+ * ref: https://minecraft.wiki/w/Java_Edition_protocol/Block_actions
+ */
+ val actionParameter: UByte,
+ /**
+ * ID in the minecraft:block registry.
+ * This value is unused by the vanilla client,
+ * as it will infer the type of block based on the given position.
+ */
+ val blockType: Int,
+) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundBlockEventPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundBlockEventPacket {
+ val location = buffer.readBlockPos()
+ val actionId = buffer.readUByte()
+ val actionParameter = buffer.readUByte()
+ val blockType = buffer.readVarInt()
+ return ClientboundBlockEventPacket(location, actionId, actionParameter, blockType)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockUpdatePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockUpdatePacket.kt
new file mode 100644
index 0000000..25b367b
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBlockUpdatePacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.BlockPos
+import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
+
+public data class ClientboundBlockUpdatePacket(val location: BlockPos, val blockId: Int) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundBlockUpdatePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundBlockUpdatePacket {
+ val position = buffer.readBlockPos()
+ val blockId = buffer.readVarInt()
+ return ClientboundBlockUpdatePacket(position, blockId)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBossEventPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBossEventPacket.kt
new file mode 100644
index 0000000..dda8419
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundBossEventPacket.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.protocol.game.bossbar.BossBarAction
+import cn.rtast.libmc.protocol.protocol.game.bossbar.BossBarColor
+import cn.rtast.libmc.protocol.protocol.game.bossbar.BossBarDivision
+import cn.rtast.libmc.protocol.protocol.game.bossbar.BossBarFlags
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+import kotlin.uuid.Uuid
+
+public data class ClientboundBossEventPacket(val uuid: Uuid, val action: BossBarAction) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundBossEventPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundBossEventPacket {
+ val uuid = buffer.readUuid()
+ val action = when (val actionId = buffer.readVarInt()) {
+ BossBarAction.ADD_ID -> {
+ val title = buffer.readNetworkNBTCompound()
+ val health = buffer.readFloat()
+ val color = BossBarColor.fromID(buffer.readVarInt())
+ val division = BossBarDivision.fromID(buffer.readVarInt())
+ val flags = BossBarFlags.fromBitmask(buffer.readByte().toInt() and 0xFF)
+ BossBarAction.Add(title, health, color, division, flags)
+ }
+
+ BossBarAction.REMOVE_ID -> BossBarAction.Remove
+ BossBarAction.UPDATE_TITLE_ID -> BossBarAction.UpdateTitle(buffer.readNetworkNBTCompound())
+ BossBarAction.UPDATE_STYLE_ID -> {
+ val color = BossBarColor.fromID(buffer.readVarInt())
+ val division = BossBarDivision.fromID(buffer.readVarInt())
+ BossBarAction.UpdateStyle(color, division)
+ }
+
+ BossBarAction.UPDATE_FLAGS_ID -> {
+ BossBarAction.UpdateFlags(BossBarFlags.fromBitmask(buffer.readByte().toInt() and 0xFF))
+ }
+
+ else -> throw IllegalArgumentException("Unknown action $actionId")
+ }
+ return ClientboundBossEventPacket(uuid, action)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChangeDifficultyPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChangeDifficultyPacket.kt
new file mode 100644
index 0000000..10741bd
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChangeDifficultyPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.BytesBuffer
+import cn.rtast.libmc.common.PacketCodec
+import cn.rtast.libmc.protocol.registry.GameDifficulty
+
+public data class ClientboundChangeDifficultyPacket(val difficulty: GameDifficulty, val locked: Boolean) :
+ ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundChangeDifficultyPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundChangeDifficultyPacket {
+ val difficulty = GameDifficulty.fromID(buffer.readByte())
+ val locked = buffer.readBoolean()
+ return ClientboundChangeDifficultyPacket(difficulty, locked)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunkBatchFinishedPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunkBatchFinishedPacket.kt
new file mode 100644
index 0000000..19d70d8
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunkBatchFinishedPacket.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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
+
+public data class ClientboundChunkBatchFinishedPacket(val batchSize: Int) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundChunkBatchFinishedPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundChunkBatchFinishedPacket {
+ return ClientboundChunkBatchFinishedPacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunkBatchStartPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunkBatchStartPacket.kt
new file mode 100644
index 0000000..1cba188
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunkBatchStartPacket.kt
@@ -0,0 +1,17 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.BytesBuffer
+import cn.rtast.libmc.common.PacketCodec
+
+public data object ClientboundChunkBatchStartPacket : ClientboundPlayPacket,
+ PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundChunkBatchStartPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundChunkBatchStartPacket = ClientboundChunkBatchStartPacket
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunksBiomesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunksBiomesPacket.kt
new file mode 100644
index 0000000..a1bda64
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundChunksBiomesPacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.chunk.ChunkBiomeData
+
+public data class ClientboundChunksBiomesPacket(val chunkBiomes: List) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundChunksBiomesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundChunksBiomesPacket {
+ val chunkCount = buffer.readVarInt()
+ val chunks = ArrayList(chunkCount)
+ repeat(chunkCount) { chunks.add(ChunkBiomeData.decode(buffer)) }
+ return ClientboundChunksBiomesPacket(chunks)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundClearTitlesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundClearTitlesPacket.kt
new file mode 100644
index 0000000..4e28469
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundClearTitlesPacket.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.BytesBuffer
+import cn.rtast.libmc.common.PacketCodec
+
+public data class ClientboundClearTitlesPacket(val reset: Boolean) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundClearTitlesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundClearTitlesPacket {
+ return ClientboundClearTitlesPacket(buffer.readBoolean())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCommandSuggestionsPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCommandSuggestionsPacket.kt
new file mode 100644
index 0000000..52cf41a
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCommandSuggestionsPacket.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+import cn.rtast.libmc.protocol.protocol.util.writeNetworkNBTCompound
+
+public data class ClientboundCommandSuggestionsPacket(
+ val id: Int,
+ val start: Int,
+ val length: Int,
+ val matches: List,
+) : ClientboundPlayPacket {
+ public data class CommandSuggestionMatch(val match: String, val tooltip: NBTCompound?) {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: CommandSuggestionMatch) {
+ buffer.writeMcString(value.match)
+ buffer.writeBoolean(value.tooltip != null)
+ if (value.tooltip != null) buffer.writeNetworkNBTCompound(value.tooltip)
+ }
+
+ override fun decode(buffer: BytesBuffer): CommandSuggestionMatch {
+ val match = buffer.readMcString()
+ val hasTooltip = buffer.readBoolean()
+ val tooltip = if (hasTooltip) buffer.readNetworkNBTCompound() else null
+ return CommandSuggestionMatch(match, tooltip)
+ }
+ }
+ }
+
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundCommandSuggestionsPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundCommandSuggestionsPacket {
+ val id = buffer.readVarInt()
+ val start = buffer.readVarInt()
+ val length = buffer.readVarInt()
+ val matchCount = buffer.readVarInt()
+ val matches = ArrayList(matchCount)
+ repeat(matchCount) { matches.add(CommandSuggestionMatch.decode(buffer)) }
+ return ClientboundCommandSuggestionsPacket(id, start, length, matches)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerClosePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerClosePacket.kt
new file mode 100644
index 0000000..b3ca798
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerClosePacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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#Close_Container
+ * This is the ID of the window that was closed. 0 for inventory.
+ */
+public data class ClientboundContainerClosePacket(val windowId: Int) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundContainerClosePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundContainerClosePacket {
+ return ClientboundContainerClosePacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetContentPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetContentPacket.kt
new file mode 100644
index 0000000..da96989
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetContentPacket.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.inventory.Slot
+import cn.rtast.libmc.protocol.protocol.game.inventory.readSlot
+
+public data class ClientboundContainerSetContentPacket(
+ val windowId: Int,
+ /**
+ * A server-managed sequence number used to avoid desynchronization
+ * see https://minecraft.wiki/w/Java_Edition_protocol/Packets#Click_Container
+ */
+ val stateId: Int,
+ val slotData: List,
+ val carriedItem: Slot,
+) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundContainerSetContentPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundContainerSetContentPacket {
+ val windowId = buffer.readVarInt()
+ val stateId = buffer.readVarInt()
+ val slotDataCount = buffer.readVarInt()
+ val slotData = ArrayList(slotDataCount)
+ repeat(slotDataCount) { slotData.add(buffer.readSlot()) }
+ val carriedItem = buffer.readSlot()
+ return ClientboundContainerSetContentPacket(windowId, stateId, slotData, carriedItem)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetDataPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetDataPacket.kt
new file mode 100644
index 0000000..f68104f
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetDataPacket.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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#Set_Container_Property
+ */
+public data class ClientboundContainerSetDataPacket(
+ val windowId: Int,
+ val property: Short,
+ val value: Short,
+) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundContainerSetDataPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundContainerSetDataPacket {
+ val windowId = buffer.readVarInt()
+ val property = buffer.readShort()
+ val value = buffer.readShort()
+ return ClientboundContainerSetDataPacket(windowId, property, value)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetSlotPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetSlotPacket.kt
new file mode 100644
index 0000000..6fff33d
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundContainerSetSlotPacket.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.inventory.Slot
+import cn.rtast.libmc.protocol.protocol.game.inventory.readSlot
+
+public data class ClientboundContainerSetSlotPacket(
+ val windowId: Int,
+ val stateId: Int,
+ val slot: Short,
+ val slotData: Slot,
+) : ClientboundPlayPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundContainerSetSlotPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundContainerSetSlotPacket {
+ val windowId = buffer.readVarInt()
+ val stateId = buffer.readVarInt()
+ val slot = buffer.readShort()
+ val slotData = buffer.readSlot()
+ return ClientboundContainerSetSlotPacket(windowId, stateId, slot, slotData)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCooldownPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCooldownPacket.kt
new file mode 100644
index 0000000..35dc209
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCooldownPacket.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.Identifier
+import cn.rtast.libmc.protocol.protocol.game.readIdentifier
+
+public data class ClientboundCooldownPacket(
+ val group: Identifier,
+ /**
+ * 0 to clear the cooldown.
+ */
+ val ticks: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundCooldownPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundCooldownPacket {
+ val group = buffer.readIdentifier()
+ val ticks = buffer.readVarInt()
+ return ClientboundCooldownPacket(group, ticks)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCustomChatCompletionsPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCustomChatCompletionsPacket.kt
new file mode 100644
index 0000000..6745e73
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundCustomChatCompletionsPacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readPrefixedStringArray
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.chat.ChatAction
+
+public data class ClientboundCustomChatCompletionsPacket(val action: ChatAction, val entries: List) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundCustomChatCompletionsPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundCustomChatCompletionsPacket {
+ val action = ChatAction.fromID(buffer.readVarInt())
+ val entries = buffer.readPrefixedStringArray()
+ return ClientboundCustomChatCompletionsPacket(action, entries)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDamageEventPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDamageEventPacket.kt
new file mode 100644
index 0000000..1d4986e
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDamageEventPacket.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Vec3d
+import cn.rtast.libmc.protocol.protocol.game.math.readVec3d
+
+public data class ClientboundDamageEventPacket(
+ val entityId: Int,
+ val sourceTypeId: Int,
+ val sourceCauseId: Int?,
+ val sourceDirectId: Int?,
+ val position: Vec3d?,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundDamageEventPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundDamageEventPacket {
+ val entityId = buffer.readVarInt()
+ val sourceTypeId = buffer.readVarInt()
+ val rawCauseId = buffer.readVarInt()
+ val sourceCauseId = if (rawCauseId > 0) rawCauseId - 1 else null
+ val rawDirectId = buffer.readVarInt()
+ val sourceDirectId = if (rawDirectId > 0) rawDirectId - 1 else null
+ val position = buffer.readVec3d(true)
+ return ClientboundDamageEventPacket(entityId, sourceTypeId, sourceCauseId, sourceDirectId, position)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDeleteChatPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDeleteChatPacket.kt
new file mode 100644
index 0000000..a1d8506
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDeleteChatPacket.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readOptional
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundDeleteChatPacket(val messageId: Int, val signature: ByteArray?) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundDeleteChatPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundDeleteChatPacket {
+ val messageId = buffer.readVarInt()
+ val signature = buffer.readOptional { buffer.readBytes(256) }
+ return ClientboundDeleteChatPacket(messageId, signature)
+ }
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+
+ other as ClientboundDeleteChatPacket
+
+ if (messageId != other.messageId) return false
+ if (!signature.contentEquals(other.signature)) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = messageId
+ result = 31 * result + (signature?.contentHashCode() ?: 0)
+ return result
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisconnectPlayPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisconnectPlayPacket.kt
index fe59f32..3117bac 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisconnectPlayPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisconnectPlayPacket.kt
@@ -13,7 +13,7 @@ import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundDisconnectPlayPacket(val reason: NBTCompound) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectPlayPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundDisconnectPlayPacket {
return ClientboundDisconnectPlayPacket(reason = buffer.readNetworkNBTCompound())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisguisedChatMessagePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisguisedChatMessagePacket.kt
new file mode 100644
index 0000000..cd08884
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundDisguisedChatMessagePacket.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.common.packet.MinecraftPacket
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.game.chat.InlineChatType
+import cn.rtast.libmc.protocol.protocol.game.chat.readInlineChatType
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundDisguisedChatMessagePacket(
+ val message: NBTCompound,
+ val chatType: IdOrX,
+ val senderName: NBTCompound,
+ val targetName: NBTCompound?,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundDisguisedChatMessagePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundDisguisedChatMessagePacket {
+ val message = buffer.readNetworkNBTCompound()
+ val chatType = buffer.readIdOrX { readInlineChatType() }
+ val senderName = buffer.readNetworkNBTCompound()
+ val targetName = buffer.readOptional { readNetworkNBTCompound() }
+ return ClientboundDisguisedChatMessagePacket(message, chatType, senderName, targetName)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityAnimationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityAnimationPacket.kt
index ce18765..1ef3e20 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityAnimationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityAnimationPacket.kt
@@ -17,7 +17,7 @@ import cn.rtast.libmc.protocol.protocol.game.Animations
*/
public data class ClientboundEntityAnimationPacket(val entityId: Int, val animation: Animations) :
ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundEntityAnimationPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundEntityAnimationPacket {
val entityId = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityEffectPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityEffectPacket.kt
new file mode 100644
index 0000000..1208035
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityEffectPacket.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.effect.EntityEffectFlags
+import cn.rtast.libmc.protocol.tick.ticks
+import kotlin.time.Duration
+
+public data class ClientboundEntityEffectPacket(
+ val entityId: Int,
+ val effectId: Int,
+ val amplifier: Int,
+ val durationTicks: Int,
+ val flags: EntityEffectFlags,
+) : MinecraftPacket {
+ public val duration: Duration get() = if (durationTicks == -1) Duration.INFINITE else durationTicks.ticks
+
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundEntityEffectPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundEntityEffectPacket {
+ val entityId = buffer.readVarInt()
+ val effectId = buffer.readVarInt()
+ val amplifier = buffer.readVarInt()
+ val durationTicks = buffer.readVarInt()
+ val flags = EntityEffectFlags.fromByte(buffer.readByte())
+ return ClientboundEntityEffectPacket(entityId, effectId, amplifier, durationTicks, flags)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityEventPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityEventPacket.kt
new file mode 100644
index 0000000..2cb1220
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntityEventPacket.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundEntityEventPacket(
+ val entityId: Int,
+ /**
+ * to get status id,
+ * see https://minecraft.wiki/w/Java_Edition_protocol/Entity_statuses#Entity_statuses
+ */
+ val status: Byte,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundEntityEventPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundEntityEventPacket {
+ val entityId = buffer.readInt()
+ val status = buffer.readByte()
+ return ClientboundEntityEventPacket(entityId, status)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntitySoundEffectPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntitySoundEffectPacket.kt
new file mode 100644
index 0000000..a3c1066
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundEntitySoundEffectPacket.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.common.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.sound.SoundCategory
+import cn.rtast.libmc.protocol.protocol.game.sound.SoundEvent
+import cn.rtast.libmc.protocol.protocol.game.sound.readSoundEvent
+
+public data class ClientboundEntitySoundEffectPacket(
+ val soundEvent: IdOrX,
+ val category: SoundCategory,
+ val entityId: Int,
+ val volume: Float,
+ val pitch: Float,
+ val seed: Long,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundEntitySoundEffectPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundEntitySoundEffectPacket {
+ val soundEvent = buffer.readIdOrX { readSoundEvent() }
+ val category = SoundCategory.fromID(buffer.readVarInt())
+ val entityId = buffer.readVarInt()
+ val volume = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ val seed = buffer.readLong()
+ return ClientboundEntitySoundEffectPacket(soundEvent, category, entityId, volume, pitch, seed)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundGameEventPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundGameEventPacket.kt
new file mode 100644
index 0000000..dec0414
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundGameEventPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+/**
+ * ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Game_Event
+ */
+public data class ClientboundGameEventPacket(val event: UByte, val value: Float) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundGameEventPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundGameEventPacket {
+ val event = buffer.readUByte()
+ val value = buffer.readFloat()
+ return ClientboundGameEventPacket(event, value)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundGameRuleValuesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundGameRuleValuesPacket.kt
new file mode 100644
index 0000000..1056506
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundGameRuleValuesPacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.gamerule.GameRuleEntry
+import cn.rtast.libmc.protocol.protocol.game.gamerule.readGameRule
+
+public data class ClientboundGameRuleValuesPacket(val rules: List) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundGameRuleValuesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundGameRuleValuesPacket {
+ val count = buffer.readVarInt()
+ val rules = ArrayList(count)
+ repeat(count) { rules.add(buffer.readGameRule()) }
+ return ClientboundGameRuleValuesPacket(rules)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundHurtAnimationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundHurtAnimationPacket.kt
new file mode 100644
index 0000000..a404138
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundHurtAnimationPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundHurtAnimationPacket(val entityId: Int, val yaw: Float) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundHurtAnimationPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundHurtAnimationPacket {
+ val entityId = buffer.readVarInt()
+ val yaw = buffer.readFloat()
+ return ClientboundHurtAnimationPacket(entityId, yaw)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundInitializeWorldBorderPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundInitializeWorldBorderPacket.kt
new file mode 100644
index 0000000..b8ac567
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundInitializeWorldBorderPacket.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.common.readVarLong
+
+public data class ClientboundInitializeWorldBorderPacket(
+ val centerX: Double,
+ val centerZ: Double,
+ val oldDiameter: Double,
+ val newDiameter: Double,
+ val speed: Long,
+ val portalTeleportBoundary: Int,
+ val warningBlocks: Int,
+ val warningTime: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundInitializeWorldBorderPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundInitializeWorldBorderPacket {
+ val centerX = buffer.readDouble()
+ val centerZ = buffer.readDouble()
+ val oldDiameter = buffer.readDouble()
+ val newDiameter = buffer.readDouble()
+ val speed = buffer.readVarLong()
+ val portalTeleportBoundary = buffer.readVarInt()
+ val warningBlocks = buffer.readVarInt()
+ val warningTime = buffer.readVarInt()
+ return ClientboundInitializeWorldBorderPacket(
+ centerX, centerZ, oldDiameter,
+ newDiameter, speed,
+ portalTeleportBoundary,
+ warningBlocks, warningTime
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundKeepAlivePlayPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundKeepAlivePlayPacket.kt
index 41472b6..5ae83f5 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundKeepAlivePlayPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundKeepAlivePlayPacket.kt
@@ -11,11 +11,8 @@ import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
public data class ClientboundKeepAlivePlayPacket(val id: Long) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
- override fun encode(buffer: BytesBuffer, value: ClientboundKeepAlivePlayPacket) {
- buffer.writeLong(value.id)
- }
-
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundKeepAlivePlayPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundKeepAlivePlayPacket =
ClientboundKeepAlivePlayPacket(buffer.readLong())
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLevelEventPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLevelEventPacket.kt
new file mode 100644
index 0000000..c286a80
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLevelEventPacket.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
+import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
+
+public data class ClientboundLevelEventPacket(
+ /**
+ * see https://minecraft.wiki/w/Java_Edition_protocol/Packets#World_Event
+ */
+ val eventId: Int,
+ val location: BlockPos,
+ val data: Int,
+ val disableRelativeVolume: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundLevelEventPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundLevelEventPacket {
+ val eventId = buffer.readInt()
+ val location = buffer.readBlockPos()
+ val data = buffer.readInt()
+ val disableRelativeVolume = buffer.readBoolean()
+ return ClientboundLevelEventPacket(eventId, location, data, disableRelativeVolume)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLinkEntitiesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLinkEntitiesPacket.kt
new file mode 100644
index 0000000..7d37bc2
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLinkEntitiesPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundLinkEntitiesPacket(val attachedEntityId: Int, val holdingEntityId: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundLinkEntitiesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundLinkEntitiesPacket {
+ val attachedEntityId = buffer.readInt()
+ val holdingEntityId = buffer.readInt()
+ return ClientboundLinkEntitiesPacket(attachedEntityId, holdingEntityId)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLoginPlayPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLoginPlayPacket.kt
index bacff8c..c5cb33f 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLoginPlayPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLoginPlayPacket.kt
@@ -41,7 +41,7 @@ public data class ClientboundLoginPlayPacket(
val isOnlineMode: Boolean,
val enforceSecureChat: Boolean,
) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundLoginPlayPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundLoginPlayPacket {
val entityId = buffer.readInt()
@@ -57,7 +57,7 @@ public data class ClientboundLoginPlayPacket(
val dimensionType = buffer.readVarInt()
val dimensionName = buffer.readIdentifier()
val hashedSeed = buffer.readLong()
- val gameMode = GameMode.fromID(buffer.readByte().toUByte())
+ val gameMode = GameMode.fromID(buffer.readUByte())
val previousGameMode = GameMode.fromID(buffer.readByte())
val isDebug = buffer.readBoolean()
val isFlat = buffer.readBoolean()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLowDiskSpaceWarningPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLowDiskSpaceWarningPacket.kt
new file mode 100644
index 0000000..fc29ede
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundLowDiskSpaceWarningPacket.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data object ClientboundLowDiskSpaceWarningPacket : MinecraftPacket,
+ PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundLowDiskSpaceWarningPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundLowDiskSpaceWarningPacket =
+ ClientboundLowDiskSpaceWarningPacket
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundMoveMinecartAlongTrackPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundMoveMinecartAlongTrackPacket.kt
new file mode 100644
index 0000000..f8d2fe5
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundMoveMinecartAlongTrackPacket.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.entity.MinecartStep
+import cn.rtast.libmc.protocol.protocol.game.entity.readMinecartStep
+
+public data class ClientboundMoveMinecartAlongTrackPacket(val entityId: Int, val steps: List) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundMoveMinecartAlongTrackPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundMoveMinecartAlongTrackPacket {
+ val entityId = buffer.readVarInt()
+ val stepCount = buffer.readVarInt()
+ val steps = ArrayList()
+ repeat(stepCount) { steps.add(buffer.readMinecartStep()) }
+ return ClientboundMoveMinecartAlongTrackPacket(entityId, steps)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundMoveVehiclePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundMoveVehiclePacket.kt
new file mode 100644
index 0000000..82931d3
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundMoveVehiclePacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.math.Vec3d
+import cn.rtast.libmc.protocol.protocol.game.math.readVec3d
+
+public data class ClientboundMoveVehiclePacket(val position: Vec3d, val yaw: Float, val pitch: Float) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundMoveVehiclePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundMoveVehiclePacket {
+ val position = buffer.readVec3d()!!
+ val yaw = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ return ClientboundMoveVehiclePacket(position, yaw, pitch)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenBookPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenBookPacket.kt
new file mode 100644
index 0000000..0968d5b
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenBookPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.player.Hand
+
+public data class ClientboundOpenBookPacket(val hand: Hand) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundOpenBookPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundOpenBookPacket {
+ return ClientboundOpenBookPacket(Hand.fromID(buffer.readVarInt()))
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenHorseScreenPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenHorseScreenPacket.kt
new file mode 100644
index 0000000..5803901
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenHorseScreenPacket.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundOpenHorseScreenPacket(
+ val windowId: Int,
+ val columnsCount: Int,
+ val entityId: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundOpenHorseScreenPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundOpenHorseScreenPacket {
+ val windowId = buffer.readVarInt()
+ val columnsCount = buffer.readVarInt()
+ val entityId = buffer.readInt()
+ return ClientboundOpenHorseScreenPacket(windowId, columnsCount, entityId)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenScreenPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenScreenPacket.kt
new file mode 100644
index 0000000..6648140
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenScreenPacket.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundOpenScreenPacket(
+ val windowId: Int,
+ val windowType: Int,
+ val title: NBTCompound,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundOpenScreenPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundOpenScreenPacket {
+ val windowId = buffer.readVarInt()
+ val windowType = buffer.readVarInt()
+ val title = buffer.readNetworkNBTCompound()
+ return ClientboundOpenScreenPacket(windowId, windowType, title)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenSignEditorPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenSignEditorPacket.kt
new file mode 100644
index 0000000..4326d04
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundOpenSignEditorPacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
+import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
+
+public data class ClientboundOpenSignEditorPacket(val location: BlockPos, val isFrontText: Boolean) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundOpenSignEditorPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundOpenSignEditorPacket {
+ val location = buffer.readBlockPos()
+ val isFrontText = buffer.readBoolean()
+ return ClientboundOpenSignEditorPacket(location, isFrontText)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPickupItemPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPickupItemPacket.kt
new file mode 100644
index 0000000..22a2dee
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPickupItemPacket.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundPickupItemPacket(
+ val collectedEntityId: Int,
+ val collectorEntityId: Int,
+ /**
+ * Seems to be 1 for XP orbs, otherwise the number of items in the stack.
+ */
+ val itemCount: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPickupItemPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPickupItemPacket {
+ val collectedEntityId = buffer.readVarInt()
+ val collectorEntityId = buffer.readVarInt()
+ val itemCount = buffer.readVarInt()
+ return ClientboundPickupItemPacket(collectedEntityId, collectorEntityId, itemCount)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPingPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPingPacket.kt
index e9b31e8..5f319ba 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPingPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPingPacket.kt
@@ -11,7 +11,7 @@ import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
public data class ClientboundPingPacket(val id: Int) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundPingPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundPingPacket {
return ClientboundPingPacket(id = buffer.readInt())
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayPacket.kt
index 9f2fb1b..9ea4a27 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayPacket.kt
@@ -9,4 +9,7 @@ package cn.rtast.libmc.protocol.packet.play.clientbound
import cn.rtast.libmc.common.packet.MinecraftPacket
+/**
+ * mark a packet that is used when join to the server
+ */
public sealed interface ClientboundPlayPacket : MinecraftPacket
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerAbilitiesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerAbilitiesPacket.kt
new file mode 100644
index 0000000..355f317
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerAbilitiesPacket.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.player.PlayerAbilities
+
+public data class ClientboundPlayerAbilitiesPacket(
+ val flags: PlayerAbilities,
+ val flyingSpeed: Float,
+ val fovModifier: Float,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerAbilitiesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerAbilitiesPacket {
+ val flag = PlayerAbilities.fromByte(buffer.readByte())
+ val flyingSpeed = buffer.readFloat()
+ val fovModifier = buffer.readFloat()
+ return ClientboundPlayerAbilitiesPacket(flag, flyingSpeed, fovModifier)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerChatMessagePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerChatMessagePacket.kt
index 3281278..201e2e1 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerChatMessagePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerChatMessagePacket.kt
@@ -36,14 +36,14 @@ public data class ClientboundPlayerChatMessagePacket(
FULLY_FILTERED(1),
PARTIALLY_FILTERED(2);
- public companion object {
- public fun fromId(id: Int): ChatFilterType =
+ internal companion object {
+ fun fromID(id: Int): ChatFilterType =
entries.firstOrNull { it.id == id } ?: PASS_THROUGH
}
}
public data class PreviousMessageEntry(val messageId: Int, val signature: ByteArray?) {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: PreviousMessageEntry) {}
override fun decode(buffer: BytesBuffer): PreviousMessageEntry {
val messageId = buffer.readVarInt()
@@ -68,7 +68,7 @@ public data class ClientboundPlayerChatMessagePacket(
}
}
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundPlayerChatMessagePacket) {}
override fun decode(buffer: BytesBuffer): ClientboundPlayerChatMessagePacket {
val globalIndex = buffer.readVarInt()
@@ -88,7 +88,7 @@ public data class ClientboundPlayerChatMessagePacket(
val unsignedContent = if (hasUnsignedContent) buffer.readNetworkNBTCompound() else null // ?
val filterTypeId = buffer.readVarInt()
- val filterType = ChatFilterType.fromId(filterTypeId)
+ val filterType = ChatFilterType.fromID(filterTypeId)
val filterMaskBits = if (filterType == ChatFilterType.PARTIALLY_FILTERED) {
val bitSetLen = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerCombatDeathPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerCombatDeathPacket.kt
new file mode 100644
index 0000000..fa25b03
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerCombatDeathPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundPlayerCombatDeathPacket(val playerId: Int, val message: NBTCompound) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerCombatDeathPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerCombatDeathPacket {
+ val playerId = buffer.readVarInt()
+ val message = buffer.readNetworkNBTCompound()
+ return ClientboundPlayerCombatDeathPacket(playerId, message)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerEndCombatPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerEndCombatPacket.kt
new file mode 100644
index 0000000..90d16a7
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerEndCombatPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.tick.ticks
+import kotlin.time.Duration
+
+public data class ClientboundPlayerEndCombatPacket(val duration: Duration) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerEndCombatPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerEndCombatPacket {
+ return ClientboundPlayerEndCombatPacket(buffer.readVarInt().ticks) // convert int to minecraft ticks
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerEnterCombatPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerEnterCombatPacket.kt
new file mode 100644
index 0000000..8f67251
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerEnterCombatPacket.kt
@@ -0,0 +1,18 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data object ClientboundPlayerEnterCombatPacket : MinecraftPacket,
+ PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerEnterCombatPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerEnterCombatPacket = ClientboundPlayerEnterCombatPacket
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerInfoRemovePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerInfoRemovePacket.kt
new file mode 100644
index 0000000..7feb188
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerInfoRemovePacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readPrefixed
+import cn.rtast.libmc.common.readUuid
+import kotlin.uuid.Uuid
+
+public data class ClientboundPlayerInfoRemovePacket(val uuids: List) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerInfoRemovePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerInfoRemovePacket {
+ return ClientboundPlayerInfoRemovePacket(buffer.readPrefixed { readUuid() })
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerLookAtPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerLookAtPacket.kt
new file mode 100644
index 0000000..ce85831
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerLookAtPacket.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Vec3d
+import cn.rtast.libmc.protocol.protocol.game.math.readVec3d
+import cn.rtast.libmc.protocol.protocol.game.player.AnchorPoint
+
+public data class ClientboundPlayerLookAtPacket(
+ val fromAnchor: AnchorPoint,
+ val targetPosition: Vec3d,
+ val entityTarget: EntityLookAtTarget?,
+) : MinecraftPacket {
+ public data class EntityLookAtTarget(
+ val entityId: Int,
+ val entityAnchor: AnchorPoint,
+ )
+
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerLookAtPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerLookAtPacket {
+ val fromAnchor = AnchorPoint.fromID(buffer.readVarInt())
+ val targetPosition = buffer.readVec3d()!!
+ val isEntity = buffer.readBoolean()
+ val entityTarget = if (isEntity) {
+ val entityId = buffer.readVarInt()
+ val entityAnchor = AnchorPoint.fromID(buffer.readVarInt())
+ EntityLookAtTarget(entityId, entityAnchor)
+ } else null
+ return ClientboundPlayerLookAtPacket(
+ fromAnchor = fromAnchor,
+ targetPosition = targetPosition,
+ entityTarget = entityTarget
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerRotationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerRotationPacket.kt
new file mode 100644
index 0000000..f3c3f1b
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerRotationPacket.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundPlayerRotationPacket(
+ val yaw: Float,
+ val relativeYaw: Boolean,
+ val pitch: Float,
+ val relativePitch: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundPlayerRotationPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundPlayerRotationPacket {
+ val yaw = buffer.readFloat()
+ val relativeYaw = buffer.readBoolean()
+ val pitch = buffer.readFloat()
+ val relativePitch = buffer.readBoolean()
+ return ClientboundPlayerRotationPacket(yaw, relativeYaw, pitch, relativePitch)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundProjectilePowerPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundProjectilePowerPacket.kt
new file mode 100644
index 0000000..a39e6e7
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundProjectilePowerPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundProjectilePowerPacket(val entityId: Int, val power: Double) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundProjectilePowerPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundProjectilePowerPacket {
+ val entityId = buffer.readVarInt()
+ val power = buffer.readDouble()
+ return ClientboundProjectilePowerPacket(entityId, power)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRemoveEntitiesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRemoveEntitiesPacket.kt
new file mode 100644
index 0000000..3b8023b
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRemoveEntitiesPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readPrefixed
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundRemoveEntitiesPacket(val entityIds: List): MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundRemoveEntitiesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundRemoveEntitiesPacket {
+ return ClientboundRemoveEntitiesPacket(buffer.readPrefixed { readVarInt() })
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRemoveEntityEffectPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRemoveEntityEffectPacket.kt
new file mode 100644
index 0000000..4f22d36
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRemoveEntityEffectPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundRemoveEntityEffectPacket(val entityId: Int, val effectId: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundRemoveEntityEffectPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundRemoveEntityEffectPacket {
+ val entityId = buffer.readVarInt()
+ val effectId = buffer.readVarInt()
+ return ClientboundRemoveEntityEffectPacket(entityId, effectId)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundResetScorePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundResetScorePacket.kt
new file mode 100644
index 0000000..2ffbdab
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundResetScorePacket.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.common.packet.MinecraftPacket
+
+public data class ClientboundResetScorePacket(val entityName: String, val objectiveName: String?) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundResetScorePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundResetScorePacket {
+ val entityName = buffer.readMcString()
+ val objectiveName = buffer.readPrefixed { readOptional { readMcString() } }.first() // ?
+ return ClientboundResetScorePacket(entityName, objectiveName)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRespawnPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRespawnPacket.kt
new file mode 100644
index 0000000..ba0a395
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundRespawnPacket.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readOptional
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.GameMode
+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.readBlockPos
+import cn.rtast.libmc.protocol.protocol.game.readIdentifier
+import cn.rtast.libmc.protocol.protocol.game.world.RespawnDataToKeep
+
+public data class ClientboundRespawnPacket(
+ val dimensionType: Int,
+ val dimensionName: Identifier,
+ val hashedSeed: Long,
+ val gameMode: GameMode,
+ val previousGameMode: GameMode,
+ val isDebug: Boolean,
+ val isFlat: Boolean,
+ val hasDeathLocation: Boolean,
+ val deathDimensionName: Identifier?,
+ val deathLocation: BlockPos?,
+ val portalCooldown: Int,
+ val seaLevel: Int,
+ val dataKept: RespawnDataToKeep,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundRespawnPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundRespawnPacket {
+ val dimensionType = buffer.readVarInt()
+ val dimensionName = buffer.readIdentifier()
+ val hashedSeed = buffer.readLong()
+ val gameMode = GameMode.fromID(buffer.readUByte())
+ val previousGameMode = GameMode.fromID(buffer.readByte())
+ val isDebug = buffer.readBoolean()
+ val isFlat = buffer.readBoolean()
+ val hasDeathLocation = buffer.readBoolean()
+ val deathDimensionName = buffer.readOptional { readIdentifier() }
+ val deathLocation = buffer.readOptional { readBlockPos() }
+ val portalCooldown = buffer.readVarInt()
+ val seaLevel = buffer.readVarInt()
+ val dataKept = RespawnDataToKeep.fromByte(buffer.readByte())
+ return ClientboundRespawnPacket(
+ dimensionType, dimensionName, hashedSeed,
+ gameMode, previousGameMode, isDebug,
+ isFlat, hasDeathLocation,
+ deathDimensionName, deathLocation,
+ portalCooldown, seaLevel, dataKept
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSelectAdvancementsTabPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSelectAdvancementsTabPacket.kt
new file mode 100644
index 0000000..fd0c4b4
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSelectAdvancementsTabPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readOptional
+import cn.rtast.libmc.protocol.protocol.game.Identifier
+import cn.rtast.libmc.protocol.protocol.game.readIdentifier
+
+public data class ClientboundSelectAdvancementsTabPacket(val tabId: Identifier?) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSelectAdvancementsTabPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSelectAdvancementsTabPacket {
+ return ClientboundSelectAdvancementsTabPacket(buffer.readOptional { readIdentifier() })
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundServerDataPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundServerDataPacket.kt
new file mode 100644
index 0000000..c0c390c
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundServerDataPacket.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readOptional
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundServerDataPacket(val motd: NBTCompound, val icon: ByteArray?) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundServerDataPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundServerDataPacket {
+ val motd = buffer.readNetworkNBTCompound()
+ val icon = buffer.readOptional { val length = readVarInt(); readBytes(length) }
+ return ClientboundServerDataPacket(motd, icon)
+ }
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+ other as ClientboundServerDataPacket
+ if (motd != other.motd) return false
+ if (!icon.contentEquals(other.icon)) return false
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = motd.hashCode()
+ result = 31 * result + (icon?.contentHashCode() ?: 0)
+ return result
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetActionBarTextPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetActionBarTextPacket.kt
new file mode 100644
index 0000000..ffb6bd7
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetActionBarTextPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundSetActionBarTextPacket(val text: NBTCompound) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetActionBarTextPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetActionBarTextPacket {
+ return ClientboundSetActionBarTextPacket(buffer.readNetworkNBTCompound())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderCenterPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderCenterPacket.kt
new file mode 100644
index 0000000..8c40c2f
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderCenterPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundSetBorderCenterPacket(val x: Double, val z: Double) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetBorderCenterPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetBorderCenterPacket {
+ val x = buffer.readDouble()
+ val z = buffer.readDouble()
+ return ClientboundSetBorderCenterPacket(x, z)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderLeapSizePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderLeapSizePacket.kt
new file mode 100644
index 0000000..aa86d3a
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderLeapSizePacket.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarLong
+
+public data class ClientboundSetBorderLeapSizePacket(
+ val oldDiameter: Double,
+ val newDiameter: Double,
+ val speed: Long,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetBorderLeapSizePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetBorderLeapSizePacket {
+ val oldDiameter = buffer.readDouble()
+ val newDiameter = buffer.readDouble()
+ val speed = buffer.readVarLong()
+ return ClientboundSetBorderLeapSizePacket(oldDiameter, newDiameter, speed)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderSizePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderSizePacket.kt
new file mode 100644
index 0000000..754f799
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderSizePacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundSetBorderSizePacket(
+ /**
+ * Length of a single side of the world border, in meters
+ */
+ val diameter: Double,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetBorderSizePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetBorderSizePacket {
+ return ClientboundSetBorderSizePacket(buffer.readDouble())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderWarningDelayPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderWarningDelayPacket.kt
new file mode 100644
index 0000000..80b823e
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderWarningDelayPacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetBorderWarningDelayPacket(
+ /**
+ * In seconds as set by /worldborder warning time
+ */
+ val warningTime: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetBorderWarningDelayPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetBorderWarningDelayPacket {
+ return ClientboundSetBorderWarningDelayPacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderWarningDistancePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderWarningDistancePacket.kt
new file mode 100644
index 0000000..293deee
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetBorderWarningDistancePacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetBorderWarningDistancePacket(
+ /**
+ * In meters.
+ */
+ val warningBlocks: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetBorderWarningDistancePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetBorderWarningDistancePacket {
+ return ClientboundSetBorderWarningDistancePacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCameraPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCameraPacket.kt
new file mode 100644
index 0000000..3c195c0
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCameraPacket.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetCameraPacket(val cameraId: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetCameraPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetCameraPacket {
+ return ClientboundSetCameraPacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCarriedItemPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCarriedItemPacket.kt
new file mode 100644
index 0000000..68c0d33
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCarriedItemPacket.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetCarriedItemPacket(val slot: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetCarriedItemPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetCarriedItemPacket {
+ return ClientboundSetCarriedItemPacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCenterChunkPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCenterChunkPacket.kt
new file mode 100644
index 0000000..209c560
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCenterChunkPacket.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetCenterChunkPacket(val chunkX: Int, val chunkZ: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetCenterChunkPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetCenterChunkPacket {
+ val chunkX = buffer.readVarInt()
+ val chunkZ = buffer.readVarInt()
+ return ClientboundSetCenterChunkPacket(chunkX, chunkZ)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCursorItemPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCursorItemPacket.kt
new file mode 100644
index 0000000..06cbd2c
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetCursorItemPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.inventory.Slot
+import cn.rtast.libmc.protocol.protocol.game.inventory.readSlot
+
+public data class ClientboundSetCursorItemPacket(val carriedItem: Slot) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetCursorItemPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetCursorItemPacket {
+ return ClientboundSetCursorItemPacket(buffer.readSlot())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetDefaultSpawnPositionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetDefaultSpawnPositionPacket.kt
new file mode 100644
index 0000000..557aa16
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetDefaultSpawnPositionPacket.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+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.readBlockPos
+import cn.rtast.libmc.protocol.protocol.game.readIdentifier
+
+public data class ClientboundSetDefaultSpawnPositionPacket(
+ val dimensionName: Identifier,
+ val location: BlockPos,
+ val yaw: Float,
+ val pitch: Float,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetDefaultSpawnPositionPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetDefaultSpawnPositionPacket {
+ val dimensionName = buffer.readIdentifier()
+ val location = buffer.readBlockPos()
+ val yaw = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ return ClientboundSetDefaultSpawnPositionPacket(dimensionName, location, yaw, pitch)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetDisplayObjectivePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetDisplayObjectivePacket.kt
new file mode 100644
index 0000000..0fa973f
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetDisplayObjectivePacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readMcString
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.scoreboard.ObjectiveDisplayPosition
+
+public data class ClientboundSetDisplayObjectivePacket(val position: ObjectiveDisplayPosition, val scoreName: String) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetDisplayObjectivePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetDisplayObjectivePacket {
+ val position = ObjectiveDisplayPosition.fromID(buffer.readVarInt())
+ val scoreName = buffer.readMcString()
+ return ClientboundSetDisplayObjectivePacket(position, scoreName)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetEntityVelocityPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetEntityVelocityPacket.kt
new file mode 100644
index 0000000..4ebb69a
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetEntityVelocityPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.LpVec3
+import cn.rtast.libmc.protocol.protocol.game.math.readLpVec3
+
+public data class ClientboundSetEntityVelocityPacket(val entityId: Int, val velocity: LpVec3) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetEntityVelocityPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetEntityVelocityPacket {
+ val entityId = buffer.readVarInt()
+ val velocity = buffer.readLpVec3()
+ return ClientboundSetEntityVelocityPacket(entityId, velocity)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetEquipmentPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetEquipmentPacket.kt
new file mode 100644
index 0000000..bdfd025
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetEquipmentPacket.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.inventory.EquipmentEntry
+import cn.rtast.libmc.protocol.protocol.game.inventory.EquipmentSlot
+import cn.rtast.libmc.protocol.protocol.game.inventory.readSlot
+
+public data class ClientboundSetEquipmentPacket(val entityId: Int, val equipment: List) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ private const val MASK_HAS_NEXT: Int = 0x80
+ private const val MASK_SLOT_ID: Int = 0x7F
+
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetEquipmentPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetEquipmentPacket {
+ val entityId = buffer.readVarInt()
+ val equipment = ArrayList()
+ while (true) {
+ val rawSlot = buffer.readByte().toInt()
+ val slotId = rawSlot and MASK_SLOT_ID
+ val slot = EquipmentSlot.fromID(slotId)
+ val item = buffer.readSlot()
+ equipment.add(EquipmentEntry(slot, item))
+ if ((rawSlot and MASK_HAS_NEXT) == 0) break
+ }
+ return ClientboundSetEquipmentPacket(entityId, equipment)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetExperiencePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetExperiencePacket.kt
new file mode 100644
index 0000000..0a45fcb
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetExperiencePacket.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetExperiencePacket(
+ /**
+ * Between 0 and 1.
+ */
+ val experienceBar: Float,
+ val level: Int,
+ val totalExperience: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetExperiencePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetExperiencePacket {
+ val experienceBar = buffer.readFloat()
+ val level = buffer.readVarInt()
+ val totalExperience = buffer.readVarInt()
+ return ClientboundSetExperiencePacket(experienceBar, level, totalExperience)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetHeadRotationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetHeadRotationPacket.kt
new file mode 100644
index 0000000..3749973
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetHeadRotationPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Angle
+import cn.rtast.libmc.protocol.protocol.game.math.readAngle
+
+public data class ClientboundSetHeadRotationPacket(val entityId: Int, val headYaw: Angle) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetHeadRotationPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetHeadRotationPacket {
+ val entityId = buffer.readVarInt()
+ val headYaw = buffer.readAngle()
+ return ClientboundSetHeadRotationPacket(entityId, headYaw)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetHealthPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetHealthPacket.kt
new file mode 100644
index 0000000..7e54937
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetHealthPacket.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetHealthPacket(
+ /**
+ * 0 or less = dead, 20 = full HP.
+ */
+ val health: Float,
+ /**
+ * 0 ~ 20
+ */
+ val food: Int,
+ /**
+ * Seems to vary from 0.0 to 5.0 in integer increments.
+ */
+ val foodSaturation: Float,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetHealthPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetHealthPacket {
+ val health = buffer.readFloat()
+ val food = buffer.readVarInt()
+ val foodSaturation = buffer.readFloat()
+ return ClientboundSetHealthPacket(health, food, foodSaturation)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetPassengersPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetPassengersPacket.kt
new file mode 100644
index 0000000..2be6f22
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetPassengersPacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readPrefixed
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetPassengersPacket(val entityId: Int, val passengersId: List) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetPassengersPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetPassengersPacket {
+ val entityId = buffer.readVarInt()
+ val passengers = buffer.readPrefixed { readVarInt() }
+ return ClientboundSetPassengersPacket(entityId, passengers)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetPlayerInventorySlotPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetPlayerInventorySlotPacket.kt
new file mode 100644
index 0000000..772db11
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetPlayerInventorySlotPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.inventory.Slot
+import cn.rtast.libmc.protocol.protocol.game.inventory.readSlot
+
+public data class ClientboundSetPlayerInventorySlotPacket(val slot: Int, val data: Slot) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetPlayerInventorySlotPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetPlayerInventorySlotPacket {
+ val slot = buffer.readVarInt()
+ val slotData = buffer.readSlot()
+ return ClientboundSetPlayerInventorySlotPacket(slot, slotData)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetRenderDistancePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetRenderDistancePacket.kt
new file mode 100644
index 0000000..7313586
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetRenderDistancePacket.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetRenderDistancePacket(
+ /**
+ * 2-32
+ */
+ val viewDistance: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetRenderDistancePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetRenderDistancePacket {
+ return ClientboundSetRenderDistancePacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetSimulationDistancePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetSimulationDistancePacket.kt
new file mode 100644
index 0000000..015b93d
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetSimulationDistancePacket.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundSetSimulationDistancePacket(val distance: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetSimulationDistancePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetSimulationDistancePacket {
+ return ClientboundSetSimulationDistancePacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetSubtitleTextPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetSubtitleTextPacket.kt
new file mode 100644
index 0000000..0b94db6
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetSubtitleTextPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundSetSubtitleTextPacket(val subTitleText: NBTCompound) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetSubtitleTextPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetSubtitleTextPacket {
+ return ClientboundSetSubtitleTextPacket(buffer.readNetworkNBTCompound())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTabListHeaderAndFooterPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTabListHeaderAndFooterPacket.kt
new file mode 100644
index 0000000..09da542
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTabListHeaderAndFooterPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundSetTabListHeaderAndFooterPacket(val header: NBTCompound, val footer: NBTCompound) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetTabListHeaderAndFooterPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetTabListHeaderAndFooterPacket {
+ val header = buffer.readNetworkNBTCompound()
+ val footer = buffer.readNetworkNBTCompound()
+ return ClientboundSetTabListHeaderAndFooterPacket(header, footer)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTickingStatePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTickingStatePacket.kt
new file mode 100644
index 0000000..96eab69
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTickingStatePacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundSetTickingStatePacket(val tickRate: Float, val isFrozen: Boolean) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetTickingStatePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetTickingStatePacket {
+ val tickRate = buffer.readFloat()
+ val isFrozen = buffer.readBoolean()
+ return ClientboundSetTickingStatePacket(tickRate, isFrozen)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTimePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTimePacket.kt
new file mode 100644
index 0000000..834ab92
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTimePacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.common.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.world.WorldClockData
+
+public data class ClientboundSetTimePacket(val worldAge: Long, val clocks: List) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetTimePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetTimePacket {
+ val age = buffer.readLong()
+ val clocks = buffer.readPrefixed {
+ WorldClockData(readVarInt(), readVarLong(), readFloat(), readFloat())
+ }
+ return ClientboundSetTimePacket(age, clocks)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTitleAnimationTimesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTitleAnimationTimesPacket.kt
new file mode 100644
index 0000000..b556f3c
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTitleAnimationTimesPacket.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundSetTitleAnimationTimesPacket(val fadeIn: Int, val stay: Int, val fadeOut: Int) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetTitleAnimationTimesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetTitleAnimationTimesPacket {
+ val fadeIn = buffer.readInt()
+ val stay = buffer.readInt()
+ val fadeOut = buffer.readInt()
+ return ClientboundSetTitleAnimationTimesPacket(fadeIn, stay, fadeOut)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTitleTextPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTitleTextPacket.kt
new file mode 100644
index 0000000..510ad09
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSetTitleTextPacket.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundSetTitleTextPacket(val text: NBTCompound) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSetTitleTextPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSetTitleTextPacket {
+ return ClientboundSetTitleTextPacket(buffer.readNetworkNBTCompound())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundShowDialogPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundShowDialogPacket.kt
index 79bb094..079a0e8 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundShowDialogPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundShowDialogPacket.kt
@@ -15,7 +15,7 @@ import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundShowDialogPacket(val dialog: IdOrX) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundShowDialogPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundShowDialogPacket {
return ClientboundShowDialogPacket(buffer.readIdOrX { this.readNetworkNBTCompound() })
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSoundEffectPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSoundEffectPacket.kt
new file mode 100644
index 0000000..cdb6935
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSoundEffectPacket.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.common.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.sound.SoundCategory
+import cn.rtast.libmc.protocol.protocol.game.sound.SoundEvent
+import cn.rtast.libmc.protocol.protocol.game.sound.readSoundEvent
+
+public data class ClientboundSoundEffectPacket(
+ val soundEvent: IdOrX,
+ val category: SoundCategory,
+ val effectPositionX: Int,
+ val effectPositionY: Int,
+ val effectPositionZ: Int,
+ val volume: Float,
+ val pitch: Float,
+ val seed: Long,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSoundEffectPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSoundEffectPacket {
+ val soundEvent = buffer.readIdOrX { readSoundEvent() }
+ val category = SoundCategory.fromID(buffer.readVarInt())
+ val effectPositionX = buffer.readInt()
+ val effectPositionY = buffer.readInt()
+ val effectPositionZ = buffer.readInt()
+ val volume = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ val seed = buffer.readLong()
+ return ClientboundSoundEffectPacket(
+ soundEvent, category, effectPositionX,
+ effectPositionY, effectPositionZ,
+ volume, pitch, seed
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSpawnEntityPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSpawnEntityPacket.kt
index d5fd47b..381be9f 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSpawnEntityPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSpawnEntityPacket.kt
@@ -33,7 +33,7 @@ public data class ClientboundSpawnEntityPacket(
val headYaw: Angle,
val data: Int,
) : ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundSpawnEntityPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundSpawnEntityPacket {
val entityId = buffer.readVarInt()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundStepTickPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundStepTickPacket.kt
new file mode 100644
index 0000000..29d6ab8
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundStepTickPacket.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundStepTickPacket(val tickSteps: Int) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundStepTickPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundStepTickPacket {
+ return ClientboundStepTickPacket(buffer.readVarInt())
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundStopSoundPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundStopSoundPacket.kt
new file mode 100644
index 0000000..d866ce3
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundStopSoundPacket.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.Identifier
+import cn.rtast.libmc.protocol.protocol.game.readIdentifier
+import cn.rtast.libmc.protocol.protocol.game.sound.SoundCategory
+
+public data class ClientboundStopSoundPacket(
+ val flags: Byte,
+ val source: SoundCategory?,
+ val sound: Identifier?,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ private const val MASK_HAS_SOURCE = 0x01
+ private const val MASK_HAS_SOUND = 0x02
+
+ override fun encode(buffer: BytesBuffer, value: ClientboundStopSoundPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundStopSoundPacket {
+ val flags = buffer.readByte()
+ val category =
+ if ((flags.toInt() and MASK_HAS_SOURCE) != 0) SoundCategory.fromID(buffer.readVarInt()) else null
+ val sound = if ((flags.toInt() and MASK_HAS_SOUND) != 0) buffer.readIdentifier() else null
+ return ClientboundStopSoundPacket(flags, category, sound)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSynchronizePlayerPositionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSynchronizePlayerPositionPacket.kt
new file mode 100644
index 0000000..4eab1d1
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSynchronizePlayerPositionPacket.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Vec3d
+import cn.rtast.libmc.protocol.protocol.game.math.readVec3d
+import cn.rtast.libmc.protocol.protocol.game.player.TeleportFlags
+
+public data class ClientboundSynchronizePlayerPositionPacket(
+ val teleportId: Int,
+ val position: Vec3d,
+ val velocity: Vec3d,
+ val yaw: Float,
+ val pitch: Float,
+ val flags: TeleportFlags,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSynchronizePlayerPositionPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSynchronizePlayerPositionPacket {
+ val teleportId = buffer.readVarInt()
+ val position = buffer.readVec3d()!!
+ val velocity = buffer.readVec3d()!!
+ val yaw = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ val rawFlags = buffer.readInt()
+ val flags = TeleportFlags.fromInt(rawFlags)
+ return ClientboundSynchronizePlayerPositionPacket(
+ teleportId, position, velocity,
+ yaw, pitch, flags
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSynchronizeVehiclePositionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSynchronizeVehiclePositionPacket.kt
new file mode 100644
index 0000000..ad26138
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSynchronizeVehiclePositionPacket.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Vec3d
+import cn.rtast.libmc.protocol.protocol.game.math.readVec3d
+import cn.rtast.libmc.protocol.protocol.game.player.TeleportFlags
+
+public data class ClientboundSynchronizeVehiclePositionPacket(
+ val entityId: Int,
+ val position: Vec3d,
+ val velocityPosition: Vec3d,
+ val yaw: Float,
+ val pitch: Float,
+ val flags: TeleportFlags,
+ val onGround: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundSynchronizeVehiclePositionPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundSynchronizeVehiclePositionPacket {
+ val entityId = buffer.readVarInt()
+ val position = buffer.readVec3d()!!
+ val velocityPosition = buffer.readVec3d()!!
+ val yaw = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ val flags = TeleportFlags.fromInt(buffer.readInt())
+ val onGround = buffer.readBoolean()
+ return ClientboundSynchronizeVehiclePositionPacket(
+ entityId, position,
+ velocityPosition, yaw,
+ pitch, flags, onGround
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSystemChatMessagePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSystemChatMessagePacket.kt
index 6bca92c..3c54f1c 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSystemChatMessagePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundSystemChatMessagePacket.kt
@@ -14,7 +14,7 @@ import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundSystemChatMessagePacket(val content: NBTCompound, val overlay: Boolean) :
ClientboundPlayPacket {
- public companion object Codec : PacketCodec {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ClientboundSystemChatMessagePacket) {}
override fun decode(buffer: BytesBuffer): ClientboundSystemChatMessagePacket {
val content = buffer.readNetworkNBTCompound()
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTagQueryResponsePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTagQueryResponsePacket.kt
new file mode 100644
index 0000000..fd9d879
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTagQueryResponsePacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundTagQueryResponsePacket(val transactionId: Int, val nbt: NBTCompound) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundTagQueryResponsePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundTagQueryResponsePacket {
+ val transactionId = buffer.readVarInt()
+ val nbt = buffer.readNetworkNBTCompound()
+ return ClientboundTagQueryResponsePacket(transactionId, nbt)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTeleportEntityPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTeleportEntityPacket.kt
new file mode 100644
index 0000000..0e57040
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTeleportEntityPacket.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Vec3d
+import cn.rtast.libmc.protocol.protocol.game.math.readVec3d
+
+public data class ClientboundTeleportEntityPacket(
+ val entityId: Int,
+ /**
+ * packed vec3d
+ */
+ val position: Vec3d,
+ /**
+ * packed vec3d
+ */
+ val velocityPosition: Vec3d,
+ val yaw: Float,
+ val pitch: Float,
+ val onGround: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundTeleportEntityPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundTeleportEntityPacket {
+ val entityId = buffer.readVarInt()
+ val position = buffer.readVec3d()!!
+ val velocityPosition = buffer.readVec3d()!!
+ val yaw = buffer.readFloat()
+ val pitch = buffer.readFloat()
+ val onGround = buffer.readBoolean()
+ return ClientboundTeleportEntityPacket(entityId, position, velocityPosition, yaw, pitch, onGround)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTestHighlightPositionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTestHighlightPositionPacket.kt
new file mode 100644
index 0000000..5c86c29
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTestHighlightPositionPacket.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.protocol.protocol.game.block.BlockPos
+import cn.rtast.libmc.protocol.protocol.game.block.readBlockPos
+
+public data class ClientboundTestHighlightPositionPacket(val absolute: BlockPos, val relative: BlockPos) :
+ MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundTestHighlightPositionPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundTestHighlightPositionPacket {
+ val abs = buffer.readBlockPos()
+ val rel = buffer.readBlockPos()
+ return ClientboundTestHighlightPositionPacket(abs, rel)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTestInstanceBlockStatusPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTestInstanceBlockStatusPacket.kt
new file mode 100644
index 0000000..697f335
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundTestInstanceBlockStatusPacket.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readOptional
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundTestInstanceBlockStatusPacket(
+ val status: NBTCompound,
+ val hasSize: Boolean,
+ val sizeX: Double?,
+ val sizeY: Double?,
+ val sizeZ: Double?,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundTestInstanceBlockStatusPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundTestInstanceBlockStatusPacket {
+ val status = buffer.readNetworkNBTCompound()
+ val hasSize = buffer.readBoolean()
+ val sizeX = buffer.readOptional { readDouble() } // ?
+ val sizeY = buffer.readOptional { readDouble() } // ?
+ val sizeZ = buffer.readOptional { readDouble() } // ?
+ return ClientboundTestInstanceBlockStatusPacket(status, hasSize, sizeX, sizeY, sizeZ)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUnloadChunkPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUnloadChunkPacket.kt
new file mode 100644
index 0000000..8e57ea1
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUnloadChunkPacket.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+
+public data class ClientboundUnloadChunkPacket(
+ /**
+ * Block coordinate divided by 16, rounded down
+ */
+ val chunkZ: Int,
+ /**
+ * Block coordinate divided by 16, rounded down
+ */
+ val chunkX: Int,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUnloadChunkPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUnloadChunkPacket {
+ val z = buffer.readInt()
+ val x = buffer.readInt()
+ return ClientboundUnloadChunkPacket(z, x)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateAttributesPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateAttributesPacket.kt
new file mode 100644
index 0000000..2dd9dac
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateAttributesPacket.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readPrefixed
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.entity.attributes.AttributeModifierData
+import cn.rtast.libmc.protocol.protocol.game.entity.attributes.AttributeModifierOperation
+import cn.rtast.libmc.protocol.protocol.game.entity.attributes.EntityAttributeProperty
+import cn.rtast.libmc.protocol.protocol.game.readIdentifier
+
+public data class ClientboundUpdateAttributesPacket(
+ val entityId: Int,
+ val properties: List,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateAttributesPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateAttributesPacket {
+ val entityId = buffer.readVarInt()
+ val properties = buffer.readPrefixed {
+ val attributeId = readVarInt()
+ val value = readDouble()
+ val modifiers = readPrefixed {
+ AttributeModifierData(readIdentifier(), readDouble(), AttributeModifierOperation.fromID(readByte()))
+ }
+ EntityAttributeProperty(
+ attributeId = attributeId,
+ value = value,
+ modifiers = modifiers
+ )
+ }
+ return ClientboundUpdateAttributesPacket(entityId, properties)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityPositionAndRotationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityPositionAndRotationPacket.kt
new file mode 100644
index 0000000..777306e
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityPositionAndRotationPacket.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Angle
+import cn.rtast.libmc.protocol.protocol.game.math.readAngle
+
+public data class ClientboundUpdateEntityPositionAndRotationPacket(
+ val entityId: Int,
+ val deltaX: Short,
+ val deltaY: Short,
+ val deltaZ: Short,
+ val yaw: Angle,
+ val pitch: Angle,
+ val onGround: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateEntityPositionAndRotationPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateEntityPositionAndRotationPacket {
+ val entityId = buffer.readVarInt()
+ val x = buffer.readShort()
+ val y = buffer.readShort()
+ val z = buffer.readShort()
+ val yaw = buffer.readAngle()
+ val pitch = buffer.readAngle()
+ val onGround = buffer.readBoolean()
+ return ClientboundUpdateEntityPositionAndRotationPacket(entityId, x, y, z,yaw, pitch, onGround)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityPositionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityPositionPacket.kt
new file mode 100644
index 0000000..2362b0a
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityPositionPacket.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+
+public data class ClientboundUpdateEntityPositionPacket(
+ val entityId: Int,
+ val deltaX: Short,
+ val deltaY: Short,
+ val deltaZ: Short,
+ val onGround: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateEntityPositionPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateEntityPositionPacket {
+ val entityId = buffer.readVarInt()
+ val x = buffer.readShort()
+ val y = buffer.readShort()
+ val z = buffer.readShort()
+ val onGround = buffer.readBoolean()
+ return ClientboundUpdateEntityPositionPacket(entityId, x, y, z, onGround)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityRotationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityRotationPacket.kt
new file mode 100644
index 0000000..0c6c167
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateEntityRotationPacket.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.protocol.protocol.game.math.Angle
+import cn.rtast.libmc.protocol.protocol.game.math.readAngle
+
+public data class ClientboundUpdateEntityRotationPacket(
+ val entityId: Int,
+ val yaw: Angle,
+ val pitch: Angle,
+ val onGround: Boolean,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateEntityRotationPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateEntityRotationPacket {
+ val entityId = buffer.readVarInt()
+ val yaw = buffer.readAngle()
+ val pitch = buffer.readAngle()
+ val onGround = buffer.readBoolean()
+ return ClientboundUpdateEntityRotationPacket(entityId, yaw, pitch, onGround)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateObjectivePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateObjectivePacket.kt
new file mode 100644
index 0000000..c4773bb
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateObjectivePacket.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readMcString
+import cn.rtast.libmc.common.readVarInt
+import cn.rtast.libmc.nbt.NBTTag
+import cn.rtast.libmc.protocol.protocol.game.scoreboard.ObjectivePayload
+import cn.rtast.libmc.protocol.protocol.game.scoreboard.ObjectiveRenderType
+import cn.rtast.libmc.protocol.protocol.game.scoreboard.ScoreNumberFormat
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundUpdateObjectivePacket(
+ val objectiveName: String,
+ val mode: Byte,
+ val payload: ObjectivePayload?,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateObjectivePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateObjectivePacket {
+ val objectiveName = buffer.readMcString()
+ val mode = buffer.readByte()
+ val payload = when (mode.toInt()) {
+ 1 -> ObjectivePayload.Remove
+ 0, 2 -> {
+ val displayName = buffer.readNetworkNBTCompound()
+ val renderType = ObjectiveRenderType.fromID(buffer.readVarInt())
+ val hasNumberFormat = buffer.readBoolean()
+ val numberFormat = if (hasNumberFormat) {
+ when (val type = buffer.readVarInt()) {
+ 0 -> ScoreNumberFormat.Blank
+ 1 -> ScoreNumberFormat.Styled(styling = buffer.readNetworkNBTCompound().element as NBTTag.CompoundTag) // fix me
+ 2 -> ScoreNumberFormat.Fixed(content = buffer.readNetworkNBTCompound()) // ?
+ else -> error("Unknown ScoreNumberFormat type: $type")
+ }
+ } else null
+ ObjectivePayload.Upsert(
+ displayName = displayName,
+ renderType = renderType,
+ defaultNumberFormat = numberFormat
+ )
+ }
+
+ else -> null
+ }
+ return ClientboundUpdateObjectivePacket(objectiveName, mode, payload)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateScorePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateScorePacket.kt
new file mode 100644
index 0000000..c5104ae
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateScorePacket.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+package cn.rtast.libmc.protocol.packet.play.clientbound
+
+import cn.rtast.libmc.common.*
+import cn.rtast.libmc.common.packet.MinecraftPacket
+import cn.rtast.libmc.nbt.NBTCompound
+import cn.rtast.libmc.nbt.NBTTag
+import cn.rtast.libmc.protocol.protocol.game.scoreboard.ScoreNumberFormat
+import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
+
+public data class ClientboundUpdateScorePacket(
+ val entityName: String,
+ val objectiveName: String,
+ val value: Int,
+ val displayName: NBTCompound?,
+ val numberFormat: ScoreNumberFormat?,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateScorePacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateScorePacket {
+ val entityName = buffer.readMcString()
+ val objectiveName = buffer.readMcString()
+ val value = buffer.readVarInt()
+ val displayName = buffer.readOptional { readNetworkNBTCompound() }
+ val numberFormat = buffer.readOptional {
+ when (val type = readVarInt()) {
+ 0 -> ScoreNumberFormat.Blank
+ 1 -> ScoreNumberFormat.Styled(styling = readNetworkNBTCompound().element as NBTTag.CompoundTag) // fix me
+ 2 -> ScoreNumberFormat.Fixed(content = readNetworkNBTCompound())
+ else -> error("Unknown ScoreNumberFormat type: $type")
+ }
+ }
+ return ClientboundUpdateScorePacket(entityName, objectiveName, value, displayName, numberFormat)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateSectionBlockPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateSectionBlockPacket.kt
new file mode 100644
index 0000000..9f02014
--- /dev/null
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundUpdateSectionBlockPacket.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2026 RTAkland
+ * Author: RTAkland
+ * Date: 2026/9/6
+ */
+
+
+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.packet.MinecraftPacket
+import cn.rtast.libmc.common.readPrefixed
+import cn.rtast.libmc.common.readVarLong
+import cn.rtast.libmc.protocol.protocol.game.chunk.BlockUpdateEntry
+import cn.rtast.libmc.protocol.protocol.game.chunk.ChunkSectionPos
+
+public data class ClientboundUpdateSectionBlockPacket(
+ val sectionPos: ChunkSectionPos,
+ val blockUpdates: List,
+) : MinecraftPacket {
+ internal companion object Codec : PacketCodec {
+ override fun encode(buffer: BytesBuffer, value: ClientboundUpdateSectionBlockPacket) {}
+ override fun decode(buffer: BytesBuffer): ClientboundUpdateSectionBlockPacket {
+ val rawSectionPos = buffer.readLong()
+ val sectionPos = ChunkSectionPos.fromRaw(rawSectionPos)
+ val blockUpdates = buffer.readPrefixed {
+ val rawBlockEntry = readVarLong()
+ BlockUpdateEntry.fromRaw(rawBlockEntry)
+ }
+ return ClientboundUpdateSectionBlockPacket(sectionPos, blockUpdates)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcceptTeleportationPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcceptTeleportationPacket.kt
index dd3f065..318b54c 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcceptTeleportationPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcceptTeleportationPacket.kt
@@ -13,7 +13,7 @@ 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 {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundAcceptTeleportationPacket) {
buffer.writeVarInt(value.teleportId)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcknowledgeChatMessagePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcknowledgeChatMessagePacket.kt
index b2e1eb6..68e4480 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcknowledgeChatMessagePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAcknowledgeChatMessagePacket.kt
@@ -13,7 +13,7 @@ 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 {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundAcknowledgeChatMessagePacket) {
buffer.writeVarInt(value.messageCount)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAttackActionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAttackActionPacket.kt
index 333f3f4..152d337 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAttackActionPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundAttackActionPacket.kt
@@ -13,7 +13,7 @@ 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 {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundAttackActionPacket) {
buffer.writeVarInt(value.entityId)
}
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundBundleItemSelectedPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundBundleItemSelectedPacket.kt
index 54d9a4e..6cd16ec 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundBundleItemSelectedPacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundBundleItemSelectedPacket.kt
@@ -13,7 +13,7 @@ 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 {
+ internal companion object Codec : PacketCodec {
override fun encode(buffer: BytesBuffer, value: ServerboundBundleItemSelectedPacket) {
buffer.writeVarInt(value.slotOfBundle)
buffer.writeVarInt(value.slotInBundle)
diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundChangeContainerSlotStatePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundChangeContainerSlotStatePacket.kt
index 5cf8f3f..55e46a2 100644
--- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundChangeContainerSlotStatePacket.kt
+++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundChangeContainerSlotStatePacket.kt
@@ -14,7 +14,7 @@ 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