mirror of
https://github.com/LANCommander/BadCompany2.MasterServer.git
synced 2026-08-30 10:23:02 -04:00
2241 lines
78 KiB
C++
2241 lines
78 KiB
C++
#include "GameClient.h"
|
||
#include "Framework.h"
|
||
#include "../Base64.h"
|
||
#include <boost/filesystem/operations.hpp>
|
||
extern Logger* debug;
|
||
extern Framework* fw;
|
||
|
||
GameClient::GameClient(int connectionType, Database* db, string emuIp, bool isLocal)
|
||
{
|
||
this->connectionType = connectionType;
|
||
this->logDatabase = fw->DatabaseLogging();
|
||
database = db;
|
||
user.data = NULL;
|
||
persona.data = NULL;
|
||
|
||
this->isLocal = isLocal;
|
||
this->emuIp = emuIp;
|
||
alreadyLoggedIn = false;
|
||
stats_data = NULL;
|
||
|
||
sock_tid = 0;
|
||
queue_position = 0;
|
||
}
|
||
|
||
GameClient::~GameClient()
|
||
{
|
||
if(connectionType == GAME_CLIENT_SSL)
|
||
{
|
||
if(user.data && (user.data[USER_ONLINE].compare("1") == 0) && !alreadyLoggedIn)
|
||
{
|
||
user.data[USER_ONLINE] = "0";
|
||
if(persona.data)
|
||
persona.data[PERSONA_ONLINE] = "0";
|
||
}
|
||
}
|
||
playerList.clear();
|
||
|
||
if(connectionType == GAME_CLIENT_SSL && stats_data)
|
||
delete stats_data;
|
||
|
||
}
|
||
|
||
bool GameClient::acct(list<Packet*>* queue, Packet* packet, string txn, const char* ip)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
|
||
if(txn.compare("GetCountryList") == 0) // User wants to create a new account
|
||
{
|
||
string countryData("");
|
||
ifstream statsFile("./templates/countryList", ifstream::in);
|
||
if(statsFile.is_open() && statsFile.good())
|
||
{
|
||
stringstream buffer;
|
||
buffer << statsFile.rdbuf();
|
||
countryData = buffer.str();
|
||
statsFile.close();
|
||
}
|
||
|
||
size_t count = 0, start = 0;
|
||
while((start = countryData.find("\n", start)) != string::npos)
|
||
{
|
||
count++;
|
||
start++;
|
||
}
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("countryList.[]", count);
|
||
start = 0;
|
||
for(size_t i = 0; i < count; i++)
|
||
{
|
||
char buffer[48];
|
||
size_t end = countryData.find("=", start);
|
||
if(end != string::npos)
|
||
{
|
||
string data = countryData.substr(start, end-start);
|
||
sprintf(buffer, "countryList.%i.ISOCode", i);
|
||
sendPacket->SetVar(buffer, data);
|
||
|
||
start = end+1;
|
||
end = countryData.find("\n", start);
|
||
if(end == string::npos)
|
||
end = countryData.size(); //we are at the last line
|
||
|
||
data = countryData.substr(start, end-start);
|
||
sprintf(buffer, "countryList.%i.description", i);
|
||
sendPacket->SetVar(buffer, data);
|
||
|
||
if(end != countryData.size())
|
||
start = end+1;
|
||
}
|
||
else
|
||
{
|
||
debug->warning(2, connectionType, "countryData is corrupted, check the file!");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("NuGetTos") == 0)
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("version", "20426_20.20426_20");
|
||
|
||
string copiedData = "";
|
||
ifstream sourceFile("./templates/termsOfService", ifstream::in);
|
||
if(sourceFile.is_open() && sourceFile.good())
|
||
{
|
||
stringstream buffer;
|
||
buffer << sourceFile.rdbuf();
|
||
copiedData = buffer.str();
|
||
sourceFile.close();
|
||
}
|
||
else
|
||
debug->warning(2, DEBUG, "NuGetTos, failed to open termsOfService template, check if the directory and the files exist.");
|
||
|
||
if(copiedData.size() > 1)
|
||
{
|
||
size_t pos = 0;
|
||
while((pos = copiedData.find_first_of('%', pos+1)) != string::npos)
|
||
copiedData.replace(pos, 1, "%25");
|
||
pos = 0;
|
||
while((pos = copiedData.find_first_of('\n', pos+1)) != string::npos)
|
||
copiedData.replace(pos, 1, "%0a");
|
||
pos = 0;
|
||
while((pos = copiedData.find_first_of(':', pos+1)) != string::npos)
|
||
copiedData.replace(pos, 1, "%3a");
|
||
pos = 0;
|
||
while((pos = copiedData.find_first_of('\"', pos+1)) != string::npos)
|
||
copiedData.replace(pos, 1, "%22");
|
||
pos = 0;
|
||
while((pos = copiedData.find_first_of('\t', pos+1)) != string::npos)
|
||
copiedData.replace(pos, 1, "%09");
|
||
}
|
||
copiedData.append("%0a%0a%09MASE%3aBC2 v0.9 made by Triver");
|
||
copiedData.insert(copiedData.begin(), '\"');
|
||
copiedData.append("\"");
|
||
sendPacket->SetVar("tos", copiedData);
|
||
}
|
||
|
||
else if(txn.compare("NuAddAccount") == 0)
|
||
{
|
||
list_entry tempUser;
|
||
tempUser.name = packet->GetVar("nuid");
|
||
int realSize = tempUser.name.size();
|
||
int pos = -1;
|
||
while((pos = tempUser.name.find_first_of('%', pos+1)) != (int)string::npos)
|
||
realSize -= 2;
|
||
|
||
if(realSize > 32 || realSize < 3) // entered user name length is out of bounds
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("errorContainer.[]", "1");
|
||
sendPacket->SetVar("errorCode", "21");
|
||
sendPacket->SetVar("localizedMessage", "\"The required parameters for this call are missing or invalid\"");
|
||
sendPacket->SetVar("errorContainer.0.fieldName", "displayName");
|
||
if(realSize > 32)
|
||
{
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "3");
|
||
sendPacket->SetVar("errorContainer.0.value", "TOO_LONG");
|
||
}
|
||
else
|
||
{
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "2");
|
||
sendPacket->SetVar("errorContainer.0.value", "TOO_SHORT");
|
||
}
|
||
} //forbidden chars due to file creation incompatibilities
|
||
else if(tempUser.name.find_first_of('/') != string::npos || tempUser.name.find_first_of('\\') != string::npos || tempUser.name.find_first_of('?') != string::npos ||
|
||
tempUser.name.find_first_of('*') != string::npos || tempUser.name.find_first_of('\"') != string::npos || tempUser.name.find_first_of('|') != string::npos ||
|
||
tempUser.name.find_first_of(':') != string::npos || tempUser.name.find_first_of('<') != string::npos || tempUser.name.find_first_of('>') != string::npos)
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("errorContainer.[]", "1");
|
||
sendPacket->SetVar("errorCode", "21");
|
||
sendPacket->SetVar("localizedMessage", "\"The required parameters for this call are missing or invalid\"");
|
||
sendPacket->SetVar("errorContainer.0.fieldName", "displayName");
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "6");
|
||
sendPacket->SetVar("errorContainer.0.value", "NOT_ALLOWED");
|
||
}
|
||
else //first check the age then do database stuff
|
||
{
|
||
time_t rawtime;
|
||
struct tm* lt;
|
||
time (&rawtime);
|
||
lt = localtime(&rawtime);
|
||
|
||
int bd_year = lexical_cast<int>(packet->GetVar("DOBYear"));
|
||
int bd_month = lexical_cast<int>(packet->GetVar("DOBMonth"));
|
||
int bd_day = lexical_cast<int>(packet->GetVar("DOBDay"));
|
||
bool isValid = false;
|
||
|
||
//have to do age check manually because boost::posix_time is too painful to use
|
||
if((lt->tm_year+1900)-bd_year > AGE_LIMIT)
|
||
isValid = true;
|
||
else if((lt->tm_year+1900)-bd_year == AGE_LIMIT)
|
||
{
|
||
if((lt->tm_mon+1) > bd_month)
|
||
isValid = true;
|
||
else if((lt->tm_mon+1) == bd_month)
|
||
{
|
||
if(lt->tm_mday >= bd_day)
|
||
isValid = true;
|
||
}
|
||
}
|
||
|
||
if(isValid)
|
||
{
|
||
tempUser.data = new string[USER_SIZE];
|
||
tempUser.data[PASSWORD] = packet->GetVar("password");
|
||
tempUser.data[COUNTRY] = packet->GetVar("country");
|
||
char buffer[12];
|
||
sprintf(buffer, "%i-%i-%i", bd_year, bd_month, bd_day);
|
||
tempUser.data[BIRTHDAY] = buffer;
|
||
tempUser.data[USER_ONLINE] = "0";
|
||
|
||
if((tempUser.id = database->addUser(tempUser)) < 0)
|
||
{
|
||
delete[] tempUser.data;
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("localizedMessage", "\"That account name is already taken\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "160");
|
||
}
|
||
else // returned id is valid so create folder for user
|
||
{
|
||
string directory = "./database/";
|
||
directory.append(tempUser.name);
|
||
filesystem::path user_dir(directory);
|
||
if(filesystem::create_directory(user_dir))
|
||
{
|
||
if(logDatabase)
|
||
debug->simpleNotification(3, DATABASE, database->listEntryToString(&tempUser, "added", true).c_str());
|
||
}
|
||
else
|
||
debug->notification(2, connectionType, "Failed to create user directory %s, check if you have access permissions for your database folder", directory.c_str());
|
||
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
}
|
||
else // new user is not old enough
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("localizedMessage", "\"The required parameters for this call are missing or invalid\"");
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("errorContainer.[]", "1");
|
||
sendPacket->SetVar("errorContainer.0.fieldName", "dob");
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "15");
|
||
sendPacket->SetVar("errorCode", "21");
|
||
}
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("NuLogin") == 0) // User is logging in with email and password
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
|
||
string buffer = packet->GetVar("nuid"), password;
|
||
if(!buffer.empty())
|
||
{
|
||
database->getUser(buffer, &user);
|
||
if(user.id > 0)
|
||
password = packet->GetVar("password");
|
||
}
|
||
else
|
||
{
|
||
string decryptedInfo = packet->GetVar("encryptedInfo");
|
||
if(!decryptedInfo.empty() && decryptedInfo.find("Ciyvab0tregdVsBtboIpeChe4G6uzC1v5_-SIxmvSL") != string::npos)
|
||
{
|
||
decryptedInfo = decryptedInfo.substr(42, decryptedInfo.size()-42); //42 is the size of that first chunk
|
||
size_t pos = 0;
|
||
while( (pos = decryptedInfo.find('-', decryptedInfo.size()-3)) != string::npos ||
|
||
(pos = decryptedInfo.find('_', decryptedInfo.size()-3)) != string::npos) // bring string into proper format again
|
||
decryptedInfo.at(pos) = '=';
|
||
|
||
decryptedInfo = base64_decode(decryptedInfo);
|
||
if((pos = decryptedInfo.find_first_of('\f')) != string::npos)
|
||
{
|
||
buffer = decryptedInfo.substr(0, pos);
|
||
password = decryptedInfo.substr(pos+1, decryptedInfo.size()-1); //skip the '\f' and dont go outside string
|
||
database->getUser(buffer, &user);
|
||
}
|
||
else
|
||
user.id = -1;
|
||
}
|
||
else
|
||
user.id = -1;
|
||
}
|
||
|
||
if(user.id > 0)
|
||
{
|
||
if(user.data[PASSWORD].compare(password) == 0)
|
||
{
|
||
if(user.data[USER_ONLINE].compare("0") == 0)
|
||
{
|
||
user_lkey = fw->randomString(27, SEED_DEFAULT);
|
||
user_lkey.append(".");
|
||
user.data[USER_ONLINE] = "1";
|
||
|
||
sendPacket->SetVar("lkey", user_lkey);
|
||
sendPacket->SetVar("nuid", user.name);
|
||
string encryptedInfo = packet->GetVar("returnEncryptedInfo");
|
||
if(!encryptedInfo.empty() && (encryptedInfo.compare("1") == 0)) //client wants to store login information
|
||
{
|
||
//Ciyvab0tregdVsBtboIpeChe4G6uzC1v5_-SIxmvSL
|
||
//Ciyvab0tregdVsBtboIpeChe4G6uzC1v5_-SIxmvSLIJIU9Vh4C77cH52ArVStN4rKMtWGByi2mOVDuM05Wj31Vit91nAbmg23z2IV4GfubCi9Owt1eBqxmXS6KrceaR
|
||
|
||
// store the user name and password as a base64 encoded string and put the chunk in front of it (so we have a similar format to the original one)
|
||
string encrypted("Ciyvab0tregdVsBtboIpeChe4G6uzC1v5_-SIxmvSL");
|
||
size_t pos = 0;
|
||
buffer.append("\f");
|
||
buffer.append(password);
|
||
buffer = base64_encode(reinterpret_cast<const unsigned char*>(buffer.c_str()), buffer.size());
|
||
|
||
pos = buffer.find('=', buffer.size()-3);
|
||
if(pos != string::npos)
|
||
{
|
||
buffer.at(pos) = '-';
|
||
pos = buffer.find('=', buffer.size()-3);
|
||
if(pos != string::npos)
|
||
buffer.at(pos) = '_';
|
||
}
|
||
|
||
encrypted.append(buffer);
|
||
sendPacket->SetVar("encryptedLoginInfo", encrypted);
|
||
//sendPacket->SetVar("encryptedLoginInfo", "Ciyvab0tregdVsBtboIpeChe4G6uzC1v5_-SIxmvSLJubxCaMWOxD1iabTkdIjA6nFyrA9nvKvtbovnovBD99T8hIHEGPkl-I9xeEXAXN9ICCmuaWcMHP6q33WjvASgI"); // is this required?
|
||
}
|
||
sendPacket->SetVar("profileId", user.id);
|
||
sendPacket->SetVar("userId", user.id);
|
||
if(logDatabase)
|
||
debug->simpleNotification(3, DATABASE, database->listEntryToString(&user, "logged in", true).c_str());
|
||
}
|
||
else // user is already online so prevent login (yes, fsys is correct here)
|
||
{
|
||
debug->notification(3, connectionType, "User %s with ID %i is already logged in, disconnecting this user...", user.name.c_str(), user.id);
|
||
delete sendPacket;
|
||
alreadyLoggedIn = true;
|
||
sendPacket = new Packet("fsys", 0x00000000);
|
||
sendPacket->SetVar("TXN", "Goodbye");
|
||
sendPacket->SetVar("reason", "2");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
sendPacket->SetVar("localizedMessage", "\"The password the user specified is incorrect\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "122");
|
||
/*sendPacket->SetVar("localizedMessage", "\"The user is not entitled to access this game\"");
|
||
sendPacket->SetVar("errorCode", "120");*/
|
||
}
|
||
}
|
||
else
|
||
{
|
||
sendPacket->SetVar("localizedMessage", "\"The user was not found\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "101");
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("NuGetPersonas") == 0) // Display all Personas to the User
|
||
{
|
||
list<list_entry> personas;
|
||
database->listMatchingPersonas(USER_ID, lexical_cast<string>(user.id), &personas);
|
||
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("personas.[]", (int)personas.size());
|
||
int i = 0;
|
||
while(!personas.empty())
|
||
{
|
||
string buffer = "personas.";
|
||
buffer.append(lexical_cast<string>(i));
|
||
sendPacket->SetVar(buffer, personas.front().name);
|
||
personas.pop_front();
|
||
i++;
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("NuLoginPersona") == 0) // User logs in with selected Persona
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
if(!database->getPersona(packet->GetVar("name"), &persona))
|
||
{
|
||
sendPacket->SetVar("localizedMessage", "\"The user was not found\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "101");
|
||
}
|
||
else
|
||
{
|
||
persona_lkey = fw->randomString(27, SEED_DEFAULT);
|
||
persona_lkey.append(".");
|
||
persona.data[PERSONA_ONLINE] = "1";
|
||
|
||
sendPacket->SetVar("lkey", persona_lkey);
|
||
sendPacket->SetVar("profileId", persona.id);
|
||
sendPacket->SetVar("userId", persona.id);
|
||
|
||
linked_key lkey_id = {persona.id, persona_lkey};
|
||
database->personaLogin(lkey_id);
|
||
if(logDatabase)
|
||
debug->simpleNotification(3, DATABASE, database->listEntryToString(&persona, "logged in", false).c_str());
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("NuAddPersona") == 0) // User wants to add a Persona
|
||
{
|
||
string name = packet->GetVar("name");
|
||
int realSize = name.size();
|
||
int pos = -1;
|
||
while((pos = name.find_first_of('%', pos+1)) != (int)string::npos)
|
||
realSize -= 2;
|
||
|
||
if(realSize > 16 || realSize < 3) // entered persona name length is out of bounds (old: 4 <= name <= 16)
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("errorContainer.[]", "1");
|
||
sendPacket->SetVar("errorCode", "21");
|
||
sendPacket->SetVar("localizedMessage", "\"The required parameters for this call are missing or invalid\"");
|
||
sendPacket->SetVar("errorContainer.0.fieldName", "displayName");
|
||
if(realSize > 16)
|
||
{
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "3");
|
||
sendPacket->SetVar("errorContainer.0.value", "TOO_LONG");
|
||
}
|
||
else
|
||
{
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "2");
|
||
sendPacket->SetVar("errorContainer.0.value", "TOO_SHORT");
|
||
}
|
||
} //forbidden chars due to file creation incompatibilities
|
||
else if(name.find_first_of('/') != string::npos || name.find_first_of('\\') != string::npos || name.find_first_of('?') != string::npos ||
|
||
name.find_first_of('*') != string::npos || name.find_first_of('\"') != string::npos || name.find_first_of('|') != string::npos ||
|
||
name.find_first_of(':') != string::npos ||name.find_first_of('<') != string::npos || name.find_first_of('>') != string::npos)
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("errorContainer.[]", "1");
|
||
sendPacket->SetVar("errorCode", "21");
|
||
sendPacket->SetVar("localizedMessage", "\"The required parameters for this call are missing or invalid\"");
|
||
sendPacket->SetVar("errorContainer.0.fieldName", "displayName");
|
||
sendPacket->SetVar("errorContainer.0.fieldError", "6");
|
||
sendPacket->SetVar("errorContainer.0.value", "NOT_ALLOWED");
|
||
}
|
||
else //valid data, check if name is unique
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
|
||
list_entry tempPersona;
|
||
tempPersona.name = name;
|
||
tempPersona.data = new string[PERSONA_SIZE];
|
||
tempPersona.data[USER_ID] = lexical_cast<string>(user.id);
|
||
tempPersona.data[USER_EMAIL] = user.name;
|
||
tempPersona.data[PLAYER_ID] = "0";
|
||
tempPersona.data[PERSONA_ONLINE] = "0";
|
||
|
||
if((tempPersona.id = database->addPersona(tempPersona)) < 0) //name already exists
|
||
{
|
||
delete[] tempPersona.data;
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("localizedMessage", "\"That account name is already taken\"");
|
||
sendPacket->SetVar("errorCode", "160");
|
||
}
|
||
else // persona added, create a default stats file for it
|
||
{
|
||
// will tempStats be "deleted" when we leave this function? I sure hope so!
|
||
Stats tempStats = Stats(user.name, name, true);
|
||
if(logDatabase)
|
||
debug->simpleNotification(3, DATABASE, database->listEntryToString(&tempPersona, "added", false).c_str());
|
||
}
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("NuDisablePersona") == 0) // User wants to remove a Persona
|
||
{
|
||
list_entry temp;
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
|
||
bool valid = false;
|
||
string name = packet->GetVar("name");
|
||
if(!database->getPersona(name, &temp))
|
||
{
|
||
sendPacket->SetVar("localizedMessage", "\"The data necessary for this transaction was not found\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "104");
|
||
}
|
||
else
|
||
{
|
||
if(user.id != lexical_cast<int>(temp.data[USER_ID]))
|
||
{
|
||
sendPacket->SetVar("localizedMessage", "\"The data necessary for this transaction was not found\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "104");
|
||
}
|
||
else
|
||
valid = true;
|
||
}
|
||
|
||
if(valid)
|
||
{
|
||
database->removePersona(name);
|
||
Stats tempStats = Stats(user.name, name, false, true);
|
||
tempStats.deleteStats();
|
||
}
|
||
}
|
||
|
||
else if(txn.compare("GetTelemetryToken") == 0)
|
||
{
|
||
//TODO: make the telemetry token database
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
|
||
//sendPacket->SetVar("telemetryToken", "MTU5LjE1My4yMzUuMjYsOTk0NixlblVTLF7ZmajcnLfGpKSJk53K/4WQj7LRw9asjLHvxLGhgoaMsrDE3bGWhsyb4e6woYKGjJiw4MCBg4bMsrnKibuDppiWxYKditSp0amvhJmStMiMlrHk4IGzhoyYsO7A4dLM26rTgAo%3d");
|
||
//changed ip to ip of the emulator, port remains the same (9946?)
|
||
size_t pos = 0;
|
||
string token = emuIp;
|
||
if(lexical_cast<int>(fw->portsCfg().emulator_port) <= 0)
|
||
token = "127.0.0.1";
|
||
token.append(",");
|
||
token.append(fw->portsCfg().emulator_port);
|
||
token.append(",enUS,^ٙ<>ܜ<EFBFBD>Ƥ<EFBFBD><C6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֬<EFBFBD><D6AC><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>̛<EFBFBD><EFBFBD><EEB0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̲<EFBFBD>ʉ<EFBFBD><CA89><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><C582>ԩѩ<D4A9><D1A9><EFBFBD><EFBFBD><EFBFBD>Ȍ<EFBFBD><C88C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۪Ӏ");
|
||
token = base64_encode(reinterpret_cast<const unsigned char*>(token.c_str()), token.size());
|
||
while((pos = token.find('=', token.size()-9)) != string::npos) // bring string into proper format again
|
||
token.replace(pos, 1, "%3d");
|
||
|
||
sendPacket->SetVar("telemetryToken", token);
|
||
sendPacket->SetVar("enabled", "CA,MX,PR,US,VI,AD,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AW,AX,AZ,BA,BB,BD,BF,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CC,CD,CF,CG,CI,CK,CL,CM,CN,CO,CR,CU,CV,CX,DJ,DM,DO,DZ,EC,EG,EH,ER,ET,FJ,FK,FM,FO,GA,GD,GE,GF,GG,GH,GI,GL,GM,GN,GP,GQ,GS,GT,GU,GW,GY,HM,HN,HT,ID,IL,IM,IN,IO,IQ,IR,IS,JE,JM,JO,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,LY,MA,MC,MD,ME,MG,MH,ML,MM,MN,MO,MP,MQ,MR,MS,MU,MV,MW,MY,MZ,NA,NC,NE,NF,NG,NI,NP,NR,NU,OM,PA,PE,PF,PG,PH,PK,PM,PN,PS,PW,PY,QA,RE,RS,RW,SA,SB,SC,clntSock,SG,SH,SJ,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TL,TM,TN,TO,TT,TV,TZ,UA,UG,UM,UY,UZ,VA,VC,VE,VG,VN,VU,WF,WS,YE,YT,ZM,ZW,ZZ");
|
||
sendPacket->SetVar("filters", "");
|
||
sendPacket->SetVar("disabled", "");
|
||
}
|
||
|
||
else if(txn.compare("NuGetEntitlements") == 0)
|
||
{
|
||
string groupName = packet->GetVar("groupName");
|
||
if(groupName.compare("BFBC2PC") == 0)
|
||
{
|
||
//TODO: make the BFBC2 entitlements database
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
int count = 0;
|
||
char buffer[36];
|
||
if(fw->emuCfg().vietnam_for_all)
|
||
{
|
||
sendPacket->SetVar("entitlements.0.grantDate", "2010-12-21T22%3a34Z");
|
||
sendPacket->SetVar("entitlements.0.groupName", groupName);
|
||
sendPacket->SetVar("entitlements.0.userId", user.id);
|
||
sendPacket->SetVar("entitlements.0.entitlementTag", "BFBC2%3aPC%3aVIETNAM_ACCESS");
|
||
sendPacket->SetVar("entitlements.0.version", "0");
|
||
sendPacket->SetVar("entitlements.0.terminationDate", "");
|
||
sendPacket->SetVar("entitlements.0.productId", "DR%3a219316800");
|
||
sendPacket->SetVar("entitlements.0.entitlementId", "1");
|
||
sendPacket->SetVar("entitlements.0.status", "ACTIVE");
|
||
|
||
sendPacket->SetVar("entitlements.1.grantDate", "2010-12-21T22%3a34Z");
|
||
sendPacket->SetVar("entitlements.1.statusReasonCode", "");
|
||
sendPacket->SetVar("entitlements.1.groupName", groupName);
|
||
sendPacket->SetVar("entitlements.1.userId", user.id);
|
||
sendPacket->SetVar("entitlements.1.entitlementTag", "BFBC2%3aPC%3aVIETNAM_PDLC");
|
||
sendPacket->SetVar("entitlements.1.version", "0");
|
||
sendPacket->SetVar("entitlements.1.terminationDate", "");
|
||
sendPacket->SetVar("entitlements.1.productId", "DR%3a219316800");
|
||
sendPacket->SetVar("entitlements.1.entitlementId", "2");
|
||
sendPacket->SetVar("entitlements.1.status", "ACTIVE");
|
||
|
||
count += 2;
|
||
}
|
||
if(fw->emuCfg().premium_for_all)
|
||
{
|
||
// need a buffer here to write the entitlement index number because this can vary
|
||
sprintf(buffer, "entitlements.%i.grantDate", count);
|
||
sendPacket->SetVar(buffer, "2010-12-21T22%3a34Z");
|
||
sprintf(buffer, "entitlements.%i.statusReasonCode", count);
|
||
sendPacket->SetVar(buffer, "");
|
||
sprintf(buffer, "entitlements.%i.groupName", count);
|
||
sendPacket->SetVar(buffer, groupName);
|
||
sprintf(buffer, "entitlements.%i.userId", count);
|
||
sendPacket->SetVar(buffer, user.id);
|
||
sprintf(buffer, "entitlements.%i.entitlementTag", count);
|
||
sendPacket->SetVar(buffer, "BFBC2%3aPC%3aLimitedEdition");
|
||
sprintf(buffer, "entitlements.%i.version", count);
|
||
sendPacket->SetVar(buffer, "1");
|
||
sprintf(buffer, "entitlements.%i.terminationDate", count);
|
||
sendPacket->SetVar(buffer, "");
|
||
sprintf(buffer, "entitlements.%i.productId", count);
|
||
sendPacket->SetVar(buffer, "OFB-BFBC%3a19120");
|
||
sprintf(buffer, "entitlements.%i.entitlementId", count);
|
||
sendPacket->SetVar(buffer, "3");
|
||
sprintf(buffer, "entitlements.%i.status", count);
|
||
sendPacket->SetVar(buffer, "ACTIVE");
|
||
count++;
|
||
}
|
||
if(fw->emuCfg().specact_for_all)
|
||
{
|
||
sprintf(buffer, "entitlements.%i.grantDate", count);
|
||
sendPacket->SetVar(buffer, "2010-12-21T22%3a34Z");
|
||
sprintf(buffer, "entitlements.%i.statusReasonCode", count);
|
||
sendPacket->SetVar(buffer, "");
|
||
sprintf(buffer, "entitlements.%i.groupName", count);
|
||
sendPacket->SetVar(buffer, groupName);
|
||
sprintf(buffer, "entitlements.%i.userId", count);
|
||
sendPacket->SetVar(buffer, user.id);
|
||
sprintf(buffer, "entitlements.%i.entitlementTag", count);
|
||
sendPacket->SetVar(buffer, "BFBC2%3aPC%3aALLKIT");
|
||
sprintf(buffer, "entitlements.%i.version", count);
|
||
sendPacket->SetVar(buffer, "0");
|
||
sprintf(buffer, "entitlements.%i.terminationDate", count);
|
||
sendPacket->SetVar(buffer, "");
|
||
sprintf(buffer, "entitlements.%i.productId", count);
|
||
sendPacket->SetVar(buffer, "DR%3a192365600");
|
||
sprintf(buffer, "entitlements.%i.entitlementId", count);
|
||
sendPacket->SetVar(buffer, "4");
|
||
sprintf(buffer, "entitlements.%i.status", count);
|
||
sendPacket->SetVar(buffer, "ACTIVE");
|
||
count++;
|
||
}
|
||
sendPacket->SetVar("entitlements.[]", count);
|
||
}
|
||
else if(groupName.compare("AddsVetRank") == 0)
|
||
{
|
||
//TODO: make the AddsVetRank entitlements database
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("entitlements.0.statusReasonCode", "");
|
||
sendPacket->SetVar("entitlements.0.groupName", "AddsVetRank");
|
||
sendPacket->SetVar("entitlements.0.grantDate", "2011-07-30T0%3a11Z");
|
||
sendPacket->SetVar("entitlements.0.version", "0");
|
||
sendPacket->SetVar("entitlements.0.entitlementId", "1114495162");
|
||
sendPacket->SetVar("entitlements.0.terminationDate", "");
|
||
sendPacket->SetVar("entitlements.0.productId", "");
|
||
sendPacket->SetVar("entitlements.0.entitlementTag", "BFBC2%3aPC%3aADDSVETRANK");
|
||
sendPacket->SetVar("entitlements.0.status", "ACTIVE");
|
||
sendPacket->SetVar("entitlements.0.userId", user.id);
|
||
if(fw->emuCfg().all_players_are_veterans)
|
||
{
|
||
sendPacket->SetVar("entitlements.1.statusReasonCode", "");
|
||
sendPacket->SetVar("entitlements.1.groupName", "AddsVetRank");
|
||
sendPacket->SetVar("entitlements.1.grantDate", "2011-10-27T6%3a49Z");
|
||
sendPacket->SetVar("entitlements.1.version", "0");
|
||
sendPacket->SetVar("entitlements.1.entitlementId", "1272849755");
|
||
sendPacket->SetVar("entitlements.1.terminationDate", "");
|
||
sendPacket->SetVar("entitlements.1.productId", "OFB-EAST%3a40873");
|
||
sendPacket->SetVar("entitlements.1.entitlementTag", "BF3%3aPC%3aADDSVETRANK");
|
||
sendPacket->SetVar("entitlements.1.status", "ACTIVE");
|
||
sendPacket->SetVar("entitlements.1.userId", user.id);
|
||
sendPacket->SetVar("entitlements.[]", "2");
|
||
}
|
||
else
|
||
sendPacket->SetVar("entitlements.[]", "1");
|
||
}
|
||
else
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("entitlements.[]", "0");
|
||
}
|
||
/*else if(groupName.compare("BattlefieldBadCompany2") == 0)
|
||
{
|
||
//TODO: make the BattlefieldBadCompany2 entitlements database
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("entitlements.[]", "0");
|
||
}
|
||
else if(groupName.compare("NoVetRank") == 0)
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("entitlements.[]", "0");
|
||
}
|
||
else
|
||
{
|
||
debug->warning(1, connectionType, "Could not handle TXN=%s group=%s", txn.c_str(), groupName.c_str());
|
||
return true;
|
||
}*/
|
||
}
|
||
|
||
else if(txn.compare("NuGrantEntitlement") == 0) //is this ever called from the client?
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
|
||
else if(txn.compare("GetLockerURL") == 0)
|
||
{
|
||
//URL=http%3a//bfbc2.gos.ea.com/fileupload/locker2.jsp
|
||
string url = "http%3a//";
|
||
if(fw->portsCfg().use_http)
|
||
url.append(emuIp);
|
||
else
|
||
url.append("127.0.0.1");
|
||
url.append("/fileupload/locker2.jsp");
|
||
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("URL", url);
|
||
}
|
||
|
||
else if(txn.compare("NuSearchOwners") == 0) // User searches for Persona name
|
||
{
|
||
string screenName = packet->GetVar("screenName");
|
||
list_entry tempPersona;
|
||
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
if(!database->getPersona(screenName, &tempPersona))
|
||
{
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "104");
|
||
sendPacket->SetVar("localizedMessage", "\"The data necessary for this transaction was not found\"");
|
||
}
|
||
else
|
||
{
|
||
// todo: check what to do here if persona was found (above msg is correct)
|
||
/*
|
||
<-TXN=NuSearchOwners
|
||
screenName=ugahbugah
|
||
searchType=1
|
||
retrieveUserIds=0
|
||
|
||
->users.[]=1
|
||
users.0.id=838297533
|
||
TXN=NuSearchOwners
|
||
users.0.name=UgaHBugaH
|
||
nameSpaceId=battlefield
|
||
users.0.type=1*/
|
||
}
|
||
//sendPacket->SetVar("retrieveUserIds", (int)result->rowsCount());
|
||
}
|
||
else if(txn.compare("NuEntitleGame") == 0) // User wants to register himself
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
/*localizedMessage="The user is not entitled to access this game"
|
||
errorContainer.[]=0
|
||
errorCode=120*/
|
||
//todo: capture this packet (with a valid code) and implement it
|
||
}
|
||
else if(txn.compare("NuEntitleUser") == 0) // User wants to redeem a code
|
||
{
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "181");
|
||
sendPacket->SetVar("localizedMessage", "\"The code is not valid for registering this game\"");
|
||
//sendPacket->SetVar("TXN", "NuGrantEntitlement");
|
||
//todo: capture this packet (with a valid code) and implement it
|
||
}
|
||
else if(txn.compare("NuLookupUserInfo") == 0)
|
||
{
|
||
string playerPersonaName = packet->GetVar("userInfo.0.userName");
|
||
list_entry result;
|
||
sendPacket = new Packet("acct", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
|
||
if(database->getPersona(playerPersonaName, &result))
|
||
{
|
||
sendPacket->SetVar("userInfo.[]", "1");
|
||
sendPacket->SetVar("userInfo.0.userName", playerPersonaName);
|
||
sendPacket->SetVar("userInfo.0.namespace", "battlefield");
|
||
sendPacket->SetVar("userInfo.0.userId", result.id); //persona id
|
||
sendPacket->SetVar("userInfo.0.masterUserId", result.data[USER_ID]);
|
||
}
|
||
else
|
||
{
|
||
sendPacket->SetVar("userInfo.[]", "1");
|
||
sendPacket->SetVar("userInfo.0.userName", playerPersonaName);
|
||
}
|
||
}
|
||
else
|
||
return true;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
bool GameClient::asso(list<Packet*>* queue, Packet* packet, string txn)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
|
||
if(txn.compare("AddAssociations") == 0)
|
||
{
|
||
sendPacket = new Packet("asso", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("type", packet->GetVar("type"));
|
||
sendPacket->SetVar("result.[]", "0");
|
||
sendPacket->SetVar("domainPartition.domain", "eagames");
|
||
sendPacket->SetVar("domainPartition.subDomain", "BFBC2");
|
||
sendPacket->SetVar("maxListSize", "100");
|
||
}
|
||
|
||
else if(txn.compare("GetAssociations") == 0)
|
||
{
|
||
string type = packet->GetVar("type");
|
||
sendPacket = new Packet("asso", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("type", type);
|
||
sendPacket->SetVar("domainPartition.domain", packet->GetVar("domainPartition.domain"));
|
||
sendPacket->SetVar("domainPartition.subDomain", packet->GetVar("domainPartition.subDomain"));
|
||
sendPacket->SetVar("owner.id", persona.id);
|
||
sendPacket->SetVar("owner.name", persona.name);
|
||
sendPacket->SetVar("owner.type", "1");
|
||
|
||
if(type.compare("PlasmaMute") == 0)
|
||
{
|
||
//TODO: make the mute list database
|
||
sendPacket->SetVar("maxListSize", "20");
|
||
sendPacket->SetVar("members.[]", "0");
|
||
}
|
||
else if(type.compare("PlasmaBlock") == 0)
|
||
{
|
||
//TODO: make the block list database
|
||
sendPacket->SetVar("maxListSize", "20");
|
||
sendPacket->SetVar("members.[]", "0");
|
||
}
|
||
else if(type.compare("PlasmaFriends") == 0)
|
||
{
|
||
//TODO: make the friends list database
|
||
sendPacket->SetVar("maxListSize", "20");
|
||
sendPacket->SetVar("members.[]", "0");
|
||
/*members.[]=6
|
||
members.0.id=243057189
|
||
members.0.name=Ragetank
|
||
members.0.type=1
|
||
members.0.created="Aug-03-2011 09%3a38%3a08 UTC"
|
||
members.0.modified="Aug-03-2011 09%3a38%3a08 UTC"
|
||
members.1.id=245421566
|
||
members.1.name=-MrFrost.-
|
||
members.1.type=1
|
||
members.1.created="Aug-03-2011 09%3a38%3a18 UTC"
|
||
members.1.modified="Aug-03-2011 09%3a38%3a18 UTC"
|
||
members.2.name=Mr.Mustang
|
||
members.2.id=239645767
|
||
members.2.type=1
|
||
members.2.created="Dec-22-2010 00%3a48%3a19 UTC"
|
||
members.2.modified="Dec-22-2010 00%3a48%3a19 UTC"
|
||
members.3.id=329836197
|
||
members.3.name=Drnegative16
|
||
members.3.type=1
|
||
members.3.created="Jul-30-2011 00%3a11%3a06 UTC"
|
||
members.3.modified="Jul-30-2011 00%3a11%3a06 UTC"
|
||
members.4.id=286375350
|
||
members.4.name=Gen.RoadRunner
|
||
members.4.type=1
|
||
members.4.created="Dec-27-2010 10%3a44%3a31 UTC"
|
||
members.4.modified="Dec-27-2010 10%3a44%3a32 UTC"
|
||
members.5.id=335897299
|
||
members.5.name=BaaldEagle
|
||
members.5.type=1
|
||
members.5.created="Jan-26-2012 10%3a18%3a49 UTC"
|
||
members.5.modified="Jan-26-2012 10%3a18%3a49 UTC"*/
|
||
}
|
||
else if(type.compare("PlasmaRecentPlayers") == 0)
|
||
{
|
||
//TODO: make the recent list database
|
||
sendPacket->SetVar("maxListSize", "100");
|
||
sendPacket->SetVar("members.[]", "0");
|
||
}
|
||
else
|
||
debug->warning(1, connectionType, "Could not handle TXN=%s type=%s", txn.c_str(), type.c_str());
|
||
}
|
||
else
|
||
return true;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return false;
|
||
}
|
||
|
||
bool GameClient::xmsg(list<Packet*>* queue, Packet* packet, string txn)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
|
||
if(txn.compare("ModifySettings") == 0)
|
||
{
|
||
//TODO: modify settings in database
|
||
sendPacket = new Packet("xmsg", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
|
||
else if(txn.compare("SendMessage") == 0) //friend request is being sent
|
||
{
|
||
sendPacket = new Packet("xmsg", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("status.0.status", "0");
|
||
sendPacket->SetVar("status.[]", "1");
|
||
sendPacket->SetVar("status.0.userid", packet->GetVar("to.0"));
|
||
sendPacket->SetVar("messageId", "1"); //need to make unique id's for the message?
|
||
/*localizedMessage="Message recipients/to invalid"
|
||
errorContainer.[]=0
|
||
TXN=SendMessage
|
||
errorCode=22006
|
||
|
||
<-TXN=SendMessage
|
||
messageType=invite/friend
|
||
to.[]=1
|
||
to.0=838297533
|
||
attachments.0.key=response
|
||
attachments.0.type=text/plain
|
||
attachments.0.data="27,1"
|
||
attachments.[]=1
|
||
expires=2592000
|
||
deliveryType=standard
|
||
purgeStrategy=all-recipients
|
||
|
||
->status.0.status=0
|
||
TXN=SendMessage
|
||
status.[]=1
|
||
status.0.userid=838297533
|
||
messageId=289421781.
|
||
*/
|
||
}
|
||
|
||
else if(txn.compare("GetMessages") == 0)
|
||
{
|
||
//are there any friend requests?
|
||
sendPacket = new Packet("xmsg", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("messages.[]", "0");
|
||
/*xmsg..."...^messages.0.from.type=1
|
||
messages.0.attachments.0.type=text/plain
|
||
messages.0.messageType=inviteresp/friend
|
||
messages.0.from.name=StonySniper
|
||
messages.0.purgeStrategy=all-recipients
|
||
messages.[]=1
|
||
messages.0.deliveryType=standard
|
||
messages.0.messageId=284890756
|
||
messages.0.timeSent="Jan-17-2013 21%3a26%3a22 UTC"
|
||
messages.0.attachments.0.key=response
|
||
messages.0.to.0.name=-%3dRick%3d-
|
||
messages.0.to.0.id=272593863
|
||
messages.0.to.[]=1
|
||
messages.0.expiration=2592000
|
||
messages.0.from.id=791406346
|
||
TXN=GetMessages
|
||
messages.0.attachments.[]=1
|
||
messages.0.to.0.type=1
|
||
messages.0.attachments.0.data=accepted*/
|
||
}
|
||
else
|
||
return true;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return false;
|
||
}
|
||
|
||
bool GameClient::pres(list<Packet*>* queue, Packet* packet, string txn)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
|
||
if(txn.compare("PresenceSubscribe") == 0) //is called when client has friends - one packet request for each friend
|
||
{
|
||
sendPacket = new Packet("pres", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("responses.[]", "1");
|
||
sendPacket->SetVar("responses.0.outcome", "0");
|
||
sendPacket->SetVar("responses.0.owner.type", "0");
|
||
sendPacket->SetVar("responses.0.owner.id", packet->GetVar("requests.0.userId"));
|
||
sendPacket->SetVar("responses.0.owner.name", "player");
|
||
//(maybe multiple responses if client has multiple personas from same user as friend?)
|
||
}
|
||
|
||
else if(txn.compare("SetPresenceStatus") == 0)
|
||
{
|
||
//TODO: make the Presence Status database
|
||
sendPacket = new Packet("pres", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
else
|
||
return true;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return false;
|
||
}
|
||
|
||
bool GameClient::recp(list<Packet*>* queue, Packet* packet, string txn)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
|
||
if(txn.compare("GetRecord") == 0)
|
||
{
|
||
//TODO: find out what it is, and what to do with it - no difference to logged packets
|
||
// recordName=clan
|
||
sendPacket = new Packet("recp", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("localizedMessage", "\"Record not found\"");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("errorCode", "5000");
|
||
}
|
||
|
||
else if(txn.compare("GetRecordAsMap") == 0) // get all dogtags the persona possesses
|
||
{
|
||
stats_data = new Stats(user.name, persona.name, false, true);
|
||
int count = stats_data->loadDogtags();
|
||
|
||
sendPacket = new Packet("recp", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
sendPacket->SetVar("TTL", "0");
|
||
sendPacket->SetVar("state", "1");
|
||
|
||
if(count > 0)
|
||
{
|
||
sendPacket->SetVar("values.{}", count);
|
||
sendPacket->SetVar("lastModified", "2011-03-08 09%3a43%3a35.0"); // todo: access the last modified time of the dogtag file and use it here
|
||
Stats::dogtag entry;
|
||
for(int i = 1; i <= count; i++) // loadDogtags() returns a 1 based value
|
||
{
|
||
string buffer;
|
||
entry = stats_data->getDogtag(i);
|
||
buffer = "values.{";
|
||
buffer.append(entry.id);
|
||
buffer.append("}");
|
||
sendPacket->SetVar(buffer, entry.data);
|
||
}
|
||
}
|
||
else
|
||
sendPacket->SetVar("values.{}", "0");
|
||
|
||
delete stats_data;
|
||
stats_data = NULL;
|
||
}
|
||
|
||
else if(txn.compare("AddRecord") == 0) //is called when player gets an enemy dogtag that he hasn't yet?...packet response should be fine though
|
||
{ //or maybe this adds a new record for a player that isn't in the database yet? I got this when I wanted to play with my new persona
|
||
//todo: implement dogtags
|
||
/*TXN=AddRecord
|
||
recordName=dogtags
|
||
values.[]=1
|
||
values.0.key=298916317
|
||
values.0.value=S0lMTEVSQk9XIChOTCkAABaS5kQAAAEAAAAjAA%3d%3d
|
||
TTL=0*/
|
||
sendPacket = new Packet("recp", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
else if(txn.compare("UpdateRecord") == 0) //is called when a player gets an enemy dogtag but already has some of them (then why was this called during testing)? (thats at least one action that triggers this) - packet response should be fine though
|
||
{
|
||
//todo: implement dogtags
|
||
/*TXN=UpdateRecord
|
||
recordName=dogtags
|
||
values.[]=1
|
||
values.0.key=334048277
|
||
values.0.value=U3phbWFuMTg1X1BMAAAAAC+S5kQAAAEAAAAdAA%3d%3d
|
||
TTL=0
|
||
remove.[]=0*/
|
||
Stats::dogtag newDogtag;
|
||
newDogtag.id = packet->GetVar("values.0.key");
|
||
newDogtag.data = packet->GetVar("values.0.value");
|
||
|
||
stats_data = new Stats(user.name, persona.name, false, true);
|
||
stats_data->loadDogtags();
|
||
stats_data->addDogtag(newDogtag);
|
||
stats_data->saveDogtags();
|
||
delete stats_data;
|
||
stats_data = NULL;
|
||
|
||
sendPacket = new Packet("recp", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
else
|
||
return true;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return false;
|
||
}
|
||
|
||
bool GameClient::pnow(list<Packet*>* queue, Packet* packet, string txn)
|
||
{
|
||
|
||
Packet* sendPacket = NULL;
|
||
if(txn.compare("Start") == 0) // User wants us to select a server for him to automatically join
|
||
{
|
||
sendPacket = new Packet("pnow", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
//int id = rand() % 5000 + 1;
|
||
string id = "1";
|
||
sendPacket->SetVar("id.id", id); // what id is this? for now put constant number
|
||
sendPacket->SetVar("id.partition", "/eagames/BFBC2");
|
||
queue->push_back(sendPacket);
|
||
|
||
sendPacket = new Packet("pnow", 0x80000000, false);
|
||
sendPacket->SetVar("TXN", "Status");
|
||
sendPacket->SetVar("id.id", id);
|
||
sendPacket->SetVar("id.partition", "/eagames/BFBC2");
|
||
sendPacket->SetVar("sessionState", "COMPLETE");
|
||
sendPacket->SetVar("props.{}", "2");
|
||
sendPacket->SetVar("props.{resultType}", "JOIN");
|
||
|
||
list<linked_key> filters;
|
||
linked_key tempFilter;
|
||
list<int> filtered;
|
||
|
||
string temp = packet->GetVar("players.0.props.{filter-gameMod}");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = GAME_MOD;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
temp = packet->GetVar("players.0.props.{filter-gamemode}");
|
||
if(!temp.empty() && temp.find_first_of('|') == string::npos) // if a '|' is in the string then all game modes are allowed so we dont need to filter
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = GAMEMODE;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
temp = packet->GetVar("players.0.props.{pref-level}");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = SERVER_LEVEL;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
database->listMatchingGames(&filters, &filtered);
|
||
|
||
if(!filtered.empty())
|
||
{
|
||
sendPacket->SetVar("props.{games}.0.fit", "1001");
|
||
sendPacket->SetVar("props.{games}.0.gid", filtered.front());
|
||
sendPacket->SetVar("props.{games}.0.lid", database->getLobbyInfo(LOBBY_ID));
|
||
sendPacket->SetVar("props.{games}.[]", "1"); // we only filter one game out
|
||
}
|
||
else
|
||
sendPacket->SetVar("props.{games}.[]", "0");
|
||
}
|
||
else
|
||
return true;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return false;
|
||
}
|
||
|
||
int GameClient::rank(list<Packet*>* queue, Packet* packet, string txn)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
int state = NORMAL;
|
||
|
||
if(txn.compare("GetStats") == 0) // get Stats for current persona
|
||
{
|
||
stats_data = new Stats(user.name, persona.name);
|
||
sendPacket = new Packet("rank", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
|
||
string buffer = packet->GetVar("keys.[]");
|
||
int count = lexical_cast<int>(buffer);
|
||
sendPacket->SetVar("stats.[]", buffer);
|
||
|
||
char iterBuf[24];
|
||
for(int i = 0; i < count; i++)
|
||
{
|
||
sprintf(iterBuf, "keys.%i", i);
|
||
buffer = packet->GetVar(iterBuf);
|
||
string value = stats_data->getKey(buffer);
|
||
|
||
sprintf(iterBuf, "stats.%i.key", i);
|
||
sendPacket->SetVar(iterBuf, buffer);
|
||
|
||
sprintf(iterBuf, "stats.%i.value", i);
|
||
sendPacket->SetVar(iterBuf, value);
|
||
}
|
||
delete stats_data;
|
||
stats_data = NULL;
|
||
}
|
||
|
||
else if(txn.compare("UpdateStats") == 0)
|
||
{
|
||
//this is coming sometimes from the server (not on EA though?) so we have to accept only u.0.ot=1 to ignore that case
|
||
//rank 0xc000001c {TXN=UpdateStats, u.0.o=100, u.0.ot=11, u.0.s.[]=1, u.0.s.0.ut=3, u.0.s.0.k=veteran, u.0.s.0.v=1.0000, u.0.s.0.pt=0, u.[]=1}
|
||
if(packet->GetVar("u.0.ot").compare("1") == 0)// && !fw->emuCfg().override_stats_with_template)
|
||
{
|
||
int playerPersonaId = lexical_cast<int>(packet->GetVar("u.0.o"));
|
||
list_entry result;
|
||
|
||
if(database->getPersona(playerPersonaId, &result))
|
||
{
|
||
Stats* stats_data = new Stats(result.data[USER_EMAIL], result.name);
|
||
int count = lexical_cast<int>(packet->GetVar("u.0.s.[]"));
|
||
double temp_score = 0.0f;
|
||
char buffer[16];
|
||
|
||
for(int i = 0; i < count; i++)
|
||
{
|
||
sprintf(buffer, "u.0.s.%i.k", i); //is now key name
|
||
string key = packet->GetVar(buffer);
|
||
sprintf(buffer, "u.0.s.%i.ut", i);
|
||
int updateMethod = lexical_cast<int>(packet->GetVar(buffer));
|
||
sprintf(buffer, "u.0.s.%i.v", i); //is now value of key
|
||
string value = packet->GetVar(buffer);
|
||
string old = stats_data->getKey(key);
|
||
|
||
if(updateMethod == 3 && !old.empty() && !value.empty()) //1 = absolute value, 3 = relative value, 0 = absolute value (should round it)
|
||
{
|
||
double old_value = atof(old.c_str());
|
||
double new_value = atof(value.c_str());
|
||
|
||
if(key.compare("sc_assault") == 0 || key.compare("sc_award") == 0 || key.compare("sc_demo") == 0 || key.compare("sc_recon") == 0 || key.compare("sc_support") == 0 || key.compare("sc_vehicle") == 0)
|
||
{
|
||
temp_score += new_value;
|
||
//debug->notification(3, connectionType, "Score relevant key \"%s\", value=%.4f, temp_score=%.4f", key.c_str(), new_value, temp_score);
|
||
}
|
||
|
||
new_value += old_value;
|
||
sprintf(buffer, "%.4f", new_value);
|
||
value = buffer;
|
||
}
|
||
strcpy(buffer, old.c_str());
|
||
debug->notification(3, connectionType, "Updated key %s with value \"%s\", old value=\"%s\", updateMethod=%i", key.c_str(), value.c_str(), buffer, updateMethod);
|
||
stats_data->setKey(key, value, true);
|
||
// normally only webstats related keys are not found
|
||
/*if(!stats_data->setKey(key, value, true)) // store which keys were not found
|
||
{
|
||
fstream file("./templates/ignoredKeys", fstream::in | fstream::out);
|
||
if(file.is_open() && file.good())
|
||
{
|
||
stringstream strmbuf;
|
||
strmbuf << file.rdbuf();
|
||
string unknownKeys = strmbuf.str();
|
||
key.insert(0, "\"");
|
||
key.append("\"\n");
|
||
int result = unknownKeys.find(key, 0);
|
||
if(result == string::npos)
|
||
file.write(key.c_str(), key.size());
|
||
|
||
file.close();
|
||
key.pop_back(); //we dont want the newline at the end to be printed
|
||
//key.erase(key.size()-1, 1);
|
||
if(result != string::npos)
|
||
debug->notification(4, connectionType, "Key %s is already in ignoredKeys file", key.c_str());
|
||
else
|
||
debug->notification(3, connectionType, "Added key %s to ignoredKeys file", key.c_str());
|
||
}
|
||
}*/
|
||
}
|
||
|
||
if(temp_score != 0.0f)
|
||
{
|
||
double score = atof(stats_data->getKey("score").c_str());
|
||
score += temp_score;
|
||
sprintf(buffer, "%.4f", score);
|
||
stats_data->setKey("score", buffer);
|
||
}
|
||
stats_data->saveStats();
|
||
delete stats_data;
|
||
}
|
||
else
|
||
debug->warning(1, connectionType, "Couldn't find persona id %i in database!!", playerPersonaId);
|
||
}
|
||
|
||
sendPacket = new Packet("rank", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
}
|
||
|
||
else if(txn.compare("GetRankedStats") == 0) // User wants to see worldwide Stats
|
||
{
|
||
sendPacket = new Packet("rank", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
// not sure why this is being sent but it's like this in the logged traffic
|
||
sendPacket->SetVar("errorCode", "99");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("localizedMessage", "\"System Error\"");
|
||
/*
|
||
<-TXN=GetRankedStats
|
||
owner=230518387
|
||
ownerType=1
|
||
periodId=0
|
||
periodPast=0
|
||
keys.0=score
|
||
rankOrders.0=0
|
||
keys.1=rank
|
||
rankOrders.1=0
|
||
keys.2=form
|
||
rankOrders.2=0
|
||
keys.3=level
|
||
rankOrders.3=0
|
||
keys.4=kills
|
||
rankOrders.4=0
|
||
keys.5=deaths
|
||
rankOrders.5=0
|
||
keys.6=sc_squad
|
||
rankOrders.6=0
|
||
keys.7=time
|
||
rankOrders.7=0
|
||
keys.8=veteran
|
||
rankOrders.8=0
|
||
keys.9=elo
|
||
rankOrders.9=0
|
||
keys.10=score
|
||
rankOrders.10=0
|
||
keys.[]=11
|
||
rankOrders.[]=11
|
||
|
||
->stats.[]=9
|
||
stats.3.text=20100316
|
||
stats.1.value=28.0
|
||
stats.0.value=851985.0
|
||
stats.5.value=2993.0
|
||
stats.7.value=372294.71
|
||
stats.4.key=kills
|
||
stats.5.key=deaths
|
||
stats.2.rank=220437
|
||
stats.8.key=score
|
||
stats.1.rank=250001
|
||
stats.6.key=sc_squad
|
||
stats.0.key=score
|
||
stats.1.key=rank
|
||
stats.4.rank=250001
|
||
stats.2.value=1.0
|
||
stats.6.rank=250001
|
||
stats.7.key=time
|
||
stats.0.rank=250001
|
||
stats.5.rank=250001
|
||
stats.6.value=42955.0
|
||
stats.8.rank=250001
|
||
stats.3.rank=187362
|
||
stats.8.value=851985.0
|
||
TXN=GetRankedStats
|
||
stats.2.key=form
|
||
stats.4.value=3088.0
|
||
stats.7.rank=250001
|
||
stats.3.value=145.0
|
||
stats.3.key=level*/
|
||
}
|
||
|
||
else if(txn.compare("GetRankedStatsForOwners") == 0) // User wants to see himself on worldwide stats?
|
||
{
|
||
sendPacket = new Packet("rank", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
// not sure why this is being sent but it's like this in the logged traffic
|
||
sendPacket->SetVar("errorCode", "99");
|
||
sendPacket->SetVar("errorContainer.[]", "0");
|
||
sendPacket->SetVar("localizedMessage", "\"System Error\"");
|
||
/*
|
||
<-TXN=GetRankedStatsForOwners
|
||
owners.[]=1
|
||
owners.0.ownerId=230518387
|
||
owners.0.ownerType=1
|
||
periodId=0
|
||
keys.0=score
|
||
keys.1=rank
|
||
keys.2=form
|
||
keys.3=level
|
||
keys.4=kills
|
||
keys.5=deaths
|
||
keys.6=sc_squad
|
||
keys.7=time
|
||
keys.8=veteran
|
||
keys.9=elo
|
||
keys.10=" score"
|
||
keys.[]=11
|
||
|
||
->rankedStats.0.ownerType=1
|
||
rankedStats.0.rankedStats.5.value=2993.0
|
||
rankedStats.[]=1
|
||
rankedStats.0.rankedStats.3.text=20100316
|
||
rankedStats.0.rankedStats.6.rank=250001
|
||
rankedStats.0.rankedStats.3.value=145.0
|
||
rankedStats.0.rankedStats.6.key=sc_squad
|
||
rankedStats.0.rankedStats.5.key=deaths
|
||
rankedStats.0.rankedStats.7.value=372294.71
|
||
rankedStats.0.rankedStats.3.rank=187362
|
||
rankedStats.0.rankedStats.2.rank=220437
|
||
rankedStats.0.rankedStats.2.key=form
|
||
rankedStats.0.rankedStats.1.rank=250001
|
||
rankedStats.0.rankedStats.0.value=851985.0
|
||
rankedStats.0.ownerId=230518387
|
||
rankedStats.0.rankedStats.4.value=3088.0
|
||
rankedStats.0.rankedStats.4.key=kills
|
||
rankedStats.0.rankedStats.4.rank=250001
|
||
rankedStats.0.rankedStats.3.key=level
|
||
rankedStats.0.rankedStats.[]=8
|
||
rankedStats.0.rankedStats.0.rank=250001
|
||
rankedStats.0.rankedStats.0.key=score
|
||
rankedStats.0.rankedStats.1.key=rank
|
||
rankedStats.0.rankedStats.5.rank=250001
|
||
rankedStats.0.rankedStats.6.value=42955.0
|
||
rankedStats.0.rankedStats.2.value=1.0
|
||
rankedStats.0.rankedStats.7.rank=250001
|
||
TXN=GetRankedStatsForOwners
|
||
rankedStats.0.rankedStats.7.key=time
|
||
rankedStats.0.rankedStats.1.value=28.0*/
|
||
}
|
||
|
||
else if(txn.compare("GetTopNAndStats") == 0)
|
||
{
|
||
sendPacket = new Packet("rank", 0x80000000);
|
||
sendPacket->SetVar("TXN", txn);
|
||
/*
|
||
<-TXN=GetTopNAndStats
|
||
key=score
|
||
ownerType=1
|
||
minRank=250001
|
||
maxRank=250100
|
||
periodId=0
|
||
periodPast=0
|
||
rankOrder=0
|
||
keys.0=score
|
||
keys.1=rank
|
||
keys.2=form
|
||
keys.3=level
|
||
keys.4=kills
|
||
keys.5=deaths
|
||
keys.6=sc_squad
|
||
keys.7=time
|
||
keys.8=veteran
|
||
keys.9=elo
|
||
keys.[]=10
|
||
|
||
->stats.[]=0
|
||
TXN=GetTopNAndStats
|
||
|
||
=================
|
||
<-TXN=GetTopNAndStats
|
||
key=score
|
||
ownerType=1
|
||
minRank=1
|
||
maxRank=100
|
||
periodId=0
|
||
periodPast=0
|
||
rankOrder=0
|
||
keys.0=score
|
||
keys.1=rank
|
||
keys.2=form
|
||
keys.3=level
|
||
keys.4=kills
|
||
keys.5=deaths
|
||
keys.6=sc_squad
|
||
keys.7=time
|
||
keys.8=veteran
|
||
keys.9=elo
|
||
keys.[]=10
|
||
|
||
->stats.26.addStats.6.key=sc_squad
|
||
stats.1.addStats.8.value=7.0
|
||
stats.73.addStats.5.key=deaths
|
||
stats.50.addStats.7.value=8821996.97
|
||
stats.50.addStats.8.key=veteran
|
||
stats.8.addStats.3.value=0.0
|
||
stats.59.addStats.0.key=score
|
||
stats.49.addStats.3.text=20100315
|
||
stats.83.addStats.1.key=rank
|
||
stats.61.addStats.3.value=0.0
|
||
stats.97.addStats.2.key=form
|
||
stats.0.addStats.[]=10
|
||
stats.85.addStats.4.key=kills
|
||
stats.1.addStats.0.value=6.8625345E7
|
||
stats.5.addStats.4.key=kills
|
||
stats.52.name=leytenant
|
||
...
|
||
*/
|
||
}
|
||
else
|
||
state = UNKNOWN;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return state;
|
||
}
|
||
|
||
|
||
int GameClient::ProcessTheater(list<Packet*>* queue, Packet* packet, char* type, const char* ip)
|
||
{
|
||
Packet* sendPacket = NULL;
|
||
int state = NORMAL;
|
||
|
||
if(strcmp(type, "CONN") == 0)
|
||
{
|
||
sendPacket = new Packet("CONN", 0x00000000);
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("TIME", (int)time(NULL));
|
||
sendPacket->SetVar("activityTimeoutSecs", "240");
|
||
sendPacket->SetVar("PROT", packet->GetVar("PROT"));
|
||
}
|
||
|
||
else if(strcmp(type, "PING") == 0)
|
||
{
|
||
state = SKIP;
|
||
}
|
||
|
||
else if(strcmp(type, "USER") == 0)
|
||
{
|
||
persona_lkey = packet->GetVar("LKEY");
|
||
int id = database->theaterLogin(persona_lkey);
|
||
|
||
if(id > 0)
|
||
{
|
||
database->getPersona(id, &persona);
|
||
sendPacket = new Packet("USER", 0x00000000);
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("NAME", persona.name);
|
||
}
|
||
else
|
||
state = SKIP;
|
||
}
|
||
|
||
else if(strcmp(type, "LLST") == 0) //Lobby List
|
||
{
|
||
sendPacket = new Packet("LLST", 0x00000000);
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("NUM-LOBBIES", "1");
|
||
queue->push_back(sendPacket);
|
||
|
||
sendPacket = new Packet("LDAT", 0x00000000);
|
||
sendPacket->SetVar("TID", sock_tid);
|
||
sendPacket->SetVar("LID", database->getLobbyInfo(LOBBY_ID));
|
||
sendPacket->SetVar("PASSING", database->getLobbyGames());
|
||
sendPacket->SetVar("NAME", database->getLobbyInfo(LOBBY_NAME));
|
||
sendPacket->SetVar("LOCALE", database->getLobbyInfo(LOBBY_LOCALE));
|
||
sendPacket->SetVar("MAX-GAMES", database->getLobbyInfo(LOBBY_MAX_GAMES));
|
||
sendPacket->SetVar("FAVORITE-GAMES", "0"); //TODO: find out how it works
|
||
sendPacket->SetVar("FAVORITE-PLAYERS", "0"); //TODO: find out how it works
|
||
sendPacket->SetVar("NUM-GAMES", database->getLobbyGames());
|
||
}
|
||
|
||
else if(strcmp(type, "GLST") == 0) //Game List
|
||
{
|
||
list<int> filtered;
|
||
int limit = lexical_cast<int>(packet->GetVar("COUNT"));
|
||
if(limit < 0)
|
||
limit = 500;
|
||
|
||
string gid = packet->GetVar("GID");
|
||
if(!gid.empty()) // client is joining a specific server, get information about it
|
||
{
|
||
// there were filters in here before but why should we need them if there is an id?
|
||
/*int tempId = lexical_cast<int>(gid);
|
||
if(database->isValidGid(tempId))
|
||
filtered.push_back(tempId);*/
|
||
// actually I'm not sure if we should do anything here, normally the given gid is invalid or not part of the wanted games
|
||
}
|
||
else
|
||
{
|
||
if(fw->emuCfg().enable_server_filters)
|
||
filterGames(packet, &filtered);
|
||
else
|
||
database->listAllGames(&filtered);
|
||
}
|
||
|
||
//todo: make filters
|
||
sendPacket = new Packet("GLST", 0x00000000);
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("LID", packet->GetVar("LID"));
|
||
sendPacket->SetVar("LOBBY-NUM-GAMES", database->getLobbyGames());
|
||
sendPacket->SetVar("LOBBY-MAX-GAMES", database->getLobbyInfo(LOBBY_MAX_GAMES));
|
||
sendPacket->SetVar("NUM-GAMES", (int)filtered.size());
|
||
|
||
while(!filtered.empty() && limit > 0)
|
||
{
|
||
queue->push_back(sendPacket);
|
||
|
||
int id = filtered.front();
|
||
string* game = database->getGameData(filtered.front(), false);
|
||
sendPacket = new Packet("GDAT", 0x00000000);
|
||
sendPacket->SetVar("TID", sock_tid);
|
||
sendPacket->SetVar("LID", database->getLobbyInfo(LOBBY_ID)); // id of lobby
|
||
sendPacket->SetVar("GID", id); // id of game/server
|
||
|
||
string persona_name, persona_id;
|
||
if(game[PLATFORM].compare("PC") == 0) // I know these checks are consistent but it's better than nothing
|
||
{
|
||
persona_name = "bfbc2.server.p";
|
||
persona_id = "1";
|
||
}
|
||
else if(game[PLATFORM].compare("ps3") == 0)
|
||
{
|
||
persona_name = "bfbc.server.ps";
|
||
persona_id = "2";
|
||
}
|
||
else
|
||
{
|
||
persona_name = "bfbc.server.xe";
|
||
persona_id = "3";
|
||
}
|
||
sendPacket->SetVar("HN", persona_name); // account name of server (host name)
|
||
sendPacket->SetVar("HU", persona_id); // account id of server (host user)
|
||
sendPacket->SetVar("N", game[SERVER_NAME]); // name of server in list
|
||
|
||
if(!fw->isEmuLocal()) // a public IP is in the config so we have to determine in what network the server is
|
||
{
|
||
string serverIp = game[IP];
|
||
|
||
if(!isLocal && serverIp.compare(ip) != 0) // client is outside and remote server ip is not equal to the client ip
|
||
sendPacket->SetVar("I", serverIp);
|
||
else if(!isLocal && serverIp.compare(ip) == 0) // client is outside but server has the same ip as the client so they must be in the same network
|
||
sendPacket->SetVar("I", game[INTERNAL_IP]);
|
||
else if(isLocal && serverIp.compare(fw->portsCfg().emulator_ip) == 0) // client is local but server has same public ip as emulator so they must be in the same network
|
||
sendPacket->SetVar("I", game[INTERNAL_IP]);
|
||
else // client is local so check in what network the server is
|
||
{
|
||
if(!fw->isIpLocal(serverIp)) // server is in another network so send public ip to client
|
||
sendPacket->SetVar("I", serverIp); // IP (probably outside server ip)
|
||
else // everyone is local
|
||
sendPacket->SetVar("I", game[INTERNAL_IP]); // we want this if the server is in the same network as the client
|
||
}
|
||
}
|
||
else
|
||
sendPacket->SetVar("I", game[IP]); // IP (probably outside server ip)
|
||
|
||
sendPacket->SetVar("P", game[PORT]); // Port
|
||
sendPacket->SetVar("JP", game[JOINING_PLAYERS]);// players that are joining the server right now?
|
||
sendPacket->SetVar("QP", game[QUEUE_LENGTH]); // something with the queue...lets just set this equal to B-U-QueueLength
|
||
sendPacket->SetVar("AP", game[ACTIVE_PLAYERS]); // current number of players on server
|
||
sendPacket->SetVar("MP", game[MAX_PLAYERS]); // Maximum players on server
|
||
sendPacket->SetVar("PL", game[PLATFORM]); // Platform - PC / XENON / PS3
|
||
|
||
// constants (at least I never saw any other values in the logged traffic)
|
||
sendPacket->SetVar("F", "0"); // ???
|
||
sendPacket->SetVar("NF", "0"); // ???
|
||
sendPacket->SetVar("J", game[JOIN]); // ??? constant value - "O"
|
||
sendPacket->SetVar("TYPE", game[TYPE]); // what type?? constant value - "G"
|
||
sendPacket->SetVar("PW", "0"); // ??? - its certainly not something like "hasPassword"
|
||
|
||
// other server specific values
|
||
sendPacket->SetVar("B-U-Softcore", game[SOFTCORE]); // Game is softcore - what does that mean?
|
||
sendPacket->SetVar("B-U-Hardcore", game[HARDCORE]); // Game is hardcore
|
||
sendPacket->SetVar("B-U-HasPassword", game[HAS_PASSWORD]); // Game has password
|
||
sendPacket->SetVar("B-U-Punkbuster", game[PUNKBUSTER]); // Game has punkbuster?
|
||
sendPacket->SetVar("B-U-EA", game[EA]); // is server EA Orginal?
|
||
|
||
sendPacket->SetVar("B-version", game[VERSION]); // Version of the server (exact version) - TRY TO CONNECT TO ACTUAL VERSION OF SERVER
|
||
sendPacket->SetVar("V", game[CLIENT_VERSION]); // "clientVersion" of server (shows up in server log on startup)
|
||
sendPacket->SetVar("B-U-level", game[SERVER_LEVEL]);// current map of server
|
||
sendPacket->SetVar("B-U-gamemode", game[GAMEMODE]); // Gameplay Mode (Conquest, Rush, SQDM, etc)
|
||
sendPacket->SetVar("B-U-sguid", game[SGUID]); // Game PB Server GUID?
|
||
sendPacket->SetVar("B-U-Time", game[TIME]); // uptime of server?
|
||
sendPacket->SetVar("B-U-hash", game[HASH]); // Game hash?
|
||
sendPacket->SetVar("B-U-region", game[REGION]); // Game region
|
||
sendPacket->SetVar("B-U-public", game[IS_PUBLIC]); // Game is public
|
||
sendPacket->SetVar("B-U-elo", game[ELO]); // value that determines how good the players on the server are?
|
||
|
||
// also constant but could be changed? (is not implemented in the game anyway)
|
||
sendPacket->SetVar("B-numObservers", game[NUM_OBSERVERS]); // observers = spectators? or admins?
|
||
sendPacket->SetVar("B-maxObservers", game[MAX_OBSERVERS]); // Game max observers
|
||
|
||
sendPacket->SetVar("B-U-Provider", game[PROVIDER]); // provider id, figured out by server
|
||
sendPacket->SetVar("B-U-gameMod", game[GAME_MOD]); // maybe different value for vietnam here?
|
||
sendPacket->SetVar("B-U-QueueLength", game[QUEUE_LENGTH]); // players in queue or maximum queue length? (sometimes smaller than QP (-1?))
|
||
|
||
if(game[PUNKBUSTER].compare("1") == 0)
|
||
sendPacket->SetVar("B-U-PunkBusterVersion", game[PUNKBUSTER_VERSION]);
|
||
|
||
filtered.pop_front();
|
||
limit--;
|
||
}
|
||
}
|
||
|
||
else if(strcmp(type, "GDAT") == 0)
|
||
{
|
||
string lobbyID = packet->GetVar("LID");
|
||
string gameID = packet->GetVar("GID");
|
||
if(lobbyID.empty() || gameID.empty())
|
||
{
|
||
sendPacket = new Packet("GDAT", 0x00000000);
|
||
debug->warning(3, connectionType, "GDAT - GID or LID is null");
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
}
|
||
else
|
||
{
|
||
GamesEntry server;
|
||
int gid = lexical_cast<int>(gameID);
|
||
server.key = database->getGameData(gid, false);
|
||
server.gdet = database->getGameData(gid, true);
|
||
|
||
if(server.key && server.gdet)
|
||
{
|
||
// TODO: implement queues (properly)
|
||
if(queue_position > 0)
|
||
{
|
||
int cur_queue_length = lexical_cast<int>(server.key[QUEUE_LENGTH]);
|
||
debug->notification(3, connectionType, "Client is still in queue, prev_queue_length=%i, cur_queue_length=%i, queue_position=%i", original_queue_length, cur_queue_length, queue_position);
|
||
if(original_queue_length != cur_queue_length)
|
||
{
|
||
if(cur_queue_length < original_queue_length)
|
||
queue_position -= original_queue_length - cur_queue_length;
|
||
else
|
||
debug->notification(3, connectionType, "Someone joined the queue, don't update pos");
|
||
original_queue_length = cur_queue_length;
|
||
debug->notification(3, connectionType, "Queue length has changed, queue_position=%i", original_queue_length, queue_position);
|
||
}
|
||
// if queue_length is smaller than queue_pos then that means a player got it (we were at the end of the queue previously right?
|
||
// why was QPOS=0 and QLEN=1 when I tried it?
|
||
sendPacket = new Packet("QLEN", 0x00000000);
|
||
sendPacket->SetVar("QPOS", queue_position-1); // is this one off??
|
||
sendPacket->SetVar("QLEN", original_queue_length);
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
queue->push_back(sendPacket);
|
||
}
|
||
sendPacket = new Packet("GDAT", 0x00000000);// interesting...no 'F' or 'NF' required here or 'B-U-PunkBusterVersion'
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("LID", lobbyID); // is the LID always in this specific packet? if not take the LID from the database entry
|
||
sendPacket->SetVar("GID", gameID);
|
||
|
||
string persona_name, persona_id;
|
||
if(server.key[PLATFORM].compare("PC") == 0) // I know this check is anything but consistent but it's better than nothing
|
||
{
|
||
persona_name = "bfbc2.server.p";
|
||
persona_id = "1";
|
||
}
|
||
else if(server.key[PLATFORM].compare("ps3") == 0)
|
||
{
|
||
persona_name = "bfbc.server.ps";
|
||
persona_id = "2";
|
||
}
|
||
else
|
||
{
|
||
persona_name = "bfbc.server.xe";
|
||
persona_id = "3";
|
||
}
|
||
|
||
sendPacket->SetVar("HU", persona_id); // account id of server (host user)
|
||
sendPacket->SetVar("HN", persona_name); // account name of server (host name)
|
||
if(!fw->isEmuLocal()) // a public IP is in the config so we have to determine in what network the server is
|
||
{
|
||
string serverIp = server.key[IP];
|
||
|
||
if(!isLocal && serverIp.compare(ip) != 0) // client is outside and remote server ip is not equal to the client ip
|
||
sendPacket->SetVar("I", serverIp);
|
||
else if(!isLocal && serverIp.compare(ip) == 0) // client is outside but server has the same ip as the client so they must be in the same network
|
||
sendPacket->SetVar("I", server.key[INTERNAL_IP]); // we want this if the server is in the same network as the client
|
||
else if(isLocal && serverIp.compare(fw->portsCfg().emulator_ip) == 0) // client is local but server has same public ip as the emulator so they must be in the same network
|
||
sendPacket->SetVar("I", server.key[INTERNAL_IP]);
|
||
else // client is local so check in what network the server is
|
||
{
|
||
if(!fw->isIpLocal(serverIp)) // server is in another network so send public ip to client
|
||
sendPacket->SetVar("I", serverIp); // IP (probably outside server ip)
|
||
else // everyone is local
|
||
sendPacket->SetVar("I", server.key[INTERNAL_IP]); // we want this if the server is in the same network as the client
|
||
}
|
||
}
|
||
else
|
||
sendPacket->SetVar("I", server.key[IP]); // IP (probably outside server ip)
|
||
sendPacket->SetVar("P", server.key[PORT]); // server Port
|
||
sendPacket->SetVar("N", server.key[SERVER_NAME]); // name of server in list
|
||
sendPacket->SetVar("AP", server.key[ACTIVE_PLAYERS]); // current number of players on server(Active players)
|
||
sendPacket->SetVar("MP", server.key[MAX_PLAYERS]); // Maximum players on server
|
||
sendPacket->SetVar("QP", server.key[QUEUE_LENGTH]); // something with the queue...lets just set this equal to B-U-QueueLength
|
||
sendPacket->SetVar("JP", server.key[JOINING_PLAYERS]); // players that are joining the server right now?
|
||
sendPacket->SetVar("PL", server.key[PLATFORM]); // Platform - PC / XENON / PS3
|
||
|
||
// constant:
|
||
sendPacket->SetVar("PW", "0"); // ???
|
||
sendPacket->SetVar("TYPE", server.key[TYPE]); // always "G"?
|
||
sendPacket->SetVar("J", server.key[JOIN]); // always "O"?
|
||
|
||
// Userdata
|
||
sendPacket->SetVar("B-U-Softcore", server.key[SOFTCORE]); // Game is softcore - what does that mean?
|
||
sendPacket->SetVar("B-U-Hardcore", server.key[HARDCORE]); // Game is hardcore
|
||
sendPacket->SetVar("B-U-HasPassword", server.key[HAS_PASSWORD]);// Game has password
|
||
sendPacket->SetVar("B-U-Punkbuster", server.key[PUNKBUSTER]); // Game has punkbuster?
|
||
sendPacket->SetVar("B-U-EA", server.key[EA]); // is server EA Orginal
|
||
|
||
sendPacket->SetVar("B-version", server.key[VERSION]); // Version of the server (exact version) - TRY TO CONNECT TO ACTUAL VERSION OF SERVER
|
||
sendPacket->SetVar("V", server.key[CLIENT_VERSION]); // "clientVersion" of server (shows up in server log)
|
||
sendPacket->SetVar("B-U-level", server.key[SERVER_LEVEL]); // current map of server
|
||
sendPacket->SetVar("B-U-gamemode", server.key[GAMEMODE]); // Gameplay Mode (Conquest, Rush, SQDM, etc)
|
||
sendPacket->SetVar("B-U-sguid", server.key[SGUID]); // Game PB Server GUID?
|
||
sendPacket->SetVar("B-U-Time", server.key[TIME]); // uptime of server?
|
||
sendPacket->SetVar("B-U-hash", server.key[HASH]); // Game hash?
|
||
sendPacket->SetVar("B-U-region", server.key[REGION]); // Game region
|
||
sendPacket->SetVar("B-U-public", server.key[IS_PUBLIC]); // Game is public
|
||
sendPacket->SetVar("B-U-elo", server.key[ELO]); // value that determines how good the players on the server are?
|
||
|
||
sendPacket->SetVar("B-numObservers", server.key[NUM_OBSERVERS]); // observers = spectators? or admins?
|
||
sendPacket->SetVar("B-maxObservers", server.key[MAX_OBSERVERS]); // Game max observers
|
||
sendPacket->SetVar("B-U-Provider", server.key[PROVIDER]); // provider id, figured out by server
|
||
sendPacket->SetVar("B-U-gameMod", server.key[GAME_MOD]); // maybe different value for vietnam here?
|
||
sendPacket->SetVar("B-U-QueueLength", server.key[QUEUE_LENGTH]); // players in queue or maximum queue length? (sometimes smaller than QP (-1?))
|
||
queue->push_back(sendPacket);
|
||
|
||
sendPacket = new Packet("GDET", 0x00000000);
|
||
sendPacket->SetVar("TID", sock_tid);
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
|
||
sendPacket->SetVar("D-AutoBalance", server.gdet[AUTOBALANCE]);
|
||
sendPacket->SetVar("D-Crosshair", server.gdet[CROSSHAIR]);
|
||
sendPacket->SetVar("D-FriendlyFire", server.gdet[FRIENDLY_FIRE]);
|
||
sendPacket->SetVar("D-KillCam", server.gdet[KILLCAM]);
|
||
sendPacket->SetVar("D-Minimap", server.gdet[MINIMAP]);
|
||
sendPacket->SetVar("D-MinimapSpotting", server.gdet[MINIMAP_SPOTTING]);
|
||
sendPacket->SetVar("UGID", server.key[UGID]);
|
||
|
||
string serverDescription = server.gdet[SERVER_DESCRIPTION];
|
||
int count = 0;
|
||
if(!serverDescription.empty())
|
||
{
|
||
for(int i = 0, pos = 0; pos < (int)serverDescription.size(); i++, pos += 63) // 63 is max limit of one description "cell"?
|
||
{
|
||
char buffer[24];
|
||
sprintf(buffer, "D-ServerDescription%i", i);
|
||
int length = 63;
|
||
if(pos+length > (int)serverDescription.size())
|
||
length = serverDescription.size()-pos;
|
||
|
||
string splittedDescr = serverDescription.substr(pos, length);
|
||
sendPacket->SetVar(buffer, splittedDescr);
|
||
count++;
|
||
}
|
||
}
|
||
sendPacket->SetVar("D-ServerDescriptionCount", count);
|
||
if(!server.gdet[BANNERURL].empty())
|
||
sendPacket->SetVar("D-BannerUrl", server.gdet[BANNERURL]);
|
||
sendPacket->SetVar("D-ThirdPersonVehicleCameras", server.gdet[THIRD_PERSON_VEHICLE_CAMERAS]);
|
||
sendPacket->SetVar("D-ThreeDSpotting", server.gdet[THREE_D_SPOTTING]);
|
||
|
||
for(int i = 0; i < 32; i++) //get all the player names that are on the server so we can get their id's
|
||
{
|
||
string entry = server.gdet[PDAT00+i];
|
||
if(entry.compare("|0|0|0|0") != 0) //when the column contains a different value than the default then we have a player
|
||
{
|
||
string name = entry;
|
||
int end = name.find_first_of('|');
|
||
name.erase(end, name.size()-end);
|
||
debug->notification(4, connectionType, "player name on server: %s", name.c_str());
|
||
playerList.push_back(name);
|
||
}
|
||
|
||
char buffer[12];
|
||
if(i < 10)
|
||
sprintf(buffer, "D-pdat0%i", i);
|
||
else
|
||
sprintf(buffer, "D-pdat%i", i);
|
||
sendPacket->SetVar(buffer, entry);
|
||
}
|
||
queue->push_back(sendPacket);
|
||
|
||
while(!playerList.empty()) //gather all the information of the players that are already on the server and put them into packets
|
||
{
|
||
list_entry tempPersona;
|
||
string name = playerList.front();
|
||
|
||
if(database->getPersona(name, &tempPersona))
|
||
{
|
||
sendPacket = new Packet("PDAT", 0x00000000);
|
||
sendPacket->SetVar("NAME", name);
|
||
sendPacket->SetVar("TID", sock_tid);
|
||
if(tempPersona.data)
|
||
sendPacket->SetVar("PID", tempPersona.data[PLAYER_ID]); //id of the player on the server
|
||
else
|
||
debug->warning(2, connectionType, "tempPersona with id %i contains no data!!", tempPersona.id);
|
||
sendPacket->SetVar("UID", tempPersona.id); //this is definitely persona_id
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
queue->push_back(sendPacket);
|
||
}
|
||
else
|
||
{
|
||
debug->warning(2, connectionType, "GDAT no persona with name \"%s\" found!", name.c_str());
|
||
break;
|
||
}
|
||
playerList.pop_front();
|
||
}
|
||
sendPacket = NULL;
|
||
}
|
||
else // invalid GID
|
||
{
|
||
sendPacket = new Packet("GDAT", 0x00000000);
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
}
|
||
}
|
||
}
|
||
|
||
else if(strcmp(type, "EGAM") == 0)
|
||
{
|
||
debug->notification(4, connectionType, "Client requesting to join server");
|
||
string lobbyID = packet->GetVar("LID");
|
||
string gameID = packet->GetVar("GID");
|
||
int gid = lexical_cast<int>(gameID);
|
||
|
||
bool server_is_full = false;
|
||
string* game = database->getGameData(gid, false);
|
||
if(game)
|
||
{
|
||
bool isServerLocal = false;
|
||
int temp_players = lexical_cast<int>(game[ACTIVE_PLAYERS]);
|
||
int max_players = lexical_cast<int>(game[MAX_PLAYERS]);
|
||
if(temp_players+1 > max_players)
|
||
{
|
||
temp_players = lexical_cast<int>(game[QUEUE_LENGTH])+1;
|
||
game[QUEUE_LENGTH] = lexical_cast<string>(temp_players);
|
||
server_is_full = true;
|
||
}
|
||
|
||
if(!server_is_full)
|
||
{
|
||
sendPacket = new Packet("EGAM", 0x00000000);
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
}
|
||
else
|
||
{
|
||
original_queue_length = queue_position = temp_players; // if we get here, temp_players already contains the queue_length value of the database
|
||
debug->notification(3, connectionType, "Client got queued, queue_length=%i, queue_position=%i", original_queue_length, queue_position);
|
||
|
||
sendPacket = new Packet("EGAM", 0x71756575); // send EGAMqueu if server is full, header: 0x71756575
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
// a new player is automatically at the end of a queue, right? but why was QPOS=1 and QLEN=2 when I tried it? simply put +/-1 for testing purposes
|
||
sendPacket->SetVar("QPOS", queue_position); // position of client in queue?
|
||
sendPacket->SetVar("QLEN", queue_position+1); // the whole length of the queue (probably) or how much players are currently in the queue?
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
}
|
||
|
||
queue->push_back(sendPacket);
|
||
// put a mutex here?
|
||
TcpConnection* server_socket = fw->getServerSocket(gid);
|
||
persona.data[PLAYER_ID] = lexical_cast<string>(server_socket->getGameServer()->addPlayerId()); // player_id is a unique id of the player on the server (just a count of all players that connected)
|
||
string ticket = fw->randomString(10, SEED_NUMBERS);
|
||
|
||
if(server_socket)
|
||
{
|
||
// this packet gets sent to the SERVER the client connects to, it contains information about the client
|
||
if(!server_is_full)
|
||
{
|
||
sendPacket = new Packet("EGRQ", 0x00000000);
|
||
sendPacket->SetVar("R-INT-PORT", packet->GetVar("R-INT-PORT"));
|
||
sendPacket->SetVar("R-INT-IP", packet->GetVar("R-INT-IP")); // internal ip where the CLIENT is hosted
|
||
sendPacket->SetVar("PORT", packet->GetVar("PORT"));
|
||
sendPacket->SetVar("NAME", persona.name);
|
||
sendPacket->SetVar("PTYPE", packet->GetVar("PTYPE"));
|
||
sendPacket->SetVar("TICKET", ticket);
|
||
sendPacket->SetVar("PID", persona.data[PLAYER_ID]);
|
||
sendPacket->SetVar("UID", persona.id); // this has to be persona_id
|
||
|
||
if(!fw->isEmuLocal()) // a public IP is in the config so we have to determine in what network the server is
|
||
{
|
||
string serverIp = game[IP];
|
||
|
||
if(!isLocal && serverIp.compare(ip) != 0) // client is outside and remote server ip is not equal to the client ip
|
||
sendPacket->SetVar("IP", ip);
|
||
else if(!isLocal && serverIp.compare(ip) == 0) // client is outside but server has the same ip as the client so they must be in the same network
|
||
sendPacket->SetVar("IP", packet->GetVar("R-INT-IP"));
|
||
else if(isLocal && serverIp.compare(fw->portsCfg().emulator_ip) == 0) // client is local and server has the same public ip as the emulator so they must be in the same network
|
||
{
|
||
isServerLocal = true;
|
||
sendPacket->SetVar("IP", packet->GetVar("R-INT-IP"));
|
||
}
|
||
else // client is local so check in what network the server is
|
||
{
|
||
isServerLocal = fw->isIpLocal(serverIp);
|
||
if(!isServerLocal) // server is in another network so send ip from the emulator config
|
||
sendPacket->SetVar("IP", emuIp);
|
||
else // everyone is local
|
||
sendPacket->SetVar("IP", ip);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
isServerLocal = true;
|
||
sendPacket->SetVar("IP", ip);
|
||
}
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
}
|
||
else //<-A QENT {R-INT-PORT=10000, R-INT-IP=192.168.178.29, NAME=Brueckel, PID=27, UID=812008934, LID=257, GID=77635}
|
||
{
|
||
sendPacket = new Packet("QENT", 0x00000000);
|
||
sendPacket->SetVar("R-INT-PORT", packet->GetVar("R-INT-PORT"));
|
||
sendPacket->SetVar("R-INT-IP", packet->GetVar("R-INT-IP")); // internal ip where the CLIENT is hosted
|
||
sendPacket->SetVar("NAME", persona.name);
|
||
sendPacket->SetVar("PID", persona.data[PLAYER_ID]);
|
||
sendPacket->SetVar("UID", persona.id); // this has to be persona_id
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
}
|
||
server_socket->handle_invoke(sendPacket);
|
||
server_socket = NULL;
|
||
}
|
||
|
||
string server_pid;
|
||
if(game[PLATFORM].compare("PC") == 0) // I know this check is anything but consistent but it's better than nothing
|
||
server_pid = "1";
|
||
else if(game[PLATFORM].compare("ps3") == 0)
|
||
server_pid = "2";
|
||
else
|
||
server_pid = "3";
|
||
|
||
sendPacket = new Packet("EGEG", 0x00000000);
|
||
sendPacket->SetVar("PL", "pc");
|
||
sendPacket->SetVar("TICKET", ticket);
|
||
sendPacket->SetVar("PID", persona.data[PLAYER_ID]);
|
||
if(!fw->isEmuLocal()) // a public IP is in the config so we have to determine in what network the server is
|
||
{
|
||
string serverIp = game[IP];
|
||
|
||
if(!isLocal && serverIp.compare(ip) != 0) // client is outside and remote server ip is not equal to the client ip
|
||
sendPacket->SetVar("I", serverIp);
|
||
else if(!isLocal && serverIp.compare(ip) == 0) // client is outside but server has the same ip as the client so they must be in the same network
|
||
sendPacket->SetVar("I", game[INTERNAL_IP]);
|
||
else // client is local so check in what network the server is
|
||
{
|
||
if(!isServerLocal) // server is in another network so send public ip
|
||
sendPacket->SetVar("I", serverIp);
|
||
else // everyone is local
|
||
sendPacket->SetVar("I", game[INTERNAL_IP]);
|
||
}
|
||
}
|
||
else
|
||
sendPacket->SetVar("I", game[IP]);
|
||
sendPacket->SetVar("P", game[PORT]);
|
||
sendPacket->SetVar("HUID", server_pid); // server persona id
|
||
sendPacket->SetVar("INT-PORT", game[INTERNAL_PORT]);
|
||
sendPacket->SetVar("EKEY", "AIBSgPFqRDg0TfdXW1zUGa4%3d"); // this must be the same key as the one we have on the server? keep it constant in both connections for now (we could integrate it in the database...)
|
||
sendPacket->SetVar("INT-IP", game[INTERNAL_IP]); // internal ip where the SERVER is hosted
|
||
sendPacket->SetVar("UGID", game[UGID]);
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
if(queue_position > 0)
|
||
sendPacket->isDelayed(true, 40);
|
||
}
|
||
else
|
||
debug->warning(2, connectionType, "GID %s was not found in the database", gameID.c_str());
|
||
}
|
||
|
||
else if(strcmp(type, "ECNL") == 0)
|
||
{
|
||
string gameID = packet->GetVar("GID");
|
||
string lobbyID = packet->GetVar("LID");
|
||
if(queue_position > 0)
|
||
{
|
||
debug->notification(3, connectionType, "Client is leaving queue, updating queue_length = %s", persona.data[PLAYER_ID].c_str()); // why did I use player id here?
|
||
string* game = database->getGameData(lexical_cast<int>(gameID), false);
|
||
if(!game)
|
||
debug->warning(1, connectionType, "EGAM - The requested GID %i was not found in the database, ignoring packet.", gameID.c_str());
|
||
else
|
||
{
|
||
int queue_length = lexical_cast<int>(game[QUEUE_LENGTH]);
|
||
if(queue_length > 0)
|
||
game[QUEUE_LENGTH] = lexical_cast<string>(queue_length-1);
|
||
|
||
// why do we need to send another packet to the server here?
|
||
TcpConnection* server_socket = fw->getServerSocket(lexical_cast<int>(gameID));
|
||
if(server_socket)
|
||
{
|
||
sendPacket = new Packet("QLVT", 0x00000000);
|
||
sendPacket->SetVar("PID", persona.data[PLAYER_ID]);
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
server_socket->handle_invoke(sendPacket);
|
||
server_socket = NULL;
|
||
}
|
||
}
|
||
queue_position = 0;
|
||
persona.data[PLAYER_ID] = "0";
|
||
}
|
||
sendPacket = new Packet("ECNL", 0x00000000); // when is this ECNLmisc?? in case we want to send that, this is the type: 0x6D697363
|
||
sendPacket->SetVar("TID", ++sock_tid);
|
||
sendPacket->SetVar("LID", lobbyID);
|
||
sendPacket->SetVar("GID", gameID);
|
||
}
|
||
else
|
||
state = UNKNOWN;
|
||
|
||
if(sendPacket)
|
||
queue->push_back(sendPacket);
|
||
|
||
return state;
|
||
}
|
||
|
||
void GameClient::filterGames(Packet* packet, list<int>* filtered)
|
||
{
|
||
/*
|
||
FILTER-ATTR-U-gameMod - GAME_MOD
|
||
FILTER-MIN-SIZE - ACTIVE_PLAYERS // just check if filter is present, then filter games with active_players > 0
|
||
FILTER-NOT-FULL - MAX_PLAYERS // just check if filter is present, then filter games where active_players < max_players
|
||
FILTER-ATTR-U-EA - EA
|
||
FILTER-ATTR-U-HasPassword - HAS_PASSWORD
|
||
FILTER-ATTR-U-Punkbuster - PUNKBUSTER
|
||
FILTER-ATTR-U-Softcore - SOFTCORE
|
||
FILTER-ATTR-U-gamemode - GAMEMODE
|
||
FILTER-ATTR-U-level - SERVER_LEVEL
|
||
FILTER-ATTR-U-region - REGION
|
||
FILTER-ATTR-U-public - IS_PUBLIC
|
||
FAV-GAME - SERVER_NAME // multiple choices, seperated with ";"
|
||
FAV-GAME-UID - UGID // multiple choices, seperated with ";"
|
||
*/
|
||
list<linked_key> filters;
|
||
linked_key tempFilter;
|
||
|
||
string temp = packet->GetVar("FILTER-ATTR-U-gameMod");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = GAME_MOD;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-MIN-SIZE");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = ACTIVE_PLAYERS;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-NOT-FULL");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = MAX_PLAYERS;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-EA");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = EA;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-HasPassword");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = HAS_PASSWORD;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
//ignore punkbuster filters since it should be always deactivated anyway
|
||
/*temp = packet->GetVar("FILTER-ATTR-U-Punkbuster");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = PUNKBUSTER;
|
||
filters.push_back(tempFilter);
|
||
}*/
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-Softcore");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = SOFTCORE;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-gamemode");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = GAMEMODE;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-level");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = SERVER_LEVEL;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-region");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = REGION;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FILTER-ATTR-U-public");
|
||
if(!temp.empty())
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = IS_PUBLIC;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
|
||
temp = packet->GetVar("FAV-GAME");
|
||
if(!temp.empty())
|
||
{
|
||
size_t start = 0, end = 0;
|
||
if((end = temp.find(';', start)) != string::npos)
|
||
{
|
||
tempFilter.key = temp.substr(start, end-start);
|
||
tempFilter.id = SERVER_NAME;
|
||
filters.push_back(tempFilter);
|
||
|
||
start = end+1;
|
||
while((end = temp.find(';', start)) != string::npos && start < temp.size())
|
||
{
|
||
tempFilter.key = temp.substr(start, end-start);
|
||
tempFilter.id = SERVER_NAME;
|
||
filters.push_back(tempFilter);
|
||
start = end+1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = SERVER_NAME;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
}
|
||
|
||
temp = packet->GetVar("FAV-GAME-UID");
|
||
if(!temp.empty())
|
||
{
|
||
size_t start = 0, end = 0;
|
||
if((end = temp.find(';', start)) != string::npos)
|
||
{
|
||
tempFilter.key = temp.substr(start, end-start);
|
||
tempFilter.id = UGID;
|
||
filters.push_back(tempFilter);
|
||
|
||
start = end+1;
|
||
while((end = temp.find(';', start)) != string::npos && start < temp.size())
|
||
{
|
||
tempFilter.key = temp.substr(start, end-start);
|
||
tempFilter.id = UGID;
|
||
filters.push_back(tempFilter);
|
||
start = end+1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
tempFilter.key = temp;
|
||
tempFilter.id = UGID;
|
||
filters.push_back(tempFilter);
|
||
}
|
||
}
|
||
database->listMatchingGames(&filters, filtered);
|
||
}
|