package org.spacehq.mc.protocol; import org.spacehq.mc.auth.data.GameProfile; import org.spacehq.mc.auth.exception.request.RequestException; import org.spacehq.mc.auth.service.AuthenticationService; import org.spacehq.mc.protocol.data.SubProtocol; import org.spacehq.mc.protocol.packet.handshake.client.HandshakePacket; import org.spacehq.mc.protocol.packet.ingame.client.*; import org.spacehq.mc.protocol.packet.ingame.client.player.*; import org.spacehq.mc.protocol.packet.ingame.client.window.*; import org.spacehq.mc.protocol.packet.ingame.client.world.*; import org.spacehq.mc.protocol.packet.ingame.server.*; import org.spacehq.mc.protocol.packet.ingame.server.entity.*; import org.spacehq.mc.protocol.packet.ingame.server.entity.player.*; import org.spacehq.mc.protocol.packet.ingame.server.entity.spawn.*; import org.spacehq.mc.protocol.packet.ingame.server.scoreboard.ServerDisplayScoreboardPacket; import org.spacehq.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket; import org.spacehq.mc.protocol.packet.ingame.server.scoreboard.ServerTeamPacket; import org.spacehq.mc.protocol.packet.ingame.server.scoreboard.ServerUpdateScorePacket; import org.spacehq.mc.protocol.packet.ingame.server.window.*; import org.spacehq.mc.protocol.packet.ingame.server.world.*; import org.spacehq.mc.protocol.packet.login.client.EncryptionResponsePacket; import org.spacehq.mc.protocol.packet.login.client.LoginStartPacket; import org.spacehq.mc.protocol.packet.login.server.EncryptionRequestPacket; import org.spacehq.mc.protocol.packet.login.server.LoginDisconnectPacket; import org.spacehq.mc.protocol.packet.login.server.LoginSetCompressionPacket; import org.spacehq.mc.protocol.packet.login.server.LoginSuccessPacket; import org.spacehq.mc.protocol.packet.status.client.StatusPingPacket; import org.spacehq.mc.protocol.packet.status.client.StatusQueryPacket; import org.spacehq.mc.protocol.packet.status.server.StatusPongPacket; import org.spacehq.mc.protocol.packet.status.server.StatusResponsePacket; import org.spacehq.packetlib.Client; import org.spacehq.packetlib.Server; import org.spacehq.packetlib.Session; import org.spacehq.packetlib.crypt.AESEncryption; import org.spacehq.packetlib.crypt.PacketEncryption; import org.spacehq.packetlib.packet.DefaultPacketHeader; import org.spacehq.packetlib.packet.PacketHeader; import org.spacehq.packetlib.packet.PacketProtocol; import java.net.Proxy; import java.security.GeneralSecurityException; import java.security.Key; import java.util.UUID; public class MinecraftProtocol extends PacketProtocol { private SubProtocol subProtocol = SubProtocol.HANDSHAKE; private PacketHeader header = new DefaultPacketHeader(); private AESEncryption encrypt; private GameProfile profile; private String accessToken = ""; @SuppressWarnings("unused") private MinecraftProtocol() { } public MinecraftProtocol(SubProtocol subProtocol) { if(subProtocol != SubProtocol.LOGIN && subProtocol != SubProtocol.STATUS) { throw new IllegalArgumentException("Only login and status modes are permitted."); } this.subProtocol = subProtocol; if(subProtocol == SubProtocol.LOGIN) { this.profile = new GameProfile((UUID) null, "Player"); } } public MinecraftProtocol(String username) { this(SubProtocol.LOGIN); this.profile = new GameProfile((UUID) null, username); } public MinecraftProtocol(String username, String password) throws RequestException { this(username, password, false); } public MinecraftProtocol(String username, String using, boolean token) throws RequestException { this(username, using, token, Proxy.NO_PROXY); } public MinecraftProtocol(String username, String using, boolean token, Proxy authProxy) throws RequestException { this(SubProtocol.LOGIN); String clientToken = UUID.randomUUID().toString(); AuthenticationService auth = new AuthenticationService(clientToken, authProxy); auth.setUsername(username); if(token) { auth.setAccessToken(using); } else { auth.setPassword(using); } auth.login(); this.profile = auth.getSelectedProfile(); this.accessToken = auth.getAccessToken(); } public MinecraftProtocol(GameProfile profile, String accessToken) { this(SubProtocol.LOGIN); this.profile = profile; this.accessToken = accessToken; } public GameProfile getProfile() { return this.profile; } public String getAccessToken() { return this.accessToken; } @Override public String getSRVRecordPrefix() { return "_minecraft"; } @Override public PacketHeader getPacketHeader() { return this.header; } @Override public PacketEncryption getEncryption() { return this.encrypt; } @Override public void newClientSession(Client client, Session session) { if(this.profile != null) { session.setFlag(MinecraftConstants.PROFILE_KEY, this.profile); session.setFlag(MinecraftConstants.ACCESS_TOKEN_KEY, this.accessToken); } this.setSubProtocol(this.subProtocol, true, session); session.addListener(new ClientListener()); } @Override public void newServerSession(Server server, Session session) { this.setSubProtocol(SubProtocol.HANDSHAKE, false, session); session.addListener(new ServerListener()); } protected void enableEncryption(Key key) { try { this.encrypt = new AESEncryption(key); } catch(GeneralSecurityException e) { throw new Error("Failed to enable protocol encryption.", e); } } public SubProtocol getSubProtocol() { return this.subProtocol; } protected void setSubProtocol(SubProtocol subProtocol, boolean client, Session session) { this.clearPackets(); switch(subProtocol) { case HANDSHAKE: if(client) { this.initClientHandshake(session); } else { this.initServerHandshake(session); } break; case LOGIN: if(client) { this.initClientLogin(session); } else { this.initServerLogin(session); } break; case GAME: if(client) { this.initClientGame(session); } else { this.initServerGame(session); } break; case STATUS: if(client) { this.initClientStatus(session); } else { this.initServerStatus(session); } break; } this.subProtocol = subProtocol; } private void initClientHandshake(Session session) { this.registerOutgoing(0, HandshakePacket.class); } private void initServerHandshake(Session session) { this.registerIncoming(0, HandshakePacket.class); } private void initClientLogin(Session session) { this.registerIncoming(0x00, LoginDisconnectPacket.class); this.registerIncoming(0x01, EncryptionRequestPacket.class); this.registerIncoming(0x02, LoginSuccessPacket.class); this.registerIncoming(0x03, LoginSetCompressionPacket.class); this.registerOutgoing(0x00, LoginStartPacket.class); this.registerOutgoing(0x01, EncryptionResponsePacket.class); } private void initServerLogin(Session session) { this.registerIncoming(0x00, LoginStartPacket.class); this.registerIncoming(0x01, EncryptionResponsePacket.class); this.registerOutgoing(0x00, LoginDisconnectPacket.class); this.registerOutgoing(0x01, EncryptionRequestPacket.class); this.registerOutgoing(0x02, LoginSuccessPacket.class); this.registerOutgoing(0x03, LoginSetCompressionPacket.class); } private void initClientGame(Session session) { this.registerIncoming(0x00, ServerSpawnObjectPacket.class); this.registerIncoming(0x01, ServerSpawnExpOrbPacket.class); this.registerIncoming(0x02, ServerSpawnGlobalEntityPacket.class); this.registerIncoming(0x03, ServerSpawnMobPacket.class); this.registerIncoming(0x04, ServerSpawnPaintingPacket.class); this.registerIncoming(0x05, ServerSpawnPlayerPacket.class); this.registerIncoming(0x06, ServerEntityAnimationPacket.class); this.registerIncoming(0x07, ServerStatisticsPacket.class); this.registerIncoming(0x08, ServerBlockBreakAnimPacket.class); this.registerIncoming(0x09, ServerUpdateTileEntityPacket.class); this.registerIncoming(0x0A, ServerBlockValuePacket.class); this.registerIncoming(0x0B, ServerBlockChangePacket.class); this.registerIncoming(0x0C, ServerBossBarPacket.class); this.registerIncoming(0x0D, ServerDifficultyPacket.class); this.registerIncoming(0x0E, ServerTabCompletePacket.class); this.registerIncoming(0x0F, ServerChatPacket.class); this.registerIncoming(0x10, ServerMultiBlockChangePacket.class); this.registerIncoming(0x11, ServerConfirmTransactionPacket.class); this.registerIncoming(0x12, ServerCloseWindowPacket.class); this.registerIncoming(0x13, ServerOpenWindowPacket.class); this.registerIncoming(0x14, ServerWindowItemsPacket.class); this.registerIncoming(0x15, ServerWindowPropertyPacket.class); this.registerIncoming(0x16, ServerSetSlotPacket.class); this.registerIncoming(0x17, ServerSetCooldownPacket.class); this.registerIncoming(0x18, ServerPluginMessagePacket.class); this.registerIncoming(0x19, ServerPlaySoundPacket.class); this.registerIncoming(0x1A, ServerDisconnectPacket.class); this.registerIncoming(0x1B, ServerEntityStatusPacket.class); this.registerIncoming(0x1C, ServerExplosionPacket.class); this.registerIncoming(0x1D, ServerUnloadChunkPacket.class); this.registerIncoming(0x1E, ServerNotifyClientPacket.class); this.registerIncoming(0x1F, ServerKeepAlivePacket.class); this.registerIncoming(0x20, ServerChunkDataPacket.class); this.registerIncoming(0x21, ServerPlayEffectPacket.class); this.registerIncoming(0x22, ServerSpawnParticlePacket.class); this.registerIncoming(0x23, ServerJoinGamePacket.class); this.registerIncoming(0x24, ServerMapDataPacket.class); this.registerIncoming(0x25, ServerEntityPositionPacket.class); this.registerIncoming(0x26, ServerEntityPositionRotationPacket.class); this.registerIncoming(0x27, ServerEntityRotationPacket.class); this.registerIncoming(0x28, ServerEntityMovementPacket.class); this.registerIncoming(0x29, ServerVehicleMovePacket.class); this.registerIncoming(0x2A, ServerOpenTileEntityEditorPacket.class); this.registerIncoming(0x2B, ServerPlayerAbilitiesPacket.class); this.registerIncoming(0x2C, ServerCombatPacket.class); this.registerIncoming(0x2D, ServerPlayerListEntryPacket.class); this.registerIncoming(0x2E, ServerPlayerPositionRotationPacket.class); this.registerIncoming(0x2F, ServerPlayerUseBedPacket.class); this.registerIncoming(0x30, ServerEntityDestroyPacket.class); this.registerIncoming(0x31, ServerEntityRemoveEffectPacket.class); this.registerIncoming(0x32, ServerResourcePackSendPacket.class); this.registerIncoming(0x33, ServerRespawnPacket.class); this.registerIncoming(0x34, ServerEntityHeadLookPacket.class); this.registerIncoming(0x35, ServerWorldBorderPacket.class); this.registerIncoming(0x36, ServerSwitchCameraPacket.class); this.registerIncoming(0x37, ServerPlayerChangeHeldItemPacket.class); this.registerIncoming(0x38, ServerDisplayScoreboardPacket.class); this.registerIncoming(0x39, ServerEntityMetadataPacket.class); this.registerIncoming(0x3A, ServerEntityAttachPacket.class); this.registerIncoming(0x3B, ServerEntityVelocityPacket.class); this.registerIncoming(0x3C, ServerEntityEquipmentPacket.class); this.registerIncoming(0x3D, ServerPlayerSetExperiencePacket.class); this.registerIncoming(0x3E, ServerPlayerHealthPacket.class); this.registerIncoming(0x3F, ServerScoreboardObjectivePacket.class); this.registerIncoming(0x40, ServerEntitySetPassengersPacket.class); this.registerIncoming(0x41, ServerTeamPacket.class); this.registerIncoming(0x42, ServerUpdateScorePacket.class); this.registerIncoming(0x43, ServerSpawnPositionPacket.class); this.registerIncoming(0x44, ServerUpdateTimePacket.class); this.registerIncoming(0x45, ServerTitlePacket.class); this.registerIncoming(0x46, ServerPlayBuiltinSoundPacket.class); this.registerIncoming(0x47, ServerPlayerListDataPacket.class); this.registerIncoming(0x48, ServerEntityCollectItemPacket.class); this.registerIncoming(0x49, ServerEntityTeleportPacket.class); this.registerIncoming(0x4A, ServerEntityPropertiesPacket.class); this.registerIncoming(0x4B, ServerEntityEffectPacket.class); this.registerOutgoing(0x00, ClientTeleportConfirmPacket.class); this.registerOutgoing(0x01, ClientTabCompletePacket.class); this.registerOutgoing(0x02, ClientChatPacket.class); this.registerOutgoing(0x03, ClientRequestPacket.class); this.registerOutgoing(0x04, ClientSettingsPacket.class); this.registerOutgoing(0x05, ClientConfirmTransactionPacket.class); this.registerOutgoing(0x06, ClientEnchantItemPacket.class); this.registerOutgoing(0x07, ClientWindowActionPacket.class); this.registerOutgoing(0x08, ClientCloseWindowPacket.class); this.registerOutgoing(0x09, ClientPluginMessagePacket.class); this.registerOutgoing(0x0A, ClientPlayerInteractEntityPacket.class); this.registerOutgoing(0x0B, ClientKeepAlivePacket.class); this.registerOutgoing(0x0C, ClientPlayerPositionPacket.class); this.registerOutgoing(0x0D, ClientPlayerPositionRotationPacket.class); this.registerOutgoing(0x0E, ClientPlayerRotationPacket.class); this.registerOutgoing(0x0F, ClientPlayerMovementPacket.class); this.registerOutgoing(0x10, ClientVehicleMovePacket.class); this.registerOutgoing(0x11, ClientSteerBoatPacket.class); this.registerOutgoing(0x12, ClientPlayerAbilitiesPacket.class); this.registerOutgoing(0x13, ClientPlayerActionPacket.class); this.registerOutgoing(0x14, ClientPlayerStatePacket.class); this.registerOutgoing(0x15, ClientSteerVehiclePacket.class); this.registerOutgoing(0x16, ClientResourcePackStatusPacket.class); this.registerOutgoing(0x17, ClientPlayerChangeHeldItemPacket.class); this.registerOutgoing(0x18, ClientCreativeInventoryActionPacket.class); this.registerOutgoing(0x19, ClientUpdateSignPacket.class); this.registerOutgoing(0x1A, ClientPlayerSwingArmPacket.class); this.registerOutgoing(0x1B, ClientSpectatePacket.class); this.registerOutgoing(0x1C, ClientPlayerPlaceBlockPacket.class); this.registerOutgoing(0x1D, ClientPlayerUseItemPacket.class); } private void initServerGame(Session session) { this.registerIncoming(0x00, ClientTeleportConfirmPacket.class); this.registerIncoming(0x01, ClientTabCompletePacket.class); this.registerIncoming(0x02, ClientChatPacket.class); this.registerIncoming(0x03, ClientRequestPacket.class); this.registerIncoming(0x04, ClientSettingsPacket.class); this.registerIncoming(0x05, ClientConfirmTransactionPacket.class); this.registerIncoming(0x06, ClientEnchantItemPacket.class); this.registerIncoming(0x07, ClientWindowActionPacket.class); this.registerIncoming(0x08, ClientCloseWindowPacket.class); this.registerIncoming(0x09, ClientPluginMessagePacket.class); this.registerIncoming(0x0A, ClientPlayerInteractEntityPacket.class); this.registerIncoming(0x0B, ClientKeepAlivePacket.class); this.registerIncoming(0x0C, ClientPlayerPositionPacket.class); this.registerIncoming(0x0D, ClientPlayerPositionRotationPacket.class); this.registerIncoming(0x0E, ClientPlayerRotationPacket.class); this.registerIncoming(0x0F, ClientPlayerMovementPacket.class); this.registerIncoming(0x10, ClientVehicleMovePacket.class); this.registerIncoming(0x11, ClientSteerBoatPacket.class); this.registerIncoming(0x12, ClientPlayerAbilitiesPacket.class); this.registerIncoming(0x13, ClientPlayerActionPacket.class); this.registerIncoming(0x14, ClientPlayerStatePacket.class); this.registerIncoming(0x15, ClientSteerVehiclePacket.class); this.registerIncoming(0x16, ClientResourcePackStatusPacket.class); this.registerIncoming(0x17, ClientPlayerChangeHeldItemPacket.class); this.registerIncoming(0x18, ClientCreativeInventoryActionPacket.class); this.registerIncoming(0x19, ClientUpdateSignPacket.class); this.registerIncoming(0x1A, ClientPlayerSwingArmPacket.class); this.registerIncoming(0x1B, ClientSpectatePacket.class); this.registerIncoming(0x1C, ClientPlayerPlaceBlockPacket.class); this.registerIncoming(0x1D, ClientPlayerUseItemPacket.class); this.registerOutgoing(0x00, ServerSpawnObjectPacket.class); this.registerOutgoing(0x01, ServerSpawnExpOrbPacket.class); this.registerOutgoing(0x02, ServerSpawnGlobalEntityPacket.class); this.registerOutgoing(0x03, ServerSpawnMobPacket.class); this.registerOutgoing(0x04, ServerSpawnPaintingPacket.class); this.registerOutgoing(0x05, ServerSpawnPlayerPacket.class); this.registerOutgoing(0x06, ServerEntityAnimationPacket.class); this.registerOutgoing(0x07, ServerStatisticsPacket.class); this.registerOutgoing(0x08, ServerBlockBreakAnimPacket.class); this.registerOutgoing(0x09, ServerUpdateTileEntityPacket.class); this.registerOutgoing(0x0A, ServerBlockValuePacket.class); this.registerOutgoing(0x0B, ServerBlockChangePacket.class); this.registerOutgoing(0x0C, ServerBossBarPacket.class); this.registerOutgoing(0x0D, ServerDifficultyPacket.class); this.registerOutgoing(0x0E, ServerTabCompletePacket.class); this.registerOutgoing(0x0F, ServerChatPacket.class); this.registerOutgoing(0x10, ServerMultiBlockChangePacket.class); this.registerOutgoing(0x11, ServerConfirmTransactionPacket.class); this.registerOutgoing(0x12, ServerCloseWindowPacket.class); this.registerOutgoing(0x13, ServerOpenWindowPacket.class); this.registerOutgoing(0x14, ServerWindowItemsPacket.class); this.registerOutgoing(0x15, ServerWindowPropertyPacket.class); this.registerOutgoing(0x16, ServerSetSlotPacket.class); this.registerOutgoing(0x17, ServerSetCooldownPacket.class); this.registerOutgoing(0x18, ServerPluginMessagePacket.class); this.registerOutgoing(0x19, ServerPlaySoundPacket.class); this.registerOutgoing(0x1A, ServerDisconnectPacket.class); this.registerOutgoing(0x1B, ServerEntityStatusPacket.class); this.registerOutgoing(0x1C, ServerExplosionPacket.class); this.registerOutgoing(0x1D, ServerUnloadChunkPacket.class); this.registerOutgoing(0x1E, ServerNotifyClientPacket.class); this.registerOutgoing(0x1F, ServerKeepAlivePacket.class); this.registerOutgoing(0x20, ServerChunkDataPacket.class); this.registerOutgoing(0x21, ServerPlayEffectPacket.class); this.registerOutgoing(0x22, ServerSpawnParticlePacket.class); this.registerOutgoing(0x23, ServerJoinGamePacket.class); this.registerOutgoing(0x24, ServerMapDataPacket.class); this.registerOutgoing(0x25, ServerEntityPositionPacket.class); this.registerOutgoing(0x26, ServerEntityPositionRotationPacket.class); this.registerOutgoing(0x27, ServerEntityRotationPacket.class); this.registerOutgoing(0x28, ServerEntityMovementPacket.class); this.registerOutgoing(0x29, ServerVehicleMovePacket.class); this.registerOutgoing(0x2A, ServerOpenTileEntityEditorPacket.class); this.registerOutgoing(0x2B, ServerPlayerAbilitiesPacket.class); this.registerOutgoing(0x2C, ServerCombatPacket.class); this.registerOutgoing(0x2D, ServerPlayerListEntryPacket.class); this.registerOutgoing(0x2E, ServerPlayerPositionRotationPacket.class); this.registerOutgoing(0x2F, ServerPlayerUseBedPacket.class); this.registerOutgoing(0x30, ServerEntityDestroyPacket.class); this.registerOutgoing(0x31, ServerEntityRemoveEffectPacket.class); this.registerOutgoing(0x32, ServerResourcePackSendPacket.class); this.registerOutgoing(0x33, ServerRespawnPacket.class); this.registerOutgoing(0x34, ServerEntityHeadLookPacket.class); this.registerOutgoing(0x35, ServerWorldBorderPacket.class); this.registerOutgoing(0x36, ServerSwitchCameraPacket.class); this.registerOutgoing(0x37, ServerPlayerChangeHeldItemPacket.class); this.registerOutgoing(0x38, ServerDisplayScoreboardPacket.class); this.registerOutgoing(0x39, ServerEntityMetadataPacket.class); this.registerOutgoing(0x3A, ServerEntityAttachPacket.class); this.registerOutgoing(0x3B, ServerEntityVelocityPacket.class); this.registerOutgoing(0x3C, ServerEntityEquipmentPacket.class); this.registerOutgoing(0x3D, ServerPlayerSetExperiencePacket.class); this.registerOutgoing(0x3E, ServerPlayerHealthPacket.class); this.registerOutgoing(0x3F, ServerScoreboardObjectivePacket.class); this.registerOutgoing(0x40, ServerEntitySetPassengersPacket.class); this.registerOutgoing(0x41, ServerTeamPacket.class); this.registerOutgoing(0x42, ServerUpdateScorePacket.class); this.registerOutgoing(0x43, ServerSpawnPositionPacket.class); this.registerOutgoing(0x44, ServerUpdateTimePacket.class); this.registerOutgoing(0x45, ServerTitlePacket.class); this.registerOutgoing(0x46, ServerPlayBuiltinSoundPacket.class); this.registerOutgoing(0x47, ServerPlayerListDataPacket.class); this.registerOutgoing(0x48, ServerEntityCollectItemPacket.class); this.registerOutgoing(0x49, ServerEntityTeleportPacket.class); this.registerOutgoing(0x4A, ServerEntityPropertiesPacket.class); this.registerOutgoing(0x4B, ServerEntityEffectPacket.class); } private void initClientStatus(Session session) { this.registerIncoming(0x00, StatusResponsePacket.class); this.registerIncoming(0x01, StatusPongPacket.class); this.registerOutgoing(0x00, StatusQueryPacket.class); this.registerOutgoing(0x01, StatusPingPacket.class); } private void initServerStatus(Session session) { this.registerIncoming(0x00, StatusQueryPacket.class); this.registerIncoming(0x01, StatusPingPacket.class); this.registerOutgoing(0x00, StatusResponsePacket.class); this.registerOutgoing(0x01, StatusPongPacket.class); } }