580 lines
21 KiB
C++
580 lines
21 KiB
C++
/*
|
|
Rose Online Server Emulator
|
|
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
developed with Main erose/hrose source server + some change from the original eich source
|
|
*/
|
|
#include "charserver.h"
|
|
|
|
// Do player identification
|
|
bool CCharServer::pakDoIdentify( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if (thisclient->isLoggedIn) return false;
|
|
MYSQL_RES *result;
|
|
MYSQL_ROW row;
|
|
thisclient->userid = GETDWORD((*P), 0x00);
|
|
memcpy( thisclient->password, &P->Buffer[4], 32 );
|
|
result = DB->QStore("SELECT username,lastsvr,accesslevel,platinum FROM accounts WHERE id=%i AND password='%s'", thisclient->userid, thisclient->password);
|
|
if(result==NULL) return false;
|
|
if (mysql_num_rows( result ) != 1)
|
|
{
|
|
Log( MSG_HACK, "Someone tried to connect to char server with an invalid account" );
|
|
DB->QFree( );
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
row = mysql_fetch_row(result);
|
|
strncpy_s (thisclient->username, row[0], 16);
|
|
thisclient->channel = atoi(row[1]);
|
|
thisclient->accesslevel = atoi(row[2]);
|
|
thisclient->platinum = atoi(row[3]);
|
|
DB->QFree( );
|
|
}
|
|
|
|
Log( MSG_INFO,"User '%s'(#%i) logged in", thisclient->username, thisclient->userid );
|
|
|
|
BEGINPACKET( pak, 0x070c );
|
|
ADDBYTE ( pak, 0 );
|
|
ADDDWORD ( pak, 0x87654321);
|
|
ADDDWORD ( pak, 0x00000000 );
|
|
thisclient->SendPacket( &pak );
|
|
result = DB->QStore( "SELECT online FROM accounts WHERE username='%s'", thisclient->username );
|
|
if(result==NULL) return false;
|
|
row = mysql_fetch_row(result);
|
|
bool online = atoi(row[0]);
|
|
DB->QFree( );
|
|
if(online)
|
|
return false;
|
|
if(!DB->QExecute( "UPDATE accounts SET online=1 WHERE username='%s'", thisclient->username ))
|
|
return false;
|
|
thisclient->isLoggedIn = true;
|
|
thisclient->returnedfromWS=false;
|
|
return true;
|
|
}
|
|
|
|
// Get this clients character list
|
|
bool CCharServer::pakGetCharacters( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if (!thisclient->isLoggedIn) return false;
|
|
// Properly delete items, quests, friends when deleting a character
|
|
// Hooray for joins.
|
|
MYSQL_RES *result;
|
|
MYSQL_ROW row;
|
|
DB->QExecute( "DELETE FROM characters, items, list_friend, list_quest USING characters LEFT JOIN items ON items.owner = characters.id LEFT JOIN list_friend \
|
|
ON (list_friend.id = characters.id OR list_friend.idfriend = characters.id) LEFT JOIN list_quest ON list_quest.owner = characters.id WHERE (characters.deletetime > 0 AND characters.deletetime <= %i)", GetServerTime( ) );
|
|
|
|
CItem items[10];
|
|
unsigned int charnum=0;
|
|
CCharacter chars[5];
|
|
// 0 1 2 3 4 5 6 7
|
|
result = DB->QStore("SELECT char_name,level,face,hairStyle,sex,classid,id,deletetime FROM characters WHERE account_name='%s'", thisclient->username);
|
|
if(result==NULL) return false;
|
|
while (row = mysql_fetch_row(result))
|
|
{
|
|
strcpy( chars[charnum].char_name , row[0] );
|
|
chars[charnum].level = atoi(row[1]);
|
|
chars[charnum].face = atoi(row[2]);
|
|
chars[charnum].hairStyle = atoi(row[3]);
|
|
chars[charnum].sex = atoi(row[4]);
|
|
chars[charnum].classid = atoi(row[5]);
|
|
chars[charnum].id = atoi(row[6]);
|
|
chars[charnum].DeleteTime = atoi(row[7]);
|
|
if(chars[charnum].DeleteTime > 0)
|
|
{
|
|
chars[charnum].DeleteTime = chars[charnum].DeleteTime - GetServerTime( );
|
|
}
|
|
charnum++;
|
|
}
|
|
DB->QFree( );
|
|
BEGINPACKET( pak, 0x0712 );
|
|
ADDBYTE ( pak, charnum );
|
|
for (unsigned k=0;k<charnum;k++)
|
|
{
|
|
for(unsigned j=0; j<10; j++)
|
|
ClearItem( items[j] );
|
|
// 0 1 2 3 4 5
|
|
//result = DB->QStore("SELECT itemnum,itemtype,refine,durability,lifespan,slotnum FROM items WHERE owner=%i AND slotnum<10", chars[k].id);
|
|
result = DB->QStore("SELECT itemid, itemtype, refine, durability, lifespan FROM charitems WHERE owner=%i", chars[k].id);
|
|
|
|
if(result == NULL) return false;
|
|
char *tmpid;
|
|
char *itmp;
|
|
while( row = mysql_fetch_row(result) )
|
|
{
|
|
tmpid = strtok( row[0] , "|");
|
|
for(unsigned int i=1;i<10; i++)
|
|
{
|
|
if((tmpid = strtok( NULL , "|"))!= NULL)
|
|
{
|
|
items[i].itemnum = atoi(tmpid);
|
|
}
|
|
}
|
|
tmpid = strtok( row[1] , "|");
|
|
for(unsigned int i=1;i<10; i++)
|
|
{
|
|
if((tmpid = strtok( NULL , "|"))!= NULL)
|
|
{
|
|
items[i].itemtype = atoi(tmpid);
|
|
}
|
|
}
|
|
tmpid = strtok( row[2] , "|");
|
|
for(unsigned int i=1;i<10; i++)
|
|
{
|
|
if((tmpid = strtok( NULL , "|"))!= NULL)
|
|
{
|
|
items[i].refine = atoi(tmpid);
|
|
}
|
|
}
|
|
tmpid = strtok( row[3] , "|");
|
|
for(unsigned int i=1;i<10; i++)
|
|
{
|
|
if((tmpid = strtok( NULL , "|"))!= NULL)
|
|
{
|
|
items[i].durability = atoi(tmpid);
|
|
}
|
|
}
|
|
tmpid = strtok( row[4] , "|");
|
|
for(unsigned int i=1;i<10; i++)
|
|
{
|
|
if((tmpid = strtok( NULL , "|"))!= NULL)
|
|
{
|
|
items[i].lifespan = atoi(tmpid);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
while(row = mysql_fetch_row(result))
|
|
{
|
|
unsigned itemnum = atoi(row[5]);
|
|
items[itemnum].itemnum = atoi(row[0]);
|
|
items[itemnum].itemtype = atoi(row[1]);
|
|
items[itemnum].refine = atoi(row[2]);
|
|
items[itemnum].durability = atoi(row[3]);
|
|
items[itemnum].lifespan = atoi(row[4]);
|
|
}*/
|
|
DB->QFree( );
|
|
|
|
ADDSTRING ( pak, chars[k].char_name );
|
|
ADDBYTE ( pak, 0x00 );
|
|
ADDBYTE ( pak, chars[k].sex ); // SEX
|
|
ADDWORD ( pak, chars[k].level ); // LEVEL
|
|
ADDWORD ( pak, chars[k].classid ); // CLASSID
|
|
ADDDWORD ( pak, chars[k].DeleteTime ); // DELETE TIME
|
|
ADDBYTE ( pak, 0x00 );//thisclient->platinum?0x01:0x00 ); // IS PLATINUM? 00-NO;01-YES;02-YES BUT USER IS NOT
|
|
ADDDWORD ( pak, chars[k].face ); // FACE
|
|
ADDDWORD ( pak, chars[k].hairStyle ); // HAIR
|
|
ADDWORD ( pak, items[2].itemnum ); // CAP
|
|
ADDWORD ( pak, items[2].refine ); // CAP REFINE
|
|
ADDWORD ( pak, items[3].itemnum ); // BODY
|
|
ADDWORD ( pak, items[3].refine ); // BODY REFINE
|
|
ADDWORD ( pak, items[5].itemnum ); // GLOVES
|
|
ADDWORD ( pak, items[5].refine ); // GLOVES REFINE
|
|
ADDWORD ( pak, items[6].itemnum ); // BOOTS
|
|
ADDWORD ( pak, items[6].refine ); // BOOTS REFINE
|
|
ADDWORD ( pak, items[1].itemnum ); // FACE
|
|
ADDWORD ( pak, items[1].refine ); // FACE REFINE
|
|
ADDWORD ( pak, items[4].itemnum ); // BACK
|
|
ADDWORD ( pak, items[4].refine ); // BACK REFINE
|
|
ADDWORD ( pak, items[7].itemnum ); // WEAPON
|
|
ADDWORD ( pak, items[7].refine ); // WEAPON REFINE
|
|
ADDWORD ( pak, items[8].itemnum ); // SUBWEAPON
|
|
ADDWORD ( pak, items[8].refine ); // SUBWEAPON REFINE
|
|
}
|
|
thisclient->SendPacket( &pak );
|
|
return true;
|
|
}
|
|
|
|
// Send away the world IP
|
|
bool CCharServer::pakRequestWorld( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if (!thisclient->isLoggedIn) return false;
|
|
MYSQL_ROW row;
|
|
MYSQL_RES *result;
|
|
memcpy( thisclient->charname, &P->Buffer[3], P->Size-6-4 );
|
|
thisclient->charname[P->Size-6-4] = 0;
|
|
Log( MSG_INFO,"User %s(%i) selected char '%s'", thisclient->username, thisclient->userid, thisclient->charname);
|
|
if(!DB->QExecute("UPDATE accounts SET lastchar='%s' WHERE id=%i", thisclient->charname, thisclient->userid))
|
|
return false;
|
|
result = DB->QStore("SELECT host,port FROM channels WHERE id=%i", thisclient->channel);
|
|
if(result==NULL) return false;
|
|
if(mysql_num_rows( result )!=1 )
|
|
{
|
|
Log( MSG_WARNING, "Invalid Server: %i", thisclient->channel );
|
|
DB->QFree( );
|
|
return false;
|
|
}
|
|
row = mysql_fetch_row( result );
|
|
BEGINPACKET( pak, 0x711 );
|
|
ADDWORD ( pak, atoi(row[1]) ); // PORT
|
|
ADDDWORD ( pak, thisclient->userid );
|
|
ADDDWORD ( pak, 0x87654321 );
|
|
ADDSTRING ( pak, row[0] );//IP
|
|
ADDBYTE ( pak, 0 );
|
|
thisclient->SendPacket( &pak );
|
|
DB->QFree( );
|
|
//CHAR INFORMATION 0 1 2 3 4
|
|
result = DB->QStore("SELECT clanid,clan_rank,id,level,classid FROM characters WHERE char_name='%s'", thisclient->charname);
|
|
if(result==NULL) return false;
|
|
if(mysql_num_rows(result)!=1)
|
|
{
|
|
Log( MSG_WARNING, "Number of user with charname '%s' is %i", thisclient->charname,mysql_num_rows(result));
|
|
DB->QFree( );
|
|
return false;
|
|
}
|
|
row = mysql_fetch_row( result );
|
|
thisclient->clanid = atoi( row[0] );
|
|
thisclient->clan_rank = atoi( row[1] );
|
|
thisclient->charid = atoi( row[2] );
|
|
thisclient->level = atoi( row[3] );
|
|
thisclient->job = atoi( row[4] );
|
|
DB->QFree( );
|
|
//MESSENGER INFORMATION
|
|
// // 0 1
|
|
result = DB->QStore("SELECT idfriend,namefriend FROM list_friend WHERE id=%i", thisclient->charid);
|
|
if(result==NULL) return false;
|
|
BYTE nfriends = mysql_num_rows(result) & 0xff;
|
|
|
|
RESETPACKET( pak, 0x7e1 );// Friend list command
|
|
ADDBYTE ( pak, 0x06 );// Sending Friend List
|
|
ADDBYTE ( pak, nfriends );// # friends
|
|
while(row = mysql_fetch_row( result ))
|
|
{
|
|
CFriendList * newfriend = new CFriendList;
|
|
assert(newfriend);
|
|
newfriend->id = atoi(row[0]); //friendid
|
|
strcpy(newfriend->name, row[1]); //friend name
|
|
thisclient->FriendList.push_back( newfriend );
|
|
ADDWORD (pak, newfriend->id);// friend id
|
|
ADDWORD (pak, 0x0000 );
|
|
CCharClient* otherclient = (CCharClient*) GetClientByID( newfriend->id );
|
|
if(otherclient!=NULL) //is online??
|
|
{
|
|
ADDBYTE (pak, 0x07 ); //online
|
|
ChangeMessengerStatus ( thisclient, otherclient, 0x07);
|
|
}
|
|
else
|
|
{
|
|
ADDBYTE (pak, 0x08 );//offline
|
|
}
|
|
ADDSTRING (pak, newfriend->name); //friend name
|
|
ADDBYTE (pak, 0x00 );
|
|
}
|
|
thisclient->SendPacket( &pak );
|
|
DB->QFree( );
|
|
thisclient->logout = false;
|
|
|
|
//SEND CLAN INFORMATION
|
|
SendClanInfo (thisclient);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Create a character
|
|
bool CCharServer::pakCreateChar( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if (!thisclient->isLoggedIn) return false;
|
|
|
|
// Get info from packet
|
|
unsigned sex = GETBYTE((*P), 0 ) % 2;
|
|
unsigned hairstyle = GETBYTE((*P), 2 );
|
|
unsigned face = GETBYTE((*P), 3 );
|
|
string newname = (char*)&P->Buffer[7];
|
|
MYSQL_RES *result;
|
|
result = DB->QStore("SELECT id FROM characters WHERE account_name='%s'", thisclient->username);
|
|
if(result==NULL) return false;
|
|
if ( mysql_num_rows( result ) == 5 )
|
|
{
|
|
STARTPACKET( pak, 0x0713, 8 );
|
|
SETWORD ( pak, 0x00, 4 )
|
|
thisclient->SendPacket( &pak );
|
|
DB->QFree( );
|
|
return true;
|
|
}
|
|
DB->QFree( );
|
|
result = DB->QStore("SELECT id FROM characters WHERE char_name='%s'", newname.c_str());
|
|
if(result==NULL) return false;
|
|
if ( mysql_num_rows( result ) > 0 )
|
|
{
|
|
STARTPACKET( pak, 0x0713, 8 );
|
|
SETWORD ( pak, 0x00, 2 );
|
|
thisclient->SendPacket( &pak );
|
|
DB->QFree( );
|
|
return true;
|
|
}
|
|
DB->QFree( );
|
|
|
|
if(!DB->QExecute("INSERT INTO characters (account_name, char_name, face, hairStyle, sex) VALUES('%s','%s',%i,%i,%i)", thisclient->username, newname.c_str(), face, hairstyle, sex))
|
|
return false;
|
|
unsigned int mid = (unsigned)mysql_insert_id( DB->Mysql );
|
|
MYSQL_ROW row;
|
|
|
|
char tmp1[1024] = ""; //itemid
|
|
char tmp2[1024] = ""; //itemtype
|
|
char tmp3[1024] = ""; //refine
|
|
char tmp4[1024] = ""; //durability
|
|
char tmp5[1024] = ""; //lifespan
|
|
char tmp6[1024] = ""; //count
|
|
char tmp7[1024] = ""; //stats
|
|
char tmp8[1024] = ""; //socketed
|
|
char tmp9[1024] = ""; //appraised
|
|
|
|
sprintf(&tmp2[strlen(tmp2)], "0|0|0|3|0|0|0|8|0|0|0|0|2|0");
|
|
sprintf(&tmp3[strlen(tmp3)], "0|0|0|0|0|0|0|0|0|0|0|0|0|0");
|
|
sprintf(&tmp4[strlen(tmp4)], "0|0|0|40|0|0|0|40|0|0|0|0|40|0");
|
|
sprintf(&tmp5[strlen(tmp5)], "0|0|0|100|0|0|0|100|0|0|0|0|100|0");
|
|
sprintf(&tmp6[strlen(tmp6)], "0|0|0|1|0|0|0|1|0|0|0|0|1|0");
|
|
sprintf(&tmp7[strlen(tmp7)], "0|0|0|0|0|0|0|0|0|0|0|0|0|0");
|
|
sprintf(&tmp8[strlen(tmp8)], "0|0|0|0|0|0|0|0|0|0|0|0|0|0");
|
|
sprintf(&tmp9[strlen(tmp9)], "0|0|0|1|0|0|0|1|0|0|0|0|1|0");
|
|
int tran = 1;
|
|
|
|
//if(!DB->QExecute("INSERT INTO items VALUES(%i,30,3,0,40,100,3,1,0,0,0,0)", mid))
|
|
// return false;
|
|
//if(!DB->QExecute("INSERT INTO items VALUES(%i,1,8,0,40,100,7,1,0,0,0,0)", mid))
|
|
// return false;
|
|
if(sex==0)
|
|
{
|
|
//if(!DB->QExecute("INSERT INTO items VALUES(%i,222,2,0,40,100,12,1,0,0,0,0)", mid))
|
|
// return false;
|
|
sprintf(&tmp1[strlen(tmp1)], "0|0|0|30|0|0|0|1|0|0|0|0|222|0");
|
|
if(!DB->QExecute("INSERT INTO charitems (owner,itemid,itemtype,refine,durability,lifespan,count,stats,socketed,appraised,trans_action) VALUES('%i','%s','%s','%s','%s','%s','%s','%s','%s','%s','%i')",
|
|
mid,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7,tmp8,tmp9,tran))
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//if(!DB->QExecute("INSERT INTO items VALUES(%i,221,2,0,40,100,12,1,0,0,0,0)", mid))
|
|
// return false;
|
|
sprintf(&tmp1[strlen(tmp1)], "0|0|0|30|0|0|0|1|0|0|0|0|221|0");
|
|
if(!DB->QExecute("INSERT INTO charitems (owner,itemid,itemtype,refine,durability,lifespan,count,stats,socketed,appraised,trans_action) VALUES('%i','%s','%s','%s','%s','%s','%s','%s','%s','%s','%i')",
|
|
mid,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7,tmp8,tmp9,tran))
|
|
return false;
|
|
}
|
|
STARTPACKET( pak, 0x0713, 8 );
|
|
SETWORD ( pak, 0x00, 0 );
|
|
thisclient->SendPacket( &pak );
|
|
|
|
return true;
|
|
}
|
|
|
|
// Connect WorldServer
|
|
bool CCharServer::pakWSReady ( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
|
|
if(thisclient->isLoggedIn) return false;
|
|
if(GETDWORD((*P),0) != Config.CharPass )
|
|
{
|
|
Log( MSG_HACK, "WorldServer Tried to connect CharServer with wrong password ");
|
|
return true;
|
|
}
|
|
thisclient->userid = GETDWORD((*P), 4); //our channelid
|
|
thisclient->accesslevel = 0xffff; //this will identify thisclient as channel
|
|
|
|
// add channel
|
|
CChanels* newchannel = new (nothrow) CChanels;
|
|
if(newchannel==NULL)
|
|
return false;
|
|
|
|
newchannel->id = GETDWORD((*P), 4);
|
|
newchannel->ip = inet_ntoa( thisclient->clientinfo.sin_addr );
|
|
newchannel->port = GETWORD((*P),8 );
|
|
Log( MSG_INFO, "Channel #%i connected from ip %s", newchannel->id, newchannel->ip );
|
|
|
|
// Connect to charserver
|
|
newchannel->sock = socket( AF_INET, SOCK_STREAM, 0 );
|
|
if (newchannel->sock == INVALID_SOCKET)
|
|
{
|
|
Log( MSG_WARNING, "Could not access worldserver IP: %s , Port: %i", newchannel->ip, newchannel->port );
|
|
delete newchannel;
|
|
return false;
|
|
}
|
|
struct sockaddr_in ain;
|
|
ain.sin_family = AF_INET;
|
|
ain.sin_addr.s_addr = inet_addr(newchannel->ip);
|
|
ain.sin_port = htons( newchannel->port );
|
|
memset(&(ain.sin_zero), '\0', 8);
|
|
if ( connect( newchannel->sock , (SOCKADDR*) &ain, sizeof(ain) ) == SOCKET_ERROR)
|
|
{
|
|
Log( MSG_WARNING, "Could not access worldserver IP: %s , Port: %i", newchannel->ip , newchannel->port );
|
|
delete newchannel;
|
|
return false;
|
|
}
|
|
ChannelList.push_back( newchannel );
|
|
|
|
thisclient->isLoggedIn = true;
|
|
BEGINPACKET( pak, 0x500 );
|
|
ADDDWORD ( pak, Config.WorldPass );
|
|
//cryptPacket( (char*)&pak, NULL );
|
|
//EncryptBuffer( CryptTable,(unsigned char*)&pak );
|
|
Log( MSG_INFO, "Accessing worldserver IP: %s , Port: %i", newchannel->ip , newchannel->port );
|
|
send( newchannel->sock, (char*)&pak, pak.Size, 0 );
|
|
return true;
|
|
|
|
}
|
|
|
|
// Login Connected
|
|
bool CCharServer::pakLoginConnected( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if(thisclient->isLoggedIn) return false;
|
|
if(GETDWORD((*P),0) != Config.CharPass )
|
|
{
|
|
Log( MSG_HACK, "LoginServer Tried to connect CharServer with wrong password ");
|
|
return true;
|
|
}
|
|
thisclient->isLoggedIn = true;
|
|
return true;
|
|
}
|
|
|
|
// Return to char select
|
|
bool CCharServer::pakWSCharSelect ( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
//if(!thisclient->isLoggedIn) return false;
|
|
Log( MSG_INFO, "World server requested char select" );
|
|
|
|
unsigned int userid = GETDWORD( (*P), 0 );
|
|
CCharClient* otherclient = GetClientByUserID( userid );
|
|
if(otherclient==NULL)
|
|
{
|
|
Log(MSG_WARNING, "Invalid userid: %i", userid );
|
|
return true;
|
|
}
|
|
BEGINPACKET( pak, 0x71c );
|
|
//ADDBYTE ( pak, 0x00 );
|
|
otherclient->SendPacket( &pak );
|
|
Log( MSG_INFO, "Client returning to char select" );
|
|
return true;
|
|
}
|
|
|
|
// ???
|
|
bool CCharServer::pak7e5 ( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
BEGINPACKET( pak, 0 );
|
|
if(!thisclient->isLoggedIn) return false;
|
|
unsigned int action = GETBYTE((*P),0);
|
|
switch(action)
|
|
{
|
|
case 0x03:
|
|
RESETPACKET( pak, 0x7e5 );
|
|
ADDBYTE ( pak, 0x01 );
|
|
ADDWORD ( pak, 0x0000 );
|
|
thisclient->SendPacket( &pak );
|
|
break;
|
|
default:
|
|
Log( MSG_WARNING,"Unknown 7e5 action %i",action);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Create a chatroom?
|
|
bool CCharServer::pakChatrooms ( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if(!thisclient->isLoggedIn) return false;
|
|
return true;
|
|
}
|
|
|
|
// delete/resurect character
|
|
bool CCharServer::pakDeleteChar( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if(!thisclient->isLoggedIn) return false;
|
|
short int action = GETBYTE((*P), 1 );
|
|
unsigned long int DeleteTime = 0;
|
|
switch(action)
|
|
{
|
|
case 0x00://Resurect
|
|
{
|
|
DeleteTime = 0;
|
|
if(!DB->QExecute(" UPDATE characters SET deletetime=0 WHERE char_name='%s'",
|
|
(char*)&P->Buffer[2] ))
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x01://Delete
|
|
{
|
|
DeleteTime = GetServerTime( ) + Config.DeleteTime;
|
|
if(!DB->QExecute(" UPDATE characters SET deletetime=%i WHERE char_name='%s'",
|
|
DeleteTime, (char*)&P->Buffer[2] ))
|
|
return false;
|
|
|
|
}
|
|
break;
|
|
}
|
|
BEGINPACKET( pak, 0x714 );
|
|
if(DeleteTime > 0 )
|
|
{
|
|
ADDDWORD ( pak, Config.DeleteTime );
|
|
}
|
|
else
|
|
{
|
|
ADDDWORD ( pak, 0x00000000 );
|
|
}
|
|
ADDSTRING ( pak, (char*)&P->Buffer[2] );
|
|
ADDBYTE ( pak, 0x00 );
|
|
thisclient->SendPacket( &pak );
|
|
return true;
|
|
}
|
|
|
|
bool CCharServer::pakUpdateLevel( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
if(!thisclient->isLoggedIn) return false;
|
|
WORD charid = GETWORD((*P),0);
|
|
WORD level = GETWORD((*P),2);
|
|
for(UINT i=0;i<ClientList.size();i++)
|
|
{
|
|
CCharClient* player = (CCharClient*) ClientList.at(i);
|
|
if(player->charid==charid)
|
|
{
|
|
player->level = level;
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Disconnect client from char/world server
|
|
bool CCharServer::pakLoginDSClient( CCharClient* thisclient, CPacket* P )
|
|
{
|
|
|
|
if(!thisclient->isLoggedIn) return false;
|
|
BYTE action = GETBYTE((*P),0);
|
|
switch(action)
|
|
{
|
|
case 1:
|
|
{
|
|
unsigned int userid = GETDWORD ((*P), 1);
|
|
CCharClient* otherclient = GetClientByUserID( userid );
|
|
if(otherclient==NULL)
|
|
{
|
|
Log( MSG_WARNING, "Userid '%u' is not online", userid );
|
|
return true;
|
|
}
|
|
otherclient->isLoggedIn = false;
|
|
otherclient->isActive = false;
|
|
BEGINPACKET( pak, 0x502 );
|
|
ADDBYTE ( pak, 1 );
|
|
ADDDWORD ( pak, userid );
|
|
ADDBYTE ( pak, 0x00 );
|
|
CChanels* thischannel = GetChannelByID( otherclient->channel );
|
|
if(thischannel!=NULL){
|
|
send( thischannel->sock, (char*)&pak, pak.Size, 0 );}
|
|
else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);}
|
|
}
|
|
break;
|
|
}
|
|
return true;
|
|
}
|