diff --git a/pom.xml b/pom.xml index 247c16dc..a2c064e9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 mcprotocollib - 1.19.2-1 + 1.19.3-SNAPSHOT jar MCProtocolLib diff --git a/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java b/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java index e01e35d6..94c5ea29 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java +++ b/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java @@ -35,6 +35,7 @@ import lombok.NonNull; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.NoSuchAlgorithmException; +import java.util.UUID; /** * Handles making initial login and status requests for clients. @@ -80,7 +81,7 @@ public class ClientListener extends SessionAdapter { return; } - session.send(new ServerboundKeyPacket(helloPacket.getPublicKey(), key, helloPacket.getVerifyToken())); + session.send(new ServerboundKeyPacket(helloPacket.getPublicKey(), key, helloPacket.getChallenge())); session.enableEncryption(protocol.enableEncryption(key)); } else if (packet instanceof ClientboundGameProfilePacket) { protocol.setState(ProtocolState.GAME); @@ -125,7 +126,7 @@ public class ClientListener extends SessionAdapter { if (this.targetState == ProtocolState.LOGIN) { GameProfile profile = session.getFlag(MinecraftConstants.PROFILE_KEY); - session.send(new ServerboundHelloPacket(profile.getName(), null, profile.getId())); + session.send(new ServerboundHelloPacket(profile.getName(), profile.getId())); } else { session.send(new ServerboundStatusRequestPacket()); } diff --git a/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java b/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java index abb0a7e9..3f27b22f 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java +++ b/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java @@ -55,15 +55,14 @@ public class ServerListener extends SessionAdapter { } } - private final byte[] verifyToken = new byte[4]; + private final byte[] challenge = new byte[4]; private String username = ""; - private ServerboundHelloPacket.ProfilePublicKeyData profilePublicKeyData; private long lastPingTime = 0; private int lastPingId = 0; public ServerListener() { - new Random().nextBytes(this.verifyToken); + new Random().nextBytes(this.challenge); } @Override @@ -99,10 +98,9 @@ public class ServerListener extends SessionAdapter { if (protocol.getState() == ProtocolState.LOGIN) { if (packet instanceof ServerboundHelloPacket) { this.username = ((ServerboundHelloPacket) packet).getUsername(); - this.profilePublicKeyData = ((ServerboundHelloPacket) packet).getPublicKey(); if (session.getFlag(MinecraftConstants.VERIFY_USERS_KEY, true)) { - session.send(new ClientboundHelloPacket(SERVER_ID, KEY_PAIR.getPublic(), this.verifyToken)); + session.send(new ClientboundHelloPacket(SERVER_ID, KEY_PAIR.getPublic(), this.challenge)); } else { new Thread(new UserAuthTask(session, null)).start(); } @@ -110,16 +108,9 @@ public class ServerListener extends SessionAdapter { ServerboundKeyPacket keyPacket = (ServerboundKeyPacket) packet; PrivateKey privateKey = KEY_PAIR.getPrivate(); - if (this.profilePublicKeyData != null) { - if (!keyPacket.verifyWithSaltSignature(this.verifyToken, this.profilePublicKeyData)) { - session.disconnect("Invalid profile key setup!"); - return; - } - } else { - if (!Arrays.equals(this.verifyToken, keyPacket.getVerifyToken(privateKey))) { - session.disconnect("Invalid nonce!"); - return; - } + if (!Arrays.equals(this.challenge, keyPacket.getEncryptedChallenge(privateKey))) { + session.disconnect("Invalid challenge!"); + return; } SecretKey key = keyPacket.getSecretKey(privateKey); diff --git a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java index 08e166a1..9e7ab48f 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java +++ b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java @@ -7,7 +7,6 @@ import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientInte import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundAwardStatsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundBossEventPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundChangeDifficultyPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundChatPreviewPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCommandSuggestionsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCommandsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCooldownPacket; @@ -15,24 +14,25 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCu import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDeleteChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDisconnectPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDisguisedChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundKeepAlivePacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPingPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerChatHeaderPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoRemovePacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoUpdatePacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRecipePacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundResourcePackPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRespawnPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSelectAdvancementsTabPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundServerDataPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSetCameraPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSetDisplayChatPreviewPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSoundEntityPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundStopSoundPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateAdvancementsPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateEnabledFeaturesPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateRecipesPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateTagsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundAnimatePacket; @@ -79,7 +79,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.Clientb import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEntityDataPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockUpdatePacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundCustomSoundPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundForgetLevelChunkPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundGameEventPacket; @@ -116,7 +115,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCh import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatAckPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPreviewPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatSessionUpdatePacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCommandSuggestionPacket; @@ -196,9 +195,9 @@ public class MinecraftCodec { } public static final PacketCodec CODEC = PacketCodec.builder() - .protocolVersion(760) + .protocolVersion(761) .helper(() -> new MinecraftCodecHelper(LEVEL_EVENTS, SOUND_NAMES)) - .minecraftVersion("1.19.1") + .minecraftVersion("1.19.3") .state(ProtocolState.HANDSHAKE, PacketStateCodec.builder() .registerServerboundPacket(0x00, ClientIntentionPacket.class, ClientIntentionPacket::new) ) @@ -229,135 +228,134 @@ public class MinecraftCodec { .registerClientboundPacket(0x09, ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new) .registerClientboundPacket(0x0A, ClientboundBossEventPacket.class, ClientboundBossEventPacket::new) .registerClientboundPacket(0x0B, ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new) - .registerClientboundPacket(0x0C, ClientboundChatPreviewPacket.class, ClientboundChatPreviewPacket::new) - .registerClientboundPacket(0x0D, ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new) - .registerClientboundPacket(0x0E, ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new) - .registerClientboundPacket(0x0F, ClientboundCommandsPacket.class, ClientboundCommandsPacket::new) - .registerClientboundPacket(0x10, ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new) - .registerClientboundPacket(0x11, ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new) - .registerClientboundPacket(0x12, ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new) - .registerClientboundPacket(0x13, ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new) - .registerClientboundPacket(0x14, ClientboundCooldownPacket.class, ClientboundCooldownPacket::new) - .registerClientboundPacket(0x15, ClientboundCustomChatCompletionsPacket.class, ClientboundCustomChatCompletionsPacket::new) - .registerClientboundPacket(0x16, ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new) - .registerClientboundPacket(0x17, ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new) - .registerClientboundPacket(0x18, ClientboundDeleteChatPacket.class, ClientboundDeleteChatPacket::new) - .registerClientboundPacket(0x19, ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new) - .registerClientboundPacket(0x1A, ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new) - .registerClientboundPacket(0x1B, ClientboundExplodePacket.class, ClientboundExplodePacket::new) - .registerClientboundPacket(0x1C, ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new) - .registerClientboundPacket(0x1D, ClientboundGameEventPacket.class, ClientboundGameEventPacket::new) - .registerClientboundPacket(0x1E, ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new) - .registerClientboundPacket(0x1F, ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new) - .registerClientboundPacket(0x20, ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new) - .registerClientboundPacket(0x21, ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new) - .registerClientboundPacket(0x22, ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new) - .registerClientboundPacket(0x23, ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new) - .registerClientboundPacket(0x24, ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new) - .registerClientboundPacket(0x25, ClientboundLoginPacket.class, ClientboundLoginPacket::new) - .registerClientboundPacket(0x26, ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new) - .registerClientboundPacket(0x27, ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new) - .registerClientboundPacket(0x28, ClientboundMoveEntityPosPacket.class, ClientboundMoveEntityPosPacket::new) - .registerClientboundPacket(0x29, ClientboundMoveEntityPosRotPacket.class, ClientboundMoveEntityPosRotPacket::new) - .registerClientboundPacket(0x2A, ClientboundMoveEntityRotPacket.class, ClientboundMoveEntityRotPacket::new) - .registerClientboundPacket(0x2B, ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new) - .registerClientboundPacket(0x2C, ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new) - .registerClientboundPacket(0x2D, ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new) - .registerClientboundPacket(0x2E, ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new) - .registerClientboundPacket(0x2F, ClientboundPingPacket.class, ClientboundPingPacket::new) - .registerClientboundPacket(0x30, ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new) - .registerClientboundPacket(0x31, ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new) - .registerClientboundPacket(0x32, ClientboundPlayerChatHeaderPacket.class, ClientboundPlayerChatHeaderPacket::new) - .registerClientboundPacket(0x33, ClientboundPlayerChatPacket.class, ClientboundPlayerChatPacket::new) - .registerClientboundPacket(0x34, ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new) - .registerClientboundPacket(0x35, ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new) - .registerClientboundPacket(0x36, ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new) - .registerClientboundPacket(0x37, ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new) - .registerClientboundPacket(0x38, ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new) - .registerClientboundPacket(0x39, ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new) - .registerClientboundPacket(0x3A, ClientboundRecipePacket.class, ClientboundRecipePacket::new) - .registerClientboundPacket(0x3B, ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new) - .registerClientboundPacket(0x3C, ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new) - .registerClientboundPacket(0x3D, ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new) - .registerClientboundPacket(0x3E, ClientboundRespawnPacket.class, ClientboundRespawnPacket::new) - .registerClientboundPacket(0x3F, ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new) - .registerClientboundPacket(0x40, ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new) - .registerClientboundPacket(0x41, ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new) - .registerClientboundPacket(0x42, ClientboundServerDataPacket.class, ClientboundServerDataPacket::new) - .registerClientboundPacket(0x43, ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new) - .registerClientboundPacket(0x44, ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new) - .registerClientboundPacket(0x45, ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new) - .registerClientboundPacket(0x46, ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new) - .registerClientboundPacket(0x47, ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new) - .registerClientboundPacket(0x48, ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new) - .registerClientboundPacket(0x49, ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new) - .registerClientboundPacket(0x4A, ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new) - .registerClientboundPacket(0x4B, ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new) - .registerClientboundPacket(0x4C, ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new) - .registerClientboundPacket(0x4D, ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new) - .registerClientboundPacket(0x4E, ClientboundSetDisplayChatPreviewPacket.class, ClientboundSetDisplayChatPreviewPacket::new) - .registerClientboundPacket(0x4F, ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new) - .registerClientboundPacket(0x50, ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new) - .registerClientboundPacket(0x51, ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new) - .registerClientboundPacket(0x52, ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new) - .registerClientboundPacket(0x53, ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new) - .registerClientboundPacket(0x54, ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new) - .registerClientboundPacket(0x55, ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new) - .registerClientboundPacket(0x56, ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new) - .registerClientboundPacket(0x57, ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new) - .registerClientboundPacket(0x58, ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new) - .registerClientboundPacket(0x59, ClientboundSetScorePacket.class, ClientboundSetScorePacket::new) - .registerClientboundPacket(0x5A, ClientboundSetSimulationDistancePacket.class, ClientboundSetSimulationDistancePacket::new) - .registerClientboundPacket(0x5B, ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new) - .registerClientboundPacket(0x5C, ClientboundSetTimePacket.class, ClientboundSetTimePacket::new) - .registerClientboundPacket(0x5D, ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new) - .registerClientboundPacket(0x5E, ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new) - .registerClientboundPacket(0x5F, ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new) - .registerClientboundPacket(0x60, ClientboundSoundPacket.class, ClientboundSoundPacket::new) - .registerClientboundPacket(0x61, ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new) - .registerClientboundPacket(0x62, ClientboundSystemChatPacket.class, ClientboundSystemChatPacket::new) - .registerClientboundPacket(0x63, ClientboundTabListPacket.class, ClientboundTabListPacket::new) - .registerClientboundPacket(0x64, ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new) - .registerClientboundPacket(0x65, ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new) - .registerClientboundPacket(0x66, ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new) - .registerClientboundPacket(0x67, ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new) - .registerClientboundPacket(0x68, ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new) - .registerClientboundPacket(0x69, ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new) - .registerClientboundPacket(0x6A, ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new) - .registerClientboundPacket(0x6B, ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new) + .registerClientboundPacket(0x0C, ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new) + .registerClientboundPacket(0x0D, ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new) + .registerClientboundPacket(0x0E, ClientboundCommandsPacket.class, ClientboundCommandsPacket::new) + .registerClientboundPacket(0x0F, ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new) + .registerClientboundPacket(0x10, ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new) + .registerClientboundPacket(0x11, ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new) + .registerClientboundPacket(0x12, ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new) + .registerClientboundPacket(0x13, ClientboundCooldownPacket.class, ClientboundCooldownPacket::new) + .registerClientboundPacket(0x14, ClientboundCustomChatCompletionsPacket.class, ClientboundCustomChatCompletionsPacket::new) + .registerClientboundPacket(0x15, ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new) + .registerClientboundPacket(0x16, ClientboundDeleteChatPacket.class, ClientboundDeleteChatPacket::new) + .registerClientboundPacket(0x17, ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new) + .registerClientboundPacket(0x18, ClientboundDisguisedChatPacket.class, ClientboundDisguisedChatPacket::new) + .registerClientboundPacket(0x19, ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new) + .registerClientboundPacket(0x1A, ClientboundExplodePacket.class, ClientboundExplodePacket::new) + .registerClientboundPacket(0x1B, ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new) + .registerClientboundPacket(0x1C, ClientboundGameEventPacket.class, ClientboundGameEventPacket::new) + .registerClientboundPacket(0x1D, ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new) + .registerClientboundPacket(0x1E, ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new) + .registerClientboundPacket(0x1F, ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new) + .registerClientboundPacket(0x20, ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new) + .registerClientboundPacket(0x21, ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new) + .registerClientboundPacket(0x22, ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new) + .registerClientboundPacket(0x23, ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new) + .registerClientboundPacket(0x24, ClientboundLoginPacket.class, ClientboundLoginPacket::new) + .registerClientboundPacket(0x25, ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new) + .registerClientboundPacket(0x26, ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new) + .registerClientboundPacket(0x27, ClientboundMoveEntityPosPacket.class, ClientboundMoveEntityPosPacket::new) + .registerClientboundPacket(0x28, ClientboundMoveEntityPosRotPacket.class, ClientboundMoveEntityPosRotPacket::new) + .registerClientboundPacket(0x29, ClientboundMoveEntityRotPacket.class, ClientboundMoveEntityRotPacket::new) + .registerClientboundPacket(0x2A, ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new) + .registerClientboundPacket(0x2B, ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new) + .registerClientboundPacket(0x2C, ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new) + .registerClientboundPacket(0x2D, ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new) + .registerClientboundPacket(0x2E, ClientboundPingPacket.class, ClientboundPingPacket::new) + .registerClientboundPacket(0x2F, ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new) + .registerClientboundPacket(0x30, ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new) + .registerClientboundPacket(0x31, ClientboundPlayerChatPacket.class, ClientboundPlayerChatPacket::new) + .registerClientboundPacket(0x32, ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new) + .registerClientboundPacket(0x33, ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new) + .registerClientboundPacket(0x34, ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new) + .registerClientboundPacket(0x35, ClientboundPlayerInfoRemovePacket.class, ClientboundPlayerInfoRemovePacket::new) + .registerClientboundPacket(0x36, ClientboundPlayerInfoUpdatePacket.class, ClientboundPlayerInfoUpdatePacket::new) + .registerClientboundPacket(0x37, ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new) + .registerClientboundPacket(0x38, ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new) + .registerClientboundPacket(0x39, ClientboundRecipePacket.class, ClientboundRecipePacket::new) + .registerClientboundPacket(0x3A, ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new) + .registerClientboundPacket(0x3B, ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new) + .registerClientboundPacket(0x3C, ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new) + .registerClientboundPacket(0x3D, ClientboundRespawnPacket.class, ClientboundRespawnPacket::new) + .registerClientboundPacket(0x3E, ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new) + .registerClientboundPacket(0x3F, ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new) + .registerClientboundPacket(0x40, ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new) + .registerClientboundPacket(0x41, ClientboundServerDataPacket.class, ClientboundServerDataPacket::new) + .registerClientboundPacket(0x42, ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new) + .registerClientboundPacket(0x43, ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new) + .registerClientboundPacket(0x44, ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new) + .registerClientboundPacket(0x45, ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new) + .registerClientboundPacket(0x46, ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new) + .registerClientboundPacket(0x47, ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new) + .registerClientboundPacket(0x48, ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new) + .registerClientboundPacket(0x49, ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new) + .registerClientboundPacket(0x4A, ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new) + .registerClientboundPacket(0x4B, ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new) + .registerClientboundPacket(0x4C, ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new) + .registerClientboundPacket(0x4D, ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new) + .registerClientboundPacket(0x4E, ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new) + .registerClientboundPacket(0x4F, ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new) + .registerClientboundPacket(0x50, ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new) + .registerClientboundPacket(0x51, ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new) + .registerClientboundPacket(0x52, ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new) + .registerClientboundPacket(0x53, ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new) + .registerClientboundPacket(0x54, ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new) + .registerClientboundPacket(0x55, ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new) + .registerClientboundPacket(0x56, ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new) + .registerClientboundPacket(0x57, ClientboundSetScorePacket.class, ClientboundSetScorePacket::new) + .registerClientboundPacket(0x58, ClientboundSetSimulationDistancePacket.class, ClientboundSetSimulationDistancePacket::new) + .registerClientboundPacket(0x59, ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new) + .registerClientboundPacket(0x5A, ClientboundSetTimePacket.class, ClientboundSetTimePacket::new) + .registerClientboundPacket(0x5B, ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new) + .registerClientboundPacket(0x5C, ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new) + .registerClientboundPacket(0x5D, ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new) + .registerClientboundPacket(0x5E, ClientboundSoundPacket.class, ClientboundSoundPacket::new) + .registerClientboundPacket(0x5F, ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new) + .registerClientboundPacket(0x60, ClientboundSystemChatPacket.class, ClientboundSystemChatPacket::new) + .registerClientboundPacket(0x61, ClientboundTabListPacket.class, ClientboundTabListPacket::new) + .registerClientboundPacket(0x62, ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new) + .registerClientboundPacket(0x63, ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new) + .registerClientboundPacket(0x64, ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new) + .registerClientboundPacket(0x65, ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new) + .registerClientboundPacket(0x66, ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new) + .registerClientboundPacket(0x67, ClientboundUpdateEnabledFeaturesPacket.class, ClientboundUpdateEnabledFeaturesPacket::new) + .registerClientboundPacket(0x68, ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new) + .registerClientboundPacket(0x69, ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new) + .registerClientboundPacket(0x6A, ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new) .registerServerboundPacket(0x00, ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new) .registerServerboundPacket(0x01, ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new) .registerServerboundPacket(0x02, ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new) .registerServerboundPacket(0x03, ServerboundChatAckPacket.class, ServerboundChatAckPacket::new) .registerServerboundPacket(0x04, ServerboundChatCommandPacket.class, ServerboundChatCommandPacket::new) .registerServerboundPacket(0x05, ServerboundChatPacket.class, ServerboundChatPacket::new) - .registerServerboundPacket(0x06, ServerboundChatPreviewPacket.class, ServerboundChatPreviewPacket::new) - .registerServerboundPacket(0x07, ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new) - .registerServerboundPacket(0x08, ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new) - .registerServerboundPacket(0x09, ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new) - .registerServerboundPacket(0x0A, ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new) - .registerServerboundPacket(0x0B, ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new) - .registerServerboundPacket(0x0C, ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new) - .registerServerboundPacket(0x0D, ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new) - .registerServerboundPacket(0x0E, ServerboundEditBookPacket.class, ServerboundEditBookPacket::new) - .registerServerboundPacket(0x0F, ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new) - .registerServerboundPacket(0x10, ServerboundInteractPacket.class, ServerboundInteractPacket::new) - .registerServerboundPacket(0x11, ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new) - .registerServerboundPacket(0x12, ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new) - .registerServerboundPacket(0x13, ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new) - .registerServerboundPacket(0x14, ServerboundMovePlayerPosPacket.class, ServerboundMovePlayerPosPacket::new) - .registerServerboundPacket(0x15, ServerboundMovePlayerPosRotPacket.class, ServerboundMovePlayerPosRotPacket::new) - .registerServerboundPacket(0x16, ServerboundMovePlayerRotPacket.class, ServerboundMovePlayerRotPacket::new) - .registerServerboundPacket(0x17, ServerboundMovePlayerStatusOnlyPacket.class, ServerboundMovePlayerStatusOnlyPacket::new) - .registerServerboundPacket(0x18, ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new) - .registerServerboundPacket(0x19, ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new) - .registerServerboundPacket(0x1A, ServerboundPickItemPacket.class, ServerboundPickItemPacket::new) - .registerServerboundPacket(0x1B, ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new) - .registerServerboundPacket(0x1C, ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new) - .registerServerboundPacket(0x1D, ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new) - .registerServerboundPacket(0x1E, ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new) - .registerServerboundPacket(0x1F, ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new) - .registerServerboundPacket(0x20, ServerboundPongPacket.class, ServerboundPongPacket::new) + .registerServerboundPacket(0x06, ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new) + .registerServerboundPacket(0x07, ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new) + .registerServerboundPacket(0x08, ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new) + .registerServerboundPacket(0x09, ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new) + .registerServerboundPacket(0x0A, ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new) + .registerServerboundPacket(0x0B, ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new) + .registerServerboundPacket(0x0C, ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new) + .registerServerboundPacket(0x0D, ServerboundEditBookPacket.class, ServerboundEditBookPacket::new) + .registerServerboundPacket(0x0E, ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new) + .registerServerboundPacket(0x0F, ServerboundInteractPacket.class, ServerboundInteractPacket::new) + .registerServerboundPacket(0x10, ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new) + .registerServerboundPacket(0x11, ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new) + .registerServerboundPacket(0x12, ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new) + .registerServerboundPacket(0x13, ServerboundMovePlayerPosPacket.class, ServerboundMovePlayerPosPacket::new) + .registerServerboundPacket(0x14, ServerboundMovePlayerPosRotPacket.class, ServerboundMovePlayerPosRotPacket::new) + .registerServerboundPacket(0x15, ServerboundMovePlayerRotPacket.class, ServerboundMovePlayerRotPacket::new) + .registerServerboundPacket(0x16, ServerboundMovePlayerStatusOnlyPacket.class, ServerboundMovePlayerStatusOnlyPacket::new) + .registerServerboundPacket(0x17, ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new) + .registerServerboundPacket(0x18, ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new) + .registerServerboundPacket(0x19, ServerboundPickItemPacket.class, ServerboundPickItemPacket::new) + .registerServerboundPacket(0x1A, ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new) + .registerServerboundPacket(0x1B, ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new) + .registerServerboundPacket(0x1C, ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new) + .registerServerboundPacket(0x1D, ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new) + .registerServerboundPacket(0x1E, ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new) + .registerServerboundPacket(0x1F, ServerboundPongPacket.class, ServerboundPongPacket::new) + .registerServerboundPacket(0x20, ServerboundChatSessionUpdatePacket.class, ServerboundChatSessionUpdatePacket::new) .registerServerboundPacket(0x21, ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new) .registerServerboundPacket(0x22, ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new) .registerServerboundPacket(0x23, ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new) diff --git a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java index 9acbef40..fe092df7 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java +++ b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java @@ -1,5 +1,6 @@ package com.github.steveice10.mc.protocol.codec; +import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; import com.github.steveice10.mc.protocol.data.MagicValues; import com.github.steveice10.mc.protocol.data.game.Identifier; @@ -24,6 +25,8 @@ import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.PositionSource; import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.PositionSourceType; import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound; +import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound; +import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; import com.github.steveice10.mc.protocol.data.game.level.sound.SoundCategory; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.statistic.StatisticCategory; @@ -44,7 +47,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.UUID; @@ -81,6 +86,14 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { } } + public String readResourceLocation(ByteBuf buf) { + return Identifier.formalize(this.readString(buf)); + } + + public void writeResourceLocation(ByteBuf buf, String location) { + this.writeString(buf, location); + } + public UUID readUUID(ByteBuf buf) { return new UUID(buf.readLong(), buf.readLong()); } @@ -280,7 +293,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { this.writeEnum(buf, type); } - private void writeEnum(ByteBuf buf, Enum e){ + private void writeEnum(ByteBuf buf, Enum e) { this.writeVarInt(buf, e.ordinal()); } @@ -592,14 +605,6 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { this.writeEnum(buf, category); } - public BuiltinSound readBuiltinSound(ByteBuf buf) { - return BuiltinSound.from(this.readVarInt(buf)); - } - - public void writeBuiltinSound(ByteBuf buf, BuiltinSound sound) { - this.writeEnum(buf, sound); - } - @Nullable public BuiltinSound getBuiltinSound(String name) { return this.soundNames.get(name); @@ -696,6 +701,85 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { this.writeDataPalette(buf, section.getBiomeData()); } + public > EnumSet readEnumSet(ByteBuf buf, E[] values) { + BitSet bitSet = this.readFixedBitSet(buf, values.length); + List readValues = new ArrayList<>(); + + for (int i = 0; i < values.length; i++) { + if (bitSet.get(i)) { + readValues.add(values[i]); + } + } + + return EnumSet.copyOf(readValues); + } + + public > void writeEnumSet(ByteBuf buf, EnumSet enumSet, E[] values) { + BitSet bitSet = new BitSet(values.length); + + for (int i = 0; i < values.length; i++) { + bitSet.set(i, enumSet.contains(values[i])); + } + + this.writeFixedBitSet(buf, bitSet, values.length); + } + + public BitSet readFixedBitSet(ByteBuf buf, int length) { + byte[] bytes = new byte[-Math.floorDiv(-length, 8)]; + buf.readBytes(bytes); + return BitSet.valueOf(bytes); + } + + public void writeFixedBitSet(ByteBuf buf, BitSet bitSet, int length) { + if (bitSet.length() > length) { + throw new IllegalArgumentException("BitSet is larger than expected size (" + bitSet.length() + " > " + length + ")"); + } else { + byte[] bytes = bitSet.toByteArray(); + buf.writeBytes(Arrays.copyOf(bytes, -Math.floorDiv(-length, 8))); + } + } + + public GameProfile.Property readProperty(ByteBuf buf) { + String name = this.readString(buf); + String value = this.readString(buf); + if (buf.readBoolean()) { + return new GameProfile.Property(name, value, this.readString(buf)); + } else { + return new GameProfile.Property(name, value); + } + } + + public void writeProperty(ByteBuf buf, GameProfile.Property property) { + this.writeString(buf, property.getName()); + this.writeString(buf, property.getValue()); + buf.writeBoolean(property.hasSignature()); + if (property.hasSignature()) { + this.writeString(buf, property.getSignature()); + } + } + + public T readById(ByteBuf buf, IntFunction registry, Function custom) { + int id = this.readVarInt(buf); + if (id == 0) { + return custom.apply(buf); + } + return registry.apply(id - 1); + } + + public CustomSound readSoundEvent(ByteBuf buf) { + String name = this.readString(buf); + boolean isNewSystem = buf.readBoolean(); + return new CustomSound(name, isNewSystem, isNewSystem ? buf.readFloat() : 16.0F); + } + + public void writeSoundEvent(ByteBuf buf, Sound soundEvent) { + writeString(buf, soundEvent.getName()); + buf.writeBoolean(soundEvent.isNewSystem()); + if (soundEvent.isNewSystem()) { + buf.writeFloat(soundEvent.getRange()); + } + } + public NibbleArray3d readNibbleArray(ByteBuf buf, int size) { return new NibbleArray3d(this.readByteArray(buf, ignored -> size)); } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java b/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java index 4fa26e9e..b65f7184 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java @@ -4,7 +4,6 @@ import com.github.steveice10.mc.protocol.data.game.BossBarAction; import com.github.steveice10.mc.protocol.data.game.BossBarColor; import com.github.steveice10.mc.protocol.data.game.BossBarDivision; import com.github.steveice10.mc.protocol.data.game.ClientCommand; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; import com.github.steveice10.mc.protocol.data.game.ResourcePackStatus; import com.github.steveice10.mc.protocol.data.game.UnlockRecipesAction; import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; @@ -156,7 +155,7 @@ public class MagicValues { register(FillStackAction.FILL, 0); - register(GameMode.UNKNOWN, 255); // https://bugs.mojang.com/browse/MC-189885 - should be -1 + register(GameMode.UNKNOWN, -1); register(GameMode.SURVIVAL, 0); register(GameMode.CREATIVE, 1); register(GameMode.ADVENTURE, 2); @@ -407,12 +406,6 @@ public class MagicValues { register(Advancement.DisplayData.FrameType.CHALLENGE, 1); register(Advancement.DisplayData.FrameType.GOAL, 2); - register(PlayerListEntryAction.ADD_PLAYER, 0); - register(PlayerListEntryAction.UPDATE_GAMEMODE, 1); - register(PlayerListEntryAction.UPDATE_LATENCY, 2); - register(PlayerListEntryAction.UPDATE_DISPLAY_NAME, 3); - register(PlayerListEntryAction.REMOVE_PLAYER, 4); - register(UnlockRecipesAction.INIT, 0); register(UnlockRecipesAction.ADD, 1); register(UnlockRecipesAction.REMOVE, 2); @@ -479,7 +472,6 @@ public class MagicValues { register(RecipeType.CRAFTING_SPECIAL_REPAIRITEM, "minecraft:crafting_special_repairitem"); register(RecipeType.CRAFTING_SPECIAL_TIPPEDARROW, "minecraft:crafting_special_tippedarrow"); register(RecipeType.CRAFTING_SPECIAL_BANNERDUPLICATE, "minecraft:crafting_special_bannerduplicate"); - register(RecipeType.CRAFTING_SPECIAL_BANNERADDPATTERN, "minecraft:crafting_special_banneraddpattern"); register(RecipeType.CRAFTING_SPECIAL_SHIELDDECORATION, "minecraft:crafting_special_shielddecoration"); register(RecipeType.CRAFTING_SPECIAL_SHULKERBOXCOLORING, "minecraft:crafting_special_shulkerboxcoloring"); register(RecipeType.CRAFTING_SPECIAL_SUSPICIOUSSTEW, "minecraft:crafting_special_suspiciousstew"); @@ -528,17 +520,17 @@ public class MagicValues { register(CommandParser.TEAM, 31); register(CommandParser.ITEM_SLOT, 32); register(CommandParser.RESOURCE_LOCATION, 33); - register(CommandParser.MOB_EFFECT, 34); - register(CommandParser.FUNCTION, 35); - register(CommandParser.ENTITY_ANCHOR, 36); - register(CommandParser.INT_RANGE, 37); - register(CommandParser.FLOAT_RANGE, 38); - register(CommandParser.ITEM_ENCHANTMENT, 39); - register(CommandParser.ENTITY_SUMMON, 40); - register(CommandParser.DIMENSION, 41); - register(CommandParser.TIME, 42); - register(CommandParser.RESOURCE_OR_TAG, 43); - register(CommandParser.RESOURCE, 44); + register(CommandParser.FUNCTION, 34); + register(CommandParser.ENTITY_ANCHOR, 35); + register(CommandParser.INT_RANGE, 36); + register(CommandParser.FLOAT_RANGE, 37); + register(CommandParser.DIMENSION, 38); + register(CommandParser.GAMEMODE, 39); + register(CommandParser.TIME, 40); + register(CommandParser.RESOURCE_OR_TAG, 41); + register(CommandParser.RESOURCE_OR_TAG_KEY, 42); + register(CommandParser.RESOURCE, 43); + register(CommandParser.RESOURCE_KEY, 44); register(CommandParser.TEMPLATE_MIRROR, 45); register(CommandParser.TEMPLATE_ROTATION, 46); register(CommandParser.UUID, 47); @@ -546,7 +538,6 @@ public class MagicValues { register(SuggestionType.ASK_SERVER, "minecraft:ask_server"); register(SuggestionType.ALL_RECIPES, "minecraft:all_recipes"); register(SuggestionType.AVAILABLE_SOUNDS, "minecraft:available_sounds"); - register(SuggestionType.AVAILABLE_BIOMES, "minecraft:available_biomes"); register(SuggestionType.SUMMONABLE_ENTITIES, "minecraft:summonable_entities"); register(StringProperties.SINGLE_WORD, 0); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/ArgumentSignature.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/ArgumentSignature.java index 0645a0ae..c0ade508 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/ArgumentSignature.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/ArgumentSignature.java @@ -6,6 +6,6 @@ import lombok.Data; @Data @AllArgsConstructor public class ArgumentSignature { - private final String name; - private final byte[] signature; + private final String name; + private final byte[] signature; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/ChatCompletionAction.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/ChatCompletionAction.java deleted file mode 100644 index 1cf1dc21..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/ChatCompletionAction.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.github.steveice10.mc.protocol.data.game; - -public enum ChatCompletionAction { - ADD, - REMOVE, - SET; - - public static final ChatCompletionAction[] VALUES = values(); - - public static ChatCompletionAction from(int id) { - return VALUES[id]; - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/ChatFilterType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/ChatFilterType.java deleted file mode 100644 index 6a19f708..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/ChatFilterType.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.github.steveice10.mc.protocol.data.game; - -public enum ChatFilterType { - PASS_THROUGH, - FULLY_FILTERED, - PARTIALLY_FILTERED; - - public static final ChatFilterType[] VALUES = values(); - - public static ChatFilterType from(int id) { - return VALUES[id]; - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/LastSeenMessage.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/LastSeenMessage.java deleted file mode 100644 index 4c8fe959..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/LastSeenMessage.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.github.steveice10.mc.protocol.data.game; - -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.util.UUID; - -@Data -@AllArgsConstructor -public class LastSeenMessage { - private final UUID profileId; - private final byte[] lastSignature; -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntry.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntry.java index 46930797..dbdfeea0 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntry.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntry.java @@ -6,33 +6,26 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NonNull; import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; import java.security.PublicKey; +import java.util.UUID; @Data @AllArgsConstructor public class PlayerListEntry { - private final @NonNull GameProfile profile; - private final GameMode gameMode; - private final int ping; - private final Component displayName; - private final long expiresAt; - private final PublicKey publicKey; - private final byte[] keySignature; + private final @NonNull UUID profileId; + private @NonNull GameProfile profile; + private boolean listed; + private int latency; + private GameMode gameMode; + private @Nullable Component displayName; + private UUID sessionId; + private long expiresAt; + private @Nullable PublicKey publicKey; + private byte @Nullable[] keySignature; - public PlayerListEntry(GameProfile profile) { - this(profile, null, 0, null, 0, null, null); - } - - public PlayerListEntry(GameProfile profile, GameMode gameMode) { - this(profile, gameMode, 0, null, 0, null, null); - } - - public PlayerListEntry(GameProfile profile, int ping) { - this(profile, null, ping, null, 0, null, null); - } - - public PlayerListEntry(GameProfile profile, Component displayName) { - this(profile, null, 0, displayName, 0, null, null); + public PlayerListEntry(UUID profileId) { + this(profileId, new GameProfile(profileId, null), false, 0, GameMode.SURVIVAL, null, null, 0, null, null); } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntryAction.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntryAction.java index 35171efe..a2f489c3 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntryAction.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/PlayerListEntryAction.java @@ -2,8 +2,15 @@ package com.github.steveice10.mc.protocol.data.game; public enum PlayerListEntryAction { ADD_PLAYER, - UPDATE_GAMEMODE, + INITIALIZE_CHAT, + UPDATE_GAME_MODE, + UPDATE_LISTED, UPDATE_LATENCY, - UPDATE_DISPLAY_NAME, - REMOVE_PLAYER; + UPDATE_DISPLAY_NAME; + + public static final PlayerListEntryAction[] VALUES = values(); + + public static PlayerListEntryAction from(int id) { + return VALUES[id]; + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/BuiltinChatType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/BuiltinChatType.java similarity index 94% rename from src/main/java/com/github/steveice10/mc/protocol/data/game/BuiltinChatType.java rename to src/main/java/com/github/steveice10/mc/protocol/data/game/chat/BuiltinChatType.java index b4c9f450..0f3fb0d0 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/BuiltinChatType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/BuiltinChatType.java @@ -1,4 +1,4 @@ -package com.github.steveice10.mc.protocol.data.game; +package com.github.steveice10.mc.protocol.data.game.chat; import java.util.HashMap; import java.util.Locale; diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/ChatCompletionAction.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/ChatCompletionAction.java new file mode 100644 index 00000000..0294c9ea --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/ChatCompletionAction.java @@ -0,0 +1,13 @@ +package com.github.steveice10.mc.protocol.data.game.chat; + +public enum ChatCompletionAction { + ADD, + REMOVE, + SET; + + public static final ChatCompletionAction[] VALUES = values(); + + public static ChatCompletionAction from(int id) { + return VALUES[id]; + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/ChatFilterType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/ChatFilterType.java new file mode 100644 index 00000000..a4f59383 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/ChatFilterType.java @@ -0,0 +1,13 @@ +package com.github.steveice10.mc.protocol.data.game.chat; + +public enum ChatFilterType { + PASS_THROUGH, + FULLY_FILTERED, + PARTIALLY_FILTERED; + + public static final ChatFilterType[] VALUES = values(); + + public static ChatFilterType from(int id) { + return VALUES[id]; + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/MessageSignature.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/MessageSignature.java new file mode 100644 index 00000000..7e7d364c --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/chat/MessageSignature.java @@ -0,0 +1,12 @@ +package com.github.steveice10.mc.protocol.data.game.chat; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +@Data +@AllArgsConstructor +public class MessageSignature { + private final int id; + private final byte @Nullable[] messageSignature; +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java index 2e3044a2..549b5767 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java @@ -1,10 +1,9 @@ package com.github.steveice10.mc.protocol.data.game.command; public enum CommandParser { - ANGLE, BOOL, - DOUBLE, FLOAT, + DOUBLE, INTEGER, LONG, STRING, @@ -28,25 +27,26 @@ public enum CommandParser { OBJECTIVE_CRITERIA, OPERATION, PARTICLE, + ANGLE, ROTATION, SCOREBOARD_SLOT, SCORE_HOLDER, SWIZZLE, - UUID, TEAM, ITEM_SLOT, RESOURCE_LOCATION, - MOB_EFFECT, FUNCTION, ENTITY_ANCHOR, INT_RANGE, FLOAT_RANGE, - ITEM_ENCHANTMENT, - ENTITY_SUMMON, DIMENSION, + GAMEMODE, TIME, - RESOURCE, RESOURCE_OR_TAG, + RESOURCE_OR_TAG_KEY, + RESOURCE, + RESOURCE_KEY, TEMPLATE_MIRROR, - TEMPLATE_ROTATION; + TEMPLATE_ROTATION, + UUID; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/SuggestionType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/SuggestionType.java index e2eef7b0..78860dcf 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/SuggestionType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/SuggestionType.java @@ -4,6 +4,5 @@ public enum SuggestionType { ASK_SERVER, ALL_RECIPES, AVAILABLE_SOUNDS, - AVAILABLE_BIOMES, SUMMONABLE_ENTITIES; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/LongMetadataType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/LongMetadataType.java new file mode 100644 index 00000000..ef2e170d --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/LongMetadataType.java @@ -0,0 +1,63 @@ +package com.github.steveice10.mc.protocol.data.game.entity.metadata; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.LongEntityMetadata; +import io.netty.buffer.ByteBuf; + +import java.io.IOException; + +public class LongMetadataType extends MetadataType { + private final LongReader primitiveReader; + private final LongWriter primitiveWriter; + private final LongEntityMetadataFactory primitiveFactory; + + protected LongMetadataType(LongReader reader, LongWriter writer, LongEntityMetadataFactory metadataFactory) { + super(reader, writer, metadataFactory); + + this.primitiveReader = reader; + this.primitiveWriter = writer; + this.primitiveFactory = metadataFactory; + } + + @Override + public EntityMetadata readMetadata(MinecraftCodecHelper helper, ByteBuf input, int id) throws IOException { + return this.primitiveFactory.createPrimitive(id, this, this.primitiveReader.readPrimitive(helper, input)); + } + + public void writeMetadataPrimitive(MinecraftCodecHelper helper, ByteBuf output, long value) throws IOException { + this.primitiveWriter.writePrimitive(helper, output, value); + } + + @FunctionalInterface + public interface LongReader extends HelperReader { + long readPrimitive(MinecraftCodecHelper helper, ByteBuf input) throws IOException; + + @Deprecated + @Override + default Long read(MinecraftCodecHelper helper, ByteBuf input) throws IOException { + return this.readPrimitive(helper, input); + } + } + + @FunctionalInterface + public interface LongWriter extends HelperWriter { + void writePrimitive(MinecraftCodecHelper helper, ByteBuf output, long value) throws IOException; + + @Deprecated + @Override + default void write(MinecraftCodecHelper helper, ByteBuf output, Long value) throws IOException { + this.writePrimitive(helper, output, value); + } + } + + @FunctionalInterface + public interface LongEntityMetadataFactory extends EntityMetadataFactory { + LongEntityMetadata createPrimitive(int id, LongMetadataType type, long value); + + @Deprecated + @Override + default EntityMetadata create(int id, MetadataType type, Long value) { + throw new UnsupportedOperationException("Unsupported read method! Use primitive createPrimitive!"); + } + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java index c3b20aec..19118a9b 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java @@ -24,6 +24,7 @@ public class MetadataType { public static final ByteMetadataType BYTE = new ByteMetadataType(ByteBuf::readByte, ByteBuf::writeByte, ByteEntityMetadata::new); public static final IntMetadataType INT = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); + public static final LongMetadataType LONG = new LongMetadataType(MinecraftCodecHelper::readVarLong, MinecraftCodecHelper::writeVarLong, LongEntityMetadata::new); public static final FloatMetadataType FLOAT = new FloatMetadataType(ByteBuf::readFloat, ByteBuf::writeFloat, FloatEntityMetadata::new); public static final MetadataType STRING = new MetadataType<>(MinecraftCodecHelper::readString, MinecraftCodecHelper::writeString, ObjectEntityMetadata::new); public static final MetadataType CHAT = new MetadataType<>(MinecraftCodecHelper::readComponent, MinecraftCodecHelper::writeComponent, ObjectEntityMetadata::new); @@ -35,7 +36,7 @@ public class MetadataType { public static final MetadataType> OPTIONAL_POSITION = new MetadataType<>(optionalReader(MinecraftCodecHelper::readPosition), optionalWriter(MinecraftCodecHelper::writePosition), ObjectEntityMetadata::new); public static final MetadataType DIRECTION = new MetadataType<>(MinecraftCodecHelper::readDirection, MinecraftCodecHelper::writeDirection, ObjectEntityMetadata::new); public static final MetadataType> OPTIONAL_UUID = new MetadataType<>(optionalReader(MinecraftCodecHelper::readUUID), optionalWriter(MinecraftCodecHelper::writeUUID), ObjectEntityMetadata::new); - public static final IntMetadataType BLOCK_STATE = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); + public static final OptionalIntMetadataType BLOCK_STATE = new OptionalIntMetadataType(ObjectEntityMetadata::new); public static final MetadataType NBT_TAG = new MetadataType<>(MinecraftCodecHelper::readTag, MinecraftCodecHelper::writeTag, ObjectEntityMetadata::new); public static final MetadataType PARTICLE = new MetadataType<>(MinecraftCodecHelper::readParticle, MinecraftCodecHelper::writeParticle, ObjectEntityMetadata::new); public static final MetadataType VILLAGER_DATA = new MetadataType<>(MinecraftCodecHelper::readVillagerData, MinecraftCodecHelper::writeVillagerData, ObjectEntityMetadata::new); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/Pose.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/Pose.java index ff2c168c..dacd4f20 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/Pose.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/Pose.java @@ -11,6 +11,7 @@ public enum Pose { DYING, CROAKING, USING_TONGUE, + SITTING, ROARING, SNIFFING, EMERGING, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/IntEntityMetadata.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/IntEntityMetadata.java index e96b5d4f..d94a0e5e 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/IntEntityMetadata.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/IntEntityMetadata.java @@ -9,9 +9,6 @@ import lombok.NonNull; import java.io.IOException; -/** - * Used for both {@link MetadataType#INT} and {@link MetadataType#BLOCK_STATE}. - */ public class IntEntityMetadata extends EntityMetadata { private final int value; diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/LongEntityMetadata.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/LongEntityMetadata.java new file mode 100644 index 00000000..700edab4 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/type/LongEntityMetadata.java @@ -0,0 +1,33 @@ +package com.github.steveice10.mc.protocol.data.game.entity.metadata.type; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.LongMetadataType; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; + +import java.io.IOException; + +public class LongEntityMetadata extends EntityMetadata { + private final long value; + + public LongEntityMetadata(int id, @NonNull LongMetadataType type, long value) { + super(id, type); + this.value = value; + } + + public long getPrimitiveValue() { + return this.value; + } + + @Override + @Deprecated + public Long getValue() { + return this.value; + } + + @Override + public void write(MinecraftCodecHelper helper, ByteBuf out) throws IOException { + this.type.writeMetadataPrimitive(helper, out, value); + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java index 7b4e7121..accd0b37 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java @@ -12,6 +12,7 @@ public enum EntityType { BOAT, CHEST_BOAT, CAT, + CAMEL, CAVE_SPIDER, CHICKEN, COD, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java index bd020c32..51957c53 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java @@ -9,6 +9,7 @@ public enum BlockEntityType { DISPENSER, DROPPER, SIGN, + HANGING_SIGN, MOB_SPAWNER, PISTON, BREWING_STAND, @@ -36,7 +37,8 @@ public enum BlockEntityType { BEEHIVE, SCULK_SENSOR, SCULK_CATALYST, - SCULK_SHRIEKER; + SCULK_SHRIEKER, + CHISELED_BOOKSHELF; private static final BlockEntityType[] VALUES = values(); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java index 11adadd5..099fcefc 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java @@ -4,9 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; -import java.util.HashMap; -import java.util.Map; - @Getter @AllArgsConstructor public enum BuiltinSound implements Sound { @@ -107,6 +104,21 @@ public enum BuiltinSound implements Sound { BLOCK_BAMBOO_SAPLING_BREAK("block.bamboo_sapling.break"), BLOCK_BAMBOO_SAPLING_HIT("block.bamboo_sapling.hit"), BLOCK_BAMBOO_SAPLING_PLACE("block.bamboo_sapling.place"), + BLOCK_BAMBOO_WOOD_BREAK("block.bamboo_wood.break"), + BLOCK_BAMBOO_WOOD_FALL("block.bamboo_wood.fall"), + BLOCK_BAMBOO_WOOD_HIT("block.bamboo_wood.hit"), + BLOCK_BAMBOO_WOOD_PLACE("block.bamboo_wood.place"), + BLOCK_BAMBOO_WOOD_STEP("block.bamboo_wood.step"), + BLOCK_BAMBOO_WOOD_DOOR_CLOSE("block.bamboo_wood_door.close"), + BLOCK_BAMBOO_WOOD_DOOR_OPEN("block.bamboo_wood_door.open"), + BLOCK_BAMBOO_WOOD_TRAPDOOR_CLOSE("block.bamboo_wood_trapdoor.close"), + BLOCK_BAMBOO_WOOD_TRAPDOOR_OPEN("block.bamboo_wood_trapdoor.open"), + BLOCK_BAMBOO_WOOD_BUTTON_CLICK_OFF("block.bamboo_wood_button.click_off"), + BLOCK_BAMBOO_WOOD_BUTTON_CLICK_ON("block.bamboo_wood_button.click_on"), + BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_OFF("block.bamboo_wood_pressure_plate.click_off"), + BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_ON("block.bamboo_wood_pressure_plate.click_on"), + BLOCK_BAMBOO_WOOD_FENCE_GATE_CLOSE("block.bamboo_wood_fence_gate.close"), + BLOCK_BAMBOO_WOOD_FENCE_GATE_OPEN("block.bamboo_wood_fence_gate.open"), BLOCK_BARREL_CLOSE("block.barrel.close"), BLOCK_BARREL_OPEN("block.barrel.open"), BLOCK_BASALT_BREAK("block.basalt.break"), @@ -187,6 +199,17 @@ public enum BuiltinSound implements Sound { BLOCK_CALCITE_PLACE("block.calcite.place"), BLOCK_CALCITE_HIT("block.calcite.hit"), BLOCK_CALCITE_FALL("block.calcite.fall"), + ENTITY_CAMEL_AMBIENT("entity.camel.ambient"), + ENTITY_CAMEL_DASH("entity.camel.dash"), + ENTITY_CAMEL_DASH_READY("entity.camel.dash_ready"), + ENTITY_CAMEL_DEATH("entity.camel.death"), + ENTITY_CAMEL_EAT("entity.camel.eat"), + ENTITY_CAMEL_HURT("entity.camel.hurt"), + ENTITY_CAMEL_SADDLE("entity.camel.saddle"), + ENTITY_CAMEL_SIT("entity.camel.sit"), + ENTITY_CAMEL_STAND("entity.camel.stand"), + ENTITY_CAMEL_STEP("entity.camel.step"), + ENTITY_CAMEL_STEP_SAND("entity.camel.step_sand"), BLOCK_CAMPFIRE_CRACKLE("block.campfire.crackle"), BLOCK_CANDLE_AMBIENT("block.candle.ambient"), BLOCK_CANDLE_BREAK("block.candle.break"), @@ -223,6 +246,15 @@ public enum BuiltinSound implements Sound { ENTITY_CHICKEN_EGG("entity.chicken.egg"), ENTITY_CHICKEN_HURT("entity.chicken.hurt"), ENTITY_CHICKEN_STEP("entity.chicken.step"), + BLOCK_CHISELED_BOOKSHELF_BREAK("block.chiseled_bookshelf.break"), + BLOCK_CHISELED_BOOKSHELF_FALL("block.chiseled_bookshelf.fall"), + BLOCK_CHISELED_BOOKSHELF_HIT("block.chiseled_bookshelf.hit"), + BLOCK_CHISELED_BOOKSHELF_INSERT("block.chiseled_bookshelf.insert"), + BLOCK_CHISELED_BOOKSHELF_INSERT_ENCHANTED("block.chiseled_bookshelf.insert.enchanted"), + BLOCK_CHISELED_BOOKSHELF_STEP("block.chiseled_bookshelf.step"), + BLOCK_CHISELED_BOOKSHELF_PICKUP("block.chiseled_bookshelf.pickup"), + BLOCK_CHISELED_BOOKSHELF_PICKUP_ENCHANTED("block.chiseled_bookshelf.pickup.enchanted"), + BLOCK_CHISELED_BOOKSHELF_PLACE("block.chiseled_bookshelf.place"), BLOCK_CHORUS_FLOWER_DEATH("block.chorus_flower.death"), BLOCK_CHORUS_FLOWER_GROW("block.chorus_flower.grow"), ITEM_CHORUS_FRUIT_TELEPORT("item.chorus_fruit.teleport"), @@ -517,6 +549,21 @@ public enum BuiltinSound implements Sound { BLOCK_HANGING_ROOTS_HIT("block.hanging_roots.hit"), BLOCK_HANGING_ROOTS_PLACE("block.hanging_roots.place"), BLOCK_HANGING_ROOTS_STEP("block.hanging_roots.step"), + BLOCK_HANGING_SIGN_STEP("block.hanging_sign.step"), + BLOCK_HANGING_SIGN_BREAK("block.hanging_sign.break"), + BLOCK_HANGING_SIGN_FALL("block.hanging_sign.fall"), + BLOCK_HANGING_SIGN_HIT("block.hanging_sign.hit"), + BLOCK_HANGING_SIGN_PLACE("block.hanging_sign.place"), + BLOCK_NETHER_WOOD_HANGING_SIGN_STEP("block.nether_wood_hanging_sign.step"), + BLOCK_NETHER_WOOD_HANGING_SIGN_BREAK("block.nether_wood_hanging_sign.break"), + BLOCK_NETHER_WOOD_HANGING_SIGN_FALL("block.nether_wood_hanging_sign.fall"), + BLOCK_NETHER_WOOD_HANGING_SIGN_HIT("block.nether_wood_hanging_sign.hit"), + BLOCK_NETHER_WOOD_HANGING_SIGN_PLACE("block.nether_wood_hanging_sign.place"), + BLOCK_BAMBOO_WOOD_HANGING_SIGN_STEP("block.bamboo_wood_hanging_sign.step"), + BLOCK_BAMBOO_WOOD_HANGING_SIGN_BREAK("block.bamboo_wood_hanging_sign.break"), + BLOCK_BAMBOO_WOOD_HANGING_SIGN_FALL("block.bamboo_wood_hanging_sign.fall"), + BLOCK_BAMBOO_WOOD_HANGING_SIGN_HIT("block.bamboo_wood_hanging_sign.hit"), + BLOCK_BAMBOO_WOOD_HANGING_SIGN_PLACE("block.bamboo_wood_hanging_sign.place"), ITEM_HOE_TILL("item.hoe.till"), ENTITY_HOGLIN_AMBIENT("entity.hoglin.ambient"), ENTITY_HOGLIN_ANGRY("entity.hoglin.angry"), @@ -733,6 +780,21 @@ public enum BuiltinSound implements Sound { BLOCK_NETHER_BRICKS_FALL("block.nether_bricks.fall"), BLOCK_NETHER_WART_BREAK("block.nether_wart.break"), ITEM_NETHER_WART_PLANT("item.nether_wart.plant"), + BLOCK_NETHER_WOOD_BREAK("block.nether_wood.break"), + BLOCK_NETHER_WOOD_FALL("block.nether_wood.fall"), + BLOCK_NETHER_WOOD_HIT("block.nether_wood.hit"), + BLOCK_NETHER_WOOD_PLACE("block.nether_wood.place"), + BLOCK_NETHER_WOOD_STEP("block.nether_wood.step"), + BLOCK_NETHER_WOOD_DOOR_CLOSE("block.nether_wood_door.close"), + BLOCK_NETHER_WOOD_DOOR_OPEN("block.nether_wood_door.open"), + BLOCK_NETHER_WOOD_TRAPDOOR_CLOSE("block.nether_wood_trapdoor.close"), + BLOCK_NETHER_WOOD_TRAPDOOR_OPEN("block.nether_wood_trapdoor.open"), + BLOCK_NETHER_WOOD_BUTTON_CLICK_OFF("block.nether_wood_button.click_off"), + BLOCK_NETHER_WOOD_BUTTON_CLICK_ON("block.nether_wood_button.click_on"), + BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_OFF("block.nether_wood_pressure_plate.click_off"), + BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_ON("block.nether_wood_pressure_plate.click_on"), + BLOCK_NETHER_WOOD_FENCE_GATE_CLOSE("block.nether_wood_fence_gate.close"), + BLOCK_NETHER_WOOD_FENCE_GATE_OPEN("block.nether_wood_fence_gate.open"), BLOCK_PACKED_MUD_BREAK("block.packed_mud.break"), BLOCK_PACKED_MUD_FALL("block.packed_mud.fall"), BLOCK_PACKED_MUD_HIT("block.packed_mud.hit"), @@ -794,6 +856,12 @@ public enum BuiltinSound implements Sound { BLOCK_NOTE_BLOCK_DIDGERIDOO("block.note_block.didgeridoo"), BLOCK_NOTE_BLOCK_BIT("block.note_block.bit"), BLOCK_NOTE_BLOCK_BANJO("block.note_block.banjo"), + BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE("block.note_block.imitate.zombie"), + BLOCK_NOTE_BLOCK_IMITATE_SKELETON("block.note_block.imitate.skeleton"), + BLOCK_NOTE_BLOCK_IMITATE_CREEPER("block.note_block.imitate.creeper"), + BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON("block.note_block.imitate.ender_dragon"), + BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON("block.note_block.imitate.wither_skeleton"), + BLOCK_NOTE_BLOCK_IMITATE_PIGLIN("block.note_block.imitate.piglin"), ENTITY_OCELOT_HURT("entity.ocelot.hurt"), ENTITY_OCELOT_AMBIENT("entity.ocelot.ambient"), ENTITY_OCELOT_DEATH("entity.ocelot.death"), @@ -1334,6 +1402,16 @@ public enum BuiltinSound implements Sound { private final @NonNull String name; + @Override + public boolean isNewSystem() { + return false; + } + + @Override + public float getRange() { + return 16F; + } + /** * For grabbing when the SoundPacket is sent. */ diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/CustomSound.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/CustomSound.java index 3d240274..e5cefe55 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/CustomSound.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/CustomSound.java @@ -2,10 +2,12 @@ package com.github.steveice10.mc.protocol.data.game.level.sound; import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NonNull; +import org.jetbrains.annotations.NotNull; @Data @AllArgsConstructor public class CustomSound implements Sound { - private final @NonNull String name; + private final @NotNull String name; + private final boolean newSystem; + private final float range; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/Sound.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/Sound.java index 3500b834..f2c41cf9 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/Sound.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/Sound.java @@ -1,4 +1,9 @@ package com.github.steveice10.mc.protocol.data.game.level.sound; public interface Sound { + String getName(); + + boolean isNewSystem(); + + float getRange(); } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/CraftingBookCategory.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/CraftingBookCategory.java new file mode 100644 index 00000000..22cf0348 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/CraftingBookCategory.java @@ -0,0 +1,15 @@ +package com.github.steveice10.mc.protocol.data.game.recipe; + +public enum CraftingBookCategory { + BUILDING, + REDSTONE, + EQUIPMENT, + MISC; + + private static final CraftingBookCategory[] VALUES = values(); + + + public static CraftingBookCategory from(int id) { + return VALUES[id]; + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java index 7b7c9372..3322f58a 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java @@ -1,8 +1,8 @@ package com.github.steveice10.mc.protocol.data.game.recipe; public enum RecipeType { - CRAFTING_SHAPELESS, CRAFTING_SHAPED, + CRAFTING_SHAPELESS, CRAFTING_SPECIAL_ARMORDYE, CRAFTING_SPECIAL_BOOKCLONING, CRAFTING_SPECIAL_MAPCLONING, @@ -10,13 +10,12 @@ public enum RecipeType { CRAFTING_SPECIAL_FIREWORK_ROCKET, CRAFTING_SPECIAL_FIREWORK_STAR, CRAFTING_SPECIAL_FIREWORK_STAR_FADE, - CRAFTING_SPECIAL_REPAIRITEM, CRAFTING_SPECIAL_TIPPEDARROW, CRAFTING_SPECIAL_BANNERDUPLICATE, - CRAFTING_SPECIAL_BANNERADDPATTERN, CRAFTING_SPECIAL_SHIELDDECORATION, CRAFTING_SPECIAL_SHULKERBOXCOLORING, CRAFTING_SPECIAL_SUSPICIOUSSTEW, + CRAFTING_SPECIAL_REPAIRITEM, SMELTING, BLASTING, SMOKING, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/CookedRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/CookedRecipeData.java index 633c73ce..864bf2b7 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/CookedRecipeData.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/CookedRecipeData.java @@ -1,6 +1,7 @@ package com.github.steveice10.mc.protocol.data.game.recipe.data; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.recipe.CraftingBookCategory; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; import lombok.Data; @@ -10,6 +11,7 @@ import lombok.NonNull; @AllArgsConstructor public class CookedRecipeData implements RecipeData { private final @NonNull String group; + private final @NonNull CraftingBookCategory category; private final @NonNull Ingredient ingredient; private final ItemStack result; private final float experience; diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapedRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapedRecipeData.java index a4935f61..48f45c20 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapedRecipeData.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapedRecipeData.java @@ -1,6 +1,7 @@ package com.github.steveice10.mc.protocol.data.game.recipe.data; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.recipe.CraftingBookCategory; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; import lombok.Data; @@ -12,6 +13,7 @@ public class ShapedRecipeData implements RecipeData { private final int width; private final int height; private final @NonNull String group; + private final @NonNull CraftingBookCategory category; private final @NonNull Ingredient[] ingredients; private final ItemStack result; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapelessRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapelessRecipeData.java index 8448ff08..9214d250 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapelessRecipeData.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/ShapelessRecipeData.java @@ -1,6 +1,7 @@ package com.github.steveice10.mc.protocol.data.game.recipe.data; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.recipe.CraftingBookCategory; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; import lombok.Data; @@ -10,6 +11,7 @@ import lombok.NonNull; @AllArgsConstructor public class ShapelessRecipeData implements RecipeData { private final @NonNull String group; + private final @NonNull CraftingBookCategory category; private final @NonNull Ingredient[] ingredients; private final ItemStack result; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SimpleCraftingRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SimpleCraftingRecipeData.java new file mode 100644 index 00000000..e9a78167 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SimpleCraftingRecipeData.java @@ -0,0 +1,12 @@ +package com.github.steveice10.mc.protocol.data.game.recipe.data; + +import com.github.steveice10.mc.protocol.data.game.recipe.CraftingBookCategory; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NonNull; + +@Data +@AllArgsConstructor +public class SimpleCraftingRecipeData implements RecipeData { + private final @NonNull CraftingBookCategory category; +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/status/ServerStatusInfo.java b/src/main/java/com/github/steveice10/mc/protocol/data/status/ServerStatusInfo.java index 10383098..17efd43a 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/status/ServerStatusInfo.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/status/ServerStatusInfo.java @@ -15,5 +15,5 @@ public class ServerStatusInfo { private @NonNull PlayerInfo playerInfo; private @NonNull Component description; private byte[] iconPng; - private boolean previewsChat; + private boolean enforcesSecureChat; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundChatPreviewPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundChatPreviewPacket.java deleted file mode 100644 index 303284a0..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundChatPreviewPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.github.steveice10.mc.protocol.packet.ingame.clientbound; - -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; -import io.netty.buffer.ByteBuf; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.With; -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; - -@Data -@With -@AllArgsConstructor -public class ClientboundChatPreviewPacket implements MinecraftPacket { - private final int queryId; - private final @Nullable Component preview; - - public ClientboundChatPreviewPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.queryId = in.readInt(); - if (in.readBoolean()) { - this.preview = helper.readComponent(in); - } else { - this.preview = null; - } - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - out.writeInt(this.queryId); - out.writeBoolean(this.preview != null); - if (this.preview != null) { - helper.writeString(out, DefaultComponentSerializer.get().serialize(this.preview)); - } - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java index c44ea29f..1fc996cb 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java @@ -134,8 +134,10 @@ public class ClientboundCommandsPacket implements MinecraftPacket { case SCORE_HOLDER: properties = new ScoreHolderProperties(in.readBoolean()); break; - case RESOURCE: case RESOURCE_OR_TAG: + case RESOURCE_OR_TAG_KEY: + case RESOURCE: + case RESOURCE_KEY: properties = new ResourceProperties(helper.readString(in)); break; default: diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCustomChatCompletionsPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCustomChatCompletionsPacket.java index 1cd64a85..0d993693 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCustomChatCompletionsPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCustomChatCompletionsPacket.java @@ -2,7 +2,7 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.game.ChatCompletionAction; +import com.github.steveice10.mc.protocol.data.game.chat.ChatCompletionAction; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -12,23 +12,23 @@ import lombok.With; @With @AllArgsConstructor public class ClientboundCustomChatCompletionsPacket implements MinecraftPacket { - private final ChatCompletionAction action; - private final String[] entries; + private final ChatCompletionAction action; + private final String[] entries; - public ClientboundCustomChatCompletionsPacket(ByteBuf in, MinecraftCodecHelper helper) { - this.action = ChatCompletionAction.from(helper.readVarInt(in)); - this.entries = new String[helper.readVarInt(in)]; - for (int i = 0; i < this.entries.length; i++) { - this.entries[i] = helper.readString(in); - } - } + public ClientboundCustomChatCompletionsPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.action = ChatCompletionAction.from(helper.readVarInt(in)); + this.entries = new String[helper.readVarInt(in)]; + for (int i = 0; i < this.entries.length; i++) { + this.entries[i] = helper.readString(in); + } + } - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) { - helper.writeVarInt(out, this.action.ordinal()); - helper.writeVarInt(out, this.entries.length); - for (String entry : this.entries) { - helper.writeString(out, entry); - } - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.action.ordinal()); + helper.writeVarInt(out, this.entries.length); + for (String entry : this.entries) { + helper.writeString(out, entry); + } + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDeleteChatPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDeleteChatPacket.java index 075b3886..c6c9da79 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDeleteChatPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDeleteChatPacket.java @@ -2,6 +2,7 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import com.github.steveice10.mc.protocol.data.game.chat.MessageSignature; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,15 +14,18 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundDeleteChatPacket implements MinecraftPacket { - private final byte[] messageSignature; + private final MessageSignature messageSignature; - public ClientboundDeleteChatPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.messageSignature = helper.readByteArray(in); - } + public ClientboundDeleteChatPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + int id = helper.readVarInt(in) - 1; + this.messageSignature = new MessageSignature(id, id == -1 ? in.readBytes(new byte[256]).array() : null); + } - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeVarInt(out, this.messageSignature.length); - out.writeBytes(this.messageSignature); - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeVarInt(out, this.messageSignature.getId() + 1); + if (this.messageSignature.getMessageSignature() != null) { + out.writeBytes(messageSignature.getMessageSignature()); + } + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDisguisedChatPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDisguisedChatPacket.java new file mode 100644 index 00000000..0ed4cf32 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDisguisedChatPacket.java @@ -0,0 +1,42 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import com.github.steveice10.mc.protocol.data.game.chat.BuiltinChatType; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + +@Data +@With +@AllArgsConstructor +public class ClientboundDisguisedChatPacket implements MinecraftPacket { + private final Component message; + /** + * Is {@link BuiltinChatType} defined in the order sent by the server in the login packet. + */ + private final int chatType; + private final Component name; + private final @Nullable Component targetName; + + + public ClientboundDisguisedChatPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.message = helper.readComponent(in); + this.chatType = helper.readVarInt(in); + this.name = helper.readComponent(in); + this.targetName = helper.readNullable(in, helper::readComponent); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeComponent(out, this.message); + helper.writeVarInt(out, this.chatType); + helper.writeComponent(out, this.name); + helper.writeNullable(out, this.targetName, helper::writeComponent); + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java index fe00f49f..515d680d 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java @@ -19,13 +19,10 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundLoginPacket implements MinecraftPacket { - private static final int GAMEMODE_MASK = 0x07; - private final int entityId; private final boolean hardcore; private final @NonNull GameMode gameMode; private final GameMode previousGamemode; - private final int worldCount; private final @NonNull String[] worldNames; private final @NonNull CompoundTag registry; private final @NonNull String dimension; @@ -42,14 +39,12 @@ public class ClientboundLoginPacket implements MinecraftPacket { public ClientboundLoginPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { this.entityId = in.readInt(); - this.hardcore = in.readBoolean(); - int gameMode = in.readUnsignedByte(); - this.gameMode = MagicValues.key(GameMode.class, gameMode & GAMEMODE_MASK); - this.previousGamemode = MagicValues.key(GameMode.class, in.readUnsignedByte()); - this.worldCount = helper.readVarInt(in); - this.worldNames = new String[this.worldCount]; - for (int i = 0; i < this.worldCount; i++) { + this.gameMode = MagicValues.key(GameMode.class, in.readByte()); + this.previousGamemode = MagicValues.key(GameMode.class, in.readByte()); + int worldCount = helper.readVarInt(in); + this.worldNames = new String[worldCount]; + for (int i = 0; i < worldCount; i++) { this.worldNames[i] = helper.readString(in); } this.registry = helper.readTag(in); @@ -73,13 +68,10 @@ public class ClientboundLoginPacket implements MinecraftPacket { @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { out.writeInt(this.entityId); - out.writeBoolean(this.hardcore); - int gameMode = MagicValues.value(Integer.class, this.gameMode) & GAMEMODE_MASK; - - out.writeByte(gameMode); + out.writeByte(MagicValues.value(Integer.class, this.gameMode)); out.writeByte(MagicValues.value(Integer.class, this.previousGamemode)); - helper.writeVarInt(out, this.worldCount); + helper.writeVarInt(out, this.worldNames.length); for (String worldName : this.worldNames) { helper.writeString(out, worldName); } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatHeaderPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatHeaderPacket.java deleted file mode 100644 index f9fd7ea4..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatHeaderPacket.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.github.steveice10.mc.protocol.packet.ingame.clientbound; - -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import io.netty.buffer.ByteBuf; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.With; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.util.UUID; - -@Data -@With -@AllArgsConstructor -public class ClientboundPlayerChatHeaderPacket implements MinecraftPacket { - private final byte @Nullable[] previousSignature; - private final UUID sender; - private final byte[] headerSignature; - private final byte[] bodyDigest; - - public ClientboundPlayerChatHeaderPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - if (in.readBoolean()) { - this.previousSignature = helper.readByteArray(in); - } else { - this.previousSignature = null; - } - - this.sender = helper.readUUID(in); - this.headerSignature = helper.readByteArray(in); - this.bodyDigest = helper.readByteArray(in); - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - if (this.previousSignature != null) { - out.writeBoolean(true); - helper.writeVarInt(out, previousSignature.length); - out.writeBytes(this.previousSignature); - } else { - out.writeBoolean(false); - } - - helper.writeUUID(out, this.sender); - helper.writeVarInt(out, this.headerSignature.length); - out.writeBytes(this.headerSignature); - helper.writeVarInt(out, this.bodyDigest.length); - out.writeBytes(this.bodyDigest); - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatPacket.java index 06bf088f..714a186e 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatPacket.java @@ -2,9 +2,9 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.game.BuiltinChatType; -import com.github.steveice10.mc.protocol.data.game.ChatFilterType; -import com.github.steveice10.mc.protocol.data.game.LastSeenMessage; +import com.github.steveice10.mc.protocol.data.game.chat.BuiltinChatType; +import com.github.steveice10.mc.protocol.data.game.chat.ChatFilterType; +import com.github.steveice10.mc.protocol.data.game.chat.MessageSignature; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -14,7 +14,6 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.ArrayList; -import java.util.BitSet; import java.util.List; import java.util.UUID; @@ -22,119 +21,75 @@ import java.util.UUID; @With @AllArgsConstructor public class ClientboundPlayerChatPacket implements MinecraftPacket { - private final byte @Nullable[] previousSignature; - private final UUID sender; - private final byte[] headerSignature; - private final String messagePlain; - private final Component messageDecorated; - private final long timeStamp; - private final long salt; - private final List lastSeenMessages; - private final @Nullable Component unsignedContent; - private final BitSet filterMask; - private final ChatFilterType filterType; - /** - * Is {@link BuiltinChatType} defined in the order sent by the server in the login packet. - */ - private final int chatType; - private final Component name; - private final @Nullable Component targetName; + private final UUID sender; + private final int index; + private final byte @Nullable[] messageSignature; + private final String content; + private final long timeStamp; + private final long salt; + private final List lastSeenMessages; + private final @Nullable Component unsignedContent; + private final ChatFilterType filterMask; + /** + * Is {@link BuiltinChatType} defined in the order sent by the server in the login packet. + */ + private final int chatType; + private final Component name; + private final @Nullable Component targetName; - public ClientboundPlayerChatPacket(ByteBuf in, MinecraftCodecHelper helper) { - if (in.readBoolean()) { - this.previousSignature = helper.readByteArray(in); - } else { - this.previousSignature = null; - } + public ClientboundPlayerChatPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.sender = helper.readUUID(in); + this.index = helper.readVarInt(in); + if (in.readBoolean()) { + this.messageSignature = in.readBytes(new byte[256]).array(); + } else { + this.messageSignature = null; + } - this.sender = helper.readUUID(in); - this.headerSignature = helper.readByteArray(in); - this.messagePlain = helper.readString(in); - if (in.readBoolean()) { - this.messageDecorated = helper.readComponent(in); - } else { - this.messageDecorated = Component.text(this.messagePlain); - } + this.content = helper.readString(in, 256); + this.timeStamp = in.readLong(); + this.salt = in.readLong(); - this.timeStamp = in.readLong(); - this.salt = in.readLong(); - this.lastSeenMessages = new ArrayList<>(); - int seenMessageCount = Math.min(helper.readVarInt(in), 5); - for (int i = 0; i < seenMessageCount; i++) { - lastSeenMessages.add(new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in))); - } + this.lastSeenMessages = new ArrayList<>(); + int seenMessageCount = Math.min(helper.readVarInt(in), 20); + for (int i = 0; i < seenMessageCount; i++) { + int id = helper.readVarInt(in) - 1; + byte[] messageSignature = id == -1 ? in.readBytes(new byte[256]).array() : null; + this.lastSeenMessages.add(new MessageSignature(id, messageSignature)); + } - if (in.readBoolean()) { - this.unsignedContent = helper.readComponent(in); - } else { - this.unsignedContent = null; - } + this.unsignedContent = helper.readNullable(in, helper::readComponent); + this.filterMask = ChatFilterType.from(helper.readVarInt(in)); + this.chatType = helper.readVarInt(in); + this.name = helper.readComponent(in); + this.targetName = helper.readNullable(in, helper::readComponent); + } - this.filterType = ChatFilterType.from(helper.readVarInt(in)); - if (filterType == ChatFilterType.PARTIALLY_FILTERED) { - this.filterMask = BitSet.valueOf(helper.readLongArray(in)); - } else { - this.filterMask = new BitSet(0); - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeUUID(out, this.sender); + helper.writeVarInt(out, this.index); + out.writeBoolean(this.messageSignature != null); + if (this.messageSignature != null) { + out.writeBytes(this.messageSignature); + } - this.chatType = helper.readVarInt(in); - this.name = helper.readComponent(in); - if (in.readBoolean()) { - this.targetName = helper.readComponent(in); - } else { - this.targetName = null; - } - } + helper.writeString(out, this.content); + out.writeLong(this.timeStamp); + out.writeLong(this.salt); - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - if (this.previousSignature != null) { - out.writeBoolean(true); - helper.writeVarInt(out, this.previousSignature.length); - out.writeBytes(this.previousSignature); - } else { - out.writeBoolean(false); - } + helper.writeVarInt(out, this.lastSeenMessages.size()); + for (MessageSignature messageSignature : this.lastSeenMessages) { + helper.writeVarInt(out, messageSignature.getId() + 1); + if (messageSignature.getMessageSignature() != null) { + out.writeBytes(messageSignature.getMessageSignature()); + } + } - helper.writeUUID(out, this.sender); - helper.writeVarInt(out, this.headerSignature.length); - out.writeBytes(this.headerSignature); - helper.writeString(out, this.messagePlain); - if (!this.messageDecorated.equals(Component.text(this.messagePlain))) { - out.writeBoolean(true); - helper.writeComponent(out, this.messageDecorated); - } else { - out.writeBoolean(false); - } - - out.writeLong(this.timeStamp); - out.writeLong(this.salt); - helper.writeVarInt(out, this.lastSeenMessages.size()); - for (LastSeenMessage entry : this.lastSeenMessages) { - helper.writeUUID(out, entry.getProfileId()); - helper.writeVarInt(out, entry.getLastSignature().length); - out.writeBytes(entry.getLastSignature()); - } - - if (this.unsignedContent != null) { - out.writeBoolean(true); - helper.writeComponent(out, this.unsignedContent); - } else { - out.writeBoolean(false); - } - - helper.writeVarInt(out, this.filterType.ordinal()); - if (this.filterType == ChatFilterType.PARTIALLY_FILTERED) { - helper.writeLongArray(out, this.filterMask.toLongArray()); - } - - helper.writeVarInt(out, this.chatType); - helper.writeComponent(out, this.name); - if (this.targetName != null) { - out.writeBoolean(true); - helper.writeComponent(out, this.targetName); - } else { - out.writeBoolean(false); - } - } + helper.writeNullable(out, this.unsignedContent, helper::writeComponent); + helper.writeVarInt(out, this.filterMask.ordinal()); + helper.writeVarInt(out, this.chatType); + helper.writeComponent(out, this.name); + helper.writeNullable(out, this.targetName, helper::writeComponent); + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoPacket.java deleted file mode 100644 index 7ea690aa..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoPacket.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.github.steveice10.mc.protocol.packet.ingame.clientbound; - -import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; -import com.github.steveice10.mc.protocol.data.MagicValues; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntry; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import io.netty.buffer.ByteBuf; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NonNull; -import lombok.With; -import net.kyori.adventure.text.Component; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyFactory; -import java.security.PublicKey; -import java.security.spec.X509EncodedKeySpec; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -@Data -@With -@AllArgsConstructor -public class ClientboundPlayerInfoPacket implements MinecraftPacket { - private final @NonNull PlayerListEntryAction action; - private final @NonNull PlayerListEntry[] entries; - - public ClientboundPlayerInfoPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.action = MagicValues.key(PlayerListEntryAction.class, helper.readVarInt(in)); - this.entries = new PlayerListEntry[helper.readVarInt(in)]; - for (int count = 0; count < this.entries.length; count++) { - UUID uuid = helper.readUUID(in); - GameProfile profile; - if (this.action == PlayerListEntryAction.ADD_PLAYER) { - profile = new GameProfile(uuid, helper.readString(in)); - } else { - profile = new GameProfile(uuid, null); - } - - PlayerListEntry entry = null; - switch (this.action) { - case ADD_PLAYER: { - int properties = helper.readVarInt(in); - List propertyList = new ArrayList<>(); - for (int index = 0; index < properties; index++) { - String propertyName = helper.readString(in); - String value = helper.readString(in); - String signature = null; - if (in.readBoolean()) { - signature = helper.readString(in); - } - - propertyList.add(new GameProfile.Property(propertyName, value, signature)); - } - - profile.setProperties(propertyList); - - int rawGameMode = helper.readVarInt(in); - GameMode gameMode = MagicValues.key(GameMode.class, Math.max(rawGameMode, 0)); - int ping = helper.readVarInt(in); - Component displayName = null; - if (in.readBoolean()) { - displayName = helper.readComponent(in); - } - - long expiresAt; - PublicKey publicKey = null; - byte[] keySignature = null; - if (in.readBoolean()) { - expiresAt = in.readLong(); - byte[] keyBytes = helper.readByteArray(in); - keySignature = helper.readByteArray(in); - - try { - publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes)); - } catch (GeneralSecurityException e) { - throw new IOException("Could not decode public key.", e); - } - } else { - expiresAt = 0L; - } - - entry = new PlayerListEntry(profile, gameMode, ping, displayName, expiresAt, publicKey, keySignature); - break; - } - case UPDATE_GAMEMODE: { - int rawGameMode = helper.readVarInt(in); - GameMode mode = MagicValues.key(GameMode.class, Math.max(rawGameMode, 0)); - - entry = new PlayerListEntry(profile, mode); - break; - } - case UPDATE_LATENCY: { - int ping = helper.readVarInt(in); - - entry = new PlayerListEntry(profile, ping); - break; - } - case UPDATE_DISPLAY_NAME: { - Component displayName = null; - if (in.readBoolean()) { - displayName = helper.readComponent(in); - } - - entry = new PlayerListEntry(profile, displayName); - break; - } - case REMOVE_PLAYER: - entry = new PlayerListEntry(profile); - break; - } - - this.entries[count] = entry; - } - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeVarInt(out, MagicValues.value(Integer.class, this.action)); - helper.writeVarInt(out, this.entries.length); - for (PlayerListEntry entry : this.entries) { - helper.writeUUID(out, entry.getProfile().getId()); - switch (this.action) { - case ADD_PLAYER: - helper.writeString(out, entry.getProfile().getName()); - helper.writeVarInt(out, entry.getProfile().getProperties().size()); - for (GameProfile.Property property : entry.getProfile().getProperties()) { - helper.writeString(out, property.getName()); - helper.writeString(out, property.getValue()); - out.writeBoolean(property.hasSignature()); - if (property.hasSignature()) { - helper.writeString(out, property.getSignature()); - } - } - - helper.writeVarInt(out, MagicValues.value(Integer.class, entry.getGameMode())); - helper.writeVarInt(out, entry.getPing()); - out.writeBoolean(entry.getDisplayName() != null); - if (entry.getDisplayName() != null) { - helper.writeString(out, DefaultComponentSerializer.get().serialize(entry.getDisplayName())); - } - - out.writeBoolean(entry.getPublicKey() != null); - if (entry.getPublicKey() != null) { - out.writeLong(entry.getExpiresAt()); - byte[] encoded = entry.getPublicKey().getEncoded(); - helper.writeVarInt(out, encoded.length); - out.writeBytes(encoded); - helper.writeVarInt(out, entry.getKeySignature().length); - out.writeBytes(entry.getKeySignature()); - } - - break; - case UPDATE_GAMEMODE: - helper.writeVarInt(out, MagicValues.value(Integer.class, entry.getGameMode())); - break; - case UPDATE_LATENCY: - helper.writeVarInt(out, entry.getPing()); - break; - case UPDATE_DISPLAY_NAME: - out.writeBoolean(entry.getDisplayName() != null); - if (entry.getDisplayName() != null) { - helper.writeString(out, DefaultComponentSerializer.get().serialize(entry.getDisplayName())); - } - - break; - case REMOVE_PLAYER: - break; - } - } - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoRemovePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoRemovePacket.java new file mode 100644 index 00000000..785f8680 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoRemovePacket.java @@ -0,0 +1,35 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Data +@With +@AllArgsConstructor +public class ClientboundPlayerInfoRemovePacket implements MinecraftPacket { + private final List profileIds; + + public ClientboundPlayerInfoRemovePacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.profileIds = new ArrayList<>(); + int numIds = helper.readVarInt(in); + for (int i = 0; i < numIds; i++) { + this.profileIds.add(helper.readUUID(in)); + } + } + + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeVarInt(out, this.profileIds.size()); + for (UUID id : this.profileIds) { + helper.writeUUID(out, id); + } + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java new file mode 100644 index 00000000..d9030cee --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java @@ -0,0 +1,141 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound; + +import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import com.github.steveice10.mc.protocol.data.MagicValues; +import com.github.steveice10.mc.protocol.data.game.PlayerListEntry; +import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; +import net.kyori.adventure.text.Component; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.UUID; + +@Data +@With +@AllArgsConstructor +public class ClientboundPlayerInfoUpdatePacket implements MinecraftPacket { + private final EnumSet actions; + private final PlayerListEntry[] entries; + + public ClientboundPlayerInfoUpdatePacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.actions = helper.readEnumSet(in, PlayerListEntryAction.VALUES); + this.entries = new PlayerListEntry[helper.readVarInt(in)]; + for (int count = 0; count < this.entries.length; count++) { + PlayerListEntry entry = new PlayerListEntry(helper.readUUID(in)); + for (PlayerListEntryAction action : this.actions) { + switch (action) { + case ADD_PLAYER: { + GameProfile profile = new GameProfile(entry.getProfile().getId(), helper.readString(in, 16)); + int propertyCount = helper.readVarInt(in); + List propertyList = new ArrayList<>(); + for (int index = 0; index < propertyCount; index++) { + propertyList.add(helper.readProperty(in)); + } + + profile.setProperties(propertyList); + + entry.setProfile(profile); + break; + } + case INITIALIZE_CHAT: { + if (in.readBoolean()) { + entry.setSessionId(helper.readUUID(in)); + entry.setExpiresAt(in.readLong()); + byte[] keyBytes = helper.readByteArray(in); + entry.setKeySignature(helper.readByteArray(in)); + + PublicKey publicKey = null; + try { + publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes)); + } catch (GeneralSecurityException e) { + throw new IOException("Could not decode public key.", e); + } + + entry.setPublicKey(publicKey); + } + break; + } + case UPDATE_GAME_MODE: { + int rawGameMode = helper.readVarInt(in); + GameMode gameMode = MagicValues.key(GameMode.class, Math.max(rawGameMode, 0)); + + entry.setGameMode(gameMode); + break; + } + case UPDATE_LISTED: { + boolean listed = in.readBoolean(); + + entry.setListed(listed); + break; + } + case UPDATE_LATENCY: { + int latency = helper.readVarInt(in); + + entry.setLatency(latency); + break; + } + case UPDATE_DISPLAY_NAME: { + Component displayName = helper.readNullable(in, helper::readComponent); + + entry.setDisplayName(displayName); + break; + } + } + } + + this.entries[count] = entry; + } + } + + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeEnumSet(out, this.actions, PlayerListEntryAction.VALUES); + helper.writeVarInt(out, this.entries.length); + for (PlayerListEntry entry : this.entries) { + helper.writeUUID(out, entry.getProfile().getId()); + for (PlayerListEntryAction action : this.actions) { + switch (action) { + case ADD_PLAYER: + helper.writeString(out, entry.getProfile().getName()); + for (GameProfile.Property property : entry.getProfile().getProperties()) { + helper.writeProperty(out, property); + } + break; + case INITIALIZE_CHAT: + out.writeBoolean(entry.getPublicKey() != null); + if (entry.getPublicKey() != null) { + helper.writeUUID(out, entry.getSessionId()); + out.writeLong(entry.getExpiresAt()); + helper.writeByteArray(out, entry.getPublicKey().getEncoded()); + helper.writeByteArray(out, entry.getKeySignature()); + } + break; + case UPDATE_GAME_MODE: + helper.writeVarInt(out, MagicValues.value(Integer.class, entry.getGameMode())); + break; + case UPDATE_LISTED: + out.writeBoolean(entry.isListed()); + break; + case UPDATE_LATENCY: + helper.writeVarInt(out, entry.getLatency()); + break; + case UPDATE_DISPLAY_NAME: + helper.writeNullable(out, entry.getDisplayName(), helper::writeComponent); + break; + } + } + } + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java index b42adef3..32b714d8 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java @@ -16,41 +16,38 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundServerDataPacket implements MinecraftPacket { - private final @Nullable Component motd; - private final @Nullable String iconBase64; - private final boolean previewsChat; - private final boolean enforcesSecureChat; + private final @Nullable Component motd; + private final @Nullable String iconBase64; + private final boolean enforcesSecureChat; - public ClientboundServerDataPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - if (in.readBoolean()) { - this.motd = helper.readComponent(in); - } else { - this.motd = null; - } + public ClientboundServerDataPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + if (in.readBoolean()) { + this.motd = helper.readComponent(in); + } else { + this.motd = null; + } - if (in.readBoolean()) { - this.iconBase64 = helper.readString(in); - } else { - this.iconBase64 = null; - } + if (in.readBoolean()) { + this.iconBase64 = helper.readString(in); + } else { + this.iconBase64 = null; + } - this.previewsChat = in.readBoolean(); - this.enforcesSecureChat = in.readBoolean(); - } + this.enforcesSecureChat = in.readBoolean(); + } - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - out.writeBoolean(this.motd != null); - if (this.motd != null) { - helper.writeString(out, DefaultComponentSerializer.get().serialize(this.motd)); - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + out.writeBoolean(this.motd != null); + if (this.motd != null) { + helper.writeString(out, DefaultComponentSerializer.get().serialize(this.motd)); + } - out.writeBoolean(this.iconBase64 != null); - if (this.iconBase64 != null) { - helper.writeString(out, this.iconBase64); - } + out.writeBoolean(this.iconBase64 != null); + if (this.iconBase64 != null) { + helper.writeString(out, this.iconBase64); + } - out.writeBoolean(this.previewsChat); - out.writeBoolean(this.enforcesSecureChat); - } + out.writeBoolean(this.enforcesSecureChat); + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSetDisplayChatPreviewPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSetDisplayChatPreviewPacket.java deleted file mode 100644 index dab9da01..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSetDisplayChatPreviewPacket.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.steveice10.mc.protocol.packet.ingame.clientbound; - -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import io.netty.buffer.ByteBuf; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.With; - -import java.io.IOException; - -@Data -@With -@AllArgsConstructor -public class ClientboundSetDisplayChatPreviewPacket implements MinecraftPacket { - private final boolean enabled; - - public ClientboundSetDisplayChatPreviewPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.enabled = in.readBoolean(); - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - out.writeBoolean(this.enabled); - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSoundEntityPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSoundEntityPacket.java index 5a959024..eca9d199 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSoundEntityPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSoundEntityPacket.java @@ -3,6 +3,8 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound; +import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound; +import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; import com.github.steveice10.mc.protocol.data.game.level.sound.SoundCategory; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -16,15 +18,15 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundSoundEntityPacket implements MinecraftPacket { - private final @NonNull BuiltinSound sound; + private final @NonNull Sound sound; private final @NonNull SoundCategory category; private final int entityId; private final float volume; private final float pitch; private final long seed; - public ClientboundSoundEntityPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.sound = helper.readBuiltinSound(in); + public ClientboundSoundEntityPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.sound = helper.readById(in, BuiltinSound::from, helper::readSoundEvent); this.category = helper.readSoundCategory(in); this.entityId = helper.readVarInt(in); this.volume = in.readFloat(); @@ -34,7 +36,12 @@ public class ClientboundSoundEntityPacket implements MinecraftPacket { @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeBuiltinSound(out, this.sound); + if (this.sound instanceof CustomSound) { + helper.writeVarInt(out, 0); + helper.writeSoundEvent(out, this.sound); + } else { + helper.writeVarInt(out, ((BuiltinSound) this.sound).ordinal() + 1); + } helper.writeSoundCategory(out, this.category); helper.writeVarInt(out, this.entityId); out.writeFloat(this.volume); diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundStopSoundPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundStopSoundPacket.java index 2260404e..2a0b9120 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundStopSoundPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundStopSoundPacket.java @@ -22,7 +22,7 @@ public class ClientboundStopSoundPacket implements MinecraftPacket { private static final int FLAG_SOUND = 0x02; private final @Nullable SoundCategory category; - private final @Nullable Sound sound; + private final @Nullable String sound; public ClientboundStopSoundPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { int flags = in.readByte(); @@ -33,13 +33,7 @@ public class ClientboundStopSoundPacket implements MinecraftPacket { } if ((flags & FLAG_SOUND) != 0) { - String value = helper.readString(in); - Sound sound = helper.getBuiltinSound(value); - if (sound != null) { - this.sound = sound; - } else { - this.sound = new CustomSound(value); - } + this.sound = helper.readResourceLocation(in); } else { this.sound = null; } @@ -62,14 +56,7 @@ public class ClientboundStopSoundPacket implements MinecraftPacket { } if (this.sound != null) { - String value = ""; - if (this.sound instanceof CustomSound) { - value = ((CustomSound) this.sound).getName(); - } else if (this.sound instanceof BuiltinSound) { - value = ((BuiltinSound) this.sound).getName(); - } - - helper.writeString(out, value); + helper.writeResourceLocation(out, this.sound); } } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSystemChatPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSystemChatPacket.java index 7290ddaa..2eda4d2f 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSystemChatPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundSystemChatPacket.java @@ -3,7 +3,6 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; -import com.github.steveice10.mc.protocol.data.game.BuiltinChatType; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -16,17 +15,17 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundSystemChatPacket implements MinecraftPacket { - private final Component content; - private final boolean overlay; + private final Component content; + private final boolean overlay; - public ClientboundSystemChatPacket(ByteBuf in, MinecraftCodecHelper helper) { - this.content = helper.readComponent(in); - this.overlay = in.readBoolean(); - } + public ClientboundSystemChatPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.content = helper.readComponent(in); + this.overlay = in.readBoolean(); + } - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeString(out, DefaultComponentSerializer.get().serialize(this.content)); - out.writeBoolean(this.overlay); - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeString(out, DefaultComponentSerializer.get().serialize(this.content)); + out.writeBoolean(this.overlay); + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateEnabledFeaturesPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateEnabledFeaturesPacket.java new file mode 100644 index 00000000..1aaccc4a --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateEnabledFeaturesPacket.java @@ -0,0 +1,31 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +import java.io.IOException; + +@Data +@With +@AllArgsConstructor +public class ClientboundUpdateEnabledFeaturesPacket implements MinecraftPacket { + private final String[] features; + + public ClientboundUpdateEnabledFeaturesPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.features = new String[helper.readVarInt(in)]; + for (int i = 0; i < this.features.length; i++) { + this.features[i] = helper.readString(in); + } + } + + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeVarInt(out, this.features.length); + for (String feature : this.features) { + helper.writeString(out, feature); + } + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java index b22dedb7..f919708e 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java @@ -5,6 +5,7 @@ import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.github.steveice10.mc.protocol.data.MagicValues; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.recipe.CraftingBookCategory; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; @@ -28,10 +29,11 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { for (int i = 0; i < this.recipes.length; i++) { RecipeType type = MagicValues.key(RecipeType.class, Identifier.formalize(helper.readString(in))); String identifier = helper.readString(in); - RecipeData data = null; + RecipeData data; switch (type) { case CRAFTING_SHAPELESS: { String group = helper.readString(in); + CraftingBookCategory category = CraftingBookCategory.from(helper.readVarInt(in)); Ingredient[] ingredients = new Ingredient[helper.readVarInt(in)]; for (int j = 0; j < ingredients.length; j++) { ingredients[j] = helper.readRecipeIngredient(in); @@ -39,13 +41,14 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { ItemStack result = helper.readItemStack(in); - data = new ShapelessRecipeData(group, ingredients, result); + data = new ShapelessRecipeData(group, category, ingredients, result); break; } case CRAFTING_SHAPED: { int width = helper.readVarInt(in); int height = helper.readVarInt(in); String group = helper.readString(in); + CraftingBookCategory category = CraftingBookCategory.from(helper.readVarInt(in)); Ingredient[] ingredients = new Ingredient[width * height]; for (int j = 0; j < ingredients.length; j++) { ingredients[j] = helper.readRecipeIngredient(in); @@ -53,7 +56,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { ItemStack result = helper.readItemStack(in); - data = new ShapedRecipeData(width, height, group, ingredients, result); + data = new ShapedRecipeData(width, height, group, category, ingredients, result); break; } case SMELTING: @@ -61,12 +64,13 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { case SMOKING: case CAMPFIRE_COOKING: { String group = helper.readString(in); + CraftingBookCategory category = CraftingBookCategory.from(helper.readVarInt(in)); Ingredient ingredient = helper.readRecipeIngredient(in); ItemStack result = helper.readItemStack(in); float experience = in.readFloat(); int cookingTime = helper.readVarInt(in); - data = new CookedRecipeData(group, ingredient, result, experience, cookingTime); + data = new CookedRecipeData(group, category, ingredient, result, experience, cookingTime); break; } case STONECUTTING: { @@ -85,8 +89,12 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { data = new SmithingRecipeData(base, addition, result); break; } - default: + default: { + CraftingBookCategory category = CraftingBookCategory.from(helper.readVarInt(in)); + + data = new SimpleCraftingRecipeData(category); break; + } } this.recipes[i] = new Recipe(type, identifier, data); @@ -104,6 +112,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { ShapelessRecipeData data = (ShapelessRecipeData) recipe.getData(); helper.writeString(out, data.getGroup()); + helper.writeVarInt(out, data.getCategory().ordinal()); helper.writeVarInt(out, data.getIngredients().length); for (Ingredient ingredient : data.getIngredients()) { helper.writeRecipeIngredient(out, ingredient); @@ -121,6 +130,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeVarInt(out, data.getWidth()); helper.writeVarInt(out, data.getHeight()); helper.writeString(out, data.getGroup()); + helper.writeVarInt(out, data.getCategory().ordinal()); for (Ingredient ingredient : data.getIngredients()) { helper.writeRecipeIngredient(out, ingredient); } @@ -135,6 +145,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { CookedRecipeData data = (CookedRecipeData) recipe.getData(); helper.writeString(out, data.getGroup()); + helper.writeVarInt(out, data.getCategory().ordinal()); helper.writeRecipeIngredient(out, data.getIngredient()); helper.writeItemStack(out, data.getResult()); out.writeFloat(data.getExperience()); @@ -157,8 +168,12 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeItemStack(out, data.getResult()); break; } - default: + default: { + SimpleCraftingRecipeData data = (SimpleCraftingRecipeData) recipe.getData(); + + helper.writeVarInt(out, data.getCategory().ordinal()); break; + } } } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundBlockChangedAckPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundBlockChangedAckPacket.java index 5859a5cf..473fb0ac 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundBlockChangedAckPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundBlockChangedAckPacket.java @@ -13,14 +13,14 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundBlockChangedAckPacket implements MinecraftPacket { - private final int sequence; + private final int sequence; - public ClientboundBlockChangedAckPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.sequence = helper.readVarInt(in); - } + public ClientboundBlockChangedAckPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.sequence = helper.readVarInt(in); + } - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeVarInt(out, this.sequence); - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeVarInt(out, this.sequence); + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundCustomSoundPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundCustomSoundPacket.java deleted file mode 100644 index 617ab67b..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundCustomSoundPacket.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level; - -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound; -import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound; -import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; -import com.github.steveice10.mc.protocol.data.game.level.sound.SoundCategory; -import io.netty.buffer.ByteBuf; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NonNull; -import lombok.With; - -import java.io.IOException; - -@Data -@With -@AllArgsConstructor -public class ClientboundCustomSoundPacket implements MinecraftPacket { - private final @NonNull Sound sound; - private final @NonNull SoundCategory category; - private final double x; - private final double y; - private final double z; - private final float volume; - private final float pitch; - private final long seed; - - public ClientboundCustomSoundPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - String value = helper.readString(in); - Sound sound = helper.getBuiltinSound(value); - if (sound != null) { - this.sound = sound; - } else { - this.sound = new CustomSound(value); - } - - this.category = helper.readSoundCategory(in); - this.x = in.readInt() / 8D; - this.y = in.readInt() / 8D; - this.z = in.readInt() / 8D; - this.volume = in.readFloat(); - this.pitch = in.readFloat(); - this.seed = in.readLong(); - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - String value = ""; - if (this.sound instanceof CustomSound) { - value = ((CustomSound) this.sound).getName(); - } else if (this.sound instanceof BuiltinSound) { - value = ((BuiltinSound) this.sound).getName(); - } - - helper.writeString(out, value); - helper.writeSoundCategory(out, this.category); - out.writeInt((int) (this.x * 8)); - out.writeInt((int) (this.y * 8)); - out.writeInt((int) (this.z * 8)); - out.writeFloat(this.volume); - out.writeFloat(this.pitch); - out.writeLong(this.seed); - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundExplodePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundExplodePacket.java index 40e46ab6..21e1b25b 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundExplodePacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundExplodePacket.java @@ -17,9 +17,9 @@ import java.util.List; @With @AllArgsConstructor public class ClientboundExplodePacket implements MinecraftPacket { - private final float x; - private final float y; - private final float z; + private final double x; + private final double y; + private final double z; private final float radius; private final @NonNull List exploded; private final float pushX; @@ -27,9 +27,9 @@ public class ClientboundExplodePacket implements MinecraftPacket { private final float pushZ; public ClientboundExplodePacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.x = in.readFloat(); - this.y = in.readFloat(); - this.z = in.readFloat(); + this.x = in.readDouble(); + this.y = in.readDouble(); + this.z = in.readDouble(); this.radius = in.readFloat(); this.exploded = new ArrayList<>(); int length = helper.readVarInt(in); @@ -44,9 +44,9 @@ public class ClientboundExplodePacket implements MinecraftPacket { @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - out.writeFloat(this.x); - out.writeFloat(this.y); - out.writeFloat(this.z); + out.writeDouble(this.x); + out.writeDouble(this.y); + out.writeDouble(this.z); out.writeFloat(this.radius); helper.writeVarInt(out, this.exploded.size()); for (Vector3i record : this.exploded) { diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundGameEventPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundGameEventPacket.java index ba3364eb..b87f9ba5 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundGameEventPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundGameEventPacket.java @@ -25,7 +25,7 @@ public class ClientboundGameEventPacket implements MinecraftPacket { float value = in.readFloat(); // TODO: Handle this in MinecraftCodecHelper if (this.notification == GameEvent.CHANGE_GAMEMODE) { - this.value = MagicValues.key(GameMode.class, ((int) value == -1) ? 255 : (int) value); // https://bugs.mojang.com/browse/MC-189885 - since we read as a float this bug doesn't apply here + this.value = MagicValues.key(GameMode.class, (int) value); } else if (this.notification == GameEvent.DEMO_MESSAGE) { this.value = MagicValues.key(DemoMessageValue.class, (int) value); } else if (this.notification == GameEvent.ENTER_CREDITS) { @@ -46,9 +46,7 @@ public class ClientboundGameEventPacket implements MinecraftPacket { out.writeByte(MagicValues.value(Integer.class, this.notification)); float value = 0; // TODO: Handle this in MinecraftCodecHelper - if (this.value instanceof GameMode && this.value == GameMode.UNKNOWN) { - value = -1; - } else if (this.value instanceof Enum) { + if (this.value instanceof Enum) { value = MagicValues.value(Integer.class, (Enum) this.value); } else if (this.value instanceof RainStrengthValue) { value = ((RainStrengthValue) this.value).getStrength(); diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSoundPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSoundPacket.java index 4de918b7..d7934f06 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSoundPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSoundPacket.java @@ -3,6 +3,8 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound; +import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound; +import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; import com.github.steveice10.mc.protocol.data.game.level.sound.SoundCategory; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -16,7 +18,7 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundSoundPacket implements MinecraftPacket { - private final @NonNull BuiltinSound sound; + private final @NonNull Sound sound; private final @NonNull SoundCategory category; private final double x; private final double y; @@ -25,8 +27,8 @@ public class ClientboundSoundPacket implements MinecraftPacket { private final float pitch; private final long seed; - public ClientboundSoundPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.sound = helper.readBuiltinSound(in); + public ClientboundSoundPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.sound = helper.readById(in, BuiltinSound::from, helper::readSoundEvent); this.category = helper.readSoundCategory(in); this.x = in.readInt() / 8D; this.y = in.readInt() / 8D; @@ -38,7 +40,12 @@ public class ClientboundSoundPacket implements MinecraftPacket { @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeBuiltinSound(out, this.sound); + if (this.sound instanceof CustomSound) { + helper.writeVarInt(out, 0); + helper.writeSoundEvent(out, this.sound); + } else { + helper.writeVarInt(out, ((BuiltinSound) this.sound).ordinal() + 1); + } helper.writeSoundCategory(out, this.category); out.writeInt((int) (this.x * 8)); out.writeInt((int) (this.y * 8)); diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatAckPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatAckPacket.java index a2539851..c2ed486d 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatAckPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatAckPacket.java @@ -2,54 +2,25 @@ package com.github.steveice10.mc.protocol.packet.ingame.serverbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.game.LastSeenMessage; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; import lombok.With; -import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; @Data @With @AllArgsConstructor public class ServerboundChatAckPacket implements MinecraftPacket { - private final List lastSeenMessages; - private final @Nullable LastSeenMessage lastReceivedMessage; + private final int offset; - public ServerboundChatAckPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.lastSeenMessages = new ArrayList<>(); - int seenMessageCount = Math.min(helper.readVarInt(in), 5); - for (int i = 0; i < seenMessageCount; i++) { - lastSeenMessages.add(new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in))); - } + public ServerboundChatAckPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.offset = helper.readVarInt(in); + } - if (in.readBoolean()) { - this.lastReceivedMessage = new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in)); - } else { - this.lastReceivedMessage = null; - } - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeVarInt(out, this.lastSeenMessages.size()); - for (LastSeenMessage entry : this.lastSeenMessages) { - helper.writeUUID(out, entry.getProfileId()); - helper.writeVarInt(out, entry.getLastSignature().length); - out.writeBytes(entry.getLastSignature()); - } - - if (this.lastReceivedMessage != null) { - out.writeBoolean(true); - helper.writeUUID(out, this.lastReceivedMessage.getProfileId()); - helper.writeVarInt(out, this.lastReceivedMessage.getLastSignature().length); - out.writeBytes(this.lastReceivedMessage.getLastSignature()); - } else { - out.writeBoolean(false); - } - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeVarInt(out, this.offset); + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java index f897d815..637d971d 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java @@ -3,83 +3,53 @@ package com.github.steveice10.mc.protocol.packet.ingame.serverbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.github.steveice10.mc.protocol.data.game.ArgumentSignature; -import com.github.steveice10.mc.protocol.data.game.LastSeenMessage; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; import lombok.With; -import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; +import java.util.BitSet; import java.util.List; -import java.util.Map; -import java.util.UUID; @Data @With @AllArgsConstructor public class ServerboundChatCommandPacket implements MinecraftPacket { - private final String command; - private final long timeStamp; - private final long salt; - private final List signatures; - private final boolean signedPreview; - private final List lastSeenMessages; - private final @Nullable LastSeenMessage lastReceivedMessage; + private final String command; + private final long timeStamp; + private final long salt; + private final List signatures; + private final int offset; + private final BitSet acknowledgedMessages; - public ServerboundChatCommandPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.command = helper.readString(in); - this.timeStamp = in.readLong(); - this.salt = in.readLong(); - this.signatures = new ArrayList<>(); - int signatureCount = Math.min(helper.readVarInt(in), 8); - for (int i = 0; i < signatureCount; i++) { - signatures.add(new ArgumentSignature(helper.readString(in), helper.readByteArray(in))); - } + public ServerboundChatCommandPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.command = helper.readString(in); + this.timeStamp = in.readLong(); + this.salt = in.readLong(); + this.signatures = new ArrayList<>(); + int signatureCount = Math.min(helper.readVarInt(in), 8); + for (int i = 0; i < signatureCount; i++) { + signatures.add(new ArgumentSignature(helper.readString(in, 16), in.readBytes(new byte[256]).array())); + } - this.signedPreview = in.readBoolean(); - this.lastSeenMessages = new ArrayList<>(); - int seenMessageCount = Math.min(helper.readVarInt(in), 5); - for (int i = 0; i < seenMessageCount; i++) { - lastSeenMessages.add(new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in))); - } + this.offset = helper.readVarInt(in); + this.acknowledgedMessages = helper.readFixedBitSet(in, 20); + } - if (in.readBoolean()) { - this.lastReceivedMessage = new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in)); - } else { - this.lastReceivedMessage = null; - } - } + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeString(out, this.command); + out.writeLong(this.timeStamp); + out.writeLong(this.salt); + helper.writeVarInt(out, this.signatures.size()); + for (ArgumentSignature signature : this.signatures) { + helper.writeString(out, signature.getName()); + out.writeBytes(signature.getSignature()); + } - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - helper.writeString(out, this.command); - out.writeLong(this.timeStamp); - out.writeLong(this.salt); - helper.writeVarInt(out, this.signatures.size()); - for (ArgumentSignature signature : this.signatures) { - helper.writeString(out, signature.getName()); - helper.writeVarInt(out, signature.getSignature().length); - out.writeBytes(signature.getSignature()); - } - - out.writeBoolean(this.signedPreview); - helper.writeVarInt(out, this.lastSeenMessages.size()); - for (LastSeenMessage entry : this.lastSeenMessages) { - helper.writeUUID(out, entry.getProfileId()); - helper.writeVarInt(out, entry.getLastSignature().length); - out.writeBytes(entry.getLastSignature()); - } - - if (this.lastReceivedMessage != null) { - out.writeBoolean(true); - helper.writeUUID(out, this.lastReceivedMessage.getProfileId()); - helper.writeVarInt(out, this.lastReceivedMessage.getLastSignature().length); - out.writeBytes(this.lastReceivedMessage.getLastSignature()); - } else { - out.writeBoolean(false); - } - } + helper.writeVarInt(out, this.offset); + helper.writeFixedBitSet(out, this.acknowledgedMessages, 20); + } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPacket.java index e9bc96c6..bc1b9800 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPacket.java @@ -2,7 +2,6 @@ package com.github.steveice10.mc.protocol.packet.ingame.serverbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.game.LastSeenMessage; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -11,8 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.BitSet; @Data @With @@ -21,28 +19,22 @@ public class ServerboundChatPacket implements MinecraftPacket { private final @NotNull String message; private final long timeStamp; private final long salt; - private final byte @NotNull[] signature; - private final boolean signedPreview; - private final List lastSeenMessages; - private final @Nullable LastSeenMessage lastReceivedMessage; + private final byte @Nullable[] signature; + private final int offset; + private final BitSet acknowledgedMessages; public ServerboundChatPacket(ByteBuf in, MinecraftCodecHelper helper) { this.message = helper.readString(in); this.timeStamp = in.readLong(); this.salt = in.readLong(); - this.signature = helper.readByteArray(in); - this.signedPreview = in.readBoolean(); - this.lastSeenMessages = new ArrayList<>(); - int seenMessageCount = Math.min(helper.readVarInt(in), 5); - for (int i = 0; i < seenMessageCount; i++) { - lastSeenMessages.add(new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in))); + if (in.readBoolean()) { + this.signature = in.readBytes(new byte[256]).array(); + } else { + this.signature = null; } - if (in.readBoolean()) { - this.lastReceivedMessage = new LastSeenMessage(helper.readUUID(in), helper.readByteArray(in)); - } else { - this.lastReceivedMessage = null; - } + this.offset = helper.readVarInt(in); + this.acknowledgedMessages = helper.readFixedBitSet(in, 20); } @Override @@ -50,23 +42,12 @@ public class ServerboundChatPacket implements MinecraftPacket { helper.writeString(out, this.message); out.writeLong(this.timeStamp); out.writeLong(this.salt); - helper.writeVarInt(out, this.signature.length); - out.writeBytes(this.signature); - out.writeBoolean(this.signedPreview); - helper.writeVarInt(out, this.lastSeenMessages.size()); - for (LastSeenMessage entry : this.lastSeenMessages) { - helper.writeUUID(out, entry.getProfileId()); - helper.writeVarInt(out, entry.getLastSignature().length); - out.writeBytes(entry.getLastSignature()); + out.writeBoolean(this.signature != null); + if (this.signature != null) { + out.writeBytes(this.signature); } - if (this.lastReceivedMessage != null) { - out.writeBoolean(true); - helper.writeUUID(out, this.lastReceivedMessage.getProfileId()); - helper.writeVarInt(out, this.lastReceivedMessage.getLastSignature().length); - out.writeBytes(this.lastReceivedMessage.getLastSignature()); - } else { - out.writeBoolean(false); - } + helper.writeVarInt(out, this.offset); + helper.writeFixedBitSet(out, this.acknowledgedMessages, 20); } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPreviewPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPreviewPacket.java deleted file mode 100644 index e30976d2..00000000 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatPreviewPacket.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.steveice10.mc.protocol.packet.ingame.serverbound; - -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import io.netty.buffer.ByteBuf; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.With; - -import java.io.IOException; - -@Data -@With -@AllArgsConstructor -public class ServerboundChatPreviewPacket implements MinecraftPacket { - private final int queryId; - private final String query; - - public ServerboundChatPreviewPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.queryId = in.readInt(); - this.query = helper.readString(in); - } - - @Override - public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - out.writeInt(this.queryId); - helper.writeString(out, this.query); - } -} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatSessionUpdatePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatSessionUpdatePacket.java new file mode 100644 index 00000000..7b66ca01 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/serverbound/ServerboundChatSessionUpdatePacket.java @@ -0,0 +1,49 @@ +package com.github.steveice10.mc.protocol.packet.ingame.serverbound; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.UUID; + +@Data +@With +@AllArgsConstructor +public class ServerboundChatSessionUpdatePacket implements MinecraftPacket { + private final UUID sessionId; + private final long expiresAt; + private final PublicKey publicKey; + private final byte[] keySignature; + + public ServerboundChatSessionUpdatePacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { + this.sessionId = helper.readUUID(in); + this.expiresAt = in.readLong(); + byte[] keyBytes = helper.readByteArray(in); + this.keySignature = helper.readByteArray(in); + + PublicKey publicKey = null; + try { + publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes)); + } catch (GeneralSecurityException e) { + throw new IOException("Could not decode public key.", e); + } + + this.publicKey = publicKey; + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { + helper.writeUUID(out, this.sessionId); + out.writeLong(this.expiresAt); + helper.writeByteArray(out, this.publicKey.getEncoded()); + helper.writeByteArray(out, this.keySignature); + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/login/clientbound/ClientboundHelloPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/login/clientbound/ClientboundHelloPacket.java index c4e90774..193b182f 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/login/clientbound/ClientboundHelloPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/login/clientbound/ClientboundHelloPacket.java @@ -20,12 +20,12 @@ import java.security.spec.X509EncodedKeySpec; public class ClientboundHelloPacket implements MinecraftPacket { private final @NonNull String serverId; private final @NonNull PublicKey publicKey; - private final @NonNull byte[] verifyToken; + private final @NonNull byte[] challenge; public ClientboundHelloPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { this.serverId = helper.readString(in); byte[] publicKey = helper.readByteArray(in); - this.verifyToken = helper.readByteArray(in); + this.challenge = helper.readByteArray(in); try { this.publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey)); @@ -39,7 +39,7 @@ public class ClientboundHelloPacket implements MinecraftPacket { helper.writeString(out, this.serverId); byte[] encoded = this.publicKey.getEncoded(); helper.writeByteArray(out, encoded); - helper.writeByteArray(out, this.verifyToken); + helper.writeByteArray(out, this.challenge); } @Override diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacket.java index b95c8612..b711ddc4 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacket.java @@ -23,26 +23,16 @@ import java.util.UUID; @AllArgsConstructor public class ServerboundHelloPacket implements MinecraftPacket { private final @NonNull String username; - private final @Nullable ProfilePublicKeyData publicKey; private final @Nullable UUID profileId; public ServerboundHelloPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { this.username = helper.readString(in); - if (in.readBoolean()) { - this.publicKey = new ProfilePublicKeyData(in, helper); - } else { - this.publicKey = null; - } this.profileId = helper.readNullable(in, helper::readUUID); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { helper.writeString(out, this.username); - out.writeBoolean(this.publicKey != null); - if (this.publicKey != null) { - this.publicKey.serialize(out, helper); - } helper.writeNullable(out, this.profileId, helper::writeUUID); } @@ -50,49 +40,4 @@ public class ServerboundHelloPacket implements MinecraftPacket { public boolean isPriority() { return true; } - - // Likely temporary; will be moved to AuthLib when full public key support is developed - public static class ProfilePublicKeyData { - private final long expiresAt; - private final PublicKey publicKey; - private final byte[] keySignature; - - public ProfilePublicKeyData(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - this.expiresAt = in.readLong(); - byte[] publicKey = helper.readByteArray(in); - this.keySignature = helper.readByteArray(in); - - try { - this.publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey)); - } catch (GeneralSecurityException e) { - throw new IOException("Could not decode public key.", e); - } - } - - public ProfilePublicKeyData(long expiresAt, PublicKey publicKey, byte[] keySignature) { - this.expiresAt = expiresAt; - this.publicKey = publicKey; - this.keySignature = keySignature; - } - - private void serialize(ByteBuf out, MinecraftCodecHelper helper) { - out.writeLong(this.expiresAt); - byte[] encoded = this.publicKey.getEncoded(); - helper.writeByteArray(out, encoded); - helper.writeByteArray(out, this.keySignature); - } - - @Contract("-> new") - public Instant getExpiresAt() { - return Instant.ofEpochMilli(this.expiresAt); - } - - public PublicKey getPublicKey() { - return publicKey; - } - - public byte[] getKeySignature() { - return keySignature; - } - } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacket.java index d43e7cb4..0c8081af 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacket.java @@ -6,8 +6,6 @@ import io.netty.buffer.ByteBuf; import lombok.EqualsAndHashCode; import lombok.NonNull; import lombok.ToString; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.crypto.Cipher; import javax.crypto.SecretKey; @@ -17,76 +15,31 @@ import java.security.*; @ToString @EqualsAndHashCode public class ServerboundKeyPacket implements MinecraftPacket { - private final @NonNull byte[] sharedKey; - private final @Nullable byte[] verifyToken; - private final @Nullable SaltSignaturePair saltSignature; + private final byte @NonNull[] sharedKey; + private final byte @NonNull[] encryptedChallenge; - public ServerboundKeyPacket(PublicKey publicKey, SecretKey secretKey, byte[] verifyToken) { + public ServerboundKeyPacket(PublicKey publicKey, SecretKey secretKey, byte[] challenge) { this.sharedKey = runEncryption(Cipher.ENCRYPT_MODE, publicKey, secretKey.getEncoded()); - this.verifyToken = runEncryption(Cipher.ENCRYPT_MODE, publicKey, verifyToken); - this.saltSignature = null; - } - - public ServerboundKeyPacket(PublicKey publicKey, SecretKey secretKey, @NotNull SaltSignaturePair saltSignature) { - this.sharedKey = runEncryption(Cipher.ENCRYPT_MODE, publicKey, secretKey.getEncoded()); - this.saltSignature = saltSignature; - this.verifyToken = null; + this.encryptedChallenge = runEncryption(Cipher.ENCRYPT_MODE, publicKey, challenge); } public SecretKey getSecretKey(PrivateKey privateKey) { return new SecretKeySpec(runEncryption(Cipher.DECRYPT_MODE, privateKey, this.sharedKey), "AES"); } - public byte[] getVerifyToken(PrivateKey privateKey) { - return runEncryption(Cipher.DECRYPT_MODE, privateKey, this.verifyToken); - } - - public boolean verifyWithSaltSignature(byte[] verifyToken, ServerboundHelloPacket.ProfilePublicKeyData profilePublicKeyData) { - try { - Signature signature = Signature.getInstance("SHA256withRSA"); - signature.initVerify(profilePublicKeyData.getPublicKey()); - - signature.update(verifyToken); - signature.update(toByteArray(saltSignature.getSalt())); - - return signature.verify(saltSignature.getSignature()); - } catch (InvalidKeyException | SignatureException | NoSuchAlgorithmException e) { - e.printStackTrace(); - return false; - } - } - - private byte[] toByteArray(long value) { - // Copied from Guava - byte[] result = new byte[8]; - for (int i = 7; i >= 0; i--) { - result[i] = (byte) (value & 0xffL); - value >>= 8; - } - return result; + public byte[] getEncryptedChallenge(PrivateKey privateKey) { + return runEncryption(Cipher.DECRYPT_MODE, privateKey, this.encryptedChallenge); } public ServerboundKeyPacket(ByteBuf in, MinecraftCodecHelper helper) { this.sharedKey = helper.readByteArray(in); - if (in.readBoolean()) { - this.verifyToken = helper.readByteArray(in); - this.saltSignature = null; - } else { - this.saltSignature = new SaltSignaturePair(in.readLong(), helper.readByteArray(in)); - this.verifyToken = null; - } + this.encryptedChallenge = helper.readByteArray(in); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { helper.writeByteArray(out, this.sharedKey); - out.writeBoolean(this.verifyToken != null); - if (this.verifyToken != null) { - helper.writeByteArray(out, this.verifyToken); - } else { - out.writeLong(this.saltSignature.salt); - helper.writeByteArray(out, this.saltSignature.signature); - } + helper.writeByteArray(out, this.encryptedChallenge); } @Override @@ -103,22 +56,4 @@ public class ServerboundKeyPacket implements MinecraftPacket { throw new IllegalStateException("Failed to " + (mode == Cipher.DECRYPT_MODE ? "decrypt" : "encrypt") + " data.", e); } } - - public static class SaltSignaturePair { - private final long salt; - private final byte[] signature; - - public SaltSignaturePair(long salt, byte[] signature) { - this.salt = salt; - this.signature = signature; - } - - public long getSalt() { - return salt; - } - - public byte[] getSignature() { - return signature; - } - } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java index 21dd9e30..a0575afd 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java @@ -53,8 +53,8 @@ public class ClientboundStatusResponsePacket implements MinecraftPacket { icon = this.stringToIcon(obj.get("favicon").getAsString()); } - boolean previewsChat = obj.get("previewsChat").getAsBoolean(); - this.info = new ServerStatusInfo(version, players, description, icon, previewsChat); + boolean enforcesSecureChat = obj.get("enforcesSecureChat").getAsBoolean(); + this.info = new ServerStatusInfo(version, players, description, icon, enforcesSecureChat); } @Override @@ -84,7 +84,7 @@ public class ClientboundStatusResponsePacket implements MinecraftPacket { if (this.info.getIconPng() != null) { obj.addProperty("favicon", this.iconToString(this.info.getIconPng())); } - obj.addProperty("previewsChat", this.info.isPreviewsChat()); + obj.addProperty("enforcesSecureChat", this.info.isEnforcesSecureChat()); helper.writeString(out, obj.toString()); } diff --git a/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java b/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java index 41357670..0e1a8291 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java @@ -51,7 +51,7 @@ public class MinecraftProtocolTest { null, false ); - private static final ClientboundLoginPacket JOIN_GAME_PACKET = new ClientboundLoginPacket(0, false, GameMode.SURVIVAL, GameMode.SURVIVAL, 1, new String[]{"minecraft:world"}, loadNetworkCodec(), "overworld", "minecraft:world", 100, 0, 16, 16, false, false, false, false, null); + private static final ClientboundLoginPacket JOIN_GAME_PACKET = new ClientboundLoginPacket(0, false, GameMode.SURVIVAL, GameMode.SURVIVAL, new String[]{"minecraft:world"}, loadLoginRegistry(), "overworld", "minecraft:world", 100, 0, 16, 16, false, false, false, false, null); private static Server server; @@ -142,8 +142,8 @@ public class MinecraftProtocolTest { } } - public static CompoundTag loadNetworkCodec() { - try (InputStream inputStream = MinecraftProtocolTest.class.getClassLoader().getResourceAsStream("network_codec.nbt"); + public static CompoundTag loadLoginRegistry() { + try (InputStream inputStream = MinecraftProtocolTest.class.getClassLoader().getResourceAsStream("networkCodec.nbt"); DataInputStream stream = new DataInputStream(new GZIPInputStream(inputStream))) { return (CompoundTag) NBTIO.readTag((DataInput) stream); } catch (IOException e) { diff --git a/src/test/java/com/github/steveice10/mc/protocol/data/MagicValuesTest.java b/src/test/java/com/github/steveice10/mc/protocol/data/MagicValuesTest.java index 8773afd3..92c36bb6 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/data/MagicValuesTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/data/MagicValuesTest.java @@ -4,7 +4,6 @@ import com.github.steveice10.mc.protocol.data.game.BossBarAction; import com.github.steveice10.mc.protocol.data.game.BossBarColor; import com.github.steveice10.mc.protocol.data.game.BossBarDivision; import com.github.steveice10.mc.protocol.data.game.ClientCommand; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; import com.github.steveice10.mc.protocol.data.game.ResourcePackStatus; import com.github.steveice10.mc.protocol.data.game.UnlockRecipesAction; import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; @@ -139,7 +138,6 @@ public class MagicValuesTest { this.register(CollisionRule.class, String.class); this.register(ScoreType.class, Integer.class); this.register(Advancement.DisplayData.FrameType.class, Integer.class); - this.register(PlayerListEntryAction.class, Integer.class); this.register(UnlockRecipesAction.class, Integer.class); this.register(CraftingBookStateType.class, Integer.class); this.register(AdvancementTabAction.class, Integer.class); diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java index 96bafad0..839585fd 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java @@ -1,6 +1,7 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.recipe.CraftingBookCategory; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; @@ -23,6 +24,7 @@ public class ServerDeclareRecipesTest extends PacketTest { "Recipe1", new ShapelessRecipeData( "Group1", + CraftingBookCategory.MISC, new Ingredient[]{ new Ingredient(new ItemStack[]{ new ItemStack(0) @@ -38,6 +40,7 @@ public class ServerDeclareRecipesTest extends PacketTest { 2, 3, "Group2", + CraftingBookCategory.BUILDING, new Ingredient[]{ new Ingredient(new ItemStack[]{ new ItemStack(1) @@ -66,6 +69,7 @@ public class ServerDeclareRecipesTest extends PacketTest { "Recipe3", new CookedRecipeData( "Group3", + CraftingBookCategory.EQUIPMENT, new Ingredient(new ItemStack[]{ new ItemStack(7) }), diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java index 3426ed21..71e10784 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java @@ -25,8 +25,9 @@ public class ClientboundSetEntityDataPacketTest extends PacketTest { new ByteEntityMetadata(4, MetadataType.BYTE, (byte) 45), new IntEntityMetadata(2, MetadataType.INT, 555), new FloatEntityMetadata(3, MetadataType.FLOAT, 3.0f), + new LongEntityMetadata(8, MetadataType.LONG, 123456789L), new ObjectEntityMetadata<>(5, MetadataType.POSITION, Vector3i.from(0, 1, 0)), - new IntEntityMetadata(2, MetadataType.BLOCK_STATE, 60), + new ObjectEntityMetadata<>(2, MetadataType.BLOCK_STATE, OptionalInt.of(60)), new ObjectEntityMetadata<>(6, MetadataType.DIRECTION, Direction.EAST), new ObjectEntityMetadata<>(7, MetadataType.OPTIONAL_VARINT, OptionalInt.of(1038)) }), diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacketTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacketTest.java index 30671d3b..4801c497 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacketTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacketTest.java @@ -3,9 +3,11 @@ package com.github.steveice10.mc.protocol.packet.login.serverbound; import com.github.steveice10.mc.protocol.packet.PacketTest; import org.junit.Before; +import java.util.UUID; + public class ServerboundHelloPacketTest extends PacketTest { @Before public void setup() { - this.setPackets(new ServerboundHelloPacket("Username", null, null)); + this.setPackets(new ServerboundHelloPacket("Username", null)); } } diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacketTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacketTest.java index 85418dfb..b54c3db9 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacketTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundKeyPacketTest.java @@ -44,6 +44,6 @@ public class ServerboundKeyPacketTest extends PacketTest { @Test public void testEncryptionResponsePacketGetters() { assertEquals("Secret key does not match.", this.secretKey, this.packet.getSecretKey(this.keyPair.getPrivate())); - assertArrayEquals("Verify token does not match.", this.verifyToken, this.packet.getVerifyToken(this.keyPair.getPrivate())); + assertArrayEquals("Verify token does not match.", this.verifyToken, this.packet.getEncryptedChallenge(this.keyPair.getPrivate())); } } diff --git a/src/test/resources/networkCodec.nbt b/src/test/resources/networkCodec.nbt new file mode 100644 index 00000000..26f80ad0 Binary files /dev/null and b/src/test/resources/networkCodec.nbt differ diff --git a/src/test/resources/network_codec.nbt b/src/test/resources/network_codec.nbt deleted file mode 100644 index 62639299..00000000 Binary files a/src/test/resources/network_codec.nbt and /dev/null differ