aboutsummaryrefslogtreecommitdiff
path: root/src/game/InstanceSaveMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/InstanceSaveMgr.cpp')
-rw-r--r--src/game/InstanceSaveMgr.cpp92
1 files changed, 53 insertions, 39 deletions
diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp
index ba34f949a5f..d45e3fac451 100644
--- a/src/game/InstanceSaveMgr.cpp
+++ b/src/game/InstanceSaveMgr.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -19,13 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "InstanceSaveMgr.h"
#include "Common.h"
#include "Database/SQLStorage.h"
#include "Player.h"
#include "GridNotifiers.h"
-#include "WorldSession.h"
#include "Log.h"
#include "GridStates.h"
#include "CellImpl.h"
@@ -37,12 +35,13 @@
#include "GridNotifiersImpl.h"
#include "Config/ConfigEnv.h"
#include "Transports.h"
-#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "World.h"
#include "Group.h"
#include "InstanceData.h"
#include "ProgressBar.h"
+#include "Policies/Singleton.h"
+#include "Policies/SingletonImp.h"
INSTANTIATE_SINGLETON_1( InstanceSaveManager );
@@ -58,16 +57,16 @@ InstanceSaveManager::~InstanceSaveManager()
for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
{
InstanceSave *save = itr->second;
- for(InstanceSave::PlayerListType::iterator itr = save->m_playerList.begin(), next = itr; itr != save->m_playerList.end(); itr = next)
+ for(InstanceSave::PlayerListType::iterator itr2 = save->m_playerList.begin(), next = itr2; itr2 != save->m_playerList.end(); itr2 = next)
{
++next;
- (*itr)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true);
+ (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true);
}
save->m_playerList.clear();
- for(InstanceSave::GroupListType::iterator itr = save->m_groupList.begin(), next = itr; itr != save->m_groupList.end(); itr = next)
+ for(InstanceSave::GroupListType::iterator itr2 = save->m_groupList.begin(), next = itr2; itr2 != save->m_groupList.end(); itr2 = next)
{
++next;
- (*itr)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true);
+ (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true);
}
save->m_groupList.clear();
delete save;
@@ -136,15 +135,14 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId)
{
// save the resettime for normal instances only when they get unloaded
if(time_t resettime = itr->second->GetResetTimeForDB())
- CharacterDatabase.PExecute("UPDATE instance SET resettime = '"I64FMTD"' WHERE id = '%u'", (uint64)resettime, InstanceId);
+ CharacterDatabase.PExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", (uint64)resettime, InstanceId);
delete itr->second;
m_instanceSaveById.erase(itr);
}
}
-InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty,
- time_t resetTime, bool canReset)
-: m_mapid(MapId), m_instanceid(InstanceId), m_resetTime(resetTime),
+InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset)
+: m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId),
m_difficulty(difficulty), m_canReset(canReset)
{
}
@@ -167,15 +165,15 @@ void InstanceSave::SaveToDB()
if(map)
{
assert(map->IsDungeon());
- InstanceData *iData = ((InstanceMap *)map)->GetInstanceData();
- if(iData && iData->Save())
+ if(InstanceData *iData = ((InstanceMap*)map)->GetInstanceData())
{
- data = iData->Save();
- CharacterDatabase.escape_string(data);
+ data = iData->GetSaveData();
+ if(!data.empty())
+ CharacterDatabase.escape_string(data);
}
}
- CharacterDatabase.PExecute("INSERT INTO instance VALUES ('%u', '%u', '"I64FMTD"', '%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());
}
time_t InstanceSave::GetResetTimeForDB()
@@ -270,7 +268,7 @@ void InstanceSaveManager::CleanupInstances()
// creature_respawn and gameobject_respawn are in another database
// first, obtain total instance set
- std::set< uint32 > InstanceSet;
+ std::set<uint32> InstanceSet;
QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance");
if( result )
{
@@ -311,6 +309,20 @@ void InstanceSaveManager::CleanupInstances()
delete result;
}
+ // gameobject_respawn
+ result = CharacterDatabase.Query("SELECT DISTINCT(instance_id) FROM characters WHERE instance_id <> 0");
+ if( result )
+ {
+ do
+ {
+ Field *fields = result->Fetch();
+ if(InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end())
+ CharacterDatabase.PExecute("UPDATE characters SET instance_id = '0' WHERE instance_id = '%u'", fields[0].GetUInt32());
+ }
+ while (result->NextRow());
+ delete result;
+ }
+
bar.step();
sLog.outString();
sLog.outString( ">> Initialized %u instances", (uint32)InstanceSet.size());
@@ -322,7 +334,7 @@ void InstanceSaveManager::PackInstances()
// TODO: this can be done a LOT more efficiently
// obtain set of all associations
- std::set< uint32 > InstanceSet;
+ std::set<uint32> InstanceSet;
// all valid ids are in the instance table
// any associations to ids not in this table are assumed to be
@@ -344,13 +356,14 @@ void InstanceSaveManager::PackInstances()
uint32 InstanceNumber = 1;
// we do assume std::set is sorted properly on integer value
- for (std::set< uint32 >::iterator i = InstanceSet.begin(); i != InstanceSet.end(); ++i)
+ for (std::set<uint32>::iterator i = InstanceSet.begin(); i != InstanceSet.end(); ++i)
{
if (*i != InstanceNumber)
{
// remap instance id
WorldDatabase.PExecute("UPDATE creature_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
WorldDatabase.PExecute("UPDATE gameobject_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
+ CharacterDatabase.PExecute("UPDATE characters SET instance_id = '%u' WHERE instance_id = '%u'", InstanceNumber, *i);
CharacterDatabase.PExecute("UPDATE corpse SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
CharacterDatabase.PExecute("UPDATE character_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
CharacterDatabase.PExecute("UPDATE instance SET id = '%u' WHERE id = '%u'", InstanceNumber, *i);
@@ -361,8 +374,8 @@ void InstanceSaveManager::PackInstances()
bar.step();
}
- sLog.outString();
sLog.outString( ">> Instance numbers remapped, next instance id is %u", InstanceNumber );
+ sLog.outString();
}
void InstanceSaveManager::LoadResetTimes()
@@ -375,14 +388,14 @@ void InstanceSaveManager::LoadResetTimes()
// get the current reset times for normal instances (these may need to be updated)
// these are only kept in memory for InstanceSaves that are loaded later
// resettime = 0 in the DB for raid/heroic instances so those are skipped
- typedef std::map<uint32, std::pair<uint32, uint64> > ResetTimeMapType;
+ typedef std::map<uint32, std::pair<uint32, time_t> > ResetTimeMapType;
ResetTimeMapType InstResetTime;
QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0");
if( result )
{
do
{
- if(uint64 resettime = (*result)[2].GetUInt64())
+ if(time_t resettime = time_t((*result)[2].GetUInt64()))
{
uint32 id = (*result)[0].GetUInt32();
uint32 mapid = (*result)[1].GetUInt32();
@@ -400,11 +413,11 @@ void InstanceSaveManager::LoadResetTimes()
{
Field *fields = result->Fetch();
uint32 instance = fields[1].GetUInt32();
- uint64 resettime = fields[0].GetUInt64() + 2 * HOUR;
+ time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR);
ResetTimeMapType::iterator itr = InstResetTime.find(instance);
if(itr != InstResetTime.end() && itr->second.second != resettime)
{
- CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"I64FMTD"' WHERE id = '%u'", resettime, instance);
+ CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance);
itr->second.second = resettime;
}
}
@@ -439,7 +452,7 @@ void InstanceSaveManager::LoadResetTimes()
uint64 oldresettime = fields[1].GetUInt64();
uint64 newresettime = (oldresettime / DAY) * DAY + diff;
if(oldresettime != newresettime)
- CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"I64FMTD"' WHERE mapid = '%u'", newresettime, mapid);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", newresettime, mapid);
m_resetTimeByMapId[mapid] = newresettime;
} while(result->NextRow());
@@ -448,13 +461,13 @@ void InstanceSaveManager::LoadResetTimes()
// clean expired instances, references to them will be deleted in CleanupInstances
// must be done before calculating new reset times
- _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime < '"I64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"I64FMTD"')", (uint64)now, (uint64)now);
+ _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now);
// calculate new global reset times for expired instances and those that have never been reset yet
// add the global reset times to the priority queue
for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
{
- InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(i);
+ InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i);
if(!temp) continue;
// only raid/heroic maps have a global reset time
const MapEntry* entry = sMapStore.LookupEntry(temp->map);
@@ -468,7 +481,7 @@ void InstanceSaveManager::LoadResetTimes()
{
// initialize the reset time
t = today + period + diff;
- CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"I64FMTD"')", i, (uint64)t);
+ CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"UI64FMTD"')", i, (uint64)t);
}
if(t < now)
@@ -477,7 +490,7 @@ void InstanceSaveManager::LoadResetTimes()
// calculate the next reset time
t = (t / DAY) * DAY;
t += ((today - t) / period + 1) * period + diff;
- CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"I64FMTD"' WHERE mapid = '%u'", (uint64)t, i);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", (uint64)t, i);
}
m_resetTimeByMapId[temp->map] = t;
@@ -559,6 +572,7 @@ void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr)
Group *group = *(gList.begin());
group->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true);
}
+ delete itr->second;
m_instanceSaveById.erase(itr++);
lock_instLists = false;
}
@@ -566,7 +580,7 @@ void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr)
void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
{
sLog.outDebug("InstanceSaveMgr::_ResetInstance %u, %u", mapid, instanceId);
- Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid);
+ Map *map = (MapInstanced*)MapManager::Instance().CreateBaseMap(mapid);
if(!map->Instanceable())
return;
@@ -583,7 +597,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
{
// global reset for all instances of the given map
// note: this isn't fast but it's meant to be executed very rarely
- Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid);
+ Map const *map = MapManager::Instance().CreateBaseMap(mapid);
if(!map->Instanceable())
return;
uint64 now = (uint64)time(NULL);
@@ -591,7 +605,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
if(!warn)
{
// this is called one minute before the reset time
- InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(mapid);
+ InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
if(!temp || !temp->reset_delay)
{
sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid);
@@ -619,17 +633,17 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
uint32 period = temp->reset_delay * DAY;
uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff;
// update it in the DB
- CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"I64FMTD"' WHERE mapid = '%d'", next_reset, mapid);
+ CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d'", next_reset, mapid);
}
MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
MapInstanced::InstancedMaps::iterator mitr;
for(mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
{
- Map *map = mitr->second;
- if(!map->IsDungeon()) continue;
- if(warn) ((InstanceMap*)map)->SendResetWarnings(timeLeft);
- else ((InstanceMap*)map)->Reset(INSTANCE_RESET_GLOBAL);
+ Map *map2 = mitr->second;
+ if(!map2->IsDungeon()) continue;
+ if(warn) ((InstanceMap*)map2)->SendResetWarnings(timeLeft);
+ else ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL);
}
// TODO: delete creature/gameobject respawn times even if the maps are not loaded