[11137] Fixed crash at reset normal dungeon while map loaded.

* Map Persistent noe have direct pointer back to map if map loaded.
  That let simplify some code and avoid map search.
* Crash showup in result changes in code logic related to reset processing.
* Also fix more old bug with reset normal dungeon with not loaded map.
* Reverse MapPersistentState::HasRespawnTimes and MapPersistentState::HasBounds() results
  to expected for function names and update related calls.

Thanks to Schmoozerd for help in research problem.
This commit is contained in:
VladimirMangos 2011-02-12 03:14:50 +03:00
parent 5858aae4d9
commit 47060fe4b1
5 changed files with 30 additions and 23 deletions

View file

@ -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()

View file

@ -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)

View file

@ -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<Player*> PlayerListType;
@ -315,7 +316,7 @@ class MANGOS_DLL_DECL MapPersistentStateManager : public MaNGOS::Singleton<MapPe
private:
typedef UNORDERED_MAP<uint32 /*InstanceId or MapId*/, MapPersistentState*> 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);

View file

@ -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)

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11136"
#define REVISION_NR "11137"
#endif // __REVISION_NR_H__