mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 01:37:00 +00:00
[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:
parent
cd867eadef
commit
852c4ddf32
5 changed files with 128 additions and 72 deletions
|
|
@ -69,8 +69,7 @@ void InstanceSave::SaveToDB()
|
|||
// save instance data too
|
||||
std::string data;
|
||||
|
||||
Map *map = sMapMgr.FindMap(GetMapId(),m_instanceid);
|
||||
if(map)
|
||||
if (Map *map = sMapMgr.FindMap(GetMapId(),m_instanceid))
|
||||
{
|
||||
InstanceData *iData = map->GetInstanceData();
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
@ -106,6 +106,7 @@ MapEntry const* InstanceSave::GetMapEntry() const
|
|||
|
||||
void InstanceSave::DeleteFromDB()
|
||||
{
|
||||
if (GetInstanceId())
|
||||
InstanceSaveManager::DeleteInstanceFromDB(GetInstanceId());
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +115,7 @@ bool InstanceSave::UnloadIfEmpty()
|
|||
{
|
||||
if (m_playerList.empty() && m_groupList.empty() && !m_usedByMap)
|
||||
{
|
||||
sInstanceSaveMgr.RemoveInstanceSave(GetInstanceId());
|
||||
sInstanceSaveMgr.RemoveInstanceSave(GetMapId(), GetInstanceId());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
|
@ -372,7 +373,9 @@ InstanceSaveManager::~InstanceSaveManager()
|
|||
// it is undefined whether this or objectmgr will be unloaded first
|
||||
// so we must be prepared for both cases
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +385,7 @@ InstanceSaveManager::~InstanceSaveManager()
|
|||
*/
|
||||
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;
|
||||
|
||||
const MapEntry* entry = sMapStore.LookupEntry(mapId);
|
||||
|
|
@ -392,23 +395,25 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (entry->Instanceable())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(!resetTime)
|
||||
if (!resetTime)
|
||||
{
|
||||
// initialize reset time
|
||||
// for normal instances if no creatures are killed the instance will reset in two hours
|
||||
if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
|
||||
if (entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
|
||||
resetTime = m_Scheduler.GetResetTimeFor(mapId,difficulty);
|
||||
else
|
||||
{
|
||||
|
|
@ -417,45 +422,97 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
|
|||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
InstanceSave *InstanceSaveManager::GetInstanceSave(uint32 InstanceId)
|
||||
InstanceSave *InstanceSaveManager::GetInstanceSave(uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(InstanceId);
|
||||
return itr != m_instanceSaveById.end() ? itr->second : NULL;
|
||||
if (instanceId)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (instanceid)
|
||||
{
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'", instanceid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_instance WHERE instance = '%u'", instanceid);
|
||||
CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", instanceid);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
}
|
||||
// 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)
|
||||
return;
|
||||
|
||||
InstanceSaveHashMap::iterator itr = m_instanceSaveById.find( InstanceId );
|
||||
if(itr != m_instanceSaveById.end())
|
||||
if (instanceId)
|
||||
{
|
||||
InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.find(instanceId);
|
||||
if (itr != m_instanceSaveByInstanceId.end())
|
||||
{
|
||||
// save the resettime for normal instances only when they get unloaded
|
||||
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();
|
||||
}
|
||||
|
||||
void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr)
|
||||
void InstanceSaveManager::_ResetSave(InstanceSaveHashMap& holder, InstanceSaveHashMap::iterator &itr)
|
||||
{
|
||||
// unbind all players bound to the instance
|
||||
// do not allow UnbindInstance to automatically unload the InstanceSaves
|
||||
lock_instLists = true;
|
||||
delete itr->second;
|
||||
m_instanceSaveById.erase(itr++);
|
||||
holder.erase(itr++);
|
||||
lock_instLists = false;
|
||||
}
|
||||
|
||||
|
|
@ -589,9 +646,9 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
|
|||
if (!iMap || !iMap->Instanceable())
|
||||
return;
|
||||
|
||||
InstanceSaveHashMap::iterator itr = m_instanceSaveById.find(instanceId);
|
||||
if (itr != m_instanceSaveById.end())
|
||||
_ResetSave(itr);
|
||||
InstanceSaveHashMap::iterator itr = m_instanceSaveByInstanceId.find(instanceId);
|
||||
if (itr != m_instanceSaveByInstanceId.end())
|
||||
_ResetSave(m_instanceSaveByInstanceId, itr);
|
||||
|
||||
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
|
||||
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)
|
||||
_ResetSave(itr);
|
||||
_ResetSave(m_instanceSaveByInstanceId, itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
|
@ -663,7 +720,8 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
|
|||
uint32 InstanceSaveManager::GetNumBoundPlayersTotal()
|
||||
{
|
||||
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();
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -671,7 +729,8 @@ uint32 InstanceSaveManager::GetNumBoundPlayersTotal()
|
|||
uint32 InstanceSaveManager::GetNumBoundGroupsTotal()
|
||||
{
|
||||
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();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,33 +201,34 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||
InstanceResetScheduler& GetScheduler() { return m_Scheduler; }
|
||||
|
||||
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);
|
||||
|
||||
/* statistics */
|
||||
uint32 GetNumInstanceSaves() { return m_instanceSaveById.size(); }
|
||||
uint32 GetNumInstanceSaves() { return m_instanceSaveByInstanceId.size() + m_instanceSaveByMapId.size(); }
|
||||
uint32 GetNumBoundPlayersTotal();
|
||||
uint32 GetNumBoundGroupsTotal();
|
||||
|
||||
void Update() { m_Scheduler.Update(); }
|
||||
private:
|
||||
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
|
||||
typedef UNORDERED_MAP<uint32 /*mapId*/, InstanceSaveHashMap> InstanceSaveMapMap;
|
||||
typedef UNORDERED_MAP<uint32 /*InstanceId or MapId*/, InstanceSave*> InstanceSaveHashMap;
|
||||
|
||||
InstanceSave *GetInstanceSave(uint32 InstanceId);
|
||||
InstanceSave *GetInstanceSave(uint32 mapId, uint32 InstanceId);
|
||||
|
||||
// called by scheduler
|
||||
void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft);
|
||||
void _ResetInstance(uint32 mapid, uint32 instanceId);
|
||||
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,...);
|
||||
|
||||
// used during global instance resets
|
||||
bool lock_instLists;
|
||||
// fast lookup by instance id
|
||||
InstanceSaveHashMap m_instanceSaveById;
|
||||
// fast lookup by instance id for instanceable maps
|
||||
InstanceSaveHashMap m_instanceSaveByInstanceId;
|
||||
// fast lookup by map id for non-instanceable maps
|
||||
InstanceSaveHashMap m_instanceSaveByMapId;
|
||||
|
||||
InstanceResetScheduler m_Scheduler;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode)
|
|||
|
||||
//add reference for TerrainData object
|
||||
m_TerrainData->AddRef();
|
||||
|
||||
m_instanceSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), GetDifficulty(), 0, Instanceable());
|
||||
m_instanceSave->SetUsedByMapState(true);
|
||||
}
|
||||
|
||||
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
|
||||
// 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);
|
||||
|
||||
// Dungeon only code
|
||||
if(IsDungeon())
|
||||
{
|
||||
m_instanceSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
|
||||
m_instanceSave->SetUsedByMapState(true);
|
||||
}
|
||||
}
|
||||
|
||||
InstanceMap::~InstanceMap()
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
|
|||
uint32 i_InstanceId;
|
||||
uint32 m_unloadTimer;
|
||||
float m_VisibleDistance;
|
||||
InstanceSave* m_instanceSave; // can be NULL for non dungeons...
|
||||
InstanceSave* m_instanceSave;
|
||||
|
||||
MapRefManager m_mapRefManager;
|
||||
MapRefManager::iterator m_mapRefIter;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "11121"
|
||||
#define REVISION_NR "11122"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue