aboutsummaryrefslogtreecommitdiff
path: root/src/game/InstanceSaveMgr.cpp
diff options
context:
space:
mode:
authorn0n4m3 <none@none>2009-12-17 11:18:07 +0100
committern0n4m3 <none@none>2009-12-17 11:18:07 +0100
commit360edd11df3911567000d5e150f3ede22af112f5 (patch)
treeb06a0244a2f24b2a5322e8f61437cae8f9fb6706 /src/game/InstanceSaveMgr.cpp
parent085bc555d73ebc1e28304c4dbfdb9542bb78f21e (diff)
Update InstanceSaveMgr for new instance system
--HG-- branch : trunk
Diffstat (limited to 'src/game/InstanceSaveMgr.cpp')
-rw-r--r--src/game/InstanceSaveMgr.cpp147
1 files changed, 86 insertions, 61 deletions
diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp
index 8c1aab1b60b..128674d978a 100644
--- a/src/game/InstanceSaveMgr.cpp
+++ b/src/game/InstanceSaveMgr.cpp
@@ -77,15 +77,27 @@ InstanceSaveManager::~InstanceSaveManager()
- adding instance into manager
- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
*/
-InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load)
+InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load)
{
- InstanceSave *save = GetInstanceSave(instanceId);
- if(save) return save;
+ if(InstanceSave *old_save = GetInstanceSave(instanceId))
+ return old_save;
const MapEntry* entry = sMapStore.LookupEntry(mapId);
- if(!entry || instanceId == 0)
+ if (!entry)
{
- sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d!", mapId, instanceId);
+ sLog.outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d!", mapId, instanceId);
+ return NULL;
+ }
+
+ if (instanceId == 0)
+ {
+ sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", 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);
return NULL;
}
@@ -93,19 +105,19 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
{
// 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 == DIFFICULTY_HEROIC)
- resetTime = GetResetTimeFor(mapId);
+ if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
+ resetTime = GetResetTimeFor(mapId,difficulty);
else
{
resetTime = time(NULL) + 2 * HOUR;
// normally this will be removed soon after in InstanceMap::Add, prevent error
- ScheduleReset(true, resetTime, InstResetEvent(0, mapId, instanceId));
+ ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId));
}
}
sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);
- save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
+ InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
if(!load) save->SaveToDB();
m_instanceSaveById[instanceId] = save;
@@ -141,7 +153,7 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId)
}
}
-InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset)
+InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset)
: m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId),
m_difficulty(difficulty), m_canReset(canReset)
{
@@ -180,7 +192,7 @@ time_t InstanceSave::GetResetTimeForDB()
{
// only save the reset time for normal instances
const MapEntry *entry = sMapStore.LookupEntry(GetMapId());
- if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DIFFICULTY_HEROIC)
+ if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC)
return 0;
else
return GetResetTime();
@@ -402,18 +414,26 @@ 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, time_t> > ResetTimeMapType;
- ResetTimeMapType InstResetTime;
- QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0");
+ typedef std::pair<uint32 /*PAIR32(map,difficulty)*/, time_t> ResetTimeMapDiffType;
+ typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType;
+ InstResetTimeMapDiffType instResetTime;
+
+ // index instance ids by map/difficulty pairs for fast reset warning send
+ typedef std::multimap<uint32 /*PAIR32(map,difficulty)*/, uint32 /*instanceid*/ > ResetTimeMapDiffInstances;
+ ResetTimeMapDiffInstances mapDiffResetInstances;
+
+ QueryResult *result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance WHERE resettime > 0");
if( result )
{
do
{
- if(time_t resettime = time_t((*result)[2].GetUInt64()))
+ if(time_t resettime = time_t((*result)[3].GetUInt64()))
{
uint32 id = (*result)[0].GetUInt32();
uint32 mapid = (*result)[1].GetUInt32();
- InstResetTime[id] = std::pair<uint32, uint64>(mapid, resettime);
+ uint32 difficulty = (*result)[2].GetUInt32();
+ instResetTime[id] = ResetTimeMapDiffType(MAKE_PAIR32(mapid,difficulty), resettime);
+ mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid,difficulty),id));
}
}
while (result->NextRow());
@@ -428,8 +448,8 @@ void InstanceSaveManager::LoadResetTimes()
Field *fields = result->Fetch();
uint32 instance = fields[1].GetUInt32();
time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR);
- ResetTimeMapType::iterator itr = InstResetTime.find(instance);
- if(itr != InstResetTime.end() && itr->second.second != resettime)
+ InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance);
+ if(itr != instResetTime.end() && itr->second.second != resettime)
{
CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance);
itr->second.second = resettime;
@@ -440,62 +460,65 @@ void InstanceSaveManager::LoadResetTimes()
}
// schedule the reset times
- for (ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr)
+ for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr)
if(itr->second.second > now)
- ScheduleReset(true, itr->second.second, InstResetEvent(0, itr->second.first, itr->first));
+ ScheduleReset(true, itr->second.second, InstResetEvent(0, PAIR32_LOPART(itr->second.first),Difficulty(PAIR32_HIPART(itr->second.first)),itr->first));
}
// load the global respawn times for raid/heroic instances
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
- m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1);
- result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset");
+ result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset");
if(result)
{
do
{
Field *fields = result->Fetch();
uint32 mapid = fields[0].GetUInt32();
- if(!objmgr.GetInstanceTemplate(mapid))
+ Difficulty difficulty = Difficulty(fields[1].GetUInt32());
+ uint64 oldresettime = fields[2].GetUInt64();
+
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if(!mapDiff)
{
- sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid %u in instance_reset!", mapid);
- CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid);
+ sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty);
+ CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid,difficulty);
continue;
}
// update the reset time if the hour in the configs changes
- uint64 oldresettime = fields[1].GetUInt64();
uint64 newresettime = (oldresettime / DAY) * DAY + diff;
if(oldresettime != newresettime)
- CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", newresettime, mapid);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty);
- m_resetTimeByMapId[mapid] = newresettime;
+ SetResetTimeFor(mapid,difficulty,newresettime);
} while(result->NextRow());
delete result;
}
// 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 < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now);
+ _DelHelper(CharacterDatabase, "id, map, instance.difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map AND instance.difficulty = instance_reset.difficulty 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++)
+ for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr)
{
- 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);
- if(!entry || !entry->HasResetTime())
+ uint32 map_diff_pair = itr->first;
+ uint32 mapid = PAIR32_LOPART(map_diff_pair);
+ Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair));
+ MapDifficulty const* mapDiff = &itr->second;
+ if (!mapDiff->resetTime)
continue;
- uint32 period = temp->reset_delay * DAY;
- assert(period != 0);
- time_t t = m_resetTimeByMapId[temp->map];
+ // the reset_delay must be at least one day
+ uint32 period = (mapDiff->resetTime / DAY * sWorld.getRate(RATE_INSTANCE_RESET_TIME)) * DAY;
+
+ time_t t = GetResetTimeFor(mapid,difficulty);
if(!t)
{
// initialize the reset time
t = today + period + diff;
- CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"UI64FMTD"')", i, (uint64)t);
+ CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','"UI64FMTD"')", mapid, difficulty, (uint64)t);
}
if(t < now)
@@ -504,17 +527,23 @@ 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 = '"UI64FMTD"' WHERE mapid = '%u'", (uint64)t, i);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty);
}
- m_resetTimeByMapId[temp->map] = t;
+ SetResetTimeFor(mapid,difficulty,t);
// schedule the global reset/warning
uint8 type = 1;
static int tim[4] = {3600, 900, 300, 60};
for (; type < 4; type++)
- if(t - tim[type-1] > now) break;
- ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i));
+ if(t - tim[type-1] > now)
+ break;
+
+ for(ResetTimeMapDiffInstances::const_iterator in_itr = mapDiffResetInstances.lower_bound(map_diff_pair);
+ in_itr != mapDiffResetInstances.upper_bound(map_diff_pair); ++in_itr)
+ {
+ ScheduleReset(true, t - tim[type-1], InstResetEvent(type, mapid, difficulty, in_itr->second));
+ }
}
}
@@ -555,8 +584,8 @@ void InstanceSaveManager::Update()
else
{
// global reset/warning for a certain map
- time_t resetTime = GetResetTimeFor(event.mapid);
- _ResetOrWarnAll(event.mapid, event.type != 4, resetTime - now);
+ time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty);
+ _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime - now);
if(event.type != 4)
{
// schedule the next warning/reset
@@ -607,29 +636,28 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
else objmgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded
}
-void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLeft)
+void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft)
{
// global reset for all instances of the given map
- // note: this isn't fast but it's meant to be executed very rarely
- Map const *map = MapManager::Instance().CreateBaseMap(mapid);
- if(!map->Instanceable())
+ MapEntry const *mapEntry = sMapStore.LookupEntry(mapid);
+ if (!mapEntry->Instanceable())
return;
+
uint64 now = (uint64)time(NULL);
if(!warn)
{
- // this is called one minute before the reset time
- InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
- if(!temp || !temp->reset_delay)
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if (!mapDiff || !mapDiff->resetTime)
{
- sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid);
+ sLog.outError("InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid);
return;
}
// remove all binds to instances of the given map
for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
{
- if(itr->second->GetMapId() == mapid)
+ if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty)
_ResetSave(itr);
else
++itr;
@@ -644,16 +672,14 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
// calculate the next reset time
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
- uint32 period = temp->reset_delay * DAY;
+ uint32 period = mapDiff->resetTime * DAY;
uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff;
// update it in the DB
- CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d'", next_reset, mapid);
-
- // schedule next reset.
- m_resetTimeByMapId[mapid] = (time_t) next_reset;
- ScheduleReset(true, (time_t) (next_reset-3600), InstResetEvent(1, mapid));
+ CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d' AND difficulty = '%d'", next_reset, mapid, difficulty);
}
+ // note: this isn't fast but it's meant to be executed very rarely
+ Map const *map = MapManager::Instance().CreateBaseMap(mapid); // _not_ include difficulty
MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
MapInstanced::InstancedMaps::iterator mitr;
for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
@@ -682,4 +708,3 @@ uint32 InstanceSaveManager::GetNumBoundGroupsTotal()
ret += itr->second->GetGroupCount();
return ret;
}
-