1
0

Merge pull request #1466 from mc-server/endofsupport

Removed protocols 1.2 to 1.6
This commit is contained in:
Mattes D 2014-09-28 22:04:30 +02:00
commit 8d55cd409e
27 changed files with 24 additions and 4757 deletions

View File

@ -1819,8 +1819,7 @@ bool cConnection::HandleServerKick(void)
Reason.append(Split[4]);
Reason.push_back(0);
Reason.append(Split[5]);
AString ReasonBE16;
UTF8ToRawBEUTF16(Reason.data(), Reason.size(), ReasonBE16);
AString ReasonBE16 = UTF8ToRawBEUTF16(Reason.data(), Reason.size());
AString PacketStart("\xff");
PacketStart.push_back((ReasonBE16.size() / 2) / 256);
PacketStart.push_back((ReasonBE16.size() / 2) % 256);

View File

@ -627,23 +627,6 @@ bool cByteBuffer::WriteBool(bool a_Value)
bool cByteBuffer::WriteBEUTF16String16(const AString & a_Value)
{
CHECK_THREAD;
CheckValid();
PUTBYTES(2);
AString UTF16BE;
UTF8ToRawBEUTF16(a_Value.data(), a_Value.size(), UTF16BE);
WriteBEShort((short)(UTF16BE.size() / 2));
PUTBYTES(UTF16BE.size());
WriteBuf(UTF16BE.data(), UTF16BE.size());
return true;
}
bool cByteBuffer::WriteVarInt(UInt32 a_Value)
{
CHECK_THREAD;

View File

@ -88,7 +88,6 @@ public:
bool WriteBEFloat (float a_Value);
bool WriteBEDouble (double a_Value);
bool WriteBool (bool a_Value);
bool WriteBEUTF16String16(const AString & a_Value); // string length as BE short, then string as UTF-16BE
bool WriteVarInt (UInt32 a_Value);
bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8
bool WriteLEInt (int a_Value);

View File

@ -1749,20 +1749,6 @@ void cClientHandle::HandleRespawn(void)
void cClientHandle::HandleDisconnect(const AString & a_Reason)
{
LOGD("Received d/c packet from %s with reason \"%s\"", m_Username.c_str(), a_Reason.c_str());
cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, a_Reason);
m_HasSentDC = true;
Destroy();
}
void cClientHandle::HandleKeepAlive(int a_KeepAliveID)
{
if (a_KeepAliveID == m_PingID)

View File

@ -239,7 +239,6 @@ public:
void HandleAnimation (char a_Animation);
void HandleChat (const AString & a_Message);
void HandleCreativeInventory(short a_SlotNum, const cItem & a_HeldItem);
void HandleDisconnect (const AString & a_Reason);
void HandleEntityCrouch (int a_EntityID, bool a_IsCrouching);
void HandleEntityLeaveBed (int a_EntityID);
void HandleEntitySprinting (int a_EntityID, bool a_IsSprinting);

View File

@ -8,11 +8,6 @@ SET (SRCS
Authenticator.cpp
ChunkDataSerializer.cpp
MojangAPI.cpp
Protocol125.cpp
Protocol132.cpp
Protocol14x.cpp
Protocol15x.cpp
Protocol16x.cpp
Protocol17x.cpp
Protocol18x.cpp
ProtocolRecognizer.cpp)
@ -22,11 +17,6 @@ SET (HDRS
ChunkDataSerializer.h
MojangAPI.h
Protocol.h
Protocol125.h
Protocol132.h
Protocol14x.h
Protocol15x.h
Protocol16x.h
Protocol17x.h
Protocol18x.h
ProtocolRecognizer.h)

View File

@ -138,108 +138,9 @@ public:
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, size_t 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 WriteChar(char a_Value)
{
SendData(&a_Value, 1);
}
void WriteShort(short a_Value)
{
u_short Value = htons((u_short)a_Value);
SendData((const char *)&Value, 2);
}
/*
void WriteShort(unsigned short a_Value)
{
a_Value = htons(a_Value);
SendData((const char *)&a_Value, 2);
}
*/
void WriteInt(int a_Value)
{
u_long Value = htonl((u_long)a_Value);
SendData((const char *)&Value, 4);
}
void WriteUInt(unsigned int a_Value)
{
a_Value = htonl(a_Value);
SendData((const char *)&a_Value, 4);
}
void WriteInt64 (Int64 a_Value)
{
UInt64 Value = HostToNetwork8(&a_Value);
SendData((const char *)&Value, 8);
}
void WriteFloat (float a_Value)
{
UInt32 val = HostToNetwork4(&a_Value);
SendData((const char *)&val, 4);
}
void WriteDouble(double a_Value)
{
UInt64 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((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];
size_t 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((UInt32)a_String.size());
SendData(a_String.data(), a_String.size());
}
} ;

File diff suppressed because it is too large Load Diff

View File

@ -1,185 +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"
#include "../Entities/Painting.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, size_t 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 SendChat (const cCompositeChat & a_Message) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, 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 SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
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 SendLoginSuccess (void) override;
virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override;
virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override;
virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override;
virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override;
virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override;
virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) 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 SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override {} // This protocol doesn't support such message
virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override {} // This protocol doesn't support such message
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, 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 SendStatistics (const cStatManager & a_Manager) 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, bool a_DoDaylightCycle) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) 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, int a_Property, int a_Value) override;
virtual AString GetAuthServerID(void) override;
protected:
/// Results of packet-parsing:
enum eParseResult
{
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
/** The dimension that was last sent to a player in a Respawn or Login packet.
Used to avoid Respawning into the same dimension, which confuses the client. */
eDimension m_LastSentDimension;
virtual void SendData(const char * a_Data, size_t 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 ParseEnchantItem (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);
} ;

View File

@ -1,880 +0,0 @@
// Protocol132.cpp
// Implements the cProtocol132 class representing the release 1.3.2 protocol (#39)
#include "Globals.h"
#include "ChunkDataSerializer.h"
#include "Protocol132.h"
#include "../Root.h"
#include "../Server.h"
#include "../World.h"
#include "../ClientHandle.h"
#include "../Item.h"
#include "../Entities/Player.h"
#include "../Mobs/Monster.h"
#include "../UI/Window.h"
#include "../Entities/Pickup.h"
#include "../WorldStorage/FastNBT.h"
#include "../WorldStorage/EnchantmentSerializer.h"
#include "../StringCompression.h"
#include "PolarSSL++/Sha1Checksum.h"
#define HANDLE_PACKET_READ(Proc, Type, Var) \
Type Var; \
{ \
if (!m_ReceivedData.Proc(Var)) \
{ \
m_ReceivedData.CheckValid(); \
return PARSE_INCOMPLETE; \
} \
m_ReceivedData.CheckValid(); \
}
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,
} ;
////////////////////////////////////////////////////////////////////////////////
// cProtocol132:
cProtocol132::cProtocol132(cClientHandle * a_Client) :
super(a_Client),
m_IsEncrypted(false)
{
}
cProtocol132::~cProtocol132()
{
if (!m_DataToSend.empty())
{
LOGD("There are " SIZE_T_FMT " unsent bytes while deleting cProtocol132", m_DataToSend.size());
}
}
void cProtocol132::DataReceived(const char * a_Data, size_t a_Size)
{
if (m_IsEncrypted)
{
Byte Decrypted[512];
while (a_Size > 0)
{
size_t 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);
WriteChar (a_Byte1);
WriteChar (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);
WriteChar (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, a_ChunkX, a_ChunkZ);
WriteByte(PACKET_CHUNK_DATA);
WriteInt (a_ChunkX);
WriteInt (a_ChunkZ);
SendData(Serialized.data(), Serialized.size());
Flush();
}
void cProtocol132::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_COLLECT_PICKUP);
WriteInt (a_Entity.GetUniqueID());
WriteInt (a_Player.GetUniqueID());
Flush();
}
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 ((Byte)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();
m_LastSentDimension = a_World.GetDimension();
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());
if (a_Player.HasCustomName())
{
WriteString(a_Player.GetCustomName());
}
else
{
WriteString(a_Player.GetName());
}
WriteInt ((int)(a_Player.GetPosX() * 32));
WriteInt ((int)(a_Player.GetPosY() * 32));
WriteInt ((int)(a_Player.GetPosZ() * 32));
WriteChar ((char)((a_Player.GetYaw() / 360.f) * 256));
WriteChar ((char)((a_Player.GetPitch() / 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, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_SOUND_EFFECT);
WriteString (a_SoundName);
WriteInt ((int)(a_X * 8.0));
WriteInt ((int)(a_Y * 8.0));
WriteInt ((int)(a_Z * 8.0));
WriteFloat (a_Volume);
WriteChar ((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((Byte)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 ((Byte)a_Mob.GetMobType());
WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32));
WriteByte ((Byte)((a_Mob.GetYaw() / 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:
cPlayer * Player = m_Client->GetPlayer();
const cInventory & Inventory = Player->GetInventory();
int BaseOffset = a_Window.GetNumSlots() - (cInventory::invNumSlots - cInventory::invInventoryOffset); // Number of non-inventory slots
char WindowID = a_Window.GetWindowID();
for (short i = 0; i < cInventory::invInventoryCount; i++)
{
SendInventorySlot(WindowID, BaseOffset + i, Inventory.GetInventorySlot(i));
} // for i - Inventory[]
BaseOffset += cInventory::invInventoryCount;
for (short 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, Player->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, static_cast<eBlockFace>(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
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)
{
// Read the encryption key:
HANDLE_PACKET_READ(ReadBEShort, short, EncKeyLength);
if (EncKeyLength > MAX_ENC_LEN)
{
LOGD("Too long encryption key");
m_Client->Kick("Hacked client");
return PARSE_OK;
}
AString EncKey;
if (!m_ReceivedData.ReadString(EncKey, (size_t)EncKeyLength))
{
return PARSE_INCOMPLETE;
}
// Read the encryption nonce:
HANDLE_PACKET_READ(ReadBEShort, short, EncNonceLength);
AString EncNonce;
if (!m_ReceivedData.ReadString(EncNonce, (size_t)EncNonceLength))
{
return PARSE_INCOMPLETE;
}
if (EncNonceLength > MAX_ENC_LEN)
{
LOGD("Too long encryption nonce");
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);
m_Client->SetLocale(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, size_t 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 * Data = m_DataToSend.data();
size_t Size = m_DataToSend.size();
if (m_IsEncrypted)
{
Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
while (Size > 0)
{
size_t NumBytes = (Size > sizeof(Encrypted)) ? sizeof(Encrypted) : Size;
m_Encryptor.ProcessData(Encrypted, (Byte *)Data, NumBytes);
super::SendData((const char *)Encrypted, NumBytes);
Size -= NumBytes;
Data += NumBytes;
}
}
else
{
super::SendData(Data, 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);
WriteChar (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";
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
Writer.Finish();
AString Compressed;
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
WriteShort((short)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((size_t)MetadataLength);
if (!m_ReceivedData.ReadBuf((void *)Metadata.data(), (size_t)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")
)
)
{
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, 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);
cServer * Server = cRoot::Get()->GetServer();
WriteByte(0xfd);
WriteString(Server->GetServerID());
const AString & PublicKeyDER = Server->GetPublicKeyDER();
WriteShort((short)(PublicKeyDER.size()));
SendData(PublicKeyDER.data(), PublicKeyDER.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
cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
int res = rsaDecryptor.Decrypt((const Byte *)a_EncNonce.data(), a_EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce));
if (res != 4)
{
LOGD("Bad nonce length");
m_Client->Kick("Hacked client");
return;
}
if (ntohl(DecryptedNonce[0]) != (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((const Byte *)a_EncKey.data(), a_EncKey.size(), DecryptedKey, sizeof(DecryptedKey));
if (res != 16)
{
LOGD("Bad key length");
m_Client->Kick("Hacked client");
return;
}
{
// Send encryption key response:
cCSLock Lock(m_CSPacket);
WriteByte(0xfc);
WriteShort(0);
WriteShort(0);
Flush();
}
#ifdef _DEBUG
AString DecryptedKeyHex;
CreateHexDump(DecryptedKeyHex, DecryptedKey, res, 16);
LOGD("Received encryption key, %d bytes:\n%s", res, DecryptedKeyHex.c_str());
#endif
StartEncryption(DecryptedKey);
return;
}
void cProtocol132::StartEncryption(const Byte * a_Key)
{
m_Encryptor.Init(a_Key, a_Key);
m_Decryptor.Init(a_Key, a_Key);
m_IsEncrypted = true;
// Prepare the m_AuthServerID:
cSha1Checksum Checksum;
cServer * Server = cRoot::Get()->GetServer();
AString ServerID = Server->GetServerID();
Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length());
Checksum.Update(a_Key, 16);
Checksum.Update((const Byte *)Server->GetPublicKeyDER().data(), Server->GetPublicKeyDER().size());
Byte Digest[20];
Checksum.Finalize(Digest);
cSha1Checksum::DigestToJava(Digest, m_AuthServerID);
}

View File

@ -1,115 +0,0 @@
// Protocol132.h
// Interfaces to the cProtocol132 class representing the release 1.3.2 protocol (#39)
#pragma once
#include "Protocol125.h"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#pragma warning(disable:4189)
#pragma warning(disable:4231)
#pragma warning(disable:4244)
#pragma warning(disable:4702)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "PolarSSL++/AesCfb128Decryptor.h"
#include "PolarSSL++/AesCfb128Encryptor.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, size_t 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 SendCollectEntity (const cEntity & a_Entity, 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, double a_X, double a_Y, double a_Z, 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 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;
cAesCfb128Decryptor m_Decryptor;
cAesCfb128Encryptor m_Encryptor;
AString m_DataToSend;
/// The ServerID used for session authentication; set in StartEncryption(), used in GetAuthServerID()
AString m_AuthServerID;
virtual void SendData(const char * a_Data, size_t 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);
} ;

View File

@ -1,265 +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 "../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"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#pragma warning(disable:4244)
#pragma warning(disable:4231)
#pragma warning(disable:4189)
#pragma warning(disable:4702)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#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
m_Client->SetLocale(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));
WriteChar((char)(a_Pickup.GetSpeedX() * 8));
WriteChar((char)(a_Pickup.GetSpeedY() * 8));
WriteChar((char)(a_Pickup.GetSpeedZ() * 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((Byte)a_SrcY);
WriteInt (a_SrcZ);
WriteInt (a_Data);
WriteBool(0);
Flush();
}
void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
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.GetSpeedX() * 32));
WriteShort((short)(a_Pickup.GetSpeedY() * 32));
WriteShort((short)(a_Pickup.GetSpeedZ() * 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());
WriteChar(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());
WriteChar (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.GetYaw() / 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();
}

View File

@ -1,63 +0,0 @@
// Protocol14x.h
/*
Interfaces to 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)
*/
#pragma once
#include "Protocol132.h"
class cProtocol142 :
public cProtocol132
{
typedef cProtocol132 super;
public:
cProtocol142(cClientHandle * a_Client);
// Sending commands (alphabetically sorted):
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
// Specific packet parsers:
virtual int ParseLocaleViewDistance(void) override;
} ;
class cProtocol146 :
public cProtocol142
{
typedef cProtocol142 super;
public:
cProtocol146(cClientHandle * a_Client);
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) 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;
} ;

View File

@ -1,209 +0,0 @@
// Protocol15x.cpp
/*
Implements the 1.5.x protocol classes:
- cProtocol150
- release 1.5 protocol (#60)
- release 1.5.2 protocol (#61, no relevant changes found)
*/
#include "Globals.h"
#include "Protocol15x.h"
#include "../ClientHandle.h"
#include "../Item.h"
#include "../UI/Window.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_WINDOW_OPEN = 0x64,
PACKET_PARTICLE_EFFECT = 0x3F,
PACKET_SCOREBOARD_OBJECTIVE = 0xCE,
PACKET_SCORE_UPDATE = 0xCF,
PACKET_DISPLAY_OBJECTIVE = 0xD0
} ;
////////////////////////////////////////////////////////////////////////////////
// cProtocol150:
cProtocol150::cProtocol150(cClientHandle * a_Client) :
super(a_Client)
{
}
void cProtocol150::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());
WriteByte (1); // Use title
Flush();
}
void cProtocol150::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_PARTICLE_EFFECT);
WriteString(a_ParticleName);
WriteFloat(a_SrcX);
WriteFloat(a_SrcY);
WriteFloat(a_SrcZ);
WriteFloat(a_OffsetX);
WriteFloat(a_OffsetY);
WriteFloat(a_OffsetZ);
WriteFloat(a_ParticleData);
WriteInt(a_ParticleAmount);
Flush();
}
void cProtocol150::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_SCOREBOARD_OBJECTIVE);
WriteString(a_Name);
WriteString(a_DisplayName);
WriteByte(a_Mode);
Flush();
}
void cProtocol150::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_SCORE_UPDATE);
WriteString(a_Player);
WriteByte(a_Mode);
if (a_Mode != 1)
{
WriteString(a_Objective);
WriteInt((int) a_Score);
}
Flush();
}
void cProtocol150::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_DISPLAY_OBJECTIVE);
WriteByte((int) a_Display);
WriteString(a_Objective);
Flush();
}
int cProtocol150::ParseWindowClick(void)
{
HANDLE_PACKET_READ(ReadChar, char, WindowID);
HANDLE_PACKET_READ(ReadBEShort, short, SlotNum);
HANDLE_PACKET_READ(ReadByte, Byte, Button);
HANDLE_PACKET_READ(ReadBEShort, short, TransactionID);
HANDLE_PACKET_READ(ReadByte, Byte, Mode);
cItem HeldItem;
int res = ParseItem(HeldItem);
if (res < 0)
{
return res;
}
// Convert Button, Mode, SlotNum and HeldItem into eClickAction:
eClickAction Action = caUnknown;
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;
}
if (Action == caUnknown)
{
LOGWARNING("Received an unknown click action combination: Mode = %d, Button = %d, Slot = %d, HeldItem = %s. Ignoring packet.",
Mode, Button, SlotNum, ItemToFullString(HeldItem).c_str()
);
ASSERT(!"Unknown click action");
return PARSE_OK;
}
m_Client->HandleWindowClick(WindowID, SlotNum, Action, HeldItem);
return PARSE_OK;
}

View File

@ -1,42 +0,0 @@
// Protocol15x.h
/*
Declares the 1.5.x protocol classes:
- cProtocol150
- release 1.5 and 1.5.1 protocol (#60)
- release 1.5.2 protocol (#61; no relevant changes found)
*/
#pragma once
#include "Protocol14x.h"
class cProtocol150 :
public cProtocol146
{
typedef cProtocol146 super;
public:
cProtocol150(cClientHandle * a_Client);
virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override;
virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override;
virtual int ParseWindowClick(void);
} ;

View File

@ -1,312 +0,0 @@
// Protocol16x.cpp
/*
Implements the 1.6.x protocol classes:
- cProtocol161
- release 1.6.1 protocol (#73)
- cProtocol162
- release 1.6.2 protocol (#74)
- release 1.6.3 protocol (#77) - no relevant changes
- release 1.6.4 protocol (#78) - no relevant changes
(others may be added later in the future for the 1.6 release series)
*/
#include "Globals.h"
#include "Protocol16x.h"
#include "../ClientHandle.h"
#include "../Entities/Entity.h"
#include "../Entities/Player.h"
#include "../UI/Window.h"
#include "../CompositeChat.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_CHAT = 0x03,
PACKET_UPDATE_HEALTH = 0x08,
PACKET_STEER_VEHICLE = 0x1b,
PACKET_ATTACH_ENTITY = 0x27,
PACKET_ENTITY_PROPERTIES = 0x2c,
PACKET_WINDOW_OPEN = 0x64,
PACKET_TILE_EDITOR_OPEN = 0x85,
PACKET_PLAYER_ABILITIES = 0xca,
} ;
////////////////////////////////////////////////////////////////////////////////
// cProtocol161:
cProtocol161::cProtocol161(cClientHandle * a_Client) :
super(a_Client)
{
}
void cProtocol161::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());
WriteBool(false); // TODO: "Should use leash?" -> no
Flush();
}
void cProtocol161::SendChat(const AString & a_Message)
{
super::SendChat(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
}
void cProtocol161::SendChat(const cCompositeChat & a_Message)
{
// This protocol version doesn't support composite messages to the full
// Just extract each part's text and use it:
super::SendChat(Printf("{\"text\":\"%s\"}", EscapeString(a_Message.ExtractText()).c_str()));
}
void cProtocol161::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_TILE_EDITOR_OPEN);
WriteByte(0);
WriteInt(a_BlockX);
WriteInt(a_BlockY);
WriteInt(a_BlockZ);
Flush();
}
void cProtocol161::SendGameMode(eGameMode a_GameMode)
{
super::SendGameMode(a_GameMode);
SendPlayerMaxSpeed();
}
void cProtocol161::SendHealth(void)
{
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_UPDATE_HEALTH);
cPlayer * Player = m_Client->GetPlayer();
WriteFloat((float)Player->GetHealth());
WriteShort((short)Player->GetFoodLevel());
WriteFloat((float)Player->GetFoodSaturationLevel());
Flush();
}
void cProtocol161::SendPlayerMaxSpeed(void)
{
cCSLock Lock(m_CSPacket);
cPlayer * Player = m_Client->GetPlayer();
WriteByte(PACKET_ENTITY_PROPERTIES);
WriteInt(Player->GetUniqueID());
WriteInt(1);
WriteString("generic.movementSpeed");
WriteDouble(0.1 * Player->GetMaxSpeed());
Flush();
}
void cProtocol161::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
super::SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks);
SendPlayerMaxSpeed();
}
void cProtocol161::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);
WriteChar (a_Window.GetWindowID());
WriteByte ((Byte)a_Window.GetWindowType());
WriteString(a_Window.GetWindowTitle());
WriteByte ((Byte)a_Window.GetNumNonInventorySlots());
WriteByte (1); // Use title
if (a_Window.GetWindowType() == cWindow::wtAnimalChest)
{
WriteInt(0); // TODO: The animal's EntityID
}
Flush();
}
int cProtocol161::ParseEntityAction(void)
{
HANDLE_PACKET_READ(ReadBEInt, int, EntityID);
HANDLE_PACKET_READ(ReadChar, char, ActionID);
HANDLE_PACKET_READ(ReadBEInt, int, UnknownHorseVal);
switch (ActionID)
{
case 1: m_Client->HandleEntityCrouch(EntityID, true); break; // Crouch
case 2: m_Client->HandleEntityCrouch(EntityID, false); break; // Uncrouch
case 3: m_Client->HandleEntityLeaveBed(EntityID); break; // Leave Bed
case 4: m_Client->HandleEntitySprinting(EntityID, true); break; // Start sprinting
case 5: m_Client->HandleEntitySprinting(EntityID, false); break; // Stop sprinting
}
return PARSE_OK;
}
int cProtocol161::ParseLogin(void)
{
// The login packet is sent by Forge clients only
// Only parse the packet, do no extra processing
// Note that the types and the names have been only guessed and are not verified at all!
HANDLE_PACKET_READ(ReadBEInt, int, Int1);
HANDLE_PACKET_READ(ReadBEUTF16String16, AString, String1);
HANDLE_PACKET_READ(ReadChar, char, Char1);
HANDLE_PACKET_READ(ReadChar, char, Char2);
HANDLE_PACKET_READ(ReadChar, char, Char3);
HANDLE_PACKET_READ(ReadByte, Byte, Byte1);
HANDLE_PACKET_READ(ReadByte, Byte, Byte2);
return PARSE_OK;
}
int cProtocol161::ParsePlayerAbilities(void)
{
HANDLE_PACKET_READ(ReadByte, Byte, Flags);
HANDLE_PACKET_READ(ReadBEFloat, float, FlyingSpeed);
HANDLE_PACKET_READ(ReadBEFloat, float, WalkingSpeed);
// TODO: m_Client->HandlePlayerAbilities(...);
return PARSE_OK;
}
int cProtocol161::ParseSteerVehicle(void)
{
HANDLE_PACKET_READ(ReadBEFloat, float, Sideways);
HANDLE_PACKET_READ(ReadBEFloat, float, Forward);
HANDLE_PACKET_READ(ReadBool, bool, Jump);
HANDLE_PACKET_READ(ReadBool, bool, Unmount);
if (Unmount)
{
m_Client->HandleUnmount();
}
else
{
m_Client->HandleSteerVehicle(Forward, Sideways);
}
return PARSE_OK;
}
int cProtocol161::ParsePacket(unsigned char a_PacketType)
{
switch (a_PacketType)
{
case PACKET_STEER_VEHICLE: return ParseSteerVehicle();
default: return super::ParsePacket(a_PacketType);
}
}
////////////////////////////////////////////////////////////////////////////////
// cProtocol162:
cProtocol162::cProtocol162(cClientHandle * a_Client) :
super(a_Client)
{
}
void cProtocol162::SendPlayerMaxSpeed(void)
{
cCSLock Lock(m_CSPacket);
cPlayer * Player = m_Client->GetPlayer();
WriteByte(PACKET_ENTITY_PROPERTIES);
WriteInt(Player->GetUniqueID());
WriteInt(1);
WriteString("generic.movementSpeed");
WriteDouble(0.1 * Player->GetMaxSpeed());
WriteShort(0);
Flush();
}

View File

@ -1,78 +0,0 @@
// Protocol16x.h
/*
Declares the 1.6.x protocol classes:
- cProtocol161
- release 1.6.1 protocol (#73)
- cProtocol162
- release 1.6.2 protocol (#74)
- release 1.6.3 protocol (#77) - no relevant changes
- release 1.6.4 protocol (#78) - no relevant changes
(others may be added later in the future for the 1.6 release series)
*/
#pragma once
#include "Protocol15x.h"
class cProtocol161 :
public cProtocol150
{
typedef cProtocol150 super;
public:
cProtocol161(cClientHandle * a_Client);
protected:
// cProtocol150 overrides:
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) 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 SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override;
virtual void SendPlayerMaxSpeed(void) override;
virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual int ParseEntityAction (void) override;
virtual int ParseLogin (void) override;
virtual int ParsePlayerAbilities(void) override;
// New packets:
virtual int ParseSteerVehicle(void);
// Enable new packets' handling
virtual int ParsePacket(unsigned char a_PacketType) override;
} ;
class cProtocol162 :
public cProtocol161
{
typedef cProtocol161 super;
public:
cProtocol162(cClientHandle * a_Client);
protected:
// cProtocol161 overrides:
virtual void SendPlayerMaxSpeed(void) override;
} ;

View File

@ -2217,20 +2217,6 @@ void cProtocol172::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer)
void cProtocol172::WritePacket(cByteBuffer & a_Packet)
{
cCSLock Lock(m_CSPacket);
AString Pkt;
a_Packet.ReadAll(Pkt);
WriteVarInt((UInt32)Pkt.size());
SendData(Pkt.data(), Pkt.size());
Flush();
}
void cProtocol172::SendData(const char * a_Data, size_t a_Size)
{
if (m_IsEncrypted)

View File

@ -296,9 +296,6 @@ protected:
void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer);
/** 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, size_t a_Size) override;

View File

@ -2508,20 +2508,6 @@ void cProtocol180::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer)
void cProtocol180::WritePacket(cByteBuffer & a_Packet)
{
cCSLock Lock(m_CSPacket);
AString Pkt;
a_Packet.ReadAll(Pkt);
WriteVarInt((UInt32)Pkt.size());
SendData(Pkt.data(), Pkt.size());
Flush();
}
void cProtocol180::SendData(const char * a_Data, size_t a_Size)
{
if (m_IsEncrypted)

View File

@ -313,9 +313,6 @@ protected:
void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer);
/** 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, size_t a_Size) override;

View File

@ -7,11 +7,6 @@
#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 "Protocol18x.h"
#include "../ClientHandle.h"
@ -50,17 +45,6 @@ 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";
case PROTO_VERSION_1_7_6: return "1.7.6";
case PROTO_VERSION_1_8_0: return "1.8";
@ -213,8 +197,13 @@ void cProtocolRecognizer::SendDisconnect(const AString & a_Reason)
else
{
// This is used when the client sends a server-ping, respond with the default packet:
WriteByte (0xff); // PACKET_DISCONNECT
WriteString(a_Reason);
static const int Packet = 0xff; // PACKET_DISCONNECT
SendData((const char *)&Packet, 1); // WriteByte()
AString UTF16 = UTF8ToRawBEUTF16(a_Reason.c_str(), a_Reason.length());
static const short Size = htons((short)(UTF16.size() / 2));
SendData((const char *)&Size, 2); // WriteShort()
SendData(UTF16.data(), UTF16.size()); // WriteString()
}
}
@ -873,51 +862,8 @@ 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();
// Lengthed protocol, try if it has the entire initial handshake packet:
UInt32 PacketLen;
UInt32 ReadSoFar = (UInt32)m_Buffer.GetReadableSpace();
if (!m_Buffer.ReadVarInt(PacketLen))
@ -938,61 +884,6 @@ bool cProtocolRecognizer::TryRecognizeProtocol(void)
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;
@ -1090,80 +981,3 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
void cProtocolRecognizer::SendLengthlessServerPing(void)
{
AString Reply;
cServer * Server = cRoot::Get()->GetServer();
AString ServerDescription = Server->GetDescription();
int NumPlayers = Server->GetNumPlayers();
int MaxPlayers = Server->GetMaxPlayers();
AString Favicon = Server->GetFaviconData();
cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon);
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",
ServerDescription.c_str(),
cChatColor::Delimiter,
NumPlayers,
cChatColor::Delimiter,
MaxPlayers
);
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);
}
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(ServerDescription);
Reply.push_back(0);
Reply.append(Printf("%d", NumPlayers));
Reply.push_back(0);
Reply.append(Printf("%d", MaxPlayers));
break;
}
} // switch (m_PrimaryServerVersion)
m_Client->Kick(Reply);
}

View File

@ -18,8 +18,8 @@
// 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, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10, 1.8"
#define MCS_PROTOCOL_VERSIONS "29, 39, 47, 49, 51, 60, 61, 73, 74, 77, 78, 4, 5"
#define MCS_CLIENT_VERSIONS "1.7.x, 1.8"
#define MCS_PROTOCOL_VERSIONS "4, 5, 47"
@ -33,22 +33,6 @@ class cProtocolRecognizer :
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,
PROTO_VERSION_1_7_6 = 5,
PROTO_VERSION_1_8_0 = 47,
@ -150,23 +134,11 @@ protected:
/// 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);
} ;

View File

@ -42,7 +42,6 @@ cRoot* cRoot::s_Root = NULL;
cRoot::cRoot(void) :
m_PrimaryServerVersion(cProtocolRecognizer::PROTO_VERSION_LATEST),
m_pDefaultWorld(NULL),
m_InputThread(NULL),
m_Server(NULL),
@ -142,17 +141,6 @@ void cRoot::Start(void)
IniFile.AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help");
}
m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0);
if (m_PrimaryServerVersion == 0)
{
m_PrimaryServerVersion = cProtocolRecognizer::PROTO_VERSION_LATEST;
}
else
{
// Make a note in the log that the primary server version is explicitly set in the ini file
LOGINFO("Primary server version set explicitly to %d.", m_PrimaryServerVersion);
}
LOG("Starting server...");
m_MojangAPI.Start(IniFile); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
if (!m_Server->InitServer(IniFile))

View File

@ -73,9 +73,6 @@ public:
/// Writes chunkstats, for each world and totals, to the output callback
void LogChunkStats(cCommandOutputCallback & a_Output);
int GetPrimaryServerVersion(void) const { return m_PrimaryServerVersion; } // tolua_export
void SetPrimaryServerVersion(int a_Version) { m_PrimaryServerVersion = a_Version; } // tolua_export
cMonsterConfig * GetMonsterConfig(void) { return m_MonsterConfig; }
cCraftingRecipes * GetCraftingRecipes(void) { return m_CraftingRecipes; } // tolua_export
@ -169,9 +166,6 @@ private:
typedef std::map<AString, cWorld *> WorldMap;
typedef std::vector<cCommand> cCommandQueue;
/// The version of the protocol that is primary for the server (reported in the server list). All versions are still supported.
int m_PrimaryServerVersion;
cWorld * m_pDefaultWorld;
WorldMap m_WorldsByName;

View File

@ -441,10 +441,10 @@ static bool isLegalUTF8(const unsigned char * source, int length)
AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a_UTF16)
AString UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length)
{
a_UTF16.clear();
a_UTF16.reserve(a_UTF8Length * 3);
AString UTF16;
UTF16.reserve(a_UTF8Length * 3);
const unsigned char * source = (const unsigned char*)a_UTF8;
const unsigned char * sourceEnd = source + a_UTF8Length;
@ -458,12 +458,12 @@ AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd)
{
return a_UTF16;
return UTF16;
}
// Do this check whether lenient or strict
if (!isLegalUTF8(source, extraBytesToRead + 1))
{
return a_UTF16;
return UTF16;
}
// The cases all fall through. See "Note A" below.
@ -487,13 +487,13 @@ AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a
ch = ' ';
}
unsigned short v = htons((unsigned short)ch);
a_UTF16.append((const char *)&v, 2);
UTF16.append((const char *)&v, 2);
}
else if (ch > UNI_MAX_UTF16)
{
// Invalid value, replace with a space
unsigned short v = htons(' ');
a_UTF16.append((const char *)&v, 2);
UTF16.append((const char *)&v, 2);
}
else
{
@ -501,11 +501,11 @@ AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a
ch -= halfBase;
unsigned short v1 = htons((ch >> halfShift) + UNI_SUR_HIGH_START);
unsigned short v2 = htons((ch & halfMask) + UNI_SUR_LOW_START);
a_UTF16.append((const char *)&v1, 2);
a_UTF16.append((const char *)&v2, 2);
UTF16.append((const char *)&v1, 2);
UTF16.append((const char *)&v2, 2);
}
}
return a_UTF16;
return UTF16;
}
/*

View File

@ -66,8 +66,8 @@ extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AS
/// Converts a stream of BE shorts into UTF-8 string; returns a ref to a_UTF8
extern AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8);
/// Converts a UTF-8 string into a UTF-16 BE string, packing that back into AString; return a ref to a_UTF16
extern AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a_UTF16);
/// Converts a UTF-8 string into a UTF-16 BE string; returns a ref to a_UTF16
extern AString UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length);
/// Creates a nicely formatted HEX dump of the given memory block. Max a_BytesPerLine is 120
extern AString & CreateHexDump(AString & a_Out, const void * a_Data, size_t a_Size, size_t a_BytesPerLine);