summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/Protocol')
-rw-r--r--src/Protocol/Authenticator.cpp269
-rw-r--r--src/Protocol/Authenticator.h15
-rw-r--r--src/Protocol/Protocol.h6
-rw-r--r--src/Protocol/Protocol125.cpp108
-rw-r--r--src/Protocol/Protocol125.h10
-rw-r--r--src/Protocol/Protocol132.cpp25
-rw-r--r--src/Protocol/Protocol132.h4
-rw-r--r--src/Protocol/Protocol14x.cpp4
-rw-r--r--src/Protocol/Protocol15x.cpp2
-rw-r--r--src/Protocol/Protocol16x.cpp18
-rw-r--r--src/Protocol/Protocol16x.h2
-rw-r--r--src/Protocol/Protocol17x.cpp109
-rw-r--r--src/Protocol/Protocol17x.h6
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp20
-rw-r--r--src/Protocol/ProtocolRecognizer.h12
15 files changed, 351 insertions, 259 deletions
diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp
index 2050393c2..18924db2f 100644
--- a/src/Protocol/Authenticator.cpp
+++ b/src/Protocol/Authenticator.cpp
@@ -11,9 +11,6 @@
#include "PolarSSL++/BlockingSslClientSocket.h"
-#include <sstream>
-#include <iomanip>
-
@@ -21,6 +18,60 @@
#define DEFAULT_AUTH_SERVER "sessionserver.mojang.com"
#define DEFAULT_AUTH_ADDRESS "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"
+/** This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
+Downloaded from http://certs.starfieldtech.com/repository/ */
+static const AString gStarfieldCACert(
+ // G2 cert
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
+ "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
+ "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n"
+ "ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\n"
+ "MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n"
+ "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n"
+ "aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\n"
+ "Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n"
+ "ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\n"
+ "nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\n"
+ "HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\n"
+ "Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\n"
+ "dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\n"
+ "HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\n"
+ "BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\n"
+ "CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\n"
+ "sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n"
+ "4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n"
+ "8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\n"
+ "pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n"
+ "mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n"
+ "-----END CERTIFICATE-----\n\n"
+ // Original (G1) cert:
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"
+ "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"
+ "U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n"
+ "NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n"
+ "ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n"
+ "ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n"
+ "DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n"
+ "8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n"
+ "+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n"
+ "X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n"
+ "K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n"
+ "1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n"
+ "A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n"
+ "zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n"
+ "YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n"
+ "bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n"
+ "DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n"
+ "L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n"
+ "eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n"
+ "xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n"
+ "VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"
+ "WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"
+ "-----END CERTIFICATE-----\n"
+);
+
@@ -61,7 +112,8 @@ void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, co
{
if (!m_ShouldAuthenticate)
{
- cRoot::Get()->AuthenticateUser(a_ClientID, a_UserName, cClientHandle::GenerateOfflineUUID(a_UserName));
+ Json::Value Value;
+ cRoot::Get()->AuthenticateUser(a_ClientID, a_UserName, cClientHandle::GenerateOfflineUUID(a_UserName), Value);
return;
}
@@ -121,10 +173,11 @@ void cAuthenticator::Execute(void)
AString NewUserName = UserName;
AString UUID;
- if (AuthWithYggdrasil(NewUserName, ServerID, UUID))
+ Json::Value Properties;
+ if (AuthWithYggdrasil(NewUserName, ServerID, UUID, Properties))
{
- LOGINFO("User %s authenticated with UUID '%s'", NewUserName.c_str(), UUID.c_str());
- cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID);
+ LOGINFO("User %s authenticated with UUID %s", NewUserName.c_str(), UUID.c_str());
+ cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID, Properties);
}
else
{
@@ -137,97 +190,27 @@ void cAuthenticator::Execute(void)
-bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID)
+bool cAuthenticator::SecureGetFromAddress(const AString & a_CACerts, const AString & a_ExpectedPeerName, const AString & a_Data, AString & a_Response)
{
- LOGD("Trying to auth user %s", a_UserName.c_str());
-
- int ret;
- unsigned char buf[1024];
-
- /* Initialize certificates */
- // This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
- // Downloaded from http://certs.starfieldtech.com/repository/
- static const AString StarfieldCACert(
- // G2 cert
- "-----BEGIN CERTIFICATE-----\n"
- "MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
- "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
- "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n"
- "ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\n"
- "MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n"
- "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n"
- "aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\n"
- "Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n"
- "ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\n"
- "nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\n"
- "HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\n"
- "Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\n"
- "dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\n"
- "HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\n"
- "BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\n"
- "CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\n"
- "sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n"
- "4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n"
- "8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\n"
- "pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n"
- "mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n"
- "-----END CERTIFICATE-----\n\n"
- // Original (G1) cert:
- "-----BEGIN CERTIFICATE-----\n"
- "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"
- "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"
- "U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n"
- "NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n"
- "ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n"
- "ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n"
- "DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n"
- "8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n"
- "+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n"
- "X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n"
- "K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n"
- "1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n"
- "A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n"
- "zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n"
- "YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n"
- "bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n"
- "DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n"
- "L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n"
- "eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n"
- "xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n"
- "VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"
- "WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"
- "-----END CERTIFICATE-----\n"
- );
-
// Connect the socket:
cBlockingSslClientSocket Socket;
- Socket.SetTrustedRootCertsFromString(StarfieldCACert, m_Server);
- if (!Socket.Connect(m_Server, 443))
+ Socket.SetTrustedRootCertsFromString(a_CACerts, a_ExpectedPeerName);
+ if (!Socket.Connect(a_ExpectedPeerName, 443))
{
- LOGWARNING("cAuthenticator: Can't connect to %s: %s", m_Server.c_str(), Socket.GetLastErrorText().c_str());
+ LOGWARNING("cAuthenticator: Can't connect to %s: %s", a_ExpectedPeerName.c_str(), Socket.GetLastErrorText().c_str());
return false;
}
- // Create the GET request:
- AString ActualAddress = m_Address;
- ReplaceString(ActualAddress, "%USERNAME%", a_UserName);
- ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
-
- AString Request;
- Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
- Request += "Host: " + m_Server + "\r\n";
- Request += "User-Agent: MCServer\r\n";
- Request += "Connection: close\r\n";
- Request += "\r\n";
-
- if (!Socket.Send(Request.c_str(), Request.size()))
+ if (!Socket.Send(a_Data.c_str(), a_Data.size()))
{
LOGWARNING("cAuthenticator: Writing SSL data failed: %s", Socket.GetLastErrorText().c_str());
return false;
}
// Read the HTTP response:
- std::string Response;
+ int ret;
+ unsigned char buf[1024];
+
for (;;)
{
ret = Socket.Receive(buf, sizeof(buf));
@@ -235,7 +218,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
{
// This value should never be returned, it is handled internally by cBlockingSslClientSocket
- LOGWARNING("cAuthenticator: SSL reading failed internally.");
+ LOGWARNING("cAuthenticator: SSL reading failed internally");
return false;
}
if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
@@ -252,18 +235,46 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
break;
}
- Response.append((const char *)buf, (size_t)ret);
+ a_Response.append((const char *)buf, (size_t)ret);
}
Socket.Disconnect();
+ return true;
+}
+
+
+
+
+
+bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties)
+{
+ LOGD("Trying to authenticate user %s", a_UserName.c_str());
+
+ // Create the GET request:
+ AString ActualAddress = m_Address;
+ ReplaceString(ActualAddress, "%USERNAME%", a_UserName);
+ ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
+
+ AString Request;
+ Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
+ Request += "Host: " + m_Server + "\r\n";
+ Request += "User-Agent: MCServer\r\n";
+ Request += "Connection: close\r\n";
+ Request += "\r\n";
+
+ AString Response;
+ if (!SecureGetFromAddress(gStarfieldCACert, m_Server, Request, Response))
+ {
+ return false;
+ }
// Check the HTTP status line:
- AString prefix("HTTP/1.1 200 OK");
+ const AString Prefix("HTTP/1.1 200 OK");
AString HexDump;
- if (Response.compare(0, prefix.size(), prefix))
+ if (Response.compare(0, Prefix.size(), Prefix))
{
- LOGINFO("User \"%s\" failed to auth, bad http status line received", a_UserName.c_str());
- LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ LOGINFO("User %s failed to auth, bad HTTP status line received", a_UserName.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
return false;
}
@@ -271,8 +282,8 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
size_t idxHeadersEnd = Response.find("\r\n\r\n");
if (idxHeadersEnd == AString::npos)
{
- LOGINFO("User \"%s\" failed to authenticate, bad http response header received", a_UserName.c_str());
- LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ LOGINFO("User %s failed to authenticate, bad HTTP response header received", a_UserName.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
return false;
}
Response.erase(0, idxHeadersEnd + 4);
@@ -286,12 +297,13 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
Json::Reader reader;
if (!reader.parse(Response, root, false))
{
- LOGWARNING("cAuthenticator: Cannot parse Received Data to json!");
+ LOGWARNING("cAuthenticator: Cannot parse received data (authentication) to JSON!");
return false;
}
a_UserName = root.get("name", "Unknown").asString();
a_UUID = root.get("id", "").asString();
-
+ a_Properties = root["properties"];
+
// If the UUID doesn't contain the hashes, insert them at the proper places:
if (a_UUID.size() == 32)
{
@@ -300,6 +312,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
a_UUID.insert(18, "-");
a_UUID.insert(23, "-");
}
+
return true;
}
@@ -307,3 +320,69 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
+/* In case we want to export this function to the plugin API later - don't forget to add the relevant INI configuration lines for DEFAULT_PROPERTIES_ADDRESS
+
+#define DEFAULT_PROPERTIES_ADDRESS "/session/minecraft/profile/%UUID%"
+
+// Gets the properties, such as skin, of a player based on their UUID via Mojang's API
+bool GetPlayerProperties(const AString & a_UUID, Json::Value & a_Properties);
+
+bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a_Properties)
+{
+ LOGD("Trying to get properties for user %s", a_UUID.c_str());
+
+ // Create the GET request:
+ AString ActualAddress = m_PropertiesAddress;
+ ReplaceString(ActualAddress, "%UUID%", a_UUID);
+
+ AString Request;
+ Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
+ Request += "Host: " + m_Server + "\r\n";
+ Request += "User-Agent: MCServer\r\n";
+ Request += "Connection: close\r\n";
+ Request += "\r\n";
+
+ AString Response;
+ if (!ConnectSecurelyToAddress(gStarfieldCACert, m_Server, Request, Response))
+ {
+ return false;
+ }
+
+ // Check the HTTP status line:
+ const AString Prefix("HTTP/1.1 200 OK");
+ AString HexDump;
+ if (Response.compare(0, Prefix.size(), Prefix))
+ {
+ LOGINFO("Failed to get properties for user %s, bad HTTP status line received", a_UUID.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return false;
+ }
+
+ // Erase the HTTP headers from the response:
+ size_t idxHeadersEnd = Response.find("\r\n\r\n");
+ if (idxHeadersEnd == AString::npos)
+ {
+ LOGINFO("Failed to get properties for user %s, bad HTTP response header received", a_UUID.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return false;
+ }
+ Response.erase(0, idxHeadersEnd + 4);
+
+ // Parse the Json response:
+ if (Response.empty())
+ {
+ return false;
+ }
+
+ Json::Value root;
+ Json::Reader reader;
+ if (!reader.parse(Response, root, false))
+ {
+ LOGWARNING("cAuthenticator: Cannot parse received properties data to JSON!");
+ return false;
+ }
+
+ a_Properties = root["properties"];
+ return true;
+}
+*/
diff --git a/src/Protocol/Authenticator.h b/src/Protocol/Authenticator.h
index 211f51394..244d94c0b 100644
--- a/src/Protocol/Authenticator.h
+++ b/src/Protocol/Authenticator.h
@@ -23,6 +23,11 @@
// fwd: "cRoot.h"
class cRoot;
+namespace Json
+{
+ class Value;
+}
+
@@ -73,13 +78,19 @@ private:
AString m_Server;
AString m_Address;
+ AString m_PropertiesAddress;
bool m_ShouldAuthenticate;
/** cIsThread override: */
virtual void Execute(void) override;
- /** Returns true if the user authenticated okay, false on error; iLevel is the recursion deptht (bails out if too deep) */
- bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID);
+ /** Connects to a hostname using SSL, sends given data, and sets the response, returning whether all was successful or not */
+ bool SecureGetFromAddress(const AString & a_CACerts, const AString & a_ExpectedPeerName, const AString & a_Request, AString & a_Response);
+
+ /** Returns true if the user authenticated okay, false on error
+ Sets the username, UUID, and properties (i.e. skin) fields
+ */
+ bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties);
};
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 5b69d32a0..7e9eed402 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -64,7 +64,7 @@ public:
virtual void SendChat (const AString & a_Message) = 0;
virtual void SendChat (const cCompositeChat & a_Message) = 0;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) = 0;
+ virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0;
virtual void SendDestroyEntity (const cEntity & a_Entity) = 0;
virtual void SendDisconnect (const AString & a_Reason) = 0;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+)
@@ -106,7 +106,7 @@ public:
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 SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) = 0;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0;
virtual void SendSpawnMob (const cMonster & a_Mob) = 0;
@@ -132,7 +132,7 @@ public:
protected:
cClientHandle * m_Client;
- cCriticalSection m_CSPacket; //< Each SendXYZ() function must acquire this CS in order to send the whole packet at once
+ 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;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index f33965cb9..8cb34c128 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -274,11 +274,11 @@ void cProtocol125::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
-void cProtocol125::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocol125::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_COLLECT_PICKUP);
- WriteInt (a_Pickup.GetUniqueID());
+ WriteInt (a_Entity.GetUniqueID());
WriteInt (a_Player.GetUniqueID());
Flush();
}
@@ -398,7 +398,7 @@ void cProtocol125::SendEntityMetadata(const cEntity & a_Entity)
else
{
WriteEntityMetadata(a_Entity);
- }
+ }
WriteByte(0x7f);
Flush();
@@ -473,7 +473,7 @@ void cProtocol125::SendEntityVelocity(const cEntity & a_Entity)
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_ENTITY_VELOCITY);
WriteInt (a_Entity.GetUniqueID());
- WriteShort((short) (a_Entity.GetSpeedX() * 400)); //400 = 8000 / 20
+ WriteShort((short) (a_Entity.GetSpeedX() * 400)); // 400 = 8000 / 20
WriteShort((short) (a_Entity.GetSpeedY() * 400));
WriteShort((short) (a_Entity.GetSpeedZ() * 400));
Flush();
@@ -760,7 +760,7 @@ void cProtocol125::SendPlayerMoveLook(void)
);
*/
- WriteByte (PACKET_PLAYER_MOVE_LOOK);
+ WriteByte(PACKET_PLAYER_MOVE_LOOK);
cPlayer * Player = m_Client->GetPlayer();
WriteDouble(Player->GetPosX());
WriteDouble(Player->GetStance() + 0.03); // Add a small amount so that the player doesn't start inside a block
@@ -833,12 +833,12 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
-void cProtocol125::SendRespawn(eDimension a_Dimension)
+void cProtocol125::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
cCSLock Lock(m_CSPacket);
- if (m_LastSentDimension == a_Dimension)
+ if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
{
- // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do
+ // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
return;
}
cPlayer * Player = m_Client->GetPlayer();
@@ -899,7 +899,7 @@ void cProtocol125::SendScoreboardObjective(const AString & a_Name, const AString
-void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+void cProtocol125::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
// Not needed in this protocol version
}
@@ -1005,10 +1005,10 @@ void cProtocol125::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleTyp
void cProtocol125::SendStatistics(const cStatManager & a_Manager)
{
/* NOTE:
- * Versions prior to minecraft 1.7 use an incremental statistic sync
- * method. The current setup does not allow us to implement that, because
- * of performance considerations.
- */
+ Versions prior to minecraft 1.7 use an incremental statistic sync
+ method. The current setup does not allow us to implement that, because
+ of performance considerations.
+ */
#if 0
for (unsigned int i = 0; i < (unsigned int)statCount; ++i)
{
@@ -1121,7 +1121,7 @@ void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bloc
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_USE_BED);
WriteInt (a_Entity.GetUniqueID());
- WriteByte(0); // Unknown byte only 0 has been observed
+ WriteByte(0); // Unknown byte only 0 has been observed
WriteInt (a_BlockX);
WriteByte((Byte)a_BlockY);
WriteInt (a_BlockZ);
@@ -1344,11 +1344,11 @@ int cProtocol125::ParseArmAnim(void)
int cProtocol125::ParseBlockDig(void)
{
- HANDLE_PACKET_READ(ReadChar, char, Status);
+ HANDLE_PACKET_READ(ReadChar, char, Status);
HANDLE_PACKET_READ(ReadBEInt, int, PosX);
- HANDLE_PACKET_READ(ReadByte, Byte, PosY);
+ HANDLE_PACKET_READ(ReadByte, Byte, PosY);
HANDLE_PACKET_READ(ReadBEInt, int, PosZ);
- HANDLE_PACKET_READ(ReadChar, char, BlockFace);
+ HANDLE_PACKET_READ(ReadChar, char, BlockFace);
m_Client->HandleLeftClick(PosX, PosY, PosZ, static_cast<eBlockFace>(BlockFace), Status);
return PARSE_OK;
}
@@ -1426,11 +1426,11 @@ int cProtocol125::ParseEntityAction(void)
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
+ 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;
@@ -1444,7 +1444,7 @@ int cProtocol125::ParseHandshake(void)
{
HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username);
- AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565"
+ AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565"
if (UserData.empty())
{
m_Client->Kick("Did not receive username");
@@ -1456,7 +1456,7 @@ int cProtocol125::ParseHandshake(void)
if (!m_Client->HandleHandshake( m_Username ))
{
- return PARSE_OK; // Player is not allowed into the server
+ return PARSE_OK; // Player is not allowed into the server
}
SendHandshake(cRoot::Get()->GetServer()->GetServerID());
@@ -1918,20 +1918,20 @@ void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity)
// No idea how Mojang makes their carts shakey shakey, so here is a complicated one-liner expression that does something similar
WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4 );
WriteByte(0x52);
- WriteInt(1); // Shaking direction, doesn't seem to affect anything
+ WriteInt(1); // Shaking direction, doesn't seem to affect anything
WriteByte(0x73);
- WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
+ WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace)
{
WriteByte(0x10);
- WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled?
+ WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled?
}
}
else if ((a_Entity.IsProjectile() && ((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow))
{
WriteByte(0x10);
- WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow?
+ WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow?
}
}
@@ -1946,43 +1946,43 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
case cMonster::mtCreeper:
{
WriteByte(0x10);
- WriteChar(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up?
+ WriteChar(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up?
WriteByte(0x11);
- WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged?
+ WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged?
break;
}
case cMonster::mtBat:
{
WriteByte(0x10);
- WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down?
+ WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down?
break;
}
case cMonster::mtPig:
{
WriteByte(0x10);
- WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled?
+ WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled?
break;
}
case cMonster::mtVillager:
{
WriteByte(0x50);
- WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE?
+ WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE?
break;
}
case cMonster::mtZombie:
{
WriteByte(0xC);
- WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie?
+ WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Baby zombie?
WriteByte(0xD);
- WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie?
+ WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie?
WriteByte(0xE);
- WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager?
+ WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager?
break;
}
case cMonster::mtGhast:
{
WriteByte(0x10);
- WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P
+ WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to spit a flameball?
break;
}
case cMonster::mtWolf:
@@ -2004,9 +2004,9 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
WriteByte(WolfStatus);
WriteByte(0x72);
- WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way)
+ WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way)
WriteByte(0x13);
- WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode?
+ WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode?
break;
}
case cMonster::mtSheep:
@@ -2028,30 +2028,30 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
case cMonster::mtEnderman:
{
WriteByte(0x10);
- WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house
+ WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house
WriteByte(0x11);
- WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house
+ WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house
WriteByte(0x12);
- WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face?
+ WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face?
break;
}
case cMonster::mtSkeleton:
{
WriteByte(0xD);
- WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not
+ WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not
break;
}
case cMonster::mtWitch:
{
WriteByte(0x15);
- WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
+ WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
break;
}
case cMonster::mtWither:
{
- WriteByte(0x54); // Int at index 20
+ WriteByte(0x54); // Int at index 20
WriteInt((Int32)((const cWither &)a_Mob).GetWitherInvulnerableTicks());
- WriteByte(0x66); // Float at index 6
+ WriteByte(0x66); // Float at index 6
WriteFloat((float)(a_Mob.GetHealth()));
break;
}
@@ -2061,11 +2061,11 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
WriteByte(0x10);
if (a_Mob.GetMobType() == cMonster::mtSlime)
{
- WriteByte((Byte)((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
+ WriteByte((Byte)((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
}
else
{
- WriteByte((Byte)((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
+ WriteByte((Byte)((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
}
break;
}
@@ -2086,7 +2086,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
}
if (((const cHorse &)a_Mob).IsBaby())
{
- Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer
+ Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer
}
if (((const cHorse &)a_Mob).IsEating())
{
@@ -2104,16 +2104,16 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
WriteInt(Flags);
WriteByte(0x13);
- WriteByte((Byte)((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.)
+ WriteByte((Byte)((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.)
WriteByte(0x54);
int Appearance = 0;
- Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF
- Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256
- WriteInt(Appearance);
+ Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF
+ Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256
+ WriteInt(Appearance);
WriteByte(0x56);
- WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour
+ WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour
break;
}
default:
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index dbf30a8e6..955e3e741 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -36,7 +36,7 @@ public:
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 SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) 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+)
@@ -72,13 +72,13 @@ public:
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) override;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) 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, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ 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;
diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 1e3fc8de8..8502702e8 100644
--- a/src/Protocol/Protocol132.cpp
+++ b/src/Protocol/Protocol132.cpp
@@ -71,7 +71,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol132:
cProtocol132::cProtocol132(cClientHandle * a_Client) :
@@ -188,20 +188,13 @@ void cProtocol132::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
-void cProtocol132::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocol132::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_COLLECT_PICKUP);
- WriteInt (a_Pickup.GetUniqueID());
+ WriteInt (a_Entity.GetUniqueID());
WriteInt (a_Player.GetUniqueID());
Flush();
-
- // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
- SendSoundEffect(
- "random.pop",
- (int)(a_Pickup.GetPosX() * 8), (int)(a_Pickup.GetPosY() * 8), (int)(a_Pickup.GetPosZ() * 8),
- 0.5, (float)(0.75 + ((float)((a_Pickup.GetUniqueID() * 23) % 32)) / 64)
- );
}
@@ -285,14 +278,14 @@ void cProtocol132::SendPlayerSpawn(const cPlayer & a_Player)
-void cProtocol132::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+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 (a_SrcX);
- WriteInt (a_SrcY);
- WriteInt (a_SrcZ);
+ 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();
@@ -389,7 +382,7 @@ void cProtocol132::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
void cProtocol132::SendWholeInventory(const cWindow & a_Window)
{
- // 1.3.2 requires player inventory slots to be sent as SetSlot packets,
+ // 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:
@@ -483,7 +476,7 @@ int cProtocol132::ParseHandshake(void)
if (!m_Client->HandleHandshake( m_Username ))
{
- return PARSE_OK; // Player is not allowed into the server
+ return PARSE_OK; // Player is not allowed into the server
}
// Send a 0xfd Encryption Key Request http://wiki.vg/Protocol#0xFD
diff --git a/src/Protocol/Protocol132.h b/src/Protocol/Protocol132.h
index 32bc7d581..1124a7253 100644
--- a/src/Protocol/Protocol132.h
+++ b/src/Protocol/Protocol132.h
@@ -48,12 +48,12 @@ public:
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override;
+ virtual void 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, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ 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;
diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp
index f60e756fd..8b177ea48 100644
--- a/src/Protocol/Protocol14x.cpp
+++ b/src/Protocol/Protocol14x.cpp
@@ -66,7 +66,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol142:
cProtocol142::cProtocol142(cClientHandle * a_Client) :
@@ -144,7 +144,7 @@ void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol146:
cProtocol146::cProtocol146(cClientHandle * a_Client) :
diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp
index 264a596b9..2b1f01b08 100644
--- a/src/Protocol/Protocol15x.cpp
+++ b/src/Protocol/Protocol15x.cpp
@@ -47,7 +47,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol150:
cProtocol150::cProtocol150(cClientHandle * a_Client) :
diff --git a/src/Protocol/Protocol16x.cpp b/src/Protocol/Protocol16x.cpp
index cc675c075..0d354a030 100644
--- a/src/Protocol/Protocol16x.cpp
+++ b/src/Protocol/Protocol16x.cpp
@@ -55,7 +55,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol161:
cProtocol161::cProtocol161(cClientHandle * a_Client) :
@@ -158,10 +158,10 @@ void cProtocol161::SendPlayerMaxSpeed(void)
-void cProtocol161::SendRespawn(eDimension a_Dimension)
+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);
+ super::SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks);
SendPlayerMaxSpeed();
}
@@ -202,11 +202,11 @@ int cProtocol161::ParseEntityAction(void)
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
+ 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;
@@ -282,7 +282,7 @@ int cProtocol161::ParsePacket(unsigned char a_PacketType)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol162:
cProtocol162::cProtocol162(cClientHandle * a_Client) :
diff --git a/src/Protocol/Protocol16x.h b/src/Protocol/Protocol16x.h
index 2d50749ec..13866801a 100644
--- a/src/Protocol/Protocol16x.h
+++ b/src/Protocol/Protocol16x.h
@@ -42,7 +42,7 @@ protected:
virtual void SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override;
virtual void SendPlayerMaxSpeed(void) override;
- virtual void SendRespawn (eDimension a_Dimension) override;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) override;
virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual int ParseEntityAction (void) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 2460a4914..a421e4da6 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -81,7 +81,7 @@ extern bool g_ShouldLogCommIn, g_ShouldLogCommOut;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol172:
cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
@@ -351,12 +351,12 @@ void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
-void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocol172::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0d); // Collect Item packet
- Pkt.WriteInt(a_Pickup.GetUniqueID());
+ Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteInt(a_Player.GetUniqueID());
}
@@ -651,7 +651,7 @@ void cProtocol172::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
cServer * Server = cRoot::Get()->GetServer();
cPacketizer Pkt(*this, 0x01); // Join Game packet
Pkt.WriteInt(a_Player.GetUniqueID());
- Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
+ Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
Pkt.WriteChar((char)a_World.GetDimension());
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60));
@@ -807,7 +807,7 @@ void cProtocol172::SendPlayerAbilities(void)
if (Player->IsGameModeCreative())
{
Flags |= 0x01;
- Flags |= 0x08; // Godmode, used for creative
+ Flags |= 0x08; // Godmode, used for creative
}
if (Player->IsFlying())
{
@@ -986,11 +986,11 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
-void cProtocol172::SendRespawn(eDimension a_Dimension)
+void cProtocol172::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
- if (m_LastSentDimension == a_Dimension)
+ if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
{
- // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do
+ // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
return;
}
@@ -1026,7 +1026,7 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
{
ASSERT(m_State == 3); // In game mode?
- cPacketizer Pkt(*this, 0x11);
+ cPacketizer Pkt(*this, 0x11);
Pkt.WriteVarInt(a_ExpOrb.GetUniqueID());
Pkt.WriteInt((int) a_ExpOrb.GetPosX());
Pkt.WriteInt((int) a_ExpOrb.GetPosY());
@@ -1084,15 +1084,15 @@ void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard
-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
+void cProtocol172::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
ASSERT(m_State == 3); // In game mode?
-
+
cPacketizer Pkt(*this, 0x29); // Sound Effect packet
Pkt.WriteString(a_SoundName);
- Pkt.WriteInt(a_SrcX);
- Pkt.WriteInt(a_SrcY);
- Pkt.WriteInt(a_SrcZ);
+ Pkt.WriteInt((int)(a_X * 8.0));
+ Pkt.WriteInt((int)(a_Y * 8.0));
+ Pkt.WriteInt((int)(a_Z * 8.0));
Pkt.WriteFloat(a_Volume);
Pkt.WriteByte((Byte)(a_Pitch * 63));
}
@@ -1130,7 +1130,7 @@ void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
Pkt.WriteFPInt(a_FallingBlock.GetPosZ());
Pkt.WriteByteAngle(a_FallingBlock.GetYaw());
Pkt.WriteByteAngle(a_FallingBlock.GetPitch());
- Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10
+ Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedX() * 400));
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedY() * 400));
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400));
@@ -1219,12 +1219,11 @@ void cProtocol172::SendStatistics(const cStatManager & a_Manager)
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x37);
- Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
+ Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
- for (unsigned int i = 0; i < (unsigned int)statCount; ++i)
+ for (size_t i = 0; i < (size_t)statCount; ++i)
{
StatValue Value = a_Manager.GetValue((eStatistic) i);
-
const AString & StatName = cStatInfo::GetName((eStatistic) i);
Pkt.WriteString(StatName);
@@ -1327,10 +1326,10 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
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
- case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
- case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
+ 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
+ case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
+ case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
}
Pkt.WriteByte(Action);
@@ -1657,7 +1656,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true;
case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true;
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
- case 0x0f: // Confirm transaction - not used in MCS
+ case 0x0f: // Confirm transaction - not used in MCS
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true;
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
@@ -1951,11 +1950,11 @@ void cProtocol172::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer)
switch (Action)
{
- case 1: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch
- case 2: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch
- case 3: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
- case 4: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
- case 5: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
+ case 1: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch
+ case 2: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch
+ case 3: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
+ case 4: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
+ case 5: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
}
}
@@ -2312,7 +2311,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
{
case TAG_List:
{
- if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
+ if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
{
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
}
@@ -2320,21 +2319,21 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
}
case TAG_Compound:
{
- if (TagName == "display") // Custom name and lore tag
+ if (TagName == "display") // Custom name and lore tag
{
for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag))
{
- if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
+ if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
{
a_Item.m_CustomName = NBT.GetString(displaytag);
}
- else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
+ else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
{
AString Lore;
- for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
+ for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
{
- AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a newline, used internally by MCS to display a new line in the client; don't forget to c_str ;)
+ AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a grave accent/backtick, used internally by MCS to display a new line in the client; don't forget to c_str ;)
}
a_Item.m_Lore = Lore;
@@ -2464,7 +2463,7 @@ void cProtocol172::AddChatPartStyle(Json::Value & a_Value, const AString & a_Par
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol172::cPacketizer:
cProtocol172::cPacketizer::~cPacketizer()
@@ -2586,7 +2585,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
{
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
- Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
+ 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());
@@ -2596,7 +2595,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
// 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
+ Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
if (!CommandBlockEntity.GetLastOutput().empty())
{
@@ -2617,7 +2616,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF);
Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF);
Writer.AddString("ExtraType", MobHeadEntity.GetOwner().c_str());
- Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+ Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
case E_BLOCK_FLOWER_POT:
@@ -2629,7 +2628,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
Writer.AddInt("Item", (Int32) FlowerPotEntity.GetItem().m_ItemType);
Writer.AddInt("Data", (Int32) FlowerPotEntity.GetItem().m_ItemDamage);
- Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+ Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
default: break;
@@ -2708,15 +2707,16 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
// The following expression makes Minecarts shake more with less health or higher damage taken
// It gets half the maximum health, and takes it away from the current health minus the half health:
- /* Health: 5 | 3 - (5 - 3) = 1 (shake power)
- Health: 3 | 3 - (3 - 3) = 3
- Health: 1 | 3 - (1 - 3) = 5
+ /*
+ Health: 5 | 3 - (5 - 3) = 1 (shake power)
+ Health: 3 | 3 - (3 - 3) = 3
+ Health: 1 | 3 - (1 - 3) = 5
*/
WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4);
WriteByte(0x52);
- WriteInt(1); // Shaking direction, doesn't seem to affect anything
+ WriteInt(1); // Shaking direction, doesn't seem to affect anything
WriteByte(0x73);
- WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
+ WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpNone)
{
@@ -2904,9 +2904,9 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
case cMonster::mtWither:
{
- WriteByte(0x54); // Int at index 20
+ WriteByte(0x54); // Int at index 20
WriteInt(((const cWither &)a_Mob).GetWitherInvulnerableTicks());
- WriteByte(0x66); // Float at index 6
+ WriteByte(0x66); // Float at index 6
WriteFloat((float)(a_Mob.GetHealth()));
break;
}
@@ -2986,7 +2986,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
return;
}
- //const cMonster & Mob = (const cMonster &)a_Entity;
+ // const cMonster & Mob = (const cMonster &)a_Entity;
// TODO: Send properties and modifiers based on the mob type
@@ -2997,7 +2997,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol176:
cProtocol176::cProtocol176(cClientHandle * a_Client, const AString &a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
@@ -3016,7 +3016,18 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
Pkt.WriteVarInt(a_Player.GetUniqueID());
Pkt.WriteString(a_Player.GetClientHandle()->GetUUID());
Pkt.WriteString(a_Player.GetName());
- Pkt.WriteVarInt(0); // We have no data to send here
+
+ const Json::Value & Properties = m_Client->GetProperties();
+ const Json::Value::const_iterator End = Properties.end();
+ Pkt.WriteVarInt(Properties.size());
+
+ for (Json::Value::iterator itr = Properties.begin(); itr != End; ++itr)
+ {
+ Pkt.WriteString(((Json::Value)*itr).get("name", "").toStyledString());
+ Pkt.WriteString(((Json::Value)*itr).get("value", "").toStyledString());
+ Pkt.WriteString(((Json::Value)*itr).get("signature", "").toStyledString());
+ }
+
Pkt.WriteFPInt(a_Player.GetPosX());
Pkt.WriteFPInt(a_Player.GetPosY());
Pkt.WriteFPInt(a_Player.GetPosZ());
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 5e3bf0e2a..2d4005f57 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -68,7 +68,7 @@ public:
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 SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) 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+)
@@ -104,8 +104,8 @@ public:
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) override;
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) 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 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;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index e1b22978e..50eb848c8 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -1,7 +1,7 @@
// ProtocolRecognizer.cpp
-// Implements the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
+// Implements the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
// protocol versions and redirects everything to them
#include "Globals.h"
@@ -181,10 +181,10 @@ void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSe
-void cProtocolRecognizer::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocolRecognizer::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendCollectPickup(a_Pickup, a_Player);
+ m_Protocol->SendCollectEntity(a_Entity, a_Player);
}
@@ -556,10 +556,10 @@ void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a
-void cProtocolRecognizer::SendRespawn(eDimension a_Dimension)
+void cProtocolRecognizer::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendRespawn(a_Dimension);
+ m_Protocol->SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks);
}
@@ -616,10 +616,10 @@ void cProtocolRecognizer::SendDisplayObjective(const AString & a_Objective, cSco
-void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);
+ m_Protocol->SendSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch);
}
@@ -828,7 +828,7 @@ void cProtocolRecognizer::SendData(const char * a_Data, size_t a_Size)
bool cProtocolRecognizer::TryRecognizeProtocol(void)
{
- // NOTE: If a new protocol is added or an old one is removed, adjust MCS_CLIENT_VERSIONS and
+ // 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:
@@ -953,7 +953,6 @@ bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void)
bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining)
{
UInt32 PacketType;
- UInt32 NumBytesRead = (UInt32)m_Buffer.GetReadableSpace();
if (!m_Buffer.ReadVarInt(PacketType))
{
return false;
@@ -972,7 +971,6 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
{
return false;
}
- NumBytesRead -= (UInt32)m_Buffer.GetReadableSpace();
switch (ProtocolVersion)
{
case PROTO_VERSION_1_7_2:
@@ -1021,7 +1019,7 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
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",
+ Printf(Reply, "%s%s%i%s%i",
Server->GetDescription().c_str(),
cChatColor::Delimiter.c_str(),
Server->GetNumPlayers(),
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index eb83fb0c0..b78528e29 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -1,7 +1,7 @@
// ProtocolRecognizer.h
-// Interfaces to the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
+// Interfaces to the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
// protocol versions and redirects everything to them
@@ -71,7 +71,7 @@ public:
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 SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) 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+)
@@ -107,13 +107,13 @@ public:
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) override;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) 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 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;
@@ -139,8 +139,8 @@ public:
virtual void SendData(const char * a_Data, size_t a_Size) override;
protected:
- cProtocol * m_Protocol; //< The recognized protocol
- cByteBuffer m_Buffer; //< Buffer for the incoming data until we recognize the protocol
+ cProtocol * m_Protocol; ///< The recognized protocol
+ cByteBuffer m_Buffer; ///< Buffer for the incoming data until we recognize the protocol
/// Tries to recognize protocol based on m_Buffer contents; returns true if recognized
bool TryRecognizeProtocol(void);