|
|
|
@ -368,48 +368,13 @@ void Client::SendPostEnterWorld() {
|
|
|
|
safe_delete(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
bool Client::HandleLoginInfoPacket(const EQApplicationPacket *app)
|
|
|
|
const WorldConfig *Config=WorldConfig::get();
|
|
|
|
|
|
|
|
EmuOpcode opcode = app->GetOpcode();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT_TRACE,"Recevied EQApplicationPacket");
|
|
|
|
|
|
|
|
_pkt(WORLD__CLIENT_TRACE,app);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!eqs->CheckState(ESTABLISHED)) {
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT,"Client disconnected (net inactive on send)");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Voidd: Anti-GM Account hack, Checks source ip against valid GM Account IP Addresses
|
|
|
|
|
|
|
|
if (RuleB(World, GMAccountIPList) && this->GetAdmin() >= (RuleI(World, MinGMAntiHackStatus))) {
|
|
|
|
|
|
|
|
if(!database.CheckGMIPs(long2ip(this->GetIP()).c_str(), this->GetAccountID())) {
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT,"GM Account not permited from source address %s and accountid %i", long2ip(this->GetIP()).c_str(), this->GetAccountID());
|
|
|
|
|
|
|
|
eqs->Close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (GetAccountID() == 0 && opcode != OP_SendLoginInfo) {
|
|
|
|
|
|
|
|
// Got a packet other than OP_SendLoginInfo when not logged in
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT_ERR,"Expecting OP_SendLoginInfo, got %s", OpcodeNames[opcode]);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (opcode == OP_AckPacket) {
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(opcode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case OP_CrashDump:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_SendLoginInfo:
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (app->size != sizeof(LoginInfo_Struct)) {
|
|
|
|
if (app->size != sizeof(LoginInfo_Struct)) {
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const WorldConfig *Config=WorldConfig::get();
|
|
|
|
LoginInfo_Struct *li=(LoginInfo_Struct *)app->pBuffer;
|
|
|
|
LoginInfo_Struct *li=(LoginInfo_Struct *)app->pBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
// Quagmire - max len for name is 18, pass 15
|
|
|
|
// Quagmire - max len for name is 18, pass 15
|
|
|
|
@ -421,8 +386,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
if (strlen(password) <= 1) {
|
|
|
|
if (strlen(password) <= 1) {
|
|
|
|
// TODO: Find out how to tell the client wrong username/password
|
|
|
|
// TODO: Find out how to tell the client wrong username/password
|
|
|
|
clog(WORLD__CLIENT_ERR,"Login without a password");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Login without a password");
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pZoning=(li->zoning==1);
|
|
|
|
pZoning=(li->zoning==1);
|
|
|
|
@ -442,13 +406,13 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
id=atoi(&name[3]);
|
|
|
|
id=atoi(&name[3]);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
id=atoi(name);
|
|
|
|
id=atoi(name);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef IPBASED_AUTH_HACK
|
|
|
|
#ifdef IPBASED_AUTH_HACK
|
|
|
|
if ((cle = zoneserver_list.CheckAuth(inet_ntoa(tmpip), password)))
|
|
|
|
if ((cle = zoneserver_list.CheckAuth(inet_ntoa(tmpip), password)))
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
if (loginserverlist.Connected() == false && !pZoning) {
|
|
|
|
if (loginserverlist.Connected() == false && !pZoning) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"Error: Login server login while not connected to login server.");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Error: Login server login while not connected to login server.");
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((minilogin && (cle = client_list.CheckAuth(id,password,ip))) || (cle = client_list.CheckAuth(id, password)))
|
|
|
|
if ((minilogin && (cle = client_list.CheckAuth(id,password,ip))) || (cle = client_list.CheckAuth(id, password)))
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
@ -459,12 +423,10 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"If so you forget the minilogin variable...");
|
|
|
|
clog(WORLD__CLIENT_ERR,"If so you forget the minilogin variable...");
|
|
|
|
else
|
|
|
|
else
|
|
|
|
clog(WORLD__CLIENT_ERR,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table.");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table.");
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cle->SetOnline();
|
|
|
|
cle->SetOnline();
|
|
|
|
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT,"Logged in. Mode=%s",pZoning ? "(Zoning)" : "(CharSel)");
|
|
|
|
clog(WORLD__CLIENT,"Logged in. Mode=%s",pZoning ? "(Zoning)" : "(CharSel)");
|
|
|
|
|
|
|
|
|
|
|
|
if(minilogin){
|
|
|
|
if(minilogin){
|
|
|
|
@ -474,6 +436,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
clog(WORLD__CLIENT,"LS Account #%d",cle->LSID());
|
|
|
|
clog(WORLD__CLIENT,"LS Account #%d",cle->LSID());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(Config->UpdateStats) {
|
|
|
|
if(Config->UpdateStats) {
|
|
|
|
ServerPacket* pack = new ServerPacket;
|
|
|
|
ServerPacket* pack = new ServerPacket;
|
|
|
|
pack->opcode = ServerOP_LSPlayerJoinWorld;
|
|
|
|
pack->opcode = ServerOP_LSPlayerJoinWorld;
|
|
|
|
@ -503,22 +466,24 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
// TODO: Find out how to tell the client wrong username/password
|
|
|
|
// TODO: Find out how to tell the client wrong username/password
|
|
|
|
clog(WORLD__CLIENT_ERR,"Bad/Expired session key '%s'",name);
|
|
|
|
clog(WORLD__CLIENT_ERR,"Bad/Expired session key '%s'",name);
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!cle)
|
|
|
|
if (!cle)
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
cle->SetIP(GetIP());
|
|
|
|
cle->SetIP(GetIP());
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_ApproveName: //Name approval
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::HandleApproveNamePacket(const EQApplicationPacket *app)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (GetAccountID() == 0) {
|
|
|
|
if (GetAccountID() == 0) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
snprintf(char_name, 64, "%s", (char*)app->pBuffer);
|
|
|
|
snprintf(char_name, 64, "%s", (char*)app->pBuffer);
|
|
|
|
uchar race = app->pBuffer[64];
|
|
|
|
uchar race = app->pBuffer[64];
|
|
|
|
uchar clas = app->pBuffer[68];
|
|
|
|
uchar clas = app->pBuffer[68];
|
|
|
|
@ -530,7 +495,9 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
outapp->SetOpcode(OP_ApproveName);
|
|
|
|
outapp->SetOpcode(OP_ApproveName);
|
|
|
|
outapp->pBuffer = new uchar[1];
|
|
|
|
outapp->pBuffer = new uchar[1];
|
|
|
|
outapp->size = 1;
|
|
|
|
outapp->size = 1;
|
|
|
|
|
|
|
|
|
|
|
|
bool valid;
|
|
|
|
bool valid;
|
|
|
|
|
|
|
|
|
|
|
|
if(!database.CheckNameFilter(char_name)) {
|
|
|
|
if(!database.CheckNameFilter(char_name)) {
|
|
|
|
valid = false;
|
|
|
|
valid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -544,17 +511,20 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
valid = false;
|
|
|
|
valid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
outapp->pBuffer[0] = valid? 1 : 0;
|
|
|
|
outapp->pBuffer[0] = valid? 1 : 0;
|
|
|
|
QueuePacket(outapp);
|
|
|
|
QueuePacket(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
|
|
|
|
|
|
|
|
if(!valid) {
|
|
|
|
if(!valid) {
|
|
|
|
memset(char_name, 0, sizeof(char_name));
|
|
|
|
memset(char_name, 0, sizeof(char_name));
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_RandomNameGenerator:
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::HandleRandomNameGeneratorPacket(const EQApplicationPacket *app)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// creates up to a 10 char name
|
|
|
|
// creates up to a 10 char name
|
|
|
|
char vowels[18]="aeiouyaeiouaeioe";
|
|
|
|
char vowels[18]="aeiouyaeiouaeioe";
|
|
|
|
@ -565,59 +535,64 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
bool dlc=false;
|
|
|
|
bool dlc=false;
|
|
|
|
bool vwl=false;
|
|
|
|
bool vwl=false;
|
|
|
|
bool dbl=false;
|
|
|
|
bool dbl=false;
|
|
|
|
if (rndnum>63)
|
|
|
|
|
|
|
|
{ // rndnum is 0 - 75 where 64-75 is cons pair, 17-63 is cons, 0-16 is vowel
|
|
|
|
if (rndnum>63) {
|
|
|
|
|
|
|
|
// rndnum is 0 - 75 where 64-75 is cons pair, 17-63 is cons, 0-16 is vowel
|
|
|
|
rndnum=(rndnum-61)*2; // name can't start with "ng" "nd" or "rk"
|
|
|
|
rndnum=(rndnum-61)*2; // name can't start with "ng" "nd" or "rk"
|
|
|
|
rndname[0]=paircons[rndnum];
|
|
|
|
rndname[0]=paircons[rndnum];
|
|
|
|
rndname[1]=paircons[rndnum+1];
|
|
|
|
rndname[1]=paircons[rndnum+1];
|
|
|
|
n=2;
|
|
|
|
n=2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rndnum>16)
|
|
|
|
else if (rndnum>16) {
|
|
|
|
{
|
|
|
|
|
|
|
|
rndnum-=17;
|
|
|
|
rndnum-=17;
|
|
|
|
rndname[0]=cons[rndnum];
|
|
|
|
rndname[0]=cons[rndnum];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else {
|
|
|
|
{
|
|
|
|
|
|
|
|
rndname[0]=vowels[rndnum];
|
|
|
|
rndname[0]=vowels[rndnum];
|
|
|
|
vwl=true;
|
|
|
|
vwl=true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int namlen=MakeRandomInt(5, 10);
|
|
|
|
int namlen=MakeRandomInt(5, 10);
|
|
|
|
for (int i=n;i<namlen;i++)
|
|
|
|
for (int i=n;i<namlen;i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
dlc=false;
|
|
|
|
dlc=false;
|
|
|
|
if (vwl) //last char was a vowel
|
|
|
|
if (vwl) {
|
|
|
|
{ // so pick a cons or cons pair
|
|
|
|
//last char was a vowel
|
|
|
|
|
|
|
|
// so pick a cons or cons pair
|
|
|
|
rndnum=MakeRandomInt(0, 62);
|
|
|
|
rndnum=MakeRandomInt(0, 62);
|
|
|
|
if (rndnum>46)
|
|
|
|
if (rndnum>46) {
|
|
|
|
{ // pick a cons pair
|
|
|
|
// pick a cons pair
|
|
|
|
if (i>namlen-3) // last 2 chars in name?
|
|
|
|
if (i>namlen-3) {
|
|
|
|
{ // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
|
|
|
|
// last 2 chars in name?
|
|
|
|
|
|
|
|
// name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
|
|
|
|
rndnum=MakeRandomInt(0, 7)*2;
|
|
|
|
rndnum=MakeRandomInt(0, 7)*2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else {
|
|
|
|
{ // pick any from the set
|
|
|
|
// pick any from the set
|
|
|
|
rndnum=(rndnum-47)*2;
|
|
|
|
rndnum=(rndnum-47)*2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rndname[i]=paircons[rndnum];
|
|
|
|
rndname[i]=paircons[rndnum];
|
|
|
|
rndname[i+1]=paircons[rndnum+1];
|
|
|
|
rndname[i+1]=paircons[rndnum+1];
|
|
|
|
dlc=true; // flag keeps second letter from being doubled below
|
|
|
|
dlc=true; // flag keeps second letter from being doubled below
|
|
|
|
i+=1;
|
|
|
|
i+=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else {
|
|
|
|
{ // select a single cons
|
|
|
|
// select a single cons
|
|
|
|
rndname[i]=cons[rndnum];
|
|
|
|
rndname[i]=cons[rndnum];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else {
|
|
|
|
{ // select a vowel
|
|
|
|
// select a vowel
|
|
|
|
rndname[i]=vowels[MakeRandomInt(0, 16)];
|
|
|
|
rndname[i]=vowels[MakeRandomInt(0, 16)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vwl=!vwl;
|
|
|
|
vwl=!vwl;
|
|
|
|
if (!dbl && !dlc)
|
|
|
|
if (!dbl && !dlc)
|
|
|
|
{ // one chance at double letters in name
|
|
|
|
|
|
|
|
if (!MakeRandomInt(0, i+9)) // chances decrease towards end of name
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// one chance at double letters in name
|
|
|
|
|
|
|
|
if (!MakeRandomInt(0, i+9)) {
|
|
|
|
|
|
|
|
// chances decrease towards end of name
|
|
|
|
rndname[i+1]=rndname[i];
|
|
|
|
rndname[i+1]=rndname[i];
|
|
|
|
dbl=true;
|
|
|
|
dbl=true;
|
|
|
|
i+=1;
|
|
|
|
i+=1;
|
|
|
|
@ -630,16 +605,12 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
memset(ngs->name,0,64);
|
|
|
|
memset(ngs->name,0,64);
|
|
|
|
strcpy(ngs->name,rndname);
|
|
|
|
strcpy(ngs->name,rndname);
|
|
|
|
|
|
|
|
|
|
|
|
// char names[8][64] = { "How", "About", "You", "Think", "Of", "Your", "Own", "Name" };
|
|
|
|
|
|
|
|
// //Could have parts of the random name in this struct and they compile together
|
|
|
|
|
|
|
|
// NameGeneration_Struct* ngs = (NameGeneration_Struct*)app->pBuffer;
|
|
|
|
|
|
|
|
// strncpy(ngs->name,"Notcreated",64);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QueuePacket(app);
|
|
|
|
QueuePacket(app);
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_CharacterCreateRequest: {
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app)
|
|
|
|
|
|
|
|
{
|
|
|
|
// New OpCode in SoF
|
|
|
|
// New OpCode in SoF
|
|
|
|
uint32 allocs = character_create_allocations.size();
|
|
|
|
uint32 allocs = character_create_allocations.size();
|
|
|
|
uint32 combos = character_create_race_class_combos.size();
|
|
|
|
uint32 combos = character_create_race_class_combos.size();
|
|
|
|
@ -665,6 +636,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
alc->BaseStats[j] = character_create_allocations[i].BaseStats[j];
|
|
|
|
alc->BaseStats[j] = character_create_allocations[i].BaseStats[j];
|
|
|
|
alc->DefaultPointAllocation[j] = character_create_allocations[i].DefaultPointAllocation[j];
|
|
|
|
alc->DefaultPointAllocation[j] = character_create_allocations[i].DefaultPointAllocation[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ptr += sizeof(RaceClassAllocation);
|
|
|
|
ptr += sizeof(RaceClassAllocation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -683,22 +655,21 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
|
|
|
|
|
|
|
|
QueuePacket(outapp);
|
|
|
|
QueuePacket(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case OP_CharacterCreate: //Char create
|
|
|
|
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (GetAccountID() == 0)
|
|
|
|
if (GetAccountID() == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character.");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character.");
|
|
|
|
ret = false;
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (app->size != sizeof(CharCreate_Struct))
|
|
|
|
else if (app->size != sizeof(CharCreate_Struct))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct));
|
|
|
|
clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct));
|
|
|
|
DumpPacket(app);
|
|
|
|
DumpPacket(app);
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer;
|
|
|
|
CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer;
|
|
|
|
@ -709,27 +680,32 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
outapp->pBuffer[0] = 0;
|
|
|
|
outapp->pBuffer[0] = 0;
|
|
|
|
QueuePacket(outapp);
|
|
|
|
QueuePacket(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
safe_delete(outapp);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
|
|
|
|
SendCharInfo();
|
|
|
|
SendCharInfo();
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_EnterWorld: // Enter world
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
const WorldConfig *Config=WorldConfig::get();
|
|
|
|
if (GetAccountID() == 0) {
|
|
|
|
if (GetAccountID() == 0) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(GetAdmin() < 0)
|
|
|
|
if(GetAdmin() < 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
clog(WORLD__CLIENT,"Account banned or suspended.");
|
|
|
|
clog(WORLD__CLIENT,"Account banned or suspended.");
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (RuleI(World, MaxClientsPerIP) >= 0) {
|
|
|
|
if (RuleI(World, MaxClientsPerIP) >= 0) {
|
|
|
|
client_list.GetCLEIP(this->GetIP()); //Check current CLE Entry IPs against incoming connection
|
|
|
|
//Check current CLE Entry IPs against incoming connection
|
|
|
|
|
|
|
|
client_list.GetCLEIP(this->GetIP());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EnterWorld_Struct *ew=(EnterWorld_Struct *)app->pBuffer;
|
|
|
|
EnterWorld_Struct *ew=(EnterWorld_Struct *)app->pBuffer;
|
|
|
|
@ -738,17 +714,18 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
EQApplicationPacket *outapp;
|
|
|
|
EQApplicationPacket *outapp;
|
|
|
|
uint32 tmpaccid = 0;
|
|
|
|
uint32 tmpaccid = 0;
|
|
|
|
charid = database.GetCharacterInfo(char_name, &tmpaccid, &zoneID, &instanceID);
|
|
|
|
charid = database.GetCharacterInfo(char_name, &tmpaccid, &zoneID, &instanceID);
|
|
|
|
|
|
|
|
|
|
|
|
if (charid == 0 || tmpaccid != GetAccountID()) {
|
|
|
|
if (charid == 0 || tmpaccid != GetAccountID()) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"Could not get CharInfo for '%s'",char_name);
|
|
|
|
clog(WORLD__CLIENT_ERR,"Could not get CharInfo for '%s'",char_name);
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure this account owns this character
|
|
|
|
// Make sure this account owns this character
|
|
|
|
if (tmpaccid != GetAccountID()) {
|
|
|
|
if (tmpaccid != GetAccountID()) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"This account does not own the character named '%s'",char_name);
|
|
|
|
clog(WORLD__CLIENT_ERR,"This account does not own the character named '%s'",char_name);
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(!pZoning && ew->return_home)
|
|
|
|
if(!pZoning && ew->return_home)
|
|
|
|
@ -780,7 +757,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
|
|
|
|
clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
|
|
|
|
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
|
|
|
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -813,7 +790,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
clog(WORLD__CLIENT_ERR,"'%s' is trying to go to tutorial but are not allowed...",char_name);
|
|
|
|
clog(WORLD__CLIENT_ERR,"'%s' is trying to go to tutorial but are not allowed...",char_name);
|
|
|
|
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
|
|
|
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -868,8 +845,8 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
outapp->pBuffer = new uchar[outapp->size];
|
|
|
|
outapp->pBuffer = new uchar[outapp->size];
|
|
|
|
memset(outapp->pBuffer,0,outapp->size);
|
|
|
|
memset(outapp->pBuffer,0,outapp->size);
|
|
|
|
strcpy((char*)outapp->pBuffer, tmp);
|
|
|
|
strcpy((char*)outapp->pBuffer, tmp);
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
else {
|
|
|
|
// Null Message of the Day. :)
|
|
|
|
// Null Message of the Day. :)
|
|
|
|
outapp->size = 1;
|
|
|
|
outapp->size = 1;
|
|
|
|
outapp->pBuffer = new uchar[outapp->size];
|
|
|
|
outapp->pBuffer = new uchar[outapp->size];
|
|
|
|
@ -893,12 +870,14 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
|
|
|
|
|
|
|
|
EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_SetChatServer);
|
|
|
|
EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_SetChatServer);
|
|
|
|
char buffer[112];
|
|
|
|
char buffer[112];
|
|
|
|
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
|
|
|
sprintf(buffer,
|
|
|
|
|
|
|
|
"%s,%i,%s.%s,%c%08X",
|
|
|
|
Config->ChatHost.c_str(),
|
|
|
|
Config->ChatHost.c_str(),
|
|
|
|
Config->ChatPort,
|
|
|
|
Config->ChatPort,
|
|
|
|
Config->ShortName.c_str(),
|
|
|
|
Config->ShortName.c_str(),
|
|
|
|
this->GetCharName(), ConnectionType, MailKey
|
|
|
|
this->GetCharName(),
|
|
|
|
);
|
|
|
|
ConnectionType,
|
|
|
|
|
|
|
|
MailKey);
|
|
|
|
outapp2->size=strlen(buffer)+1;
|
|
|
|
outapp2->size=strlen(buffer)+1;
|
|
|
|
outapp2->pBuffer = new uchar[outapp2->size];
|
|
|
|
outapp2->pBuffer = new uchar[outapp2->size];
|
|
|
|
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
|
|
|
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
|
|
|
@ -914,8 +893,10 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
Config->MailHost.c_str(),
|
|
|
|
Config->MailHost.c_str(),
|
|
|
|
Config->MailPort,
|
|
|
|
Config->MailPort,
|
|
|
|
Config->ShortName.c_str(),
|
|
|
|
Config->ShortName.c_str(),
|
|
|
|
this->GetCharName(), ConnectionType, MailKey
|
|
|
|
this->GetCharName(),
|
|
|
|
);
|
|
|
|
ConnectionType,
|
|
|
|
|
|
|
|
MailKey);
|
|
|
|
|
|
|
|
|
|
|
|
outapp2->size=strlen(buffer)+1;
|
|
|
|
outapp2->size=strlen(buffer)+1;
|
|
|
|
outapp2->pBuffer = new uchar[outapp2->size];
|
|
|
|
outapp2->pBuffer = new uchar[outapp2->size];
|
|
|
|
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
|
|
|
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
|
|
|
@ -923,10 +904,68 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
safe_delete(outapp2);
|
|
|
|
safe_delete(outapp2);
|
|
|
|
|
|
|
|
|
|
|
|
EnterWorld();
|
|
|
|
EnterWorld();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
|
|
|
|
const WorldConfig *Config=WorldConfig::get();
|
|
|
|
|
|
|
|
EmuOpcode opcode = app->GetOpcode();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT_TRACE,"Recevied EQApplicationPacket");
|
|
|
|
|
|
|
|
_pkt(WORLD__CLIENT_TRACE,app);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!eqs->CheckState(ESTABLISHED)) {
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT,"Client disconnected (net inactive on send)");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Voidd: Anti-GM Account hack, Checks source ip against valid GM Account IP Addresses
|
|
|
|
|
|
|
|
if (RuleB(World, GMAccountIPList) && this->GetAdmin() >= (RuleI(World, MinGMAntiHackStatus))) {
|
|
|
|
|
|
|
|
if(!database.CheckGMIPs(long2ip(this->GetIP()).c_str(), this->GetAccountID())) {
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT,"GM Account not permited from source address %s and accountid %i", long2ip(this->GetIP()).c_str(), this->GetAccountID());
|
|
|
|
|
|
|
|
eqs->Close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (GetAccountID() == 0 && opcode != OP_SendLoginInfo) {
|
|
|
|
|
|
|
|
// Got a packet other than OP_SendLoginInfo when not logged in
|
|
|
|
|
|
|
|
clog(WORLD__CLIENT_ERR,"Expecting OP_SendLoginInfo, got %s", OpcodeNames[opcode]);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (opcode == OP_AckPacket) {
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(opcode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case OP_CrashDump:
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_SendLoginInfo:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return HandleLoginInfoPacket(app);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_ApproveName: //Name approval
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return HandleApproveNamePacket(app);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_RandomNameGenerator:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return HandleRandomNameGeneratorPacket(app);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_CharacterCreateRequest:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return HandleCharacterCreateRequestPacket(app);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_CharacterCreate: //Char create
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return HandleCharacterCreatePacket(app);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_EnterWorld: // Enter world
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return HandleEnterWorldPacket(app);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_LoginComplete:{
|
|
|
|
case OP_LoginComplete:{
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_DeleteCharacter: {
|
|
|
|
case OP_DeleteCharacter: {
|
|
|
|
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
|
|
|
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
|
|
|
@ -936,14 +975,14 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
database.DeleteCharacter((char *)app->pBuffer);
|
|
|
|
database.DeleteCharacter((char *)app->pBuffer);
|
|
|
|
SendCharInfo();
|
|
|
|
SendCharInfo();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_ApproveWorld:
|
|
|
|
case OP_ApproveWorld:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_WorldClientReady:{
|
|
|
|
case OP_WorldClientReady:{
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_World_Client_CRC1:
|
|
|
|
case OP_World_Client_CRC1:
|
|
|
|
case OP_World_Client_CRC2: {
|
|
|
|
case OP_World_Client_CRC2: {
|
|
|
|
@ -952,18 +991,18 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
// before OP_World_Client_CRC1. Therefore, if we receive OP_World_Client_CRC1 before OP_EnterWorld,
|
|
|
|
// before OP_World_Client_CRC1. Therefore, if we receive OP_World_Client_CRC1 before OP_EnterWorld,
|
|
|
|
// then 'Start Tutorial' was not chosen.
|
|
|
|
// then 'Start Tutorial' was not chosen.
|
|
|
|
StartInTutorial = false;
|
|
|
|
StartInTutorial = false;
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_WearChange: { // User has selected a different character
|
|
|
|
case OP_WearChange: { // User has selected a different character
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_WorldComplete: {
|
|
|
|
case OP_WorldComplete: {
|
|
|
|
eqs->Close();
|
|
|
|
eqs->Close();
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OP_LoginUnknown1:
|
|
|
|
case OP_LoginUnknown1:
|
|
|
|
case OP_LoginUnknown2:
|
|
|
|
case OP_LoginUnknown2:
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
case OP_ZoneChange:
|
|
|
|
case OP_ZoneChange:
|
|
|
|
// HoT sends this to world while zoning and wants it echoed back.
|
|
|
|
// HoT sends this to world while zoning and wants it echoed back.
|
|
|
|
@ -971,16 +1010,13 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
QueuePacket(app);
|
|
|
|
QueuePacket(app);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default: {
|
|
|
|
default: {
|
|
|
|
clog(WORLD__CLIENT_ERR,"Received unknown EQApplicationPacket");
|
|
|
|
clog(WORLD__CLIENT_ERR,"Received unknown EQApplicationPacket");
|
|
|
|
_pkt(WORLD__CLIENT_ERR,app);
|
|
|
|
_pkt(WORLD__CLIENT_ERR,app);
|
|
|
|
break;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::Process() {
|
|
|
|
bool Client::Process() {
|
|
|
|
|