summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/Protocol')
-rw-r--r--src/Protocol/Protocol.h5
-rw-r--r--src/Protocol/Protocol125.h8
-rw-r--r--src/Protocol/Protocol132.cpp154
-rw-r--r--src/Protocol/Protocol132.h16
-rw-r--r--src/Protocol/Protocol14x.cpp2
-rw-r--r--src/Protocol/Protocol15x.cpp54
-rw-r--r--src/Protocol/Protocol15x.h3
-rw-r--r--src/Protocol/Protocol17x.cpp207
-rw-r--r--src/Protocol/Protocol17x.h22
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp44
-rw-r--r--src/Protocol/ProtocolRecognizer.h4
11 files changed, 369 insertions, 150 deletions
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 3293da32c..791082537 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -12,6 +12,7 @@
#include "../Defines.h"
#include "../Endianness.h"
+#include "../Scoreboard.h"
@@ -92,6 +93,9 @@ public:
virtual void SendRespawn (void) = 0;
virtual void SendExperience (void) = 0;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
+ virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
+ virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) = 0;
+ virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 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;
@@ -103,6 +107,7 @@ public:
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 SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 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;
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index d0e5c9428..cd15ab518 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -68,6 +68,9 @@ public:
virtual void SendRespawn (void) 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 {} // This protocol doesn't support such message
+ 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, 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;
@@ -79,11 +82,12 @@ public:
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 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 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;
diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 29fbb4bba..f5fd95c7e 100644
--- a/src/Protocol/Protocol132.cpp
+++ b/src/Protocol/Protocol132.cpp
@@ -16,6 +16,7 @@
#include "../UI/Window.h"
#include "../Entities/Pickup.h"
#include "../WorldStorage/FastNBT.h"
+#include "../WorldStorage/EnchantmentSerializer.h"
#include "../StringCompression.h"
#ifdef _MSC_VER
@@ -27,13 +28,14 @@
#pragma warning(disable:4702)
#endif
-#include "cryptopp/randpool.h"
-
#ifdef _MSC_VER
#pragma warning(pop)
#endif
+
+
+
#define HANDLE_PACKET_READ(Proc, Type, Var) \
Type Var; \
{ \
@@ -48,17 +50,6 @@
-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...
@@ -92,81 +83,6 @@ enum
-// 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:
@@ -196,11 +112,11 @@ void cProtocol132::DataReceived(const char * a_Data, int a_Size)
{
if (m_IsEncrypted)
{
- byte Decrypted[512];
+ Byte Decrypted[512];
while (a_Size > 0)
{
int NumBytes = (a_Size > (int)sizeof(Decrypted)) ? (int)sizeof(Decrypted) : a_Size;
- m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes);
+ m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes);
super::DataReceived((const char *)Decrypted, NumBytes);
a_Size -= NumBytes;
a_Data += NumBytes;
@@ -581,9 +497,7 @@ int cProtocol132::ParseHandshake(void)
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);
+ // Send a 0xfd Encryption Key Request http://wiki.vg/Protocol#0xFD
SendEncryptionKeyRequest();
return PARSE_OK;
@@ -595,7 +509,7 @@ int cProtocol132::ParseHandshake(void)
int cProtocol132::ParseClientStatuses(void)
{
- HANDLE_PACKET_READ(ReadByte, byte, Status);
+ HANDLE_PACKET_READ(ReadByte, Byte, Status);
if ((Status & 1) == 0)
{
m_Client->HandleLogin(39, m_Username);
@@ -713,11 +627,11 @@ void cProtocol132::Flush(void)
int a_Size = m_DataToSend.size();
if (m_IsEncrypted)
{
- byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
+ Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
while (a_Size > 0)
{
int NumBytes = (a_Size > (int)sizeof(Encrypted)) ? (int)sizeof(Encrypted) : a_Size;
- m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes);
+ m_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes);
super::SendData((const char *)Encrypted, NumBytes);
a_Size -= NumBytes;
a_Data += NumBytes;
@@ -763,7 +677,7 @@ void cProtocol132::WriteItem(const cItem & a_Item)
// Send the enchantments:
cFastNBTWriter Writer;
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
- a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName);
+ EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
Writer.Finish();
AString Compressed;
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
@@ -849,7 +763,7 @@ int cProtocol132::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
)
)
{
- a_Item.m_Enchantments.ParseFromNBT(NBT, tag);
+ EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
}
}
@@ -879,8 +793,8 @@ void cProtocol132::SendEncryptionKeyRequest(void)
cCSLock Lock(m_CSPacket);
WriteByte(0xfd);
WriteString(cRoot::Get()->GetServer()->GetServerID());
- WriteShort((short)m_ServerPublicKey.size());
- SendData(m_ServerPublicKey.data(), m_ServerPublicKey.size());
+ WriteShort((short)(cRoot::Get()->GetServer()->GetPublicKeyDER().size()));
+ SendData(cRoot::Get()->GetServer()->GetPublicKeyDER().data(), cRoot::Get()->GetServer()->GetPublicKeyDER().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();
@@ -893,13 +807,11 @@ void cProtocol132::SendEncryptionKeyRequest(void)
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));
+ cRSAPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
+
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
- DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), (byte *)DecryptedNonce);
- if (!res.isValidCoding || (res.messageLength != 4))
+ 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");
@@ -913,9 +825,9 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
}
// 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))
+ 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");
@@ -931,6 +843,12 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
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;
}
@@ -939,21 +857,21 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
-void cProtocol132::StartEncryption(const byte * a_Key)
+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_Encryptor.Init(a_Key, a_Key);
+ m_Decryptor.Init(a_Key, a_Key);
m_IsEncrypted = true;
// Prepare the m_AuthServerID:
- CryptoPP::SHA1 Checksum;
+ cSHA1Checksum Checksum;
AString ServerID = cRoot::Get()->GetServer()->GetServerID();
- Checksum.Update((const byte *)ServerID.c_str(), ServerID.length());
+ 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);
+ Checksum.Update((const Byte *)cRoot::Get()->GetServer()->GetPublicKeyDER().data(), cRoot::Get()->GetServer()->GetPublicKeyDER().size());
+ Byte Digest[20];
+ Checksum.Finalize(Digest);
+ cSHA1Checksum::DigestToJava(Digest, m_AuthServerID);
}
diff --git a/src/Protocol/Protocol132.h b/src/Protocol/Protocol132.h
index 80fc8740a..89f4636f5 100644
--- a/src/Protocol/Protocol132.h
+++ b/src/Protocol/Protocol132.h
@@ -20,13 +20,12 @@
#pragma warning(disable:4702)
#endif
-#include "cryptopp/modes.h"
-#include "cryptopp/aes.h"
-
#ifdef _MSC_VER
#pragma warning(pop)
#endif
+#include "../Crypto.h"
+
@@ -79,16 +78,15 @@ public:
protected:
bool m_IsEncrypted;
- CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_Decryptor;
- CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_Encryptor;
+
+ cAESCFBDecryptor m_Decryptor;
+ cAESCFBEncryptor 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:
@@ -108,7 +106,7 @@ protected:
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);
+ void StartEncryption(const Byte * a_Key);
} ;
diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp
index 127ce9d4b..f82e6de45 100644
--- a/src/Protocol/Protocol14x.cpp
+++ b/src/Protocol/Protocol14x.cpp
@@ -33,8 +33,6 @@ Implements the 1.4.x protocol classes representing these protocols:
#pragma warning(disable:4702)
#endif
-#include "cryptopp/randpool.h"
-
#ifdef _MSC_VER
#pragma warning(pop)
#endif
diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp
index 0f1e59f10..264a596b9 100644
--- a/src/Protocol/Protocol15x.cpp
+++ b/src/Protocol/Protocol15x.cpp
@@ -35,8 +35,11 @@ Implements the 1.5.x protocol classes:
enum
{
- PACKET_WINDOW_OPEN = 0x64,
- PACKET_PARTICLE_EFFECT = 0x3F,
+ PACKET_WINDOW_OPEN = 0x64,
+ PACKET_PARTICLE_EFFECT = 0x3F,
+ PACKET_SCOREBOARD_OBJECTIVE = 0xCE,
+ PACKET_SCORE_UPDATE = 0xCF,
+ PACKET_DISPLAY_OBJECTIVE = 0xD0
} ;
@@ -97,6 +100,53 @@ void cProtocol150::SendParticleEffect(const AString & a_ParticleName, float a_Sr
+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);
diff --git a/src/Protocol/Protocol15x.h b/src/Protocol/Protocol15x.h
index 0074b3a83..0d171a67c 100644
--- a/src/Protocol/Protocol15x.h
+++ b/src/Protocol/Protocol15x.h
@@ -30,6 +30,9 @@ public:
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_ParticleAmmount) 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);
} ;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 5b3a79555..9bb2cfbf0 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1,4 +1,3 @@
-
// Protocol17x.cpp
/*
@@ -16,6 +15,7 @@ Implements the 1.7.x protocol classes:
#include "../Server.h"
#include "../World.h"
#include "../WorldStorage/FastNBT.h"
+#include "../WorldStorage/EnchantmentSerializer.h"
#include "../StringCompression.h"
#include "../Entities/ExpOrb.h"
#include "../Entities/Minecart.h"
@@ -24,6 +24,7 @@ Implements the 1.7.x protocol classes:
#include "../Entities/Player.h"
#include "../Mobs/IncludeAllMonsters.h"
#include "../UI/Window.h"
+#include "../BlockEntities/CommandBlockEntity.h"
@@ -52,6 +53,16 @@ Implements the 1.7.x protocol classes:
+// fwd: main.cpp:
+extern bool g_ShouldLogComm;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cProtocol172:
+
cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
super(a_Client),
m_ServerAddress(a_ServerAddress),
@@ -62,6 +73,13 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd
m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt
m_IsEncrypted(false)
{
+ // Create the comm log file, if so requested:
+ if (g_ShouldLogComm)
+ {
+ cFile::CreateFolder("CommLogs");
+ AString FileName = Printf("CommLogs/%x__%s.log", (unsigned)time(NULL), a_Client->GetIPString().c_str());
+ m_CommLogFile.Open(FileName, cFile::fmWrite);
+ }
}
@@ -72,11 +90,11 @@ void cProtocol172::DataReceived(const char * a_Data, int a_Size)
{
if (m_IsEncrypted)
{
- byte Decrypted[512];
+ 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);
+ m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes);
AddReceivedData((const char *)Decrypted, NumBytes);
a_Size -= NumBytes;
a_Data += NumBytes;
@@ -122,7 +140,7 @@ void cProtocol172::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, cha
void cProtocol172::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
{
cPacketizer Pkt(*this, 0x25); // Block Break Animation packet
- Pkt.WriteInt(a_EntityID);
+ Pkt.WriteVarInt(a_EntityID);
Pkt.WriteInt(a_BlockX);
Pkt.WriteInt(a_BlockY);
Pkt.WriteInt(a_BlockZ);
@@ -705,6 +723,46 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
+void cProtocol172::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode)
+{
+ cPacketizer Pkt(*this, 0x3B);
+ Pkt.WriteString(a_Name);
+ Pkt.WriteString(a_DisplayName);
+ Pkt.WriteByte(a_Mode);
+}
+
+
+
+
+
+void cProtocol172::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode)
+{
+ cPacketizer Pkt(*this, 0x3C);
+ Pkt.WriteString(a_Player);
+ Pkt.WriteByte(a_Mode);
+
+ if (a_Mode != 1)
+ {
+ Pkt.WriteString(a_Objective);
+ Pkt.WriteInt((int) a_Score);
+ }
+}
+
+
+
+
+
+void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display)
+{
+ cPacketizer Pkt(*this, 0x3D);
+ Pkt.WriteByte((int) a_Display);
+ Pkt.WriteString(a_Objective);
+}
+
+
+
+
+
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
@@ -892,6 +950,28 @@ void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
+{
+ cPacketizer Pkt(*this, 0x35); // Update tile entity packet
+ Pkt.WriteInt(a_BlockEntity.GetPosX());
+ Pkt.WriteShort(a_BlockEntity.GetPosY());
+ Pkt.WriteInt(a_BlockEntity.GetPosZ());
+
+ Byte Action = 0;
+ switch (a_BlockEntity.GetBlockType())
+ {
+ case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
+ case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
+ default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
+ }
+ Pkt.WriteByte(Action);
+
+ Pkt.WriteBlockEntity(a_BlockEntity);
+}
+
+
+
+
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)
{
@@ -1002,6 +1082,29 @@ void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property
void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
{
+ // Write the incoming data into the comm log file:
+ if (g_ShouldLogComm)
+ {
+ if (m_ReceivedData.GetReadableSpace() > 0)
+ {
+ AString AllData;
+ int OldReadableSpace = m_ReceivedData.GetReadableSpace();
+ m_ReceivedData.ReadAll(AllData);
+ m_ReceivedData.ResetRead();
+ m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace);
+ AString Hex;
+ CreateHexDump(Hex, AllData.data(), AllData.size(), 16);
+ m_CommLogFile.Printf("Incoming data, %d (0x%x) bytes unparsed already present in buffer:\n%s\n",
+ AllData.size(), AllData.size(), Hex.c_str()
+ );
+ }
+ AString Hex;
+ CreateHexDump(Hex, a_Data, a_Size, 16);
+ m_CommLogFile.Printf("Incoming data: %d (0x%x) bytes: \n%s\n",
+ a_Size, a_Size, Hex.c_str()
+ );
+ }
+
if (!m_ReceivedData.Write(a_Data, a_Size))
{
// Too much data in the incoming queue, report to caller:
@@ -1037,6 +1140,22 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
return;
}
+ // Log the packet info into the comm log file:
+ if (g_ShouldLogComm)
+ {
+ AString PacketData;
+ bb.ReadAll(PacketData);
+ bb.ResetRead();
+ bb.ReadVarInt(PacketType);
+ ASSERT(PacketData.size() > 0);
+ PacketData.resize(PacketData.size() - 1);
+ AString PacketDataHex;
+ CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16);
+ m_CommLogFile.Printf("Next incoming packet is type %u (0x%x), length %u (0x%x) at state %d. Payload:\n%s\n",
+ PacketType, PacketType, PacketLen, PacketLen, m_State, PacketDataHex.c_str()
+ );
+ }
+
if (!HandlePacket(bb, PacketType))
{
// Unknown packet, already been reported, but without the length. Log the length here:
@@ -1053,6 +1172,12 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
LOGD("Packet contents:\n%s", Out.c_str());
#endif // _DEBUG
+ // Put a message in the comm log:
+ if (g_ShouldLogComm)
+ {
+ m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n");
+ }
+
return;
}
@@ -1062,6 +1187,16 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x, state %d. Read %u bytes, packet contained %u bytes",
PacketType, m_State, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen
);
+
+ // Put a message in the comm log:
+ if (g_ShouldLogComm)
+ {
+ m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %d left) ^^^^^^\n\n\n",
+ 1, bb.GetReadableSpace()
+ );
+ m_CommLogFile.Flush();
+ }
+
ASSERT(!"Read wrong number of bytes!");
m_Client->PacketError(PacketType);
}
@@ -1601,11 +1736,11 @@ 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)
+ 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_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes);
m_Client->SendData((const char *)Encrypted, NumBytes);
a_Size -= NumBytes;
a_Data += NumBytes;
@@ -1696,7 +1831,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
)
)
{
- a_Item.m_Enchantments.ParseFromNBT(NBT, tag);
+ EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
}
else if ((NBT.GetType(tag) == TAG_Compound) && (NBT.GetName(tag) == "display")) // Custom name and lore tag
{
@@ -1744,6 +1879,17 @@ cProtocol172::cPacketizer::~cPacketizer()
m_Out.ReadAll(DataToSend);
m_Protocol.SendData(DataToSend.data(), DataToSend.size());
m_Out.CommitRead();
+
+ // Log the comm into logfile:
+ if (g_ShouldLogComm)
+ {
+ AString Hex;
+ ASSERT(DataToSend.size() > 0);
+ CreateHexDump(Hex, DataToSend.data() + 1, DataToSend.size() - 1, 16);
+ m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n",
+ DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str()
+ );
+ }
}
@@ -1781,7 +1927,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
if (!a_Item.m_Enchantments.IsEmpty())
{
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
- a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName);
+ EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments,Writer, TagName);
}
if (!a_Item.IsBothNameAndLoreEmpty())
{
@@ -1819,6 +1965,51 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
+void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEntity)
+{
+ cFastNBTWriter Writer;
+
+ switch (a_BlockEntity.GetBlockType())
+ {
+ case E_BLOCK_COMMAND_BLOCK:
+ {
+ cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
+
+ Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
+ Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
+ Writer.AddInt("x", CommandBlockEntity.GetPosX());
+ Writer.AddInt("y", CommandBlockEntity.GetPosY());
+ Writer.AddInt("z", CommandBlockEntity.GetPosZ());
+ Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str());
+ // You can set custom names for windows in Vanilla
+ // For a command block, this would be the 'name' prepended to anything it outputs into global chat
+ // MCS doesn't have this, so just leave it @ '@'. (geddit?)
+ Writer.AddString("CustomName", "@");
+ Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+
+ if (!CommandBlockEntity.GetLastOutput().empty())
+ {
+ AString Output;
+ Printf(Output, "{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str());
+
+ Writer.AddString("LastOutput", Output.c_str());
+ }
+ break;
+ }
+ default: break;
+ }
+
+ 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)
{
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 07dba834b..72544b575 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -26,21 +26,20 @@ Declares the 1.7.x protocol classes:
#pragma warning(disable:4702)
#endif
-#include "cryptopp/modes.h"
-#include "cryptopp/aes.h"
-
#ifdef _MSC_VER
#pragma warning(pop)
#endif
+#include "../Crypto.h"
+
class cProtocol172 :
- public cProtocol // TODO
+ public cProtocol
{
- typedef cProtocol super; // TODO
+ typedef cProtocol super;
public:
@@ -92,6 +91,9 @@ public:
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 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;
+ virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) 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;
@@ -102,6 +104,7 @@ public:
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 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;
@@ -189,6 +192,7 @@ protected:
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
+ void WriteBlockEntity(const cBlockEntity & a_BlockEntity);
protected:
cProtocol172 & m_Protocol;
@@ -215,8 +219,12 @@ protected:
cByteBuffer m_OutPacketLenBuffer;
bool m_IsEncrypted;
- CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_Decryptor;
- CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_Encryptor;
+
+ cAESCFBDecryptor m_Decryptor;
+ cAESCFBEncryptor m_Encryptor;
+
+ /** The logfile where the comm is logged, when g_ShouldLogComm is true */
+ cFile m_CommLogFile;
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index a21f4f042..32409c2aa 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -526,6 +526,36 @@ void cProtocolRecognizer::SendExperienceOrb(const cExpOrb & a_ExpOrb)
+void cProtocolRecognizer::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendScoreboardObjective(a_Name, a_DisplayName, a_Mode);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendScoreUpdate(a_Objective, a_Player, a_Score, a_Mode);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendDisplayObjective(a_Objective, a_Display);
+}
+
+
+
+
+
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);
@@ -636,6 +666,16 @@ void cProtocolRecognizer::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+void cProtocolRecognizer::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendUpdateBlockEntity(a_BlockEntity);
+}
+
+
+
+
+
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);
@@ -797,7 +837,7 @@ bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void)
}
switch (ch)
{
- case PROTO_VERSION_1_3_2:
+ case PROTO_VERSION_1_3_2:
{
m_Protocol = new cProtocol132(m_Client);
return true;
@@ -925,7 +965,7 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
m_Buffer.ResetRead();
if (m_Buffer.CanReadBytes(2))
{
- byte val;
+ Byte val;
m_Buffer.ReadByte(val); // Packet type - Serverlist ping
m_Buffer.ReadByte(val); // 0x01 magic value
ASSERT(val == 0x01);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index e94f4cde8..daeed1845 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -103,6 +103,9 @@ public:
virtual void SendRespawn (void) 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;
+ virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) 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;
@@ -114,6 +117,7 @@ public:
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 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;