[11122] Create InstanceSave for non-instanceable maps.

This preparation for use structure for store another map persistance data like respawn times.
This commit is contained in:
VladimirMangos 2011-02-08 00:14:10 +03:00
parent cd867eadef
commit 852c4ddf32
5 changed files with 128 additions and 72 deletions

View file

@ -69,8 +69,7 @@ void InstanceSave::SaveToDB()
// save instance data too // save instance data too
std::string data; std::string data;
Map *map = sMapMgr.FindMap(GetMapId(),m_instanceid); if (Map *map = sMapMgr.FindMap(GetMapId(),m_instanceid))
if(map)
{ {
InstanceData *iData = map->GetInstanceData(); InstanceData *iData = map->GetInstanceData();
if(iData && iData->Save()) if(iData && iData->Save())
@ -80,6 +79,7 @@ void InstanceSave::SaveToDB()
} }
} }
if (m_instanceid)
CharacterDatabase.PExecute("INSERT INTO instance VALUES ('%u', '%u', '"UI64FMTD"', '%u', '%s')", m_instanceid, GetMapId(), (uint64)GetResetTimeForDB(), GetDifficulty(), data.c_str()); CharacterDatabase.PExecute("INSERT INTO instance VALUES ('%u', '%u', '"UI64FMTD"', '%u', '%s')", m_instanceid, GetMapId(), (uint64)GetResetTimeForDB(), GetDifficulty(), data.c_str());
} }
@ -106,6 +106,7 @@ MapEntry const* InstanceSave::GetMapEntry() const
void InstanceSave::DeleteFromDB() void InstanceSave::DeleteFromDB()
{ {
if (GetInstanceId())
InstanceSaveManager::DeleteInstanceFromDB(GetInstanceId()); InstanceSaveManager::DeleteInstanceFromDB(GetInstanceId());
} }
@ -114,7 +115,7 @@ bool InstanceSave::UnloadIfEmpty()
{ {
if (m_playerList.empty() && m_groupList.empty() && !m_usedByMap) if (m_playerList.empty() && m_groupList.empty() && !m_usedByMap)
{ {
sInstanceSaveMgr.RemoveInstanceSave(GetInstanceId()); sInstanceSaveMgr.RemoveInstanceSave(GetMapId(), GetInstanceId());
return false; return false;
} }
else else
@ -372,7 +373,9 @@ InstanceSaveManager::~InstanceSaveManager()
// it is undefined whether this or objectmgr will be unloaded first // it is undefined whether this or objectmgr will be unloaded first
// so we must be prepared for both cases // so we must be prepared for both cases
lock_instLists = true; lock_instLists = true;
for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr) for (InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end(); ++itr)
delete itr->second;
for (InstanceSaveHashMap::iterator itr = m_instanceSaveByMapId.begin(); itr != m_instanceSaveByMapId.end(); ++itr)
delete itr->second; delete itr->second;
} }
@ -382,7 +385,7 @@ InstanceSaveManager::~InstanceSaveManager()
*/ */
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load) InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load)
{ {
if(InstanceSave *old_save = GetInstanceSave(instanceId)) if(InstanceSave *old_save = GetInstanceSave(mapId, instanceId))
return old_save; return old_save;
const MapEntry* entry = sMapStore.LookupEntry(mapId); const MapEntry* entry = sMapStore.LookupEntry(mapId);
@ -392,15 +395,17 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
return NULL; return NULL;
} }
if (entry->Instanceable())
{
if (instanceId == 0) if (instanceId == 0)
{ {
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId); sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d for instanceable map!", mapId, instanceId);
return NULL; return NULL;
} }
if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
{ {
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty); sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong difficulty %u!", mapId, instanceId, difficulty);
return NULL; return NULL;
} }
@ -417,45 +422,97 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
m_Scheduler.ScheduleReset(true, resetTime, InstanceResetEvent(RESET_EVENT_DUNGEON, mapId, difficulty, instanceId)); m_Scheduler.ScheduleReset(true, resetTime, InstanceResetEvent(RESET_EVENT_DUNGEON, mapId, difficulty, instanceId));
} }
} }
}
else
{
if (instanceId != 0)
{
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d for non-instanceable map!", mapId, instanceId);
return NULL;
}
DEBUG_LOG("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId); if (difficulty != REGULAR_DIFFICULTY)
{
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong difficulty %u for non-instanceable map!", mapId, instanceId, difficulty);
return NULL;
}
if (resetTime)
{
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong reset time %u for non-instanceable map!", mapId, instanceId, resetTime);
return NULL;
}
if (canReset)
{
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong canReset %u for non-instanceable map!", mapId, instanceId, canReset ? 1 : 0);
return NULL;
}
}
DEBUG_LOG("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, reset time = %u, canRset = %u", mapId, instanceId, resetTime, canReset ? 1 : 0);
InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset); InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
if(!load) save->SaveToDB(); if (!load)
save->SaveToDB();
if (entry->Instanceable())
m_instanceSaveByInstanceId[instanceId] = save;
else
m_instanceSaveByMapId[mapId] = save;
m_instanceSaveById[instanceId] = save;
return save; return save;
} }
InstanceSave *InstanceSaveManager::GetInstanceSave(uint32 InstanceId) InstanceSave *InstanceSaveManager::GetInstanceSave(uint32 mapId, uint32 instanceId)
{ {
InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(InstanceId); if (instanceId)
return itr != m_instanceSaveById.end() ? itr->second : NULL; {
InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.find(instanceId);
return itr != m_instanceSaveByInstanceId.end() ? itr->second : NULL;
}
else
{
InstanceSaveHashMap::iterator itr = m_instanceSaveByMapId.find(mapId);
return itr != m_instanceSaveByMapId.end() ? itr->second : NULL;
}
} }
void InstanceSaveManager::DeleteInstanceFromDB(uint32 instanceid) void InstanceSaveManager::DeleteInstanceFromDB(uint32 instanceid)
{
if (instanceid)
{ {
CharacterDatabase.BeginTransaction(); CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'", instanceid); CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'", instanceid);
CharacterDatabase.PExecute("DELETE FROM character_instance WHERE instance = '%u'", instanceid); CharacterDatabase.PExecute("DELETE FROM character_instance WHERE instance = '%u'", instanceid);
CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", instanceid); CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", instanceid);
CharacterDatabase.CommitTransaction(); CharacterDatabase.CommitTransaction();
}
// respawn times should be deleted only when the map gets unloaded // respawn times should be deleted only when the map gets unloaded
} }
void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId) void InstanceSaveManager::RemoveInstanceSave(uint32 mapId, uint32 instanceId)
{ {
if (lock_instLists) if (lock_instLists)
return; return;
InstanceSaveHashMap::iterator itr = m_instanceSaveById.find( InstanceId ); if (instanceId)
if(itr != m_instanceSaveById.end()) {
InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.find(instanceId);
if (itr != m_instanceSaveByInstanceId.end())
{ {
// save the resettime for normal instances only when they get unloaded // save the resettime for normal instances only when they get unloaded
if(time_t resettime = itr->second->GetResetTimeForDB()) if(time_t resettime = itr->second->GetResetTimeForDB())
CharacterDatabase.PExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", (uint64)resettime, InstanceId); CharacterDatabase.PExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", (uint64)resettime, instanceId);
_ResetSave(itr); _ResetSave(m_instanceSaveByInstanceId, itr);
}
}
else
{
InstanceSaveHashMap::iterator itr = m_instanceSaveByMapId.find(mapId);
if (itr != m_instanceSaveByMapId.end())
_ResetSave(m_instanceSaveByMapId, itr);
} }
} }
@ -572,13 +629,13 @@ void InstanceSaveManager::PackInstances()
sLog.outString(); sLog.outString();
} }
void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr) void InstanceSaveManager::_ResetSave(InstanceSaveHashMap& holder, InstanceSaveHashMap::iterator &itr)
{ {
// unbind all players bound to the instance // unbind all players bound to the instance
// do not allow UnbindInstance to automatically unload the InstanceSaves // do not allow UnbindInstance to automatically unload the InstanceSaves
lock_instLists = true; lock_instLists = true;
delete itr->second; delete itr->second;
m_instanceSaveById.erase(itr++); holder.erase(itr++);
lock_instLists = false; lock_instLists = false;
} }
@ -589,9 +646,9 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
if (!iMap || !iMap->Instanceable()) if (!iMap || !iMap->Instanceable())
return; return;
InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(instanceId); InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.find(instanceId);
if (itr != m_instanceSaveById.end()) if (itr != m_instanceSaveByInstanceId.end())
_ResetSave(itr); _ResetSave(m_instanceSaveByInstanceId, itr);
DeleteInstanceFromDB(instanceId); // even if save not loaded DeleteInstanceFromDB(instanceId); // even if save not loaded
@ -620,10 +677,10 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
} }
// remove all binds to instances of the given map // remove all binds to instances of the given map
for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) for(InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end();)
{ {
if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty)
_ResetSave(itr); _ResetSave(m_instanceSaveByInstanceId, itr);
else else
++itr; ++itr;
} }
@ -663,7 +720,8 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
uint32 InstanceSaveManager::GetNumBoundPlayersTotal() uint32 InstanceSaveManager::GetNumBoundPlayersTotal()
{ {
uint32 ret = 0; uint32 ret = 0;
for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr) // only instanceable maps have bounds
for(InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end(); ++itr)
ret += itr->second->GetPlayerCount(); ret += itr->second->GetPlayerCount();
return ret; return ret;
} }
@ -671,7 +729,8 @@ uint32 InstanceSaveManager::GetNumBoundPlayersTotal()
uint32 InstanceSaveManager::GetNumBoundGroupsTotal() uint32 InstanceSaveManager::GetNumBoundGroupsTotal()
{ {
uint32 ret = 0; uint32 ret = 0;
for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr) // only instanceable maps have bounds
for(InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end(); ++itr)
ret += itr->second->GetGroupCount(); ret += itr->second->GetGroupCount();
return ret; return ret;
} }

View file

@ -201,33 +201,34 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
InstanceResetScheduler& GetScheduler() { return m_Scheduler; } InstanceResetScheduler& GetScheduler() { return m_Scheduler; }
InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load = false); InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load = false);
void RemoveInstanceSave(uint32 InstanceId); void RemoveInstanceSave(uint32 mapId, uint32 instanceId);
static void DeleteInstanceFromDB(uint32 instanceid); static void DeleteInstanceFromDB(uint32 instanceid);
/* statistics */ /* statistics */
uint32 GetNumInstanceSaves() { return m_instanceSaveById.size(); } uint32 GetNumInstanceSaves() { return m_instanceSaveByInstanceId.size() + m_instanceSaveByMapId.size(); }
uint32 GetNumBoundPlayersTotal(); uint32 GetNumBoundPlayersTotal();
uint32 GetNumBoundGroupsTotal(); uint32 GetNumBoundGroupsTotal();
void Update() { m_Scheduler.Update(); } void Update() { m_Scheduler.Update(); }
private: private:
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap; typedef UNORDERED_MAP<uint32 /*InstanceId or MapId*/, InstanceSave*> InstanceSaveHashMap;
typedef UNORDERED_MAP<uint32 /*mapId*/, InstanceSaveHashMap> InstanceSaveMapMap;
InstanceSave *GetInstanceSave(uint32 InstanceId); InstanceSave *GetInstanceSave(uint32 mapId, uint32 InstanceId);
// called by scheduler // called by scheduler
void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft); void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft);
void _ResetInstance(uint32 mapid, uint32 instanceId); void _ResetInstance(uint32 mapid, uint32 instanceId);
void _CleanupExpiredInstancesAtTime(time_t t); void _CleanupExpiredInstancesAtTime(time_t t);
void _ResetSave(InstanceSaveHashMap::iterator &itr); void _ResetSave(InstanceSaveHashMap& holder, InstanceSaveHashMap::iterator &itr);
void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...); void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...);
// used during global instance resets // used during global instance resets
bool lock_instLists; bool lock_instLists;
// fast lookup by instance id // fast lookup by instance id for instanceable maps
InstanceSaveHashMap m_instanceSaveById; InstanceSaveHashMap m_instanceSaveByInstanceId;
// fast lookup by map id for non-instanceable maps
InstanceSaveHashMap m_instanceSaveByMapId;
InstanceResetScheduler m_Scheduler; InstanceResetScheduler m_Scheduler;
}; };

View file

@ -94,6 +94,9 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode)
//add reference for TerrainData object //add reference for TerrainData object
m_TerrainData->AddRef(); m_TerrainData->AddRef();
m_instanceSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), GetDifficulty(), 0, Instanceable());
m_instanceSave->SetUsedByMapState(true);
} }
void Map::InitVisibilityDistance() void Map::InitVisibilityDistance()
@ -1311,13 +1314,6 @@ InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 Spaw
// the timer is started by default, and stopped when the first player joins // the timer is started by default, and stopped when the first player joins
// this make sure it gets unloaded if for some reason no player joins // this make sure it gets unloaded if for some reason no player joins
m_unloadTimer = std::max(sWorld.getConfig(CONFIG_UINT32_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); m_unloadTimer = std::max(sWorld.getConfig(CONFIG_UINT32_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
// Dungeon only code
if(IsDungeon())
{
m_instanceSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
m_instanceSave->SetUsedByMapState(true);
}
} }
InstanceMap::~InstanceMap() InstanceMap::~InstanceMap()

View file

@ -294,7 +294,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
uint32 i_InstanceId; uint32 i_InstanceId;
uint32 m_unloadTimer; uint32 m_unloadTimer;
float m_VisibleDistance; float m_VisibleDistance;
InstanceSave* m_instanceSave; // can be NULL for non dungeons... InstanceSave* m_instanceSave;
MapRefManager m_mapRefManager; MapRefManager m_mapRefManager;
MapRefManager::iterator m_mapRefIter; MapRefManager::iterator m_mapRefIter;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11121" #define REVISION_NR "11122"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__