diff options
author | xinef1 <w.szyszko2@gmail.com> | 2017-01-28 05:00:28 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2019-07-21 21:06:54 +0200 |
commit | b485f3e6733950920cc1b9afe2a81a30eeeeaa95 (patch) | |
tree | d1a4171eb3a5d9f3b4f8a6a011addeb32a2f76eb | |
parent | e6885d50c688437ea21855eb0161373de02bcf9f (diff) |
Few small optimizations here and there (#18684)
Changes list:
- Added CharacterGuidByNameContainer which contains name -> guid unordered map (updated along CharacterInfo)
- Extended CharacterInfo structure with GuildId
- Extended CharacterInfo structure with ArenaTeamId[3], for all possible teams (2v2, 3v3, 5v5)
- Removed CHAR_SEL_GUID_BY_NAME and CHAR_SEL_CHAR_GUID_BY_NAME synchronous queries, name -> guid can be now retrieved in World::GetCharacterGuidByName
- Removed CHAR_SEL_GUID_RACE_ACC_BY_NAME synchronous query, guid can be retrieved by name and rest of the data can be retrieved by guid
- Removed CHAR_SEL_CHAR_LEVEL synchronous query, level can be retrieved by guid
- Changed CHAR_SEL_CHARACTER_ACTIONS_SPEC to asynchronous query, action bars are now loaded asynchronously
- Removed CHAR_SEL_CHARACTER_NAME_CLASS synchronous query, guid can be retrieved by name and rest of the data can be retrieved by guid
- Removed CHAR_SEL_PLAYER_ARENA_TEAMS and CHAR_SEL_ARENA_TEAM_ID_BY_PLAYER_GUID synchronous queries, arena teams are now stored in CharacterInfo
- Replaced synchronous db calls with CharacterInfo lookups
- Removed ObjectMgr::GetPlayerGUIDByName, as it used db query
- Replaced some unnecessary UpdateObjectVisibility() calls because they were either duplicated (called few lines above in other function) or it is enough to call DestroyForNearbyPlayers because object is being removed or should be invisible and DestroyForNearbyPlayers is faster
- Corrected typo in Player::DestroyForPlayer, only items in slots 0 to EQUIPMENT_SLOT_END are sent to other players
- Renamed Player::GetGuildIdFromDB to Player::GetGuildIdFromCharacterInfo and changed the function to use CharacterInfo structure
- Renamed Player::GetArenaTeamIdFromDB to Player::GetArenaTeamIdFromCharacterInfo and changed the function to use CharacterInfo structure
- Renamed Player::GetLevelFromDB to Player::GetLevelFromCharacterInfo and changed the function to use CharacterInfo structure
- Removed GameEventMgr::_questToEventLinks and associated functions, eventId is now stored in Quest class under _eventIdForQuest variable
- Changed some functions checking quest status to use other functions for quest status check instead of duplicating code
- Removed callback from add friend, because we can get the guid from appropriate storage, no need to make db query
- Removed callback from add ignore, because we can get the guid from appropriate storage, no need to make db query
- Added callback to unwrap wrapped items asynchronously
- Removed synchronous select in tutorials to check if we have any entries in db, if any entry exists in db, m_TutorialsChanged variable will have TUTORIALS_FLAG_LOADED_FROM_DB flag added and it is no longer necessary to query database
(cherrypicked from b955456008191e60b6bda1f22e3486a3792b08db)
33 files changed, 299 insertions, 298 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 11604c63616..2b32f9f0a60 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -34,7 +34,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); @@ -69,8 +68,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.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT name, at_login FROM characters WHERE guid = ? 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_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH); @@ -146,7 +143,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 " SelectItemInstanceContent ", ii.owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE mail_id = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT " SelectItemInstanceContent " FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_AUCTIONS, "SELECT id, auctioneerguid, 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); @@ -194,7 +191,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER, "DELETE im FROM item_instance_modifiers im LEFT JOIN item_instance ii ON im.itemGuid = ii.guid WHERE ii.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); @@ -361,7 +358,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 @@ -507,7 +503,6 @@ 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_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); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index e98697227a5..306f545540a 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -32,7 +32,6 @@ enum CharacterDatabaseStatements : uint32 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, @@ -52,8 +51,6 @@ enum CharacterDatabaseStatements : uint32 CHAR_SEL_UNDELETE_ENUM, CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, CHAR_SEL_FREE_NAME, - CHAR_SEL_GUID_RACE_ACC_BY_NAME, - CHAR_SEL_CHAR_LEVEL, CHAR_SEL_CHAR_ZONE, CHAR_SEL_CHAR_POSITION_XYZ, CHAR_SEL_CHAR_POSITION, @@ -280,7 +277,6 @@ enum CharacterDatabaseStatements : uint32 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, @@ -413,7 +409,6 @@ enum CharacterDatabaseStatements : uint32 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_DEL_CHAR_AURA_FROZEN, CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index e1e9f928f6e..61661093479 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -114,7 +114,7 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid) return false; // 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; @@ -157,6 +157,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); @@ -252,6 +253,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()); @@ -311,11 +313,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; } + } // 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 2502ed30c3b..c699c2e075c 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -78,7 +78,7 @@ void CalendarMgr::LoadFromDB() ObjectGuid::LowType guildID = UI64LIT(0); if (flags & CALENDAR_FLAG_GUILD_EVENT || flags & CALENDAR_FLAG_WITHOUT_INVITES) - guildID = Player::GetGuildIdFromDB(ownerGUID); + guildID = Player::GetGuildIdFromCharacterInfo(ownerGUID); CalendarEvent* calendarEvent = new CalendarEvent(eventID, ownerGUID, guildID, type, textureID, time_t(date), flags, title, description, time_t(lockDate)); _events.insert(calendarEvent); @@ -433,7 +433,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); WorldPackets::Calendar::SCalendarEventInvite packet; packet.EventID = calendarEvent ? calendarEvent->GetEventId() : 0; @@ -572,8 +572,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); WorldPackets::Calendar::CalendarEventInviteInfo inviteInfo; inviteInfo.Guid = inviteeGuid; diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index a48d1536766..ead2eb05498 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -937,7 +937,7 @@ ObjectGuid::LowType ChatHandler::extractLowGuidFromLink(char* text, HighGuid& gu if (Player* player = ObjectAccessor::FindPlayerByName(name)) return player->GetGUID().GetCounter(); - ObjectGuid guid = ObjectMgr::GetPlayerGUIDByName(name); + ObjectGuid guid = sWorld->GetCharacterGuidByName(name); if (guid.IsEmpty()) return 0; @@ -994,7 +994,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) ? ObjectMgr::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) @@ -1153,7 +1153,7 @@ bool ChatHandler::GetPlayerGroupAndGUIDByName(const char* cname, Player*& player player = ObjectAccessor::FindPlayerByName(name); if (offline) - guid = ObjectMgr::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 7c4361bf39a..e8a5eafe527 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -274,7 +274,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 4f0294aafe5..a2e58bccdd2 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -817,7 +817,7 @@ void GameObject::Update(uint32 diff) if (!m_spawnedByDefault) { m_respawnTime = 0; - UpdateObjectVisibility(); + DestroyForNearbyPlayers(); // old UpdateObjectVisibility() return; } @@ -827,7 +827,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 476e2553966..ba5035e74ca 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -88,6 +88,7 @@ #include "Pet.h" #include "PetPackets.h" #include "PhasingHandler.h" +#include "QueryCallback.h" #include "QueryHolder.h" #include "QuestDef.h" #include "QuestObjectiveCriteriaMgr.h" @@ -3704,7 +3705,7 @@ void Player::DestroyForPlayer(Player* target) const { Unit::DestroyForPlayer(target); - 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; @@ -3788,10 +3789,14 @@ 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 charDeleteMethod = sWorld->getIntConfig(CONFIG_CHARDELETE_METHOD); + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(playerguid); + std::string name; + if (characterInfo) + name = characterInfo->Name; if (deleteFinally) charDeleteMethod = CHAR_DELETE_REMOVE; - else if (CharacterInfo const* characterInfo = 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 charDeleteMinLvl; @@ -3810,7 +3815,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe } 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); @@ -4159,7 +4164,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe Garrison::DeleteFromDB(guid, trans); - sWorld->DeleteCharacterInfo(playerguid); + sWorld->DeleteCharacterInfo(playerguid, name); break; } // The character gets unlinked from the account, the name gets freed up and appears as deleted ingame @@ -6934,26 +6939,17 @@ void Player::SetInGuild(ObjectGuid::LowType guildId) SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::GuildGUID), ObjectGuid::Empty); RemovePlayerFlag(PLAYER_FLAGS_GUILD_LEVEL_ENABLED); } -} - -ObjectGuid::LowType Player::GetGuildIdFromDB(ObjectGuid guid) -{ - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER); - stmt->setUInt64(0, guid.GetCounter()); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - return result->Fetch()[0].GetUInt64(); - return UI64LIT(0); + sWorld->UpdateCharacterGuildId(GetGUID(), guildId); } -uint8 Player::GetRankFromDB(ObjectGuid guid) +ObjectGuid::LowType Player::GetGuildIdFromCharacterInfo(ObjectGuid guid) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER); - stmt->setUInt64(0, guid.GetCounter()); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - return result->Fetch()[1].GetUInt8(); + CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); + if (!characterInfo) + return UI64LIT(0); - return 0; + return characterInfo->GuildId; } void Player::SetArenaTeamInfoField(uint8 /*slot*/, ArenaTeamInfoType /*type*/, uint32 /*value*/) @@ -6966,18 +6962,13 @@ void Player::SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type) SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, type); } -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->setUInt64(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) @@ -7026,19 +7017,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->setUInt64(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) @@ -16028,17 +16013,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*/) @@ -16125,14 +16110,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 @@ -16155,14 +16133,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; } } @@ -22025,17 +21998,13 @@ void Player::RemovePetitionsAndSigns(ObjectGuid guid) void Player::LeaveAllArenaTeams(ObjectGuid guid) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_ARENA_TEAMS); - stmt->setUInt64(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); @@ -22043,7 +22012,6 @@ void Player::LeaveAllArenaTeams(ObjectGuid guid) arenaTeam->DelMember(guid, true); } } - while (result->NextRow()); } bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc /*= nullptr*/, uint32 spellid /*= 0*/, uint32 preferredMountDisplay /*= 0*/) @@ -24222,7 +24190,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; } @@ -26997,15 +26965,22 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec) InitTalentForLevel(); + // load them asynchronously { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC); stmt->setUInt64(0, GetGUID().GetCounter()); stmt->setUInt8(1, GetActiveTalentGroup()); - 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); + })); + } UpdateDisplayPower(); Powers pw = GetPowerType(); @@ -27041,6 +27016,14 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec) } } +void Player::LoadActions(PreparedQueryResult result) +{ + if (result) + _LoadActions(result); + + SendActionButtons(1); +} + void Player::ResetTimeSync() { m_timeSyncTimer = 0; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index b23ed7f7fae..a482ad4c5c1 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1336,7 +1336,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; @@ -1437,7 +1437,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; } @@ -1610,6 +1610,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> std::vector<uint32> const& GetGlyphs(uint8 spec) const { return _specializationInfo.Glyphs[spec]; } std::vector<uint32>& GetGlyphs(uint8 spec) { return _specializationInfo.Glyphs[spec]; } ActionButtonList const& GetActionButtons() const { return m_actionButtons; } + void LoadActions(PreparedQueryResult result); uint32 GetFreePrimaryProfessionPoints() const { return m_activePlayerData->CharacterPoints; } void SetFreePrimaryProfessions(uint16 profs) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CharacterPoints), profs); } @@ -1703,15 +1704,14 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> ObjectGuid::LowType GetGuildId() const { return m_unitData->GuildGUID->GetCounter(); /* return only lower part */ } Guild* GetGuild(); Guild const* GetGuild() const; - static ObjectGuid::LowType GetGuildIdFromDB(ObjectGuid guid); - static uint8 GetRankFromDB(ObjectGuid guid); + static ObjectGuid::LowType GetGuildIdFromCharacterInfo(ObjectGuid guid); ObjectGuid::LowType GetGuildIdInvited() const { return m_GuildIdInvited; } static void RemovePetitionsAndSigns(ObjectGuid guid); // 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 0; } uint32 GetArenaPersonalRating(uint8 slot) const { return m_activePlayerData->PvpInfo[slot].Rating; } diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 2f3102f5e65..3969caedba3 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -767,7 +767,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; @@ -779,7 +780,7 @@ void GameEventMgr::LoadFromDB() continue; } - _questToEventLinks[questId] = eventEntry; + questTemplate->SetEventIdForQuest(static_cast<uint16>(eventEntry)); ++count; } while (result->NextRow()); @@ -1682,18 +1683,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 2786485c1a1..d83f7edb5bd 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -118,7 +118,6 @@ class TC_GAME_API GameEventMgr void HandleWorldEventGossip(Player* player, Creature* c); uint64 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); } @@ -170,7 +169,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 fc12ac76f7f..3e8d5a1f02f 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2541,18 +2541,6 @@ void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectDat } } -// name must be checked to correctness (if received) before call this function -ObjectGuid ObjectMgr::GetPlayerGUIDByName(std::string const& name) -{ - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - stmt->setString(0, name); - - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - return ObjectGuid::Create<HighGuid::Player>((*result)[0].GetUInt64()); - - return ObjectGuid::Empty; -} - bool ObjectMgr::GetPlayerNameByGUID(ObjectGuid const& guid, std::string& name) { CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid); @@ -2593,11 +2581,9 @@ uint32 ObjectMgr::GetPlayerAccountIdByGUID(ObjectGuid const& guid) uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(std::string const& name) { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_BY_NAME); - stmt->setString(0, name); - - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - return (*result)[0].GetUInt32(); + 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 667b8ea1da4..67188e8028f 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -991,8 +991,6 @@ class TC_GAME_API ObjectMgr void GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const; - static ObjectGuid GetPlayerGUIDByName(std::string const& name); - std::vector<uint32> 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 07e24e3c26e..96618d225d3 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -2364,7 +2364,8 @@ void Guild::LoadRankFromDB(Field* fields) bool Guild::LoadMemberFromDB(Field* fields) { ObjectGuid::LowType lowguid = fields[1].GetUInt64(); - Member *member = new Member(m_id, ObjectGuid::Create<HighGuid::Player>(lowguid), fields[2].GetUInt8()); + ObjectGuid playerGuid(ObjectGuid::Create<HighGuid::Player>(lowguid)); + Member* member = new Member(m_id, playerGuid, fields[2].GetUInt8()); if (!member->LoadFromDB(fields)) { SQLTransaction trans(nullptr); @@ -2373,6 +2374,7 @@ bool Guild::LoadMemberFromDB(Field* fields) return false; } + sWorld->UpdateCharacterGuildId(playerGuid, GetId()); m_members[member->GetGUID()] = member; return true; } @@ -2621,7 +2623,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)) packet.Invites.emplace_back(member->GetGUID(), level); @@ -2640,7 +2642,7 @@ bool Guild::AddMember(SQLTransaction& trans, ObjectGuid guid, uint8 rankId) if (player->GetGuildId()) return false; } - else if (Player::GetGuildIdFromDB(guid)) + else if (Player::GetGuildIdFromCharacterInfo(guid)) return false; // Remove all player signs from another petitions @@ -2695,6 +2697,7 @@ bool Guild::AddMember(SQLTransaction& trans, ObjectGuid guid, uint8 rankId) return false; } m_members[guid] = member; + sWorld->UpdateCharacterGuildId(guid, GetId()); } member->SaveToDB(trans); @@ -2767,6 +2770,8 @@ void Guild::DeleteMember(SQLTransaction& trans, ObjectGuid guid, bool isDisbandi for (GuildPerkSpellsEntry const* entry : sGuildPerkSpellsStore) player->RemoveSpell(entry->SpellID, false, false); } + else + sWorld->UpdateCharacterGuildId(guid, 0); Guild::_DeleteMemberFromDB(trans, guid.GetCounter()); if (!isDisbanding) diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 46d61cab35a..82dedefb997 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -255,15 +255,16 @@ void WorldSession::HandleCalendarEventInvite(WorldPackets::Calendar::CalendarEve } else { - // Invitee offline, get data from database - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME); - stmt->setString(0, calendarEventInvite.Name); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + // Invitee offline, get data from storage + ObjectGuid guid = sWorld->GetCharacterGuidByName(calendarEventInvite.Name); + if (!guid.IsEmpty()) { - Field* fields = result->Fetch(); - inviteeGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - 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 6e9136a952f..b994e827e1a 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1324,6 +1324,7 @@ void WorldSession::HandleCharRenameCallBack(std::shared_ptr<WorldPackets::Charac SendCharRename(RESPONSE_SUCCESS, renameInfo.get()); sWorld->UpdateCharacterInfo(renameInfo->Guid, renameInfo->NewName); + sWorld->UpdateCharacterGuidByName(renameInfo->Guid, oldName, renameInfo->NewName); } void WorldSession::HandleSetPlayerDeclinedNames(WorldPackets::Character::SetPlayerDeclinedNames& packet) @@ -1548,7 +1549,7 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Cha // character with this name already exist /// @todo: make async - ObjectGuid newGuid = ObjectMgr::GetPlayerGUIDByName(customizeInfo->CharName); + ObjectGuid newGuid = sWorld->GetCharacterGuidByName(customizeInfo->CharName); if (!newGuid.IsEmpty()) { if (newGuid != customizeInfo->CharGUID) @@ -1599,6 +1600,7 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Cha CharacterDatabase.CommitTransaction(trans); sWorld->UpdateCharacterInfo(customizeInfo->CharGUID, customizeInfo->CharName, customizeInfo->SexID); + sWorld->UpdateCharacterGuidByName(customizeInfo->CharGUID, oldName, customizeInfo->CharName); SendCharCustomize(RESPONSE_SUCCESS, customizeInfo.get()); @@ -1862,7 +1864,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa } // character with this name already exist - ObjectGuid newGuid = ObjectMgr::GetPlayerGUIDByName(factionChangeInfo->Name); + ObjectGuid newGuid = sWorld->GetCharacterGuidByName(factionChangeInfo->Name); if (!newGuid.IsEmpty()) { if (newGuid != factionChangeInfo->Guid) @@ -1931,6 +1933,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa } sWorld->UpdateCharacterInfo(factionChangeInfo->Guid, factionChangeInfo->Name, factionChangeInfo->SexID, factionChangeInfo->RaceID); + sWorld->UpdateCharacterGuidByName(factionChangeInfo->Guid, oldName, factionChangeInfo->Name); if (oldRace != factionChangeInfo->RaceID) { @@ -2034,16 +2037,11 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa 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->setUInt64(0, lowGuid); - - if (PreparedQueryResult memberResult = CharacterDatabase.Query(stmt)) - if (Guild* guild = sGuildMgr->GetGuildById(memberResult->Fetch()[0].GetUInt64())) - 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/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index d15ea033240..bf4b8f790c4 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -85,7 +85,7 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet) ObjectGuid receiverGuid; if (normalizePlayerName(packet.Info.Target)) - receiverGuid = ObjectMgr::GetPlayerGUIDByName(packet.Info.Target); + receiverGuid = sWorld->GetCharacterGuidByName(packet.Info.Target); if (!receiverGuid) { @@ -159,7 +159,12 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet) } else { - receiverTeam = ObjectMgr::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->setUInt64(0, receiverGuid.GetCounter()); @@ -171,17 +176,6 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet) mailsCount = fields[0].GetUInt64(); } - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL); - stmt->setUInt64(0, receiverGuid.GetCounter()); - - result = CharacterDatabase.Query(stmt); - if (result) - { - Field* fields = result->Fetch(); - receiverLevel = fields[0].GetUInt8(); - } - - receiverAccountId = ObjectMgr::GetPlayerAccountIdByGUID(receiverGuid); receiverBnetAccountId = Battlenet::AccountMgr::GetIdByGameAccount(receiverAccountId); } diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index ba17b382bb0..e756f48f7ac 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -315,13 +315,7 @@ void WorldSession::SendSpiritResurrect() if (corpseGrave != ghostGrave) _player->TeleportTo(corpseGrave->MapID, corpseGrave->Loc.X, corpseGrave->Loc.Y, corpseGrave->Loc.Z, (corpseGrave->Facing * M_PI) / 180); // Orientation is initially in degrees - // or update at original position - else - _player->UpdateObjectVisibility(); } - // or update at original position - else - _player->UpdateObjectVisibility(); } void WorldSession::HandleBinderActivateOpcode(WorldPackets::NPC::Hello& packet) diff --git a/src/server/game/Handlers/SocialHandler.cpp b/src/server/game/Handlers/SocialHandler.cpp index a6cff8c2417..dcafebe93e1 100644 --- a/src/server/game/Handlers/SocialHandler.cpp +++ b/src/server/game/Handlers/SocialHandler.cpp @@ -43,30 +43,14 @@ void WorldSession::HandleAddFriendOpcode(WorldPackets::Social::AddFriend& packet TC_LOG_DEBUG("network", "WorldSession::HandleAddFriendOpcode: %s asked to add friend: %s", GetPlayerInfo().c_str(), packet.Name.c_str()); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME); - stmt->setString(0, packet.Name); - - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) - .WithPreparedCallback(std::bind(&WorldSession::HandleAddFriendOpcodeCallBack, this, std::move(packet.Notes), 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(packet.Name); + if (!friendGuid.IsEmpty()) { - Field* fields = result->Fetch(); - - if (ObjectGuid::LowType lowGuid = fields[0].GetUInt64()) + if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(friendGuid)) { - friendGuid = ObjectGuid::Create<HighGuid::Player>(lowGuid); - uint32 team = Player::TeamForRace(fields[1].GetUInt8()); - uint32 friendAccountId = fields[2].GetUInt32(); + 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))) { @@ -85,7 +69,7 @@ void WorldSession::HandleAddFriendOpcodeCallBack(std::string const& friendNote, friendResult = FRIEND_ADDED_OFFLINE; if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, SOCIAL_FLAG_FRIEND)) - GetPlayer()->GetSocial()->SetFriendNote(friendGuid, friendNote); + GetPlayer()->GetSocial()->SetFriendNote(friendGuid, packet.Notes); else friendResult = FRIEND_LIST_FULL; } @@ -112,42 +96,23 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPackets::Social::AddIgnore& packet return; TC_LOG_DEBUG("network", "WorldSession::HandleAddIgnoreOpcode: %s asked to Ignore: %s", - GetPlayerInfo().c_str(), packet.Name.c_str()); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - stmt->setString(0, packet.Name); + GetPlayer()->GetName().c_str(), packet.Name.c_str()); - _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(packet.Name); FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; - - if (result) + if (!ignoreGuid.IsEmpty()) { - Field* fields = result->Fetch(); - - if (ObjectGuid::LowType lowGuid = fields[0].GetUInt64()) + 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 c91231df279..a3ae9f579fd 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -132,31 +132,38 @@ void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet) void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) { - Player* player = _player; + Player* player = GetPlayer(); // ignore for remote control state if (player->m_unitMovedByMe != player) return; TC_LOG_INFO("network", "bagIndex: %u, slot: %u", packet.Slot, packet.PackSlot); + // additional check, client outputs message on its own + if (!player->IsAlive()) + { + player->SendEquipError(EQUIP_ERR_PLAYER_DEAD, nullptr, nullptr); + return; + } + Item* item = player->GetItemByPos(packet.Slot, packet.PackSlot); if (!item) { - player->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) { - player->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->GetFlags() & ITEM_FLAG_HAS_LOOT) && !item->HasItemFlag(ITEM_FIELD_FLAG_WRAPPED)) { - player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL); + player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, nullptr); TC_LOG_ERROR("entities.player.cheat", "Possible hacking attempt: Player %s [%s] tried to open item [%s, entry: %u] which is not openable!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), item->GetGUID().ToString().c_str(), proto->GetId()); return; @@ -170,7 +177,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) if (!lockInfo) { - player->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL); + player->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, nullptr); TC_LOG_ERROR("network", "WORLD::OpenItem: item [%s] has an unknown lockId: %u!", item->GetGUID().ToString().c_str(), lockId); return; } @@ -178,7 +185,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) // was not unlocked yet if (item->IsLocked()) { - player->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL); + player->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, nullptr); return; } } @@ -186,37 +193,51 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) if (item->HasItemFlag(ITEM_FIELD_FLAG_WRAPPED))// wrapped? { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM); - stmt->setUInt64(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->SetGiftCreator(ObjectGuid::Empty); - item->SetEntry(entry); - item->SetItemFlags(ItemFieldFlags(flags)); - item->SetState(ITEM_CHANGED, player); - } - else - { - TC_LOG_ERROR("network", "Wrapped item %s don't have record in character_gifts table and will deleted", item->GetGUID().ToString().c_str()); - player->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->setUInt64(0, item->GetGUID().GetCounter()); + if (item->GetGUID() != itemGuid || !item->HasItemFlag(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 %s don't have record in character_gifts table and will deleted", item->GetGUID().ToString().c_str()); + GetPlayer()->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + return; } - else - player->SendLoot(item->GetGUID(), LOOT_CORPSE); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + Field* fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + uint32 flags = fields[1].GetUInt32(); + + item->SetGiftCreator(ObjectGuid::Empty); + item->SetEntry(entry); + item->SetItemFlags(ItemFieldFlags(flags)); + item->SetState(ITEM_CHANGED, GetPlayer()); + + GetPlayer()->SaveInventoryAndGoldToDB(trans); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT); + stmt->setUInt64(0, itemGuid.GetCounter()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); } void WorldSession::HandleGameObjectUseOpcode(WorldPackets::GameObject::GameObjUse& packet) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 4004d7c03ed..a58f36b8e07 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -959,10 +959,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 @@ -975,11 +980,14 @@ 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 247b2c37f30..91c6516e2e9 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -32,6 +32,7 @@ Quest::Quest(Field* questRecord) EmoteOnComplete = 0; _rewItemsCount = 0; _rewChoiceItemsCount = 0; + _eventIdForQuest = 0; _rewCurrencyCount = 0; ID = questRecord[0].GetUInt32(); diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 6382134acab..6e6b90bdbd9 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -460,6 +460,9 @@ class TC_GAME_API Quest uint32 GetRewItemsCount() const { return _rewItemsCount; } uint32 GetRewCurrencyCount() const { return _rewCurrencyCount; } + void SetEventIdForQuest(uint16 eventId) { _eventIdForQuest = eventId; } + uint16 GetEventIdForQuest() const { return _eventIdForQuest; } + void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const; typedef std::vector<int32> PrevQuests; @@ -470,6 +473,7 @@ class TC_GAME_API Quest private: uint32 _rewChoiceItemsCount; uint32 _rewItemsCount; + uint16 _eventIdForQuest; uint32 _rewCurrencyCount; public: diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 1f5f2a829c7..f59c652b9a0 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -126,7 +126,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun m_sessionDbLocaleIndex(locale), m_latency(0), m_clientTimeDelay(0), - _tutorialsChanged(false), + _tutorialsChanged(TUTORIALS_FLAG_NONE), _filterAddonMessages(false), recruiterId(recruiter), isRecruiter(isARecruiter), @@ -802,10 +802,13 @@ void WorldSession::LoadTutorialsData(PreparedQueryResult result) memset(_tutorials, 0, sizeof(uint32) * MAX_ACCOUNT_TUTORIAL_VALUES); if (result) + { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) _tutorials[i] = (*result)[i].GetUInt32(); + _tutorialsChanged |= TUTORIALS_FLAG_LOADED_FROM_DB; + } - _tutorialsChanged = false; + _tutorialsChanged &= ~TUTORIALS_FLAG_CHANGED; } void WorldSession::SendTutorialsData() @@ -817,20 +820,17 @@ void WorldSession::SendTutorialsData() void WorldSession::SaveTutorialsData(SQLTransaction& trans) { - if (!_tutorialsChanged) + if (!(_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 = (_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, _tutorials[i]); stmt->setUInt32(MAX_ACCOUNT_TUTORIAL_VALUES, GetAccountId()); trans->Append(stmt); - _tutorialsChanged = false; + _tutorialsChanged &= ~TUTORIALS_FLAG_CHANGED; } bool WorldSession::IsAddonRegistered(const std::string& prefix) const diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 9c492dbaace..320bf10dcfc 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -834,6 +834,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 @@ -1010,7 +1017,7 @@ class TC_GAME_API WorldSession if (_tutorials[index] != value) { _tutorials[index] = value; - _tutorialsChanged = true; + _tutorialsChanged |= TUTORIALS_FLAG_CHANGED; } } // Auction @@ -1187,10 +1194,8 @@ class TC_GAME_API WorldSession // Social void HandleContactListOpcode(WorldPackets::Social::SendContactList& packet); void HandleAddFriendOpcode(WorldPackets::Social::AddFriend& packet); - void HandleAddFriendOpcodeCallBack(std::string const& friendNote, PreparedQueryResult result); void HandleDelFriendOpcode(WorldPackets::Social::DelFriend& packet); void HandleAddIgnoreOpcode(WorldPackets::Social::AddIgnore& packet); - void HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result); void HandleDelIgnoreOpcode(WorldPackets::Social::DelIgnore& packet); void HandleSetContactNotesOpcode(WorldPackets::Social::SetContactNotes& packet); @@ -1411,6 +1416,7 @@ class TC_GAME_API WorldSession void HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet); void HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet); + void HandleOpenWrappedItemCallback(uint16 pos, ObjectGuid itemGuid, PreparedQueryResult result); void HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& castRequest); void HandleCancelCastOpcode(WorldPackets::Spells::CancelCast& packet); void HandleCancelAuraOpcode(WorldPackets::Spells::CancelAura& cancelAura); @@ -1722,6 +1728,10 @@ class TC_GAME_API WorldSession }; uint64 GetConnectToInstanceKey() const { return _instanceConnectKey.Raw; } + + public: + QueryCallbackProcessor& GetQueryProcessor() { return _queryProcessor; } + private: void ProcessQueryCallbacks(); @@ -1814,7 +1824,7 @@ class TC_GAME_API WorldSession std::atomic<uint32> m_clientTimeDelay; AccountData _accountData[NUM_ACCOUNT_DATA_TYPES]; uint32 _tutorials[MAX_ACCOUNT_TUTORIAL_VALUES]; - bool _tutorialsChanged; + uint8 _tutorialsChanged; std::vector<std::string> _registeredAddonPrefixes; bool _filterAddonMessages; uint32 recruiterId; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 2d8caeaa696..7abaf15a857 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1938,6 +1938,10 @@ void World::SetInitialWorldSettings() sBlackMarketMgr->LoadAuctions(); } + // Load before guilds and arena teams + TC_LOG_INFO("server.loading", "Loading character info store..."); + LoadCharacterInfoStore(); + TC_LOG_INFO("server.loading", "Loading Guild rewards..."); sGuildMgr->LoadGuildRewards(); @@ -2181,8 +2185,6 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Calculate next currency reset time..."); InitCurrencyResetTime(); - LoadCharacterInfoStore(); - TC_LOG_INFO("server.loading", "Loading race and class expansion requirements..."); sObjectMgr->LoadRaceAndClassExpansionRequirements(); @@ -2843,20 +2845,20 @@ 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 guid; uint32 duration_secs = TimeStringToSecs(duration); /// Pick a player to ban if not online - if (!pBanned) + if (!banned) { - guid = ObjectMgr::GetPlayerGUIDByName(name); + guid = sWorld->GetCharacterGuidByName(name); if (guid.IsEmpty()) return BAN_NOTFOUND; // Nobody to ban } else - guid = pBanned->GetGUID(); + guid = banned->GetGUID(); //Use transaction in order to ensure the order of the queries SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -2873,8 +2875,8 @@ BanReturn World::BanCharacter(std::string const& name, std::string const& durati trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); - if (pBanned) - pBanned->GetSession()->KickPlayer(); + if (banned) + banned->GetSession()->KickPlayer(); return BAN_SUCCESS; } @@ -2882,18 +2884,18 @@ 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 guid; /// Pick a player to ban if not online - if (!pBanned) + if (!banned) { - guid = ObjectMgr::GetPlayerGUIDByName(name); + guid = sWorld->GetCharacterGuidByName(name); if (guid.IsEmpty()) return false; // Nobody to ban } else - guid = pBanned->GetGUID(); + guid = banned->GetGUID(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN); stmt->setUInt64(0, guid.GetCounter()); @@ -3524,6 +3526,15 @@ void World::ProcessQueryCallbacks() _queryProcessor.ProcessReadyQueries(); } +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. @@ -3556,8 +3567,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, deleteDate FROM characters"); @@ -3587,9 +3596,18 @@ 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 data.IsDeleted = isDeleted; } +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*/) { CharacterInfoContainer::iterator itr = _characterInfoStore.find(guid); @@ -3627,6 +3645,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::UpdateCharacterInfoDeleted(ObjectGuid const& guid, bool deleted, std::string const* name /*= nullptr*/) { CharacterInfoContainer::iterator itr = _characterInfoStore.find(guid); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 51036b31d06..18c0770fece 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -576,6 +576,8 @@ struct CharacterInfo uint8 Race; uint8 Sex; uint8 Level; + ObjectGuid::LowType GuildId; + uint32 ArenaTeamId[3]; bool IsDeleted; }; @@ -799,12 +801,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, bool isDeleted); - 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); void UpdateCharacterInfoDeleted(ObjectGuid const& guid, bool deleted, std::string const* name = nullptr); uint32 GetCleaningFlags() const { return m_CleaningFlags; } @@ -921,8 +927,10 @@ class TC_GAME_API World typedef std::unordered_map<uint8, Autobroadcast> AutobroadcastContainer; AutobroadcastContainer m_Autobroadcasts; + typedef std::unordered_map<std::string, ObjectGuid> CharacterGuidByNameContainer; typedef std::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 48ff488216f..837bcc8462e 100644 --- a/src/server/scripts/Commands/cs_arena.cpp +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -86,7 +86,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 393058b0264..a2320449dcf 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -306,7 +306,7 @@ public: if (!target) { - targetGuid = ObjectMgr::GetPlayerGUIDByName(name); + targetGuid = sWorld->GetCharacterGuidByName(name); if (targetGuid.IsEmpty()) { handler->PSendSysMessage(LANG_BANINFO_NOCHARACTER); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 9e3c199a638..d7305193ff5 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -214,7 +214,7 @@ public: return; } - if (!ObjectMgr::GetPlayerGUIDByName(delInfo.name).IsEmpty()) + if (!sWorld->GetCharacterGuidByName(delInfo.name).IsEmpty()) { handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId); return; @@ -386,6 +386,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()); @@ -448,7 +449,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) @@ -864,7 +865,7 @@ public: } else { - characterGuid = ObjectMgr::GetPlayerGUIDByName(characterName); + characterGuid = sWorld->GetCharacterGuidByName(characterName); if (!characterGuid) { handler->PSendSysMessage(LANG_NO_PLAYER, characterName.c_str()); @@ -902,7 +903,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; @@ -1059,7 +1060,7 @@ public: return false; } - guid = ObjectMgr::GetPlayerGUIDByName(name); + guid = sWorld->GetCharacterGuidByName(name); } if (!ObjectMgr::GetPlayerAccountIdByGUID(guid)) diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp index a6da8f985ff..dccbbec60ac 100644 --- a/src/server/scripts/Commands/cs_guild.cpp +++ b/src/server/scripts/Commands/cs_guild.cpp @@ -162,7 +162,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; @@ -189,7 +189,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 4f8d7099fe3..10cf9398c00 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2621,7 +2621,7 @@ public: if (targetName) { // Check for offline players - ObjectGuid guid = ObjectMgr::GetPlayerGUIDByName(name); + ObjectGuid guid = sWorld->GetCharacterGuidByName(name); if (guid.IsEmpty()) { handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG); diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 4da93fad156..e517235dac7 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -125,7 +125,7 @@ bool ticket_commandscript::HandleTicketAssignToCommand(ChatHandler* handler, cha return true; } - ObjectGuid targetGuid = ObjectMgr::GetPlayerGUIDByName(target); + ObjectGuid targetGuid = sWorld->GetCharacterGuidByName(target); uint32 accountId = ObjectMgr::GetPlayerAccountIdByGUID(targetGuid); // Target must exist and have administrative rights if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realm.Id.Realm)) |