diff options
-rw-r--r-- | sql/base/auth_database.sql | 5 | ||||
-rw-r--r-- | sql/updates/auth/master/2022_10_03_00_auth.sql | 3 | ||||
-rw-r--r-- | sql/updates/world/master/2022_10_03_01_world.sql | 6 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 1 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.h | 1 | ||||
-rw-r--r-- | src/server/game/Accounts/RBAC.h | 2 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceLockMgr.cpp | 56 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceLockMgr.h | 27 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/Language.h | 4 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_instance.cpp | 177 |
11 files changed, 179 insertions, 109 deletions
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 1de9e3d0c9f..a9fd569837b 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -1426,7 +1426,6 @@ INSERT INTO `rbac_linked_permissions` VALUES (198,413), (198,414), (198,415), -(198,416), (198,430), (198,431), (198,432), @@ -1801,7 +1800,6 @@ INSERT INTO `rbac_permissions` VALUES (413,'Command: instance listbinds'), (414,'Command: instance unbind'), (415,'Command: instance stats'), -(416,'Command: instance savedata'), (417,'Command: learn'), (418,'Command: learn all'), (419,'Command: learn all my'), @@ -2622,7 +2620,8 @@ INSERT INTO `updates` VALUES ('2022_08_21_00_auth.sql','5DEC0CB848F99D575B90356D82276749F2473B72','ARCHIVED','2022-08-21 00:02:03',0), ('2022_09_02_00_auth.sql','E2ED8B4B90829CFD283C9679AE265A9C9B2CF762','RELEASED','2022-09-02 15:52:22',0), ('2022_09_08_00_auth.sql','20B4503E316E042432AC25F7CEE9DCD9EDC631C6','RELEASED','2022-09-08 15:38:35',0), -('2022_09_23_00_auth.sql','F7DB1B903982D99295BC0D7D2BC205C5A2145F03','RELEASED','2022-09-23 03:44:55',0); +('2022_09_23_00_auth.sql','F7DB1B903982D99295BC0D7D2BC205C5A2145F03','RELEASED','2022-09-23 03:44:55',0), +('2022_10_03_00_auth.sql','30220B5474AFA716B141B3879ADE287BAEC61016','RELEASED','2022-10-03 21:32:38',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/auth/master/2022_10_03_00_auth.sql b/sql/updates/auth/master/2022_10_03_00_auth.sql new file mode 100644 index 00000000000..bfe9962d953 --- /dev/null +++ b/sql/updates/auth/master/2022_10_03_00_auth.sql @@ -0,0 +1,3 @@ +DELETE FROM `rbac_account_permissions` WHERE `permissionId`=416; +DELETE FROM `rbac_linked_permissions` WHERE `linkedId`=416; +DELETE FROM `rbac_permissions` WHERE `id=416; diff --git a/sql/updates/world/master/2022_10_03_01_world.sql b/sql/updates/world/master/2022_10_03_01_world.sql new file mode 100644 index 00000000000..33768e20f45 --- /dev/null +++ b/sql/updates/world/master/2022_10_03_01_world.sql @@ -0,0 +1,6 @@ +UPDATE `trinity_string` SET `content_default`='Map: %u-%s | Difficulty: %u-%s | InstanceID: %u | Expired: %s | Extended: %s | Time remaining: %s',`content_loc1`=NULL,`content_loc2`=NULL,`content_loc3`=NULL,`content_loc4`=NULL,`content_loc5`=NULL,`content_loc6`=NULL,`content_loc7`=NULL,`content_loc8`=NULL WHERE `entry`=5045; -- LANG_COMMAND_LIST_BIND_INFO +UPDATE `trinity_string` SET `content_default`='Failed to unbind (lock in use by map) - Map: %u-%s | Difficulty: %u-%s | InstanceID: %u | Expired: %s | Extended: %s | Time remaining: %s',`content_loc1`=NULL,`content_loc2`=NULL,`content_loc3`=NULL,`content_loc4`=NULL,`content_loc5`=NULL,`content_loc6`=NULL,`content_loc7`=NULL,`content_loc8`=NULL WHERE `entry`=5047; -- LANG_COMMAND_INST_UNBIND_FAILED +UPDATE `trinity_string` SET `content_default`='Unbinding - Map: %u-%s | Difficulty: %u-%s | InstanceID: %u | Expired: %s | Extended: %s | Time remaining: %s',`content_loc1`=NULL,`content_loc2`=NULL,`content_loc3`=NULL,`content_loc4`=NULL,`content_loc5`=NULL,`content_loc6`=NULL,`content_loc7`=NULL,`content_loc8`=NULL WHERE `entry`=5048; -- LANG_COMMAND_INST_UNBIND_UNBINDING +DELETE FROM `trinity_string` WHERE `entry`=5054; -- LANG_COMMAND_INST_STAT_GROUPSBOUND + +DELETE FROM `command` WHERE `name`='instance savedata'; diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 5cc1a8ed01f..5d448f35a68 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -762,6 +762,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHARACTER_INSTANCE_LOCK_BY_GUID, "DELETE FROM character_instance_lock WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_CHARACTER_INSTANCE_LOCK, "INSERT INTO character_instance_lock (guid, mapId, lockId, instanceId, difficulty, data, completedEncountersMask, entranceWorldSafeLocId, expiryTime, extended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHARACTER_INSTANCE_LOCK_EXTENSION, "UPDATE character_instance_lock SET extended = ? WHERE guid = ? AND mapId = ? AND lockId = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_CHARACTER_INSTANCE_LOCK_FORCE_EXPIRE, "UPDATE character_instance_lock SET expiryTime = ?, extended = 0 WHERE guid = ? AND mapId = ? AND lockId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_INSTANCE, "DELETE FROM instance WHERE instanceId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_INSTANCE, "INSERT INTO instance (instanceId, data, completedEncountersMask, entranceWorldSafeLocId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); } diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index 80e7f76337c..c0579fe6a3d 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -629,6 +629,7 @@ enum CharacterDatabaseStatements : uint32 CHAR_DEL_CHARACTER_INSTANCE_LOCK_BY_GUID, CHAR_INS_CHARACTER_INSTANCE_LOCK, CHAR_UPD_CHARACTER_INSTANCE_LOCK_EXTENSION, + CHAR_UPD_CHARACTER_INSTANCE_LOCK_FORCE_EXPIRE, CHAR_DEL_INSTANCE, CHAR_INS_INSTANCE, diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index c06c9fbe8df..11f3698732d 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -285,7 +285,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_INSTANCE_LISTBINDS = 413, RBAC_PERM_COMMAND_INSTANCE_UNBIND = 414, RBAC_PERM_COMMAND_INSTANCE_STATS = 415, - RBAC_PERM_COMMAND_INSTANCE_SAVEDATA = 416, + // 416 previously used, do not reuse RBAC_PERM_COMMAND_LEARN = 417, // 418 previously used, do not reuse RBAC_PERM_COMMAND_LEARN_ALL_MY = 419, diff --git a/src/server/game/Instances/InstanceLockMgr.cpp b/src/server/game/Instances/InstanceLockMgr.cpp index 7443a7f192d..97687ef8a8e 100644 --- a/src/server/game/Instances/InstanceLockMgr.cpp +++ b/src/server/game/Instances/InstanceLockMgr.cpp @@ -29,7 +29,7 @@ InstanceLockData::InstanceLockData() = default; InstanceLockData::~InstanceLockData() = default; InstanceLock::InstanceLock(uint32 mapId, Difficulty difficultyId, InstanceResetTimePoint expiryTime, uint32 instanceId) - : _mapId(mapId), _difficultyId(difficultyId), _instanceId(instanceId), _expiryTime(expiryTime), _extended(false) + : _mapId(mapId), _difficultyId(difficultyId), _instanceId(instanceId), _expiryTime(expiryTime), _extended(false), _isInUse(false) { } @@ -460,6 +460,60 @@ std::pair<InstanceResetTimePoint, InstanceResetTimePoint> InstanceLockMgr::Updat return { InstanceResetTimePoint::min(), InstanceResetTimePoint::min() }; } +void InstanceLockMgr::ResetInstanceLocksForPlayer(ObjectGuid const& playerGuid, Optional<uint32> mapId, Optional<Difficulty> difficulty, + std::vector<InstanceLock const*>* locksReset, std::vector<InstanceLock const*>* locksFailedToReset) +{ + auto playerLocksItr = _instanceLocksByPlayer.find(playerGuid); + if (playerLocksItr == _instanceLocksByPlayer.end()) + return; + + for (PlayerLockMap::value_type const& playerLockPair : playerLocksItr->second) + { + if (playerLockPair.second->IsInUse()) + { + locksFailedToReset->push_back(playerLockPair.second.get()); + continue; + } + + if (mapId && *mapId != playerLockPair.second->GetMapId()) + continue; + + if (difficulty && *difficulty != playerLockPair.second->GetDifficultyId()) + continue; + + locksReset->push_back(playerLockPair.second.get()); + } + + if (!locksReset->empty()) + { + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + for (InstanceLock const* instanceLock : *locksReset) + { + MapDb2Entries entries(instanceLock->GetMapId(), instanceLock->GetDifficultyId()); + InstanceResetTimePoint newExpiryTime = GetNextResetTime(entries) - Seconds(entries.MapDifficulty->GetRaidDuration()); + // set reset time to last reset time + const_cast<InstanceLock*>(instanceLock)->SetExpiryTime(newExpiryTime); + const_cast<InstanceLock*>(instanceLock)->SetExtended(false); + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_INSTANCE_LOCK_FORCE_EXPIRE); + stmt->setUInt64(0, uint64(std::chrono::system_clock::to_time_t(newExpiryTime))); + stmt->setUInt64(1, playerGuid.GetCounter()); + stmt->setUInt32(2, entries.MapDifficulty->MapID); + stmt->setUInt32(3, entries.MapDifficulty->LockID); + trans->Append(stmt); + } + CharacterDatabase.CommitTransaction(trans); + } +} + +InstanceLocksStatistics InstanceLockMgr::GetStatistics() const +{ + InstanceLocksStatistics statistics; + statistics.InstanceCount = _instanceLockDataById.size(); + statistics.PlayerCount = _instanceLocksByPlayer.size(); + return statistics; +} + InstanceResetTimePoint InstanceLockMgr::GetNextResetTime(MapDb2Entries const& entries) { tm dateTime = *GameTime::GetDateAndTime(); diff --git a/src/server/game/Instances/InstanceLockMgr.h b/src/server/game/Instances/InstanceLockMgr.h index 3f8aebf6d25..b860335b48f 100644 --- a/src/server/game/Instances/InstanceLockMgr.h +++ b/src/server/game/Instances/InstanceLockMgr.h @@ -112,6 +112,9 @@ public: InstanceResetTimePoint GetEffectiveExpiryTime() const; + bool IsInUse() const { return _isInUse; } + void SetInUse(bool inUse) { _isInUse = inUse; } + private: uint32 _mapId; Difficulty _difficultyId; @@ -119,6 +122,7 @@ private: std::chrono::system_clock::time_point _expiryTime; bool _extended; InstanceLockData _data; + bool _isInUse; }; struct SharedInstanceLockData : InstanceLockData @@ -193,6 +197,12 @@ struct InstanceLockUpdateEvent Optional<uint32> EntranceWorldSafeLocId; }; +struct InstanceLocksStatistics +{ + uint32 InstanceCount = 0; // Number of existing ID-based locks + uint32 PlayerCount = 0; // Number of players that have any lock +}; + class TC_GAME_API InstanceLockMgr { public: @@ -264,6 +274,23 @@ public: */ std::pair<InstanceResetTimePoint, InstanceResetTimePoint> UpdateInstanceLockExtensionForPlayer(ObjectGuid const& playerGuid, MapDb2Entries const& entries, bool extended); + /** + @brief Resets instances that match given filter - for use in GM commands + @param playerGuid Guid of player whose locks will be removed + @param mapId (Optional) Map id of instance locks to reset + @param difficulty (Optional) Difficulty of instance locks to reset + @param locksReset All locks that were reset + @param locksFailedToReset Locks that could not be reset because they are used by existing instance map + */ + void ResetInstanceLocksForPlayer(ObjectGuid const& playerGuid, Optional<uint32> mapId, Optional<Difficulty> difficulty, + std::vector<InstanceLock const*>* locksReset, std::vector<InstanceLock const*>* locksFailedToReset); + + /** + @brief Retrieves instance lock statistics - for use in GM commands + @return Statistics info + */ + InstanceLocksStatistics GetStatistics() const; + static InstanceLockMgr& Instance(); static InstanceResetTimePoint GetNextResetTime(MapDb2Entries const& entries); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index fbf89f37050..d69b5581179 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2781,10 +2781,16 @@ InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, Difficulty sWorldStateMgr->SetValue(WS_TEAM_IN_INSTANCE_ALLIANCE, InstanceTeam == TEAM_ALLIANCE, false, this); sWorldStateMgr->SetValue(WS_TEAM_IN_INSTANCE_HORDE, InstanceTeam == TEAM_HORDE, false, this); + + if (i_instanceLock) + i_instanceLock->SetInUse(true); } InstanceMap::~InstanceMap() { + if (i_instanceLock) + i_instanceLock->SetInUse(false); + delete i_data; delete i_scenario; } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 18f1a1e6ff2..19a0712b3d8 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1100,14 +1100,14 @@ enum TrinityStrings // Instance commands LANG_COMMAND_LIST_BIND_INFO = 5045, LANG_COMMAND_LIST_BIND_PLAYER_BINDS = 5046, - LANG_COMMAND_LIST_BIND_GROUP_BINDS = 5047, + LANG_COMMAND_INST_UNBIND_FAILED = 5047, LANG_COMMAND_INST_UNBIND_UNBINDING = 5048, LANG_COMMAND_INST_UNBIND_UNBOUND = 5049, LANG_COMMAND_INST_STAT_LOADED_INST = 5050, LANG_COMMAND_INST_STAT_PLAYERS_IN = 5051, LANG_COMMAND_INST_STAT_SAVES = 5052, LANG_COMMAND_INST_STAT_PLAYERSBOUND = 5053, - LANG_COMMAND_INST_STAT_GROUPSBOUND = 5054, + // = 5054, // old LANG_COMMAND_INST_STAT_GROUPSBOUND LANG_NOT_DUNGEON = 5055, // Map is not a dungeon. LANG_NO_INSTANCE_DATA = 5056, // Map has no instance data. LANG_COMMAND_INST_SET_BOSS_STATE = 5057, diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp index 210f23ebae4..5eb1cb14940 100644 --- a/src/server/scripts/Commands/cs_instance.cpp +++ b/src/server/scripts/Commands/cs_instance.cpp @@ -28,12 +28,15 @@ EndScriptData */ #include "DB2Stores.h" #include "GameTime.h" #include "Group.h" +#include "InstanceLockMgr.h" #include "InstanceScript.h" #include "Language.h" #include "Map.h" #include "MapManager.h" #include "Player.h" #include "RBAC.h" +#include "Util.h" +#include "World.h" #include "WorldSession.h" #include <sstream> @@ -51,7 +54,6 @@ public: { "listbinds", HandleInstanceListBindsCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_LISTBINDS, Console::No }, { "unbind", HandleInstanceUnbindCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, Console::No }, { "stats", HandleInstanceStatsCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_STATS, Console::Yes }, - { "savedata", HandleInstanceSaveDataCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_SAVEDATA, Console::No }, { "setbossstate", HandleInstanceSetBossStateCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_SET_BOSS_STATE, Console::Yes }, { "getbossstate", HandleInstanceGetBossStateCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE, Console::Yes }, }; @@ -64,89 +66,81 @@ public: return commandTable; } - static bool HandleInstanceListBindsCommand(ChatHandler* /*handler*/) + static bool HandleInstanceListBindsCommand(ChatHandler* handler) { - //Player* player = handler->getSelectedPlayer(); - //if (!player) - // player = handler->GetSession()->GetPlayer(); - - //uint32 counter = 0; - //for (DifficultyEntry const* difficulty : sDifficultyStore) - //{ - // auto binds = player->GetBoundInstances(Difficulty(difficulty->ID)); - // if (binds != player->m_boundInstances.end()) - // { - // for (auto const& [mapId, bind] : binds->second) - // { - // InstanceSave* save = bind.save; - // std::string timeleft = secsToTimeString(save->GetResetTime() - GameTime::GetGameTime(), TimeFormat::ShortText); - // handler->PSendSysMessage(LANG_COMMAND_LIST_BIND_INFO, mapId, save->GetInstanceId(), bind.perm ? "yes" : "no", bind.extendState == EXTEND_STATE_EXPIRED ? "expired" : bind.extendState == EXTEND_STATE_EXTENDED ? "yes" : "no", save->GetDifficultyID(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - // counter++; - // } - // } - //} - //handler->PSendSysMessage(LANG_COMMAND_LIST_BIND_PLAYER_BINDS, counter); - - //counter = 0; - //if (Group* group = player->GetGroup()) - //{ - // for (DifficultyEntry const* difficulty : sDifficultyStore) - // { - // auto binds = group->GetBoundInstances(Difficulty(difficulty->ID)); - // if (binds != group->GetBoundInstanceEnd()) - // { - // for (auto const& [mapId, bind] : binds->second) - // { - // InstanceSave* save = bind.save; - // std::string timeleft = secsToTimeString(save->GetResetTime() - GameTime::GetGameTime(), TimeFormat::ShortText); - // handler->PSendSysMessage(LANG_COMMAND_LIST_BIND_INFO, mapId, save->GetInstanceId(), bind.perm ? "yes" : "no", "-", save->GetDifficultyID(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - // counter++; - // } - // } - // } - //} - //handler->PSendSysMessage(LANG_COMMAND_LIST_BIND_GROUP_BINDS, counter); + Player* player = handler->getSelectedPlayer(); + if (!player) + player = handler->GetSession()->GetPlayer(); + + InstanceResetTimePoint now = GameTime::GetTime<InstanceResetTimePoint::clock>(); + std::vector<InstanceLock const*> instanceLocks = sInstanceLockMgr.GetInstanceLocksForPlayer(player->GetGUID()); + for (InstanceLock const* instanceLock : instanceLocks) + { + MapDb2Entries entries{ instanceLock->GetMapId(), instanceLock->GetDifficultyId() }; + std::string timeleft = !instanceLock->IsExpired() ? secsToTimeString(std::chrono::duration_cast<Seconds>(instanceLock->GetEffectiveExpiryTime() - now).count()) : "-"; + handler->PSendSysMessage(LANG_COMMAND_LIST_BIND_INFO, + entries.Map->ID, entries.Map->MapName[sWorld->GetDefaultDbcLocale()], + uint32(entries.MapDifficulty->DifficultyID), sDifficultyStore.AssertEntry(entries.MapDifficulty->DifficultyID)->Name[sWorld->GetDefaultDbcLocale()], + instanceLock->GetInstanceId(), + handler->GetTrinityString(instanceLock->IsExpired() ? LANG_YES : LANG_NO), + handler->GetTrinityString(instanceLock->IsExtended() ? LANG_YES : LANG_NO), + timeleft.c_str()); + } + handler->PSendSysMessage(LANG_COMMAND_LIST_BIND_PLAYER_BINDS, uint32(instanceLocks.size())); return true; } - static bool HandleInstanceUnbindCommand(ChatHandler* /*handler*/, Variant<uint32, EXACT_SEQUENCE("all")> /*mapArg*/, Optional<uint8> /*difficultyArg*/) + static bool HandleInstanceUnbindCommand(ChatHandler* handler, Variant<uint32, EXACT_SEQUENCE("all")> mapArg, Optional<uint32> difficultyArg) { - //Player* player = handler->getSelectedPlayer(); - //if (!player) - // player = handler->GetSession()->GetPlayer(); - - //uint16 counter = 0; - //uint32 mapId = 0; - - //if (mapArg.holds_alternative<uint32>()) - //{ - // mapId = mapArg.get<uint32>(); - // if (!mapId) - // return false; - //} - - //for (DifficultyEntry const* difficulty : sDifficultyStore) - //{ - // auto binds = player->GetBoundInstances(Difficulty(difficulty->ID)); - // if (binds != player->m_boundInstances.end()) - // { - // for (auto itr = binds->second.begin(); itr != binds->second.end();) - // { - // InstanceSave const* save = itr->second.save; - // if (itr->first != player->GetMapId() && (!mapId || mapId == itr->first) && (!difficultyArg || difficultyArg == save->GetDifficultyID())) - // { - // std::string timeleft = secsToTimeString(save->GetResetTime() - GameTime::GetGameTime(), TimeFormat::ShortText); - // handler->PSendSysMessage(LANG_COMMAND_INST_UNBIND_UNBINDING, itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficultyID(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - // player->UnbindInstance(itr, binds); - // counter++; - // } - // else - // ++itr; - // } - // } - //} - //handler->PSendSysMessage(LANG_COMMAND_INST_UNBIND_UNBOUND, counter); + Player* player = handler->getSelectedPlayer(); + if (!player) + player = handler->GetSession()->GetPlayer(); + + Optional<uint32> mapId; + Optional<Difficulty> difficulty; + + if (mapArg.holds_alternative<uint32>()) + mapId = mapArg.get<uint32>(); + + if (difficultyArg && sDifficultyStore.LookupEntry(*difficultyArg)) + difficulty = Difficulty(*difficultyArg); + + std::vector<InstanceLock const*> locksReset; + std::vector<InstanceLock const*> locksNotReset; + + sInstanceLockMgr.ResetInstanceLocksForPlayer(player->GetGUID(), mapId, difficulty, &locksReset, &locksNotReset); + + InstanceResetTimePoint now = GameTime::GetTime<InstanceResetTimePoint::clock>(); + for (InstanceLock const* instanceLock : locksReset) + { + MapDb2Entries entries{ instanceLock->GetMapId(), instanceLock->GetDifficultyId() }; + std::string timeleft = !instanceLock->IsExpired() ? secsToTimeString(std::chrono::duration_cast<Seconds>(instanceLock->GetEffectiveExpiryTime() - now).count()) : "-"; + handler->PSendSysMessage(LANG_COMMAND_INST_UNBIND_UNBINDING, + entries.Map->ID, entries.Map->MapName[sWorld->GetDefaultDbcLocale()], + uint32(entries.MapDifficulty->DifficultyID), sDifficultyStore.AssertEntry(entries.MapDifficulty->DifficultyID)->Name[sWorld->GetDefaultDbcLocale()], + instanceLock->GetInstanceId(), + handler->GetTrinityString(instanceLock->IsExpired() ? LANG_YES : LANG_NO), + handler->GetTrinityString(instanceLock->IsExtended() ? LANG_YES : LANG_NO), + timeleft.c_str()); + } + + handler->PSendSysMessage(LANG_COMMAND_INST_UNBIND_UNBOUND, uint32(locksReset.size())); + + for (InstanceLock const* instanceLock : locksNotReset) + { + MapDb2Entries entries{ instanceLock->GetMapId(), instanceLock->GetDifficultyId() }; + std::string timeleft = !instanceLock->IsExpired() ? secsToTimeString(std::chrono::duration_cast<Seconds>(instanceLock->GetEffectiveExpiryTime() - now).count()) : "-"; + handler->PSendSysMessage(LANG_COMMAND_INST_UNBIND_FAILED, + entries.Map->ID, entries.Map->MapName[sWorld->GetDefaultDbcLocale()], + uint32(entries.MapDifficulty->DifficultyID), sDifficultyStore.AssertEntry(entries.MapDifficulty->DifficultyID)->Name[sWorld->GetDefaultDbcLocale()], + instanceLock->GetInstanceId(), + handler->GetTrinityString(instanceLock->IsExpired() ? LANG_YES : LANG_NO), + handler->GetTrinityString(instanceLock->IsExtended() ? LANG_YES : LANG_NO), + timeleft.c_str()); + } + + player->SendRaidInfo(); return true; } @@ -155,32 +149,11 @@ public: { handler->PSendSysMessage(LANG_COMMAND_INST_STAT_LOADED_INST, sMapMgr->GetNumInstances()); handler->PSendSysMessage(LANG_COMMAND_INST_STAT_PLAYERS_IN, sMapMgr->GetNumPlayersInInstances()); - //handler->PSendSysMessage(LANG_COMMAND_INST_STAT_SAVES, sInstanceSaveMgr->GetNumInstanceSaves()); - //handler->PSendSysMessage(LANG_COMMAND_INST_STAT_PLAYERSBOUND, sInstanceSaveMgr->GetNumBoundPlayersTotal()); - //handler->PSendSysMessage(LANG_COMMAND_INST_STAT_GROUPSBOUND, sInstanceSaveMgr->GetNumBoundGroupsTotal()); - return true; - } + InstanceLocksStatistics statistics = sInstanceLockMgr.GetStatistics(); - static bool HandleInstanceSaveDataCommand(ChatHandler* handler) - { - //Player* player = handler->GetSession()->GetPlayer(); - //InstanceMap* map = player->GetMap()->ToInstanceMap(); - //if (!map) - //{ - // handler->PSendSysMessage(LANG_NOT_DUNGEON); - // handler->SetSentErrorMessage(true); - // return false; - //} - - //if (!map->GetInstanceScript()) - //{ - // handler->PSendSysMessage(LANG_NO_INSTANCE_DATA); - // handler->SetSentErrorMessage(true); - // return false; - //} - - //map->GetInstanceScript()->SaveToDB(); + handler->PSendSysMessage(LANG_COMMAND_INST_STAT_SAVES, statistics.InstanceCount); + handler->PSendSysMessage(LANG_COMMAND_INST_STAT_PLAYERSBOUND, statistics.PlayerCount); return true; } |