diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Instances/InstanceSaveMgr.cpp | 147 | ||||
-rwxr-xr-x | src/server/game/Instances/InstanceSaveMgr.h | 3 | ||||
-rwxr-xr-x | src/server/game/World/World.cpp | 7 |
3 files changed, 40 insertions, 117 deletions
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 882a8653b35..48a1b042f3b 100755 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -246,120 +246,47 @@ void InstanceSaveManager::_DelHelper(const char *fields, const char *table, cons } } -void InstanceSaveManager::CleanupInstances() +void InstanceSaveManager::CleanupAndPackInstances() { - barGoLink bar(2); - bar.step(); - // load reset times and clean expired instances sInstanceSaveMgr.LoadResetTimes(); - // clean character/group - instance binds with invalid group/characters - _DelHelper("character_instance.guid, instance", "character_instance", "LEFT JOIN characters ON character_instance.guid = characters.guid WHERE characters.guid IS NULL"); - _DelHelper("group_instance.guid, instance", "group_instance", "LEFT JOIN groups ON group_instance.guid = groups.guid LEFT JOIN characters ON groups.leaderGuid = characters.guid WHERE characters.guid IS NULL OR groups.guid IS NULL"); - - // clean instances that do not have any players or groups bound to them - _DelHelper("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("character_instance.guid, instance", "character_instance", "LEFT JOIN instance ON character_instance.instance = instance.id WHERE instance.id IS NULL"); - _DelHelper("guid, instance", "group_instance", "LEFT JOIN instance ON group_instance.instance = instance.id WHERE instance.id IS NULL"); - - // Clean respawn data from non existing instances - CharacterDatabase.PExecute("DELETE FROM creature_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)"); - CharacterDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)"); - - // 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()); - } - - // characters - 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()); - } - - // corpse - result = CharacterDatabase.Query("SELECT DISTINCT(instance) FROM corpse WHERE instance <> 0"); - if (result) - { - do - { - Field *fields = result->Fetch(); - if (InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end()) - CharacterDatabase.PExecute("UPDATE corpse SET instance = '0' WHERE instance = '%u'", fields[0].GetUInt32()); - } - while (result->NextRow()); - } - - bar.step(); - sLog.outString(); - sLog.outString(">> Initialized %u instances", (uint32)InstanceSet.size()); -} - -void InstanceSaveManager::PackInstances() -{ - // this routine renumbers player instance associations in such a way so they start from 1 and go up - // TODO: this can be done a LOT more efficiently - - // obtain set of all associations - std::set<uint32> InstanceSet; - - // all valid ids are in the instance table - // any associations to ids not in this table are assumed to be - // cleaned already in CleanupInstances - QueryResult result = CharacterDatabase.Query("SELECT id FROM instance"); - if (result) - { - do - { - Field *fields = result->Fetch(); - InstanceSet.insert(fields[0].GetUInt32()); - } - while (result->NextRow()); - } - - barGoLink bar(InstanceSet.size() + 1); - bar.step(); - - 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) - { - if (*i != InstanceNumber) - { - // remap instance id - CharacterDatabase.PExecute("UPDATE creature_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); - CharacterDatabase.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); - CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); - } - - ++InstanceNumber; - bar.step(); - } - - sLog.outString(); - sLog.outString(">> Instance numbers remapped, next instance id is %u", InstanceNumber); + // Delete invalid character_instance and group_instance references + CharacterDatabase.DirectExecute("DELETE ci.* FROM character_instance AS ci LEFT JOIN characters AS c ON ci.guid = c.guid WHERE c.guid IS NULL"); + CharacterDatabase.DirectExecute("DELETE gi.* FROM group_instance AS gi LEFT JOIN groups AS g ON gi.guid = g.guid WHERE g.guid IS NULL"); + + // Delete invalid instance references + CharacterDatabase.DirectExecute("DELETE i.* FROM instance AS i LEFT JOIN character_instance AS ci ON i.id = ci.instance LEFT JOIN group_instance AS gi ON i.id = gi.instance WHERE ci.guid IS NULL AND gi.guid IS NULL"); + + // Delete invalid references to instance + CharacterDatabase.DirectExecute("DELETE tmp.* FROM creature_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL"); + CharacterDatabase.DirectExecute("DELETE tmp.* FROM gameobject_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL"); + 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"); + CharacterDatabase.DirectExecute("DELETE tmp.* FROM group_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 AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = 0 WHERE tmp.instance > 0 AND instance.id IS NULL"); + 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"); + + // Create new index + CharacterDatabase.DirectExecute("ALTER TABLE instance ADD newid INT UNSIGNED AUTO_INCREMENT, ADD INDEX(newid)"); + + // Update old ids + CharacterDatabase.DirectExecute("UPDATE corpse AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0"); + CharacterDatabase.DirectExecute("UPDATE character_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0"); + CharacterDatabase.DirectExecute("UPDATE group_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0"); + CharacterDatabase.DirectExecute("UPDATE characters AS tmp LEFT JOIN instance ON tmp.instance_id = instance.id SET tmp.instance_id = instance.newid WHERE tmp.instance_id > 0"); + CharacterDatabase.DirectExecute("UPDATE creature_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0"); + CharacterDatabase.DirectExecute("UPDATE gameobject_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0"); + + // Update instance too + CharacterDatabase.Query("UPDATE instance SET id = newid"); + + // Finally drop the no longer needed column + CharacterDatabase.Query("ALTER TABLE instance DROP COLUMN newid"); + + // Bake some cookies for click + sLog.outString(">> Cleaned up and packed instances"); } void InstanceSaveManager::LoadResetTimes() diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index aaeefe65c9d..f65720a6d47 100755 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -141,8 +141,7 @@ class InstanceSaveManager }; typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue; - void CleanupInstances(); - void PackInstances(); + void CleanupAndPackInstances(); void LoadResetTimes(); time_t GetResetTimeFor(uint32 mapid, Difficulty d) const diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 65053dbc684..f9bd822865f 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1256,11 +1256,8 @@ void World::SetInitialWorldSettings() sSpellMgr.LoadSkillLineAbilityMap(); ///- Clean up and pack instances - sLog.outString("Cleaning up instances..."); - sInstanceSaveMgr.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables - - sLog.outString("Packing instances..."); - sInstanceSaveMgr.PackInstances(); + sLog.outString("Cleaning up and packing instances..."); + sInstanceSaveMgr.CleanupAndPackInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables sLog.outString("Loading Localization strings..."); sObjectMgr.LoadCreatureLocales(); |