Merge branch 'feature/1.19.3'

This commit is contained in:
Camotoy 2022-12-05 20:03:28 -05:00
commit 3c88c3b072
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
75 changed files with 1137 additions and 1180 deletions

View file

@ -5,7 +5,7 @@
<groupId>com.github.steveice10</groupId>
<artifactId>mcprotocollib</artifactId>
<version>1.19.2-1</version>
<version>1.19.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MCProtocolLib</name>

View file

@ -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());
}

View file

@ -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);

View file

@ -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)

View file

@ -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 <E extends Enum<E>> EnumSet<E> readEnumSet(ByteBuf buf, E[] values) {
BitSet bitSet = this.readFixedBitSet(buf, values.length);
List<E> readValues = new ArrayList<>();
for (int i = 0; i < values.length; i++) {
if (bitSet.get(i)) {
readValues.add(values[i]);
}
}
return EnumSet.copyOf(readValues);
}
public <E extends Enum<E>> void writeEnumSet(ByteBuf buf, EnumSet<E> 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> T readById(ByteBuf buf, IntFunction<T> registry, Function<ByteBuf, T> 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));
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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];
}
}

View file

@ -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];
}
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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];
}
}

View file

@ -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;

View file

@ -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];
}
}

View file

@ -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];
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -4,6 +4,5 @@ public enum SuggestionType {
ASK_SERVER,
ALL_RECIPES,
AVAILABLE_SOUNDS,
AVAILABLE_BIOMES,
SUMMONABLE_ENTITIES;
}

View file

@ -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<Long> {
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<Long, LongMetadataType> 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> {
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<Long> {
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<Long> {
LongEntityMetadata createPrimitive(int id, LongMetadataType type, long value);
@Deprecated
@Override
default EntityMetadata<Long, LongMetadataType> create(int id, MetadataType<Long> type, Long value) {
throw new UnsupportedOperationException("Unsupported read method! Use primitive createPrimitive!");
}
}
}

View file

@ -24,6 +24,7 @@ public class MetadataType<T> {
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> STRING = new MetadataType<>(MinecraftCodecHelper::readString, MinecraftCodecHelper::writeString, ObjectEntityMetadata::new);
public static final MetadataType<Component> CHAT = new MetadataType<>(MinecraftCodecHelper::readComponent, MinecraftCodecHelper::writeComponent, ObjectEntityMetadata::new);
@ -35,7 +36,7 @@ public class MetadataType<T> {
public static final MetadataType<Optional<Vector3i>> OPTIONAL_POSITION = new MetadataType<>(optionalReader(MinecraftCodecHelper::readPosition), optionalWriter(MinecraftCodecHelper::writePosition), ObjectEntityMetadata::new);
public static final MetadataType<Direction> DIRECTION = new MetadataType<>(MinecraftCodecHelper::readDirection, MinecraftCodecHelper::writeDirection, ObjectEntityMetadata::new);
public static final MetadataType<Optional<UUID>> 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<CompoundTag> NBT_TAG = new MetadataType<>(MinecraftCodecHelper::readTag, MinecraftCodecHelper::writeTag, ObjectEntityMetadata::new);
public static final MetadataType<Particle> PARTICLE = new MetadataType<>(MinecraftCodecHelper::readParticle, MinecraftCodecHelper::writeParticle, ObjectEntityMetadata::new);
public static final MetadataType<VillagerData> VILLAGER_DATA = new MetadataType<>(MinecraftCodecHelper::readVillagerData, MinecraftCodecHelper::writeVillagerData, ObjectEntityMetadata::new);

View file

@ -11,6 +11,7 @@ public enum Pose {
DYING,
CROAKING,
USING_TONGUE,
SITTING,
ROARING,
SNIFFING,
EMERGING,

View file

@ -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<Integer, IntMetadataType> {
private final int value;

View file

@ -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<Long, LongMetadataType> {
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);
}
}

View file

@ -12,6 +12,7 @@ public enum EntityType {
BOAT,
CHEST_BOAT,
CAT,
CAMEL,
CAVE_SPIDER,
CHICKEN,
COD,

View file

@ -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();

View file

@ -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.
*/

View file

@ -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;
}

View file

@ -1,4 +1,9 @@
package com.github.steveice10.mc.protocol.data.game.level.sound;
public interface Sound {
String getName();
boolean isNewSystem();
float getRange();
}

View file

@ -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];
}
}

View file

@ -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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -15,5 +15,5 @@ public class ServerStatusInfo {
private @NonNull PlayerInfo playerInfo;
private @NonNull Component description;
private byte[] iconPng;
private boolean previewsChat;
private boolean enforcesSecureChat;
}

View file

@ -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));
}
}
}

View file

@ -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:

View file

@ -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);
}
}
}

View file

@ -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());
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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<LastSeenMessage> 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<MessageSignature> 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);
}
}

View file

@ -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<GameProfile.Property> 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;
}
}
}
}

View file

@ -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<UUID> 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);
}
}
}

View file

@ -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<PlayerListEntryAction> 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<GameProfile.Property> 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;
}
}
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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<Vector3i> 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) {

View file

@ -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();

View file

@ -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));

View file

@ -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<LastSeenMessage> 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);
}
}

View file

@ -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<ArgumentSignature> signatures;
private final boolean signedPreview;
private final List<LastSeenMessage> lastSeenMessages;
private final @Nullable LastSeenMessage lastReceivedMessage;
private final String command;
private final long timeStamp;
private final long salt;
private final List<ArgumentSignature> 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);
}
}

View file

@ -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<LastSeenMessage> 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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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());
}

View file

@ -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) {

View file

@ -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);

View file

@ -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)
}),

View file

@ -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))
}),

View file

@ -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));
}
}

View file

@ -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()));
}
}

Binary file not shown.

Binary file not shown.