diff --git a/README.md b/README.md index 2a7e8ba..1c5910a 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ A lightweight minecraft client-side protocol library and related library, includ - [x] `0x0D` Chunks Biomes (`ClientboundChunksBiomesPacket`) - [x] `0x0E` Clear Titles (`ClientboundClearTitlesPacket`) - [x] `0x0F` Command Suggestions (`ClientboundCommandSuggestionsPacket`) -- [ ] `0x10` Commands (`ClientboundCommandsPacket`) +- [x] `0x10` Commands (`ClientboundCommandsPacket`) - [x] `0x11` Container Close (`ClientboundContainerClosePacket`) - [ ] `0x12` Container Set Content (`ClientboundContainerSetContentPacket`) - [x] `0x13` Container Set Data (`ClientboundContainerSetDataPacket`) @@ -178,7 +178,7 @@ A lightweight minecraft client-side protocol library and related library, includ - [ ] `0x30` Light Update (`ClientboundLightUpdatePacket`) - [x] `0x31` Login Play (`ClientboundLoginPlayPacket`) - [x] `0x32` Low Disk Space Warning (`ClientboundLowDiskSpaceWarningPacket`) -- [ ] `0x33` Map Item Data (`ClientboundMapItemDataPacket`) +- [x] `0x33` Map Item Data (`ClientboundMapItemDataPacket`) - [ ] `0x34` Merchant Offers (`ClientboundMerchantOffersPacket`) - [x] `0x35` Update Entity Position (`ClientboundUpdateEntityPositionPacket`) - [x] `0x36` Update Entity Position and Rotation (`ClientboundUpdateEntityPositionAndRotationPacket`) @@ -197,7 +197,7 @@ A lightweight minecraft client-side protocol library and related library, includ - [x] `0x43` Player Enter Combat (`ClientboundPlayerEnterCombatPacket`) - [x] `0x44` Player Combat Death (`ClientboundPlayerCombatDeathPacket`) - [x] `0x45` Player Info Remove (`ClientboundPlayerInfoRemovePacket`) -- [ ] `0x46` Player Info Update (`ClientboundPlayerInfoUpdatePacket`) +- [x] `0x46` Player Info Update (`ClientboundPlayerInfoUpdatePacket`) - [x] `0x47` Player Look At (`ClientboundPlayerLookAtPacket`) - [x] `0x48` Synchronize Player Position (`ClientboundSynchronizePlayerPositionPacket`) - [x] `0x49` Player Rotation (`ClientboundPlayerRotationPacket`) @@ -265,7 +265,7 @@ A lightweight minecraft client-side protocol library and related library, includ - [x] `0x87` Projectile Power (`ClientboundProjectilePowerPacket`) - [x] `0x88` Custom Report Details (`ClientboundCustomReportDetailsPacket`) - [x] `0x89` Server Links (`ClientboundServerLinksPacket`) -- [ ] `0x8A` Waypoint (`ClientboundWaypointPacket`) +- [x] `0x8A` Waypoint (`ClientboundWaypointPacket`) - [x] `0x8B` Clear Dialog (`ClientboundClearDialogPacket`) - [x] `0x8C` Show Dialog (`ClientboundShowDialogPacket`) diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerInfoUpdatePacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerInfoUpdatePacket.kt new file mode 100644 index 0000000..fff88ba --- /dev/null +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/clientbound/ClientboundPlayerInfoUpdatePacket.kt @@ -0,0 +1,89 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/7 + */ + + +package cn.rtast.libmc.protocol.packet.play.clientbound + +import cn.rtast.libmc.packet.MinecraftPacket +import cn.rtast.libmc.packet.PacketCodec +import cn.rtast.libmc.primitives.* +import cn.rtast.libmc.protocol.protocol.game.chat.readTextComponent +import cn.rtast.libmc.protocol.protocol.game.player.action.PlayerInfoUpdateEntry +import cn.rtast.libmc.protocol.protocol.game.player.action.PlayerUpdateInfoAction +import cn.rtast.libmc.protocol.protocol.game.player.action.SinglePlayerAction +import cn.rtast.libmc.protocol.protocol.game.session.GameProfile +import cn.rtast.libmc.stream.BytesBuffer + +public data class ClientboundPlayerInfoUpdatePacket( + val actions: Set, + val entries: List, +) : MinecraftPacket { + internal companion object Codec : PacketCodec { + override suspend fun encode(buffer: BytesBuffer, value: ClientboundPlayerInfoUpdatePacket) {} + override suspend fun decode(buffer: BytesBuffer): ClientboundPlayerInfoUpdatePacket { + val actionsMask = buffer.readUByte().toInt() + val actionsSet = PlayerUpdateInfoAction.parseActions(actionsMask) + val playerCount = buffer.readVarInt() + val entries = ArrayList(playerCount) + repeat(playerCount) { + val playerUuid = buffer.readUuid() + val playerActions = ArrayList(actionsSet.size) + for (action in PlayerUpdateInfoAction.entries) { + if (action !in actionsSet) continue + val parsedAction = when (action) { + PlayerUpdateInfoAction.ADD_PLAYER -> { + val name = buffer.readMcString() + val properties = buffer.readPrefixed { + GameProfile.Property.decode(buffer) + } + SinglePlayerAction.AddPlayer(name, properties) + } + + PlayerUpdateInfoAction.INITIALIZE_CHAT -> { + buffer.readOptional { + SinglePlayerAction.InitializeChat( + readUuid(), readLong(), + readBytes(512), readBytes(4096) + ) + } ?: SinglePlayerAction.InitializeChat(null, null, null, null) + } + + PlayerUpdateInfoAction.UPDATE_GAME_MODE -> { + SinglePlayerAction.UpdateGameMode(buffer.readVarInt()) + } + + PlayerUpdateInfoAction.UPDATE_LISTED -> { + SinglePlayerAction.UpdateListed(buffer.readBoolean()) + } + + PlayerUpdateInfoAction.UPDATE_LATENCY -> { + SinglePlayerAction.UpdateLatency(buffer.readVarInt()) + } + + PlayerUpdateInfoAction.UPDATE_DISPLAY_NAME -> { + val hasDisplayName = buffer.readBoolean() + val displayName = if (hasDisplayName) buffer.readTextComponent() else null + SinglePlayerAction.UpdateDisplayName(displayName) + } + + PlayerUpdateInfoAction.UPDATE_LIST_PRIORITY -> { + SinglePlayerAction.UpdateListPriority(buffer.readVarInt()) + } + + PlayerUpdateInfoAction.UPDATE_HAT -> { + SinglePlayerAction.UpdateHat(buffer.readBoolean()) + } + } + + playerActions.add(parsedAction) + } + + entries.add(PlayerInfoUpdateEntry(playerUuid, playerActions)) + } + return ClientboundPlayerInfoUpdatePacket(actionsSet, entries) + } + } +} \ No newline at end of file diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundClientCommandPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundClientCommandPacket.kt index 95338b9..a6b8efb 100644 --- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundClientCommandPacket.kt +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundClientCommandPacket.kt @@ -11,7 +11,7 @@ import cn.rtast.libmc.stream.BytesBuffer import cn.rtast.libmc.packet.PacketCodec import cn.rtast.libmc.packet.MinecraftPacket import cn.rtast.libmc.primitives.writeVarInt -import cn.rtast.libmc.protocol.protocol.game.player.PlayerActionStatus +import cn.rtast.libmc.protocol.protocol.game.player.action.PlayerActionStatus public data class ServerboundClientCommandPacket(val action: PlayerActionStatus) : MinecraftPacket { internal companion object Codec : PacketCodec { diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerActionPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerActionPacket.kt index 169bdff..1170d5e 100644 --- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerActionPacket.kt +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerActionPacket.kt @@ -14,7 +14,7 @@ import cn.rtast.libmc.primitives.writeVarInt import cn.rtast.libmc.protocol.protocol.game.block.BlockFace import cn.rtast.libmc.protocol.protocol.game.block.BlockPos import cn.rtast.libmc.protocol.protocol.game.block.writeBlockPos -import cn.rtast.libmc.protocol.protocol.game.player.PlayerActionStatus +import cn.rtast.libmc.protocol.protocol.game.player.action.PlayerActionStatus /** * ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Player_Action diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerCommandPacket.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerCommandPacket.kt index ee9e382..1aef918 100644 --- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerCommandPacket.kt +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/packet/play/serverbound/ServerboundPlayerCommandPacket.kt @@ -11,7 +11,7 @@ import cn.rtast.libmc.stream.BytesBuffer import cn.rtast.libmc.packet.PacketCodec import cn.rtast.libmc.packet.MinecraftPacket import cn.rtast.libmc.primitives.writeVarInt -import cn.rtast.libmc.protocol.protocol.game.player.PlayerCommandAction +import cn.rtast.libmc.protocol.protocol.game.player.action.PlayerCommandAction public data class ServerboundPlayerCommandPacket( val entityId: Int, diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/GamePacketsProtocolCodec.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/GamePacketsProtocolCodec.kt index 20266d8..7cf8d52 100644 --- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/GamePacketsProtocolCodec.kt +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/GamePacketsProtocolCodec.kt @@ -48,12 +48,12 @@ internal object GamePacketsProtocolCodec { register(0x07, ClientboundRegistryDataPacket) register(0x08, ClientboundRemoveResourcePackPacket) register(0x09, ClientboundAddResourcePackPacket) - register(0x0a, ClientboundStoreCookiePacket) - register(0x0b, ClientboundTransferPacket) - register(0x0c, ClientboundUpdateEnabledFeaturesPacket) - register(0x0d, ClientboundUpdateTagsPacket) - register(0x0e, ClientboundSelectKnownPacksPacket) - register(0x0f, ClientboundCustomReportDetailsPacket) + register(0x0A, ClientboundStoreCookiePacket) + register(0x0B, ClientboundTransferPacket) + register(0x0C, ClientboundUpdateEnabledFeaturesPacket) + register(0x0D, ClientboundUpdateTagsPacket) + register(0x0E, ClientboundSelectKnownPacksPacket) + register(0x0F, ClientboundCustomReportDetailsPacket) register(0x10, ClientboundServerLinksPacket) register(0x11, ClientboundClearDialogPacket) register(0x12, ClientboundConfigurationShowDialogPacket) @@ -70,12 +70,12 @@ internal object GamePacketsProtocolCodec { register(0x07, ClientboundBlockEventPacket) register(0x08, ClientboundBlockUpdatePacket) register(0x09, ClientboundBossEventPacket) - register(0x0a, ClientboundChangeDifficultyPacket) - register(0x0b, ClientboundChunkBatchFinishedPacket) - register(0x0c, ClientboundChunkBatchStartPacket) - register(0x0d, ClientboundChunksBiomesPacket) - register(0x0e, ClientboundClearTitlesPacket) - register(0x0f, ClientboundCommandSuggestionsPacket) + register(0x0A, ClientboundChangeDifficultyPacket) + register(0x0B, ClientboundChunkBatchFinishedPacket) + register(0x0C, ClientboundChunkBatchStartPacket) + register(0x0D, ClientboundChunksBiomesPacket) + register(0x0E, ClientboundClearTitlesPacket) + register(0x0F, ClientboundCommandSuggestionsPacket) register(0x10, ClientboundCommandsPacket) register(0x11, ClientboundContainerClosePacket) // register(0x12, ClientboundContainerSetContentPacket) @@ -86,12 +86,12 @@ internal object GamePacketsProtocolCodec { register(0x17, ClientboundCustomChatCompletionsPacket) register(0x18, ClientboundCustomPayloadPacket) register(0x19, ClientboundDamageEventPacket) -// register(0x1a, ClientboundDebugBlockValuePacket) -// register(0x1b, ClientboundDebugChunkValuePacket) -// register(0x1c, ClientboundDebugEntityValuePacket) -// register(0x1d, ClientboundDebugEventPacket) -// register(0x1e, ClientboundDebugSamplePacket) - register(0x1f, ClientboundDeleteChatPacket) +// register(0x1A, ClientboundDebugBlockValuePacket) +// register(0x1B, ClientboundDebugChunkValuePacket) +// register(0x1C, ClientboundDebugEntityValuePacket) +// register(0x1D, ClientboundDebugEventPacket) +// register(0x1E, ClientboundDebugSamplePacket) + register(0x1F, ClientboundDeleteChatPacket) register(0x20, ClientboundDisconnectPlayPacket) register(0x21, ClientboundDisguisedChatMessagePacket) register(0x22, ClientboundEntityEventPacket) @@ -102,12 +102,12 @@ internal object GamePacketsProtocolCodec { register(0x27, ClientboundGameRuleValuesPacket) register(0x28, ClientboundTestHighlightPositionPacket) register(0x29, ClientboundOpenHorseScreenPacket) - register(0x2a, ClientboundHurtAnimationPacket) - register(0x2b, ClientboundInitializeWorldBorderPacket) - register(0x2c, ClientboundKeepAlivePlayPacket) -// register(0x2d, ClientboundLevelChunkUpdateWithLightPacket) - register(0x2e, ClientboundLevelEventPacket) -// register(0x2f, ClientboundParticlePacket) + register(0x2A, ClientboundHurtAnimationPacket) + register(0x2B, ClientboundInitializeWorldBorderPacket) + register(0x2C, ClientboundKeepAlivePlayPacket) +// register(0x2D, ClientboundLevelChunkUpdateWithLightPacket) + register(0x2E, ClientboundLevelEventPacket) +// register(0x2F, ClientboundParticlePacket) // register(0x30, ClientboundLightUpdatePacket) register(0x31, ClientboundLoginPlayPacket) register(0x32, ClientboundLowDiskSpaceWarningPacket) @@ -118,28 +118,28 @@ internal object GamePacketsProtocolCodec { register(0x37, ClientboundMoveMinecartAlongTrackPacket) register(0x38, ClientboundUpdateEntityRotationPacket) register(0x39, ClientboundMoveVehiclePacket) - register(0x3a, ClientboundOpenBookPacket) - register(0x3b, ClientboundOpenScreenPacket) - register(0x3c, ClientboundOpenSignEditorPacket) - register(0x3d, ClientboundPingPacket) - register(0x3e, ClientboundPongResponsePacket) -// register(0x3f, ClientboundPlaceGhostRecipePacket) + register(0x3A, ClientboundOpenBookPacket) + register(0x3B, ClientboundOpenScreenPacket) + register(0x3C, ClientboundOpenSignEditorPacket) + register(0x3D, ClientboundPingPacket) + register(0x3E, ClientboundPongResponsePacket) +// register(0x3F, ClientboundPlaceGhostRecipePacket) register(0x40, ClientboundPlayerAbilitiesPacket) register(0x41, ClientboundPlayerChatMessagePacket) register(0x42, ClientboundPlayerEndCombatPacket) register(0x43, ClientboundPlayerEnterCombatPacket) register(0x44, ClientboundPlayerCombatDeathPacket) register(0x45, ClientboundPlayerInfoRemovePacket) -// register(0x46, ClientboundPlayerInfoUpdatePacket) + register(0x46, ClientboundPlayerInfoUpdatePacket) register(0x47, ClientboundPlayerLookAtPacket) register(0x48, ClientboundSynchronizePlayerPositionPacket) register(0x49, ClientboundPlayerRotationPacket) -// register(0x4a, ClientboundRecipeBookAddPacket) -// register(0x4b, ClientboundRecipeBookRemovePacket) -// register(0x4c, ClientboundRecipeBookSettingsPacket) - register(0x4d, ClientboundRemoveEntitiesPacket) - register(0x4e, ClientboundRemoveEntityEffectPacket) - register(0x4f, ClientboundResetScorePacket) +// register(0x4A, ClientboundRecipeBookAddPacket) +// register(0x4B, ClientboundRecipeBookRemovePacket) +// register(0x4C, ClientboundRecipeBookSettingsPacket) + register(0x4D, ClientboundRemoveEntitiesPacket) + register(0x4E, ClientboundRemoveEntityEffectPacket) + register(0x4F, ClientboundResetScorePacket) register(0x50, ClientboundRemoveResourcePackPacket) register(0x51, ClientboundAddResourcePackPacket) register(0x52, ClientboundRespawnPacket) @@ -150,12 +150,12 @@ internal object GamePacketsProtocolCodec { register(0x57, ClientboundSetActionBarTextPacket) register(0x58, ClientboundSetBorderCenterPacket) register(0x59, ClientboundSetBorderLeapSizePacket) - register(0x5a, ClientboundSetBorderSizePacket) - register(0x5b, ClientboundSetBorderWarningDelayPacket) - register(0x5c, ClientboundSetBorderWarningDistancePacket) - register(0x5d, ClientboundSetCameraPacket) - register(0x5e, ClientboundSetCenterChunkPacket) - register(0x5f, ClientboundSetRenderDistancePacket) + register(0x5A, ClientboundSetBorderSizePacket) + register(0x5B, ClientboundSetBorderWarningDelayPacket) + register(0x5C, ClientboundSetBorderWarningDistancePacket) + register(0x5D, ClientboundSetCameraPacket) + register(0x5E, ClientboundSetCenterChunkPacket) + register(0x5F, ClientboundSetRenderDistancePacket) // register(0x60, ClientboundSetCursorItemPacket) register(0x61, ClientboundSetDefaultSpawnPositionPacket) register(0x62, ClientboundSetDisplayObjectivePacket) @@ -166,12 +166,12 @@ internal object GamePacketsProtocolCodec { register(0x67, ClientboundSetExperiencePacket) register(0x68, ClientboundSetHealthPacket) register(0x69, ClientboundSetCarriedItemPacket) - register(0x6a, ClientboundUpdateObjectivePacket) - register(0x6b, ClientboundSetPassengersPacket) -// register(0x6c, ClientboundSetPlayerInventorySlotPacket) -// register(0x6d, ClientboundSetPlayerTeamPacket) - register(0x6e, ClientboundUpdateScorePacket) - register(0x6f, ClientboundSetSimulationDistancePacket) + register(0x6A, ClientboundUpdateObjectivePacket) + register(0x6B, ClientboundSetPassengersPacket) +// register(0x6C, ClientboundSetPlayerInventorySlotPacket) +// register(0x6D, ClientboundSetPlayerTeamPacket) + register(0x6E, ClientboundUpdateScorePacket) + register(0x6F, ClientboundSetSimulationDistancePacket) register(0x70, ClientboundSetSubtitleTextPacket) register(0x71, ClientboundSetTimePacket) register(0x72, ClientboundSetTitleTextPacket) @@ -182,12 +182,12 @@ internal object GamePacketsProtocolCodec { register(0x77, ClientboundStopSoundPacket) register(0x78, ClientboundStoreCookiePacket) register(0x79, ClientboundSystemChatMessagePacket) - register(0x7a, ClientboundSetTabListHeaderAndFooterPacket) - register(0x7b, ClientboundTagQueryResponsePacket) - register(0x7c, ClientboundPickupItemPacket) - register(0x7d, ClientboundSynchronizeVehiclePositionPacket) - register(0x7e, ClientboundTestInstanceBlockStatusPacket) - register(0x7f, ClientboundSetTickingStatePacket) + register(0x7A, ClientboundSetTabListHeaderAndFooterPacket) + register(0x7B, ClientboundTagQueryResponsePacket) + register(0x7C, ClientboundPickupItemPacket) + register(0x7D, ClientboundSynchronizeVehiclePositionPacket) + register(0x7E, ClientboundTestInstanceBlockStatusPacket) + register(0x7F, ClientboundSetTickingStatePacket) register(0x80, ClientboundStepTickPacket) register(0x81, ClientboundTransferPacket) // register(0x82, ClientboundUpdateAdvancementsPacket) @@ -198,9 +198,9 @@ internal object GamePacketsProtocolCodec { register(0x87, ClientboundProjectilePowerPacket) register(0x88, ClientboundCustomReportDetailsPacket) register(0x89, ClientboundServerLinksPacket) - register(0x8a, ClientboundWaypointPacket) - register(0x8b, ClientboundClearDialogPacket) - register(0x8c, ClientboundShowDialogPacket) + register(0x8A, ClientboundWaypointPacket) + register(0x8B, ClientboundClearDialogPacket) + register(0x8C, ClientboundShowDialogPacket) } } @@ -241,12 +241,12 @@ internal object GamePacketsProtocolCodec { register(0x07, ServerboundChatCommandPacket) register(0x08, ServerboundSignedChatCommandPacket) register(0x09, ServerboundChatMessagePacket) - register(0x0a, ServerboundUpdateChatSessionPacket) - register(0x0b, ServerboundChunkBatchReceivedPacket) - register(0x0c, ServerboundClientCommandPacket) - register(0x0d, ServerboundClientTickEndPacket) - register(0x0e, ServerboundClientInformationPacket) - register(0x0f, ServerboundCommandSuggestionRequestPacket) + register(0x0A, ServerboundUpdateChatSessionPacket) + register(0x0B, ServerboundChunkBatchReceivedPacket) + register(0x0C, ServerboundClientCommandPacket) + register(0x0D, ServerboundClientTickEndPacket) + register(0x0E, ServerboundClientInformationPacket) + register(0x0F, ServerboundCommandSuggestionRequestPacket) register(0x10, ServerboundConfigurationAcknowledgedPacket) register(0x11, ServerboundContainerClickButtonPacket) // register(0x12, ServerboundContainerClickPacket) @@ -257,12 +257,12 @@ internal object GamePacketsProtocolCodec { // register(0x17, ServerboundDebugSubscriptionRequestPacket) register(0x18, ServerboundEditBookPacket) register(0x19, ServerboundQueryEntityTagPacket) - register(0x1a, ServerboundInteractPacket) - register(0x1b, ServerboundJigsawGeneratePacket) - register(0x1c, ServerboundKeepAlivePlayPacket) - register(0x1d, ServerboundLockDifficultyPacket) - register(0x1e, ServerboundSetPlayerPositionPacket) - register(0x1f, ServerboundSetPlayerPositionAndRotationPacket) + register(0x1A, ServerboundInteractPacket) + register(0x1B, ServerboundJigsawGeneratePacket) + register(0x1C, ServerboundKeepAlivePlayPacket) + register(0x1D, ServerboundLockDifficultyPacket) + register(0x1E, ServerboundSetPlayerPositionPacket) + register(0x1F, ServerboundSetPlayerPositionAndRotationPacket) register(0x20, ServerboundSetPlayerRotationPacket) register(0x21, ServerboundSetPlayerMovementFlagPacket) register(0x22, ServerboundMoveVehiclePacket) @@ -273,12 +273,12 @@ internal object GamePacketsProtocolCodec { register(0x27, ServerboundPlaceRecipePacket) register(0x28, ServerboundPlayerAbilitiesPacket) register(0x29, ServerboundPlayerActionPacket) - register(0x2a, ServerboundPlayerCommandPacket) - register(0x2b, ServerboundPlayerInputPacket) - register(0x2c, ServerboundPlayerLoadedPacket) - register(0x2d, ServerboundPongPlayPacket) - register(0x2e, ServerboundRecipeBookChangeSettingsPacket) - register(0x2f, ServerboundRecipeBookSeenRecipePacket) + register(0x2A, ServerboundPlayerCommandPacket) + register(0x2B, ServerboundPlayerInputPacket) + register(0x2C, ServerboundPlayerLoadedPacket) + register(0x2D, ServerboundPongPlayPacket) + register(0x2E, ServerboundRecipeBookChangeSettingsPacket) + register(0x2F, ServerboundRecipeBookSeenRecipePacket) register(0x30, ServerboundRenameItemPacket) register(0x31, ServerboundResourcePackResponsePacket) register(0x32, ServerboundSeenAdvancementsPacket) @@ -289,12 +289,12 @@ internal object GamePacketsProtocolCodec { register(0x37, ServerboundSetCommandMinecartPacket) // register(0x38, ServerboundSetCreativeModeSlotPacket) register(0x39, ServerboundSetGameRulePacket) - register(0x3a, ServerboundSetJigsawBlockPacket) - register(0x3b, ServerboundSetStructureBlockPacket) - register(0x3c, ServerboundSetTestBlockPacket) - register(0x3d, ServerboundSignUpdatePacket) - register(0x3e, ServerboundSpectatorActionPacket) - register(0x3f, ServerboundSwingPacket) + register(0x3A, ServerboundSetJigsawBlockPacket) + register(0x3B, ServerboundSetStructureBlockPacket) + register(0x3C, ServerboundSetTestBlockPacket) + register(0x3D, ServerboundSignUpdatePacket) + register(0x3E, ServerboundSpectatorActionPacket) + register(0x3F, ServerboundSwingPacket) register(0x40, ServerboundTeleportToEntityPacket) register(0x41, ServerboundTestInstanceBlockActionPacket) register(0x42, ServerboundUseItemOnPacket) diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/PlayerActionStatus.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerActionStatus.kt similarity index 88% rename from libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/PlayerActionStatus.kt rename to libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerActionStatus.kt index da9e2f0..801c78f 100644 --- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/PlayerActionStatus.kt +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerActionStatus.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.libmc.protocol.protocol.game.player +package cn.rtast.libmc.protocol.protocol.game.player.action public enum class PlayerActionStatus(public val id: Int) { STARTED_DIGGING(0), diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/PlayerCommandAction.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerCommandAction.kt similarity index 88% rename from libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/PlayerCommandAction.kt rename to libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerCommandAction.kt index 5dcb5c1..b745daf 100644 --- a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/PlayerCommandAction.kt +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerCommandAction.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.libmc.protocol.protocol.game.player +package cn.rtast.libmc.protocol.protocol.game.player.action public enum class PlayerCommandAction(public val id: Int) { LEAVE_BED(0), diff --git a/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerUpdateInfoAction.kt b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerUpdateInfoAction.kt new file mode 100644 index 0000000..e6e443b --- /dev/null +++ b/libmc-protocol/src/commonMain/kotlin/cn/rtast/libmc/protocol/protocol/game/player/action/PlayerUpdateInfoAction.kt @@ -0,0 +1,79 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/7 + */ + + +package cn.rtast.libmc.protocol.protocol.game.player.action + +import cn.rtast.libmc.protocol.protocol.game.chat.TextComponent +import cn.rtast.libmc.protocol.protocol.game.session.GameProfile +import kotlin.uuid.Uuid + +public enum class PlayerUpdateInfoAction(public val mask: Int) { + ADD_PLAYER(0x01), + INITIALIZE_CHAT(0x02), + UPDATE_GAME_MODE(0x04), + UPDATE_LISTED(0x08), + UPDATE_LATENCY(0x10), + UPDATE_DISPLAY_NAME(0x20), + UPDATE_LIST_PRIORITY(0x40), + UPDATE_HAT(0x80); + + public companion object { + public fun parseActions(mask: Int): Set { + val set = HashSet() + for (action in entries) if ((mask and action.mask) != 0) set.add(action) + return set + } + + public fun toMask(actions: Set): Int { + var mask = 0 + for (action in actions) mask = mask or action.mask + return mask + } + } +} + +public sealed class SinglePlayerAction { + public data class AddPlayer(val name: String, val properties: List) : SinglePlayerAction() + + public data class InitializeChat( + val sessionId: Uuid?, + val keyExpiryTime: Long?, + val encodedPublicKey: ByteArray?, + val publicKeySignature: ByteArray?, + ) : SinglePlayerAction() { + val hasSignatureData: Boolean get() = sessionId != null + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + other as InitializeChat + if (keyExpiryTime != other.keyExpiryTime) return false + if (sessionId != other.sessionId) return false + if (!encodedPublicKey.contentEquals(other.encodedPublicKey)) return false + if (!publicKeySignature.contentEquals(other.publicKeySignature)) return false + if (hasSignatureData != other.hasSignatureData) return false + return true + } + + override fun hashCode(): Int { + var result = keyExpiryTime.hashCode() + result = 31 * result + sessionId.hashCode() + result = 31 * result + (encodedPublicKey?.contentHashCode() ?: 0) + result = 31 * result + (publicKeySignature?.contentHashCode() ?: 0) + result = 31 * result + hasSignatureData.hashCode() + return result + } + } + + public data class UpdateGameMode(val gameMode: Int) : SinglePlayerAction() + public data class UpdateListed(val listed: Boolean) : SinglePlayerAction() + public data class UpdateLatency(val ping: Int) : SinglePlayerAction() + public data class UpdateDisplayName(val displayName: TextComponent?) : SinglePlayerAction() + public data class UpdateListPriority(val priority: Int) : SinglePlayerAction() + public data class UpdateHat(val visible: Boolean) : SinglePlayerAction() +} + +public data class PlayerInfoUpdateEntry(val uuid: Uuid, val actions: List) \ No newline at end of file diff --git a/libmc-protocol/src/jvmTest/kotlin/test/TestClientTestInJvm.kt b/libmc-protocol/src/jvmTest/kotlin/test/TestClientTestInJvm.kt index 183d150..9dd9e1b 100644 --- a/libmc-protocol/src/jvmTest/kotlin/test/TestClientTestInJvm.kt +++ b/libmc-protocol/src/jvmTest/kotlin/test/TestClientTestInJvm.kt @@ -7,12 +7,11 @@ package test +import cn.rtast.libmc.packet.ClientboundUnknownPacket import cn.rtast.libmc.protocol.client.createMinecraftClient import cn.rtast.libmc.protocol.crypto.DefaultProtocolContext -import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundCommandsPacket -import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundDisconnectPlayPacket -import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundDisguisedChatMessagePacket -import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundSystemChatMessagePacket +import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayerInfoUpdatePacket +import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundWaypointPacket import cn.rtast.libmc.protocol.util.generateOfflineUuid import kotlinx.coroutines.launch import org.junit.Test @@ -81,8 +80,12 @@ class TestClientTestInJvm { null, crypto = DefaultProtocolContext ) - cli.on { packet, direction -> println("$direction -> $packet") } -// cli.onPacket { println(it.content.content) } +// cli.on { packet, direction -> +// if (packet !is ClientboundWaypointPacket) +// println("$direction -> $packet") +// } +// cli.onPacket { println(it) } + cli.onPacket { println(it) } cli.launch { cli.connect() } while (true) { }