void InstanceSaveManager::LoadInstances() { uint32 oldMSTime = getMSTime(); // Delete character_instance for non-existent character CharacterDatabase.DirectExecute("DELETE ci.* FROM character_instance AS ci LEFT JOIN characters AS c ON ci.guid = c.guid WHERE c.guid IS NULL"); // Delete expired normal instances (normals expire after 3 days even if someone is still bound to them, cleared on startup) CharacterDatabase.DirectExecute("DELETE FROM instance WHERE resettime > 0 AND resettime < UNIX_TIMESTAMP()"); // Delete instance with no binds CharacterDatabase.DirectExecute("DELETE i.* FROM instance AS i LEFT JOIN character_instance AS ci ON i.id = ci.instance WHERE ci.guid IS NULL"); // Delete creature_respawn, gameobject_respawn and creature_instance for non-existent instance CharacterDatabase.DirectExecute("DELETE FROM creature_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)"); CharacterDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)"); CharacterDatabase.DirectExecute("DELETE tmp.* FROM character_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL"); // Clean invalid references to instance CharacterDatabase.DirectExecute("UPDATE corpse SET instanceId = 0 WHERE instanceId > 0 AND instanceId NOT IN (SELECT id FROM instance)"); CharacterDatabase.DirectExecute("UPDATE characters AS tmp LEFT JOIN instance ON tmp.instance_id = instance.id SET tmp.instance_id = 0 WHERE tmp.instance_id > 0 AND instance.id IS NULL"); // Initialize instance id storage (Needs to be done after the trash has been clean out) sMapMgr->InitInstanceIds(); // Load reset times and clean expired instances LoadResetTimes(); // pussywizard LoadInstanceSaves(); LoadCharacterBinds(); sLog->outString(">> Loaded instances and binds in %u ms", GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void InstanceSaveManager::CleanupInstances() { barGoLink bar(2); bar.step(); // load reset times and clean expired instances LoadResetTimes(); // clean character/group - instance binds with invalid group/characters _DelHelper(CharacterDatabase, "character_instance.guid, instance", "character_instance", "LEFT JOIN characters ON character_instance.guid = characters.guid WHERE characters.guid IS NULL"); _DelHelper(CharacterDatabase, "group_instance.leaderGuid, instance", "group_instance", "LEFT JOIN characters ON group_instance.leaderGuid = characters.guid LEFT JOIN groups ON group_instance.leaderGuid = groups.leaderGuid WHERE characters.guid IS NULL OR groups.leaderGuid IS NULL"); // clean instances that do not have any players or groups bound to them _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN character_instance ON character_instance.instance = id LEFT JOIN group_instance ON group_instance.instance = id WHERE character_instance.instance IS NULL AND group_instance.instance IS NULL"); // clean invalid instance references in other tables _DelHelper(CharacterDatabase, "character_instance.guid, instance", "character_instance", "LEFT JOIN instance ON character_instance.instance = instance.id WHERE instance.id IS NULL"); _DelHelper(CharacterDatabase, "group_instance.leaderGuid, instance", "group_instance", "LEFT JOIN instance ON group_instance.instance = instance.id WHERE instance.id IS NULL"); // creature_respawn and gameobject_respawn are in another database // first, obtain total instance set std::set<uint32> InstanceSet; QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance"); if( result ) { do { Field *fields = result->Fetch(); InstanceSet.insert(fields[0].GetUInt32()); } while (result->NextRow()); delete result; } // creature_respawn result = WorldDatabase.Query("SELECT DISTINCT(instance) FROM creature_respawn WHERE instance <> 0"); if( result ) { do { Field *fields = result->Fetch(); if(InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end()) WorldDatabase.DirectPExecute("DELETE FROM creature_respawn WHERE instance = '%u'", fields[0].GetUInt32()); } while (result->NextRow()); delete result; } // gameobject_respawn result = WorldDatabase.Query("SELECT DISTINCT(instance) FROM gameobject_respawn WHERE instance <> 0"); if( result ) { do { Field *fields = result->Fetch(); if(InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end()) WorldDatabase.DirectPExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'", fields[0].GetUInt32()); } while (result->NextRow()); delete result; } bar.step(); sLog.outString(); sLog.outString( ">> Initialized %u instances", (uint32)InstanceSet.size()); }