diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 28ddb36cd5..e7695aa9e1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -18251,9 +18251,6 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TodayHonorableKills), fields.totalKills); SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::YesterdayHonorableKills), fields.yesterdayKills); - _LoadInstanceTimeRestrictions(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES)); - UpdateInstanceEnterTimes(); - _LoadBGData(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BG_DATA)); GetSession()->SetPlayer(this); @@ -20165,41 +20162,6 @@ bool Player::CheckInstanceValidity(bool /*isLogin*/) return true; } -bool Player::UpdateAndCheckInstanceCount(uint32 instanceId) -{ - UpdateInstanceEnterTimes(); - - if (_instanceResetTimes.size() < sWorld->getIntConfig(CONFIG_MAX_INSTANCES_PER_HOUR)) - return true; - - if (instanceId == 0) - return false; - - return _instanceResetTimes.find(instanceId) != _instanceResetTimes.end(); -} - -void Player::AddInstanceEnterTime(uint32 instanceId, time_t enterTime) -{ - if (_instanceResetTimes.find(instanceId) == _instanceResetTimes.end()) - _instanceResetTimes.insert(InstanceTimeMap::value_type(instanceId, enterTime + HOUR)); -} - -void Player::UpdateInstanceEnterTimes() -{ - if (_instanceResetTimes.empty()) - return; - - time_t now = GameTime::GetGameTime(); - - for (InstanceTimeMap::iterator itr = _instanceResetTimes.begin(); itr != _instanceResetTimes.end();) - { - if (itr->second < now) - itr = _instanceResetTimes.erase(itr); - else - ++itr; - } -} - WorldSafeLocsEntry const* Player::GetInstanceEntrance(uint32 targetMapId) { WorldSafeLocsEntry const* entranceLocation = nullptr; @@ -20775,7 +20737,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba _SaveTransmogOutfits(trans); _SaveCharacterSelectOutfit(trans); GetSession()->SaveTutorialsData(trans); // changed only while character in game - _SaveInstanceTimeRestrictions(trans); + GetSession()->SaveInstanceTimeRestrictions(trans); _SaveCurrency(trans); _SaveCUFProfiles(trans); _SavePlayerData(trans); @@ -30027,18 +29989,6 @@ float Player::GetAverageItemLevel() const return ((float)sum) / count; } -void Player::_LoadInstanceTimeRestrictions(PreparedQueryResult result) -{ - if (!result) - return; - - do - { - Field* fields = result->Fetch(); - _instanceResetTimes.insert(InstanceTimeMap::value_type(fields[0].GetUInt32(), fields[1].GetUInt64())); - } while (result->NextRow()); -} - void Player::_LoadPetStable(uint32 summonedPetNumber, PreparedQueryResult result) { if (!result) @@ -30095,25 +30045,6 @@ void Player::_LoadPetStable(uint32 summonedPetNumber, PreparedQueryResult result m_temporaryUnsummonedPetNumber = summonedPetNumber; } -void Player::_SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans) -{ - if (_instanceResetTimes.empty()) - return; - - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES); - stmt->setUInt32(0, GetSession()->GetAccountId()); - trans->Append(stmt); - - for (InstanceTimeMap::const_iterator itr = _instanceResetTimes.begin(); itr != _instanceResetTimes.end(); ++itr) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES); - stmt->setUInt32(0, GetSession()->GetAccountId()); - stmt->setUInt32(1, itr->first); - stmt->setInt64(2, itr->second); - trans->Append(stmt); - } -} - bool Player::IsInWhisperWhiteList(ObjectGuid guid) { for (GuidList::const_iterator itr = WhisperList.begin(); itr != WhisperList.end(); ++itr) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index dd34189b58..a7f56da772 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -353,8 +353,6 @@ typedef std::unordered_map PlayerSpellMap; typedef Trinity::Containers::FlatSet SpellModContainer; typedef std::unordered_map PlayerCurrenciesMap; -typedef std::unordered_map InstanceTimeMap; - enum ActionButtonUpdateState { ACTIONBUTTON_UNCHANGED = 0, @@ -1007,7 +1005,6 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_RANDOM_BG, PLAYER_LOGIN_QUERY_LOAD_BANNED, PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_REW, - PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES, PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS, PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS, PLAYER_LOGIN_QUERY_LOAD_CURRENCY, @@ -2781,9 +2778,6 @@ class TC_GAME_API Player final : public Unit, public GridObject void SendRaidInfo(); bool Satisfy(AccessRequirement const* ar, uint32 target_map, TransferAbortParams* params = nullptr, bool report = false); bool CheckInstanceValidity(bool /*isLogin*/); - bool UpdateAndCheckInstanceCount(uint32 instanceId); - void AddInstanceEnterTime(uint32 instanceId, time_t enterTime); - void UpdateInstanceEnterTimes(); WorldSafeLocsEntry const* GetInstanceEntrance(uint32 targetMapId); // last used pet number (for BG's) @@ -3155,7 +3149,6 @@ class TC_GAME_API Player final : public Unit, public GridObject void _LoadTalents(PreparedQueryResult result); void _LoadPvpTalents(PreparedQueryResult result); void _LoadTraits(PreparedQueryResult configsResult, PreparedQueryResult entriesResult); - void _LoadInstanceTimeRestrictions(PreparedQueryResult result); void _LoadPetStable(uint32 summonedPetNumber, PreparedQueryResult result); void _LoadCurrency(PreparedQueryResult result); void _LoadCUFProfiles(PreparedQueryResult result); @@ -3187,7 +3180,6 @@ class TC_GAME_API Player final : public Unit, public GridObject void _SaveTalents(CharacterDatabaseTransaction trans); void _SaveTraits(CharacterDatabaseTransaction trans); void _SaveStats(CharacterDatabaseTransaction trans) const; - void _SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans); void _SaveCurrency(CharacterDatabaseTransaction trans); void _SaveCUFProfiles(CharacterDatabaseTransaction trans); void _SavePlayerData(CharacterDatabaseTransaction trans); @@ -3397,7 +3389,6 @@ class TC_GAME_API Player final : public Unit, public GridObject uint32 m_ChampioningFaction; - InstanceTimeMap _instanceResetTimes; uint32 _pendingBindId; uint32 _pendingBindTimer; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index faacdf137e..65a74228b9 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -310,10 +310,6 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_REW, stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES); - stmt->setUInt32(0, m_accountId); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES, stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_CURRENCY); stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CURRENCY, stmt); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 585bdfa7dd..66154d42cb 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -1836,7 +1836,7 @@ TransferAbortParams Map::PlayerCannotEnter(uint32 mapid, Player* player) return denyReason; // players are only allowed to enter 10 instances per hour - if (!entry->GetFlags2().HasFlag(MapFlags2::IgnoreInstanceFarmLimit) && entry->IsDungeon() && !player->UpdateAndCheckInstanceCount(instanceIdToCheck) && !player->isDead()) + if (!entry->GetFlags2().HasFlag(MapFlags2::IgnoreInstanceFarmLimit) && entry->IsDungeon() && !player->GetSession()->UpdateAndCheckInstanceCount(instanceIdToCheck) && !player->isDead()) return TRANSFER_ABORT_TOO_MANY_INSTANCES; } @@ -2943,7 +2943,7 @@ TransferAbortParams InstanceMap::CannotEnter(Player* player) bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { // increase current instances (hourly limit) - player->AddInstanceEnterTime(GetInstanceId(), GameTime::GetGameTime()); + player->GetSession()->AddInstanceEnterTime(GetInstanceId(), GameTime::GetSystemTime()); MapDb2Entries entries{ GetEntry(), GetMapDifficulty() }; if (entries.MapDifficulty->HasResetSchedule() && i_instanceLock && !i_instanceLock->IsNew() && i_data) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index b4b397b186..d344c52410 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -978,6 +978,66 @@ void WorldSession::SaveTutorialsData(CharacterDatabaseTransaction trans) _tutorialsChanged &= ~TUTORIALS_FLAG_CHANGED; } +void WorldSession::LoadInstanceTimeRestrictions(PreparedQueryResult result) +{ + if (!result) + return; + + SystemTimePoint now = GameTime::GetSystemTime(); + do + { + Field* fields = result->Fetch(); + SystemTimePoint restrictionExpireTime = SystemTimePoint::clock::from_time_t(fields[1].GetUInt64()); + if (restrictionExpireTime > now) + _instanceResetTimes.try_emplace(fields[0].GetUInt32(), restrictionExpireTime); + } while (result->NextRow()); +} + +void WorldSession::SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans) +{ + if (_instanceResetTimes.empty()) + return; + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES); + stmt->setUInt32(0, GetAccountId()); + trans->Append(stmt); + + for (auto const& [instanceId, restrictionExpireTime] : _instanceResetTimes) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES); + stmt->setUInt32(0, GetAccountId()); + stmt->setUInt32(1, instanceId); + stmt->setUInt64(2, SystemTimePoint::clock::to_time_t(restrictionExpireTime)); + trans->Append(stmt); + } +} + +bool WorldSession::UpdateAndCheckInstanceCount(uint32 instanceId) +{ + UpdateInstanceEnterTimes(); + + if (_instanceResetTimes.size() < sWorld->getIntConfig(CONFIG_MAX_INSTANCES_PER_HOUR)) + return true; + + if (instanceId == 0) + return false; + + return _instanceResetTimes.contains(instanceId); +} + +void WorldSession::AddInstanceEnterTime(uint32 instanceId, SystemTimePoint enterTime) +{ + _instanceResetTimes.try_emplace(instanceId, enterTime + 1h); +} + +void WorldSession::UpdateInstanceEnterTimes() +{ + Trinity::Containers::EraseIf(_instanceResetTimes, [now = GameTime::GetSystemTime()](std::pair const& value) + { + return value.second < now; + }); +} + void WorldSession::LoadPlayerDataAccount(PreparedQueryResult const& elementsResult, PreparedQueryResult const& flagsResult) { if (elementsResult) @@ -1219,6 +1279,7 @@ public: { GLOBAL_ACCOUNT_DATA = 0, TUTORIALS, + INSTANCE_TIMES, MAX_QUERIES }; @@ -1237,6 +1298,10 @@ public: stmt->setUInt32(0, accountId); ok = SetPreparedQuery(TUTORIALS, stmt) && ok; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES); + stmt->setUInt32(0, accountId); + ok = SetPreparedQuery(INSTANCE_TIMES, stmt) && ok; + return ok; } }; @@ -1369,6 +1434,7 @@ void WorldSession::InitializeSessionCallback(LoginDatabaseQueryHolder const& hol { LoadAccountData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::GLOBAL_ACCOUNT_DATA), GLOBAL_CACHE_MASK); LoadTutorialsData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS)); + LoadInstanceTimeRestrictions(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::INSTANCE_TIMES)); _collectionMgr->LoadAccountToys(holder.GetPreparedResult(AccountInfoQueryHolder::GLOBAL_ACCOUNT_TOYS)); _collectionMgr->LoadAccountHeirlooms(holder.GetPreparedResult(AccountInfoQueryHolder::GLOBAL_ACCOUNT_HEIRLOOMS)); _collectionMgr->LoadAccountMounts(holder.GetPreparedResult(AccountInfoQueryHolder::MOUNTS)); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 7faa549247..6e61f33c9f 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -1112,6 +1112,11 @@ class TC_GAME_API WorldSession _tutorialsChanged |= TUTORIALS_FLAG_CHANGED; } } + void LoadInstanceTimeRestrictions(PreparedQueryResult result); + void SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans); + bool UpdateAndCheckInstanceCount(uint32 instanceId); + void AddInstanceEnterTime(uint32 instanceId, SystemTimePoint enterTime); + void UpdateInstanceEnterTimes(); struct PlayerDataAccount { @@ -2014,6 +2019,9 @@ class TC_GAME_API WorldSession AccountData _accountData[NUM_ACCOUNT_DATA_TYPES]; std::array _tutorials; uint8 _tutorialsChanged; + + std::unordered_map _instanceResetTimes; + PlayerDataAccount _playerDataAccount; std::vector _registeredAddonPrefixes; bool _filterAddonMessages;