diff options
Diffstat (limited to 'src')
35 files changed, 364 insertions, 384 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index ecf3b52e8d9..6c17f0c4c07 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -26,7 +26,6 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_INS_QUEST_POOL_SAVE, "INSERT INTO pool_quest_save (pool_id, quest_id) VALUES (?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_GUID_BY_NAME, "SELECT guid FROM characters WHERE name = ?", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHECK_NAME, "SELECT 1 FROM characters WHERE name = ?", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHECK_GUID, "SELECT 1 FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_SUM_CHARS, "SELECT COUNT(guid) FROM characters WHERE account = ?", CONNECTION_BOTH); @@ -52,8 +51,6 @@ void CharacterDatabaseConnection::DoPrepareStatements() "LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid " "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name, at_login FROM characters WHERE guid = ? AND account = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_BOTH); - PrepareStatement(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level, name FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH); @@ -123,7 +120,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW, "SELECT quest FROM character_queststatus_rewarded WHERE guid = ? AND active = 1", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES, "SELECT instanceId, releaseTime FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, item_guid, itemEntry, owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid WHERE mail_id = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, itemguid, itemEntry FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_AUCTIONS, "SELECT id, houseid, itemguid, itemEntry, count, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid", CONNECTION_SYNCH); @@ -154,12 +151,11 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER, "DELETE FROM item_instance WHERE owner_guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_GIFT_OWNER, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GIFT, "DELETE FROM character_gifts WHERE item_guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM, "SELECT entry, flags FROM character_gifts WHERE item_guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM, "SELECT entry, flags FROM character_gifts WHERE item_guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_ACCOUNT_BY_NAME, "SELECT account FROM characters WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_UPD_ACCOUNT_BY_GUID, "UPDATE characters SET account = ? WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES, "DELETE FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES, "INSERT INTO account_instance_times (accountId, instanceId, releaseTime) VALUES (?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_NAME_CLASS, "SELECT name, class FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_NAME_BY_GUID, "UPDATE characters SET name = ? WHERE guid = ?", CONNECTION_ASYNC); @@ -299,7 +295,6 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_ARENA_TEAM_MEMBER, "UPDATE arena_team_member SET personalRating = ?, weekGames = ?, weekWins = ?, seasonGames = ?, seasonWins = ? WHERE arenaTeamId = ? AND guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHARACTER_ARENA_STATS, "DELETE FROM character_arena_stats WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_REP_CHARACTER_ARENA_STATS, "REPLACE INTO character_arena_stats (guid, slot, matchMakerRating) VALUES (?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_PLAYER_ARENA_TEAMS, "SELECT arena_team_member.arenaTeamId FROM arena_team_member JOIN arena_team ON arena_team_member.arenaTeamId = arena_team.arenaTeamId WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_UPD_ARENA_TEAM_NAME, "UPDATE arena_team SET name = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC); // Character battleground data @@ -435,9 +430,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_COD_ITEM_MAIL, "SELECT id, messageType, mailTemplateId, sender, subject, body, money, has_items FROM mail WHERE receiver = ? AND has_items <> 0 AND cod <> 0", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_SOCIAL, "SELECT DISTINCT guid FROM character_social WHERE friend = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_OLD_CHARS, "SELECT guid, deleteInfos_Account FROM characters WHERE deleteDate IS NOT NULL AND deleteDate < ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_ARENA_TEAM_ID_BY_PLAYER_GUID, "SELECT arena_team_member.arenateamid FROM arena_team_member JOIN arena_team ON arena_team_member.arenateamid = arena_team.arenateamid WHERE guid = ? AND type = ? LIMIT 1", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MAIL, "SELECT id, messageType, sender, receiver, subject, body, has_items, expire_time, deliver_time, money, cod, checked, stationery, mailTemplateId FROM mail WHERE receiver = ? ORDER BY id DESC", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_CHAR_GUID_BY_NAME, "SELECT guid FROM characters WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index 5998b5f584c..0d9b518cafa 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -33,7 +33,6 @@ enum CharacterDatabaseStatements CHAR_INS_QUEST_POOL_SAVE, CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM, CHAR_DEL_EXPIRED_BANS, - CHAR_SEL_GUID_BY_NAME, CHAR_SEL_CHECK_NAME, CHAR_SEL_CHECK_GUID, CHAR_SEL_SUM_CHARS, @@ -51,8 +50,6 @@ enum CharacterDatabaseStatements CHAR_SEL_ENUM, CHAR_SEL_ENUM_DECLINED_NAME, CHAR_SEL_FREE_NAME, - CHAR_SEL_GUID_RACE_ACC_BY_NAME, - CHAR_SEL_CHAR_LEVEL, CHAR_SEL_CHAR_ZONE, CHAR_SEL_CHARACTER_NAME_DATA, CHAR_SEL_CHAR_POSITION_XYZ, @@ -145,7 +142,6 @@ enum CharacterDatabaseStatements CHAR_UPD_ACCOUNT_BY_GUID, CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES, CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES, - CHAR_SEL_CHARACTER_NAME_CLASS, CHAR_SEL_MATCH_MAKER_RATING, CHAR_SEL_CHARACTER_COUNT, CHAR_UPD_NAME_BY_GUID, @@ -239,7 +235,6 @@ enum CharacterDatabaseStatements CHAR_UPD_ARENA_TEAM_MEMBER, CHAR_DEL_CHARACTER_ARENA_STATS, CHAR_REP_CHARACTER_ARENA_STATS, - CHAR_SEL_PLAYER_ARENA_TEAMS, CHAR_UPD_ARENA_TEAM_NAME, CHAR_SEL_PETITION, @@ -366,9 +361,7 @@ enum CharacterDatabaseStatements CHAR_SEL_CHAR_COD_ITEM_MAIL, CHAR_SEL_CHAR_SOCIAL, CHAR_SEL_CHAR_OLD_CHARS, - CHAR_SEL_ARENA_TEAM_ID_BY_PLAYER_GUID, CHAR_SEL_MAIL, - CHAR_SEL_CHAR_GUID_BY_NAME, CHAR_DEL_CHAR_AURA_FROZEN, CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, CHAR_SEL_MAIL_COUNT_ITEM, diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index fd535085111..6dd833410f2 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -104,21 +104,16 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid) } else { - // 0 1 - // SELECT name, class FROM characters WHERE guid = ? - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_CLASS); - stmt->setUInt32(0, playerGuid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + CharacterInfo const* cInfo = sWorld->GetCharacterInfo(playerGuid); + if (!cInfo) return false; - playerName = (*result)[0].GetString(); - playerClass = (*result)[1].GetUInt8(); + playerName = cInfo->Name; + playerClass = cInfo->Class; } // Check if player is already in a similar arena team - if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0) + if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromCharacterInfo(playerGuid, GetType()) != 0) { TC_LOG_DEBUG("bg.arena", "Arena: %s %s already has an arena team of type %u", playerGuid.ToString().c_str(), playerName.c_str(), GetType()); return false; @@ -161,6 +156,7 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid) newMember.MatchMakerRating = matchMakerRating; Members.push_back(newMember); + sWorld->UpdateCharacterArenaTeamId(playerGuid, GetSlot(), GetId()); // Save player's arena team membership to db stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER); @@ -256,6 +252,7 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result) // Put the player in the team Members.push_back(newMember); + sWorld->UpdateCharacterArenaTeamId(newMember.Guid, GetSlot(), GetId()); } while (result->NextRow()); @@ -315,11 +312,14 @@ void ArenaTeam::DelMember(ObjectGuid guid, bool cleanDb) { // Remove member from team for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr) + { if (itr->Guid == guid) { Members.erase(itr); + sWorld->UpdateCharacterArenaTeamId(guid, GetSlot(), 0); break; } + } // Inform player and remove arena team info from player data if (Player* player = ObjectAccessor::FindPlayer(guid)) diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index 9904eabcec8..f3192d71e96 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -75,7 +75,7 @@ void CalendarMgr::LoadFromDB() ObjectGuid::LowType guildId = 0; if (flags & CALENDAR_FLAG_GUILD_EVENT || flags & CALENDAR_FLAG_WITHOUT_INVITES) - guildId = Player::GetGuildIdFromDB(creatorGUID); + guildId = Player::GetGuildIdFromCharacterInfo(creatorGUID); CalendarEvent* calendarEvent = new CalendarEvent(eventId, creatorGUID, guildId, type, dungeonId, time_t(eventTime), flags, time_t(timezoneTime), title, description); _events.insert(calendarEvent); @@ -432,7 +432,7 @@ void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite) ObjectGuid invitee = invite.GetInviteeGUID(); Player* player = ObjectAccessor::FindConnectedPlayer(invitee); - uint8 level = player ? player->getLevel() : Player::GetLevelFromDB(invitee); + uint8 level = player ? player->getLevel() : Player::GetLevelFromCharacterInfo(invitee); WorldPacket data(SMSG_CALENDAR_EVENT_INVITE, 8 + 8 + 8 + 1 + 1 + 1 + (statusTime ? 4 : 0) + 1); data << invitee.WriteAsPacked(); @@ -578,8 +578,8 @@ void CalendarMgr::SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calend ObjectGuid inviteeGuid = calendarInvite->GetInviteeGUID(); Player* invitee = ObjectAccessor::FindPlayer(inviteeGuid); - uint8 inviteeLevel = invitee ? invitee->getLevel() : Player::GetLevelFromDB(inviteeGuid); - ObjectGuid::LowType inviteeGuildId = invitee ? invitee->GetGuildId() : Player::GetGuildIdFromDB(inviteeGuid); + uint8 inviteeLevel = invitee ? invitee->getLevel() : Player::GetLevelFromCharacterInfo(inviteeGuid); + ObjectGuid::LowType inviteeGuildId = invitee ? invitee->GetGuildId() : Player::GetGuildIdFromCharacterInfo(inviteeGuid); data << inviteeGuid.WriteAsPacked(); data << uint8(inviteeLevel); diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index d486a95c52a..abc5f520deb 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -1030,7 +1030,7 @@ ObjectGuid::LowType ChatHandler::extractLowGuidFromLink(char* text, HighGuid& gu if (Player* player = ObjectAccessor::FindPlayerByName(name)) return player->GetGUID().GetCounter(); - if (ObjectGuid guid = sObjectMgr->GetPlayerGUIDByName(name)) + if (ObjectGuid guid = sWorld->GetCharacterGuidByName(name)) return guid.GetCounter(); return 0; @@ -1086,7 +1086,7 @@ bool ChatHandler::extractPlayerTarget(char* args, Player** player, ObjectGuid* p *player = pl; // if need guid value from DB (in name case for check player existence) - ObjectGuid guid = !pl && (player_guid || player_name) ? sObjectMgr->GetPlayerGUIDByName(name) : ObjectGuid::Empty; + ObjectGuid guid = !pl && (player_guid || player_name) ? sWorld->GetCharacterGuidByName(name) : ObjectGuid::Empty; // if allowed player guid (if no then only online players allowed) if (player_guid) @@ -1245,7 +1245,7 @@ bool ChatHandler::GetPlayerGroupAndGUIDByName(char const* cname, Player*& player player = ObjectAccessor::FindPlayerByName(name); if (offline) - guid = sObjectMgr->GetPlayerGUIDByName(name.c_str()); + guid = sWorld->GetCharacterGuidByName(name); } } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 1dfe70186ff..52e7611ebb5 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -285,7 +285,7 @@ void Creature::RemoveCorpse(bool setSpawnTime) m_corpseRemoveTime = time(NULL); setDeathState(DEAD); RemoveAllAuras(); - UpdateObjectVisibility(); + DestroyForNearbyPlayers(); // old UpdateObjectVisibility() loot.clear(); uint32 respawnDelay = m_respawnDelay; if (IsAIEnabled) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index d1a1dcf0f05..8b80d027c9f 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -683,7 +683,7 @@ void GameObject::Update(uint32 diff) if (!m_spawnedByDefault) { m_respawnTime = 0; - UpdateObjectVisibility(); + DestroyForNearbyPlayers(); // old UpdateObjectVisibility() return; } @@ -693,8 +693,7 @@ void GameObject::Update(uint32 diff) if (sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) SaveRespawnTime(); - UpdateObjectVisibility(); - + DestroyForNearbyPlayers(); // old UpdateObjectVisibility() break; } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0718f193d97..9e1d00b72ce 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -59,6 +59,7 @@ #include "OutdoorPvP.h" #include "OutdoorPvPMgr.h" #include "Pet.h" +#include "QueryCallback.h" #include "QuestDef.h" #include "ReputationMgr.h" #include "GitRevision.h" @@ -4091,7 +4092,7 @@ void Player::DestroyForPlayer(Player* target, bool onDeath) const { Unit::DestroyForPlayer(target, onDeath); - for (uint8 i = 0; i < INVENTORY_SLOT_BAG_END; ++i) + for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) { if (m_items[i] == nullptr) continue; @@ -4227,22 +4228,26 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe // Convert guid to low GUID for CharacterNameData, but also other methods on success ObjectGuid::LowType guid = playerguid.GetCounter(); uint32 charDelete_method = sWorld->getIntConfig(CONFIG_CHARDELETE_METHOD); + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(playerguid); + std::string name; + if (characterInfo) + name = characterInfo->Name; if (deleteFinally) charDelete_method = CHAR_DELETE_REMOVE; - else if (CharacterInfo const* nameData = sWorld->GetCharacterInfo(playerguid)) // To avoid a query, we select loaded data. If it doesn't exist, return. + else if (characterInfo) // To avoid a query, we select loaded data. If it doesn't exist, return. { // Define the required variables - uint32 charDelete_minLvl = sWorld->getIntConfig(nameData->Class != CLASS_DEATH_KNIGHT ? CONFIG_CHARDELETE_MIN_LEVEL : CONFIG_CHARDELETE_HEROIC_MIN_LEVEL); + uint32 charDelete_minLvl = sWorld->getIntConfig(characterInfo->Class != CLASS_DEATH_KNIGHT ? CONFIG_CHARDELETE_MIN_LEVEL : CONFIG_CHARDELETE_HEROIC_MIN_LEVEL); // if we want to finalize the character removal or the character does not meet the level requirement of either heroic or non-heroic settings, // we set it to mode CHAR_DELETE_REMOVE - if (nameData->Level < charDelete_minLvl) + if (characterInfo->Level < charDelete_minLvl) charDelete_method = CHAR_DELETE_REMOVE; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); - if (ObjectGuid::LowType guildId = GetGuildIdFromDB(playerguid)) + if (ObjectGuid::LowType guildId = Player::GetGuildIdFromCharacterInfo(playerguid)) if (Guild* guild = sGuildMgr->GetGuildById(guildId)) guild->DeleteMember(trans, playerguid, false, false, true); @@ -4582,7 +4587,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe if (updateRealmChars) sWorld->UpdateRealmCharCount(accountId); - sWorld->DeleteCharacterInfo(playerguid); + sWorld->DeleteCharacterInfo(playerguid, name); } /** @@ -6994,32 +6999,13 @@ void Player::ModifyArenaPoints(int32 value, SQLTransaction trans) } } -ObjectGuid::LowType Player::GetGuildIdFromDB(ObjectGuid guid) +ObjectGuid::LowType Player::GetGuildIdFromCharacterInfo(ObjectGuid guid) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER); - stmt->setUInt32(0, guid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); + if (!characterInfo) return 0; - uint32 id = result->Fetch()[0].GetUInt32(); - return id; -} - -uint8 Player::GetRankFromDB(ObjectGuid guid) -{ - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER); - stmt->setUInt32(0, guid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - uint32 v = result->Fetch()[1].GetUInt8(); - return v; - } - else - return 0; + return characterInfo->GuildId; } void Player::SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type) @@ -7033,18 +7019,13 @@ void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 va SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value); } -uint32 Player::GetArenaTeamIdFromDB(ObjectGuid guid, uint8 type) +uint32 Player::GetArenaTeamIdFromCharacterInfo(ObjectGuid guid, uint8 type) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ARENA_TEAM_ID_BY_PLAYER_GUID); - stmt->setUInt32(0, guid.GetCounter()); - stmt->setUInt8(1, type); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); + if (!characterInfo) return 0; - uint32 id = (*result)[0].GetUInt32(); - return id; + return characterInfo->ArenaTeamId[type]; } uint32 Player::GetZoneIdFromDB(ObjectGuid guid) @@ -7093,19 +7074,13 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid) return zone; } -uint32 Player::GetLevelFromDB(ObjectGuid guid) +uint32 Player::GetLevelFromCharacterInfo(ObjectGuid guid) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL); - stmt->setUInt32(0, guid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); + if (!characterInfo) return 0; - Field* fields = result->Fetch(); - uint8 level = fields[0].GetUInt8(); - - return level; + return characterInfo->Level; } void Player::UpdateArea(uint32 newArea) @@ -15706,17 +15681,17 @@ bool Player::SatisfyQuestWeek(Quest const* qInfo, bool /*msg*/) return m_weeklyquests.find(qInfo->GetQuestId()) == m_weeklyquests.end(); } -bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/) +bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/) const { if (!qInfo->IsSeasonal() || m_seasonalquests.empty()) return true; - uint16 eventId = sGameEventMgr->GetEventIdForQuest(qInfo); - if (m_seasonalquests.find(eventId) == m_seasonalquests.end() || m_seasonalquests[eventId].empty()) + auto itr = m_seasonalquests.find(qInfo->GetEventIdForQuest()); + if (itr == m_seasonalquests.end() || itr->second.empty()) return true; // if not found in cooldown list - return m_seasonalquests[eventId].find(qInfo->GetQuestId()) == m_seasonalquests[eventId].end(); + return itr->second.find(qInfo->GetQuestId()) == itr->second.end(); } bool Player::SatisfyQuestMonth(Quest const* qInfo, bool /*msg*/) @@ -15802,15 +15777,7 @@ bool Player::GetQuestRewardStatus(uint32 quest_id) const if (qInfo) { if (qInfo->IsSeasonal() && !qInfo->IsRepeatable()) - { - uint16 eventId = sGameEventMgr->GetEventIdForQuest(qInfo); - auto seasonalQuestItr = m_seasonalquests.find(eventId); - if (seasonalQuestItr != m_seasonalquests.end()) - return seasonalQuestItr->second.find(quest_id) != seasonalQuestItr->second.end(); - - return false; - } - + return !SatisfyQuestSeasonal(qInfo, false); // for repeatable quests: rewarded field is set after first reward only to prevent getting XP more than once if (!qInfo->IsRepeatable()) @@ -15832,14 +15799,9 @@ QuestStatus Player::GetQuestStatus(uint32 quest_id) const if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id)) { if (qInfo->IsSeasonal() && !qInfo->IsRepeatable()) - { - uint16 eventId = sGameEventMgr->GetEventIdForQuest(qInfo); - auto seasonalQuestItr = m_seasonalquests.find(eventId); - if (seasonalQuestItr == m_seasonalquests.end() || seasonalQuestItr->second.find(quest_id) == seasonalQuestItr->second.end()) - return QUEST_STATUS_NONE; - } + return SatisfyQuestSeasonal(qInfo, false) ? QUEST_STATUS_NONE : QUEST_STATUS_REWARDED; - if (!qInfo->IsRepeatable() && m_RewardedQuests.find(quest_id) != m_RewardedQuests.end()) + if (!qInfo->IsRepeatable() && IsQuestRewarded(quest_id)) return QUEST_STATUS_REWARDED; } } @@ -21006,17 +20968,13 @@ void Player::RemovePetitionsAndSigns(ObjectGuid guid, uint32 type) void Player::LeaveAllArenaTeams(ObjectGuid guid) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_ARENA_TEAMS); - stmt->setUInt32(0, guid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); + if (!characterInfo) return; - do + for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i) { - Field* fields = result->Fetch(); - uint32 arenaTeamId = fields[0].GetUInt32(); + uint32 arenaTeamId = characterInfo->ArenaTeamId[i]; if (arenaTeamId != 0) { ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); @@ -21024,7 +20982,6 @@ void Player::LeaveAllArenaTeams(ObjectGuid guid) arenaTeam->DelMember(guid, true); } } - while (result->NextRow()); } void Player::SetRestBonus(float rest_bonus_new) @@ -23017,7 +22974,7 @@ void Player::SetSeasonalQuestStatus(uint32 quest_id) if (!quest) return; - m_seasonalquests[sGameEventMgr->GetEventIdForQuest(quest)].insert(quest_id); + m_seasonalquests[quest->GetEventIdForQuest()].insert(quest_id); m_SeasonalQuestChanged = true; } @@ -25905,15 +25862,22 @@ void Player::ActivateSpec(uint8 spec) m_usedTalentCount = spentTalents; InitTalentForLevel(); + // load them asynchronously { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC); stmt->setUInt32(0, GetGUID().GetCounter()); stmt->setUInt8(1, m_activeSpec); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - _LoadActions(result); - } - SendActionButtons(1); + WorldSession* mySess = GetSession(); + mySess->GetQueryProcessor().AddQuery(CharacterDatabase.AsyncQuery(stmt) + .WithPreparedCallback([mySess](PreparedQueryResult result) + { + // safe callback, we can't pass this pointer directly + // in case player logs out before db response (player would be deleted in that case) + if (Player* thisPlayer = mySess->GetPlayer()) + thisPlayer->LoadActions(result); + })); + } Powers pw = getPowerType(); if (pw != POWER_MANA) @@ -25929,6 +25893,14 @@ void Player::ActivateSpec(uint8 spec) } } +void Player::LoadActions(PreparedQueryResult result) +{ + if (result) + _LoadActions(result); + + SendActionButtons(1); +} + void Player::ResetTimeSync() { m_timeSyncCounter = 0; @@ -26402,6 +26374,12 @@ std::string Player::GetCoordsMapAreaAndZoneString() const return str.str(); } +void Player::SetInGuild(uint32 guildId) +{ + SetUInt32Value(PLAYER_GUILDID, guildId); + sWorld->UpdateCharacterGuildId(GetGUID(), guildId); +} + Guild* Player::GetGuild() { uint32 guildId = GetGuildId(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 9fcf2bb89d8..9e671a305b0 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1361,7 +1361,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> bool SatisfyQuestDay(Quest const* qInfo, bool msg) const; bool SatisfyQuestWeek(Quest const* qInfo, bool msg); bool SatisfyQuestMonth(Quest const* qInfo, bool msg); - bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg); + bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg) const; bool GiveQuestSourceItem(Quest const* quest); bool TakeQuestSourceItem(uint32 questId, bool msg); bool GetQuestRewardStatus(uint32 quest_id) const; @@ -1446,7 +1446,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> static uint32 GetUInt32ValueFromArray(Tokenizer const& data, uint16 index); static float GetFloatValueFromArray(Tokenizer const& data, uint16 index); static uint32 GetZoneIdFromDB(ObjectGuid guid); - static uint32 GetLevelFromDB(ObjectGuid guid); + static uint32 GetLevelFromCharacterInfo(ObjectGuid guid); static bool LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, ObjectGuid guid); static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE; } @@ -1590,6 +1590,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint8 GetSpecsCount() const { return m_specsCount; } void SetSpecsCount(uint8 count) { m_specsCount = count; } void ActivateSpec(uint8 spec); + void LoadActions(PreparedQueryResult result); void InitGlyphsForLevel(); void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); } @@ -1678,21 +1679,20 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void RemoveFromGroup(RemoveMethod method = GROUP_REMOVEMETHOD_DEFAULT) { RemoveFromGroup(GetGroup(), GetGUID(), method); } void SendUpdateToOutOfRangeGroupMembers(); - void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); } + void SetInGuild(uint32 guildId); void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); } uint8 GetRank() const { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); } void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; } uint32 GetGuildId() const { return GetUInt32Value(PLAYER_GUILDID); } Guild* GetGuild(); - static ObjectGuid::LowType GetGuildIdFromDB(ObjectGuid guid); - static uint8 GetRankFromDB(ObjectGuid guid); + static ObjectGuid::LowType GetGuildIdFromCharacterInfo(ObjectGuid guid); int GetGuildIdInvited() const { return m_GuildIdInvited; } static void RemovePetitionsAndSigns(ObjectGuid guid, uint32 type); // Arena Team void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type); void SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value); - static uint32 GetArenaTeamIdFromDB(ObjectGuid guid, uint8 slot); + static uint32 GetArenaTeamIdFromCharacterInfo(ObjectGuid guid, uint8 slot); static void LeaveAllArenaTeams(ObjectGuid guid); uint32 GetArenaTeamId(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID); } uint32 GetArenaPersonalRating(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); } diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index f2f775811d7..0d59f6731af 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -763,7 +763,8 @@ void GameEventMgr::LoadFromDB() uint32 questId = fields[0].GetUInt32(); uint32 eventEntry = fields[1].GetUInt32(); /// @todo Change to uint8 - if (!sObjectMgr->GetQuestTemplate(questId)) + Quest* questTemplate = const_cast<Quest*>(sObjectMgr->GetQuestTemplate(questId)); + if (!questTemplate) { TC_LOG_ERROR("sql.sql", "`game_event_seasonal_questrelation`: quest id (%u) does not exist in `quest_template`.", questId); continue; @@ -775,7 +776,7 @@ void GameEventMgr::LoadFromDB() continue; } - _questToEventLinks[questId] = eventEntry; + questTemplate->SetEventIdForQuest(static_cast<uint16>(eventEntry)); ++count; } while (result->NextRow()); @@ -1664,18 +1665,6 @@ void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate) }); } -uint16 GameEventMgr::GetEventIdForQuest(Quest const* quest) const -{ - if (!quest) - return 0; - - std::unordered_map<uint32, uint16>::const_iterator itr = _questToEventLinks.find(quest->GetQuestId()); - if (itr == _questToEventLinks.end()) - return 0; - - return itr->second; -} - bool IsHolidayActive(HolidayIds id) { if (id == HOLIDAY_NONE) diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index 23ad117001f..05737b23426 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -121,7 +121,6 @@ class TC_GAME_API GameEventMgr void HandleWorldEventGossip(Player* player, Creature* c); uint32 GetNPCFlag(Creature* cr); uint32 GetNpcTextId(uint32 guid); - uint16 GetEventIdForQuest(Quest const* quest) const; private: void SendWorldStateUpdate(Player* player, uint16 event_id); void AddActiveEvent(uint16 event_id) { m_ActiveEvents.insert(event_id); } @@ -173,7 +172,6 @@ class TC_GAME_API GameEventMgr QuestIdToEventConditionMap mQuestToEventConditions; GameEventNPCFlagMap mGameEventNPCFlags; ActiveEvents m_ActiveEvents; - std::unordered_map<uint32, uint16> _questToEventLinks; bool isSystemInit; public: GameEventGuidMap mGameEventCreatureGuids; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1b08ec1a68f..a880b527d17 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2226,21 +2226,6 @@ Player* ObjectMgr::GetPlayerByLowGUID(ObjectGuid::LowType lowguid) const return ObjectAccessor::FindPlayer(guid); } -// name must be checked to correctness (if received) before call this function -ObjectGuid ObjectMgr::GetPlayerGUIDByName(std::string const& name) const -{ - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - - stmt->setString(0, name); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - return ObjectGuid(HighGuid::Player, (*result)[0].GetUInt32()); - - return ObjectGuid::Empty; -} - bool ObjectMgr::GetPlayerNameByGUID(ObjectGuid guid, std::string& name) const { CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); @@ -2268,19 +2253,11 @@ uint32 ObjectMgr::GetPlayerAccountIdByGUID(ObjectGuid guid) const return 0; } -uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const +uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(std::string const& name) const { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_BY_NAME); - - stmt->setString(0, name); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - uint32 acc = (*result)[0].GetUInt32(); - return acc; - } + ObjectGuid guid = sWorld->GetCharacterGuidByName(name); + if (!guid.IsEmpty()) + return GetPlayerAccountIdByGUID(guid); return 0; } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index ef054932d8b..087970fd31d 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -755,8 +755,6 @@ class TC_GAME_API ObjectMgr void GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const; - ObjectGuid GetPlayerGUIDByName(std::string const& name) const; - GameObjectQuestItemList const* GetGameObjectQuestItemList(uint32 id) const { GameObjectQuestItemMap::const_iterator itr = _gameObjectQuestItemStore.find(id); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 1812a4b059b..9a27c800a2b 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1978,7 +1978,8 @@ void Guild::LoadRankFromDB(Field* fields) bool Guild::LoadMemberFromDB(Field* fields) { ObjectGuid::LowType lowguid = fields[1].GetUInt32(); - Member* member = new Member(m_id, ObjectGuid(HighGuid::Player, lowguid), fields[2].GetUInt8()); + ObjectGuid playerGuid(HighGuid::Player, lowguid); + Member* member = new Member(m_id, playerGuid, fields[2].GetUInt8()); if (!member->LoadFromDB(fields)) { SQLTransaction trans(nullptr); @@ -1986,6 +1987,8 @@ bool Guild::LoadMemberFromDB(Field* fields) delete member; return false; } + + sWorld->UpdateCharacterGuildId(playerGuid, GetId()); m_members[lowguid] = member; return true; } @@ -2197,7 +2200,7 @@ void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 max } Member* member = itr->second; - uint32 level = Player::GetLevelFromDB(member->GetGUID()); + uint32 level = Player::GetLevelFromCharacterInfo(member->GetGUID()); if (member->GetGUID() != session->GetPlayer()->GetGUID() && level >= minLevel && level <= maxLevel && member->IsRankNotLower(minRank)) { @@ -2222,7 +2225,7 @@ bool Guild::AddMember(SQLTransaction& trans, ObjectGuid guid, uint8 rankId) if (player->GetGuildId() != 0) return false; } - else if (Player::GetGuildIdFromDB(guid) != 0) + else if (Player::GetGuildIdFromCharacterInfo(guid) != 0) return false; // Remove all player signs from another petitions @@ -2274,6 +2277,7 @@ bool Guild::AddMember(SQLTransaction& trans, ObjectGuid guid, uint8 rankId) return false; } m_members[lowguid] = member; + sWorld->UpdateCharacterGuildId(guid, GetId()); } member->SaveToDB(trans); @@ -2341,6 +2345,8 @@ void Guild::DeleteMember(SQLTransaction& trans, ObjectGuid guid, bool isDisbandi player->SetInGuild(0); player->SetRank(0); } + else + sWorld->UpdateCharacterGuildId(guid, 0); _DeleteMemberFromDB(trans, lowguid); if (!isDisbanding) diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 4a855a204b8..c2c4b912eba 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -441,15 +441,16 @@ void WorldSession::HandleCalendarEventInvite(WorldPacket& recvData) } else { - // Invitee offline, get data from database - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME); - stmt->setString(0, name); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + // Invitee offline, get data from storage + ObjectGuid guid = sWorld->GetCharacterGuidByName(name); + if (!guid.IsEmpty()) { - Field* fields = result->Fetch(); - inviteeGuid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32()); - inviteeTeam = Player::TeamForRace(fields[1].GetUInt8()); - inviteeGuildId = Player::GetGuildIdFromDB(inviteeGuid); + if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid)) + { + inviteeGuid = guid; + inviteeTeam = Player::TeamForRace(characterInfo->Race); + inviteeGuildId = characterInfo->GuildId; + } } } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 0d6d750c73f..a4e78b5be77 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1120,6 +1120,7 @@ void WorldSession::HandleCharRenameCallback(std::shared_ptr<CharacterRenameInfo> SendCharRename(RESPONSE_SUCCESS, renameInfo.get()); sWorld->UpdateCharacterInfo(renameInfo->Guid, renameInfo->Name); + sWorld->UpdateCharacterGuidByName(renameInfo->Guid, oldName, renameInfo->Name); } void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData) @@ -1377,7 +1378,7 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomiz } // character with this name already exist - if (ObjectGuid newGuid = sObjectMgr->GetPlayerGUIDByName(customizeInfo->Name)) + if (ObjectGuid newGuid = sWorld->GetCharacterGuidByName(customizeInfo->Name)) { if (newGuid != customizeInfo->Guid) { @@ -1412,6 +1413,7 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomiz CharacterDatabase.CommitTransaction(trans); sWorld->UpdateCharacterInfo(customizeInfo->Guid, customizeInfo->Name, customizeInfo->Gender); + sWorld->UpdateCharacterGuidByName(customizeInfo->Guid, oldName, customizeInfo->Name); SendCharCustomize(RESPONSE_SUCCESS, customizeInfo.get()); @@ -1595,6 +1597,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact uint8 oldRace = characterInfo->Race; uint8 playerClass = characterInfo->Class; uint8 level = characterInfo->Level; + std::string oldName = characterInfo->Name; if (!sObjectMgr->GetPlayerInfo(factionChangeInfo->Race, playerClass)) { @@ -1659,7 +1662,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact } // character with this name already exist - ObjectGuid newGuid = sObjectMgr->GetPlayerGUIDByName(factionChangeInfo->Name); + ObjectGuid newGuid = sWorld->GetCharacterGuidByName(factionChangeInfo->Name); if (!newGuid.IsEmpty()) { if (newGuid != factionChangeInfo->Guid) @@ -1711,6 +1714,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact } sWorld->UpdateCharacterInfo(factionChangeInfo->Guid, factionChangeInfo->Name, factionChangeInfo->Gender, factionChangeInfo->Race); + sWorld->UpdateCharacterGuidByName(factionChangeInfo->Guid, oldName, factionChangeInfo->Name); if (oldRace != factionChangeInfo->Race) { @@ -1803,15 +1807,11 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact trans->Append(stmt); } - /// @todo: make this part async if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) { // Reset guild - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER); - stmt->setUInt32(0, lowGuid); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32())) - guild->DeleteMember(trans, factionChangeInfo->Guid, false, false, true); + if (Guild* guild = sGuildMgr->GetGuildById(characterInfo->GuildId)) + guild->DeleteMember(trans, factionChangeInfo->Guid, false, false, true); Player::LeaveAllArenaTeams(factionChangeInfo->Guid); } diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index cf716855175..05b39c4788a 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -607,7 +607,7 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData) else { CharacterDatabase.EscapeString(name); - guid = sObjectMgr->GetPlayerGUIDByName(name.c_str()); + guid = sWorld->GetCharacterGuidByName(name); } group->ChangeMembersGroup(guid, groupNr); diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 7bc0bfdc440..0941074663a 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -104,7 +104,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) ObjectGuid receiverGuid; if (normalizePlayerName(receiverName)) - receiverGuid = sObjectMgr->GetPlayerGUIDByName(receiverName); + receiverGuid = sWorld->GetCharacterGuidByName(receiverName); if (!receiverGuid) { @@ -160,7 +160,12 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) } else { - receiverTeam = sObjectMgr->GetPlayerTeamByGUID(receiverGuid); + if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(receiverGuid)) + { + receiverTeam = Player::TeamForRace(characterInfo->Race); + receiverLevel = characterInfo->Level; + receiverAccountId = characterInfo->AccountId; + } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT); stmt->setUInt32(0, receiverGuid.GetCounter()); @@ -171,18 +176,6 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) 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.. diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 055ad830f7b..076ac7c35ba 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -391,13 +391,7 @@ void WorldSession::SendSpiritResurrect() if (corpseGrave != ghostGrave) _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); - // or update at original position - else - _player->UpdateObjectVisibility(); } - // or update at original position - else - _player->UpdateObjectVisibility(); } void WorldSession::HandleBinderActivateOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/SocialHandler.cpp b/src/server/game/Handlers/SocialHandler.cpp index 2b13cfdbd9b..11e441527a8 100644 --- a/src/server/game/Handlers/SocialHandler.cpp +++ b/src/server/game/Handlers/SocialHandler.cpp @@ -40,50 +40,37 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "WorldSession::HandleAddFriendOpcode: %s asked to add friend: %s", GetPlayer()->GetName().c_str(), friendName.c_str()); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME); - stmt->setString(0, friendName); - - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) - .WithPreparedCallback(std::bind(&WorldSession::HandleAddFriendOpcodeCallback, this, std::move(friendNote), std::placeholders::_1))); -} - -void WorldSession::HandleAddFriendOpcodeCallback(std::string const& friendNote, PreparedQueryResult result) -{ - if (!GetPlayer()) - return; - - ObjectGuid friendGuid; FriendsResult friendResult = FRIEND_NOT_FOUND; - - if (result) + ObjectGuid friendGuid = sWorld->GetCharacterGuidByName(friendName); + if (!friendGuid.IsEmpty()) { - Field* fields = result->Fetch(); - - friendGuid = ObjectGuid(HighGuid::Player, 0, fields[0].GetUInt32()); - uint32 team = Player::TeamForRace(fields[1].GetUInt8()); - uint32 friendAccountId = fields[2].GetUInt32(); - - if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm))) + if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(friendGuid)) { - if (friendGuid) + uint32 team = Player::TeamForRace(characterInfo->Race); + uint32 friendAccountId = characterInfo->AccountId; + + if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm))) { - if (friendGuid == GetPlayer()->GetGUID()) - friendResult = FRIEND_SELF; - else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND)) - friendResult = FRIEND_ENEMY; - else if (GetPlayer()->GetSocial()->HasFriend(friendGuid)) - friendResult = FRIEND_ALREADY; - else + if (friendGuid) { - Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); - if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer())) - friendResult = FRIEND_ADDED_ONLINE; - else - friendResult = FRIEND_ADDED_OFFLINE; - if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, SOCIAL_FLAG_FRIEND)) - GetPlayer()->GetSocial()->SetFriendNote(friendGuid, friendNote); + if (friendGuid == GetPlayer()->GetGUID()) + friendResult = FRIEND_SELF; + else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND)) + friendResult = FRIEND_ENEMY; + else if (GetPlayer()->GetSocial()->HasFriend(friendGuid)) + friendResult = FRIEND_ALREADY; else - friendResult = FRIEND_LIST_FULL; + { + Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); + if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer())) + friendResult = FRIEND_ADDED_ONLINE; + else + friendResult = FRIEND_ADDED_OFFLINE; + if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, SOCIAL_FLAG_FRIEND)) + GetPlayer()->GetSocial()->SetFriendNote(friendGuid, friendNote); + else + friendResult = FRIEND_LIST_FULL; + } } } } @@ -114,40 +101,21 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "WorldSession::HandleAddIgnoreOpcode: %s asked to Ignore: %s", GetPlayer()->GetName().c_str(), ignoreName.c_str()); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - stmt->setString(0, ignoreName); - - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleAddIgnoreOpcodeCallback, this, std::placeholders::_1))); -} - -void WorldSession::HandleAddIgnoreOpcodeCallback(PreparedQueryResult result) -{ - if (!GetPlayer()) - return; - - ObjectGuid ignoreGuid; + ObjectGuid ignoreGuid = sWorld->GetCharacterGuidByName(ignoreName); FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; - - if (result) + if (!ignoreGuid.IsEmpty()) { - Field* fields = result->Fetch(); - - if (ObjectGuid::LowType lowGuid = fields[0].GetUInt32()) + if (ignoreGuid == GetPlayer()->GetGUID()) //not add yourself + ignoreResult = FRIEND_IGNORE_SELF; + else if (GetPlayer()->GetSocial()->HasIgnore(ignoreGuid)) + ignoreResult = FRIEND_IGNORE_ALREADY; + else { - ignoreGuid = ObjectGuid::Create<HighGuid::Player>(lowGuid); + ignoreResult = FRIEND_IGNORE_ADDED; - if (ignoreGuid == GetPlayer()->GetGUID()) //not add yourself - ignoreResult = FRIEND_IGNORE_SELF; - else if (GetPlayer()->GetSocial()->HasIgnore(ignoreGuid)) - ignoreResult = FRIEND_IGNORE_ALREADY; - else - { - ignoreResult = FRIEND_IGNORE_ADDED; - - // ignore list full - if (!GetPlayer()->GetSocial()->AddToSocialList(ignoreGuid, SOCIAL_FLAG_IGNORED)) - ignoreResult = FRIEND_IGNORE_FULL; - } + // ignore list full + if (!GetPlayer()->GetSocial()->AddToSocialList(ignoreGuid, SOCIAL_FLAG_IGNORED)) + ignoreResult = FRIEND_IGNORE_FULL; } } diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 554aee1dc37..32ace07d9ec 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -31,6 +31,7 @@ #include "SpellAuraEffects.h" #include "Player.h" #include "Config.h" +#include "QueryCallback.h" void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets) { @@ -169,38 +170,44 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); - Player* pUser = _player; + Player* player = GetPlayer(); // ignore for remote control state - if (pUser->m_unitMovedByMe != pUser) + if (player->m_unitMovedByMe != player) return; - uint8 bagIndex, slot; + // additional check, client outputs message on its own + if (!player->IsAlive()) + { + player->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, nullptr, nullptr); + return; + } + uint8 bagIndex, slot; recvPacket >> bagIndex >> slot; TC_LOG_INFO("network", "bagIndex: %u, slot: %u", bagIndex, slot); - Item* item = pUser->GetItemByPos(bagIndex, slot); + Item* item = player->GetItemByPos(bagIndex, slot); if (!item) { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, nullptr, nullptr); return; } ItemTemplate const* proto = item->GetTemplate(); if (!proto) { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL); + player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, nullptr); return; } // Verify that the bag is an actual bag or wrapped item that can be used "normally" if (!(proto->Flags & ITEM_FLAG_HAS_LOOT) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { - pUser->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL); + player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL); TC_LOG_ERROR("entities.player.cheat", "Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!", - pUser->GetName().c_str(), pUser->GetGUID().GetCounter(), item->GetGUID().GetCounter(), proto->ItemId); + player->GetName().c_str(), player->GetGUID().GetCounter(), item->GetGUID().GetCounter(), proto->ItemId); return; } @@ -212,7 +219,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) if (!lockInfo) { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL); + player->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, nullptr); TC_LOG_ERROR("network", "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", item->GetGUID().GetCounter(), lockId); return; } @@ -220,7 +227,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) // was not unlocked yet if (item->IsLocked()) { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL); + player->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, nullptr); return; } } @@ -228,37 +235,51 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))// wrapped? { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM); - stmt->setUInt32(0, item->GetGUID().GetCounter()); + _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) + .WithPreparedCallback(std::bind(&WorldSession::HandleOpenWrappedItemCallback, this, item->GetPos(), item->GetGUID(), std::placeholders::_1))); + } + else + player->SendLoot(item->GetGUID(), LOOT_CORPSE); +} - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - uint32 entry = fields[0].GetUInt32(); - uint32 flags = fields[1].GetUInt32(); - - item->SetGuidValue(ITEM_FIELD_GIFTCREATOR, ObjectGuid::Empty); - item->SetEntry(entry); - item->SetUInt32Value(ITEM_FIELD_FLAGS, flags); - item->SetState(ITEM_CHANGED, pUser); - } - else - { - TC_LOG_ERROR("network", "Wrapped item %u don't have record in character_gifts table and will deleted", item->GetGUID().GetCounter()); - pUser->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); - return; - } +void WorldSession::HandleOpenWrappedItemCallback(uint16 pos, ObjectGuid itemGuid, PreparedQueryResult result) +{ + if (!GetPlayer()) + return; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT); + Item* item = GetPlayer()->GetItemByPos(pos); + if (!item) + return; - stmt->setUInt32(0, item->GetGUID().GetCounter()); + if (item->GetGUID() != itemGuid || !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) // during getting result, gift was swapped with another item + return; - CharacterDatabase.Execute(stmt); + if (!result) + { + TC_LOG_ERROR("network", "Wrapped item %u don't have record in character_gifts table and will deleted", itemGuid.GetCounter()); + GetPlayer()->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + return; } - else - pUser->SendLoot(item->GetGUID(), LOOT_CORPSE); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + Field* fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + uint32 flags = fields[1].GetUInt32(); + + item->SetGuidValue(ITEM_FIELD_GIFTCREATOR, ObjectGuid::Empty); + item->SetEntry(entry); + item->SetUInt32Value(ITEM_FIELD_FLAGS, flags); + item->SetState(ITEM_CHANGED, GetPlayer()); + + GetPlayer()->SaveInventoryAndGoldToDB(trans); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT); + stmt->setUInt32(0, itemGuid.GetCounter()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); } void WorldSession::HandleGameObjectUseOpcode(WorldPacket& recvData) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index b52d9377e1a..27d784a8110 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -886,10 +886,15 @@ void Map::RemovePlayerFromMap(Player* player, bool remove) { sScriptMgr->OnPlayerLeaveMap(this, player); + player->getHostileRefManager().deleteReferences(); // multithreading crashfix + + bool const inWorld = player->IsInWorld(); player->RemoveFromWorld(); SendRemoveTransports(player); - player->UpdateObjectVisibility(true); + if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers() + player->DestroyForNearbyPlayers(); // previous player->UpdateObjectVisibility(true) + if (player->IsInGrid()) player->RemoveFromGrid(); else @@ -902,11 +907,15 @@ void Map::RemovePlayerFromMap(Player* player, bool remove) template<class T> void Map::RemoveFromMap(T *obj, bool remove) { + bool const inWorld = obj->IsInWorld() && obj->GetTypeId() >= TYPEID_UNIT && obj->GetTypeId() <= TYPEID_GAMEOBJECT; obj->RemoveFromWorld(); + if (obj->isActiveObject()) RemoveFromActive(obj); - obj->UpdateObjectVisibility(true); + if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers() + obj->DestroyForNearbyPlayers(); // previous obj->UpdateObjectVisibility(true) + obj->RemoveFromGrid(); obj->ResetMap(); diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 194266c499c..f38d3c37b12 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -28,6 +28,7 @@ Quest::Quest(Field* questRecord) _reqCreatureOrGOcount = 0; _rewItemsCount = 0; _rewChoiceItemsCount = 0; + _eventIdForQuest = 0; Id = questRecord[0].GetUInt32(); Method = questRecord[1].GetUInt8(); diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 300603e7e39..13b959c2100 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -304,6 +304,9 @@ class TC_GAME_API Quest uint32 GetRewChoiceItemsCount() const { return _rewChoiceItemsCount; } uint32 GetRewItemsCount() const { return _rewItemsCount; } + void SetEventIdForQuest(uint16 eventId) { _eventIdForQuest = eventId; } + uint16 GetEventIdForQuest() const { return _eventIdForQuest; } + typedef std::vector<int32> PrevQuests; PrevQuests prevQuests; typedef std::vector<uint32> PrevChainQuests; @@ -315,6 +318,7 @@ class TC_GAME_API Quest uint32 _reqCreatureOrGOcount; uint32 _rewChoiceItemsCount; uint32 _rewItemsCount; + uint16 _eventIdForQuest; // table data protected: diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 4664d2efb8f..c716b0bdd3b 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -121,7 +121,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS m_sessionDbLocaleIndex(locale), m_latency(0), m_clientTimeDelay(0), - m_TutorialsChanged(false), + m_TutorialsChanged(TUTORIALS_FLAG_NONE), recruiterId(recruiter), isRecruiter(isARecruiter), _RBACData(NULL), @@ -751,10 +751,13 @@ void WorldSession::LoadTutorialsData(PreparedQueryResult result) memset(m_Tutorials, 0, sizeof(uint32) * MAX_ACCOUNT_TUTORIAL_VALUES); if (result) + { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) m_Tutorials[i] = (*result)[i].GetUInt32(); + m_TutorialsChanged |= TUTORIALS_FLAG_LOADED_FROM_DB; + } - m_TutorialsChanged = false; + m_TutorialsChanged &= ~TUTORIALS_FLAG_CHANGED; } void WorldSession::SendTutorialsData() @@ -767,20 +770,17 @@ void WorldSession::SendTutorialsData() void WorldSession::SaveTutorialsData(SQLTransaction &trans) { - if (!m_TutorialsChanged) + if (!(m_TutorialsChanged & TUTORIALS_FLAG_CHANGED)) return; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_HAS_TUTORIALS); - stmt->setUInt32(0, GetAccountId()); - bool hasTutorials = bool(CharacterDatabase.Query(stmt)); - // Modify data in DB - stmt = CharacterDatabase.GetPreparedStatement(hasTutorials ? CHAR_UPD_TUTORIALS : CHAR_INS_TUTORIALS); + bool const hasTutorialsInDB = (m_TutorialsChanged & TUTORIALS_FLAG_LOADED_FROM_DB) != 0; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(hasTutorialsInDB ? CHAR_UPD_TUTORIALS : CHAR_INS_TUTORIALS); for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) stmt->setUInt32(i, m_Tutorials[i]); stmt->setUInt32(MAX_ACCOUNT_TUTORIAL_VALUES, GetAccountId()); trans->Append(stmt); - m_TutorialsChanged = false; + m_TutorialsChanged &= ~TUTORIALS_FLAG_CHANGED; } void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi) diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index a95aa75cccf..1e66e832a04 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -144,6 +144,13 @@ enum DeclinedNameResult DECLINED_NAMES_RESULT_ERROR = 1 }; +enum TutorialsFlag : uint8 +{ + TUTORIALS_FLAG_NONE = 0x00, + TUTORIALS_FLAG_CHANGED = 0x01, + TUTORIALS_FLAG_LOADED_FROM_DB = 0x02 +}; + //class to deal with packet processing //allows to determine if next packet is safe to be processed class PacketFilter @@ -376,7 +383,7 @@ class TC_GAME_API WorldSession if (m_Tutorials[index] != value) { m_Tutorials[index] = value; - m_TutorialsChanged = true; + m_TutorialsChanged |= TUTORIALS_FLAG_CHANGED; } } //used with item_page table @@ -536,10 +543,8 @@ class TC_GAME_API WorldSession // Social void HandleContactListOpcode(WorldPacket& recvPacket); void HandleAddFriendOpcode(WorldPacket& recvPacket); - void HandleAddFriendOpcodeCallback(std::string const& friendNote, PreparedQueryResult result); void HandleDelFriendOpcode(WorldPacket& recvPacket); void HandleAddIgnoreOpcode(WorldPacket& recvPacket); - void HandleAddIgnoreOpcodeCallback(PreparedQueryResult result); void HandleDelIgnoreOpcode(WorldPacket& recvPacket); void HandleSetContactNotesOpcode(WorldPacket& recvPacket); void HandleBugOpcode(WorldPacket& recvPacket); @@ -725,6 +730,7 @@ class TC_GAME_API WorldSession void HandleUseItemOpcode(WorldPacket& recvPacket); void HandleOpenItemOpcode(WorldPacket& recvPacket); + void HandleOpenWrappedItemCallback(uint16 pos, ObjectGuid itemGuid, PreparedQueryResult result); void HandleCastSpellOpcode(WorldPacket& recvPacket); void HandleCancelCastOpcode(WorldPacket& recvPacket); void HandleCancelAuraOpcode(WorldPacket& recvPacket); @@ -970,6 +976,9 @@ class TC_GAME_API WorldSession void HandleUpdateProjectilePosition(WorldPacket& recvPacket); void HandleUpdateMissileTrajectory(WorldPacket& recvPacket); + public: + QueryCallbackProcessor& GetQueryProcessor() { return _queryProcessor; } + private: void ProcessQueryCallbacks(); @@ -1056,7 +1065,7 @@ class TC_GAME_API WorldSession std::atomic<uint32> m_clientTimeDelay; AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES]; - bool m_TutorialsChanged; + uint8 m_TutorialsChanged; AddonsList m_addonsList; uint32 recruiterId; bool isRecruiter; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 363e0284632..f4fcb36f995 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1472,6 +1472,10 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading instances..."); sInstanceSaveMgr->LoadInstances(); + // Load before guilds and arena teams + TC_LOG_INFO("server.loading", "Loading character info store..."); + LoadCharacterInfoStore(); + TC_LOG_INFO("server.loading", "Loading Broadcast texts..."); sObjectMgr->LoadBroadcastTexts(); sObjectMgr->LoadBroadcastTextLocales(); @@ -1954,8 +1958,6 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time..."); InitGuildResetTime(); - LoadCharacterInfoStore(); - // Preload all cells, if required for the base maps if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS)) { @@ -2615,25 +2617,22 @@ bool World::RemoveBanAccount(BanMode mode, std::string const& nameOrIP) /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban BanReturn World::BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author) { - Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name); + Player* banned = ObjectAccessor::FindConnectedPlayerByName(name); ObjectGuid::LowType guid = 0; uint32 duration_secs = TimeStringToSecs(duration); /// Pick a player to ban if not online - if (!pBanned) + if (!banned) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - stmt->setString(0, name); - PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt); - - if (!resultCharacter) + ObjectGuid fullGuid = sWorld->GetCharacterGuidByName(name); + if (fullGuid.IsEmpty()) return BAN_NOTFOUND; // Nobody to ban - guid = (*resultCharacter)[0].GetUInt32(); + guid = fullGuid.GetCounter(); } else - guid = pBanned->GetGUID().GetCounter(); + guid = banned->GetGUID().GetCounter(); // make sure there is only one active ban PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN); @@ -2647,8 +2646,8 @@ BanReturn World::BanCharacter(std::string const& name, std::string const& durati stmt->setString(3, reason); CharacterDatabase.Execute(stmt); - if (pBanned) - pBanned->GetSession()->KickPlayer(); + if (banned) + banned->GetSession()->KickPlayer(); return BAN_SUCCESS; } @@ -2656,23 +2655,20 @@ BanReturn World::BanCharacter(std::string const& name, std::string const& durati /// Remove a ban from a character bool World::RemoveBanCharacter(std::string const& name) { - Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name); + Player* banned = ObjectAccessor::FindConnectedPlayerByName(name); ObjectGuid::LowType guid = 0; /// Pick a player to ban if not online - if (!pBanned) + if (!banned) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - stmt->setString(0, name); - PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt); - - if (!resultCharacter) + ObjectGuid fullGuid = sWorld->GetCharacterGuidByName(name); + if (fullGuid.IsEmpty()) return false; - guid = (*resultCharacter)[0].GetUInt32(); + guid = fullGuid.GetCounter(); } else - guid = pBanned->GetGUID().GetCounter(); + guid = banned->GetGUID().GetCounter(); if (!guid) return false; @@ -3284,6 +3280,15 @@ CharacterInfo const* World::GetCharacterInfo(ObjectGuid const& guid) const return nullptr; } +ObjectGuid World::GetCharacterGuidByName(std::string const& name) const +{ + auto itr = _characterGuidByNameStore.find(name); + if (itr != _characterGuidByNameStore.end()) + return itr->second; + + return ObjectGuid::Empty; +} + /** * @brief Loads several pieces of information on server startup with the GUID * There is no further database query necessary. @@ -3307,8 +3312,6 @@ CharacterInfo const* World::GetCharacterInfo(ObjectGuid const& guid) const void World::LoadCharacterInfoStore() { - TC_LOG_INFO("server.loading", "Loading character info store"); - _characterInfoStore.clear(); QueryResult result = CharacterDatabase.Query("SELECT guid, name, account, race, gender, class, level FROM characters"); @@ -3337,6 +3340,15 @@ void World::AddCharacterInfo(ObjectGuid const& guid, uint32 accountId, std::stri data.Sex = gender; data.Class = playerClass; data.Level = level; + data.GuildId = 0; // Will be set in guild loading or guild setting + for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i) + data.ArenaTeamId[i] = 0; // Will be set in arena teams loading +} + +void World::DeleteCharacterInfo(ObjectGuid const& guid, std::string const& name) +{ + _characterInfoStore.erase(guid); + _characterGuidByNameStore.erase(name); } void World::UpdateCharacterInfo(ObjectGuid const& guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/) @@ -3376,6 +3388,30 @@ void World::UpdateCharacterInfoAccount(ObjectGuid const& guid, uint32 accountId) itr->second.AccountId = accountId; } +void World::UpdateCharacterGuildId(ObjectGuid const& guid, ObjectGuid::LowType guildId) +{ + auto itr = _characterInfoStore.find(guid); + if (itr == _characterInfoStore.end()) + return; + + itr->second.GuildId = guildId; +} + +void World::UpdateCharacterArenaTeamId(ObjectGuid const& guid, uint8 slot, uint32 arenaTeamId) +{ + auto itr = _characterInfoStore.find(guid); + if (itr == _characterInfoStore.end()) + return; + + itr->second.ArenaTeamId[slot] = arenaTeamId; +} + +void World::UpdateCharacterGuidByName(ObjectGuid const& guid, std::string const& oldName, std::string const& newName) +{ + _characterGuidByNameStore.erase(oldName); + _characterGuidByNameStore[newName] = guid; +} + void World::ReloadRBAC() { // Passive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 87f5c9415b8..30e1283bc16 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -549,6 +549,8 @@ struct CharacterInfo uint8 Race; uint8 Sex; uint8 Level; + ObjectGuid::LowType GuildId; + uint32 ArenaTeamId[3]; }; /// The World @@ -765,12 +767,16 @@ class TC_GAME_API World void UpdateAreaDependentAuras(); CharacterInfo const* GetCharacterInfo(ObjectGuid const& guid) const; + ObjectGuid GetCharacterGuidByName(std::string const& name) const; void AddCharacterInfo(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level); - void DeleteCharacterInfo(ObjectGuid const& guid) { _characterInfoStore.erase(guid); } + void DeleteCharacterInfo(ObjectGuid const& guid, std::string const& name); bool HasCharacterInfo(ObjectGuid const& guid) { return _characterInfoStore.find(guid) != _characterInfoStore.end(); } void UpdateCharacterInfo(ObjectGuid const& guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE); void UpdateCharacterInfoLevel(ObjectGuid const& guid, uint8 level); void UpdateCharacterInfoAccount(ObjectGuid const& guid, uint32 accountId); + void UpdateCharacterGuildId(ObjectGuid const& guid, ObjectGuid::LowType guildId); + void UpdateCharacterArenaTeamId(ObjectGuid const& guid, uint8 slot, uint32 arenaTeamId); + void UpdateCharacterGuidByName(ObjectGuid const& guid, std::string const& oldName, std::string const& newName); uint32 GetCleaningFlags() const { return m_CleaningFlags; } void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; } @@ -877,8 +883,10 @@ class TC_GAME_API World typedef std::map<uint8, uint8> AutobroadcastsWeightMap; AutobroadcastsWeightMap m_AutobroadcastsWeights; + typedef std::unordered_map<std::string, ObjectGuid> CharacterGuidByNameContainer; typedef std::unordered_map<ObjectGuid, CharacterInfo> CharacterInfoContainer; CharacterInfoContainer _characterInfoStore; + CharacterGuidByNameContainer _characterGuidByNameStore; void LoadCharacterInfoStore(); void ProcessQueryCallbacks(); diff --git a/src/server/scripts/Commands/cs_arena.cpp b/src/server/scripts/Commands/cs_arena.cpp index d284c9acebc..9419d5eb9ea 100644 --- a/src/server/scripts/Commands/cs_arena.cpp +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -83,7 +83,7 @@ public: if (type == 2 || type == 3 || type == 5 ) { - if (Player::GetArenaTeamIdFromDB(target->GetGUID(), type) != 0) + if (Player::GetArenaTeamIdFromCharacterInfo(target->GetGUID(), type) != 0) { handler->PSendSysMessage(LANG_ARENA_ERROR_SIZE, target->GetName().c_str()); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index 606e5a05b2c..c9373d7237c 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -300,17 +300,14 @@ public: if (!target) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - stmt->setString(0, name); - PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt); - - if (!resultCharacter) + ObjectGuid fullGuid = sWorld->GetCharacterGuidByName(name); + if (fullGuid.IsEmpty()) { handler->PSendSysMessage(LANG_BANINFO_NOCHARACTER); return false; } - targetGuid = (*resultCharacter)[0].GetUInt32(); + targetGuid = fullGuid.GetCounter(); } else targetGuid = target->GetGUID().GetCounter(); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index d6b06882810..ebd28a1ac06 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -208,7 +208,7 @@ public: return; } - if (sObjectMgr->GetPlayerGUIDByName(delInfo.name)) + if (sWorld->GetCharacterGuidByName(delInfo.name)) { handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.guid.GetCounter(), delInfo.accountId); return; @@ -384,6 +384,7 @@ public: } sWorld->UpdateCharacterInfo(targetGuid, newName); + sWorld->UpdateCharacterGuidByName(targetGuid, playerOldName, newName); handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, playerOldName.c_str(), newName.c_str()); @@ -446,7 +447,7 @@ public: if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName)) return false; - int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(targetGuid); + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromCharacterInfo(targetGuid); int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; if (newlevel < 1) @@ -862,8 +863,8 @@ public: } else { - characterGuid = sObjectMgr->GetPlayerGUIDByName(characterName); - if (!characterGuid) + characterGuid = sWorld->GetCharacterGuidByName(characterName); + if (characterGuid.IsEmpty()) { handler->PSendSysMessage(LANG_NO_PLAYER, characterName.c_str()); handler->SetSentErrorMessage(true); @@ -900,7 +901,7 @@ public: if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName)) return false; - int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(targetGuid); + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromCharacterInfo(targetGuid); int32 addlevel = levelStr ? atoi(levelStr) : 1; int32 newlevel = oldlevel + addlevel; @@ -1057,7 +1058,7 @@ public: return false; } - guid = sObjectMgr->GetPlayerGUIDByName(name); + guid = sWorld->GetCharacterGuidByName(name); } if (!sObjectMgr->GetPlayerAccountIdByGUID(guid)) diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp index 22696f86d63..8ee2b6c4634 100644 --- a/src/server/scripts/Commands/cs_guild.cpp +++ b/src/server/scripts/Commands/cs_guild.cpp @@ -157,7 +157,7 @@ public: if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid)) return false; - ObjectGuid::LowType guildId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(targetGuid); + ObjectGuid::LowType guildId = target ? target->GetGuildId() : Player::GetGuildIdFromCharacterInfo(targetGuid); if (!guildId) return false; @@ -184,7 +184,7 @@ public: if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &target_name)) return false; - ObjectGuid::LowType guildId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(targetGuid); + ObjectGuid::LowType guildId = target ? target->GetGuildId() : Player::GetGuildIdFromCharacterInfo(targetGuid); if (!guildId) return false; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 9c5e30c340e..bcd919d5899 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2550,22 +2550,16 @@ public: if (targetName) { // Check for offline players - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_GUID_BY_NAME); - stmt->setString(0, name); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + ObjectGuid guid = sWorld->GetCharacterGuidByName(name); + if (guid.IsEmpty()) { handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG); return true; } // If player found: delete his freeze aura - Field* fields = result->Fetch(); - ObjectGuid::LowType lowGuid = fields[0].GetUInt32(); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_FROZEN); - stmt->setUInt32(0, lowGuid); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_FROZEN); + stmt->setUInt32(0, guid.GetCounter()); CharacterDatabase.Execute(stmt); handler->PSendSysMessage(LANG_COMMAND_UNFREEZE, name.c_str()); diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index a4fc86f8048..8aaed4f2ad1 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -92,7 +92,7 @@ public: return true; } - ObjectGuid targetGuid = sObjectMgr->GetPlayerGUIDByName(target); + ObjectGuid targetGuid = sWorld->GetCharacterGuidByName(target); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); // Target must exist and have administrative rights if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realm.Id.Realm)) @@ -452,10 +452,10 @@ public: if (Player* player = ObjectAccessor::FindPlayerByName(name)) guid = player->GetGUID(); else - guid = sObjectMgr->GetPlayerGUIDByName(name); + guid = sWorld->GetCharacterGuidByName(name); // Target must exist - if (!guid) + if (guid.IsEmpty()) { handler->SendSysMessage(LANG_NO_PLAYERS_FOUND); return true; diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 2085320eca5..1dc5fee6a12 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -442,10 +442,23 @@ class TC_SHARED_API ByteBuffer ASSERT(size() < 10000000); - if (_storage.size() < _wpos + cnt) - _storage.resize(_wpos + cnt); + size_t const newSize = _wpos + cnt; + if (_storage.capacity() < newSize) // custom memory allocation rules + { + if (newSize < 100) + _storage.reserve(300); + else if (newSize < 750) + _storage.reserve(2500); + else if (newSize < 6000) + _storage.reserve(10000); + else + _storage.reserve(400000); + } + + if (_storage.size() < newSize) + _storage.resize(newSize); std::memcpy(&_storage[_wpos], src, cnt); - _wpos += cnt; + _wpos = newSize; } void append(const ByteBuffer& buffer) |