diff options
author | Tiger Wang <ziwei.tiger@hotmail.co.uk> | 2013-11-27 22:35:13 +0100 |
---|---|---|
committer | Tiger Wang <ziwei.tiger@hotmail.co.uk> | 2013-11-27 22:35:13 +0100 |
commit | a6630d32394120a78af56bc612fa3c3449283248 (patch) | |
tree | 2c791266b0f213cd56961299da8d2258b8f85d8e /source/Protocol | |
parent | Fixed spawn point being generally in an ocean (diff) | |
parent | Voronoi-related biomegens use the new cVoronoiMap class. (diff) | |
download | cuberite-a6630d32394120a78af56bc612fa3c3449283248.tar cuberite-a6630d32394120a78af56bc612fa3c3449283248.tar.gz cuberite-a6630d32394120a78af56bc612fa3c3449283248.tar.bz2 cuberite-a6630d32394120a78af56bc612fa3c3449283248.tar.lz cuberite-a6630d32394120a78af56bc612fa3c3449283248.tar.xz cuberite-a6630d32394120a78af56bc612fa3c3449283248.tar.zst cuberite-a6630d32394120a78af56bc612fa3c3449283248.zip |
Diffstat (limited to '')
17 files changed, 0 insertions, 6998 deletions
diff --git a/source/Protocol/ChunkDataSerializer.cpp b/source/Protocol/ChunkDataSerializer.cpp deleted file mode 100644 index 2a9230fee..000000000 --- a/source/Protocol/ChunkDataSerializer.cpp +++ /dev/null @@ -1,176 +0,0 @@ - -// ChunkDataSerializer.cpp - -// Implements the cChunkDataSerializer class representing the object that can: -// - serialize chunk data to different protocol versions -// - cache such serialized data for multiple clients - -#include "Globals.h" -#include "ChunkDataSerializer.h" -#include "zlib.h" - - - - -cChunkDataSerializer::cChunkDataSerializer( - const cChunkDef::BlockTypes & a_BlockTypes, - const cChunkDef::BlockNibbles & a_BlockMetas, - const cChunkDef::BlockNibbles & a_BlockLight, - const cChunkDef::BlockNibbles & a_BlockSkyLight, - const unsigned char * a_BiomeData -) : - m_BlockTypes(a_BlockTypes), - m_BlockMetas(a_BlockMetas), - m_BlockLight(a_BlockLight), - m_BlockSkyLight(a_BlockSkyLight), - m_BiomeData(a_BiomeData) -{ -} - - - - -const AString & cChunkDataSerializer::Serialize(int a_Version) -{ - Serializations::const_iterator itr = m_Serializations.find(a_Version); - if (itr != m_Serializations.end()) - { - return itr->second; - } - - AString data; - switch (a_Version) - { - case RELEASE_1_2_5: Serialize29(data); break; - case RELEASE_1_3_2: Serialize39(data); break; - // TODO: Other protocol versions may serialize the data differently; implement here - - default: - { - LOGERROR("cChunkDataSerializer::Serialize(): Unknown version: %d", a_Version); - ASSERT(!"Unknown chunk data serialization version"); - break; - } - } - m_Serializations[a_Version] = data; - return m_Serializations[a_Version]; -} - - - - - -void cChunkDataSerializer::Serialize29(AString & a_Data) -{ - // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) - - const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; - const int MetadataOffset = sizeof(m_BlockTypes); - const int BlockLightOffset = MetadataOffset + sizeof(m_BlockMetas); - const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); - const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); - const int DataSize = BiomeOffset + BiomeDataSize; - - // Temporary buffer for the composed data: - char AllData [DataSize]; - - memcpy(AllData, m_BlockTypes, sizeof(m_BlockTypes)); - memcpy(AllData + MetadataOffset, m_BlockMetas, sizeof(m_BlockMetas)); - memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); - memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); - memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); - - // Compress the data: - // In order not to use allocation, use a fixed-size buffer, with the size - // that uses the same calculation as compressBound(): - const uLongf CompressedMaxSize = DataSize + (DataSize >> 12) + (DataSize >> 14) + (DataSize >> 25) + 16; - char CompressedBlockData[CompressedMaxSize]; - - uLongf CompressedSize = compressBound(DataSize); - - // Run-time check that our compile-time guess about CompressedMaxSize was enough: - ASSERT(CompressedSize <= CompressedMaxSize); - - compress2((Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)AllData, sizeof(AllData), Z_DEFAULT_COMPRESSION); - - // Now put all those data into a_Data: - - // "Ground-up continuous", or rather, "biome data present" flag: - a_Data.push_back('\x01'); - - // Two bitmaps; we're aways sending the full chunk with no additional data, so the bitmaps are 0xffff and 0, respectively - // Also, no endian flipping is needed because of the const values - unsigned short BitMap1 = 0xffff; - unsigned short BitMap2 = 0; - a_Data.append((const char *)&BitMap1, sizeof(short)); - a_Data.append((const char *)&BitMap2, sizeof(short)); - - Int32 CompressedSizeBE = htonl(CompressedSize); - a_Data.append((const char *)&CompressedSizeBE, sizeof(CompressedSizeBE)); - - Int32 UnusedInt32 = 0; - a_Data.append((const char *)&UnusedInt32, sizeof(UnusedInt32)); - - a_Data.append(CompressedBlockData, CompressedSize); -} - - - - - -void cChunkDataSerializer::Serialize39(AString & a_Data) -{ - // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) - - const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; - const int MetadataOffset = sizeof(m_BlockTypes); - const int BlockLightOffset = MetadataOffset + sizeof(m_BlockMetas); - const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); - const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); - const int DataSize = BiomeOffset + BiomeDataSize; - - // Temporary buffer for the composed data: - char AllData [DataSize]; - - memcpy(AllData, m_BlockTypes, sizeof(m_BlockTypes)); - memcpy(AllData + MetadataOffset, m_BlockMetas, sizeof(m_BlockMetas)); - memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); - memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); - memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); - - // Compress the data: - // In order not to use allocation, use a fixed-size buffer, with the size - // that uses the same calculation as compressBound(): - const uLongf CompressedMaxSize = DataSize + (DataSize >> 12) + (DataSize >> 14) + (DataSize >> 25) + 16; - char CompressedBlockData[CompressedMaxSize]; - - uLongf CompressedSize = compressBound(DataSize); - - // Run-time check that our compile-time guess about CompressedMaxSize was enough: - ASSERT(CompressedSize <= CompressedMaxSize); - - compress2((Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)AllData, sizeof(AllData), Z_DEFAULT_COMPRESSION); - - // Now put all those data into a_Data: - - // "Ground-up continuous", or rather, "biome data present" flag: - a_Data.push_back('\x01'); - - // Two bitmaps; we're aways sending the full chunk with no additional data, so the bitmaps are 0xffff and 0, respectively - // Also, no endian flipping is needed because of the const values - unsigned short BitMap1 = 0xffff; - unsigned short BitMap2 = 0; - a_Data.append((const char *)&BitMap1, sizeof(short)); - a_Data.append((const char *)&BitMap2, sizeof(short)); - - Int32 CompressedSizeBE = htonl(CompressedSize); - a_Data.append((const char *)&CompressedSizeBE, sizeof(CompressedSizeBE)); - - // Unlike 29, 39 doesn't have the "unused" int - - a_Data.append(CompressedBlockData, CompressedSize); -} - - - - diff --git a/source/Protocol/Protocol.h b/source/Protocol/Protocol.h deleted file mode 100644 index 542060ece..000000000 --- a/source/Protocol/Protocol.h +++ /dev/null @@ -1,216 +0,0 @@ - -// Protocol.h - -// Interfaces to the cProtocol class representing the generic interface that a protocol -// parser and serializer must implement - - - - - -#pragma once - -#include "../Defines.h" -#include "../Endianness.h" - - - - -class cPlayer; -class cEntity; -class cWindow; -class cInventory; -class cPawn; -class cPickup; -class cWorld; -class cMonster; -class cChunkDataSerializer; -class cFallingBlock; - - - - - -typedef unsigned char Byte; - - - - - -class cProtocol -{ -public: - cProtocol(cClientHandle * a_Client) : - m_Client(a_Client) - { - } - virtual ~cProtocol() {} - - /// Called when client sends some data - virtual void DataReceived(const char * a_Data, int a_Size) = 0; - - // Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) = 0; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; - virtual void SendChat (const AString & a_Message) = 0; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0; - virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) = 0; - virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; - virtual void SendDisconnect (const AString & a_Reason) = 0; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0; - virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0; - virtual void SendEntityLook (const cEntity & a_Entity) = 0; - virtual void SendEntityMetadata (const cEntity & a_Entity) = 0; - virtual void SendEntityProperties (const cEntity & a_Entity) = 0; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0; - virtual void SendEntityVelocity (const cEntity & a_Entity) = 0; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; - virtual void SendGameMode (eGameMode a_GameMode) = 0; - virtual void SendHealth (void) = 0; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; - virtual void SendKeepAlive (int a_PingID) = 0; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0; - virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0; - virtual void SendPlayerAbilities (void) = 0; - virtual void SendPlayerAnimation (const cPlayer & a_Player, char a_Animation) = 0; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) = 0; - virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) - virtual void SendPlayerMoveLook (void) = 0; - virtual void SendPlayerPosition (void) = 0; - virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; - virtual void SendRespawn (void) = 0; - virtual void SendExperience (void) = 0; - virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8 - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0; - virtual void SendSpawnMob (const cMonster & a_Mob) = 0; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) = 0; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) = 0; - virtual void SendTabCompletionResults(const AStringVector & a_Results) = 0; - virtual void SendTeleportEntity (const cEntity & a_Entity) = 0; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) = 0; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0; - virtual void SendWeather (eWeather a_Weather) = 0; - virtual void SendWholeInventory (const cWindow & a_Window) = 0; - virtual void SendWindowClose (const cWindow & a_Window) = 0; - virtual void SendWindowOpen (const cWindow & a_Window) = 0; - virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) = 0; - - /// Returns the ServerID used for authentication through session.minecraft.net - virtual AString GetAuthServerID(void) = 0; - -protected: - cClientHandle * m_Client; - cCriticalSection m_CSPacket; //< Each SendXYZ() function must acquire this CS in order to send the whole packet at once - - /// A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it - virtual void SendData(const char * a_Data, int a_Size) = 0; - - /// Called after writing each packet, enables descendants to flush their buffers - virtual void Flush(void) {}; - - // Helpers for writing partial packet data, write using SendData() - void WriteByte(Byte a_Value) - { - SendData((const char *)&a_Value, 1); - } - - void WriteShort(short a_Value) - { - a_Value = htons(a_Value); - SendData((const char *)&a_Value, 2); - } - - /* - void WriteShort(unsigned short a_Value) - { - a_Value = htons(a_Value); - SendData((const char *)&a_Value, 2); - } - */ - - void WriteInt(int a_Value) - { - a_Value = htonl(a_Value); - SendData((const char *)&a_Value, 4); - } - - void WriteUInt(unsigned int a_Value) - { - a_Value = htonl(a_Value); - SendData((const char *)&a_Value, 4); - } - - void WriteInt64 (Int64 a_Value) - { - a_Value = HostToNetwork8(&a_Value); - SendData((const char *)&a_Value, 8); - } - - void WriteFloat (float a_Value) - { - unsigned int val = HostToNetwork4(&a_Value); - SendData((const char *)&val, 4); - } - - void WriteDouble(double a_Value) - { - unsigned long long val = HostToNetwork8(&a_Value); - SendData((const char *)&val, 8); - } - - void WriteString(const AString & a_Value) - { - AString UTF16; - UTF8ToRawBEUTF16(a_Value.c_str(), a_Value.length(), UTF16); - WriteShort((unsigned short)(UTF16.size() / 2)); - SendData(UTF16.data(), UTF16.size()); - } - - void WriteBool(bool a_Value) - { - WriteByte(a_Value ? 1 : 0); - } - - void WriteVectorI(const Vector3i & a_Vector) - { - WriteInt(a_Vector.x); - WriteInt(a_Vector.y); - WriteInt(a_Vector.z); - } - - void WriteVarInt(UInt32 a_Value) - { - // A 32-bit integer can be encoded by at most 5 bytes: - unsigned char b[5]; - int idx = 0; - do - { - b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00); - a_Value = a_Value >> 7; - idx++; - } while (a_Value > 0); - - SendData((const char *)b, idx); - } - - void WriteVarUTF8String(const AString & a_String) - { - WriteVarInt(a_String.size()); - SendData(a_String.data(), a_String.size()); - } -} ; - - - - - diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp deleted file mode 100644 index 54be65b12..000000000 --- a/source/Protocol/Protocol125.cpp +++ /dev/null @@ -1,1884 +0,0 @@ - -// Protocol125.cpp - -// Implements the cProtocol125 class representing the release 1.2.5 protocol (#29) -/* -Documentation: - - protocol: http://wiki.vg/wiki/index.php?title=Protocol&oldid=2513 - - session handling: http://wiki.vg/wiki/index.php?title=Session&oldid=2262 - - slot format: http://wiki.vg/wiki/index.php?title=Slot_Data&oldid=2152 -*/ - -#include "Globals.h" - -#include "Protocol125.h" - -#include "../ClientHandle.h" -#include "../World.h" -#include "ChunkDataSerializer.h" -#include "../Entities/Entity.h" -#include "../Mobs/Monster.h" -#include "../Entities/Pickup.h" -#include "../Entities/Player.h" -#include "../ChatColor.h" -#include "../UI/Window.h" -#include "../Root.h" -#include "../Server.h" - -#include "../Entities/ProjectileEntity.h" -#include "../Entities/Minecart.h" -#include "../Entities/FallingBlock.h" - -#include "../Mobs/IncludeAllMonsters.h" - - - - - -enum -{ - PACKET_KEEP_ALIVE = 0x00, - PACKET_LOGIN = 0x01, - PACKET_HANDSHAKE = 0x02, - PACKET_CHAT = 0x03, - PACKET_UPDATE_TIME = 0x04, - PACKET_ENTITY_EQUIPMENT = 0x05, - PACKET_USE_ENTITY = 0x07, - PACKET_UPDATE_HEALTH = 0x08, - PACKET_RESPAWN = 0x09, - PACKET_PLAYER_ON_GROUND = 0x0a, - PACKET_PLAYER_POS = 0x0b, - PACKET_PLAYER_LOOK = 0x0c, - PACKET_PLAYER_MOVE_LOOK = 0x0d, - PACKET_BLOCK_DIG = 0x0e, - PACKET_BLOCK_PLACE = 0x0f, - PACKET_SLOT_SELECTED = 0x10, - PACKET_USE_BED = 0x11, - PACKET_ANIMATION = 0x12, - PACKET_PACKET_ENTITY_ACTION = 0x13, - PACKET_PLAYER_SPAWN = 0x14, - PACKET_PICKUP_SPAWN = 0x15, - PACKET_COLLECT_PICKUP = 0x16, - PACKET_SPAWN_OBJECT = 0x17, - PACKET_SPAWN_MOB = 0x18, - PACKET_ENTITY_VELOCITY = 0x1c, - PACKET_DESTROY_ENTITY = 0x1d, - PACKET_ENTITY = 0x1e, - PACKET_ENT_REL_MOVE = 0x1f, - PACKET_ENT_LOOK = 0x20, - PACKET_ENT_REL_MOVE_LOOK = 0x21, - PACKET_ENT_TELEPORT = 0x22, - PACKET_ENT_HEAD_LOOK = 0x23, - PACKET_ENT_STATUS = 0x26, - PACKET_ATTACH_ENTITY = 0x27, - PACKET_METADATA = 0x28, - PACKET_EXPERIENCE = 0x2b, - PACKET_PRE_CHUNK = 0x32, - PACKET_MAP_CHUNK = 0x33, - PACKET_MULTI_BLOCK = 0x34, - PACKET_BLOCK_CHANGE = 0x35, - PACKET_BLOCK_ACTION = 0x36, - PACKET_EXPLOSION = 0x3C, - PACKET_SOUND_EFFECT = 0x3e, - PACKET_SOUND_PARTICLE_EFFECT = 0x3d, - PACKET_CHANGE_GAME_STATE = 0x46, - PACKET_THUNDERBOLT = 0x47, - PACKET_WINDOW_OPEN = 0x64, - PACKET_WINDOW_CLOSE = 0x65, - PACKET_WINDOW_CLICK = 0x66, - PACKET_INVENTORY_SLOT = 0x67, - PACKET_INVENTORY_WHOLE = 0x68, - PACKET_WINDOW_PROPERTY = 0x69, - PACKET_CREATIVE_INVENTORY_ACTION = 0x6B, - PACKET_UPDATE_SIGN = 0x82, - PACKET_PLAYER_LIST_ITEM = 0xC9, - PACKET_PLAYER_ABILITIES = 0xca, - PACKET_PLUGIN_MESSAGE = 0xfa, - PACKET_PING = 0xfe, - PACKET_DISCONNECT = 0xff -} ; - - - - - -#define HANDLE_PACKET_READ(Proc, Type, Var) \ - Type Var; \ - { \ - if (!m_ReceivedData.Proc(Var)) \ - { \ - m_ReceivedData.CheckValid(); \ - return PARSE_INCOMPLETE; \ - } \ - m_ReceivedData.CheckValid(); \ - } - - - - -typedef unsigned char Byte; - - - - - -cProtocol125::cProtocol125(cClientHandle * a_Client) : - super(a_Client), - m_ReceivedData(32 KiB) -{ -} - - - - - -void cProtocol125::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ATTACH_ENTITY); - WriteInt(a_Entity.GetUniqueID()); - WriteInt((a_Vehicle == NULL) ? -1 : a_Vehicle->GetUniqueID()); - Flush(); -} - - - - - -void cProtocol125::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) -{ - UNUSED(a_BlockType); - - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_BLOCK_ACTION); - WriteInt (a_BlockX); - WriteShort((short)a_BlockY); - WriteInt (a_BlockZ); - WriteByte (a_Byte1); - WriteByte (a_Byte2); - Flush(); -} - - - - - -void cProtocol125::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) -{ - // Not supported in this protocol version -} - - - - - -void cProtocol125::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_BLOCK_CHANGE); - WriteInt (a_BlockX); - WriteByte((unsigned char)a_BlockY); - WriteInt (a_BlockZ); - WriteByte(a_BlockType); - WriteByte(a_BlockMeta); - Flush(); -} - - - - - -void cProtocol125::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) -{ - cCSLock Lock(m_CSPacket); - if (a_Changes.size() == 1) - { - // Special packet for single-block changes - const sSetBlock & blk = a_Changes.front(); - SendBlockChange(a_ChunkX * cChunkDef::Width + blk.x, blk.y, a_ChunkZ * cChunkDef::Width + blk.z, blk.BlockType, blk.BlockMeta); - return; - } - - WriteByte (PACKET_MULTI_BLOCK); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - WriteShort((unsigned short)a_Changes.size()); - WriteUInt (sizeof(int) * a_Changes.size()); - for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) - { - unsigned int Coords = itr->y | (itr->z << 8) | (itr->x << 12); - unsigned int Blocks = itr->BlockMeta | (itr->BlockType << 4); - WriteUInt(Coords << 16 | Blocks); - } - Flush(); -} - - - - - -void cProtocol125::SendChat(const AString & a_Message) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_CHAT); - WriteString(a_Message); - Flush(); -} - - - - - -void cProtocol125::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - cCSLock Lock(m_CSPacket); - - // Send the pre-chunk: - SendPreChunk(a_ChunkX, a_ChunkZ, true); - - // Send the chunk data: - AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_2_5); - WriteByte(PACKET_MAP_CHUNK); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - SendData(Serialized.data(), Serialized.size()); - Flush(); -} - - - - - -void cProtocol125::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_COLLECT_PICKUP); - WriteInt (a_Pickup.GetUniqueID()); - WriteInt (a_Player.GetUniqueID()); - Flush(); -} - - - - - -void cProtocol125::SendDestroyEntity(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_DESTROY_ENTITY); - WriteInt (a_Entity.GetUniqueID()); - Flush(); -} - - - - - -void cProtocol125::SendDisconnect(const AString & a_Reason) -{ - cCSLock Lock(m_CSPacket); - WriteByte ((unsigned char)PACKET_DISCONNECT); - WriteString(a_Reason); - Flush(); -} - - - - - -void cProtocol125::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - // This protocol version doesn't support this packet, sign editor is invoked by the client automatically - UNUSED(a_BlockX); - UNUSED(a_BlockY); - UNUSED(a_BlockZ); -} - - - - - -void cProtocol125::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_ENTITY_EQUIPMENT); - WriteInt (a_Entity.GetUniqueID()); - WriteShort(a_SlotNum); - WriteShort(a_Item.m_ItemType); - WriteShort(a_Item.m_ItemDamage); - Flush(); -} - - - - - -void cProtocol125::SendEntityHeadLook(const cEntity & a_Entity) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_HEAD_LOOK); - WriteInt (a_Entity.GetUniqueID()); - WriteByte((char)((a_Entity.GetHeadYaw() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendEntityLook(const cEntity & a_Entity) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_LOOK); - WriteInt (a_Entity.GetUniqueID()); - WriteByte((char)((a_Entity.GetRotation() / 360.f) * 256)); - WriteByte((char)((a_Entity.GetPitch() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendEntityMetadata(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_METADATA); - WriteInt (a_Entity.GetUniqueID()); - - WriteCommonMetadata(a_Entity); - if (a_Entity.IsMob()) - { - WriteMobMetadata(((const cMonster &)a_Entity)); - } - else - { - WriteEntityMetadata(a_Entity); - } - WriteByte(0x7f); - - Flush(); -} - - - - - -void cProtocol125::SendEntityProperties(const cEntity & a_Entity) -{ - // Not supported in this protocol version -} - - - - - -void cProtocol125::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_REL_MOVE); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_RelX); - WriteByte(a_RelY); - WriteByte(a_RelZ); - Flush(); -} - - - - - -void cProtocol125::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_REL_MOVE_LOOK); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_RelX); - WriteByte(a_RelY); - WriteByte(a_RelZ); - WriteByte((char)((a_Entity.GetRotation() / 360.f) * 256)); - WriteByte((char)((a_Entity.GetPitch() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendEntityStatus(const cEntity & a_Entity, char a_Status) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_STATUS); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_Status); - Flush(); -} - - - - - -void cProtocol125::SendEntityVelocity(const cEntity & a_Entity) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENTITY_VELOCITY); - WriteInt (a_Entity.GetUniqueID()); - WriteShort((short) (a_Entity.GetSpeedX() * 400)); //400 = 8000 / 20 - WriteShort((short) (a_Entity.GetSpeedY() * 400)); - WriteShort((short) (a_Entity.GetSpeedZ() * 400)); - Flush(); -} - - - - - -void cProtocol125::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_EXPLOSION); - WriteDouble (a_BlockX); - WriteDouble (a_BlockY); - WriteDouble (a_BlockZ); - WriteFloat (a_Radius); - WriteInt (a_BlocksAffected.size()); - int BlockX = (int)a_BlockX; - int BlockY = (int)a_BlockY; - int BlockZ = (int)a_BlockZ; - for (cVector3iArray::const_iterator itr = a_BlocksAffected.begin(); itr != a_BlocksAffected.end(); ++itr) - { - WriteByte((Byte)(itr->x - BlockX)); - WriteByte((Byte)(itr->y - BlockY)); - WriteByte((Byte)(itr->z - BlockZ)); - } - WriteFloat((float)a_PlayerMotion.x); - WriteFloat((float)a_PlayerMotion.y); - WriteFloat((float)a_PlayerMotion.z); - Flush(); -} - - - - - -void cProtocol125::SendGameMode(eGameMode a_GameMode) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_CHANGE_GAME_STATE); - WriteByte(3); - WriteByte((char)a_GameMode); - Flush(); -} - - - - - -void cProtocol125::SendHandshake(const AString & a_ConnectionHash) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_HANDSHAKE); - WriteString(a_ConnectionHash); - Flush(); -} - - - - - -void cProtocol125::SendHealth(void) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_UPDATE_HEALTH); - WriteShort((short)m_Client->GetPlayer()->GetHealth()); - WriteShort(m_Client->GetPlayer()->GetFoodLevel()); - WriteFloat((float)m_Client->GetPlayer()->GetFoodSaturationLevel()); - Flush(); -} - - - - - -void cProtocol125::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_INVENTORY_SLOT); - WriteByte (a_WindowID); - WriteShort(a_SlotNum); - WriteItem (a_Item); - Flush(); -} - - - - - -void cProtocol125::SendKeepAlive(int a_PingID) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_KEEP_ALIVE); - WriteInt (a_PingID); - Flush(); -} - - - - - -void cProtocol125::SendLogin(const cPlayer & a_Player, const cWorld & a_World) -{ - UNUSED(a_World); - cCSLock Lock(m_CSPacket); - - WriteByte (PACKET_LOGIN); - WriteInt (a_Player.GetUniqueID()); // EntityID of the player - WriteString(""); // Username, not used - WriteString("default"); // Level type - WriteInt ((int)a_Player.GetGameMode()); - WriteInt ((int)(a_World.GetDimension())); - WriteByte (2); // TODO: Difficulty - WriteByte (0); // Unused - WriteByte (60); // Client list width or something - Flush(); -} - - - - - -void cProtocol125::SendPickupSpawn(const cPickup & a_Pickup) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_PICKUP_SPAWN); - WriteInt (a_Pickup.GetUniqueID()); - WriteShort (a_Pickup.GetItem().m_ItemType); - WriteByte (a_Pickup.GetItem().m_ItemCount); - WriteShort (a_Pickup.GetItem().m_ItemDamage); - WriteVectorI((Vector3i)(a_Pickup.GetPosition() * 32)); - WriteByte ((char)(a_Pickup.GetSpeed().x * 8)); - WriteByte ((char)(a_Pickup.GetSpeed().y * 8)); - WriteByte ((char)(a_Pickup.GetSpeed().z * 8)); - Flush(); -} - - - - - -void cProtocol125::SendPlayerAnimation(const cPlayer & a_Player, char a_Animation) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ANIMATION); - WriteInt (a_Player.GetUniqueID()); - WriteByte(a_Animation); - Flush(); -} - - - - - -void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) -{ - cCSLock Lock(m_CSPacket); - AString PlayerName(a_Player.GetColor()); - PlayerName.append(a_Player.GetName()); - if (PlayerName.length() > 14) - { - PlayerName.erase(14); - } - PlayerName += cChatColor::White; - - WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM); - WriteString(PlayerName); - WriteBool (a_IsOnline); - WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); - Flush(); -} - - - - - -void cProtocol125::SendPlayerMaxSpeed(void) -{ - // Not supported by this protocol version -} - - - - - -void cProtocol125::SendPlayerMoveLook(void) -{ - cCSLock Lock(m_CSPacket); - - /* - LOGD("Sending PlayerMoveLook: {%0.2f, %0.2f, %0.2f}, stance %0.2f, OnGround: %d", - m_Player->GetPosX(), m_Player->GetPosY(), m_Player->GetPosZ(), m_Player->GetStance(), m_Player->IsOnGround() ? 1 : 0 - ); - */ - - WriteByte (PACKET_PLAYER_MOVE_LOOK); - cPlayer * Player = m_Client->GetPlayer(); - WriteDouble(Player->GetPosX()); - WriteDouble(Player->GetStance() + 0.03); // Add a small amount so that the player doesn't start inside a block - WriteDouble(Player->GetPosY() + 0.03); // Add a small amount so that the player doesn't start inside a block - WriteDouble(Player->GetPosZ()); - WriteFloat ((float)(Player->GetRotation())); - WriteFloat ((float)(Player->GetPitch())); - WriteBool (Player->IsOnGround()); - Flush(); -} - - - - - -void cProtocol125::SendPlayerPosition(void) -{ - cCSLock Lock(m_CSPacket); - LOGD("Ignore send PlayerPos"); // PlayerPos is a C->S packet only now -} - - - - - -void cProtocol125::SendPlayerSpawn(const cPlayer & a_Player) -{ - const cItem & HeldItem = a_Player.GetEquippedItem(); - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_PLAYER_SPAWN); - WriteInt (a_Player.GetUniqueID()); - WriteString(a_Player.GetName()); - WriteInt ((int)(a_Player.GetPosX() * 32)); - WriteInt ((int)(a_Player.GetPosY() * 32)); - WriteInt ((int)(a_Player.GetPosZ() * 32)); - WriteByte ((char)((a_Player.GetRot().x / 360.f) * 256)); - WriteByte ((char)((a_Player.GetRot().y / 360.f) * 256)); - WriteShort (HeldItem.IsEmpty() ? 0 : HeldItem.m_ItemType); - Flush(); -} - - - - - -void cProtocol125::SendRespawn(void) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_RESPAWN); - WriteInt ((int)(m_Client->GetPlayer()->GetWorld()->GetDimension())); - WriteByte (2); // TODO: Difficulty; 2 = Normal - WriteByte ((char)m_Client->GetPlayer()->GetGameMode()); - WriteShort (256); // Current world height - WriteString("default"); -} - - - - - -void cProtocol125::SendExperience(void) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_EXPERIENCE); - WriteFloat (m_Client->GetPlayer()->GetXpPercentage()); - WriteShort (m_Client->GetPlayer()->GetXpLevel()); - WriteShort (m_Client->GetPlayer()->GetCurrentXp()); - Flush(); -} - - - - - -void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) -{ - // Not needed in this protocol version -} - - - - - -void cProtocol125::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) -{ - // Not implemented in this protocol version -} - - - - - -void cProtocol125::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) -{ - // This protocol version implements falling blocks using the spawn object / vehicle packet: - SendSpawnObject(a_FallingBlock, 70, a_FallingBlock.GetBlockType(), 0, 0); -} - - - - - -void cProtocol125::SendSpawnMob(const cMonster & a_Mob) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SPAWN_MOB); - WriteInt (a_Mob.GetUniqueID()); - WriteByte (a_Mob.GetMobType()); - WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); - WriteByte (0); - WriteByte (0); - WriteByte (0); - - WriteCommonMetadata(a_Mob); - WriteMobMetadata(a_Mob); - WriteByte(0x7f); - - Flush(); -} - - - - - -void cProtocol125::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) -{ - UNUSED(a_Yaw); - UNUSED(a_Pitch); - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_SPAWN_OBJECT); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_ObjectType); - WriteInt ((int)(a_Entity.GetPosX() * 32)); - WriteInt ((int)(a_Entity.GetPosY() * 32)); - WriteInt ((int)(a_Entity.GetPosZ() * 32)); - WriteByte(a_Pitch); - WriteByte(a_Yaw); - WriteInt (a_ObjectData); - if (a_ObjectData != 0) - { - WriteShort((short)(a_Entity.GetSpeedX() * 400)); - WriteShort((short)(a_Entity.GetSpeedY() * 400)); - WriteShort((short)(a_Entity.GetSpeedZ() * 400)); - } - Flush(); -} - - - - - -void cProtocol125::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SPAWN_OBJECT); - WriteInt (a_Vehicle.GetUniqueID()); - WriteByte (a_VehicleType); - WriteInt ((int)(a_Vehicle.GetPosX() * 32)); - WriteInt ((int)(a_Vehicle.GetPosY() * 32)); - WriteInt ((int)(a_Vehicle.GetPosZ() * 32)); - WriteByte ((Byte)((a_Vehicle.GetPitch() / 360.f) * 256)); - WriteByte ((Byte)((a_Vehicle.GetRotation() / 360.f) * 256)); - WriteInt (a_VehicleSubType); - if (a_VehicleSubType != 0) - { - WriteShort((short)(a_Vehicle.GetSpeedX() * 400)); - WriteShort((short)(a_Vehicle.GetSpeedY() * 400)); - WriteShort((short)(a_Vehicle.GetSpeedZ() * 400)); - } - Flush(); -} - - - - - -void cProtocol125::SendTabCompletionResults(const AStringVector & a_Results) -{ - // This protocol version doesn't support tab completion - UNUSED(a_Results); -} - - - - - -void cProtocol125::SendTeleportEntity(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_ENT_TELEPORT); - WriteInt (a_Entity.GetUniqueID()); - WriteInt ((int)(floor(a_Entity.GetPosX() * 32))); - WriteInt ((int)(floor(a_Entity.GetPosY() * 32))); - WriteInt ((int)(floor(a_Entity.GetPosZ() * 32))); - WriteByte ((char)((a_Entity.GetRotation() / 360.f) * 256)); - WriteByte ((char)((a_Entity.GetPitch() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_THUNDERBOLT); - WriteInt (0x7fffffff); // Entity ID of the thunderbolt; we use a constant one - WriteBool(true); // Unknown bool - WriteInt (a_BlockX * 32); - WriteInt (a_BlockY * 32); - WriteInt (a_BlockZ * 32); - Flush(); -} - - - - - -void cProtocol125::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_UPDATE_TIME); - // Use a_WorldAge for daycount, and a_TimeOfDay for the proper time of day: - WriteInt64((24000 * (a_WorldAge / 24000)) + (a_TimeOfDay % 24000)); - Flush(); -} - - - - - -void cProtocol125::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) -{ - cCSLock Lock(m_CSPacket); - SendPreChunk(a_ChunkX, a_ChunkZ, false); -} - - - - - -void cProtocol125::SendUpdateSign( - int a_BlockX, int a_BlockY, int a_BlockZ, - const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4 -) -{ - cCSLock Lock(m_CSPacket); - WriteByte ((unsigned char)PACKET_UPDATE_SIGN); - WriteInt (a_BlockX); - WriteShort ((short)a_BlockY); - WriteInt (a_BlockZ); - WriteString(a_Line1); - WriteString(a_Line2); - WriteString(a_Line3); - WriteString(a_Line4); - Flush(); -} - - - - - -void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_USE_BED); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(0); // Unknown byte only 0 has been observed - WriteInt (a_BlockX); - WriteByte(a_BlockY); - WriteInt (a_BlockZ); - Flush(); -} - - - - - -void cProtocol125::SendWeather(eWeather a_Weather) -{ - cCSLock Lock(m_CSPacket); - switch( a_Weather ) - { - case eWeather_Sunny: - { - WriteByte(PACKET_CHANGE_GAME_STATE); - WriteByte(2); // Stop rain - WriteByte(0); // Unused - Flush(); - break; - } - - case eWeather_Rain: - case eWeather_ThunderStorm: - { - WriteByte(PACKET_CHANGE_GAME_STATE); - WriteByte(1); // Begin rain - WriteByte(0); // Unused - Flush(); - break; - } - } -} - - - - - -void cProtocol125::SendWholeInventory(const cWindow & a_Window) -{ - cCSLock Lock(m_CSPacket); - cItems Slots; - a_Window.GetSlots(*(m_Client->GetPlayer()), Slots); - SendWindowSlots(a_Window.GetWindowID(), Slots.size(), &(Slots[0])); -} - - - - - -void cProtocol125::SendWindowClose(const cWindow & a_Window) -{ - if (a_Window.GetWindowType() == cWindow::wtInventory) - { - // Do not send inventory-window-close - return; - } - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_WINDOW_CLOSE); - WriteByte(a_Window.GetWindowID()); - Flush(); -} - - - - - -void cProtocol125::SendWindowOpen(const cWindow & a_Window) -{ - if (a_Window.GetWindowType() < 0) - { - // Do not send for inventory windows - return; - } - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_WINDOW_OPEN); - WriteByte (a_Window.GetWindowID()); - WriteByte (a_Window.GetWindowType()); - WriteString(a_Window.GetWindowTitle()); - WriteByte (a_Window.GetNumNonInventorySlots()); - Flush(); -} - - - - - -void cProtocol125::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_WINDOW_PROPERTY); - WriteByte (a_Window.GetWindowID()); - WriteShort(a_Property); - WriteShort(a_Value); - Flush(); -} - - - - - -AString cProtocol125::GetAuthServerID(void) -{ - // http://wiki.vg/wiki/index.php?title=Session&oldid=2262 - // The server generates a random hash and that is used for all clients, unmodified - return cRoot::Get()->GetServer()->GetServerID(); -} - - - - - -void cProtocol125::SendData(const char * a_Data, int a_Size) -{ - m_Client->SendData(a_Data, a_Size); -} - - - - - -void cProtocol125::DataReceived(const char * a_Data, int a_Size) -{ - if (!m_ReceivedData.Write(a_Data, a_Size)) - { - // Too much data in the incoming queue, report to caller: - m_Client->PacketBufferFull(); - return; - } - - // Parse and handle all complete packets in m_ReceivedData: - while (m_ReceivedData.CanReadBytes(1)) - { - unsigned char PacketType; - m_ReceivedData.ReadByte(PacketType); - switch (ParsePacket(PacketType)) - { - case PARSE_UNKNOWN: - { - // An unknown packet has been received, notify the client and abort: - m_Client->PacketUnknown(PacketType); - return; - } - case PARSE_ERROR: - { - // An error occurred while parsing a known packet, notify the client and abort: - m_Client->PacketError(PacketType); - return; - } - case PARSE_INCOMPLETE: - { - // Incomplete packet, bail out and process with the next batch of data - m_ReceivedData.ResetRead(); - return; - } - default: - { - // Packet successfully parsed, commit the read data and try again one more packet - m_ReceivedData.CommitRead(); - break; - } - } - } -} - - - - - -int cProtocol125::ParsePacket(unsigned char a_PacketType) -{ - switch (a_PacketType) - { - default: return PARSE_UNKNOWN; - case PACKET_ANIMATION: return ParseArmAnim(); - case PACKET_BLOCK_DIG: return ParseBlockDig(); - case PACKET_BLOCK_PLACE: return ParseBlockPlace(); - case PACKET_CHAT: return ParseChat(); - case PACKET_CREATIVE_INVENTORY_ACTION: return ParseCreativeInventoryAction(); - case PACKET_DISCONNECT: return ParseDisconnect(); - case PACKET_HANDSHAKE: return ParseHandshake(); - case PACKET_KEEP_ALIVE: return ParseKeepAlive(); - case PACKET_LOGIN: return ParseLogin(); - case PACKET_PACKET_ENTITY_ACTION: return ParseEntityAction(); - case PACKET_PING: return ParsePing(); - case PACKET_PLAYER_ABILITIES: return ParsePlayerAbilities(); - case PACKET_PLAYER_LOOK: return ParsePlayerLook(); - case PACKET_PLAYER_MOVE_LOOK: return ParsePlayerMoveLook(); - case PACKET_PLAYER_ON_GROUND: return ParsePlayerOnGround(); - case PACKET_PLAYER_POS: return ParsePlayerPosition(); - case PACKET_PLUGIN_MESSAGE: return ParsePluginMessage(); - case PACKET_RESPAWN: return ParseRespawn(); - case PACKET_SLOT_SELECTED: return ParseSlotSelected(); - case PACKET_UPDATE_SIGN: return ParseUpdateSign(); - case PACKET_USE_ENTITY: return ParseUseEntity(); - case PACKET_WINDOW_CLICK: return ParseWindowClick(); - case PACKET_WINDOW_CLOSE: return ParseWindowClose(); - } -} - - - - - -#define HANDLE_PACKET_PARSE(Packet) \ - { \ - int res = Packet.Parse(m_ReceivedData); \ - if (res < 0) \ - { \ - return res; \ - } \ - } - - - - - -int cProtocol125::ParseArmAnim(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, EntityID); - HANDLE_PACKET_READ(ReadChar, char, Animation); - m_Client->HandleAnimation(Animation); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseBlockDig(void) -{ - HANDLE_PACKET_READ(ReadChar, char, Status); - HANDLE_PACKET_READ(ReadBEInt, int, PosX); - HANDLE_PACKET_READ(ReadByte, Byte, PosY); - HANDLE_PACKET_READ(ReadBEInt, int, PosZ); - HANDLE_PACKET_READ(ReadChar, char, BlockFace); - m_Client->HandleLeftClick(PosX, PosY, PosZ, BlockFace, Status); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseBlockPlace(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, PosX); - HANDLE_PACKET_READ(ReadByte, Byte, PosY); - HANDLE_PACKET_READ(ReadBEInt, int, PosZ); - HANDLE_PACKET_READ(ReadChar, char, BlockFace); - - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - - // 1.2.5 didn't have any cursor position, so use 8, 8, 8, so that halfslabs and stairs work correctly and the special value is recognizable. - m_Client->HandleRightClick(PosX, PosY, PosZ, BlockFace, 8, 8, 8, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseChat(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Message); - m_Client->HandleChat(Message); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseCreativeInventoryAction(void) -{ - HANDLE_PACKET_READ(ReadBEShort, short, SlotNum); - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - m_Client->HandleCreativeInventory(SlotNum, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseDisconnect(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Reason); - m_Client->HandleDisconnect(Reason); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseEntityAction(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, EntityID); - HANDLE_PACKET_READ(ReadChar, char, ActionID); - m_Client->HandleEntityAction(EntityID, ActionID); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseHandshake(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); - - AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565" - if (UserData.empty()) - { - m_Client->Kick("Did not receive username"); - return PARSE_OK; - } - m_Username = UserData[0]; - - LOGD("HANDSHAKE %s", Username.c_str()); - - if (!m_Client->HandleHandshake( m_Username )) - { - return PARSE_OK; // Player is not allowed into the server - } - - SendHandshake(cRoot::Get()->GetServer()->GetServerID()); - LOGD("User \"%s\" was sent a handshake response", m_Username.c_str()); - - return PARSE_OK; -} - - - - - -int cProtocol125::ParseKeepAlive(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, KeepAliveID); - m_Client->HandleKeepAlive(KeepAliveID); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseLogin(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, ProtocolVersion); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, LevelType); - HANDLE_PACKET_READ(ReadBEInt, int, ServerMode); - HANDLE_PACKET_READ(ReadBEInt, int, Dimension); - HANDLE_PACKET_READ(ReadChar, char, Difficulty); - HANDLE_PACKET_READ(ReadByte, Byte, WorldHeight); - HANDLE_PACKET_READ(ReadByte, Byte, MaxPlayers); - - if (ProtocolVersion < 29) - { - m_Client->Kick("Your client is outdated!"); - return PARSE_OK; - } - else if (ProtocolVersion > 29) - { - m_Client->Kick("Your client version is higher than the server!"); - return PARSE_OK; - } - - if (m_Username.compare(Username) != 0) - { - LOGWARNING("Login Username (\"%s\") does not match Handshake username (\"%s\") for client @ \"%s\", kicking", - Username.c_str(), - m_Username.c_str(), - m_Client->GetIPString().c_str() - ); - m_Client->Kick("Hacked client"); // Don't tell them why we don't want them - return PARSE_OK; - } - - m_Client->HandleLogin(ProtocolVersion, Username); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePing(void) -{ - // Packet has no more data - m_Client->HandlePing(); - return PARSE_OK; -} - - - - - - -int cProtocol125::ParsePlayerAbilities(void) -{ - HANDLE_PACKET_READ(ReadBool, bool, Invulnerable); - HANDLE_PACKET_READ(ReadBool, bool, IsFlying); - HANDLE_PACKET_READ(ReadBool, bool, CanFly); - HANDLE_PACKET_READ(ReadBool, bool, InstaMine); - // TODO: m_Client->HandlePlayerAbilities(...); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerLook(void) -{ - HANDLE_PACKET_READ(ReadBEFloat, float, Rotation); - HANDLE_PACKET_READ(ReadBEFloat, float, Pitch); - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerLook(Rotation, Pitch, IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerMoveLook(void) -{ - HANDLE_PACKET_READ(ReadBEDouble, double, PosX); - HANDLE_PACKET_READ(ReadBEDouble, double, PosY); - HANDLE_PACKET_READ(ReadBEDouble, double, Stance); - HANDLE_PACKET_READ(ReadBEDouble, double, PosZ); - HANDLE_PACKET_READ(ReadBEFloat, float, Rotation); - HANDLE_PACKET_READ(ReadBEFloat, float, Pitch); - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - // LOGD("Recv PML: {%0.2f, %0.2f, %0.2f}, Stance %0.2f, Gnd: %d", PosX, PosY, PosZ, Stance, IsOnGround ? 1 : 0); - m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, Stance, Rotation, Pitch, IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerOnGround(void) -{ - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - // TODO: m_Client->HandleFlying(IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerPosition(void) -{ - HANDLE_PACKET_READ(ReadBEDouble, double, PosX); - HANDLE_PACKET_READ(ReadBEDouble, double, PosY); - HANDLE_PACKET_READ(ReadBEDouble, double, Stance); - HANDLE_PACKET_READ(ReadBEDouble, double, PosZ); - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerPos(PosX, PosY, PosZ, Stance, IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePluginMessage(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, ChannelName); - HANDLE_PACKET_READ(ReadBEShort, short, Length); - AString Data; - if (!m_ReceivedData.ReadString(Data, Length)) - { - m_ReceivedData.CheckValid(); - return PARSE_INCOMPLETE; - } - m_ReceivedData.CheckValid(); - - // TODO: Process the data - LOGD("Received %d bytes of plugin data on channel \"%s\".", Length, ChannelName.c_str()); - - return PARSE_OK; -} - - - - - -int cProtocol125::ParseRespawn(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, Dimension); - HANDLE_PACKET_READ(ReadChar, char, Difficulty); - HANDLE_PACKET_READ(ReadChar, char, CreativeMode); - HANDLE_PACKET_READ(ReadBEShort, short, WorldHeight); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, LevelType); - m_Client->HandleRespawn(); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseSlotSelected(void) -{ - HANDLE_PACKET_READ(ReadBEShort, short, SlotNum); - m_Client->HandleSlotSelected(SlotNum); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseUpdateSign(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, BlockX); - HANDLE_PACKET_READ(ReadBEShort, short, BlockY); - HANDLE_PACKET_READ(ReadBEInt, int, BlockZ); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line1); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line2); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line3); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line4); - m_Client->HandleUpdateSign(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseUseEntity(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, SourceEntityID); - HANDLE_PACKET_READ(ReadBEInt, int, TargetEntityID); - HANDLE_PACKET_READ(ReadBool, bool, IsLeftClick); - m_Client->HandleUseEntity(TargetEntityID, IsLeftClick); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseWindowClick(void) -{ - HANDLE_PACKET_READ(ReadChar, char, WindowID); - HANDLE_PACKET_READ(ReadBEShort, short, SlotNum); - HANDLE_PACKET_READ(ReadBool, bool, IsRightClick); - HANDLE_PACKET_READ(ReadBEShort, short, TransactionID); - HANDLE_PACKET_READ(ReadBool, bool, IsShiftPressed); - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - - // Convert IsShiftPressed, IsRightClick, SlotNum and HeldItem into eClickAction used in the newer protocols: - eClickAction Action; - if (IsRightClick) - { - if (IsShiftPressed) - { - Action = caShiftRightClick; - } - else - { - if (SlotNum == -999) - { - Action = (HeldItem.IsEmpty()) ? caRightClickOutsideHoldNothing : caRightClickOutside; - } - else - { - Action = caRightClick; - } - } - } - else - { - // IsLeftClick - if (IsShiftPressed) - { - Action = caShiftLeftClick; - } - else - { - if (SlotNum == -999) - { - Action = (HeldItem.IsEmpty()) ? caLeftClickOutsideHoldNothing : caRightClickOutside; - } - else - { - Action = caLeftClick; - } - } - } - m_Client->HandleWindowClick(WindowID, SlotNum, Action, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseWindowClose(void) -{ - HANDLE_PACKET_READ(ReadChar, char, WindowID); - m_Client->HandleWindowClose(WindowID); - return PARSE_OK; -} - - - - - -void cProtocol125::SendPreChunk(int a_ChunkX, int a_ChunkZ, bool a_ShouldLoad) -{ - WriteByte(PACKET_PRE_CHUNK); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - WriteBool(a_ShouldLoad); - Flush(); -} - - - - - -void cProtocol125::SendWindowSlots(char a_WindowID, int a_NumItems, const cItem * a_Items) -{ - WriteByte (PACKET_INVENTORY_WHOLE); - WriteByte (a_WindowID); - WriteShort((short)a_NumItems); - - for (int j = 0; j < a_NumItems; j++) - { - WriteItem(a_Items[j]); - } - Flush(); -} - - - - - -void cProtocol125::WriteItem(const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - WriteShort(ItemType); - if (a_Item.IsEmpty()) - { - return; - } - - WriteByte (a_Item.m_ItemCount); - WriteShort(a_Item.m_ItemDamage); - - if (cItem::IsEnchantable(a_Item.m_ItemType)) - { - // TODO: Implement enchantments - WriteShort(-1); - } -} - - - - - -int cProtocol125::ParseItem(cItem & a_Item) -{ - HANDLE_PACKET_READ(ReadBEShort, short, ItemType); - - if (ItemType <= -1) - { - a_Item.Empty(); - return PARSE_OK; - } - a_Item.m_ItemType = ItemType; - - HANDLE_PACKET_READ(ReadChar, char, ItemCount); - HANDLE_PACKET_READ(ReadBEShort, short, ItemDamage); - a_Item.m_ItemCount = ItemCount; - a_Item.m_ItemDamage = ItemDamage; - if (ItemCount <= 0) - { - a_Item.Empty(); - } - - if (!cItem::IsEnchantable(ItemType)) - { - return PARSE_OK; - } - - HANDLE_PACKET_READ(ReadBEShort, short, EnchantNumBytes); - - if (EnchantNumBytes <= 0) - { - return PARSE_OK; - } - - // TODO: Enchantment not implemented yet! - if (!m_ReceivedData.SkipRead(EnchantNumBytes)) - { - return PARSE_INCOMPLETE; - } - - return PARSE_OK; -} - - - - - -void cProtocol125::WriteCommonMetadata(const cEntity & a_Entity) -{ - Byte CommonMetadata = 0; - - if (a_Entity.IsOnFire()) - { - CommonMetadata |= 0x1; - } - if (a_Entity.IsCrouched()) - { - CommonMetadata |= 0x2; - } - if (a_Entity.IsRiding()) - { - CommonMetadata |= 0x4; - } - if (a_Entity.IsSprinting()) - { - CommonMetadata |= 0x8; - } - if (a_Entity.IsRclking()) - { - CommonMetadata |= 0x10; - } - if (a_Entity.IsInvisible()) - { - CommonMetadata |= 0x20; - } - - WriteByte(0x0); - WriteByte(CommonMetadata); -} - - - - - -void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity) -{ - if (a_Entity.IsMinecart()) - { - WriteByte(0x51); - // No idea how Mojang makes their carts shakey shakey, so here is a complicated one-liner expression that does something similar - WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4 ); - WriteByte(0x52); - WriteInt(1); // Shaking direction, doesn't seem to affect anything - WriteByte(0x73); - WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer - - if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace) - { - WriteByte(0x10); - WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? - } - } - else if ((a_Entity.IsProjectile() && ((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow)) - { - WriteByte(0x10); - WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow? - } -} - - - - - -void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) -{ - switch (a_Mob.GetMobType()) - { - case cMonster::mtCreeper: - { - WriteByte(0x10); - WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? - WriteByte(0x11); - WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? - break; - } - case cMonster::mtBat: - { - WriteByte(0x10); - WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? - break; - } - case cMonster::mtPig: - { - WriteByte(0x10); - WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? - break; - } - case cMonster::mtVillager: - { - WriteByte(0x50); - WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? - break; - } - case cMonster::mtZombie: - { - WriteByte(0xC); - WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie? - WriteByte(0xD); - WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie? - WriteByte(0xE); - WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? - break; - } - case cMonster::mtGhast: - { - WriteByte(0x10); - WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P - break; - } - case cMonster::mtWolf: - { - Byte WolfStatus = 0; - if (((const cWolf &)a_Mob).IsSitting()) - { - WolfStatus |= 0x1; - } - if (((const cWolf &)a_Mob).IsAngry()) - { - WolfStatus |= 0x2; - } - if (((const cWolf &)a_Mob).IsTame()) - { - WolfStatus |= 0x4; - } - WriteByte(0x10); - WriteByte(WolfStatus); - - WriteByte(0x72); - WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) - WriteByte(0x13); - WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode? - break; - } - case cMonster::mtSheep: - { - // [1](1111) - // [] = Is sheared? () = Color, from 0 to 15 - - WriteByte(0x10); - Byte SheepMetadata = 0; - SheepMetadata = ((const cSheep &)a_Mob).GetFurColor(); // Fur colour - - if (((const cSheep &)a_Mob).IsSheared()) // Is sheared? - { - SheepMetadata |= 0x16; - } - WriteByte(SheepMetadata); - break; - } - case cMonster::mtEnderman: - { - WriteByte(0x10); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house - WriteByte(0x11); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house - WriteByte(0x12); - WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face? - break; - } - case cMonster::mtSkeleton: - { - WriteByte(0xD); - WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not - break; - } - case cMonster::mtWitch: - { - WriteByte(0x15); - WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything - break; - } - case cMonster::mtSlime: - case cMonster::mtMagmaCube: - { - WriteByte(0x10); - if (a_Mob.GetMobType() == cMonster::mtSlime) - { - WriteByte(((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME - } - else - { - WriteByte(((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME - } - break; - } - case cMonster::mtHorse: - { - int Flags = 0; - if (((const cHorse &)a_Mob).IsTame()) - { - Flags |= 0x2; - } - if (((const cHorse &)a_Mob).IsSaddled()) - { - Flags |= 0x4; - } - if (((const cHorse &)a_Mob).IsChested()) - { - Flags |= 0x8; - } - if (((const cHorse &)a_Mob).IsBaby()) - { - Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer - } - if (((const cHorse &)a_Mob).IsEating()) - { - Flags |= 0x20; - } - if (((const cHorse &)a_Mob).IsRearing()) - { - Flags |= 0x40; - } - if (((const cHorse &)a_Mob).IsMthOpen()) - { - Flags |= 0x80; - } - WriteByte(0x50); - WriteInt(Flags); - - WriteByte(0x13); - WriteByte(((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.) - - WriteByte(0x54); - int Appearance = 0; - Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF - Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256 - WriteInt(Appearance); - - WriteByte(0x56); - WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour - break; - } - } -} - - - - diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h deleted file mode 100644 index c5f44c818..000000000 --- a/source/Protocol/Protocol125.h +++ /dev/null @@ -1,158 +0,0 @@ - -// Protocol125.h - -// Interfaces to the cProtocol125 class representing the release 1.2.5 protocol (#29) - - - - - -#pragma once - -#include "Protocol.h" -#include "../ByteBuffer.h" - - - - - -class cProtocol125 : - public cProtocol -{ - typedef cProtocol super; -public: - cProtocol125(cClientHandle * a_Client); - - /// Called when client sends some data: - virtual void DataReceived(const char * a_Data, int a_Size) override; - - /// Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message - virtual void SendPlayerAnimation (const cPlayer & a_Player, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendRespawn (void) override; - virtual void SendExperience (void) override; - virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; - - virtual AString GetAuthServerID(void) override; - -protected: - /// Results of packet-parsing: - enum { - PARSE_OK = 1, - PARSE_ERROR = -1, - PARSE_UNKNOWN = -2, - PARSE_INCOMPLETE = -3, - } ; - - cByteBuffer m_ReceivedData; ///< Buffer for the received data - - AString m_Username; ///< Stored in ParseHandshake(), compared to Login username - - virtual void SendData(const char * a_Data, int a_Size) override; - - /// Sends the Handshake packet - void SendHandshake(const AString & a_ConnectionHash); - - /// Parse the packet of the specified type from m_ReceivedData (switch into ParseXYZ() ) - virtual int ParsePacket(unsigned char a_PacketType); - - // Specific packet parsers: - virtual int ParseArmAnim (void); - virtual int ParseBlockDig (void); - virtual int ParseBlockPlace (void); - virtual int ParseChat (void); - virtual int ParseCreativeInventoryAction(void); - virtual int ParseDisconnect (void); - virtual int ParseEntityAction (void); - virtual int ParseHandshake (void); - virtual int ParseKeepAlive (void); - virtual int ParseLogin (void); - virtual int ParsePing (void); - virtual int ParsePlayerAbilities (void); - virtual int ParsePlayerLook (void); - virtual int ParsePlayerMoveLook (void); - virtual int ParsePlayerOnGround (void); - virtual int ParsePlayerPosition (void); - virtual int ParsePluginMessage (void); - virtual int ParseRespawn (void); - virtual int ParseSlotSelected (void); - virtual int ParseUpdateSign (void); - virtual int ParseUseEntity (void); - virtual int ParseWindowClick (void); - virtual int ParseWindowClose (void); - - // Utility functions: - /// Writes a "pre-chunk" packet - void SendPreChunk(int a_ChunkX, int a_ChunkZ, bool a_ShouldLoad); - - /// Writes a "set window items" packet with the specified params - void SendWindowSlots(char a_WindowID, int a_NumItems, const cItem * a_Items); - - /// Writes one item, "slot" as the protocol wiki calls it - virtual void WriteItem(const cItem & a_Item); - - /// Parses one item, "slot" as the protocol wiki calls it, from m_ReceivedData; returns the usual ParsePacket() codes - virtual int ParseItem(cItem & a_Item); - - /// Writes the COMMON entity metadata - void WriteCommonMetadata(const cEntity & a_Entity); - - /// Writes normal entity metadata - void WriteEntityMetadata(const cEntity & a_Entity); - - /// Writes mobile entity metadata - void WriteMobMetadata(const cMonster & a_Mob); -} ; - - - - diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp deleted file mode 100644 index 22eac4312..000000000 --- a/source/Protocol/Protocol132.cpp +++ /dev/null @@ -1,950 +0,0 @@ - -// Protocol132.cpp - -// Implements the cProtocol132 class representing the release 1.3.2 protocol (#39) - -#include "Globals.h" -#include "Protocol132.h" -#include "../Root.h" -#include "../Server.h" -#include "../World.h" -#include "../ClientHandle.h" -#include "../../CryptoPP/randpool.h" -#include "../Item.h" -#include "ChunkDataSerializer.h" -#include "../Entities/Player.h" -#include "../Mobs/Monster.h" -#include "../UI/Window.h" -#include "../Entities/Pickup.h" -#include "../WorldStorage/FastNBT.h" -#include "../StringCompression.h" - - - - - -#define HANDLE_PACKET_READ(Proc, Type, Var) \ - Type Var; \ - { \ - if (!m_ReceivedData.Proc(Var)) \ - { \ - m_ReceivedData.CheckValid(); \ - return PARSE_INCOMPLETE; \ - } \ - m_ReceivedData.CheckValid(); \ - } - - - - -typedef unsigned char Byte; - - - - - -using namespace CryptoPP; - - - - - -const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... - - - - - -enum -{ - PACKET_KEEP_ALIVE = 0x00, - PACKET_LOGIN = 0x01, - PACKET_ENTITY_EQUIPMENT = 0x05, - PACKET_COMPASS = 0x06, - PACKET_PLAYER_SPAWN = 0x14, - PACKET_COLLECT_PICKUP = 0x16, - PACKET_SPAWN_MOB = 0x18, - PACKET_DESTROY_ENTITIES = 0x1d, - PACKET_CHUNK_DATA = 0x33, - PACKET_BLOCK_CHANGE = 0x35, - PACKET_BLOCK_ACTION = 0x36, - PACKET_BLOCK_BREAK_ANIM = 0x37, - PACKET_SOUND_EFFECT = 0x3e, - PACKET_SOUND_PARTICLE_EFFECT = 0x3d, - PACKET_TAB_COMPLETION = 0xcb, - PACKET_LOCALE_VIEW_DISTANCE = 0xcc, - PACKET_CLIENT_STATUSES = 0xcd, - PACKET_ENCRYPTION_KEY_RESP = 0xfc, -} ; - - - - - -// Converts a raw 160-bit SHA1 digest into a Java Hex representation -// According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802 -static void DigestToJava(byte a_Digest[20], AString & a_Out) -{ - bool IsNegative = (a_Digest[0] >= 0x80); - if (IsNegative) - { - // Two's complement: - bool carry = true; // Add one to the whole number - for (int i = 19; i >= 0; i--) - { - a_Digest[i] = ~a_Digest[i]; - if (carry) - { - carry = (a_Digest[i] == 0xff); - a_Digest[i]++; - } - } - } - a_Out.clear(); - a_Out.reserve(40); - for (int i = 0; i < 20; i++) - { - AppendPrintf(a_Out, "%02x", a_Digest[i]); - } - while ((a_Out.length() > 0) && (a_Out[0] == '0')) - { - a_Out.erase(0, 1); - } - if (IsNegative) - { - a_Out.insert(0, "-"); - } -} - - - - - -/* -// Self-test the hash formatting for known values: -// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48 -// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1 -// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6 - -class Test -{ -public: - Test(void) - { - AString DigestNotch, DigestJeb, DigestSimon; - byte Digest[20]; - CryptoPP::SHA1 Checksum; - Checksum.Update((const byte *)"Notch", 5); - Checksum.Final(Digest); - DigestToJava(Digest, DigestNotch); - Checksum.Restart(); - Checksum.Update((const byte *)"jeb_", 4); - Checksum.Final(Digest); - DigestToJava(Digest, DigestJeb); - Checksum.Restart(); - Checksum.Update((const byte *)"simon", 5); - Checksum.Final(Digest); - DigestToJava(Digest, DigestSimon); - printf("Notch: \"%s\"", DigestNotch.c_str()); - printf("jeb_: \"%s\"", DigestJeb.c_str()); - printf("simon: \"%s\"", DigestSimon.c_str()); - } -} test; -*/ - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cProtocol132: - -cProtocol132::cProtocol132(cClientHandle * a_Client) : - super(a_Client), - m_IsEncrypted(false) -{ -} - - - - - -cProtocol132::~cProtocol132() -{ - if (!m_DataToSend.empty()) - { - LOGD("There are %d unsent bytes while deleting cProtocol132", m_DataToSend.size()); - } -} - - - - - -void cProtocol132::DataReceived(const char * a_Data, int a_Size) -{ - if (m_IsEncrypted) - { - byte Decrypted[512]; - while (a_Size > 0) - { - int NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size; - m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes); - super::DataReceived((const char *)Decrypted, NumBytes); - a_Size -= NumBytes; - a_Data += NumBytes; - } - } - else - { - super::DataReceived(a_Data, a_Size); - } -} - - - - - -void cProtocol132::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_BLOCK_ACTION); - WriteInt (a_BlockX); - WriteShort((short)a_BlockY); - WriteInt (a_BlockZ); - WriteByte (a_Byte1); - WriteByte (a_Byte2); - WriteShort(a_BlockType); - Flush(); -} - - - - - -void cProtocol132::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_BLOCK_BREAK_ANIM); - WriteInt (a_entityID); - WriteInt (a_BlockX); - WriteInt (a_BlockY); - WriteInt (a_BlockZ); - WriteByte (stage); - Flush(); -} - - - - - -void cProtocol132::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_BLOCK_CHANGE); - WriteInt (a_BlockX); - WriteByte ((unsigned char)a_BlockY); - WriteInt (a_BlockZ); - WriteShort(a_BlockType); - WriteByte (a_BlockMeta); - Flush(); -} - - - - - -void cProtocol132::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - cCSLock Lock(m_CSPacket); - - // Pre-chunk not used in 1.3.2. Finally. - - // Send the chunk data: - AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2); - WriteByte(PACKET_CHUNK_DATA); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - SendData(Serialized.data(), Serialized.size()); - Flush(); -} - - - - - -void cProtocol132::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_COLLECT_PICKUP); - WriteInt (a_Pickup.GetUniqueID()); - WriteInt (a_Player.GetUniqueID()); - Flush(); - - // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;) - SendSoundEffect( - "random.pop", - (int)(a_Pickup.GetPosX() * 8), (int)(a_Pickup.GetPosY() * 8), (int)(a_Pickup.GetPosZ() * 8), - 0.5, (float)(0.75 + ((float)((a_Pickup.GetUniqueID() * 23) % 32)) / 64) - ); -} - - - - - -void cProtocol132::SendDestroyEntity(const cEntity & a_Entity) -{ - if (a_Entity.GetUniqueID() == m_Client->GetPlayer()->GetUniqueID()) - { - // Do not send "destroy self" to the client, the client would crash (FS #254) - return; - } - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_DESTROY_ENTITIES); - WriteByte(1); // entity count - WriteInt (a_Entity.GetUniqueID()); - Flush(); -} - - - - - -void cProtocol132::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_ENTITY_EQUIPMENT); - WriteInt (a_Entity.GetUniqueID()); - WriteShort(a_SlotNum); - WriteItem (a_Item); - Flush(); -} - - - - - -void cProtocol132::SendLogin(const cPlayer & a_Player, const cWorld & a_World) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_LOGIN); - WriteInt (a_Player.GetUniqueID()); // EntityID of the player - WriteString("default"); // Level type - WriteByte ((int)a_Player.GetGameMode()); - WriteByte ((Byte)(a_World.GetDimension())); - WriteByte (2); // TODO: Difficulty - WriteByte (0); // Unused, used to be world height - WriteByte (8); // Client list width or something - Flush(); - - SendCompass(a_World); -} - - - - - -void cProtocol132::SendPlayerSpawn(const cPlayer & a_Player) -{ - const cItem & HeldItem = a_Player.GetEquippedItem(); - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_PLAYER_SPAWN); - WriteInt (a_Player.GetUniqueID()); - WriteString(a_Player.GetName()); - WriteInt ((int)(a_Player.GetPosX() * 32)); - WriteInt ((int)(a_Player.GetPosY() * 32)); - WriteInt ((int)(a_Player.GetPosZ() * 32)); - WriteByte ((char)((a_Player.GetRot().x / 360.f) * 256)); - WriteByte ((char)((a_Player.GetRot().y / 360.f) * 256)); - WriteShort (HeldItem.IsEmpty() ? 0 : HeldItem.m_ItemType); - // Player metadata: just use a default metadata value, since the client doesn't like starting without any metadata: - WriteByte (0); // Index 0, byte (flags) - WriteByte (0); // Flags, empty - WriteByte (0x7f); // End of metadata - Flush(); -} - - - - - -void cProtocol132::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SOUND_EFFECT); - WriteString (a_SoundName); - WriteInt (a_SrcX); - WriteInt (a_SrcY); - WriteInt (a_SrcZ); - WriteFloat (a_Volume); - WriteByte ((char)(a_Pitch * 63.0f)); - Flush(); -} - - - - - -void cProtocol132::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_SOUND_PARTICLE_EFFECT); - WriteInt (a_EffectID); - WriteInt (a_SrcX); - WriteByte(a_SrcY); - WriteInt (a_SrcZ); - WriteInt (a_Data); - Flush(); -} - - - - - -void cProtocol132::SendSpawnMob(const cMonster & a_Mob) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SPAWN_MOB); - WriteInt (a_Mob.GetUniqueID()); - WriteByte (a_Mob.GetMobType()); - WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); - WriteByte ((Byte)((a_Mob.GetRotation() / 360.f) * 256)); - WriteByte ((Byte)((a_Mob.GetPitch() / 360.f) * 256)); - WriteByte ((Byte)((a_Mob.GetHeadYaw() / 360.f) * 256)); - WriteShort ((short)(a_Mob.GetSpeedX() * 400)); - WriteShort ((short)(a_Mob.GetSpeedY() * 400)); - WriteShort ((short)(a_Mob.GetSpeedZ() * 400)); - - WriteCommonMetadata(a_Mob); - WriteMobMetadata(a_Mob); - WriteByte(0x7f); - - Flush(); -} - - - - - -void cProtocol132::SendTabCompletionResults(const AStringVector & a_Results) -{ - if (a_Results.empty()) - { - // No results to send - return; - } - - AString Serialized(a_Results[0]); - for (AStringVector::const_iterator itr = a_Results.begin() + 1, end = a_Results.end(); itr != end; ++itr) - { - Serialized.push_back(0); - Serialized.append(*itr); - } // for itr - a_Results[] - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_TAB_COMPLETION); - WriteString(Serialized); - Flush(); -} - - - - - -void cProtocol132::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) -{ - // Unloading the chunk is done by sending a "map chunk" packet - // with IncludeInitialize set to true and primary bitmap set to 0: - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_CHUNK_DATA); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - WriteBool(true); // IncludeInitialize - WriteShort(0); // Primary bitmap - WriteShort(0); // Add bitmap - WriteInt(0); - Flush(); -} - - - - - -void cProtocol132::SendWholeInventory(const cWindow & a_Window) -{ - // 1.3.2 requires player inventory slots to be sent as SetSlot packets, - // otherwise it sometimes fails to update the window - - // Send the entire window: - super::SendWholeInventory(a_Window); - - // Send the player inventory and hotbar: - const cInventory & Inventory = m_Client->GetPlayer()->GetInventory(); - int BaseOffset = a_Window.GetNumSlots() - (cInventory::invNumSlots - cInventory::invInventoryOffset); // Number of non-inventory slots - char WindowID = a_Window.GetWindowID(); - for (int i = 0; i < cInventory::invInventoryCount; i++) - { - SendInventorySlot(WindowID, BaseOffset + i, Inventory.GetInventorySlot(i)); - } // for i - Inventory[] - BaseOffset += cInventory::invInventoryCount; - for (int i = 0; i < cInventory::invHotbarCount; i++) - { - SendInventorySlot(WindowID, BaseOffset + i, Inventory.GetHotbarSlot(i)); - } // for i - Hotbar[] - - // Send even the item being dragged: - SendInventorySlot(-1, -1, m_Client->GetPlayer()->GetDraggingItem()); -} - - - - - -AString cProtocol132::GetAuthServerID(void) -{ - // http://wiki.vg/wiki/index.php?title=Session&oldid=2615 - // Server uses SHA1 to mix ServerID, Client secret and server public key together - // The mixing is done in StartEncryption, the result is in m_AuthServerID - - return m_AuthServerID; -} - - - - - -int cProtocol132::ParsePacket(unsigned char a_PacketType) -{ - switch (a_PacketType) - { - default: return super::ParsePacket(a_PacketType); // off-load previously known packets into cProtocol125 - case PACKET_CLIENT_STATUSES: return ParseClientStatuses(); - case PACKET_ENCRYPTION_KEY_RESP: return ParseEncryptionKeyResponse(); - case PACKET_LOCALE_VIEW_DISTANCE: return ParseLocaleViewDistance(); - case PACKET_TAB_COMPLETION: return ParseTabCompletion(); - } -} - - - - - -int cProtocol132::ParseBlockPlace(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, PosX); - HANDLE_PACKET_READ(ReadByte, Byte, PosY); - HANDLE_PACKET_READ(ReadBEInt, int, PosZ); - HANDLE_PACKET_READ(ReadChar, char, BlockFace); - - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - - HANDLE_PACKET_READ(ReadChar, char, CursorX); - HANDLE_PACKET_READ(ReadChar, char, CursorY); - HANDLE_PACKET_READ(ReadChar, char, CursorZ); - - m_Client->HandleRightClick(PosX, PosY, PosZ, BlockFace, CursorX, CursorY, CursorZ, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol132::ParseHandshake(void) -{ - HANDLE_PACKET_READ(ReadByte, Byte, ProtocolVersion); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, ServerHost); - HANDLE_PACKET_READ(ReadBEInt, int, ServerPort); - m_Username = Username; - - if (!m_Client->HandleHandshake( m_Username )) - { - return PARSE_OK; // Player is not allowed into the server - } - - // Send a 0xFD Encryption Key Request http://wiki.vg/Protocol#0xFD - CryptoPP::StringSink sink(m_ServerPublicKey); // GCC won't allow inline instantiation in the following line, damned temporary refs - cRoot::Get()->GetServer()->GetPublicKey().Save(sink); - SendEncryptionKeyRequest(); - - return PARSE_OK; -} - - - - - -int cProtocol132::ParseClientStatuses(void) -{ - HANDLE_PACKET_READ(ReadByte, byte, Status); - if ((Status & 1) == 0) - { - m_Client->HandleLogin(39, m_Username); - } - else - { - m_Client->HandleRespawn(); - } - return PARSE_OK; -} - - - - - -int cProtocol132::ParseEncryptionKeyResponse(void) -{ - HANDLE_PACKET_READ(ReadBEShort, short, EncKeyLength); - AString EncKey; - if (!m_ReceivedData.ReadString(EncKey, EncKeyLength)) - { - return PARSE_INCOMPLETE; - } - HANDLE_PACKET_READ(ReadBEShort, short, EncNonceLength); - AString EncNonce; - if (!m_ReceivedData.ReadString(EncNonce, EncNonceLength)) - { - return PARSE_INCOMPLETE; - } - if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN)) - { - LOGD("Too long encryption"); - m_Client->Kick("Hacked client"); - return PARSE_OK; - } - - HandleEncryptionKeyResponse(EncKey, EncNonce); - return PARSE_OK; -} - - - - - -int cProtocol132::ParseLocaleViewDistance(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Locale); - HANDLE_PACKET_READ(ReadChar, char, ViewDistance); - HANDLE_PACKET_READ(ReadChar, char, ChatFlags); - HANDLE_PACKET_READ(ReadChar, char, ClientDifficulty); - // TODO: m_Client->HandleLocale(Locale); - // TODO: m_Client->HandleViewDistance(ViewDistance); - // TODO: m_Client->HandleChatFlags(ChatFlags); - // Ignoring client difficulty - return PARSE_OK; -} - - - - - -int cProtocol132::ParseLogin(void) -{ - // Login packet not used in 1.3.2 - return PARSE_ERROR; -} - - - - - -int cProtocol132::ParsePlayerAbilities(void) -{ - HANDLE_PACKET_READ(ReadBool, bool, Flags); - HANDLE_PACKET_READ(ReadChar, char, FlyingSpeed); - HANDLE_PACKET_READ(ReadChar, char, WalkingSpeed); - // TODO: m_Client->HandlePlayerAbilities(...); - return PARSE_OK; -} - - - - - -int cProtocol132::ParseTabCompletion(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Text); - m_Client->HandleTabCompletion(Text); - return PARSE_OK; -} - - - - - -void cProtocol132::SendData(const char * a_Data, int a_Size) -{ - m_DataToSend.append(a_Data, a_Size); -} - - - - - -void cProtocol132::Flush(void) -{ - ASSERT(m_CSPacket.IsLockedByCurrentThread()); // Did all packets lock the CS properly? - - if (m_DataToSend.empty()) - { - LOGD("Flushing empty"); - return; - } - const char * a_Data = m_DataToSend.data(); - int a_Size = m_DataToSend.size(); - if (m_IsEncrypted) - { - byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) - while (a_Size > 0) - { - int NumBytes = (a_Size > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Size; - m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes); - super::SendData((const char *)Encrypted, NumBytes); - a_Size -= NumBytes; - a_Data += NumBytes; - } - } - else - { - super::SendData(a_Data, a_Size); - } - m_DataToSend.clear(); -} - - - - - -void cProtocol132::WriteItem(const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - if (a_Item.IsEmpty()) - { - WriteShort(-1); - return; - } - - WriteShort(ItemType); - WriteByte (a_Item.m_ItemCount); - WriteShort(a_Item.m_ItemDamage); - - if (a_Item.m_Enchantments.IsEmpty()) - { - WriteShort(-1); - return; - } - - // Send the enchantments: - cFastNBTWriter Writer; - const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName); - Writer.Finish(); - AString Compressed; - CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); - WriteShort(Compressed.size()); - SendData(Compressed.data(), Compressed.size()); -} - - - - - -int cProtocol132::ParseItem(cItem & a_Item) -{ - HANDLE_PACKET_READ(ReadBEShort, short, ItemType); - - if (ItemType <= -1) - { - a_Item.Empty(); - return PARSE_OK; - } - a_Item.m_ItemType = ItemType; - - HANDLE_PACKET_READ(ReadChar, char, ItemCount); - HANDLE_PACKET_READ(ReadBEShort, short, ItemDamage); - a_Item.m_ItemCount = ItemCount; - a_Item.m_ItemDamage = ItemDamage; - if (ItemCount <= 0) - { - a_Item.Empty(); - } - - HANDLE_PACKET_READ(ReadBEShort, short, MetadataLength); - if (MetadataLength <= 0) - { - return PARSE_OK; - } - - // Read the metadata - AString Metadata; - Metadata.resize(MetadataLength); - if (!m_ReceivedData.ReadBuf((void *)Metadata.data(), MetadataLength)) - { - return PARSE_INCOMPLETE; - } - - return ParseItemMetadata(a_Item, Metadata); -} - - - - - -int cProtocol132::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) -{ - // Uncompress the GZIPped data: - AString Uncompressed; - if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Uncompressed) != Z_OK) - { - AString HexDump; - CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); - LOG("Cannot unGZIP item metadata:\n%s", HexDump.c_str()); - return PARSE_ERROR; - } - - // Parse into NBT: - cParsedNBT NBT(Uncompressed.data(), Uncompressed.size()); - if (!NBT.IsValid()) - { - AString HexDump; - CreateHexDump(HexDump, Uncompressed.data(), Uncompressed.size(), 16); - LOG("Cannot parse NBT item metadata:\n%s", HexDump.c_str()); - return PARSE_ERROR; - } - - // Load enchantments from the NBT: - for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag)) - { - if ( - (NBT.GetType(tag) == TAG_List) && - ( - (NBT.GetName(tag) == "ench") || - (NBT.GetName(tag) == "StoredEnchantments") - ) - ) - { - a_Item.m_Enchantments.ParseFromNBT(NBT, tag); - } - } - - return PARSE_OK; -} - - - - - -void cProtocol132::SendCompass(const cWorld & a_World) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_COMPASS); - WriteInt((int)(a_World.GetSpawnX())); - WriteInt((int)(a_World.GetSpawnY())); - WriteInt((int)(a_World.GetSpawnZ())); - Flush(); -} - - - - - -void cProtocol132::SendEncryptionKeyRequest(void) -{ - cCSLock Lock(m_CSPacket); - WriteByte((char)0xfd); - WriteString(cRoot::Get()->GetServer()->GetServerID()); - WriteShort((short)m_ServerPublicKey.size()); - SendData(m_ServerPublicKey.data(), m_ServerPublicKey.size()); - WriteShort(4); - WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) - Flush(); -} - - - - - -void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce) -{ - // Decrypt EncNonce using privkey - RSAES<PKCS1v15>::Decryptor rsaDecryptor(cRoot::Get()->GetServer()->GetPrivateKey()); - time_t CurTime = time(NULL); - CryptoPP::RandomPool rng; - rng.Put((const byte *)&CurTime, sizeof(CurTime)); - byte DecryptedNonce[MAX_ENC_LEN]; - DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), DecryptedNonce); - if (!res.isValidCoding || (res.messageLength != 4)) - { - LOGD("Bad nonce length"); - m_Client->Kick("Hacked client"); - return; - } - if (ntohl(*((int *)DecryptedNonce)) != (unsigned)(uintptr_t)this) - { - LOGD("Bad nonce value"); - m_Client->Kick("Hacked client"); - return; - } - - // Decrypt the symmetric encryption key using privkey: - byte DecryptedKey[MAX_ENC_LEN]; - res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncKey.data(), a_EncKey.size(), DecryptedKey); - if (!res.isValidCoding || (res.messageLength != 16)) - { - LOGD("Bad key length"); - m_Client->Kick("Hacked client"); - return; - } - - { - // Send encryption key response: - cCSLock Lock(m_CSPacket); - WriteByte((char)0xfc); - WriteShort(0); - WriteShort(0); - Flush(); - } - - StartEncryption(DecryptedKey); - return; -} - - - - - -void cProtocol132::StartEncryption(const byte * a_Key) -{ - m_Encryptor.SetKey(a_Key, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(a_Key, 16))(Name::FeedbackSize(), 1)); - m_Decryptor.SetKey(a_Key, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(a_Key, 16))(Name::FeedbackSize(), 1)); - m_IsEncrypted = true; - - // Prepare the m_AuthServerID: - CryptoPP::SHA1 Checksum; - AString ServerID = cRoot::Get()->GetServer()->GetServerID(); - Checksum.Update((const byte *)ServerID.c_str(), ServerID.length()); - Checksum.Update(a_Key, 16); - Checksum.Update((const byte *)m_ServerPublicKey.c_str(), m_ServerPublicKey.length()); - byte Digest[20]; - Checksum.Final(Digest); - DigestToJava(Digest, m_AuthServerID); -} - - - - diff --git a/source/Protocol/Protocol132.h b/source/Protocol/Protocol132.h deleted file mode 100644 index dc4d8aeef..000000000 --- a/source/Protocol/Protocol132.h +++ /dev/null @@ -1,102 +0,0 @@ - -// Protocol132.h - -// Interfaces to the cProtocol132 class representing the release 1.3.2 protocol (#39) - - - - - -#pragma once - -#include "Protocol125.h" -#include "../../CryptoPP/modes.h" -#include "../../CryptoPP/aes.h" - - - - - -class cProtocol132 : - public cProtocol125 -{ - typedef cProtocol125 super; -public: - - cProtocol132(cClientHandle * a_Client); - virtual ~cProtocol132(); - - /// Called when client sends some data: - virtual void DataReceived(const char * a_Data, int a_Size) override; - - // Sending commands (alphabetically sorted): - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - - virtual AString GetAuthServerID(void) override; - - /// Handling of the additional packets: - virtual int ParsePacket(unsigned char a_PacketType) override; - - // Modified packets: - virtual int ParseBlockPlace (void) override; - virtual int ParseHandshake (void) override; - virtual int ParseLogin (void) override; - virtual int ParsePlayerAbilities(void) override; - - // New packets: - virtual int ParseClientStatuses (void); - virtual int ParseEncryptionKeyResponse(void); - virtual int ParseLocaleViewDistance (void); - virtual int ParseTabCompletion (void); - -protected: - bool m_IsEncrypted; - CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_Decryptor; - CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_Encryptor; - AString m_DataToSend; - - /// The ServerID used for session authentication; set in StartEncryption(), used in GetAuthServerID() - AString m_AuthServerID; - - /// The server's public key, as used by SendEncryptionKeyRequest() and StartEncryption() - AString m_ServerPublicKey; - - virtual void SendData(const char * a_Data, int a_Size) override; - - // DEBUG: - virtual void Flush(void) override; - - // Items in slots are sent differently - virtual void WriteItem(const cItem & a_Item) override; - virtual int ParseItem(cItem & a_Item) override; - - /// Parses the metadata that may come with the item. - int ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); - - virtual void SendCompass(const cWorld & a_World); - virtual void SendEncryptionKeyRequest(void); - - /// Decrypts the key and nonce, checks nonce, starts the symmetric encryption - void HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce); - - /// Starts the symmetric encryption with the specified key; also sets m_AuthServerID - void StartEncryption(const byte * a_Key); -} ; - - - - diff --git a/source/Protocol/Protocol14x.cpp b/source/Protocol/Protocol14x.cpp deleted file mode 100644 index d2582458b..000000000 --- a/source/Protocol/Protocol14x.cpp +++ /dev/null @@ -1,256 +0,0 @@ - -// Protocol14x.cpp - -/* -Implements the 1.4.x protocol classes representing these protocols: -- cProtocol142: - - release 1.4.2 protocol (#47) - - release 1.4.4 protocol (#49) - the same protocol class is used, because the only difference is in a packet that MCServer doesn't implement yet (ITEM_DATA) - - release 1.4.5 protocol (same as 1.4.4) -- cProtocol146: - - release 1.4.6 protocol (#51) -*/ - -#include "Globals.h" -#include "Protocol14x.h" -#include "../Root.h" -#include "../Server.h" -#include "../ClientHandle.h" -#include "../../CryptoPP/randpool.h" -#include "../Item.h" -#include "ChunkDataSerializer.h" -#include "../Entities/Player.h" -#include "../Mobs/Monster.h" -#include "../UI/Window.h" -#include "../Entities/Pickup.h" -#include "../Entities/FallingBlock.h" - - - - - -#define HANDLE_PACKET_READ(Proc, Type, Var) \ - Type Var; \ - { \ - if (!m_ReceivedData.Proc(Var)) \ - { \ - m_ReceivedData.CheckValid(); \ - return PARSE_INCOMPLETE; \ - } \ - m_ReceivedData.CheckValid(); \ - } - - - - - -enum -{ - PACKET_UPDATE_TIME = 0x04, - PACKET_PICKUP_SPAWN = 0x15, - PACKET_SPAWN_OBJECT = 0x17, - PACKET_ENTITY_METADATA = 0x28, - PACKET_SOUND_PARTICLE_EFFECT = 0x3d -} ; - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cProtocol142: - -cProtocol142::cProtocol142(cClientHandle * a_Client) : - super(a_Client) -{ -} - - - - - -int cProtocol142::ParseLocaleViewDistance(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Locale); - HANDLE_PACKET_READ(ReadChar, char, ViewDistance); - HANDLE_PACKET_READ(ReadChar, char, ChatFlags); - HANDLE_PACKET_READ(ReadChar, char, ClientDifficulty); - HANDLE_PACKET_READ(ReadChar, char, ShouldShowCape); // <-- new in 1.4.2 - // TODO: m_Client->HandleLocale(Locale); - // TODO: m_Client->HandleViewDistance(ViewDistance); - // TODO: m_Client->HandleChatFlags(ChatFlags); - // Ignoring client difficulty - return PARSE_OK; -} - - - - - -void cProtocol142::SendPickupSpawn(const cPickup & a_Pickup) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_PICKUP_SPAWN); - WriteInt (a_Pickup.GetUniqueID()); - WriteItem (a_Pickup.GetItem()); - WriteVectorI((Vector3i)(a_Pickup.GetPosition() * 32)); - WriteByte ((char)(a_Pickup.GetSpeed().x * 8)); - WriteByte ((char)(a_Pickup.GetSpeed().y * 8)); - WriteByte ((char)(a_Pickup.GetSpeed().z * 8)); - Flush(); -} - - - - - -void cProtocol142::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_SOUND_PARTICLE_EFFECT); - WriteInt (a_EffectID); - WriteInt (a_SrcX); - WriteByte(a_SrcY); - WriteInt (a_SrcZ); - WriteInt (a_Data); - WriteBool(0); - Flush(); -} - - - - - -void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_UPDATE_TIME); - WriteInt64(a_WorldAge); - WriteInt64(a_TimeOfDay); - Flush(); -} - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cProtocol146: - -cProtocol146::cProtocol146(cClientHandle * a_Client) : - super(a_Client) -{ -} - - - - - -void cProtocol146::SendPickupSpawn(const cPickup & a_Pickup) -{ - ASSERT(!a_Pickup.GetItem().IsEmpty()); - - cCSLock Lock(m_CSPacket); - - // Send a SPAWN_OBJECT packet for the base entity: - WriteByte(PACKET_SPAWN_OBJECT); - WriteInt (a_Pickup.GetUniqueID()); - WriteByte(0x02); - WriteInt ((int)(a_Pickup.GetPosX() * 32)); - WriteInt ((int)(a_Pickup.GetPosY() * 32)); - WriteInt ((int)(a_Pickup.GetPosZ() * 32)); - WriteInt (1); - WriteShort((short)(a_Pickup.GetSpeed().x * 32)); - WriteShort((short)(a_Pickup.GetSpeed().y * 32)); - WriteShort((short)(a_Pickup.GetSpeed().z * 32)); - WriteByte(0); - WriteByte(0); - - // Send a ENTITY_METADATA packet with the slot info: - WriteByte(PACKET_ENTITY_METADATA); - WriteInt(a_Pickup.GetUniqueID()); - WriteByte(0xaa); // a slot value at index 10 - WriteItem(a_Pickup.GetItem()); - WriteByte(0x7f); // End of metadata - Flush(); -} - - - - - -void cProtocol146::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) -{ - // Send a spawn object / vehicle packet - cCSLock Lock(m_CSPacket); - - WriteByte(PACKET_SPAWN_OBJECT); - WriteInt (a_FallingBlock.GetUniqueID()); - WriteByte(70); - WriteInt ((int)(a_FallingBlock.GetPosX() * 32)); - WriteInt ((int)(a_FallingBlock.GetPosY() * 32)); - WriteInt ((int)(a_FallingBlock.GetPosZ() * 32)); - WriteByte (0); // Pitch - WriteByte (0); // Yaw - WriteInt (a_FallingBlock.GetBlockType()); // data indicator = blocktype - WriteShort((short)(a_FallingBlock.GetSpeedX() * 400)); - WriteShort((short)(a_FallingBlock.GetSpeedY() * 400)); - WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400)); - Flush(); -} - - - - - -void cProtocol146::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_SPAWN_OBJECT); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_ObjectType); - WriteInt ((int)(a_Entity.GetPosX() * 32)); - WriteInt ((int)(a_Entity.GetPosY() * 32)); - WriteInt ((int)(a_Entity.GetPosZ() * 32)); - WriteByte(a_Pitch); - WriteByte(a_Yaw); - WriteInt (a_ObjectData); - if (a_ObjectData != 0) - { - WriteShort((short)(a_Entity.GetSpeedX() * 400)); - WriteShort((short)(a_Entity.GetSpeedY() * 400)); - WriteShort((short)(a_Entity.GetSpeedZ() * 400)); - } - Flush(); -} - - - - - -void cProtocol146::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SPAWN_OBJECT); - WriteInt (a_Vehicle.GetUniqueID()); - WriteByte (a_VehicleType); - WriteInt ((int)(a_Vehicle.GetPosX() * 32)); - WriteInt ((int)(a_Vehicle.GetPosY() * 32)); - WriteInt ((int)(a_Vehicle.GetPosZ() * 32)); - WriteByte ((Byte)((a_Vehicle.GetPitch() / 360.f) * 256)); - WriteByte ((Byte)((a_Vehicle.GetRotation() / 360.f) * 256)); - WriteInt (a_VehicleSubType); - if (a_VehicleSubType != 0) - { - WriteShort((short)(a_Vehicle.GetSpeedX() * 400)); - WriteShort((short)(a_Vehicle.GetSpeedY() * 400)); - WriteShort((short)(a_Vehicle.GetSpeedZ() * 400)); - } - Flush(); -} - - - - - diff --git a/source/Protocol/Protocol17x.cpp b/source/Protocol/Protocol17x.cpp deleted file mode 100644 index ae1df7395..000000000 --- a/source/Protocol/Protocol17x.cpp +++ /dev/null @@ -1,1929 +0,0 @@ - -// Protocol17x.cpp - -/* -Implements the 1.7.x protocol classes: - - cProtocol172 - - release 1.7.2 protocol (#4) -(others may be added later in the future for the 1.7 release series) -*/ - -#include "Globals.h" -#include "Protocol17x.h" -#include "ChunkDataSerializer.h" -#include "../ClientHandle.h" -#include "../Root.h" -#include "../Server.h" -#include "../World.h" -#include "../WorldStorage/FastNBT.h" -#include "../StringCompression.h" -#include "../Entities/Minecart.h" -#include "../Entities/FallingBlock.h" -#include "../Entities/Pickup.h" -#include "../Entities/Player.h" -#include "../Mobs/IncludeAllMonsters.h" -#include "../UI/Window.h" - - - - - -#define HANDLE_READ(Proc, Type, Var) \ - Type Var; \ - m_ReceivedData.Proc(Var); - - - - - -#define HANDLE_PACKET_READ(Proc, Type, Var) \ - Type Var; \ - { \ - if (!m_ReceivedData.Proc(Var)) \ - { \ - m_ReceivedData.CheckValid(); \ - return false; \ - } \ - m_ReceivedData.CheckValid(); \ - } - - - - - -cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : - super(a_Client), - m_ServerAddress(a_ServerAddress), - m_ServerPort(a_ServerPort), - m_State(a_State), - m_ReceivedData(32 KiB), - m_OutPacketBuffer(64 KiB), - m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt - m_IsEncrypted(false) -{ -} - - - - - -void cProtocol172::DataReceived(const char * a_Data, int a_Size) -{ - if (m_IsEncrypted) - { - byte Decrypted[512]; - while (a_Size > 0) - { - int NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size; - m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes); - AddReceivedData((const char *)Decrypted, NumBytes); - a_Size -= NumBytes; - a_Data += NumBytes; - } - } - else - { - AddReceivedData(a_Data, a_Size); - } -} - - - - - -void cProtocol172::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle) -{ - cPacketizer Pkt(*this, 0x1b); // Attach Entity packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteInt((a_Vehicle != NULL) ? a_Vehicle->GetUniqueID() : 0); - Pkt.WriteBool(false); -} - - - - - -void cProtocol172::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) -{ - cPacketizer Pkt(*this, 0x24); // Block Action packet - Pkt.WriteInt(a_BlockX); - Pkt.WriteShort(a_BlockY); - Pkt.WriteInt(a_BlockZ); - Pkt.WriteByte(a_Byte1); - Pkt.WriteByte(a_Byte2); - Pkt.WriteVarInt(a_BlockType); -} - - - - - -void cProtocol172::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) -{ - cPacketizer Pkt(*this, 0x24); // Block Break Animation packet - Pkt.WriteInt(a_EntityID); - Pkt.WriteInt(a_BlockX); - Pkt.WriteInt(a_BlockY); - Pkt.WriteInt(a_BlockZ); - Pkt.WriteChar(a_Stage); -} - - - - - -void cProtocol172::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - cPacketizer Pkt(*this, 0x23); // Block Change packet - Pkt.WriteInt(a_BlockX); - Pkt.WriteByte(a_BlockY); - Pkt.WriteInt(a_BlockZ); - Pkt.WriteVarInt(a_BlockType); - Pkt.WriteByte(a_BlockMeta); -} - - - - - -void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) -{ - cPacketizer Pkt(*this, 0x22); // Multi Block Change packet - Pkt.WriteInt(a_ChunkX); - Pkt.WriteInt(a_ChunkZ); - Pkt.WriteShort((short)a_Changes.size()); - Pkt.WriteInt(a_Changes.size() * 4); - for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) - { - unsigned int Coords = itr->y | (itr->z << 8) | (itr->x << 12); - unsigned int Blocks = itr->BlockMeta | (itr->BlockType << 4); - Pkt.WriteInt((Coords << 16) | Blocks); - } // for itr - a_Changes[] -} - - - - - -void cProtocol172::SendChat(const AString & a_Message) -{ - cPacketizer Pkt(*this, 0x02); // Chat Message packet - Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str())); -} - - - - - -void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - // Serialize first, before creating the Packetizer (the packetizer locks a CS) - // This contains the flags and bitmasks, too - const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2); - - cPacketizer Pkt(*this, 0x21); // Chunk Data packet - Pkt.WriteInt(a_ChunkX); - Pkt.WriteInt(a_ChunkZ); - Pkt.WriteBuf(ChunkData.data(), ChunkData.size()); -} - - - - - -void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player) -{ - cPacketizer Pkt(*this, 0x0d); // Collect Item packet - Pkt.WriteInt(a_Pickup.GetUniqueID()); - Pkt.WriteInt(a_Player.GetUniqueID()); -} - - - - - -void cProtocol172::SendDestroyEntity(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x13); // Destroy Entities packet - Pkt.WriteByte(1); - Pkt.WriteInt(a_Entity.GetUniqueID()); -} - - - - - -void cProtocol172::SendDisconnect(const AString & a_Reason) -{ - cPacketizer Pkt(*this, 0x40); - Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Reason).c_str())); -} - - - - - -void cProtocol172::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - cPacketizer Pkt(*this, 0x36); // Sign Editor Open packet - Pkt.WriteInt(a_BlockX); - Pkt.WriteInt(a_BlockY); - Pkt.WriteInt(a_BlockZ); -} - - - - - -void cProtocol172::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) -{ - cPacketizer Pkt(*this, 0x04); // Entity Equipment packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteShort(a_SlotNum); - Pkt.WriteItem(a_Item); -} - - - - - -void cProtocol172::SendEntityHeadLook(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x19); // Entity Head Look packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteByteAngle(a_Entity.GetHeadYaw()); -} - - - - - -void cProtocol172::SendEntityLook(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x16); // Entity Look packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); -} - - - - - -void cProtocol172::SendEntityMetadata(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteEntityMetadata(a_Entity); - Pkt.WriteByte(0x7f); // The termination byte -} - - - - - -void cProtocol172::SendEntityProperties(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x20); // Entity Properties packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteEntityProperties(a_Entity); -} - - - - - -void cProtocol172::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_RelX); - Pkt.WriteByte(a_RelY); - Pkt.WriteByte(a_RelZ); -} - - - - - -void cProtocol172::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_RelX); - Pkt.WriteByte(a_RelY); - Pkt.WriteByte(a_RelZ); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); -} - - - - - -void cProtocol172::SendEntityStatus(const cEntity & a_Entity, char a_Status) -{ - cPacketizer Pkt(*this, 0x1a); // Entity Status packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteChar(a_Status); -} - - - - - -void cProtocol172::SendEntityVelocity(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x12); // Entity Velocity packet - Pkt.WriteInt(a_Entity.GetUniqueID()); - // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick - Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); -} - - - - - -void cProtocol172::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) -{ - cPacketizer Pkt(*this, 0x27); // Explosion packet - Pkt.WriteFloat((float)a_BlockX); - Pkt.WriteFloat((float)a_BlockY); - Pkt.WriteFloat((float)a_BlockZ); - Pkt.WriteFloat((float)a_Radius); - Pkt.WriteInt(a_BlocksAffected.size()); - for (cVector3iArray::const_iterator itr = a_BlocksAffected.begin(), end = a_BlocksAffected.end(); itr != end; ++itr) - { - Pkt.WriteChar((char)itr->x); - Pkt.WriteChar((char)itr->y); - Pkt.WriteChar((char)itr->z); - } // for itr - a_BlockAffected[] - Pkt.WriteFloat((float)a_PlayerMotion.x); - Pkt.WriteFloat((float)a_PlayerMotion.y); - Pkt.WriteFloat((float)a_PlayerMotion.z); -} - - - - - -void cProtocol172::SendGameMode(eGameMode a_GameMode) -{ - cPacketizer Pkt(*this, 0x2b); // Change Game State packet - Pkt.WriteByte(3); // Reason: Change game mode - Pkt.WriteFloat((float)a_GameMode); -} - - - - - -void cProtocol172::SendHealth(void) -{ - cPacketizer Pkt(*this, 0x06); // Update Health packet - Pkt.WriteFloat((float)m_Client->GetPlayer()->GetHealth()); - Pkt.WriteShort(m_Client->GetPlayer()->GetFoodLevel()); - Pkt.WriteFloat((float)m_Client->GetPlayer()->GetFoodSaturationLevel()); -} - - - - - -void cProtocol172::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) -{ - cPacketizer Pkt(*this, 0x2f); // Set Slot packet - Pkt.WriteChar(a_WindowID); - Pkt.WriteShort(a_SlotNum); - Pkt.WriteItem(a_Item); -} - - - - - -void cProtocol172::SendKeepAlive(int a_PingID) -{ - cPacketizer Pkt(*this, 0x00); // Keep Alive packet - Pkt.WriteInt(a_PingID); -} - - - - - -void cProtocol172::SendLogin(const cPlayer & a_Player, const cWorld & a_World) -{ - // Send the Join Game packet: - { - cPacketizer Pkt(*this, 0x01); // Join Game packet - Pkt.WriteInt(a_Player.GetUniqueID()); - Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (cRoot::Get()->GetServer()->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 - Pkt.WriteChar((char)a_World.GetDimension()); - Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) - Pkt.WriteByte(cRoot::Get()->GetServer()->GetMaxPlayers()); - Pkt.WriteString("default"); // Level type - wtf? - } - - // Send the spawn position: - { - cPacketizer Pkt(*this, 0x05); // Spawn Position packet - Pkt.WriteInt((int)a_World.GetSpawnX()); - Pkt.WriteInt((int)a_World.GetSpawnY()); - Pkt.WriteInt((int)a_World.GetSpawnZ()); - } - - // Send player abilities: - SendPlayerAbilities(); -} - - - - - -void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup) -{ - { - cPacketizer Pkt(*this, 0x0e); // Spawn Object packet - Pkt.WriteVarInt(a_Pickup.GetUniqueID()); - Pkt.WriteByte(2); // Type = Pickup - Pkt.WriteFPInt(a_Pickup.GetPosX()); - Pkt.WriteFPInt(a_Pickup.GetPosY()); - Pkt.WriteFPInt(a_Pickup.GetPosZ()); - Pkt.WriteByteAngle(a_Pickup.GetYaw()); - Pkt.WriteByteAngle(a_Pickup.GetPitch()); - Pkt.WriteInt(0); // No object data - } - { - cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet - Pkt.WriteInt(a_Pickup.GetUniqueID()); - Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10 - Pkt.WriteItem(a_Pickup.GetItem()); - Pkt.WriteByte(0x7f); // End of metadata - } -} - - - - - -void cProtocol172::SendPlayerAbilities(void) -{ - cPacketizer Pkt(*this, 0x39); // Player Abilities packet - Byte Flags = 0; - if (m_Client->GetPlayer()->IsGameModeCreative()) - { - Flags |= 0x01; - } - // TODO: Other flags (god mode, flying, can fly - Pkt.WriteByte(Flags); - // TODO: Pkt.WriteFloat(m_Client->GetPlayer()->GetMaxFlyingSpeed()); - Pkt.WriteFloat(0.05f); - Pkt.WriteFloat((float)m_Client->GetPlayer()->GetMaxSpeed()); -} - - - - - -void cProtocol172::SendPlayerAnimation(const cPlayer & a_Player, char a_Animation) -{ - cPacketizer Pkt(*this, 0x0b); // Animation packet - Pkt.WriteVarInt(a_Player.GetUniqueID()); - Pkt.WriteChar(a_Animation); -} - - - - - -void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) -{ - cPacketizer Pkt(*this, 0x38); // Playerlist Item packet - Pkt.WriteString(a_Player.GetName()); - Pkt.WriteBool(a_IsOnline); - Pkt.WriteShort(a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); -} - - - - - -void cProtocol172::SendPlayerMaxSpeed(void) -{ - cPacketizer Pkt(*this, 0x20); // Entity Properties - Pkt.WriteInt(m_Client->GetPlayer()->GetUniqueID()); - Pkt.WriteInt(1); // Count - Pkt.WriteString("generic.movementSpeed"); - Pkt.WriteDouble(0.1); - if (m_Client->GetPlayer()->IsSprinting()) - { - Pkt.WriteShort(1); // Modifier count - Pkt.WriteInt64(0x662a6b8dda3e4c1c); - Pkt.WriteInt64(0x881396ea6097278d); // UUID of the modifier - Pkt.WriteDouble(0.3); - Pkt.WriteByte(2); - } - else - { - Pkt.WriteShort(0); // Modifier count - } -} - - - - - -void cProtocol172::SendPlayerMoveLook(void) -{ - cPacketizer Pkt(*this, 0x08); // Player Position And Look packet - Pkt.WriteDouble(m_Client->GetPlayer()->GetPosX()); - Pkt.WriteDouble(m_Client->GetPlayer()->GetPosY()); - Pkt.WriteDouble(m_Client->GetPlayer()->GetPosZ()); - Pkt.WriteFloat((float)m_Client->GetPlayer()->GetYaw()); - Pkt.WriteFloat((float)m_Client->GetPlayer()->GetPitch()); - Pkt.WriteBool(m_Client->GetPlayer()->IsOnGround()); -} - - - - - -void cProtocol172::SendPlayerPosition(void) -{ - // There is no dedicated packet for this, send the whole thing: - SendPlayerMoveLook(); -} - - - - - -void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player) -{ - // Called to spawn another player for the client - cPacketizer Pkt(*this, 0x0c); // Spawn Player packet - Pkt.WriteVarInt(a_Player.GetUniqueID()); - Pkt.WriteString(Printf("%d", a_Player.GetUniqueID())); // TODO: Proper UUID - Pkt.WriteString(a_Player.GetName()); - Pkt.WriteFPInt(a_Player.GetPosX()); - Pkt.WriteFPInt(a_Player.GetPosY()); - Pkt.WriteFPInt(a_Player.GetPosZ()); - Pkt.WriteByteAngle(a_Player.GetYaw()); - Pkt.WriteByteAngle(a_Player.GetPitch()); - short ItemType = a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType; - Pkt.WriteShort(ItemType); - Pkt.WriteByte((3 << 5) | 6); // Metadata: float + index 6 - Pkt.WriteFloat((float)a_Player.GetHealth()); - Pkt.WriteByte(0x7f); // Metadata: end -} - - - - - -void cProtocol172::SendRespawn(void) -{ - cPacketizer Pkt(*this, 0x07); // Respawn packet - Pkt.WriteInt(m_Client->GetPlayer()->GetWorld()->GetDimension()); - Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) - Pkt.WriteByte((Byte)m_Client->GetPlayer()->GetEffectiveGameMode()); - Pkt.WriteString("default"); -} - - - - - -void cProtocol172::SendExperience (void) -{ - cPacketizer Pkt(*this, 0x1F); //Experience Packet - Pkt.WriteFloat(m_Client->GetPlayer()->GetXpPercentage()); - Pkt.WriteShort(m_Client->GetPlayer()->GetXpLevel()); - Pkt.WriteShort(m_Client->GetPlayer()->GetCurrentXp()); -} - - - - - -void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8 -{ - cPacketizer Pkt(*this, 0x29); // Sound Effect packet - Pkt.WriteString(a_SoundName); - Pkt.WriteInt(a_SrcX); - Pkt.WriteInt(a_SrcY); - Pkt.WriteInt(a_SrcZ); - Pkt.WriteFloat(a_Volume); - Pkt.WriteByte((Byte)(a_Pitch * 63)); -} - - - - - -void cProtocol172::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) -{ - cPacketizer Pkt(*this, 0x28); // Effect packet - Pkt.WriteInt(a_EffectID); - Pkt.WriteInt(a_SrcX); - Pkt.WriteByte(a_SrcY); - Pkt.WriteInt(a_SrcZ); - Pkt.WriteInt(a_Data); - Pkt.WriteBool(false); -} - - - - - -void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) -{ - cPacketizer Pkt(*this, 0x0e); // Spawn Object packet - Pkt.WriteVarInt(a_FallingBlock.GetUniqueID()); - Pkt.WriteByte(70); // Falling block - Pkt.WriteFPInt(a_FallingBlock.GetPosX()); - Pkt.WriteFPInt(a_FallingBlock.GetPosY()); - Pkt.WriteFPInt(a_FallingBlock.GetPosZ()); - Pkt.WriteByteAngle(a_FallingBlock.GetYaw()); - Pkt.WriteByteAngle(a_FallingBlock.GetPitch()); - Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 12)); - Pkt.WriteShort((short)(a_FallingBlock.GetSpeedX() * 400)); - Pkt.WriteShort((short)(a_FallingBlock.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400)); -} - - - - - -void cProtocol172::SendSpawnMob(const cMonster & a_Mob) -{ - cPacketizer Pkt(*this, 0x0f); // Spawn Mob packet - Pkt.WriteVarInt(a_Mob.GetUniqueID()); - Pkt.WriteByte((Byte)a_Mob.GetMobType()); - Pkt.WriteFPInt(a_Mob.GetPosX()); - Pkt.WriteFPInt(a_Mob.GetPosY()); - Pkt.WriteFPInt(a_Mob.GetPosZ()); - Pkt.WriteByteAngle(a_Mob.GetPitch()); - Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); - Pkt.WriteByteAngle(a_Mob.GetYaw()); - Pkt.WriteShort((short)(a_Mob.GetSpeedX() * 400)); - Pkt.WriteShort((short)(a_Mob.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Mob.GetSpeedZ() * 400)); - Pkt.WriteEntityMetadata(a_Mob); - Pkt.WriteByte(0x7f); // Metadata terminator -} - - - - - -void cProtocol172::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) -{ - cPacketizer Pkt(*this, 0xe); // Spawn Object packet - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_ObjectType); - Pkt.WriteFPInt(a_Entity.GetPosX()); - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosZ()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteInt(a_ObjectData); - if (a_ObjectData != 0) - { - Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); - } -} - - - - - -void cProtocol172::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) -{ - cPacketizer Pkt(*this, 0xe); // Spawn Object packet - Pkt.WriteVarInt(a_Vehicle.GetUniqueID()); - Pkt.WriteByte(a_VehicleType); - Pkt.WriteFPInt(a_Vehicle.GetPosX()); - Pkt.WriteFPInt(a_Vehicle.GetPosY()); - Pkt.WriteFPInt(a_Vehicle.GetPosZ()); - Pkt.WriteByteAngle(a_Vehicle.GetYaw()); - Pkt.WriteByteAngle(a_Vehicle.GetPitch()); - Pkt.WriteInt(a_VehicleSubType); - if (a_VehicleSubType != 0) - { - Pkt.WriteShort((short)(a_Vehicle.GetSpeedX() * 400)); - Pkt.WriteShort((short)(a_Vehicle.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Vehicle.GetSpeedZ() * 400)); - } -} - - - - - -void cProtocol172::SendTabCompletionResults(const AStringVector & a_Results) -{ - AString Results; - Results.reserve(500); // Make a moderate reservation to avoid excessive reallocations - for (AStringVector::const_iterator itr = a_Results.begin(), end = a_Results.end(); itr != end; ++itr) - { - Results.append(*itr); - Results.push_back(0); - } - - cPacketizer Pkt(*this, 0x3a); // Tab-Complete packet - Pkt.WriteVarInt(a_Results.size()); - Pkt.WriteString(Results); -} - - - - - -void cProtocol172::SendTeleportEntity(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, 0x18); - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteFPInt(a_Entity.GetPosX()); - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosZ()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); -} - - - - - -void cProtocol172::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - cPacketizer Pkt(*this, 0x2c); // Spawn Global Entity packet - Pkt.WriteVarInt(0); // EntityID = 0, always - Pkt.WriteByte(1); // Type = Thunderbolt - Pkt.WriteFPInt(a_BlockX); - Pkt.WriteFPInt(a_BlockY); - Pkt.WriteFPInt(a_BlockZ); -} - - - - - -void cProtocol172::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) -{ - cPacketizer Pkt(*this, 0x03); - Pkt.WriteInt64(a_WorldAge); - Pkt.WriteInt64(a_TimeOfDay); -} - - - - - -void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) -{ - cPacketizer Pkt(*this, 0x21); // Chunk Data packet - Pkt.WriteInt(a_ChunkX); - Pkt.WriteInt(a_ChunkZ); - Pkt.WriteBool(true); - Pkt.WriteShort(0); // Primary bitmap - Pkt.WriteShort(0); // Add bitmap - Pkt.WriteInt(0); // Compressed data size -} - - - - - -void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) -{ - cPacketizer Pkt(*this, 0x33); - Pkt.WriteInt(a_BlockX); - Pkt.WriteShort((short)a_BlockY); - Pkt.WriteInt(a_BlockZ); - Pkt.WriteString(a_Line1); - Pkt.WriteString(a_Line2); - Pkt.WriteString(a_Line3); - Pkt.WriteString(a_Line4); -} - - - - - -void cProtocol172::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) -{ - cPacketizer Pkt(*this, 0x0a); - Pkt.WriteInt(a_Entity.GetUniqueID()); - Pkt.WriteInt(a_BlockX); - Pkt.WriteByte((Byte)a_BlockY); - Pkt.WriteInt(a_BlockZ); -} - - - - - -void cProtocol172::SendWeather(eWeather a_Weather) -{ - { - cPacketizer Pkt(*this, 0x2b); // Change Game State packet - Pkt.WriteByte((a_Weather == wSunny) ? 1 : 2); // End rain / begin rain - Pkt.WriteFloat(0); // Unused for weather - } - - // TODO: Fade effect, somehow -} - - - - - -void cProtocol172::SendWholeInventory(const cWindow & a_Window) -{ - cPacketizer Pkt(*this, 0x30); // Window Items packet - Pkt.WriteChar(a_Window.GetWindowID()); - Pkt.WriteShort(a_Window.GetNumSlots()); - cItems Slots; - a_Window.GetSlots(*(m_Client->GetPlayer()), Slots); - for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr) - { - Pkt.WriteItem(*itr); - } // for itr - Slots[] -} - - - - - -void cProtocol172::SendWindowClose(const cWindow & a_Window) -{ - cPacketizer Pkt(*this, 0x2e); - Pkt.WriteChar(a_Window.GetWindowID()); -} - - - - - -void cProtocol172::SendWindowOpen(const cWindow & a_Window) -{ - if (a_Window.GetWindowType() < 0) - { - // Do not send this packet for player inventory windows - return; - } - - cPacketizer Pkt(*this, 0x2d); - Pkt.WriteChar(a_Window.GetWindowID()); - Pkt.WriteChar(a_Window.GetWindowType()); - Pkt.WriteString(a_Window.GetWindowTitle()); - Pkt.WriteChar(a_Window.GetNumNonInventorySlots()); - Pkt.WriteBool(true); - if (a_Window.GetWindowType() == cWindow::wtAnimalChest) - { - Pkt.WriteInt(0); // TODO: The animal's EntityID - } -} - - - - - -void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) -{ - cPacketizer Pkt(*this, 0x31); // Window Property packet - Pkt.WriteChar(a_Window.GetWindowID()); - Pkt.WriteShort(a_Property); - Pkt.WriteShort(a_Value); -} - - - - - -void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) -{ - if (!m_ReceivedData.Write(a_Data, a_Size)) - { - // Too much data in the incoming queue, report to caller: - m_Client->PacketBufferFull(); - return; - } - - // Handle all complete packets: - while (true) - { - UInt32 PacketLen; - if (!m_ReceivedData.ReadVarInt(PacketLen)) - { - // Not enough data - return; - } - if (!m_ReceivedData.CanReadBytes(PacketLen)) - { - // The full packet hasn't been received yet - return; - } - UInt32 PacketType; - UInt32 Mark1 = m_ReceivedData.GetReadableSpace(); - if (!m_ReceivedData.ReadVarInt(PacketType)) - { - // Not enough data - return; - } - - UInt32 NumBytesRead = Mark1 - m_ReceivedData.GetReadableSpace(); - HandlePacket(PacketType, PacketLen - NumBytesRead); - - if (Mark1 - m_ReceivedData.GetReadableSpace() > PacketLen) - { - // Read more than packet length, report as error - m_Client->PacketError(PacketType); - } - - // Go to packet end in any case: - m_ReceivedData.ResetRead(); - m_ReceivedData.ReadVarInt(PacketType); - m_ReceivedData.SkipRead(PacketLen); - m_ReceivedData.CommitRead(); - } // while (true) -} - - - - -void cProtocol172::HandlePacket(UInt32 a_PacketType, UInt32 a_RemainingBytes) -{ - switch (m_State) - { - case 1: - { - // Status - switch (a_PacketType) - { - case 0x00: HandlePacketStatusRequest(a_RemainingBytes); return; - case 0x01: HandlePacketStatusPing (a_RemainingBytes); return; - } - break; - } - - case 2: - { - // Login - switch (a_PacketType) - { - case 0x00: HandlePacketLoginStart(a_RemainingBytes); return; - case 0x01: HandlePacketLoginEncryptionResponse(a_RemainingBytes); return; - } - break; - } - - case 3: - { - // Game - switch (a_PacketType) - { - case 0x00: HandlePacketKeepAlive (a_RemainingBytes); return; - case 0x01: HandlePacketChatMessage (a_RemainingBytes); return; - case 0x02: HandlePacketUseEntity (a_RemainingBytes); return; - case 0x03: HandlePacketPlayer (a_RemainingBytes); return; - case 0x04: HandlePacketPlayerPos (a_RemainingBytes); return; - case 0x05: HandlePacketPlayerLook (a_RemainingBytes); return; - case 0x06: HandlePacketPlayerPosLook (a_RemainingBytes); return; - case 0x07: HandlePacketBlockDig (a_RemainingBytes); return; - case 0x08: HandlePacketBlockPlace (a_RemainingBytes); return; - case 0x09: HandlePacketSlotSelect (a_RemainingBytes); return; - case 0x0a: HandlePacketAnimation (a_RemainingBytes); return; - case 0x0b: HandlePacketEntityAction (a_RemainingBytes); return; - case 0x0c: HandlePacketSteerVehicle (a_RemainingBytes); return; - case 0x0d: HandlePacketWindowClose (a_RemainingBytes); return; - case 0x0e: HandlePacketWindowClick (a_RemainingBytes); return; - case 0x0f: // Confirm transaction - not used in MCS - case 0x10: HandlePacketCreativeInventoryAction(a_RemainingBytes); return; - case 0x12: HandlePacketUpdateSign (a_RemainingBytes); return; - case 0x13: HandlePacketPlayerAbilities (a_RemainingBytes); return; - case 0x14: HandlePacketTabComplete (a_RemainingBytes); return; - case 0x15: HandlePacketClientSettings (a_RemainingBytes); return; - case 0x16: HandlePacketClientStatus (a_RemainingBytes); return; - case 0x17: HandlePacketPluginMessage (a_RemainingBytes); return; - } - break; - } - } // switch (m_State) - - // Unknown packet type, report to the client: - m_Client->PacketUnknown(a_PacketType); - m_ReceivedData.SkipRead(a_RemainingBytes); - m_ReceivedData.CommitRead(); -} - - - - - -void cProtocol172::HandlePacketStatusPing(UInt32 a_RemainingBytes) -{ - ASSERT(a_RemainingBytes == 8); - if (a_RemainingBytes != 8) - { - m_Client->PacketError(0x01); - m_ReceivedData.SkipRead(a_RemainingBytes); - m_ReceivedData.CommitRead(); - return; - } - Int64 Timestamp; - m_ReceivedData.ReadBEInt64(Timestamp); - m_ReceivedData.CommitRead(); - - cPacketizer Pkt(*this, 0x01); // Ping packet - Pkt.WriteInt64(Timestamp); -} - - - - - -void cProtocol172::HandlePacketStatusRequest(UInt32 a_RemainingBytes) -{ - // No more bytes in this packet - ASSERT(a_RemainingBytes == 0); - m_ReceivedData.CommitRead(); - - // Send the response: - AString Response = "{\"version\":{\"name\":\"1.7.2\",\"protocol\":4},\"players\":{"; - AppendPrintf(Response, "\"max\":%u,\"online\":%u,\"sample\":[]},", - cRoot::Get()->GetServer()->GetMaxPlayers(), - cRoot::Get()->GetServer()->GetNumPlayers() - ); - AppendPrintf(Response, "\"description\":{\"text\":\"%s\"}", - cRoot::Get()->GetServer()->GetDescription().c_str() - ); - Response.append("}"); - - cPacketizer Pkt(*this, 0x00); // Response packet - Pkt.WriteString(Response); -} - - - - - -void cProtocol172::HandlePacketLoginEncryptionResponse(UInt32 a_RemainingBytes) -{ - // TODO: Add protocol encryption -} - - - - - -void cProtocol172::HandlePacketLoginStart(UInt32 a_RemainingBytes) -{ - AString Username; - m_ReceivedData.ReadVarUTF8String(Username); - - // TODO: Protocol encryption should be set up here if not localhost / auth - - // Send login success: - { - cPacketizer Pkt(*this, 0x02); // Login success packet - Pkt.WriteString(Printf("%d", m_Client->GetUniqueID())); // TODO: proper UUID - Pkt.WriteString(Username); - } - - m_State = 3; // State = Game - m_Client->HandleLogin(4, Username); -} - - - - - -void cProtocol172::HandlePacketAnimation(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEInt, int, EntityID); - HANDLE_READ(ReadByte, Byte, Animation); - m_Client->HandleAnimation(Animation); -} - - - - - -void cProtocol172::HandlePacketBlockDig(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadByte, Byte, Status); - HANDLE_READ(ReadBEInt, int, BlockX); - HANDLE_READ(ReadByte, Byte, BlockY); - HANDLE_READ(ReadBEInt, int, BlockZ); - HANDLE_READ(ReadByte, Byte, Face); - m_Client->HandleLeftClick(BlockX, BlockY, BlockZ, Face, Status); -} - - - - - -void cProtocol172::HandlePacketBlockPlace(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEInt, int, BlockX); - HANDLE_READ(ReadByte, Byte, BlockY); - HANDLE_READ(ReadBEInt, int, BlockZ); - HANDLE_READ(ReadByte, Byte, Face); - HANDLE_READ(ReadByte, Byte, CursorX); - HANDLE_READ(ReadByte, Byte, CursorY); - HANDLE_READ(ReadByte, Byte, CursorZ); - m_Client->HandleRightClick(BlockX, BlockY, BlockZ, Face, CursorX, CursorY, CursorZ, m_Client->GetPlayer()->GetEquippedItem()); -} - - - - - -void cProtocol172::HandlePacketChatMessage(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadVarUTF8String, AString, Message); - m_Client->HandleChat(Message); -} - - - - - -void cProtocol172::HandlePacketClientSettings(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadVarUTF8String, AString, Locale); - HANDLE_READ(ReadByte, Byte, ViewDistance); - HANDLE_READ(ReadByte, Byte, ChatFlags); - HANDLE_READ(ReadByte, Byte, Unused); - HANDLE_READ(ReadByte, Byte, Difficulty); - HANDLE_READ(ReadByte, Byte, ShowCape); - // TODO: handle in m_Client -} - - - - - -void cProtocol172::HandlePacketClientStatus(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadByte, Byte, ActionID); - switch (ActionID) - { - case 0: - { - // Respawn - m_Client->HandleRespawn(); - break; - } - case 1: - { - // Request stats - // TODO - break; - } - case 2: - { - // Open Inventory achievement - // TODO - break; - } - } -} - - - - - -void cProtocol172::HandlePacketCreativeInventoryAction(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEShort, short, SlotNum); - cItem Item; - if (!ReadItem(Item)) - { - return; - } - m_Client->HandleCreativeInventory(SlotNum, Item); -} - - - - - -void cProtocol172::HandlePacketEntityAction(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEInt, int, PlayerID); - HANDLE_READ(ReadByte, Byte, Action); - HANDLE_READ(ReadBEInt, int, JumpBoost); - m_Client->HandleEntityAction(PlayerID, Action); -} - - - - - -void cProtocol172::HandlePacketKeepAlive(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEInt, int, KeepAliveID); - m_Client->HandleKeepAlive(KeepAliveID); -} - - - - - -void cProtocol172::HandlePacketPlayer(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBool, bool, IsOnGround); - // TODO: m_Client->HandlePlayerOnGround(IsOnGround); -} - - - - - -void cProtocol172::HandlePacketPlayerAbilities(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadByte, Byte, Flags); - HANDLE_READ(ReadBEFloat, float, FlyingSpeed); - HANDLE_READ(ReadBEFloat, float, WalkingSpeed); - // TODO: m_Client->HandlePlayerAbilities(); -} - - - - - -void cProtocol172::HandlePacketPlayerLook(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEFloat, float, Yaw); - HANDLE_READ(ReadBEFloat, float, Pitch); - HANDLE_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerLook(Yaw, Pitch, IsOnGround); -} - - - - - -void cProtocol172::HandlePacketPlayerPos(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEDouble, double, PosX); - HANDLE_READ(ReadBEDouble, double, PosY); - HANDLE_READ(ReadBEDouble, double, Stance); - HANDLE_READ(ReadBEDouble, double, PosZ); - HANDLE_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerPos(PosX, PosY, PosZ, Stance, IsOnGround); -} - - - - - -void cProtocol172::HandlePacketPlayerPosLook(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEDouble, double, PosX); - HANDLE_READ(ReadBEDouble, double, PosY); - HANDLE_READ(ReadBEDouble, double, Stance); - HANDLE_READ(ReadBEDouble, double, PosZ); - HANDLE_READ(ReadBEFloat, float, Yaw); - HANDLE_READ(ReadBEFloat, float, Pitch); - HANDLE_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, Stance, Yaw, Pitch, IsOnGround); -} - - - - - -void cProtocol172::HandlePacketPluginMessage(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadVarUTF8String, AString, Channel); - HANDLE_READ(ReadBEShort, short, Length); - AString Data; - m_ReceivedData.ReadString(Data, Length); - // TODO: m_Client->HandlePluginMessage(Channel, Data); -} - - - - - -void cProtocol172::HandlePacketSlotSelect(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEShort, short, SlotNum); - m_Client->HandleSlotSelected(SlotNum); -} - - - - - -void cProtocol172::HandlePacketSteerVehicle(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEFloat, float, Forward); - HANDLE_READ(ReadBEFloat, float, Sideways); - HANDLE_READ(ReadBool, bool, ShouldJump); - HANDLE_READ(ReadBool, bool, ShouldUnmount); - if (ShouldUnmount) - { - m_Client->HandleUnmount(); - } - else - { - m_Client->HandleSteerVehicle(Forward, Sideways); - } -} - - - - - -void cProtocol172::HandlePacketTabComplete(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadVarUTF8String, AString, Text); - m_Client->HandleTabCompletion(Text); -} - - - - - -void cProtocol172::HandlePacketUpdateSign(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEInt, int, BlockX); - HANDLE_READ(ReadBEShort, short, BlockY); - HANDLE_READ(ReadBEInt, int, BlockZ); - HANDLE_READ(ReadVarUTF8String, AString, Line1); - HANDLE_READ(ReadVarUTF8String, AString, Line2); - HANDLE_READ(ReadVarUTF8String, AString, Line3); - HANDLE_READ(ReadVarUTF8String, AString, Line4); - m_Client->HandleUpdateSign(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); -} - - - - - -void cProtocol172::HandlePacketUseEntity(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadBEInt, int, EntityID); - HANDLE_READ(ReadByte, Byte, MouseButton); - m_Client->HandleUseEntity(EntityID, (MouseButton == 1)); -} - - - - - -void cProtocol172::HandlePacketWindowClick(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadChar, char, WindowID); - HANDLE_READ(ReadBEShort, short, SlotNum); - HANDLE_READ(ReadByte, Byte, Button); - HANDLE_READ(ReadBEShort, short, TransactionID); - HANDLE_READ(ReadByte, Byte, Mode); - cItem Item; - ReadItem(Item); - - // Convert Button, Mode, SlotNum and HeldItem into eClickAction: - eClickAction Action; - switch ((Mode << 8) | Button) - { - case 0x0000: Action = (SlotNum != -999) ? caLeftClick : caLeftClickOutside; break; - case 0x0001: Action = (SlotNum != -999) ? caRightClick : caRightClickOutside; break; - case 0x0100: Action = caShiftLeftClick; break; - case 0x0101: Action = caShiftRightClick; break; - case 0x0200: Action = caNumber1; break; - case 0x0201: Action = caNumber2; break; - case 0x0202: Action = caNumber3; break; - case 0x0203: Action = caNumber4; break; - case 0x0204: Action = caNumber5; break; - case 0x0205: Action = caNumber6; break; - case 0x0206: Action = caNumber7; break; - case 0x0207: Action = caNumber8; break; - case 0x0208: Action = caNumber9; break; - case 0x0300: Action = caMiddleClick; break; - case 0x0400: Action = (SlotNum == -999) ? caLeftClickOutsideHoldNothing : caDropKey; break; - case 0x0401: Action = (SlotNum == -999) ? caRightClickOutsideHoldNothing : caCtrlDropKey; break; - case 0x0500: Action = (SlotNum == -999) ? caLeftPaintBegin : caUnknown; break; - case 0x0501: Action = (SlotNum != -999) ? caLeftPaintProgress : caUnknown; break; - case 0x0502: Action = (SlotNum == -999) ? caLeftPaintEnd : caUnknown; break; - case 0x0504: Action = (SlotNum == -999) ? caRightPaintBegin : caUnknown; break; - case 0x0505: Action = (SlotNum != -999) ? caRightPaintProgress : caUnknown; break; - case 0x0506: Action = (SlotNum == -999) ? caRightPaintEnd : caUnknown; break; - case 0x0600: Action = caDblClick; break; - } - - m_Client->HandleWindowClick(WindowID, SlotNum, Action, Item); -} - - - - - -void cProtocol172::HandlePacketWindowClose(UInt32 a_RemainingBytes) -{ - HANDLE_READ(ReadChar, char, WindowID); - m_Client->HandleWindowClose(WindowID); -} - - - - - -void cProtocol172::WritePacket(cByteBuffer & a_Packet) -{ - cCSLock Lock(m_CSPacket); - AString Pkt; - a_Packet.ReadAll(Pkt); - WriteVarInt(Pkt.size()); - SendData(Pkt.data(), Pkt.size()); - Flush(); -} - - - - - -void cProtocol172::SendData(const char * a_Data, int a_Size) -{ - if (m_IsEncrypted) - { - byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) - while (a_Size > 0) - { - int NumBytes = (a_Size > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Size; - m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes); - m_Client->SendData((const char *)Encrypted, NumBytes); - a_Size -= NumBytes; - a_Data += NumBytes; - } - } - else - { - m_Client->SendData(a_Data, a_Size); - } -} - - - - - - -bool cProtocol172::ReadItem(cItem & a_Item) -{ - HANDLE_PACKET_READ(ReadBEShort, short, ItemType); - if (ItemType == -1) - { - // The item is empty, no more data follows - a_Item.Empty(); - return true; - } - a_Item.m_ItemType = ItemType; - - HANDLE_PACKET_READ(ReadChar, char, ItemCount); - HANDLE_PACKET_READ(ReadBEShort, short, ItemDamage); - a_Item.m_ItemCount = ItemCount; - a_Item.m_ItemDamage = ItemDamage; - if (ItemCount <= 0) - { - a_Item.Empty(); - } - - HANDLE_PACKET_READ(ReadBEShort, short, MetadataLength); - if (MetadataLength <= 0) - { - return true; - } - - // Read the metadata - AString Metadata; - if (!m_ReceivedData.ReadString(Metadata, MetadataLength)) - { - return false; - } - - ParseItemMetadata(a_Item, Metadata); - return true; -} - - - - - -void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) -{ - // Uncompress the GZIPped data: - AString Uncompressed; - if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Uncompressed) != Z_OK) - { - AString HexDump; - CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); - LOGWARNING("Cannot unGZIP item metadata (%u bytes):\n%s", a_Metadata.size(), HexDump.c_str()); - return; - } - - // Parse into NBT: - cParsedNBT NBT(Uncompressed.data(), Uncompressed.size()); - if (!NBT.IsValid()) - { - AString HexDump; - CreateHexDump(HexDump, Uncompressed.data(), Uncompressed.size(), 16); - LOGWARNING("Cannot parse NBT item metadata: (%u bytes)\n%s", Uncompressed.size(), HexDump.c_str()); - return; - } - - // Load enchantments from the NBT: - for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag)) - { - if ( - (NBT.GetType(tag) == TAG_List) && - ( - (NBT.GetName(tag) == "ench") || - (NBT.GetName(tag) == "StoredEnchantments") - ) - ) - { - a_Item.m_Enchantments.ParseFromNBT(NBT, tag); - } - } -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cProtocol172::cPacketizer: - -cProtocol172::cPacketizer::~cPacketizer() -{ - AString DataToSend; - - // Send the packet length - UInt32 PacketLen = m_Out.GetUsedSpace(); - m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); - m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); - m_Protocol.SendData(DataToSend.data(), DataToSend.size()); - m_Protocol.m_OutPacketLenBuffer.CommitRead(); - - // Send the packet data: - m_Out.ReadAll(DataToSend); - m_Protocol.SendData(DataToSend.data(), DataToSend.size()); - m_Out.CommitRead(); -} - - - - - -void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - if (a_Item.IsEmpty()) - { - WriteShort(-1); - return; - } - - WriteShort(ItemType); - WriteByte (a_Item.m_ItemCount); - WriteShort(a_Item.m_ItemDamage); - - if (a_Item.m_Enchantments.IsEmpty()) - { - WriteShort(-1); - return; - } - - // Send the enchantments: - cFastNBTWriter Writer; - const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName); - Writer.Finish(); - AString Compressed; - CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); - WriteShort(Compressed.size()); - WriteBuf(Compressed.data(), Compressed.size()); -} - - - - - -void cProtocol172::cPacketizer::WriteByteAngle(double a_Angle) -{ - WriteByte((char)(255 * a_Angle / 360)); -} - - - - - -void cProtocol172::cPacketizer::WriteFPInt(double a_Value) -{ - int Value = (int)(a_Value * 32); - WriteInt(Value); -} - - - - - -void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) -{ - // Common metadata: - Byte Flags = 0; - if (a_Entity.IsOnFire()) - { - Flags |= 0x01; - } - if (a_Entity.IsCrouched()) - { - Flags |= 0x02; - } - if (a_Entity.IsSprinting()) - { - Flags |= 0x08; - } - if (a_Entity.IsRclking()) - { - Flags |= 0x10; - } - if (a_Entity.IsInvisible()) - { - Flags |= 0x20; - } - WriteByte(0); // Byte(0) + index 0 - WriteByte(Flags); - - switch (a_Entity.GetEntityType()) - { - case cEntity::etPlayer: break; // TODO? - case cEntity::etPickup: - { - WriteByte((5 << 5) | 10); // Slot(5) + index 10 - WriteItem(((const cPickup &)a_Entity).GetItem()); - break; - } - case cEntity::etMinecart: - { - WriteByte(0x51); - - // The following expression makes Minecarts shake more with less health or higher damage taken - // It gets half the maximum health, and takes it away from the current health minus the half health: - /* Health: 5 | 3 - (5 - 3) = 1 (shake power) - Health: 3 | 3 - (3 - 3) = 3 - Health: 1 | 3 - (1 - 3) = 5 - */ - WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4); - WriteByte(0x52); - WriteInt(1); // Shaking direction, doesn't seem to affect anything - WriteByte(0x73); - WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer - - if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace) - { - WriteByte(0x10); - WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); - } - break; - } - case cEntity::etProjectile: - { - if (((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow) - { - WriteByte(0x10); - WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); - } - break; - } - case cEntity::etMonster: - { - WriteMobMetadata((const cMonster &)a_Entity); - break; - } - } -} - - - - - -void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) -{ - switch (a_Mob.GetMobType()) - { - case cMonster::mtCreeper: - { - WriteByte(0x10); - WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); - WriteByte(0x11); - WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); - break; - } - - case cMonster::mtBat: - { - WriteByte(0x10); - WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); - break; - } - - case cMonster::mtPig: - { - WriteByte(0x10); - WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); - break; - } - - case cMonster::mtVillager: - { - WriteByte(0x50); - WriteInt(((const cVillager &)a_Mob).GetVilType()); - break; - } - - case cMonster::mtZombie: - { - WriteByte(0x0c); - WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); - WriteByte(0x0d); - WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); - WriteByte(0x0e); - WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); - break; - } - - case cMonster::mtGhast: - { - WriteByte(0x10); - WriteByte(((const cGhast &)a_Mob).IsCharging()); - break; - } - - case cMonster::mtWolf: - { - const cWolf & Wolf = (const cWolf &)a_Mob; - Byte WolfStatus = 0; - if (Wolf.IsSitting()) - { - WolfStatus |= 0x1; - } - if (Wolf.IsAngry()) - { - WolfStatus |= 0x2; - } - if (Wolf.IsTame()) - { - WolfStatus |= 0x4; - } - WriteByte(0x10); - WriteByte(WolfStatus); - - WriteByte(0x72); - WriteFloat((float)(a_Mob.GetHealth())); - WriteByte(0x13); - WriteByte(Wolf.IsBegging() ? 1 : 0); - WriteByte(0x14); - WriteByte(Wolf.GetCollarColor()); - break; - } - - case cMonster::mtSheep: - { - WriteByte(0x10); - Byte SheepMetadata = 0; - SheepMetadata = ((const cSheep &)a_Mob).GetFurColor(); - if (((const cSheep &)a_Mob).IsSheared()) - { - SheepMetadata |= 0x10; - } - WriteByte(SheepMetadata); - break; - } - - case cMonster::mtEnderman: - { - WriteByte(0x10); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); - WriteByte(0x11); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); - WriteByte(0x12); - WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); - break; - } - - case cMonster::mtSkeleton: - { - WriteByte(0x0d); - WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); - break; - } - - case cMonster::mtWitch: - { - WriteByte(0x15); - WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); - break; - } - - case cMonster::mtSlime: - { - WriteByte(0x10); - WriteByte(((const cSlime &)a_Mob).GetSize()); - break; - } - - case cMonster::mtMagmaCube: - { - WriteByte(0x10); - WriteByte(((const cMagmaCube &)a_Mob).GetSize()); - break; - } - - case cMonster::mtHorse: - { - const cHorse & Horse = (const cHorse &)a_Mob; - int Flags = 0; - if (Horse.IsTame()) - { - Flags |= 0x02; - } - if (Horse.IsSaddled()) - { - Flags |= 0x04; - } - if (Horse.IsChested()) - { - Flags |= 0x08; - } - if (Horse.IsBaby()) - { - Flags |= 0x10; - } - if (Horse.IsEating()) - { - Flags |= 0x20; - } - if (Horse.IsRearing()) - { - Flags |= 0x40; - } - if (Horse.IsMthOpen()) - { - Flags |= 0x80; - } - WriteByte(0x50); // Int at index 16 - WriteInt(Flags); - WriteByte(0x13); // Byte at index 19 - WriteByte(Horse.GetHorseType()); - WriteByte(0x54); // Int at index 20 - int Appearance = 0; - Appearance = Horse.GetHorseColor(); - Appearance |= Horse.GetHorseStyle() << 8; - WriteInt(Appearance); - WriteByte(0x56); // Int at index 22 - WriteInt(Horse.GetHorseArmour()); - break; - } - } // switch (a_Mob.GetType()) -} - - - - - -void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity) -{ - if (!a_Entity.IsMob()) - { - // No properties for anything else than mobs - WriteInt(0); - return; - } - const cMonster & Mob = (const cMonster &)a_Entity; - - // TODO: Send properties and modifiers based on the mob type - - WriteInt(0); // NumProperties -} - - - - diff --git a/source/Protocol/Protocol17x.h b/source/Protocol/Protocol17x.h deleted file mode 100644 index e3f2ad922..000000000 --- a/source/Protocol/Protocol17x.h +++ /dev/null @@ -1,259 +0,0 @@ - -// Protocol17x.h - -/* -Declares the 1.7.x protocol classes: - - cProtocol172 - - release 1.7.2 protocol (#4) -(others may be added later in the future for the 1.7 release series) -*/ - - - - - -#pragma once - -#include "Protocol.h" -#include "../ByteBuffer.h" -#include "../../CryptoPP/modes.h" -#include "../../CryptoPP/aes.h" - - - - - -class cProtocol172 : - public cProtocol // TODO -{ - typedef cProtocol super; // TODO - -public: - - cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); - - /// Called when client sends some data: - virtual void DataReceived(const char * a_Data, int a_Size) override; - - /// Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override; - virtual void SendPlayerAnimation (const cPlayer & a_Player, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendRespawn (void) override; - virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 - virtual void SendExperience (void) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; - - virtual AString GetAuthServerID(void) override { return m_AuthServerID; } - -protected: - - /// Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed - class cPacketizer - { - public: - cPacketizer(cProtocol172 & a_Protocol, UInt32 a_PacketType) : - m_Protocol(a_Protocol), - m_Out(a_Protocol.m_OutPacketBuffer), - m_Lock(a_Protocol.m_CSPacket) - { - m_Out.WriteVarInt(a_PacketType); - } - - ~cPacketizer(); - - void WriteBool(bool a_Value) - { - m_Out.WriteBool(a_Value); - } - - void WriteByte(Byte a_Value) - { - m_Out.WriteByte(a_Value); - } - - void WriteChar(char a_Value) - { - m_Out.WriteChar(a_Value); - } - - void WriteShort(short a_Value) - { - m_Out.WriteBEShort(a_Value); - } - - void WriteInt(int a_Value) - { - m_Out.WriteBEInt(a_Value); - } - - void WriteInt64(Int64 a_Value) - { - m_Out.WriteBEInt64(a_Value); - } - - void WriteFloat(float a_Value) - { - m_Out.WriteBEFloat(a_Value); - } - - void WriteDouble(double a_Value) - { - m_Out.WriteBEDouble(a_Value); - } - - void WriteVarInt(UInt32 a_Value) - { - m_Out.WriteVarInt(a_Value); - } - - void WriteString(const AString & a_Value) - { - m_Out.WriteVarUTF8String(a_Value); - } - - void WriteBuf(const char * a_Data, int a_Size) - { - m_Out.Write(a_Data, a_Size); - } - - void WriteItem(const cItem & a_Item); - void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte - void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer - void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f - void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob - void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field - - protected: - cProtocol172 & m_Protocol; - cByteBuffer & m_Out; - cCSLock m_Lock; - } ; - - AString m_ServerAddress; - - UInt16 m_ServerPort; - - AString m_AuthServerID; - - /// State of the protocol. 1 = status, 2 = login, 3 = game - UInt32 m_State; - - /// Buffer for the received data - cByteBuffer m_ReceivedData; - - /// Buffer for composing the outgoing packets, through cPacketizer - cByteBuffer m_OutPacketBuffer; - - /// Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) - cByteBuffer m_OutPacketLenBuffer; - - bool m_IsEncrypted; - CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_Decryptor; - CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_Encryptor; - - - /// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets - void AddReceivedData(const char * a_Data, int a_Size); - - /// Reads and handles the packet. The packet length and type have already been read. - void HandlePacket(UInt32 a_PacketType, UInt32 a_RemainingBytes); - - // Packet handlers while in the Status state (m_State == 1): - void HandlePacketStatusPing (UInt32 a_RemainingBytes); - void HandlePacketStatusRequest(UInt32 a_RemainingBytes); - - // Packet handlers while in the Login state (m_State == 2): - void HandlePacketLoginEncryptionResponse(UInt32 a_RemainingBytes); - void HandlePacketLoginStart (UInt32 a_RemainingBytes); - - // Packet handlers while in the Game state (m_State == 3): - void HandlePacketAnimation (UInt32 a_RemainingBytes); - void HandlePacketBlockDig (UInt32 a_RemainingBytes); - void HandlePacketBlockPlace (UInt32 a_RemainingBytes); - void HandlePacketChatMessage (UInt32 a_RemainingBytes); - void HandlePacketClientSettings (UInt32 a_RemainingBytes); - void HandlePacketClientStatus (UInt32 a_RemainingBytes); - void HandlePacketCreativeInventoryAction(UInt32 a_RemainingBytes); - void HandlePacketEntityAction (UInt32 a_RemainingBytes); - void HandlePacketKeepAlive (UInt32 a_RemainingBytes); - void HandlePacketPlayer (UInt32 a_RemainingBytes); - void HandlePacketPlayerAbilities (UInt32 a_RemainingBytes); - void HandlePacketPlayerLook (UInt32 a_RemainingBytes); - void HandlePacketPlayerPos (UInt32 a_RemainingBytes); - void HandlePacketPlayerPosLook (UInt32 a_RemainingBytes); - void HandlePacketPluginMessage (UInt32 a_RemainingBytes); - void HandlePacketSlotSelect (UInt32 a_RemainingBytes); - void HandlePacketSteerVehicle (UInt32 a_RemainingBytes); - void HandlePacketTabComplete (UInt32 a_RemainingBytes); - void HandlePacketUpdateSign (UInt32 a_RemainingBytes); - void HandlePacketUseEntity (UInt32 a_RemainingBytes); - void HandlePacketWindowClick (UInt32 a_RemainingBytes); - void HandlePacketWindowClose (UInt32 a_RemainingBytes); - - - /// Writes an entire packet into the output stream. a_Packet is expected to start with the packet type; data length is prepended here. - void WritePacket(cByteBuffer & a_Packet); - - /// Sends the data to the client, encrypting them if needed. - virtual void SendData(const char * a_Data, int a_Size) override; - - void SendCompass(const cWorld & a_World); - - /// Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data - bool ReadItem(cItem & a_Item); - - /// Parses item metadata as read by ReadItem(), into the item enchantments. - void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); -} ; - - - - diff --git a/source/Protocol/ProtocolRecognizer.cpp b/source/Protocol/ProtocolRecognizer.cpp deleted file mode 100644 index 64bd83075..000000000 --- a/source/Protocol/ProtocolRecognizer.cpp +++ /dev/null @@ -1,915 +0,0 @@ - -// ProtocolRecognizer.cpp - -// Implements the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple -// protocol versions and redirects everything to them - -#include "Globals.h" - -#include "ProtocolRecognizer.h" -#include "Protocol125.h" -#include "Protocol132.h" -#include "Protocol14x.h" -#include "Protocol15x.h" -#include "Protocol16x.h" -#include "Protocol17x.h" -#include "../ClientHandle.h" -#include "../Root.h" -#include "../Server.h" -#include "../World.h" -#include "../ChatColor.h" - - - - - -cProtocolRecognizer::cProtocolRecognizer(cClientHandle * a_Client) : - super(a_Client), - m_Protocol(NULL), - m_Buffer(512) -{ -} - - - - - -cProtocolRecognizer::~cProtocolRecognizer() -{ - delete m_Protocol; -} - - - - - -AString cProtocolRecognizer::GetVersionTextFromInt(int a_ProtocolVersion) -{ - switch (a_ProtocolVersion) - { - case PROTO_VERSION_1_2_5: return "1.2.5"; - case PROTO_VERSION_1_3_2: return "1.3.2"; - case PROTO_VERSION_1_4_2: return "1.4.2"; - case PROTO_VERSION_1_4_4: return "1.4.4"; - case PROTO_VERSION_1_4_6: return "1.4.6"; - case PROTO_VERSION_1_5_0: return "1.5"; - case PROTO_VERSION_1_5_2: return "1.5.2"; - case PROTO_VERSION_1_6_1: return "1.6.1"; - case PROTO_VERSION_1_6_2: return "1.6.2"; - case PROTO_VERSION_1_6_3: return "1.6.3"; - case PROTO_VERSION_1_6_4: return "1.6.4"; - case PROTO_VERSION_1_7_2: return "1.7.2"; - } - ASSERT(!"Unknown protocol version"); - return Printf("Unknown protocol (%d)", a_ProtocolVersion); -} - - - - - -void cProtocolRecognizer::DataReceived(const char * a_Data, int a_Size) -{ - if (m_Protocol == NULL) - { - if (!m_Buffer.Write(a_Data, a_Size)) - { - m_Client->Kick("Unsupported protocol version"); - return; - } - - if (!TryRecognizeProtocol()) - { - return; - } - - // The protocol has just been recognized, dump the whole m_Buffer contents into it for parsing: - AString Dump; - m_Buffer.ResetRead(); - m_Buffer.ReadAll(Dump); - m_Protocol->DataReceived(Dump.data(), Dump.size()); - } - else - { - m_Protocol->DataReceived(a_Data, a_Size); - } -} - - - - - -void cProtocolRecognizer::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendAttachEntity(a_Entity, a_Vehicle); -} - - - - - -void cProtocolRecognizer::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendBlockAction(a_BlockX, a_BlockY, a_BlockZ, a_Byte1, a_Byte2, a_BlockType); -} - - - - - -void cProtocolRecognizer::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendBlockBreakAnim(a_entityID, a_BlockX, a_BlockY, a_BlockZ, stage); -} - - - - - -void cProtocolRecognizer::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendBlockChange(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); -} - - - - - -void cProtocolRecognizer::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendBlockChanges(a_ChunkX, a_ChunkZ, a_Changes); -} - - - - - -void cProtocolRecognizer::SendChat(const AString & a_Message) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendChat(a_Message); -} - - - - - -void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendChunkData(a_ChunkX, a_ChunkZ, a_Serializer); -} - - - - - -void cProtocolRecognizer::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendCollectPickup(a_Pickup, a_Player); -} - - - - - -void cProtocolRecognizer::SendDestroyEntity(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendDestroyEntity(a_Entity); -} - - - - - -void cProtocolRecognizer::SendDisconnect(const AString & a_Reason) -{ - if (m_Protocol != NULL) - { - m_Protocol->SendDisconnect(a_Reason); - } - else - { - // This is used when the client sends a server-ping, respond with the default packet: - WriteByte ((char)0xff); // PACKET_DISCONNECT - WriteString(a_Reason); - } -} - - - - -void cProtocolRecognizer::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEditSign(a_BlockX, a_BlockY, a_BlockZ); -} - - - - - -void cProtocolRecognizer::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityEquipment(a_Entity, a_SlotNum, a_Item); -} - - - - - -void cProtocolRecognizer::SendEntityHeadLook(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityHeadLook(a_Entity); -} - - - - - -void cProtocolRecognizer::SendEntityLook(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityLook(a_Entity); -} - - - - - -void cProtocolRecognizer::SendEntityMetadata(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityMetadata(a_Entity); -} - - - - - -void cProtocolRecognizer::SendEntityProperties(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityProperties(a_Entity); -} - - - - - -void cProtocolRecognizer::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityRelMove(a_Entity, a_RelX, a_RelY, a_RelZ); -} - - - - - -void cProtocolRecognizer::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityRelMoveLook(a_Entity, a_RelX, a_RelY, a_RelZ); -} - - - - - -void cProtocolRecognizer::SendEntityStatus(const cEntity & a_Entity, char a_Status) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityStatus(a_Entity, a_Status); -} - - - - - -void cProtocolRecognizer::SendEntityVelocity(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendEntityVelocity(a_Entity); -} - - - - - -void cProtocolRecognizer::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion); -} - - - - - -void cProtocolRecognizer::SendGameMode(eGameMode a_GameMode) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendGameMode(a_GameMode); -} - - - - - -void cProtocolRecognizer::SendHealth(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendHealth(); -} - - - - - -void cProtocolRecognizer::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendWindowProperty(a_Window, a_Property, a_Value); -} - - - - - -void cProtocolRecognizer::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendInventorySlot(a_WindowID, a_SlotNum, a_Item); -} - - - - - -void cProtocolRecognizer::SendKeepAlive(int a_PingID) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendKeepAlive(a_PingID); -} - - - - - -void cProtocolRecognizer::SendLogin(const cPlayer & a_Player, const cWorld & a_World) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendLogin(a_Player, a_World); -} - - - - - -void cProtocolRecognizer::SendPickupSpawn(const cPickup & a_Pickup) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPickupSpawn(a_Pickup); -} - - - - - -void cProtocolRecognizer::SendPlayerAbilities(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerAbilities(); -} - - - - - -void cProtocolRecognizer::SendPlayerAnimation(const cPlayer & a_Player, char a_Animation) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerAnimation(a_Player, a_Animation); -} - - - - - -void cProtocolRecognizer::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerListItem(a_Player, a_IsOnline); -} - - - - - -void cProtocolRecognizer::SendPlayerMaxSpeed(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerMaxSpeed(); -} - - - - - -void cProtocolRecognizer::SendPlayerMoveLook(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerMoveLook(); -} - - - - - -void cProtocolRecognizer::SendPlayerPosition(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerPosition(); -} - - - - - -void cProtocolRecognizer::SendPlayerSpawn(const cPlayer & a_Player) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerSpawn(a_Player); -} - - - - - -void cProtocolRecognizer::SendRespawn(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendRespawn(); -} - - - - - -void cProtocolRecognizer::SendExperience(void) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendExperience(); -} - - - - - -void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch); -} - - - - - -void cProtocolRecognizer::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendSoundParticleEffect(a_EffectID, a_SrcX, a_SrcY, a_SrcZ, a_Data); -} - - - - - -void cProtocolRecognizer::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendSpawnFallingBlock(a_FallingBlock); -} - - - - - -void cProtocolRecognizer::SendSpawnMob(const cMonster & a_Mob) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendSpawnMob(a_Mob); -} - - - - - -void cProtocolRecognizer::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendSpawnObject(a_Entity, a_ObjectType, a_ObjectData, a_Yaw, a_Pitch); -} - - - - - -void cProtocolRecognizer::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendSpawnVehicle(a_Vehicle, a_VehicleType, a_VehicleSubType); -} - - - - - -void cProtocolRecognizer::SendTabCompletionResults(const AStringVector & a_Results) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendTabCompletionResults(a_Results); -} - - - - - -void cProtocolRecognizer::SendTeleportEntity(const cEntity & a_Entity) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendTeleportEntity(a_Entity); -} - - - - - -void cProtocolRecognizer::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendThunderbolt(a_BlockX, a_BlockY, a_BlockZ); -} - - - - - -void cProtocolRecognizer::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay); -} - - - - - -void cProtocolRecognizer::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendUnloadChunk(a_ChunkX, a_ChunkZ); -} - - - - - -void cProtocolRecognizer::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendUpdateSign(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4); -} - - - - - -void cProtocolRecognizer::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); -} - - - - - -void cProtocolRecognizer::SendWeather(eWeather a_Weather) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendWeather(a_Weather); -} - - - - - -void cProtocolRecognizer::SendWholeInventory(const cWindow & a_Window) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendWholeInventory(a_Window); -} - - - - - -void cProtocolRecognizer::SendWindowClose(const cWindow & a_Window) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendWindowClose(a_Window); -} - - - - - -void cProtocolRecognizer::SendWindowOpen(const cWindow & a_Window) -{ - ASSERT(m_Protocol != NULL); - m_Protocol->SendWindowOpen(a_Window); -} - - - - - -AString cProtocolRecognizer::GetAuthServerID(void) -{ - ASSERT(m_Protocol != NULL); - return m_Protocol->GetAuthServerID(); -} - - - - - -void cProtocolRecognizer::SendData(const char * a_Data, int a_Size) -{ - // This is used only when handling the server ping - m_Client->SendData(a_Data, a_Size); -} - - - - - -bool cProtocolRecognizer::TryRecognizeProtocol(void) -{ - // NOTE: If a new protocol is added or an old one is removed, adjust MCS_CLIENT_VERSIONS and - // MCS_PROTOCOL_VERSIONS macros in the header file, as well as PROTO_VERSION_LATEST macro - - // The first packet should be a Handshake, 0x02: - unsigned char PacketType; - if (!m_Buffer.ReadByte(PacketType)) - { - return false; - } - switch (PacketType) - { - case 0x02: return TryRecognizeLengthlessProtocol(); // Handshake, continue recognizing - case 0xfe: - { - // This may be either a packet length or the length-less Ping packet - Byte NextByte; - if (!m_Buffer.ReadByte(NextByte)) - { - // Not enough data for either protocol - // This could actually happen with the 1.2 / 1.3 client, but their support is fading out anyway - return false; - } - if (NextByte != 0x01) - { - // This is definitely NOT a length-less Ping packet, handle as lengthed protocol: - break; - } - if (!m_Buffer.ReadByte(NextByte)) - { - // There is no more data. Although this *could* mean TCP fragmentation, it is highly unlikely - // and rather this is a 1.4 client sending a regular Ping packet (without the following Plugin message) - SendLengthlessServerPing(); - return false; - } - if (NextByte == 0xfa) - { - // Definitely a length-less Ping followed by a Plugin message - SendLengthlessServerPing(); - return false; - } - // Definitely a lengthed Initial handshake, handle below: - break; - } - } // switch (PacketType) - - // This must be a lengthed protocol, try if it has the entire initial handshake packet: - m_Buffer.ResetRead(); - UInt32 PacketLen; - UInt32 ReadSoFar = m_Buffer.GetReadableSpace(); - if (!m_Buffer.ReadVarInt(PacketLen)) - { - // Not enough bytes for the packet length, keep waiting - return false; - } - ReadSoFar -= m_Buffer.GetReadableSpace(); - if (!m_Buffer.CanReadBytes(PacketLen)) - { - // Not enough bytes for the packet, keep waiting - return false; - } - return TryRecognizeLengthedProtocol(PacketLen - ReadSoFar); -} - - - - - -bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void) -{ - // The comm started with 0x02, which is a Handshake packet in the length-less protocol family - // 1.3.2 starts with 0x02 0x39 <name-length-short> - // 1.2.5 starts with 0x02 <name-length-short> and name is expected to less than 0x3900 long :) - char ch; - if (!m_Buffer.ReadChar(ch)) - { - return false; - } - switch (ch) - { - case PROTO_VERSION_1_3_2: - { - m_Protocol = new cProtocol132(m_Client); - return true; - } - case PROTO_VERSION_1_4_2: - case PROTO_VERSION_1_4_4: - { - m_Protocol = new cProtocol142(m_Client); - return true; - } - case PROTO_VERSION_1_4_6: - { - m_Protocol = new cProtocol146(m_Client); - return true; - } - case PROTO_VERSION_1_5_0: - case PROTO_VERSION_1_5_2: - { - m_Protocol = new cProtocol150(m_Client); - return true; - } - case PROTO_VERSION_1_6_1: - { - m_Protocol = new cProtocol161(m_Client); - return true; - } - case PROTO_VERSION_1_6_2: - case PROTO_VERSION_1_6_3: - case PROTO_VERSION_1_6_4: - { - m_Protocol = new cProtocol162(m_Client); - return true; - } - } - m_Protocol = new cProtocol125(m_Client); - return true; -} - - - - - -bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining) -{ - UInt32 PacketType; - UInt32 NumBytesRead = m_Buffer.GetReadableSpace(); - if (!m_Buffer.ReadVarInt(PacketType)) - { - return false; - } - if (PacketType != 0x00) - { - // Not an initial handshake packet, we don't know how to talk to them - LOGINFO("Client \"%s\" uses an unsupported protocol (lengthed, initial packet %u)", - m_Client->GetIPString().c_str(), PacketType - ); - m_Client->Kick("Unsupported protocol version"); - return false; - } - UInt32 ProtocolVersion; - if (!m_Buffer.ReadVarInt(ProtocolVersion)) - { - return false; - } - NumBytesRead -= m_Buffer.GetReadableSpace(); - switch (ProtocolVersion) - { - case PROTO_VERSION_1_7_2: - { - AString ServerAddress; - short ServerPort; - UInt32 NextState; - m_Buffer.ReadVarUTF8String(ServerAddress); - m_Buffer.ReadBEShort(ServerPort); - m_Buffer.ReadVarInt(NextState); - m_Buffer.CommitRead(); - m_Protocol = new cProtocol172(m_Client, ServerAddress, ServerPort, NextState); - return true; - } - } - LOGINFO("Client \"%s\" uses an unsupported protocol (lengthed, version %u)", - m_Client->GetIPString().c_str(), ProtocolVersion - ); - m_Client->Kick("Unsupported protocol version"); - return false; -} - - - - - -void cProtocolRecognizer::SendLengthlessServerPing(void) -{ - AString Reply; - switch (cRoot::Get()->GetPrimaryServerVersion()) - { - case PROTO_VERSION_1_2_5: - case PROTO_VERSION_1_3_2: - { - // http://wiki.vg/wiki/index.php?title=Protocol&oldid=3099#Server_List_Ping_.280xFE.29 - Printf(Reply, "%s%s%i%s%i", - cRoot::Get()->GetServer()->GetDescription().c_str(), - cChatColor::Delimiter.c_str(), - cRoot::Get()->GetServer()->GetNumPlayers(), - cChatColor::Delimiter.c_str(), - cRoot::Get()->GetServer()->GetMaxPlayers() - ); - break; - } - - case PROTO_VERSION_1_4_2: - case PROTO_VERSION_1_4_4: - case PROTO_VERSION_1_4_6: - case PROTO_VERSION_1_5_0: - case PROTO_VERSION_1_5_2: - case PROTO_VERSION_1_6_1: - case PROTO_VERSION_1_6_2: - case PROTO_VERSION_1_6_3: - case PROTO_VERSION_1_6_4: - { - // The server list ping now has 1 more byte of "magic". Mojang just loves to complicate stuff. - // http://wiki.vg/wiki/index.php?title=Protocol&oldid=3101#Server_List_Ping_.280xFE.29 - // _X 2012_10_31: I know that this needn't eat the byte, since it still may be in transit. - // Who cares? We're disconnecting anyway. - m_Buffer.ResetRead(); - if (m_Buffer.CanReadBytes(2)) - { - byte val; - m_Buffer.ReadByte(val); // Packet type - Serverlist ping - m_Buffer.ReadByte(val); // 0x01 magic value - ASSERT(val == 0x01); - } - - // http://wiki.vg/wiki/index.php?title=Server_List_Ping&oldid=3100 - AString NumPlayers; - Printf(NumPlayers, "%d", cRoot::Get()->GetServer()->GetNumPlayers()); - AString MaxPlayers; - Printf(MaxPlayers, "%d", cRoot::Get()->GetServer()->GetMaxPlayers()); - - AString ProtocolVersionNum; - Printf(ProtocolVersionNum, "%d", cRoot::Get()->GetPrimaryServerVersion()); - AString ProtocolVersionTxt(GetVersionTextFromInt(cRoot::Get()->GetPrimaryServerVersion())); - - // Cannot use Printf() because of in-string NUL bytes. - Reply = cChatColor::Delimiter; - Reply.append("1"); - Reply.push_back(0); - Reply.append(ProtocolVersionNum); - Reply.push_back(0); - Reply.append(ProtocolVersionTxt); - Reply.push_back(0); - Reply.append(cRoot::Get()->GetServer()->GetDescription()); - Reply.push_back(0); - Reply.append(NumPlayers); - Reply.push_back(0); - Reply.append(MaxPlayers); - break; - } - } // switch (m_PrimaryServerVersion) - m_Client->Kick(Reply); -} - - - - diff --git a/source/Protocol/ProtocolRecognizer.h b/source/Protocol/ProtocolRecognizer.h deleted file mode 100644 index 03f48fb35..000000000 --- a/source/Protocol/ProtocolRecognizer.h +++ /dev/null @@ -1,153 +0,0 @@ - -// ProtocolRecognizer.h - -// Interfaces to the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple -// protocol versions and redirects everything to them - - - - - -#pragma once - -#include "Protocol.h" -#include "../ByteBuffer.h" - - - - - -// Adjust these if a new protocol is added or an old one is removed: -#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2" -#define MCS_PROTOCOL_VERSIONS "29, 39, 47, 49, 51, 60, 61, 73, 74, 77, 78, 4" - - - - - -class cProtocolRecognizer : - public cProtocol -{ - typedef cProtocol super; - -public: - enum - { - PROTO_VERSION_1_2_5 = 29, - PROTO_VERSION_1_3_2 = 39, - PROTO_VERSION_1_4_2 = 47, - PROTO_VERSION_1_4_4 = 49, - PROTO_VERSION_1_4_6 = 51, - PROTO_VERSION_1_5_0 = 60, - PROTO_VERSION_1_5_2 = 61, - PROTO_VERSION_1_6_1 = 73, - PROTO_VERSION_1_6_2 = 74, - PROTO_VERSION_1_6_3 = 77, - PROTO_VERSION_1_6_4 = 78, - - PROTO_VERSION_NEXT, - PROTO_VERSION_LATEST = PROTO_VERSION_NEXT - 1, ///< Automatically assigned to the last protocol version, this serves as the default for PrimaryServerVersion - - // These will be kept "under" the next / latest, because the next and latest are only needed for previous protocols - PROTO_VERSION_1_7_2 = 4, - } ; - - cProtocolRecognizer(cClientHandle * a_Client); - virtual ~cProtocolRecognizer(); - - /// Translates protocol version number into protocol version text: 49 -> "1.4.4" - static AString GetVersionTextFromInt(int a_ProtocolVersion); - - /// Called when client sends some data: - virtual void DataReceived(const char * a_Data, int a_Size) override; - - /// Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override; - virtual void SendPlayerAnimation (const cPlayer & a_Player, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendRespawn (void) override; - virtual void SendExperience (void) override; - virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; - - virtual AString GetAuthServerID(void) override; - - virtual void SendData(const char * a_Data, int a_Size) override; - -protected: - cProtocol * m_Protocol; //< The recognized protocol - cByteBuffer m_Buffer; //< Buffer for the incoming data until we recognize the protocol - - /// Tries to recognize protocol based on m_Buffer contents; returns true if recognized - bool TryRecognizeProtocol(void); - - /** Tries to recognize a protocol in the length-less family, based on m_Buffer; returns true if recognized. - Handles protocols before release 1.7, that didn't include packet lengths, and started with a 0x02 handshake packet - Note that length-less server ping is handled directly in TryRecognizeProtocol(), this function is called only - when the 0x02 Handshake packet has been received - */ - bool TryRecognizeLengthlessProtocol(void); - - /** Tries to recognize a protocol in the leghted family (1.7+), based on m_Buffer; returns true if recognized. - The packet length and type have already been read, type is 0 - The number of bytes remaining in the packet is passed as a_PacketLengthRemaining - **/ - bool TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining); - - /** Called when the recognizer gets a length-less protocol's server ping packet - Responds with server stats and destroys the client. - */ - void SendLengthlessServerPing(void); -} ; - - - - - diff --git a/source/Protocol/ChunkDataSerializer.h b/src/Protocol/ChunkDataSerializer.h index a42856356..a42856356 100644 --- a/source/Protocol/ChunkDataSerializer.h +++ b/src/Protocol/ChunkDataSerializer.h diff --git a/source/Protocol/Protocol14x.h b/src/Protocol/Protocol14x.h index ca497bbc1..ca497bbc1 100644 --- a/source/Protocol/Protocol14x.h +++ b/src/Protocol/Protocol14x.h diff --git a/source/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp index c337d26e7..c337d26e7 100644 --- a/source/Protocol/Protocol15x.cpp +++ b/src/Protocol/Protocol15x.cpp diff --git a/source/Protocol/Protocol15x.h b/src/Protocol/Protocol15x.h index e554fe130..e554fe130 100644 --- a/source/Protocol/Protocol15x.h +++ b/src/Protocol/Protocol15x.h diff --git a/source/Protocol/Protocol16x.cpp b/src/Protocol/Protocol16x.cpp index cfa27b3c4..cfa27b3c4 100644 --- a/source/Protocol/Protocol16x.cpp +++ b/src/Protocol/Protocol16x.cpp diff --git a/source/Protocol/Protocol16x.h b/src/Protocol/Protocol16x.h index 325e41c5a..325e41c5a 100644 --- a/source/Protocol/Protocol16x.h +++ b/src/Protocol/Protocol16x.h |