// Return to char select bool CCharServer::pakWSCharSelect ( CCharClient* thisclient, CPacket* P ) { if(!thisclient->isLoggedIn) return false; Log( MSG_INFO, "World server requested char select" ); DWORD 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" ); RESETPACKET( pak, 0x505 ); ADDDWORD( pak, thisclient->userid ); //cryptPacket( (char*)&pak, NULL ); CChanels* thischannel = GetChannelByID( thisclient->channel ); if(thischannel!=NULL) { send( thischannel->sock, (char*)&pak, pak.Size, 0 ); } //LMA: resetting chatroom ID. DisconnectClientFromChat(thisclient); return true; }
// When a a client is disconnected void CCharServer::OnClientDisconnect( CClientSocket* thisclient ) { CCharClient* thisclientwc = (CCharClient*)thisclient; if(!thisclientwc->logout) { // Send logout message to friends for(UINT i=0; i<thisclientwc->FriendList.size( ); i++) { CFriendList* Friend = thisclientwc->FriendList.at( i );; CCharClient* otherclient = GetClientByID( Friend->id ); if(otherclient!=NULL) { ChangeMessengerStatus ( thisclientwc, otherclient, 0x08); } } //set logout messga to clan CClans* thisclan = GetClanByID(thisclientwc->clanid); if(thisclan==NULL) return; for(UINT i=0; i<thisclan->ClanMembers.size( ); i++) { CClanMembers* ClanMember = thisclan->ClanMembers.at( i ); CCharClient* otherclient = GetClientByID( ClanMember->id ); if(otherclient!=NULL) ChangeClanStatus (thisclientwc, otherclient, 0xff); } //LMA: Disconnecting a client from chatroom. DisconnectClientFromChat(thisclientwc ); } }
// Get this clients character list bool CCharServer::pakGetCharacters( CCharClient* thisclient, CPacket* P ) { if (!thisclient->isLoggedIn) return false; if(!DB->QExecute( "DELETE FROM characters WHERE deletetime>0 AND deletetime<=%i",GetServerTime( ) )) return false; MYSQL_RES *result; MYSQL_ROW row; 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)) { memset( &chars[charnum].char_name, '\0', 17 ); 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); if(result==NULL) return false; 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]); //LMA: now with 2010/05, naRose handles until refine 15 //LMA: little check, refine from 1 to 15 are not valid since it's refine*16 that's we're supposed to store now... if(items[itemnum].refine>0&&items[itemnum].refine<=15) { Log(MSG_WARNING,"Invalid refine %i for item (%i:%i) for %s",items[itemnum].refine,items[itemnum].itemtype,items[itemnum].itemnum,thisclient->username); items[itemnum].refine*=16; } //Another check, just to be sure. //LMA: up to refine 15 now (2010/05)... switch (items[itemnum].refine) { case 0: case 16: case 32: case 48: case 64: case 80: case 96: case 112: case 128: case 144: case 160: case 176: case 192: case 208: case 224: case 240: { //Ok. } break; default: { Log(MSG_WARNING,"Invalid refine %i for item (%i:%i) for %s",items[itemnum].refine,items[itemnum].itemtype,items[itemnum].itemnum,thisclient->username); items[itemnum].refine=0; } break; } } 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 ); //LMA: we clean the chat ID. if (thisclient->chatroom_id!=0) { DisconnectClientFromChat(thisclient); } return true; }
//LMA: Talking in a chatroom. bool CCharServer::pakChatrooms ( CCharClient* thisclient, CPacket* P ) { if(!thisclient->isLoggedIn) return false; BYTE action = GETBYTE((*P),0); switch(action) { case 0x01: { //Asking for the chatroom list. if(thisclient->chatroom_id!=0) { //if already in a chatroom you can't ask for that. BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x22 ); thisclient->SendPacket( &pak ); return true; } //LMA: we have to clean the chatrooms if needed if(chatroom_list.size()!=0) { map<DWORD,CChatroom*>::iterator it; for ( it=chatroom_list.begin() ; it != chatroom_list.end(); it++ ) { if((*it).second->People_list.size()==0) { chatroom_list.erase((*it).second->chatroom_id); continue; } //checking members now. for (int k=0;k<(*it).second->People_list.size();k++) { CCharClient* otherclient=GetClientByID((*it).second->People_list.at(k)->charid); if(otherclient==NULL) { (*it).second->People_list.erase((*it).second->People_list.begin()+k); k=0; continue; } } if((*it).second->People_list.size()==0) { chatroom_list.erase((*it).second->chatroom_id); continue; } } } BEGINPACKET( pak, 0x7e3); ADDBYTE ( pak, 0x21 ); ADDBYTE ( pak, chatroom_list.size() ); if(chatroom_list.size()!=0) { map<DWORD,CChatroom*>::iterator it; for ( it=chatroom_list.begin() ; it != chatroom_list.end(); it++ ) { if ((*it).second->is_protected) { ADDBYTE ( pak, 0x01 ); } else { ADDBYTE ( pak, 0x00 ); } ADDWORD ( pak, (*it).second->chatroom_id); ADDBYTE ( pak, (*it).second->People_list.size()); //Nb of people inside. ADDSTRING ( pak, (*it).second->chatroom_name.c_str()); ADDBYTE ( pak, 0x00); } } thisclient->SendPacket( &pak ); } break; case 0x02: { //Creating a chatroom. BYTE protection_asked=GETBYTE((*P),1); BYTE max_people=GETBYTE((*P),2); string chatroom_name = (char*) &P->Buffer[3]; string password=""; if(protection_asked==1) { password = (char*) &P->Buffer[3+chatroom_name.size()+1]; if (password.size()>4) { Log(MSG_WARNING,"Player %s tried to give a weird password %s to his chatroom.",thisclient->charname,password.c_str()); password=""; protection_asked=0; } } if (thisclient->chatroom_id!=0) { //already in a chat room. BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x22 ); thisclient->SendPacket( &pak ); return true; } if(max_people==0||chatroom_name.size()==0) { //bogus (but non blocking) error. BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x13 ); thisclient->SendPacket( &pak ); return true; } //Checking if the chatroom name is already taken? map<DWORD,CChatroom*>::iterator it; for ( it=chatroom_list.begin() ; it != chatroom_list.end(); it++ ) { if ((*it).second->chatroom_name==chatroom_name) { //Name already taken, sorry ^_^ BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x18 ); thisclient->SendPacket( &pak ); return true; } } //getting a chatroom ID, like client Id, loop. last_chatroom_id=GetChatroomID ( last_chatroom_id ); if (last_chatroom_id==0xffff) { //bogus (but non blocking) error. BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x13 ); thisclient->SendPacket( &pak ); return true; } CChatroom* newchatroom=new (nothrow) CChatroom; newchatroom->chatroom_id=last_chatroom_id; newchatroom->chatroom_name=chatroom_name; newchatroom->creation_time=time(NULL); newchatroom->nb_max=max_people; newchatroom->password=""; newchatroom->is_protected=false; if (protection_asked==1) { newchatroom->password=password; newchatroom->is_protected=true; } newchatroom->People_list.clear(); //adding the owner for now. CPeople* mypeople=new (nothrow) CPeople; mypeople->account_id=thisclient->userid; mypeople->charid=thisclient->charid; mypeople->charname=thisclient->charname; mypeople->is_active=true; newchatroom->People_list.push_back(mypeople); //adding the new chatroom. chatroom_list[last_chatroom_id]=newchatroom; thisclient->chatroom_id=last_chatroom_id; BEGINPACKET( pak, 0x7e3); ADDBYTE ( pak, 0x01 ); ADDWORD ( pak, thisclient->userid ); ADDWORD ( pak, last_chatroom_id ); //TODO: check if chat ID? ADDWORD ( pak, 0x2066 ); //???? ADDSTRING ( pak, chatroom_name.c_str()); ADDBYTE ( pak, 0x00); thisclient->SendPacket( &pak ); } break; case 0x03: { //joining a chatroom. WORD chatroom_id=GETWORD((*P),2); if (chatroom_list.find(chatroom_id)==chatroom_list.end()) { //LMA: chatroom not found. Log(MSG_WARNING,"Player %s asked to join chatroom %u but it didn't exist.",thisclient->charname,chatroom_id); BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x13 ); thisclient->SendPacket( &pak ); return true; } //checking the password if needed. if (chatroom_list[chatroom_id]->is_protected==1) { if (P->Size<5) { Log(MSG_WARNING,"The chatroom has a password and the player %s didn't send one.",thisclient->charname); BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x12 ); thisclient->SendPacket( &pak ); return true; } string password = (char*) &P->Buffer[4]; if (password!=chatroom_list[chatroom_id]->password) { Log(MSG_WARNING,"Player %s tried to connect to chatroom %s with a wrong password %s != %s",thisclient->charname,chatroom_list[chatroom_id]->chatroom_name.c_str(),password.c_str(),chatroom_list[chatroom_id]->password.c_str()); BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x12 ); thisclient->SendPacket( &pak ); return true; } } CChatroom* mychatroom=chatroom_list[chatroom_id]; int nb_users=mychatroom->People_list.size(); int max_users=0; bool is_ok=false; for (int k=0;k<nb_users;k++) { if (mychatroom->People_list.at(k)->charid==thisclient->charid) { if (!mychatroom->People_list.at(k)->is_active) { //User leaved earlier? is_ok=true; mychatroom->People_list.at(k)->is_active=true; break; } //player is already in the chatroom... break; } max_users++; } if(max_users<=mychatroom->nb_max) { is_ok=true; } else { //chatroom is full BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x11 ); thisclient->SendPacket( &pak ); return true; } if(!is_ok) { BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x22 ); thisclient->SendPacket( &pak ); return true; } //adding the player. CPeople* mypeople=new (nothrow) CPeople; mypeople->account_id=thisclient->userid; mypeople->charid=thisclient->charid; mypeople->charname=thisclient->charname; mypeople->is_active=true; mychatroom->People_list.push_back(mypeople); BEGINPACKET( pak, 0x7e3); ADDBYTE ( pak, 0x10 ); ADDWORD ( pak, thisclient->userid ); ADDWORD ( pak, 0x9031 ); //???? ADDWORD ( pak, mychatroom->nb_max ); //Nb max people??? ADDSTRING ( pak, mychatroom->chatroom_name.c_str()); ADDBYTE ( pak, 0x00); //looping through people list here. nb_users=mychatroom->People_list.size(); for (int k=0;k<nb_users;k++) { if (mychatroom->People_list.at(k)->charid==thisclient->charid) { continue; } ADDWORD ( pak, mychatroom->People_list.at(k)->account_id ); ADDDWORD ( pak, mychatroom->People_list.at(k)->charid ); ADDSTRING ( pak, mychatroom->People_list.at(k)->charname.c_str()); ADDBYTE ( pak, 0x00); } thisclient->SendPacket( &pak ); thisclient->chatroom_id=mychatroom->chatroom_id; //We must tell the others someone came in... for (int k=0;k<nb_users;k++) { if (mychatroom->People_list.at(k)->charid==thisclient->charid) { continue; } CCharClient* otherclient=GetClientByID(mychatroom->People_list.at(k)->charid); if (otherclient==NULL) { continue; } BEGINPACKET( pak, 0x7e3); ADDBYTE ( pak, 0x14); ADDWORD ( pak, thisclient->userid ); ADDDWORD ( pak, thisclient->charid ); ADDSTRING ( pak, thisclient->charname); ADDBYTE ( pak, 0x00); otherclient->SendPacket( &pak ); } } break; case 0x04: { //Asking to leave the chatroom. It seems for now there's a bug in naRose and you just can't leave? BEGINPACKET( pak, 0x7e3 ); ADDBYTE ( pak, 0x15 ); thisclient->SendPacket( &pak ); DisconnectClientFromChat(thisclient); return true; } default: { Log(MSG_WARNING,"Asking for an uncoded chatroom request %i",action); } break; } return true; }