2010-07-22 13:41:19 -06:00
/*
2010-07-24 04:16:23 +02:00
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
2010-07-22 13:41:19 -06:00
* Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
*
2010-07-24 04:16:23 +02:00
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
2010-07-22 13:41:19 -06:00
*
2010-07-24 04:16:23 +02:00
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
2010-07-22 13:41:19 -06:00
*
2010-07-24 04:16:23 +02:00
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2010-07-22 13:41:19 -06:00
*/
#include "Common.h"
#include "CharacterDatabaseCleaner.h"
#include "World.h"
#include "Database/DatabaseEnv.h"
#include "DBCStores.h"
void CharacterDatabaseCleaner :: CleanDatabase ()
{
// config to disable
2010-12-28 04:19:37 +01:00
if ( ! sWorld -> getBoolConfig ( CONFIG_CLEAN_CHARACTER_DB ))
2010-07-22 13:41:19 -06:00
return ;
2010-12-23 23:25:44 +01:00
sLog -> outString ( "Cleaning character database..." );
2010-07-22 13:41:19 -06:00
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2010-07-22 13:41:19 -06:00
// check flags which clean ups are necessary
2010-12-28 04:19:37 +01:00
QueryResult result = CharacterDatabase . Query ( "SELECT value FROM worldstates WHERE entry = 20004" );
if ( ! result )
2010-07-22 13:41:19 -06:00
return ;
2010-12-28 04:19:37 +01:00
2010-07-22 13:41:19 -06:00
uint32 flags = ( * result )[ 0 ]. GetUInt32 ();
// clean up
2010-12-28 04:19:37 +01:00
if ( flags & CLEANING_FLAG_ACHIEVEMENT_PROGRESS )
2010-07-22 13:41:19 -06:00
CleanCharacterAchievementProgress ();
2010-12-28 04:19:37 +01:00
if ( flags & CLEANING_FLAG_SKILLS )
2010-07-22 13:41:19 -06:00
CleanCharacterSkills ();
2010-12-28 04:19:37 +01:00
if ( flags & CLEANING_FLAG_SPELLS )
2010-07-22 13:41:19 -06:00
CleanCharacterSpell ();
2010-12-28 04:19:37 +01:00
if ( flags & CLEANING_FLAG_TALENTS )
2010-07-22 13:41:19 -06:00
CleanCharacterTalent ();
2010-12-28 04:19:37 +01:00
2010-12-28 04:26:25 +01:00
if ( flags & CLEANING_FLAG_QUESTSTATUS )
CleanCharacterQuestStatus ();
2010-12-28 05:01:31 +01:00
CharacterDatabase . DirectPExecute ( "UPDATE worldstates SET value = value & %u WHERE entry = 20004" , sWorld -> getIntConfig ( CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS ));
2010-12-19 17:06:33 +01:00
2010-12-23 23:25:44 +01:00
sLog -> outString ( ">> Cleaned character database in %u ms" , GetMSTimeDiffToNow ( oldMSTime ));
sLog -> outString ();
2010-07-22 13:41:19 -06:00
}
2010-12-28 04:19:37 +01:00
void CharacterDatabaseCleaner :: CheckUnique ( const char * column , const char * table , bool ( * check )( uint32 ))
2010-07-22 13:41:19 -06:00
{
2010-09-11 21:10:54 +02:00
QueryResult result = CharacterDatabase . PQuery ( "SELECT DISTINCT %s FROM %s" , column , table );
2010-12-28 04:19:37 +01:00
if ( ! result )
2010-07-22 13:41:19 -06:00
{
2010-12-28 04:19:37 +01:00
sLog -> outString ( "Table %s is empty." , table );
2010-07-22 13:41:19 -06:00
return ;
}
bool found = false ;
std :: ostringstream ss ;
do
{
Field * fields = result -> Fetch ();
uint32 id = fields [ 0 ]. GetUInt32 ();
2010-12-28 04:19:37 +01:00
if ( ! check ( id ))
2010-07-22 13:41:19 -06:00
{
2010-12-28 04:19:37 +01:00
if ( ! found )
2010-07-22 13:41:19 -06:00
{
2010-07-24 04:16:23 +02:00
ss << "DELETE FROM " << table << " WHERE " << column << " IN (" ;
2010-07-22 13:41:19 -06:00
found = true ;
}
else
ss << "," ;
2010-12-28 04:19:37 +01:00
2010-07-22 13:41:19 -06:00
ss << id ;
}
}
2010-12-28 04:19:37 +01:00
while ( result -> NextRow ());
2010-07-22 13:41:19 -06:00
if ( found )
{
ss << ")" ;
2010-12-28 04:19:37 +01:00
CharacterDatabase . Execute ( ss . str (). c_str ());
2010-07-22 13:41:19 -06:00
}
}
bool CharacterDatabaseCleaner :: AchievementProgressCheck ( uint32 criteria )
{
return sAchievementCriteriaStore . LookupEntry ( criteria );
}
void CharacterDatabaseCleaner :: CleanCharacterAchievementProgress ()
{
2010-07-24 04:16:23 +02:00
CheckUnique ( "criteria" , "character_achievement_progress" , & AchievementProgressCheck );
2010-07-22 13:41:19 -06:00
}
bool CharacterDatabaseCleaner :: SkillCheck ( uint32 skill )
{
return sSkillLineStore . LookupEntry ( skill );
}
void CharacterDatabaseCleaner :: CleanCharacterSkills ()
{
CheckUnique ( "skill" , "character_skills" , & SkillCheck );
}
bool CharacterDatabaseCleaner :: SpellCheck ( uint32 spell_id )
{
2010-07-24 04:16:23 +02:00
return sSpellStore . LookupEntry ( spell_id ) && ! GetTalentSpellPos ( spell_id );
2010-07-22 13:41:19 -06:00
}
void CharacterDatabaseCleaner :: CleanCharacterSpell ()
{
CheckUnique ( "spell" , "character_spell" , & SpellCheck );
}
bool CharacterDatabaseCleaner :: TalentCheck ( uint32 talent_id )
{
2010-12-28 04:19:37 +01:00
TalentEntry const * talentInfo = sTalentStore . LookupEntry ( talent_id );
if ( ! talentInfo )
2010-07-22 13:41:19 -06:00
return false ;
2010-12-28 04:19:37 +01:00
return sTalentTabStore . LookupEntry ( talentInfo -> TalentTab );
2010-07-22 13:41:19 -06:00
}
void CharacterDatabaseCleaner :: CleanCharacterTalent ()
{
2010-07-24 04:16:23 +02:00
CharacterDatabase . DirectPExecute ( "DELETE FROM character_talent WHERE spec > %u" , MAX_TALENT_SPECS );
CheckUnique ( "spell" , "character_talent" , & TalentCheck );
2010-07-22 13:41:19 -06:00
}
2010-12-28 04:26:25 +01:00
void CharacterDatabaseCleaner :: CleanCharacterQuestStatus ()
{
CharacterDatabase . DirectExecute ( "DELETE FROM character_queststatus WHERE status = 0" );
}