void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { std::string name; uint8 race_,class_; recv_data >> name; recv_data >> race_; recv_data >> class_; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if(GetSecurity() == SEC_PLAYER) { if(uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; uint32 team = Player::TeamForRace(race_); switch(team) { case ALLIANCE: disabled = mask & (1<<0); break; case HORDE: disabled = mask & (1<<1); break; } if(disabled) { data << (uint8)CHAR_CREATE_DISABLED; SendPacket( &data ); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if( !classEntry || !raceEntry ) { data << (uint8)CHAR_CREATE_FAILED; SendPacket( &data ); sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating with invalid name if (!normalizePlayerName(name)) { data << (uint8)CHAR_NAME_NO_NAME; SendPacket( &data ); sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); return; } // check name limitations uint8 res = ObjectMgr::CheckPlayerName(name,true); if (res != CHAR_NAME_SUCCESS) { data << uint8(res); SendPacket( &data ); return; } if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) { data << (uint8)CHAR_NAME_RESERVED; SendPacket( &data ); return; } if (objmgr.GetPlayerGUIDByName(name)) { data << (uint8)CHAR_CREATE_NAME_IN_USE; SendPacket( &data ); return; } QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); delete resultacct; if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) { data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; SendPacket( &data ); return; } } QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); uint8 charcount = 0; if ( result ) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) { data << (uint8)CHAR_CREATE_SERVER_LIMIT; SendPacket( &data ); return; } } bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; if(!AllowTwoSideAccounts || skipCinematics == 1) { QueryResult *result2 = CharacterDatabase.PQuery("SELECT race FROM characters WHERE account = '%u' %s", GetAccountId(), (skipCinematics == 1) ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 acc_race = field[0].GetUInt32(); // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { uint32 acc_team=0; if(acc_race > 0) acc_team = Player::TeamForRace(acc_race); if(acc_team != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); delete result2; return; } } // search same race for cinematic or same class if need // TODO: check if cinematic already shown? (already logged in?; cinematic field) while (skipCinematics == 1 && !have_same_race) { if(!result2->NextRow()) break; field = result2->Fetch(); acc_race = field[0].GetUInt32(); have_same_race = race_ == acc_race; } delete result2; } } // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; Player * pNewChar = new Player(this); if(!pNewChar->Create( objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId )) { // Player not create (race/class problem?) delete pNewChar; data << (uint8)CHAR_CREATE_ERROR; SendPacket( &data ); return; } if ((have_same_race && skipCinematics == 1) || skipCinematics == 2) pNewChar->setCinematic(1); // not show intro // Player created, save it now pNewChar->SaveToDB(); charcount+=1; loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); delete pNewChar; // created only to call SaveToDB() data << (uint8)CHAR_CREATE_SUCCESS; SendPacket( &data ); std::string IP_str = GetRemoteAddress(); sLog.outBasic("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); sLog.outChar("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); }
void WorldSession::HandleSendMail(WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+1+1+1+4+4+1+4+4+8+1); uint64 mailbox, unk3; std::string receiver, subject, body; uint32 unk1, unk2, money, COD; uint8 unk4; recv_data >> mailbox; recv_data >> receiver; // recheck CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+1+1+4+4+1+4+4+8+1); recv_data >> subject; // recheck CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+1+4+4+1+4+4+8+1); recv_data >> body; // recheck CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+(body.size()+1)+4+4+1+4+4+8+1); recv_data >> unk1; // stationery? recv_data >> unk2; // 0x00000000 MailItemsInfo mi; uint8 items_count; recv_data >> items_count; // attached items count if(items_count > 12) // client limit return; // recheck CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+(body.size()+1)+4+4+1+items_count*(1+8)+4+4+8+1); if(items_count) { for(uint8 i = 0; i < items_count; ++i) { uint8 item_slot; uint64 item_guid; recv_data >> item_slot; recv_data >> item_guid; mi.AddItem(GUID_LOPART(item_guid), item_slot); } } recv_data >> money >> COD; // money and cod recv_data >> unk3; // const 0 recv_data >> unk4; // const 0 items_count = mi.size(); // this is the real size after the duplicates have been removed if (receiver.empty()) return; Player* pl = _player; uint64 rc = 0; if(normalizePlayerName(receiver)) rc = objmgr.GetPlayerGUIDByName(receiver); if (!rc) { sLog.outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); pl->SendMailResult(0, 0, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } sLog.outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if(pl->GetGUID() == rc) { pl->SendMailResult(0, 0, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 reqmoney = money + 30; if (items_count) reqmoney = money + (30 * items_count); if (pl->GetMoney() < reqmoney) { pl->SendMailResult(0, 0, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player *receive = objmgr.GetPlayer(rc); uint32 rc_team = 0; uint8 mails_count = 0; //do not allow to send to one player more than 100 mails if(receive) { rc_team = receive->GetTeam(); mails_count = receive->GetMailSize(); } else { rc_team = objmgr.GetPlayerTeamByGUID(rc); QueryResult* result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", GUID_LOPART(rc)); if(result) { Field *fields = result->Fetch(); mails_count = fields[0].GetUInt32(); delete result; } } //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mails_count > 100) { pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); return; } // test the receiver's Faction... if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && GetSecurity() == SEC_PLAYER) { pl->SendMailResult(0, 0, MAIL_ERR_NOT_YOUR_TEAM); return; } if (items_count) { for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter) { MailItem& mailItem = mailItemIter->second; if(!mailItem.item_guidlow) { pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); return; } mailItem.item = pl->GetItemByGuid(MAKE_NEW_GUID(mailItem.item_guidlow, 0, HIGHGUID_ITEM)); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if(!mailItem.item || !mailItem.item->CanBeTraded()) { pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); return; } if (mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || mailItem.item->GetUInt32Value(ITEM_FIELD_DURATION)) { pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR); return; } if(COD && mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED)) { pl->SendMailResult(0, 0, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } } } pl->SendMailResult(0, 0, MAIL_OK); uint32 itemTextId = 0; if (!body.empty()) { itemTextId = objmgr.CreateItemText( body ); } pl->ModifyMoney( -int32(reqmoney) ); bool needItemDelay = false; if(items_count > 0 || money > 0) { uint32 rc_account = 0; if(receive) rc_account = receive->GetSession()->GetAccountId(); else rc_account = objmgr.GetPlayerAccountIdByGUID(rc); if (items_count > 0) { for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter) { MailItem& mailItem = mailItemIter->second; if(!mailItem.item) continue; mailItem.item_template = mailItem.item ? mailItem.item->GetEntry() : 0; if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) { sLog.outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), mailItem.item->GetProto()->Name1, mailItem.item->GetEntry(), mailItem.item->GetCount(), receiver.c_str(), rc_account); } pl->MoveItemFromInventory(mailItem.item->GetBagSlot(), mailItem.item->GetSlot(), true); CharacterDatabase.BeginTransaction(); mailItem.item->DeleteFromInventoryDB(); //deletes item from character's inventory mailItem.item->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), mailItem.item->GetGUIDLow()); CharacterDatabase.CommitTransaction(); } // if item send to character at another account, then apply item delivery delay needItemDelay = pl->GetSession()->GetAccountId() != rc_account; } if(money > 0 && GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list WorldSession::SendMailTo(receive, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, pl->GetGUIDLow(), GUID_LOPART(rc), subject, itemTextId, &mi, money, COD, MAIL_CHECK_MASK_NONE, deliver_delay); CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { // check character count { QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account); uint8 charcount = 0; if (result) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= 10) return DUMP_TOO_MANY_CHARS; } } FILE *fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult * result = NULL; char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < sObjectMgr.m_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid); if (result) { guid = sObjectMgr.m_hiCharGuid; // use first free if exists delete result; } else incHighest = false; } else guid = sObjectMgr.m_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { name = ""; // use the one from the dump delete result; } } else name = ""; // name encoded or empty snprintf(newguid, 20, "%d", guid); snprintf(chraccount, 20, "%d", account); snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32,uint32> items; std::map<uint32,uint32> mails; std::map<uint32,uint32> itemTexts; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while(!feof(fin)) { if(!fgets(buf, 32000, fin)) { if(feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if(nw_pos==std::string::npos) continue; // skip NOTE if(line.substr(nw_pos,15)=="IMPORTANT NOTE:") continue; // add required_ check if(line.substr(nw_pos,41)=="UPDATE character_db_version SET required_") { if(!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } // determine table name and load type std::string tn = gettablename(line); if(tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type; uint8 i; for(i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch(type) { case DTT_CHAR_TABLE: if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: // character t. { if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // guid, data field:guid, items if(!changenth(line, 2, chraccount)) ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line, 3); if(!changetoknth(vals, OBJECT_FIELD_GUID+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); for(uint16 field = PLAYER_FIELD_INV_SLOT_HEAD; field < PLAYER_FARSIGHT; field++) if(!changetokGuid(vals, field+1, items, sObjectMgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 4); CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { delete result; if(!changenth(line, 37, "1")) // rename on login: `at_login` field 37 in raw field list ROLLBACK(DUMP_FILE_BROKEN); } } else if(!changenth(line, 4, name.c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_INVENTORY: // character_inventory t. { if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // bag, item if(!changeGuid(line, 2, items, sObjectMgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 4, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM: // item_instance t. { // item, owner, data field:item, owner guid if(!changeGuid(line, 1, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 2, newguid)) ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line,3); if(!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, sObjectMgr.m_ItemTextId,true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: // character_gift { // guid,item_guid, if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 2, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET: // character_pet t { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if(strlen(lastpetid)==0) snprintf(lastpetid, 20, "%s", currpetid); if(strcmp(lastpetid,currpetid)!=0) { snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if(petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } // item, entry, owner, ... if(!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown t { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if(petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if(!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { // id,messageType,stationery,mailtemplate,sender,receiver,subject,itemText if(!changeGuid(line, 1, mails, sObjectMgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 6, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 8, itemTexts, sObjectMgr.m_ItemTextId)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { // mail_id,item_guid,item_template,receiver if(!changeGuid(line, 1, mails, sObjectMgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 2, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 4, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_TEXT: // item_text { // id if(!changeGuid(line, 1, itemTexts, sObjectMgr.m_ItemTextId)) ROLLBACK(DUMP_FILE_BROKEN); // add it to cache uint32 id= atoi(getnth(line,1).c_str()); std::string text = getnth(line,2); sObjectMgr.AddItemText(id,text); break; } default: sLog.outError("Unknown dump table type: %u",type); break; } if(!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); sObjectMgr.m_hiItemGuid += items.size(); sObjectMgr.m_mailid += mails.size(); sObjectMgr.m_ItemTextId += itemTexts.size(); if(incHighest) ++sObjectMgr.m_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }
void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE"); std::string membername; recvData >> membername; recvData.read_skip<uint32>(); // attempt add selected player // cheating if (!normalizePlayerName(membername)) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } Player* invitingPlayer = GetPlayer(); Player* invitedPlayer = ObjectAccessor::FindPlayerByName(membername); // no player if (!invitedPlayer) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } // player trying to invite himself (most likely cheating) if (invitedPlayer == invitingPlayer) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } // restrict invite to GMs if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !invitingPlayer->IsGameMaster() && invitedPlayer->IsGameMaster()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } // can't group with if (!invitingPlayer->IsGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && invitingPlayer->GetTeam() != invitedPlayer->GetTeam()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); return; } if (invitingPlayer->GetInstanceId() != 0 && invitedPlayer->GetInstanceId() != 0 && invitingPlayer->GetInstanceId() != invitedPlayer->GetInstanceId() && invitingPlayer->GetMapId() == invitedPlayer->GetMapId()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); return; } // just ignore us if (invitedPlayer->GetInstanceId() != 0 && invitedPlayer->GetDungeonDifficulty() != invitingPlayer->GetDungeonDifficulty()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); return; } if (invitedPlayer->GetSocial()->HasIgnore(invitingPlayer->GetGUID())) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); return; } if (!invitedPlayer->GetSocial()->HasFriend(invitingPlayer->GetGUID()) && invitingPlayer->getLevel() < sWorld->getIntConfig(CONFIG_PARTY_LEVEL_REQ)) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_INVITE_RESTRICTED); return; } Group* group = invitingPlayer->GetGroup(); if (group && group->isBGGroup()) group = invitingPlayer->GetOriginalGroup(); if (!group) group = invitingPlayer->GetGroupInvite(); Group* group2 = invitedPlayer->GetGroup(); if (group2 && group2->isBGGroup()) group2 = invitedPlayer->GetOriginalGroup(); // player already in another group or invited if (group2 || invitedPlayer->GetGroupInvite()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); if (group2) { // tell the player that they were invited but it failed as they were already in a group WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size data << uint8(0); // invited/already in group flag data << invitingPlayer->GetName(); // max len 48 data << uint32(0); // unk data << uint8(0); // count data << uint32(0); // unk invitedPlayer->SendDirectMessage(&data); } return; } if (group) { // not have permissions for invite if (!group->IsLeader(invitingPlayer->GetGUID()) && !group->IsAssistant(invitingPlayer->GetGUID())) { if (group->IsCreated()) SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); return; } // not have place if (group->IsFull()) { SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); return; } } // ok, but group not exist, start a new group // but don't create and save the group to the DB until // at least one person joins if (!group) { group = new Group(); // new group: if can't add then delete if (!group->AddLeaderInvite(invitingPlayer)) { delete group; return; } if (!group->AddInvite(invitedPlayer)) { group->RemoveAllInvites(); delete group; return; } } else { // already existed group: if can't add then just leave if (!group->AddInvite(invitedPlayer)) { return; } } // ok, we do it WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size data << uint8(1); // invited/already in group flag data << invitingPlayer->GetName(); // max len 48 data << uint32(0); // unk data << uint8(0); // count data << uint32(0); // unk invitedPlayer->SendDirectMessage(&data); SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); }
/** * Handles the Packet sent by the client when sending a mail. * * This methods takes the packet sent by the client and performs the following actions: * - Checks whether the mail is valid: i.e. can he send the selected items, * does he have enough money, etc. * - Creates a MailDraft and adds the needed items, money, cost data. * - Sends the mail. * * Depending on the outcome of the checks performed the player will recieve a different * MailResponseResult. * * @see MailResponseResult * @see SendMailResult() * * @param recv_data the WorldPacket containing the data sent by the client. */ void WorldSession::HandleSendMail(WorldPacket & recv_data ) { uint64 mailbox, unk3; std::string receiver, subject, body; uint32 unk1, unk2, money, COD; uint8 unk4; recv_data >> mailbox; recv_data >> receiver; recv_data >> subject; recv_data >> body; recv_data >> unk1; // stationery? recv_data >> unk2; // 0x00000000 uint8 items_count; recv_data >> items_count; // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam return; } uint64 itemGUIDs[MAX_MAIL_ITEMS]; for(uint8 i = 0; i < items_count; ++i) { recv_data.read_skip<uint8>(); // item slot in mail, not used recv_data >> itemGUIDs[i]; } recv_data >> money >> COD; // money and cod recv_data >> unk3; // const 0 recv_data >> unk4; // const 0 // packet read complete, now do check if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; if (receiver.empty()) return; Player* pl = _player; ObjectGuid rc; if (normalizePlayerName(receiver)) rc = sObjectMgr.GetPlayerGUIDByName(receiver); if (rc.IsEmpty()) { DETAIL_LOG("%s is sending mail to %s (GUID: nonexistent!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGuidStr().c_str(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } DETAIL_LOG("%s is sending mail to %s with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGuidStr().c_str(), rc.GetString().c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if (pl->GetObjectGuid() == rc) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint32 reqmoney = cost + money; if (pl->GetMoney() < reqmoney) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player *receive = sObjectMgr.GetPlayer(rc); Team rc_team; uint8 mails_count = 0; // do not allow to send to one player more than 100 mails if (receive) { rc_team = receive->GetTeam(); mails_count = receive->GetMailSize(); } else { rc_team = sObjectMgr.GetPlayerTeamByGUID(rc); if (QueryResult* result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", rc.GetCounter())) { Field *fields = result->Fetch(); mails_count = fields[0].GetUInt32(); delete result; } } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mails_count > 100) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // check the receiver's Faction... if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && GetSecurity() == SEC_PLAYER) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(rc); Item* items[MAX_MAIL_ITEMS]; for(uint8 i = 0; i < items_count; ++i) { if (!itemGUIDs[i]) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = pl->GetItemByGuid(itemGUIDs[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if(!item) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && pl->GetSession()->GetAccountId() != rc_account) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); return; } if ((item->GetProto()->Flags & ITEM_FLAG_CONJURED) || item->GetUInt32Value(ITEM_FIELD_DURATION)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } items[i] = item; } pl->SendMailResult(0, MAIL_SEND, MAIL_OK); pl->ModifyMoney( -int32(reqmoney) ); pl->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); if (items_count > 0 || money > 0) { if (items_count > 0) { for(uint8 i = 0; i < items_count; ++i) { Item* item = items[i]; if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), item->GetProto()->Name1, item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account); } pl->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(); // deletes item from character's inventory item->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", rc.GetCounter(), item->GetGUIDLow()); CharacterDatabase.CommitTransaction(); draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = pl->GetSession()->GetAccountId() != rc_account; } if (money > 0 && GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_UINT32_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list draft .SetMoney(money) .SetCOD(COD) .SendMailTo(MailReceiver(receive, rc), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
static bool HandlePDumpLoadCommand(ChatHandler* handler, char const* args) { if (!*args) return false; char* fileStr = strtok((char*)args, " "); if (!fileStr) return false; char* accountStr = strtok(NULL, " "); if (!accountStr) return false; std::string accountName = accountStr; if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } uint32 accountId = AccountMgr::GetId(accountName); if (!accountId) { accountId = atoi(accountStr); // use original string if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } } if (!AccountMgr::GetName(accountId, accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } char* guidStr = NULL; char* nameStr = strtok(NULL, " "); std::string name; if (nameStr) { name = nameStr; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME); handler->SetSentErrorMessage(true); return false; } if (ObjectMgr::CheckPlayerName(name, true) != CHAR_NAME_SUCCESS) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME); handler->SetSentErrorMessage(true); return false; } guidStr = strtok(NULL, " "); } uint32 guid = 0; if (guidStr) { guid = uint32(atoi(guidStr)); if (!guid) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_GUID); handler->SetSentErrorMessage(true); return false; } if (sObjectMgr->GetPlayerAccountIdByGUID(ObjectGuid(HIGHGUID_PLAYER, guid))) { handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, guid); handler->SetSentErrorMessage(true); return false; } } switch (PlayerDumpReader().LoadDump(fileStr, accountId, name, guid)) { case DUMP_SUCCESS: handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); break; case DUMP_FILE_OPEN_ERROR: handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileStr); handler->SetSentErrorMessage(true); return false; case DUMP_FILE_BROKEN: handler->PSendSysMessage(LANG_DUMP_BROKEN, fileStr); handler->SetSentErrorMessage(true); return false; case DUMP_TOO_MANY_CHARS: handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, accountName.c_str(), accountId); handler->SetSentErrorMessage(true); return false; default: handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); handler->SetSentErrorMessage(true); return false; } return true; }
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { std::string name; uint8 race_, class_; recv_data >> name; recv_data >> race_; recv_data >> class_; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if(GetSecurity() == SEC_PLAYER) { if(uint32 mask = sWorld.getConfig(CONFIG_UINT32_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; uint32 team = Player::TeamForRace(race_); switch(team) { case ALLIANCE: disabled = mask & (1 << 0); break; case HORDE: disabled = mask & (1 << 1); break; } if(disabled) { data << (uint8)CHAR_CREATE_DISABLED; SendPacket( &data ); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if( !classEntry || !raceEntry ) { data << (uint8)CHAR_CREATE_FAILED; SendPacket( &data ); sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating Expansion race without Expansion account if (raceEntry->expansion > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION; sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, race_); SendPacket( &data ); return; } // prevent character creating Expansion class without Expansion account if (classEntry->expansion > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION_CLASS; sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, class_); SendPacket( &data ); return; } // prevent character creating with invalid name if (!normalizePlayerName(name)) { data << (uint8)CHAR_NAME_NO_NAME; SendPacket( &data ); sLog.outError("Account:[%d] but tried to Create character with empty [name]", GetAccountId()); return; } // check name limitations uint8 res = ObjectMgr::CheckPlayerName(name, true); if (res != CHAR_NAME_SUCCESS) { data << uint8(res); SendPacket( &data ); return; } if (GetSecurity() == SEC_PLAYER && sObjectMgr.IsReservedName(name)) { data << (uint8)CHAR_NAME_RESERVED; SendPacket( &data ); return; } if (sObjectMgr.GetPlayerGUIDByName(name)) { data << (uint8)CHAR_CREATE_NAME_IN_USE; SendPacket( &data ); return; } QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); delete resultacct; if (acctcharcount >= sWorld.getConfig(CONFIG_UINT32_CHARACTERS_PER_ACCOUNT)) { data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; SendPacket( &data ); return; } } QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); uint8 charcount = 0; if ( result ) { Field *fields = result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= sWorld.getConfig(CONFIG_UINT32_CHARACTERS_PER_REALM)) { data << (uint8)CHAR_CREATE_SERVER_LIMIT; SendPacket( &data ); return; } } // speedup check for heroic class disabled case uint32 heroic_free_slots = sWorld.getConfig(CONFIG_UINT32_HEROIC_CHARACTERS_PER_REALM); if(heroic_free_slots == 0 && GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; SendPacket( &data ); return; } // speedup check for heroic class disabled case uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_UINT32_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING); if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)) { data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; SendPacket( &data ); return; } bool AllowTwoSideAccounts = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; CinematicsSkipMode skipCinematics = CinematicsSkipMode(sWorld.getConfig(CONFIG_UINT32_SKIP_CINEMATICS)); bool have_same_race = false; // if 0 then allowed creating without any characters bool have_req_level_for_heroic = (req_level_for_heroic==0); if(!AllowTwoSideAccounts || skipCinematics == CINEMATICS_SKIP_SAME_RACE || class_ == CLASS_DEATH_KNIGHT) { QueryResult *result2 = CharacterDatabase.PQuery("SELECT level,race,class FROM characters WHERE account = '%u' %s", GetAccountId(), (skipCinematics == CINEMATICS_SKIP_SAME_RACE || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 acc_race = field[1].GetUInt32(); if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { uint8 acc_class = field[2].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT) { if(heroic_free_slots > 0) --heroic_free_slots; if(heroic_free_slots == 0) { data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; SendPacket( &data ); delete result2; return; } } if(!have_req_level_for_heroic) { uint32 acc_level = field[0].GetUInt32(); if(acc_level >= req_level_for_heroic) have_req_level_for_heroic = true; } } // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { uint32 acc_team = 0; if(acc_race > 0) acc_team = Player::TeamForRace(acc_race); if(acc_team != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); delete result2; return; } } // search same race for cinematic or same class if need // TODO: check if cinematic already shown? (already logged in?; cinematic field) while ((skipCinematics == CINEMATICS_SKIP_SAME_RACE && !have_same_race) || class_ == CLASS_DEATH_KNIGHT) { if(!result2->NextRow()) break; field = result2->Fetch(); acc_race = field[1].GetUInt32(); if(!have_same_race) have_same_race = race_ == acc_race; if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { uint8 acc_class = field[2].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT) { if(heroic_free_slots > 0) --heroic_free_slots; if(heroic_free_slots == 0) { data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; SendPacket( &data ); delete result2; return; } } if(!have_req_level_for_heroic) { uint32 acc_level = field[0].GetUInt32(); if(acc_level >= req_level_for_heroic) have_req_level_for_heroic = true; } } } delete result2; } } if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic) { data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; SendPacket( &data ); return; } // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; Player *pNewChar = new Player(this); if(!pNewChar->Create( sObjectMgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId )) { // Player not create (race/class problem?) delete pNewChar; data << (uint8)CHAR_CREATE_ERROR; SendPacket( &data ); return; } if ((have_same_race && skipCinematics == CINEMATICS_SKIP_SAME_RACE) || skipCinematics == CINEMATICS_SKIP_ALL) pNewChar->setCinematic(1); // not show intro pNewChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login // Player created, save it now pNewChar->SaveToDB(); charcount += 1; loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); data << (uint8)CHAR_CREATE_SUCCESS; SendPacket( &data ); std::string IP_str = GetRemoteAddress(); BASIC_LOG("Account: %d (IP: %s) Create Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); sLog.outChar("Account: %d (IP: %s) Create Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); delete pNewChar; // created only to call SaveToDB() }
void WorldSession::HandleSendMail(WorldPacket& recvData) { ObjectGuid mailbox, unk3; std::string receiverName, subject, body; uint32 stationery, package, money, COD; uint8 unk4; uint8 items_count; recvData >> mailbox >> receiverName >> subject >> body >> stationery // stationery? >> package // 0x00000000 >> items_count; // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recvData.rfinish(); // set to end to avoid warnings spam return; } ObjectGuid itemGUIDs[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { recvData.read_skip<uint8>(); // item slot in mail, not used recvData >> itemGUIDs[i]; } recvData >> money >> COD; // money and cod recvData >> unk3; // const 0 recvData >> unk4; // const 0 // packet read complete, now do check if (!CanOpenMailBox(mailbox)) return; if (receiverName.empty()) return; Player* player = _player; if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } ObjectGuid receiverGuid; if (normalizePlayerName(receiverName)) receiverGuid = sObjectMgr->GetPlayerGUIDByName(receiverName); if (!receiverGuid) { TC_LOG_INFO("network", "Player %u is sending mail to %s (GUID: not existed!) with subject %s " "and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, stationery, package); player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } TC_LOG_INFO("network", "Player %u is sending mail to %s (%s) with subject %s and body %s " "includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiverName.c_str(), receiverGuid.ToString().c_str(), subject.c_str(), body.c_str(), items_count, money, COD, stationery, package); if (player->GetGUID() == receiverGuid) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint32 reqmoney = cost + money; // Check for overflow if (reqmoney < money) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } if (!player->HasEnoughMoney(reqmoney) && !player->IsGameMaster()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid); uint32 receiverTeam = 0; uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails uint8 receiverLevel = 0; uint32 receiverAccountId = 0; if (receiver) { receiverTeam = receiver->GetTeam(); mailsCount = receiver->GetMailSize(); receiverLevel = receiver->getLevel(); receiverAccountId = receiver->GetSession()->GetAccountId(); } else { receiverTeam = sObjectMgr->GetPlayerTeamByGUID(receiverGuid); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT); stmt->setUInt32(0, receiverGuid.GetCounter()); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); mailsCount = fields[0].GetUInt64(); } stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL); stmt->setUInt32(0, receiverGuid.GetCounter()); result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); receiverLevel = fields[0].GetUInt8(); } receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid); } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mailsCount > 100) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // test the receiver's Faction... or all items are account bound bool accountBound = items_count ? true : false; for (uint8 i = 0; i < items_count; ++i) { if (Item* item = player->GetItemByGuid(itemGUIDs[i])) { ItemTemplate const* itemProto = item->GetTemplate(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; } } } if (!accountBound && player->GetTeam() != receiverTeam && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } if (receiverLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } if (!ChatHandler(this).isValidChatMessage(subject.c_str()) || !ChatHandler(this).isValidChatMessage(body.c_str())) return; Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { if (!itemGUIDs[i]) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = player->GetItemByGuid(itemGUIDs[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); return; } if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } if (item->IsNotEmptyBag()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS); return; } items[i] = item; } // Check for spamming if (!UpdateAntispamCount()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR); SendNotification(GetTrinityString(LANG_ANTISPAM_ERROR)); return; } player->SendMailResult(0, MAIL_SEND, MAIL_OK); player->ModifyMoney(-int32(reqmoney)); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (items_count > 0 || money > 0) { bool log = HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE); if (items_count > 0) { for (uint8 i = 0; i < items_count; ++i) { Item* item = items[i]; if (log) { sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail item: %s (Entry: %u Count: %u) " "to: %s (%s) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory item->SetOwnerGUID(receiverGuid); item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId; } if (log && money > 0) { sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: %u to: %s (%s) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // don't ask for COD if there are no items if (items_count == 0) COD = 0; // will delete item or place to receiver mail list draft .AddMoney(money) .AddCOD(COD) .SendMailTo(trans, MailReceiver(receiver, receiverGuid.GetCounter()), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { uint32 charcount = sAccountMgr->GetCharactersCount(account); if(charcount >= 10) return DUMP_TOO_MANY_CHARS; FILE *fin = fopen(file.c_str(), "r"); if(!fin) return DUMP_FILE_OPEN_ERROR; QueryResult result = QueryResult(NULL); char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if(guid != 0 && guid < sObjectMgr->m_hiCharGuid) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_CHECK_GUID); stmt->setUInt32(0, guid); PreparedQueryResult result = CharacterDatabase.Query(stmt); if(result) guid = sObjectMgr->m_hiCharGuid; // use first free if exists else incHighest = false; } else guid = sObjectMgr->m_hiCharGuid; // normalize the name if specified and check if it exists if(!normalizePlayerName(name)) name = ""; if(ObjectMgr::CheckPlayerName(name, true) == CHAR_NAME_SUCCESS) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); if(result) name = ""; // use the one from the dump } else name = ""; // name encoded or empty snprintf(newguid, 20, "%d", guid); snprintf(chraccount, 20, "%d", account); snprintf(newpetid, 20, "%d", sObjectMgr->GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32, uint32> items; std::map<uint32, uint32> mails; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; uint8 gender = GENDER_NONE; uint8 race = RACE_NONE; uint8 playerClass = 0; SQLTransaction trans = CharacterDatabase.BeginTransaction(); while(!feof(fin)) { if(!fgets(buf, 32000, fin)) { if(feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if(nw_pos == std::string::npos) continue; // skip logfile-side dump start notice, the important notes and dump end notices if((line.substr(nw_pos, 16) == "== START DUMP ==") || (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") || (line.substr(nw_pos, 14) == "== END DUMP ==")) continue; // determine table name and load type std::string tn = gettablename(line); if(tn.empty()) { sLog->outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type = DumpTableType(0); uint8 i; for(i = 0; i < DUMP_TABLE_COUNT; ++i) { if(tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if(i == DUMP_TABLE_COUNT) { sLog->outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch(type) { case DTT_CHARACTER: { if(!changenth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); race = uint8(atol(getnth(line, 4).c_str())); playerClass = uint8(atol(getnth(line, 5).c_str())); gender = uint8(atol(getnth(line, 6).c_str())); if(name == "") { // check if the original name already exists name = getnth(line, 3); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); if(result) { if(!changenth(line, 37, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); } } else if(!changenth(line, 3, name.c_str())) // characters.name ROLLBACK(DUMP_FILE_BROKEN); const char null[5] = "NULL"; if(!changenth(line, 68, null)) // characters.deleteInfos_Account ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 69, null)) // characters.deleteInfos_Name ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 70, null)) // characters.deleteDate ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_CHAR_TABLE: { if(!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_EQSET_TABLE: { if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid char newSetGuid[24]; snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid()); if(!changenth(line, 2, newSetGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid break; } case DTT_INVENTORY: { if(!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 2, items, sObjectMgr->m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if(!changeGuid(line, 4, items, sObjectMgr->m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_MAIL: // mail { if(!changeGuid(line, 1, mails, sObjectMgr->m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if(!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if(!changeGuid(line, 1, mails, sObjectMgr->m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if(!changeGuid(line, 2, items, sObjectMgr->m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if(!changenth(line, 3, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if(!changeGuid(line, 1, items, sObjectMgr->m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if(!changenth(line, 3, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if(!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 2, items, sObjectMgr->m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_PET: { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if(*lastpetid == '\0') snprintf(lastpetid, 20, "%s", currpetid); if(strcmp(lastpetid, currpetid) != 0) { snprintf(newpetid, 20, "%d", sObjectMgr->GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if(petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } if(!changenth(line, 1, newpetid)) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if(petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if(!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } default: sLog->outError("Unknown dump table type: %u", type); break; } fixNULLfields(line); trans->Append(line.c_str()); } CharacterDatabase.CommitTransaction(trans); // in case of name conflict player has to rename at login anyway sWorld->AddCharacterNameData(guid, name, gender, race, playerClass); sObjectMgr->m_hiItemGuid += items.size(); sObjectMgr->m_mailid += mails.size(); if(incHighest) ++sObjectMgr->m_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }
void WorldSession::HandleSendMail(WorldPacket & recvData) { uint64 mailbox, unk3; std::string receiver, subject, body; uint32 unk1, unk2, money, COD; uint8 unk4; recvData >> mailbox; recvData >> receiver; recvData >> subject; recvData >> body; recvData >> unk1; // stationery? recvData >> unk2; // 0x00000000 uint8 items_count; recvData >> items_count; // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recvData.rfinish(); // set to end to avoid warnings spam return; } uint64 itemGUIDs[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { recvData.read_skip<uint8>(); // item slot in mail, not used recvData >> itemGUIDs[i]; } recvData >> money >> COD; // money and cod recvData >> unk3; // const 0 recvData >> unk4; // const 0 // packet read complete, now do check if (!CanOpenMailBox(mailbox)) return; if (receiver.empty()) return; Player* player = _player; if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint64 rc = 0; if (normalizePlayerName(receiver)) rc = sObjectMgr->GetPlayerGUIDByName(receiver); if (!rc) { ;//sLog->outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", // player->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } ;//sLog->outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if (player->GetGUID() == rc) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint32 reqmoney = cost + money; // Check for overflow if (reqmoney < money) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } if (!player->HasEnoughMoney(reqmoney)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player* receive = ObjectAccessor::FindPlayerInOrOutOfWorld(rc); uint32 rc_teamId = TEAM_NEUTRAL; uint16 mails_count = 0; //do not allow to send to one player more than 100 mails if (receive) { rc_teamId = receive->GetTeamId(); mails_count = receive->GetMailSize(); } else { // xinef: get data from global storage if (GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(GUID_LOPART(rc))) { rc_teamId = Player::TeamIdForRace(playerData->race); mails_count = playerData->mailCount; } } //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mails_count > 100) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // test the receiver's Faction... or all items are account bound // Xinef: check for boa items, not used currently /*bool accountBound = items_count && !money && !COD ? true : false; for (uint8 i = 0; i < items_count; ++i) { Item* item = player->GetItemByGuid(itemGUIDs[i]); if (item) { ItemTemplate const* itemProto = item->GetTemplate(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; } } }*/ uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(rc); if (/*!accountBound*/ GetAccountId() != rc_account && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeamId() != rc_teamId && AccountMgr::IsPlayerAccount(GetSecurity())) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { if (!itemGUIDs[i]) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = player->GetItemByGuid(itemGUIDs[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && GetAccountId() != rc_account) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); return; } if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } if (item->IsNotEmptyBag()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS); return; } items[i] = item; } player->SendMailResult(0, MAIL_SEND, MAIL_OK); player->ModifyMoney(-int32(reqmoney)); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (items_count > 0 || money > 0) { if (items_count > 0) { for (uint8 i = 0; i < items_count; ++i) { Item* item = items[i]; item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory if (item->GetState() == ITEM_UNCHANGED) item->FSetState(ITEM_CHANGED); // pussywizard: so the item will be saved and owner will be updated in database item->SetOwnerGUID(rc); item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = GetAccountId() != rc_account; } if( money >= 10*GOLD ) { CleanStringForMysqlQuery(subject); CharacterDatabase.PExecute("INSERT INTO log_money VALUES(%u, %u, \"%s\", \"%s\", %u, \"%s\", %u, \"<MAIL> %s\", NOW())", GetAccountId(), player->GetGUIDLow(), player->GetName().c_str(), player->GetSession()->GetRemoteAddress().c_str(), rc_account, receiver.c_str(), money, subject.c_str()); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // don't ask for COD if there are no items if (items_count == 0) COD = 0; // will delete item or place to receiver mail list draft .AddMoney(money) .AddCOD(COD) .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
// Playerbot mod bool ChatHandler::HandlePlayerbotCommand(const char* args) { if (! m_session) { PSendSysMessage("You may only add bots from an active session"); SetSentErrorMessage(true); return false; } if (!*args) { PSendSysMessage("usage: add PLAYERNAME or remove PLAYERNAME"); SetSentErrorMessage(true); return false; } char *cmd = strtok ((char*)args, " "); char *charname = strtok (NULL, " "); if (!cmd || !charname) { PSendSysMessage("usage: add PLAYERNAME or remove PLAYERNAME"); SetSentErrorMessage(true); return false; } std::string cmdStr = cmd; std::string charnameStr = charname; if(!normalizePlayerName(charnameStr)) return false; uint64 guid = objmgr.GetPlayerGUIDByName(charnameStr.c_str()); if (guid == 0 || (guid == m_session->GetPlayer()->GetGUID())) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); return false; } uint32 accountId = objmgr.GetPlayerAccountIdByGUID(guid); if (accountId != m_session->GetAccountId()) { PSendSysMessage("You may only add bots from the same account."); SetSentErrorMessage(true); return false; } if (cmdStr == "add" || cmdStr == "login") { if (m_session->GetPlayerBot(guid) != NULL) { PSendSysMessage("Bot already exists in world."); SetSentErrorMessage(true); return false; } m_session->AddPlayerBot(guid); PSendSysMessage("Bot added successfully."); } else if (cmdStr == "remove" || cmdStr == "logout") { if (m_session->GetPlayerBot(guid) == NULL) { PSendSysMessage("Bot can not be removed because bot does not exist in world."); SetSentErrorMessage(true); return false; } m_session->LogoutPlayerBot(guid, true); PSendSysMessage("Bot removed successfully."); } return true; }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { bool nameInvalidated = false; // set when name changed or will requested changed at next login // check character count uint32 charcount = sAccountMgr.GetCharactersCount(account); if (charcount >= 10) return DUMP_TOO_MANY_CHARS; FILE* fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult* result = NULL; char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < sObjectMgr.m_CharGuids.GetNextAfterMaxUsed()) { result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%u'", guid); if (result) { guid = sObjectMgr.m_CharGuids.GetNextAfterMaxUsed(); delete result; } else incHighest = false; } else guid = sObjectMgr.m_CharGuids.GetNextAfterMaxUsed(); // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name, true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { name = ""; // use the one from the dump delete result; } } else name = ""; // name encoded or empty snprintf(newguid, 20, "%u", guid); snprintf(chraccount, 20, "%u", account); snprintf(newpetid, 20, "%u", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32, uint32> items; std::map<uint32, uint32> mails; std::map<uint32, uint32> eqsets; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; // skip NOTE if (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") continue; // add required_ check if (line.substr(nw_pos, 41) == "UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } // determine table name and load type std::string tn = gettablename(line); if (tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type = DTT_CHARACTER; // Fixed: Using uninitialized memory 'type' DumpTable* dTable = &dumpTables[0]; for (; dTable->isValid(); ++dTable) { if (tn == dTable->name) { type = dTable->type; break; } } if (!dTable->isValid()) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } bool execute_ok = true; // false, if need skip soem query // change the data to server values switch (type) { case DTT_CHAR_TABLE: if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHAR_NAME_TABLE: if (nameInvalidated) // ignore declined names if name will changed in some way { execute_ok = false; break; } if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: { if (!changenth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 3); // characters.name CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { delete result; if (!changenth(line, 36, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); nameInvalidated = true; } } else { if (!changenth(line, 3, name.c_str())) // characters.name update ROLLBACK(DUMP_FILE_BROKEN); nameInvalidated = true; } break; } case DTT_INVENTORY: { if (!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed(), true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if (!changeGuid(line, 4, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if (!changeGuid(line, 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 2, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line, 3); // item_instance.data get if (!changetokGuid(vals, OBJECT_FIELD_GUID + 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.OBJECT_FIELD_GUID update if (!changetoknth(vals, ITEM_FIELD_OWNER + 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.ITEM_FIELD_OWNER update if (!changenth(line, 3, vals.c_str())) // item_instance.data update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if (!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_ITEM_LOOT: { // item, owner if (!changeGuid(line, 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // item_loot.guid update if (!changenth(line, 2, newguid)) // item_Loot.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET: { // store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if (strlen(lastpetid) == 0) snprintf(lastpetid, 20, "%s", currpetid); if (strcmp(lastpetid, currpetid) != 0) { snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } if (!changenth(line, 1, newpetid)) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) // pet_*.guid -> petid in fact ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_DECL: // character_pet_declinedname { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) // character_pet_declinedname.id ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, newguid)) // character_pet_declinedname.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { if (!changeGuid(line, 1, mails, sObjectMgr.m_MailIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if (!changeGuid(line, 1, mails, sObjectMgr.m_MailIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!changenth(line, 4, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_EQSET_TABLE: { if (!changenth(line, 1, newguid)) // character_equipmentsets.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, eqsets, sObjectMgr.m_EquipmentSetIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid for (int i = 0; i < 19; ++i) // character_equipmentsets.item0..item18 if (!changeGuid(line, 6 + i, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); break; } default: sLog.outError("Unknown dump table type: %u", type); break; } if (execute_ok && !CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); // FIXME: current code with post-updating guids not safe for future per-map threads sObjectMgr.m_ItemGuids.Set(sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed() + items.size()); sObjectMgr.m_MailIds.Set(sObjectMgr.m_MailIds.GetNextAfterMaxUsed() + mails.size()); sObjectMgr.m_EquipmentSetIds.Set(sObjectMgr.m_EquipmentSetIds.GetNextAfterMaxUsed() + eqsets.size()); if (incHighest) sObjectMgr.m_CharGuids.Set(sObjectMgr.m_CharGuids.GetNextAfterMaxUsed() + 1); fclose(fin); return DUMP_SUCCESS; }
void WorldSession::HandleSendMail(WorldPacket & recv_data) { uint64 mailbox, unk3, money, COD; std::string receiver, subject, body; uint32 unk1, unk2; uint8 unk4; recv_data >> mailbox; recv_data >> receiver; recv_data >> subject; recv_data >> body; recv_data >> unk1; // stationery? recv_data >> unk2; // 0x00000000 uint8 items_count; recv_data >> items_count; // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam return; } uint64 itemGUIDs[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { recv_data.read_skip<uint8>(); // item slot in mail, not used recv_data >> itemGUIDs[i]; } recv_data >> money >> COD; // money and cod recv_data >> unk3; // const 0 recv_data >> unk4; // const 0 // packet read complete, now do check if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; if (receiver.empty()) return; Player* pl = _player; if (pl->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetSkyFireString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint64 rc = 0; if (normalizePlayerName(receiver)) rc = sObjectMgr->GetPlayerGUIDByName(receiver); if (!rc) { sLog->outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, "UI64FMTD" copper and "UI64FMTD" COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } sLog->outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, "UI64FMTD" copper and "UI64FMTD" COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if (pl->GetGUID() == rc) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint64 reqmoney = cost + money; if (!pl->HasEnoughMoney(uint32(reqmoney))) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player *receive = sObjectMgr->GetPlayer(rc); uint32 rc_team = 0; uint8 mails_count = 0; //do not allow to send to one player more than 100 mails uint8 receiveLevel = 0; if (receive) { rc_team = receive->GetTeam(); mails_count = receive->GetMailSize(); receiveLevel = receive->getLevel(); } else { rc_team = sObjectMgr->GetPlayerTeamByGUID(rc); if (QueryResult result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", GUID_LOPART(rc))) { Field *fields = result->Fetch(); mails_count = fields[0].GetUInt32(); } if (QueryResult result = CharacterDatabase.PQuery("SELECT level FROM characters WHERE guid = '%u'", GUID_LOPART(rc))) { Field *fields = result->Fetch(); receiveLevel = fields[0].GetUInt8(); } } //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mails_count > 100) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // test the receiver's Faction... or all items are account bound bool accountBound = items_count ? true : false; for (uint8 i = 0; i < items_count; ++i) { Item* item = pl->GetItemByGuid(itemGUIDs[i]); if (item) { ItemPrototype const* itemProto = item->GetProto(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; } } } if (!accountBound && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && GetSecurity() == SEC_PLAYER) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } if (receiveLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetSkyFireString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(rc); Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { if (!itemGUIDs[i]) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = pl->GetItemByGuid(itemGUIDs[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && pl->GetSession()->GetAccountId() != rc_account) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); return; } if (item->GetProto()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } if (item->IsBag() && !((Bag*)item)->IsEmpty()) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS); return; } items[i] = item; } pl->SendMailResult(0, MAIL_SEND, MAIL_OK); pl->ModifyMoney(-int32(reqmoney)); pl->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (items_count > 0 || money > 0) { if (items_count > 0) { for (uint8 i = 0; i < items_count; ++i) { Item* item = items[i]; if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), item->GetProto()->Name1, item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable pl->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_ITEM_OWNER); stmt->setUInt32(0, GUID_LOPART(rc)); stmt->setUInt32(1, item->GetGUIDLow()); trans->Append(stmt); draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = pl->GetSession()->GetAccountId() != rc_account; } if (money > 0 && GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: "UI64FMTD" to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list draft .AddMoney(money) .AddCOD(COD) .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(pl), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); pl->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_INVITE"); uint32 ArenaTeamId; // arena team id std::string Invitedname; Player * player = NULL; recv_data >> ArenaTeamId >> Invitedname; if(!Invitedname.empty()) { if(!normalizePlayerName(Invitedname)) return; player = ObjectAccessor::FindPlayerByName(Invitedname.c_str()); } if(!player) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; } if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW); return; } ArenaTeam *arenateam = sObjectMgr.GetArenaTeamById(ArenaTeamId); if(!arenateam) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM); return; } // OK result but not send invite if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) return; if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); return; } if(player->GetArenaTeamId(arenateam->GetSlot())) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); return; } if(player->GetArenaTeamIdInvited()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } if(arenateam->GetMembersSize() >= arenateam->GetType() * 2) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,arenateam->GetName(),"",ERR_ARENA_TEAM_FULL); return; } sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str()); player->SetArenaTeamIdInvited(arenateam->GetId()); WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10)); data << GetPlayer()->GetName(); data << arenateam->GetName(); player->GetSession()->SendPacket(&data); sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_INVITE"); }
static bool HandleBanHelper(BanMode mode, char const* args, ChatHandler* handler) { if (!*args) return false; char* cnameOrIP = strtok((char*)args, " "); if (!cnameOrIP) return false; std::string nameOrIP = cnameOrIP; char* durationStr = strtok(NULL, " "); if (!durationStr || !atoi(durationStr)) return false; char* reasonStr = strtok(NULL, ""); if (!reasonStr) return false; switch (mode) { case BAN_ACCOUNT: if (!AccountMgr::normalizeString(nameOrIP)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str()); handler->SetSentErrorMessage(true); return false; } break; case BAN_CHARACTER: if (!normalizePlayerName(nameOrIP)) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); handler->SetSentErrorMessage(true); return false; } break; case BAN_IP: if (!IsIPAddress(nameOrIP.c_str())) return false; break; } switch (sWorld->BanAccount(mode, nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "")) { case BAN_SUCCESS: if (atoi(durationStr) > 0) handler->PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); else handler->PSendSysMessage(LANG_BAN_YOUPERMBANNED, nameOrIP.c_str(), reasonStr); break; case BAN_SYNTAX_ERROR: return false; case BAN_NOTFOUND: switch (mode) { default: handler->PSendSysMessage(LANG_BAN_NOTFOUND, "account", nameOrIP.c_str()); break; case BAN_CHARACTER: handler->PSendSysMessage(LANG_BAN_NOTFOUND, "character", nameOrIP.c_str()); break; case BAN_IP: handler->PSendSysMessage(LANG_BAN_NOTFOUND, "ip", nameOrIP.c_str()); break; } handler->SetSentErrorMessage(true); return false; } return true; }
void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE"); ObjectGuid crossRealmGuid; // unused recvData.read_skip<uint32>(); // Non-zero in cross realm invites recvData.read_skip<uint32>(); // Always 0 crossRealmGuid[2] = recvData.ReadBit(); crossRealmGuid[7] = recvData.ReadBit(); uint8 realmLen = recvData.ReadBits(9); crossRealmGuid[3] = recvData.ReadBit(); uint8 nameLen = recvData.ReadBits(10); crossRealmGuid[5] = recvData.ReadBit(); crossRealmGuid[4] = recvData.ReadBit(); crossRealmGuid[6] = recvData.ReadBit(); crossRealmGuid[0] = recvData.ReadBit(); crossRealmGuid[1] = recvData.ReadBit(); recvData.ReadByteSeq(crossRealmGuid[4]); recvData.ReadByteSeq(crossRealmGuid[7]); recvData.ReadByteSeq(crossRealmGuid[6]); std::string memberName, realmName; memberName = recvData.ReadString(nameLen); realmName = recvData.ReadString(realmLen); // unused recvData.ReadByteSeq(crossRealmGuid[1]); recvData.ReadByteSeq(crossRealmGuid[0]); recvData.ReadByteSeq(crossRealmGuid[5]); recvData.ReadByteSeq(crossRealmGuid[3]); recvData.ReadByteSeq(crossRealmGuid[2]); // attempt add selected player // cheating if (!normalizePlayerName(memberName)) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S); return; } Player* player = ObjectAccessor::FindPlayerByName(memberName); // no player if (!player) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S); return; } // restrict invite to GMs if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->IsGameMaster() && player->IsGameMaster()) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S); return; } // can't group with if (!GetPlayer()->IsGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PLAYER_WRONG_FACTION); return; } if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_TARGET_NOT_IN_INSTANCE_S); return; } // just ignore us if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty()) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S); return; } if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S); return; } ObjectGuid invitedGuid = player->GetGUID(); Group* group = GetPlayer()->GetGroup(); if (group && group->isBGGroup()) group = GetPlayer()->GetOriginalGroup(); Group* group2 = player->GetGroup(); if (group2 && group2->isBGGroup()) group2 = player->GetOriginalGroup(); // player already in another group or invited if (group2 || player->GetGroupInvite()) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_ALREADY_IN_GROUP_S); if (group2) { // tell the player that they were invited but it failed as they were already in a group WorldPacket data(SMSG_GROUP_INVITE, 45); data.WriteBit(0); data.WriteBit(invitedGuid[0]); data.WriteBit(invitedGuid[3]); data.WriteBit(invitedGuid[2]); data.WriteBit(0); // Inverse already in group data.WriteBit(invitedGuid[6]); data.WriteBit(invitedGuid[5]); data.WriteBits(0, 9); // Realm name data.WriteBit(invitedGuid[4]); data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length data.WriteBits(0, 24); // Count 2 data.WriteBit(0); data.WriteBit(invitedGuid[1]); data.WriteBit(invitedGuid[7]); data.FlushBits(); data.WriteByteSeq(invitedGuid[1]); data.WriteByteSeq(invitedGuid[4]); data << int32(getMSTime()); data << int32(0); data << int32(0); data.WriteByteSeq(invitedGuid[6]); data.WriteByteSeq(invitedGuid[0]); data.WriteByteSeq(invitedGuid[2]); data.WriteByteSeq(invitedGuid[3]); // for count2 { int32(0) } data.WriteByteSeq(invitedGuid[5]); // data.append(realm name); data.WriteByteSeq(invitedGuid[7]); data.WriteString(GetPlayer()->GetName()); // inviter name data << int32(0); player->GetSession()->SendPacket(&data); } return; } if (group) { // not have permissions for invite if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) { SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); return; } // not have place if (group->IsFull()) { SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); return; } } // ok, but group not exist, start a new group // but don't create and save the group to the DB until // at least one person joins if (!group) { group = new Group; // new group: if can't add then delete if (!group->AddLeaderInvite(GetPlayer())) { delete group; return; } if (!group->AddInvite(player)) { delete group; return; } } else { // already existed group: if can't add then just leave if (!group->AddInvite(player)) { return; } } // ok, we do it WorldPacket data(SMSG_GROUP_INVITE, 45); data.WriteBit(0); data.WriteBit(invitedGuid[0]); data.WriteBit(invitedGuid[3]); data.WriteBit(invitedGuid[2]); data.WriteBit(1); // Inverse already in group data.WriteBit(invitedGuid[6]); data.WriteBit(invitedGuid[5]); data.WriteBits(0, 9); // Realm name data.WriteBit(invitedGuid[4]); data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length data.WriteBits(0, 24); // Count 2 data.WriteBit(0); data.WriteBit(invitedGuid[1]); data.WriteBit(invitedGuid[7]); data.FlushBits(); data.WriteByteSeq(invitedGuid[1]); data.WriteByteSeq(invitedGuid[4]); data << int32(getMSTime()); data << int32(0); data << int32(0); data.WriteByteSeq(invitedGuid[6]); data.WriteByteSeq(invitedGuid[0]); data.WriteByteSeq(invitedGuid[2]); data.WriteByteSeq(invitedGuid[3]); // for count2 { int32(0) } data.WriteByteSeq(invitedGuid[5]); // data.append(realm name); data.WriteByteSeq(invitedGuid[7]); data.WriteString(GetPlayer()->GetName()); data << int32(0); player->GetSession()->SendPacket(&data); SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PARTY_RESULT_OK); }
//rename characters static bool HandleCharacterRenameCommand(ChatHandler* handler, char const* args) { Player* target; ObjectGuid targetGuid; std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; char const* newNameStr = strtok(NULL, " "); if (newNameStr) { std::string playerOldName; std::string newName = newNameStr; if (target) { // check online security if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; playerOldName = target->GetName(); } else { // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; sObjectMgr->GetPlayerNameByGUID(targetGuid, playerOldName); } if (!normalizePlayerName(newName)) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } if (ObjectMgr::CheckPlayerName(newName, true) != CHAR_NAME_SUCCESS) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } if (WorldSession* session = handler->GetSession()) { if (!session->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName)) { handler->SendSysMessage(LANG_RESERVED_NAME); handler->SetSentErrorMessage(true); return false; } } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, newName); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str()); handler->SetSentErrorMessage(true); return false; } // Remove declined name from db stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME); stmt->setUInt32(0, targetGuid.GetCounter()); CharacterDatabase.Execute(stmt); if (target) { target->SetName(newName); if (WorldSession* session = target->GetSession()) session->KickPlayer(); } else { stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID); stmt->setString(0, newName); stmt->setUInt32(1, targetGuid.GetCounter()); CharacterDatabase.Execute(stmt); } sWorld->UpdateCharacterNameData(targetGuid, newName); handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, playerOldName.c_str(), newName.c_str()); if (WorldSession* session = handler->GetSession()) { if (Player* player = session->GetPlayer()) sLog->outCommand(session->GetAccountId(), "GM %s (Account: %u) forced rename %s to player %s (Account: %u)", player->GetName().c_str(), session->GetAccountId(), newName.c_str(), playerOldName.c_str(), sObjectMgr->GetPlayerAccountIdByGUID(targetGuid)); } else sLog->outCommand(0, "CONSOLE forced rename '%s' to '%s' (%s)", playerOldName.c_str(), newName.c_str(), targetGuid.ToString().c_str()); } else { if (target) { // check online security if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_RENAME); } else { // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; std::string oldNameLink = handler->playerLink(targetName); handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), targetGuid.GetCounter()); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); stmt->setUInt32(1, targetGuid.GetCounter()); CharacterDatabase.Execute(stmt); } } return true; }
bool ChatHandler::HandleGMTicketAssignToCommand(const char* args) { if (!*args) return false; char* tguid = strtok((char*)args, " "); uint64 ticketGuid = atoi(tguid); char* targetgm = strtok(NULL, " "); if (!targetgm) return false; std::string targm = targetgm; if (!normalizePlayerName(targm)) return false; Player *cplr = m_session->GetPlayer(); GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid); if (!ticket || ticket->closed != 0) { SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); return true; } uint64 tarGUID = sObjectMgr->GetPlayerGUIDByName(targm.c_str()); uint64 accid = sObjectMgr->GetPlayerAccountIdByGUID(tarGUID); uint32 gmlevel = sAccountMgr->GetSecurity(accid, realmID); if (!tarGUID || gmlevel == SEC_PLAYER) { SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); return true; } if (ticket->assignedToGM == tarGUID) { PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->guid); return true; } std::string gmname; sObjectMgr->GetPlayerNameByGUID(tarGUID, gmname); if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) { PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str()); return true; } ticket->assignedToGM = tarGUID; if (gmlevel == SEC_ADMINISTRATOR && ticket->escalated == TICKET_IN_ESCALATION_QUEUE) ticket->escalated = TICKET_ESCALATED_ASSIGNED; else if (ticket->escalated == TICKET_UNASSIGNED) ticket->escalated = TICKET_ASSIGNED; sTicketMgr->AddOrUpdateGMTicket(*ticket); std::stringstream ss; ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); SendGlobalGMSysMessage(ss.str().c_str()); sTicketMgr->UpdateLastChange(); return true; }
void WorldSession::HandleCharCustomize(WorldPacket& recv_data) { uint64 guid; std::string newname; recv_data >> guid; recv_data >> newname; uint8 gender, skin, face, hairStyle, hairColor, facialHair; recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); if (!result) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_ERROR); SendPacket( &data ); return; } Field *fields = result->Fetch(); uint32 at_loginFlags = fields[0].GetUInt32(); delete result; if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_ERROR); SendPacket( &data ); return; } // prevent character rename to invalid name if (!normalizePlayerName(newname)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_NAME_NO_NAME); SendPacket( &data ); return; } uint8 res = ObjectMgr::CheckPlayerName(newname,true); if (res != CHAR_NAME_SUCCESS) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(res); SendPacket( &data ); return; } // check name limitations if (GetSecurity() == SEC_PLAYER && sObjectMgr.IsReservedName(newname)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_NAME_RESERVED); SendPacket( &data ); return; } // character with this name already exist if (uint64 newguid = sObjectMgr.GetPlayerGUIDByName(newname)) { if (newguid != guid) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket( &data ); return; } } CharacterDatabase.escape_string(newname); Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid)); CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s), Character guid: %u Customized to: %s", GetAccountId(), IP_str.c_str(), GUID_LOPART(guid), newname.c_str()); WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6); data << uint8(RESPONSE_SUCCESS); data << uint64(guid); data << newname; data << uint8(gender); data << uint8(skin); data << uint8(face); data << uint8(hairStyle); data << uint8(hairColor); data << uint8(facialHair); SendPacket(&data); }
void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data ) { std::string membername; recv_data >> membername; // attempt add selected player // cheating if(!normalizePlayerName(membername)) { SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_CANT_FIND_TARGET); return; } Player *player = sObjectMgr.GetPlayer(membername.c_str()); // no player if(!player) { SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_CANT_FIND_TARGET); return; } // can't group with if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) { SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_TARGET_UNFRIENDLY); return; } if(GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) { SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_NOT_IN_YOUR_INSTANCE); return; } // just ignore us if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_TARGET_IGNORE_YOU); return; } Group *group = GetPlayer()->GetGroup(); if( group && group->isBGGroup() ) group = GetPlayer()->GetOriginalGroup(); Group *group2 = player->GetGroup(); if( group2 && group2->isBGGroup() ) group2 = player->GetOriginalGroup(); // player already in another group or invited if( group2 || player->GetGroupInvite() ) { SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_ALREADY_IN_GROUP); return; } if(group) { // not have permissions for invite if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) { SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_YOU_NOT_LEADER); return; } // not have place if(group->IsFull()) { SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_PARTY_FULL); return; } } // ok, but group not exist, start a new group // but don't create and save the group to the DB until // at least one person joins if(!group) { group = new Group; // new group: if can't add then delete if(!group->AddLeaderInvite(GetPlayer())) { delete group; return; } if(!group->AddInvite(player)) { delete group; return; } } else { // already existed group: if can't add then just leave if(!group->AddInvite(player)) { return; } } // ok, we do it WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size data << uint8(1); // ok data << GetPlayer()->GetName(); player->GetSession()->SendPacket(&data); SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_OK); }
void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) { uint64 guid; recv_data >> guid; // not accept declined names for unsupported languages std::string name; if(!sObjectMgr.GetPlayerNameByGUID(guid, name)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } std::wstring wname; if(!Utf8toWStr(name, wname)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } if(!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } std::string name2; DeclinedName declinedname; recv_data >> name2; if(name2 != name) // character have different name { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; if(!normalizePlayerName(declinedname.name[i])) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } } if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); CharacterDatabase.CommitTransaction(); WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(0); // OK data << uint64(guid); SendPacket(&data); }
void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE"); std::string membername; recv_data >> membername; recv_data.read_skip<uint32>(); // attempt add selected player // cheating if (!normalizePlayerName(membername)) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } Player* player = sObjectAccessor->FindPlayerByName(membername.c_str()); // no player if (!player) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } // restrict invite to GMs if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster()) return; // can't group with if (!GetPlayer()->isGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); return; } if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); return; } // just ignore us if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); return; } if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); return; } Group* group = GetPlayer()->GetGroup(); if (group && group->isBGGroup()) group = GetPlayer()->GetOriginalGroup(); Group* group2 = player->GetGroup(); if (group2 && group2->isBGGroup()) group2 = player->GetOriginalGroup(); // player already in another group or invited if (group2 || player->GetGroupInvite()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); if (group2) { // tell the player that they were invited but it failed as they were already in a group WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size data << uint8(0); // invited/already in group flag data << GetPlayer()->GetName(); // max len 48 data << uint32(0); // unk data << uint8(0); // count data << uint32(0); // unk player->GetSession()->SendPacket(&data); } return; } if (group) { // not have permissions for invite if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) { SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); return; } // not have place if (group->IsFull()) { SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); return; } } // ok, but group not exist, start a new group // but don't create and save the group to the DB until // at least one person joins if (!group) { group = new Group; // new group: if can't add then delete if (!group->AddLeaderInvite(GetPlayer())) { delete group; return; } if (!group->AddInvite(player)) { delete group; return; } } else { // already existed group: if can't add then just leave if (!group->AddInvite(player)) { return; } } // ok, we do it WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size data << uint8(1); // invited/already in group flag data << GetPlayer()->GetName(); // max len 48 data << uint32(0); // unk data << uint8(0); // count data << uint32(0); // unk player->GetSession()->SendPacket(&data); SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); }
void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data ) { std::string membername; recv_data >> membername; recv_data.read_skip<uint32>(); // roles mask? // attempt add selected player // cheating if(!normalizePlayerName(membername)) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } Player *player = sObjectMgr.GetPlayer(membername.c_str()); // no player if(!player) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } // can't group with if(!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); return; } if(GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); return; } // just ignore us if(player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); return; } Group *group = GetPlayer()->GetGroup(); if( group && group->isBGGroup() ) group = GetPlayer()->GetOriginalGroup(); Group *group2 = player->GetGroup(); if( group2 && group2->isBGGroup() ) group2 = player->GetOriginalGroup(); // player already in another group or invited if( group2 || player->GetGroupInvite() ) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); return; } if(group) { // not have permissions for invite if (!group->IsLeader(GetPlayer()->GetObjectGuid()) && !group->IsAssistant(GetPlayer()->GetObjectGuid())) { SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); return; } // not have place if(group->IsFull()) { SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); return; } } // ok, but group not exist, start a new group // but don't create and save the group to the DB until // at least one person joins if(!group) { group = new Group; // new group: if can't add then delete if(!group->AddLeaderInvite(GetPlayer())) { delete group; return; } if(!group->AddInvite(player)) { delete group; return; } } else { // already existing group: if can't add then just leave if(!group->AddInvite(player)) { return; } } // ok, we do it WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size data << uint8(1); // invited/already in group flag data << GetPlayer()->GetName(); // max len 48 data << uint32(0); // unk data << uint8(0); // count //for(int i = 0; i < count; ++i) // data << uint32(0); data << uint32(0); // unk player->GetSession()->SendPacket(&data); SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); }
bool ChatHandler::HandleGMTicketAssignToCommand(const char* args) { if (!*args) return false; char* sTicketId = strtok((char*)args, " "); uint32 ticketId = atoi(sTicketId); char* sTarget = strtok(NULL, " "); if (!sTarget) return false; std::string target(sTarget); if (!normalizePlayerName(target)) return false; GmTicket* ticket = sTicketMgr->GetTicket(ticketId); if (!ticket || ticket->IsClosed()) { SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); return true; } // Get target information uint64 targetGuid = sObjectMgr->GetPlayerGUIDByName(target.c_str()); uint64 targetAccId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); uint32 targetGmLevel = AccountMgr::GetSecurity(targetAccId, realmID); // Target must exist and have administrative rights if (!targetGuid || AccountMgr::IsPlayerAccount(targetGmLevel)) { SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); return true; } // If already assigned, leave if (ticket->IsAssignedTo(targetGuid)) { PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->GetId()); return true; } // If assigned to different player other than current, leave //! Console can override though Player* player = m_session ? m_session->GetPlayer() : NULL; if (player && ticket->IsAssignedNotTo(player->GetGUID())) { PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId(), target.c_str()); return true; } // Assign ticket SQLTransaction trans = SQLTransaction(NULL); ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(targetGmLevel)); ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); std::string msg = ticket->FormatMessageString(*this, NULL, target.c_str(), NULL, NULL); SendGlobalGMSysMessage(msg.c_str()); return true; }
void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) { uint32 type; uint32 lang; recv_data >> type; recv_data >> lang; if (type >= MAX_CHAT_MSG_TYPE) { sLog.outError("CHAT: Wrong message type received: %u", type); return; } DEBUG_LOG("CHAT: packet received. type %u, lang %u", type, lang ); // prevent talking at unknown language (cheating) LanguageDesc const* langDesc = GetLanguageDescByID(lang); if (!langDesc) { SendNotification(LANG_UNKNOWN_LANGUAGE); return; } if (langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) { // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) Unit::AuraList const& langAuras = _player->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE); bool foundAura = false; for(Unit::AuraList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) { if ((*i)->GetModifier()->m_miscvalue == int32(lang)) { foundAura = true; break; } } if (!foundAura) { SendNotification(LANG_NOT_LEARNED_LANGUAGE); return; } } if (lang == LANG_ADDON) { // Disabled addon channel? if (!sWorld.getConfig(CONFIG_BOOL_ADDON_CHANNEL)) return; } // LANG_ADDON should not be changed nor be affected by flood control else { // send in universal language if player in .gmon mode (ignore spell effects) if (_player->isGameMaster()) lang = LANG_UNIVERSAL; else { // send in universal language in two side iteration allowed mode if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT) || _player->isInTeamBG()) lang = LANG_UNIVERSAL; else { switch(type) { case CHAT_MSG_PARTY: case CHAT_MSG_RAID: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: // allow two side chat at group channel if two side group allowed if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) lang = LANG_UNIVERSAL; break; case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: // allow two side chat at guild channel if two side guild allowed if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GUILD)) lang = LANG_UNIVERSAL; break; } } // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) Unit::AuraList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE); if (!ModLangAuras.empty()) lang = ModLangAuras.front()->GetModifier()->m_miscvalue; } if (!_player->CanSpeak()) { std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); return; } if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) GetPlayer()->UpdateSpeakTime(); } switch(type) { case CHAT_MSG_SAY: case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (type == CHAT_MSG_SAY) GetPlayer()->Say(msg, lang); else if (type == CHAT_MSG_EMOTE) GetPlayer()->TextEmote(msg); else if (type == CHAT_MSG_YELL) GetPlayer()->Yell(msg, lang); } break; case CHAT_MSG_WHISPER: { std::string to, msg; recv_data >> to; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (!normalizePlayerName(to)) { SendPlayerNotFoundNotice(to); break; } Player *player = sObjectMgr.GetPlayer(to.c_str()); uint32 tSecurity = GetSecurity(); uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) { SendPlayerNotFoundNotice(to); return; } if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER ) { uint32 sidea = GetPlayer()->getOriginalTeam(); uint32 sideb = player->getOriginalTeam(); if ( sidea != sideb ) { SendWrongFactionNotice(); return; } } GetPlayer()->Whisper(msg, lang, player->GetGUID()); } break; case CHAT_MSG_PARTY: case CHAT_MSG_PARTY_LEADER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /p Group *group = GetPlayer()->GetOriginalGroup(); if (!group) { group = _player->GetGroup(); if (!group || group->isBGGroup()) return; } if ((type == CHAT_MSG_PARTY_LEADER) && !group->IsLeader(_player->GetGUID())) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, type, lang, NULL, 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); } break; case CHAT_MSG_GUILD: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (GetPlayer()->GetGuildId()) if (Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId())) guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); } break; case CHAT_MSG_OFFICER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (GetPlayer()->GetGuildId()) if (Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId())) guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); } break; case CHAT_MSG_RAID: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /ra Group *group = GetPlayer()->GetOriginalGroup(); if (!group) { group = GetPlayer()->GetGroup(); if (!group || group->isBGGroup() || !group->isRaidGroup()) return; } WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_LEADER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /ra Group *group = GetPlayer()->GetOriginalGroup(); if (!group) { group = GetPlayer()->GetGroup(); if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) return; } WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_WARNING: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; Group *group = GetPlayer()->GetGroup(); if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID()))) return; WorldPacket data; //in battleground, raid warning is sent only to players in battleground - code is ok ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group *group = GetPlayer()->GetGroup(); if (!group || !group->isBGGroup()) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND_LEADER: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group *group = GetPlayer()->GetGroup(); if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_CHANNEL: { std::string channel, msg; recv_data >> channel; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel *chn = cMgr->GetChannel(channel, _player)) chn->Say(_player->GetGUID(), msg.c_str(), lang); } break; case CHAT_MSG_AFK: { std::string msg; recv_data >> msg; if ((msg.empty() || !_player->isAFK()) && !_player->isInCombat() ) { if (!_player->isAFK()) { if (msg.empty()) msg = GetMangosString(LANG_PLAYER_AFK_DEFAULT); _player->afkMsg = msg; } _player->ToggleAFK(); if (_player->isAFK() && _player->isDND()) _player->ToggleDND(); } } break; case CHAT_MSG_DND: { std::string msg; recv_data >> msg; if (msg.empty() || !_player->isDND()) { if (!_player->isDND()) { if (msg.empty()) msg = GetMangosString(LANG_PLAYER_DND_DEFAULT); _player->dndMsg = msg; } _player->ToggleDND(); if (_player->isDND() && _player->isAFK()) _player->ToggleAFK(); } } break; default: sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); break; } }
//Playerbot mod bool ChatHandler::HandlePlayerbotCommand(const char *args) { if(!m_session) { PSendSysMessage("You may only add bots from an active session"); SetSentErrorMessage(true); return false; } if(!*args) { PSendSysMessage("usage: add PLAYERNAME or remove PLAYERNAME"); SetSentErrorMessage(true); return false; } char *cmd = strtok ((char*)args, " "); char *charname = strtok (NULL, " "); if(!cmd || !charname) { PSendSysMessage("usage: add PLAYERNAME or remove PLAYERNAME"); SetSentErrorMessage(true); return false; } std::string cmdStr = cmd; std::string charnameStr = charname; uint64 guid; if (charnameStr.compare("all") != 0) { if (!normalizePlayerName(charnameStr)) return false; guid = sObjectMgr->GetPlayerGUIDByName(charnameStr.c_str()); if (guid == 0 || (guid == m_session->GetPlayer()->GetGUID())) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); return false; } uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid); if (accountId != m_session->GetAccountId()) { PSendSysMessage("You may only add bots from the same account."); SetSentErrorMessage(true); return false; } } if (cmdStr.compare("add") == 0 || cmdStr.compare("login") == 0) { if (charnameStr.compare("all") == 0) { std::list<std::string> *names; names=m_session->GetPlayer()->GetCharacterList(); std::list<std::string>::iterator iter,next; for (iter = names->begin(); iter != names->end(); iter++) { std::stringstream arg; arg << "add " << (*iter).c_str(); HandlePlayerbotCommand(arg.str().c_str()); } PSendSysMessage("Bots added successfully."); return true; } else { if(m_session->GetPlayerBot(guid) != NULL) { PSendSysMessage("Bot already exists in world."); SetSentErrorMessage(true); return false; } m_session->AddPlayerBot(guid); } } else if (cmdStr.compare("remove") == 0 || cmdStr.compare("logout") == 0) { if (charnameStr.compare("all") == 0) { std::list<std::string> *names = new std::list<std::string>; for (PlayerBotMap::const_iterator iter = m_session->GetPlayerBotsBegin(); iter != m_session->GetPlayerBotsEnd(); ++iter) { names->push_back(iter->second->GetName()); } std::list<std::string>::iterator iter,next; for (iter = names->begin(); iter != names->end(); iter++) { std::stringstream arg; arg << "remove " << (*iter).c_str(); HandlePlayerbotCommand(arg.str().c_str()); } return true; } else { if (m_session->GetPlayerBot(guid) == NULL) { PSendSysMessage("Bot can not be removed because bot does not exist in world."); SetSentErrorMessage(true); return false; } m_session->LogoutPlayerBot(guid, true); PSendSysMessage("Bot removed successfully."); return true; } } return true; }
void WorldSession::HandleGroupInviteOpcode(WorldPacket& recv_data) { std::string membername; recv_data >> membername; recv_data.read_skip<uint32>(); // roles mask? // attempt add selected player // cheating if(!normalizePlayerName(membername)) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } Player *player = sObjectMgr.GetPlayer(membername.c_str()); // no player if(!player) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); return; } // can't group with if(!GetPlayer()->isGameMaster() && !sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); return; } if(GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); return; } // just ignore us if(player->GetSocial()->HasIgnore(GetPlayer()->GetObjectGuid())) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); return; } Group *group = GetPlayer()->GetGroup(); if( group && group->isBGGroup() ) group = GetPlayer()->GetOriginalGroup(); if(group && group->isRaidGroup() && !player->GetAllowLowLevelRaid() && (player->getLevel() < sWorld.getConfig(CONFIG_UINT32_MIN_LEVEL_FOR_RAID))) { SendPartyResult(PARTY_OP_INVITE, "", ERR_RAID_DISALLOWED_BY_LEVEL); return; } // player already invited if (player->GetGroupInvite()) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); return; } Group* group2 = player->GetGroup(); if (group2 && group2->isBGGroup()) group2 = player->GetOriginalGroup(); // player already in another group if (group2) { SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); // tell the player that they were invited but it failed as they were already in a group SendGroupInvite(player, true); return; } if(group) { // not have permissions for invite if (!group->IsLeader(GetPlayer()->GetObjectGuid()) && !group->IsAssistant(GetPlayer()->GetObjectGuid())) { SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); return; } // not have place if(group->IsFull()) { SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); return; } } // ok, but group not exist, start a new group // but don't create and save the group to the DB until // at least one person joins if(!group) { group = new Group; // new group: if can't add then delete if(!group->AddLeaderInvite(GetPlayer())) { delete group; return; } if(!group->AddInvite(player)) { delete group; return; } } else { // already existing group: if can't add then just leave if(!group->AddInvite(player)) { return; } } SendGroupInvite(player); SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); }
void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "CMSG_ARENA_TEAM_INVITE"); uint32 arenaTeamId; // arena team id std::string invitedName; Player* player = NULL; recvData >> arenaTeamId >> invitedName; if (!invitedName.empty()) { if (!normalizePlayerName(invitedName)) return; player = sObjectAccessor->FindPlayerByName(invitedName); } if (!player) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", invitedName, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; } if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); return; } ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); if (!arenaTeam) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM); return; } if (arenaTeam->GetCaptain() != _player->GetGUID()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); return; } // OK result but don't send invite if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) return; if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); return; } if (player->GetArenaTeamId(arenaTeam->GetSlot())) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); return; } if (player->GetArenaTeamIdInvited()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } if (arenaTeam->GetMembersSize() >= arenaTeam->GetType() * 2) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, arenaTeam->GetName(), "", ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S); return; } TC_LOG_DEBUG("bg.battleground", "Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName().c_str(), invitedName.c_str()); player->SetArenaTeamIdInvited(arenaTeam->GetId()); WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10)); data << GetPlayer()->GetName(); data << arenaTeam->GetName(); player->GetSession()->SendPacket(&data); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_ARENA_TEAM_INVITE"); }
void WorldSession::HandleSendMail(WorldPacket& recvData) { ObjectGuid mailbox; uint64 money, COD; std::string receiver, subject, body; uint32 bodyLength, subjectLength, receiverLength; uint32 unk1, unk2; recvData >> unk1; recvData >> unk2; // Stationery? recvData >> COD >> money; // money and cod bodyLength = recvData.ReadBits(12); subjectLength = recvData.ReadBits(9); uint8 items_count = recvData.ReadBits(5); // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recvData.rfinish(); // set to end to avoid warnings spam return; } mailbox[0] = recvData.ReadBit(); ObjectGuid itemGUIDs[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { itemGUIDs[i][2] = recvData.ReadBit(); itemGUIDs[i][6] = recvData.ReadBit(); itemGUIDs[i][3] = recvData.ReadBit(); itemGUIDs[i][7] = recvData.ReadBit(); itemGUIDs[i][1] = recvData.ReadBit(); itemGUIDs[i][0] = recvData.ReadBit(); itemGUIDs[i][4] = recvData.ReadBit(); itemGUIDs[i][5] = recvData.ReadBit(); } mailbox[3] = recvData.ReadBit(); mailbox[4] = recvData.ReadBit(); receiverLength = recvData.ReadBits(7); mailbox[2] = recvData.ReadBit(); mailbox[6] = recvData.ReadBit(); mailbox[1] = recvData.ReadBit(); mailbox[7] = recvData.ReadBit(); mailbox[5] = recvData.ReadBit(); recvData.ReadByteSeq(mailbox[4]); for (uint8 i = 0; i < items_count; ++i) { recvData.ReadByteSeq(itemGUIDs[i][6]); recvData.ReadByteSeq(itemGUIDs[i][1]); recvData.ReadByteSeq(itemGUIDs[i][7]); recvData.ReadByteSeq(itemGUIDs[i][2]); recvData.read_skip<uint8>(); // item slot in mail, not used recvData.ReadByteSeq(itemGUIDs[i][3]); recvData.ReadByteSeq(itemGUIDs[i][0]); recvData.ReadByteSeq(itemGUIDs[i][4]); recvData.ReadByteSeq(itemGUIDs[i][5]); } recvData.ReadByteSeq(mailbox[7]); recvData.ReadByteSeq(mailbox[3]); recvData.ReadByteSeq(mailbox[6]); recvData.ReadByteSeq(mailbox[5]); subject = recvData.ReadString(subjectLength); receiver = recvData.ReadString(receiverLength); recvData.ReadByteSeq(mailbox[2]); recvData.ReadByteSeq(mailbox[0]); body = recvData.ReadString(bodyLength); recvData.ReadByteSeq(mailbox[1]); // packet read complete, now do check if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; if (receiver.empty()) return; Player* player = _player; if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint64 rc = 0; if (normalizePlayerName(receiver)) rc = sObjectMgr->GetPlayerGUIDByName(receiver); if (!rc) { sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if (player->GetGUID() == rc) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint64 reqmoney = cost + money; if (!player->HasEnoughMoney(reqmoney) && !player->isGameMaster()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player* receive = ObjectAccessor::FindPlayer(rc); uint32 rc_team = 0; uint8 mails_count = 0; //do not allow to send to one player more than 100 mails uint8 receiveLevel = 0; if (receive) { rc_team = receive->GetTeam(); mails_count = receive->GetMailSize(); receiveLevel = receive->getLevel(); } else { rc_team = sObjectMgr->GetPlayerTeamByGUID(rc); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT); stmt->setUInt32(0, GUID_LOPART(rc)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); mails_count = fields[0].GetUInt64(); } InfoCharEntry info; if(sInfoMgr->GetCharInfo(GUID_LOPART(rc), info)) receiveLevel = info.Level; else { stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL); stmt->setUInt32(0, GUID_LOPART(rc)); result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); receiveLevel = fields[0].GetUInt8(); } } } //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mails_count > 100) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // test the receiver's Faction... or all items are account bound bool accountBound = items_count ? true : false; for (uint8 i = 0; i < items_count; ++i) { Item* item = player->GetItemByGuid(itemGUIDs[i]); if (item) { ItemTemplate const* itemProto = item->GetTemplate(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; } } } if (!accountBound && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeam() != rc_team && AccountMgr::IsPlayerAccount(GetSecurity())) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } if (receiveLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(rc); Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { if (!itemGUIDs[i]) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = player->GetItemByGuid(itemGUIDs[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != rc_account) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT); return; } if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } if (item->IsNotEmptyBag()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_DESTROY_NONEMPTY_BAG); return; } items[i] = item; } player->SendMailResult(0, MAIL_SEND, MAIL_OK); player->ModifyMoney(-int64(reqmoney)); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (items_count > 0 || money > 0) { if (items_count > 0) { for (uint8 i = 0; i < items_count; ++i) { Item* item = items[i]; if (!AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory item->SetOwnerGUID(rc); item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = player->GetSession()->GetAccountId() != rc_account; } if (money > 0 && !AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: " UI64FMTD " to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(), money, receiver.c_str(), rc_account); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list draft .AddMoney(money) .AddCOD(COD) .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
Player *IRCCmd::GetPlayer(std::string WHO) { normalizePlayerName(WHO); return sObjectAccessor->FindPlayerByName(WHO.c_str()); }