aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-03-21 12:07:54 +0100
committerShauren <shauren.trinity@gmail.com>2023-03-21 12:07:54 +0100
commit2569dc8cfec7a5fd89f037579ea6081504b9223f (patch)
treefaa1c70bb7d9f00081d3a70498efe1ab98cd5410
parent5f642b78f04bbbc723d573362ff25f2ede24f5af (diff)
Core/Instances: Fixed not being able to reenter instances that have no encounters completed
Closes #28737
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/Instances/InstanceLockMgr.cpp29
-rw-r--r--src/server/game/Instances/InstanceLockMgr.h4
-rw-r--r--src/server/game/Maps/Map.cpp12
-rw-r--r--src/server/game/Maps/MapManager.cpp2
5 files changed, 34 insertions, 15 deletions
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 046dbc11e95..9d990ff17f9 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -1731,7 +1731,7 @@ LfgLockMap LFGMgr::GetLockedDungeons(ObjectGuid guid)
return LFG_LOCKSTATUS_NOT_IN_SEASON;
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player))
return LFG_LOCKSTATUS_RAID_LOCKED;
- if (dungeon->difficulty > DIFFICULTY_NORMAL && sInstanceLockMgr.FindActiveInstanceLock(guid, { dungeon->map, Difficulty(dungeon->difficulty) }))
+ if (sInstanceLockMgr.FindActiveInstanceLock(guid, { dungeon->map, Difficulty(dungeon->difficulty) }))
return LFG_LOCKSTATUS_RAID_LOCKED;
if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(dungeon->contentTuningId, player->m_playerData->CtrOptions->ContentTuningConditionMask))
{
diff --git a/src/server/game/Instances/InstanceLockMgr.cpp b/src/server/game/Instances/InstanceLockMgr.cpp
index cddb94c8e7b..44aaeb145ea 100644
--- a/src/server/game/Instances/InstanceLockMgr.cpp
+++ b/src/server/game/Instances/InstanceLockMgr.cpp
@@ -29,7 +29,8 @@ 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), _isInUse(false)
+ : _mapId(mapId), _difficultyId(difficultyId), _instanceId(instanceId), _expiryTime(expiryTime), _extended(false),
+ _isInUse(false), _isNew(false)
{
}
@@ -149,7 +150,7 @@ void InstanceLockMgr::Load()
}
instanceLock = new SharedInstanceLock(mapId, difficulty, expiryTime, instanceId, sharedDataItr->second);
- _instanceLockDataById[instanceId] = std::weak_ptr<SharedInstanceLockData>(sharedDataItr->second);
+ _instanceLockDataById[instanceId] = sharedDataItr->second;
}
else
instanceLock = new InstanceLock(mapId, difficulty, expiryTime, instanceId);
@@ -186,7 +187,7 @@ TransferAbortReason InstanceLockMgr::CanJoinInstanceLock(ObjectGuid const& playe
return TRANSFER_ABORT_NONE;
}
- if (!entries.MapDifficulty->IsUsingEncounterLocks() && playerInstanceLock->GetInstanceId() && playerInstanceLock->GetInstanceId() != instanceLock->GetInstanceId())
+ if (!entries.MapDifficulty->IsUsingEncounterLocks() && !playerInstanceLock->IsNew() && playerInstanceLock->GetInstanceId() != instanceLock->GetInstanceId())
return TRANSFER_ABORT_LOCKED_TO_DIFFERENT_INSTANCE;
return TRANSFER_ABORT_NONE;
@@ -256,11 +257,13 @@ InstanceLock* InstanceLockMgr::CreateInstanceLockForNewInstance(ObjectGuid const
std::shared_ptr<SharedInstanceLockData> sharedData = std::make_shared<SharedInstanceLockData>();
_instanceLockDataById[instanceId] = sharedData;
instanceLock = new SharedInstanceLock(entries.MapDifficulty->MapID, Difficulty(entries.MapDifficulty->DifficultyID),
- GetNextResetTime(entries), 0, std::move(sharedData));
+ GetNextResetTime(entries), instanceId, std::move(sharedData));
}
else
instanceLock = new InstanceLock(entries.MapDifficulty->MapID, Difficulty(entries.MapDifficulty->DifficultyID),
- GetNextResetTime(entries), 0);
+ GetNextResetTime(entries), instanceId);
+
+ instanceLock->SetIsNew(true);
_temporaryInstanceLocksByPlayer[playerGuid][entries.GetKey()].reset(instanceLock);
TC_LOG_DEBUG("instance.locks", "[{}-{} | {}-{}] Created new temporary instance lock for {} in instance {}",
@@ -333,7 +336,7 @@ InstanceLock* InstanceLockMgr::UpdateInstanceLockForPlayer(CharacterDatabaseTran
{
if (entries.IsInstanceIdBound())
{
- ASSERT(!instanceLock->GetInstanceId() || instanceLock->GetInstanceId() == updateEvent.InstanceId);
+ ASSERT(instanceLock->GetInstanceId() == updateEvent.InstanceId);
auto sharedDataItr = _instanceLockDataById.find(updateEvent.InstanceId);
ASSERT(sharedDataItr != _instanceLockDataById.end());
ASSERT(sharedDataItr->second.lock().get() == static_cast<SharedInstanceLock*>(instanceLock)->GetSharedData());
@@ -342,6 +345,7 @@ InstanceLock* InstanceLockMgr::UpdateInstanceLockForPlayer(CharacterDatabaseTran
instanceLock->SetInstanceId(updateEvent.InstanceId);
}
+ instanceLock->SetIsNew(false);
instanceLock->GetData()->Data = std::move(updateEvent.NewData);
if (updateEvent.CompletedEncounter)
{
@@ -428,7 +432,15 @@ void InstanceLockMgr::OnSharedInstanceLockDataDelete(uint32 instanceId)
if (_unloading)
return;
- _instanceLockDataById.erase(instanceId);
+ auto itr = _instanceLockDataById.find(instanceId);
+ if (itr == _instanceLockDataById.end())
+ return;
+
+ // weak_ptr state must be checked as well, it might be pointing to a different and valid lock data
+ if (!itr->second.expired())
+ return;
+
+ _instanceLockDataById.erase(itr);
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INSTANCE);
stmt->setUInt32(0, instanceId);
CharacterDatabase.Execute(stmt);
@@ -482,6 +494,9 @@ void InstanceLockMgr::ResetInstanceLocksForPlayer(ObjectGuid const& playerGuid,
if (difficulty && *difficulty != playerLockPair.second->GetDifficultyId())
continue;
+ if (playerLockPair.second->IsExpired())
+ continue;
+
locksReset->push_back(playerLockPair.second.get());
}
diff --git a/src/server/game/Instances/InstanceLockMgr.h b/src/server/game/Instances/InstanceLockMgr.h
index 84edcd90621..40fc27e05b3 100644
--- a/src/server/game/Instances/InstanceLockMgr.h
+++ b/src/server/game/Instances/InstanceLockMgr.h
@@ -115,6 +115,9 @@ public:
bool IsInUse() const { return _isInUse; }
void SetInUse(bool inUse) { _isInUse = inUse; }
+ bool IsNew() const { return _isNew; }
+ void SetIsNew(bool isNew) { _isNew = isNew; }
+
private:
uint32 _mapId;
Difficulty _difficultyId;
@@ -123,6 +126,7 @@ private:
bool _extended;
InstanceLockData _data;
bool _isInUse;
+ bool _isNew;
};
struct SharedInstanceLockData : InstanceLockData
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index d215693c4cc..c5a44aefc51 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2860,7 +2860,7 @@ bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
player->AddInstanceEnterTime(GetInstanceId(), GameTime::GetGameTime());
MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
- if (entries.MapDifficulty->HasResetSchedule() && i_instanceLock && i_instanceLock->GetData()->CompletedEncountersMask)
+ if (entries.MapDifficulty->HasResetSchedule() && i_instanceLock && !i_instanceLock->IsNew())
{
if (!entries.MapDifficulty->IsUsingEncounterLocks())
{
@@ -2948,7 +2948,7 @@ void InstanceMap::CreateInstanceData()
if (!i_data)
return;
- if (!i_instanceLock || !i_instanceLock->GetInstanceId())
+ if (!i_instanceLock || i_instanceLock->IsNew())
{
i_data->Create();
return;
@@ -2985,7 +2985,7 @@ void InstanceMap::TrySetOwningGroup(Group* group)
InstanceResetResult InstanceMap::Reset(InstanceResetMethod method)
{
// raids can be reset if no boss was killed
- if (method != InstanceResetMethod::Expire && i_instanceLock && i_instanceLock->GetData()->CompletedEncountersMask)
+ if (method != InstanceResetMethod::Expire && i_instanceLock && !i_instanceLock->IsNew())
return InstanceResetResult::CannotReset;
if (HavePlayers())
@@ -3075,7 +3075,7 @@ void InstanceMap::UpdateInstanceLock(UpdateBossStateSaveDataEvent const& updateS
playerCompletedEncounters = playerLock->GetData()->CompletedEncountersMask | (1u << updateSaveDataEvent.DungeonEncounter->Bit);
}
- bool isNewLock = !playerLock || !playerLock->GetData()->CompletedEncountersMask || playerLock->IsExpired();
+ bool isNewLock = !playerLock || playerLock->IsNew() || playerLock->IsExpired();
InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
InstanceLockUpdateEvent(GetInstanceId(), i_data->UpdateBossStateSaveData(oldData ? *oldData : "", updateSaveDataEvent),
@@ -3121,7 +3121,7 @@ void InstanceMap::UpdateInstanceLock(UpdateAdditionalSaveDataEvent const& update
if (playerLock)
oldData = &playerLock->GetData()->Data;
- bool isNewLock = !playerLock || !playerLock->GetData()->CompletedEncountersMask || playerLock->IsExpired();
+ bool isNewLock = !playerLock || playerLock->IsNew() || playerLock->IsExpired();
InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
InstanceLockUpdateEvent(GetInstanceId(), i_data->UpdateAdditionalSaveData(oldData ? *oldData : "", updateSaveDataEvent),
@@ -3146,7 +3146,7 @@ void InstanceMap::CreateInstanceLockForPlayer(Player* player)
MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(player->GetGUID(), entries);
- bool isNewLock = !playerLock || !playerLock->GetData()->CompletedEncountersMask || playerLock->IsExpired();
+ bool isNewLock = !playerLock || playerLock->IsNew() || playerLock->IsExpired();
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index fe9c950cc49..0c2d686d10d 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -95,7 +95,7 @@ InstanceMap* MapManager::CreateInstance(uint32 mapId, uint32 instanceId, Instanc
sDB2Manager.GetDownscaledMapDifficultyData(mapId, difficulty);
TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: {}map instance {} for {} created with difficulty {}",
- instanceLock && instanceLock->GetInstanceId() ? "" : "new ", instanceId, mapId, sDifficultyStore.AssertEntry(difficulty)->Name[sWorld->GetDefaultDbcLocale()]);
+ instanceLock && instanceLock->IsNew() ? "" : "new ", instanceId, mapId, sDifficultyStore.AssertEntry(difficulty)->Name[sWorld->GetDefaultDbcLocale()]);
InstanceMap* map = new InstanceMap(mapId, i_gridCleanUpDelay, instanceId, difficulty, team, instanceLock);
ASSERT(map->IsDungeon());