diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 8aec468ab..79528f1cf 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -47,7 +47,7 @@ Map::~Map() sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size()); if (m_persistentState) - m_persistentState->SetUsedByMapState(false); // field pointer can be deleted after this + m_persistentState->SetUsedByMapState(NULL); // field pointer can be deleted after this if(i_data) { @@ -96,7 +96,7 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) m_TerrainData->AddRef(); m_persistentState = sMapPersistentStateMgr.AddPersistentState(i_mapEntry, GetInstanceId(), GetDifficulty(), 0, IsDungeon()); - m_persistentState->SetUsedByMapState(true); + m_persistentState->SetUsedByMapState(this); } void Map::InitVisibilityDistance() diff --git a/src/game/MapPersistentStateMgr.cpp b/src/game/MapPersistentStateMgr.cpp index 3224d35f0..3f793119b 100644 --- a/src/game/MapPersistentStateMgr.cpp +++ b/src/game/MapPersistentStateMgr.cpp @@ -43,7 +43,7 @@ static uint32 resetEventTypeDelay[MAX_RESET_EVENT_TYPE] = { 0, 3600, 900, 300, 6 MapPersistentState::MapPersistentState(uint16 MapId, uint32 InstanceId, Difficulty difficulty) : m_instanceid(InstanceId), m_mapid(MapId), - m_difficulty(difficulty), m_usedByMap(false) + m_difficulty(difficulty), m_usedByMap(NULL) { } @@ -134,7 +134,7 @@ bool WorldPersistentState::CanBeUnload() const { // prevent unload if used for loaded map // prevent unload if respawn data still exist (will not prevent reset by scheduler) - return MapPersistentState::CanBeUnload() && HasRespawnTimes(); + return MapPersistentState::CanBeUnload() && !HasRespawnTimes(); } //== DungeonPersistentState functions ===================== @@ -161,7 +161,7 @@ DungeonPersistentState::~DungeonPersistentState() bool DungeonPersistentState::CanBeUnload() const { // prevent unload if any bounded groups or online bounded player still exists - return MapPersistentState::CanBeUnload() && HasBounds() && HasRespawnTimes(); + return MapPersistentState::CanBeUnload() && !HasBounds() && !HasRespawnTimes(); } /* @@ -172,7 +172,7 @@ void DungeonPersistentState::SaveToDB() // state instance data too std::string data; - if (Map *map = sMapMgr.FindMap(GetMapId(), GetInstanceId())) + if (Map *map = GetMap()) { InstanceData *iData = map->GetInstanceData(); if(iData && iData->Save()) @@ -192,7 +192,7 @@ void DungeonPersistentState::DeleteRespawnTimes() CharacterDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'", GetInstanceId()); CharacterDatabase.CommitTransaction(); - ClearRespawnTimes(); + ClearRespawnTimes(); // state can be deleted at call if only respawn data prevent unload } void DungeonPersistentState::DeleteFromDB() @@ -711,19 +711,25 @@ void MapPersistentStateManager::_ResetSave(PersistentStateMap& holder, Persisten void MapPersistentStateManager::_ResetInstance(uint32 mapid, uint32 instanceId) { - DEBUG_LOG("InstanceSaveMgr::_ResetInstance %u, %u", mapid, instanceId); - Map * iMap = sMapMgr.FindMap(mapid, instanceId); - if (!iMap || !iMap->Instanceable()) - return; + DEBUG_LOG("MapPersistentStateManager::_ResetInstance %u, %u", mapid, instanceId); PersistentStateMap::iterator itr = m_instanceSaveByInstanceId.find(instanceId); if (itr != m_instanceSaveByInstanceId.end()) + { + // delay reset until map unload for loaded map + if (Map * iMap = itr->second->GetMap()) + { + MANGOS_ASSERT(iMap->IsDungeon()); + + ((DungeonMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); + return; + } + _ResetSave(m_instanceSaveByInstanceId, itr); + } + DeleteInstanceFromDB(instanceId); // even if state not loaded - - if (iMap->IsDungeon()) - ((DungeonMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); } void MapPersistentStateManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft) diff --git a/src/game/MapPersistentStateMgr.h b/src/game/MapPersistentStateMgr.h index 0a1f3eb82..b71ee1fcc 100644 --- a/src/game/MapPersistentStateMgr.h +++ b/src/game/MapPersistentStateMgr.h @@ -65,10 +65,11 @@ class MapPersistentState Difficulty GetDifficulty() const { return m_difficulty; } bool IsUsedByMap() const { return m_usedByMap; } - void SetUsedByMapState(bool state) + Map* GetMap() const { return m_usedByMap; } // Can be NULL if map not loaded for persistent state + void SetUsedByMapState(Map* map) { - m_usedByMap = state; - if (!state) + m_usedByMap = map; + if (!map) UnloadIfEmpty(); } @@ -90,7 +91,7 @@ class MapPersistentState bool UnloadIfEmpty(); void ClearRespawnTimes(); - bool HasRespawnTimes() const { return m_creatureRespawnTimes.empty() && m_goRespawnTimes.empty(); } + bool HasRespawnTimes() const { return !m_creatureRespawnTimes.empty() || !m_goRespawnTimes.empty(); } private: void SetCreatureRespawnTime(uint32 loguid, time_t t); @@ -102,7 +103,7 @@ class MapPersistentState uint32 m_instanceid; uint32 m_mapid; Difficulty m_difficulty; - bool m_usedByMap; // true when instance map loaded, lock MapPersistentState from unload + Map* m_usedByMap; // NULL if map not loaded, non-NULL lock MapPersistentState from unload // persistent data RespawnTimes m_creatureRespawnTimes; // lock MapPersistentState from unload, for example for temporary bound dungeon unload delay @@ -184,7 +185,7 @@ class DungeonPersistentState : public MapPersistentState protected: bool CanBeUnload() const; // overwrite MapPersistentState::CanBeUnload - bool HasBounds() const { return m_playerList.empty() && m_groupList.empty(); } + bool HasBounds() const { return !m_playerList.empty() || !m_groupList.empty(); } private: typedef std::list PlayerListType; @@ -315,7 +316,7 @@ class MANGOS_DLL_DECL MapPersistentStateManager : public MaNGOS::Singleton PersistentStateMap; - // called by scheduler + // called by scheduler for DungeonPersistentStates void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft); void _ResetInstance(uint32 mapid, uint32 instanceId); void _CleanupExpiredInstancesAtTime(time_t t); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 5a045b31d..32cd0d35e 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2496,7 +2496,7 @@ enum InstanceResetMethod INSTANCE_RESET_GLOBAL, INSTANCE_RESET_GROUP_DISBAND, INSTANCE_RESET_GROUP_JOIN, - INSTANCE_RESET_RESPAWN_DELAY + INSTANCE_RESET_RESPAWN_DELAY // called from reset scheduler for request reset at map unload when map loaded at reset attempt for normal dungeon difficulty }; // byte value (UNIT_FIELD_BYTES_2,3) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 7cdcdc6f6..e86841716 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11136" + #define REVISION_NR "11137" #endif // __REVISION_NR_H__