This commit is contained in:
TheLuda 2008-10-14 00:29:20 +02:00
parent d767495d5b
commit 800ee76535
3322 changed files with 903437 additions and 0 deletions

View file

@ -0,0 +1,104 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DBCENUMS_H
#define DBCENUMS_H
enum AreaTeams
{
AREATEAM_NONE = 0,
AREATEAM_ALLY = 2,
AREATEAM_HORDE = 4
};
enum AreaFlags
{
AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
AREA_FLAG_UNK1 = 0x00000002, // unknown, (only Naxxramas and Razorfen Downs)
AREA_FLAG_UNK2 = 0x00000004, // Only used on development map
AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // slave capital city flag?
AREA_FLAG_UNK3 = 0x00000010, // unknown
AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
AREA_FLAG_UNK4 = 0x00000040, // many zones have this flag
AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
AREA_FLAG_OUTLAND = 0x00000400, // outland zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
AREA_FLAG_NEED_FLY = 0x00001000, // only Netherwing Ledge, Socrethar's Seat, Tempest Keep, The Arcatraz, The Botanica, The Mechanar, Sorrow Wing Point, Dragonspine Ridge, Netherwing Mines, Dragonmaw Base Camp, Dragonmaw Skyway
AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 2.4.2)
AREA_FLAG_OUTLAND2 = 0x00004000, // outland zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
AREA_FLAG_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 2.4.2)
AREA_FLAG_UNK5 = 0x00040000, // just used for Amani Pass, Hatchet Hills
AREA_FLAG_LOWLEVEL = 0x00100000 // used for some starting areas with area_level <=15
};
enum FactionTemplateFlags
{
FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats
};
enum FactionMasks
{
FACTION_MASK_PLAYER = 1, // any player
FACTION_MASK_ALLIANCE = 2, // player or creature from alliance team
FACTION_MASK_HORDE = 4, // player or creature from horde team
FACTION_MASK_MONSTER = 8 // aggressive creature from monster team
// if none flags set then non-aggressive creature
};
enum MapTypes
{
MAP_COMMON = 0,
MAP_INSTANCE = 1,
MAP_RAID = 2,
MAP_BATTLEGROUND = 3,
MAP_ARENA = 4
};
enum AbilytyLearnType
{
ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1,
ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2
};
enum ItemEnchantmentType
{
ITEM_ENCHANTMENT_TYPE_NONE = 0,
ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL = 1,
ITEM_ENCHANTMENT_TYPE_DAMAGE = 2,
ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL = 3,
ITEM_ENCHANTMENT_TYPE_RESISTANCE = 4,
ITEM_ENCHANTMENT_TYPE_STAT = 5,
ITEM_ENCHANTMENT_TYPE_TOTEM = 6
};
enum TotemCategoryType
{
TOTEM_CATEGORY_TYPE_KNIFE = 1,
TOTEM_CATEGORY_TYPE_TOTEM = 2,
TOTEM_CATEGORY_TYPE_ROD = 3,
TOTEM_CATEGORY_TYPE_PICK = 21,
TOTEM_CATEGORY_TYPE_STONE = 22,
TOTEM_CATEGORY_TYPE_HAMMER = 23,
TOTEM_CATEGORY_TYPE_SPANNER = 24
};
#endif

View file

@ -0,0 +1,637 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "DBCStores.h"
//#include "DataStore.h"
#include "Policies/SingletonImp.h"
#include "Log.h"
#include "ProgressBar.h"
#include "DBCfmt.cpp"
#include <map>
typedef std::map<uint16,uint32> AreaFlagByAreaID;
typedef std::map<uint32,uint32> AreaFlagByMapID;
DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt);
static AreaFlagByAreaID sAreaFlagByAreaID;
static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt);
DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt);
DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
DBCStorage <EmotesTextEntry> sEmotesTextStore(EmoteEntryfmt);
typedef std::map<uint32,SimpleFactionsList> FactionTeamMap;
static FactionTeamMap sFactionTeamMap;
DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt);
DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt);
DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore(GtCombatRatingsfmt);
DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt);
DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt);
DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt);
DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore(GtChanceToSpellCritfmt);
DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
DBCStorage <ItemEntry> sItemStore(Itemfmt);
//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
DBCStorage <LockEntry> sLockStore(LockEntryfmt);
DBCStorage <MailTemplateEntry> sMailTemplateStore(MailTemplateEntryfmt);
DBCStorage <MapEntry> sMapStore(MapEntryfmt);
DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt);
DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore(RandomPropertiesPointsfmt);
DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt);
DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt);
DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
SpellCategoryStore sSpellCategoryStore;
PetFamilySpellsStore sPetFamilySpellsStore;
DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt);
DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt);
DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt);
DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
TalentSpellPosMap sTalentSpellPosMap;
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
// store absolute bit position for first rank for talent inspect
typedef std::map<uint32,uint32> TalentInspectMap;
static TalentInspectMap sTalentPosInInspect;
static TalentInspectMap sTalentTabSizeInInspect;
static uint32 sTalentTabPages[12/*MAX_CLASSES*/][3];
DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
TaxiMask sTaxiNodesMask;
// DBC used only for initialization sTaxiPathSetBySource at startup.
TaxiPathSetBySource sTaxiPathSetBySource;
DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
// DBC used only for initialization sTaxiPathSetBySource at startup.
TaxiPathNodesByPath sTaxiPathNodesByPath;
static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
typedef std::list<std::string> StoreProblemList;
static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename)
{
sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize);
// assert must fail after function call
return false;
}
template<class T>
inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage<T>& storage, std::string dbc_path, std::string filename)
{
// compatibility format and C++ structure sizes
assert(DBCFile::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFile::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename));
std::string dbc_filename = dbc_path + filename;
if(storage.Load(dbc_filename.c_str()))
{
bar.step();
for(uint8 i = 0; i < MAX_LOCALE; ++i)
{
if(!(availableDbcLocales & (1 << i)))
continue;
std::string dbc_filename_loc = dbc_path + localeNames[i] + "/" + filename;
if(!storage.LoadStringsFrom(dbc_filename_loc.c_str()))
availableDbcLocales &= ~(1<<i); // mark as not available for speedup next checks
}
}
else
{
// sort problematic dbc to (1) non compatible and (2) non-existed
FILE * f=fopen(dbc_filename.c_str(),"rb");
if(f)
{
char buf[100];
snprintf(buf,100," (exist, but have %d fields instead %d) Wrong client version DBC file?",storage.GetFieldCount(),strlen(storage.GetFormat()));
errlist.push_back(dbc_filename + buf);
fclose(f);
}
else
errlist.push_back(dbc_filename);
}
}
void LoadDBCStores(std::string dataPath)
{
std::string dbcPath = dataPath+"dbc/";
const uint32 DBCFilesCount = 56;
barGoLink bar( DBCFilesCount );
StoreProblemList bad_dbc_files;
uint32 availableDbcLocales = 0xFFFFFFFF;
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaStore, dbcPath,"AreaTable.dbc");
// must be after sAreaStore loading
for(uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0
{
if(AreaTableEntry const* area = sAreaStore.LookupEntry(i))
{
// fill AreaId->DBC records
sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag));
// fill MapId->DBC records ( skip sub zones and continents )
if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 )
sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag));
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrRacesStore, dbcPath,"ChrRaces.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc");
for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i)
{
FactionEntry const * faction = sFactionStore.LookupEntry(i);
if (faction && faction->team)
{
SimpleFactionsList &flist = sFactionTeamMap[faction->team];
flist.push_back(i);
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritStore, dbcPath,"gtChanceToMeleeCrit.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritBaseStore, dbcPath,"gtChanceToSpellCritBase.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritStore, dbcPath,"gtChanceToSpellCrit.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenHPStore, dbcPath,"gtOCTRegenHP.dbc");
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc");
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemExtendedCostStore, dbcPath,"ItemExtendedCost.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry const * spell = sSpellStore.LookupEntry(i);
if(spell && spell->Category)
sSpellCategoryStore[spell->Category].insert(i);
// DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields
// uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view
#if MANGOS_ENDIAN == MANGOS_BIGENDIAN
std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1));
#endif
}
for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
{
SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
if(!skillLine)
continue;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
if(spellInfo && (spellInfo->Attributes & 0x1D0) == 0x1D0)
{
for (unsigned int i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i)
{
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i);
if(!cFamily)
continue;
if(skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1])
continue;
sPetFamilySpellsStore[i].insert(spellInfo->Id);
}
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastTimesStore, dbcPath,"SpellCastTimes.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDurationStore, dbcPath,"SpellDuration.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellFocusObjectStore, dbcPath,"SpellFocusObject.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentStore,dbcPath,"SpellItemEnchantment.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc");
// create talent spells set
for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i)
{
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
if (!talentInfo) continue;
for (int j = 0; j < 5; j++)
if(talentInfo->RankID[j])
sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i,j);
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentTabStore, dbcPath,"TalentTab.dbc");
// preper fast data access to bit pos of talent ranks for use at inspecting
{
// fill table by amount of talent ranks and fill sTalentTabBitSizeInInspect
// store in with (row,col,talent)->size key for correct sorting by (row,col)
typedef std::map<uint32,uint32> TalentBitSize;
TalentBitSize sTalentBitSize;
for(uint32 i = 1; i < sTalentStore.GetNumRows(); ++i)
{
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
if (!talentInfo) continue;
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
if(!talentTabInfo)
continue;
// find talent rank
uint32 curtalent_maxrank = 0;
for(uint32 k = 5; k > 0; --k)
{
if(talentInfo->RankID[k-1])
{
curtalent_maxrank = k;
break;
}
}
sTalentBitSize[(talentInfo->Row<<24) + (talentInfo->Col<<16)+talentInfo->TalentID] = curtalent_maxrank;
sTalentTabSizeInInspect[talentInfo->TalentTab] += curtalent_maxrank;
}
// now have all max ranks (and then bit amount used for store talent ranks in inspect)
for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId)
{
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId );
if(!talentTabInfo)
continue;
// store class talent tab pages
uint32 cls = 1;
for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < 12 /*MAX_CLASSES*/;m <<=1, ++cls) {}
sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId;
// add total amount bits for first rank starting from talent tab first talent rank pos.
uint32 pos = 0;
for(TalentBitSize::iterator itr = sTalentBitSize.begin(); itr != sTalentBitSize.end(); ++itr)
{
uint32 talentId = itr->first & 0xFFFF;
TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentId );
if(!talentInfo)
continue;
if(talentInfo->TalentTab != talentTabId)
continue;
sTalentPosInInspect[talentId] = pos;
pos+= itr->second;
}
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc");
// Initialize global taxinodes mask
memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
if(sTaxiNodesStore.LookupEntry(i))
{
uint8 field = (uint8)((i - 1) / 32);
uint32 submask = 1<<((i-1)%32);
sTaxiNodesMask[field] |= submask;
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc");
for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID,entry->price);
uint32 pathCount = sTaxiPathStore.GetNumRows();
//## TaxiPathNode.dbc ## Loaded only for initialization different structures
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathNodeStore, dbcPath,"TaxiPathNode.dbc");
// Calculate path nodes count
std::vector<uint32> pathLength;
pathLength.resize(pathCount); // 0 and some other indexes not used
for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
++pathLength[entry->path];
// Set path length
sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used
for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i)
sTaxiPathNodesByPath[i].resize(pathLength[i]);
// fill data
for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay);
sTaxiPathNodeStore.Clear();
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc");
// error checks
if(bad_dbc_files.size() >= DBCFilesCount )
{
sLog.outError("\nIncorrect DataDir value in mangosd.conf or ALL required *.dbc files (%d) not found by path: %sdbc",DBCFilesCount,dataPath.c_str());
exit(1);
}
else if(!bad_dbc_files.empty() )
{
std::string str;
for(std::list<std::string>::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i)
str += *i + "\n";
sLog.outError("\nSome required *.dbc files (%u from %d) not found or not compatible:\n%s",bad_dbc_files.size(),DBCFilesCount,str.c_str());
exit(1);
}
// check at up-to-date DBC files (53085 is last added spell in 2.4.3)
// check at up-to-date DBC files (17514 is last ID in SkillLineAbilities in 2.4.3)
// check at up-to-date DBC files (598 is last map added in 2.4.3)
// check at up-to-date DBC files (1127 is last gem property added in 2.4.3)
// check at up-to-date DBC files (2425 is last item extended cost added in 2.4.3)
// check at up-to-date DBC files (71 is last char title added in 2.4.3)
// check at up-to-date DBC files (1768 is last area added in 2.4.3)
if( !sSpellStore.LookupEntry(53085) ||
!sSkillLineAbilityStore.LookupEntry(17514) ||
!sMapStore.LookupEntry(598) ||
!sGemPropertiesStore.LookupEntry(1127) ||
!sItemExtendedCostStore.LookupEntry(2425) ||
!sCharTitlesStore.LookupEntry(71) ||
!sAreaStore.LookupEntry(1768) )
{
sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client.");
exit(1);
}
sLog.outString();
sLog.outString( ">> Loaded %d data stores", DBCFilesCount );
sLog.outString();
}
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
{
FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction);
if(itr==sFactionTeamMap.end())
return NULL;
return &itr->second;
}
char* GetPetName(uint32 petfamily, uint32 dbclang)
{
if(!petfamily)
return NULL;
CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(petfamily);
if(!pet_family)
return NULL;
return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL;
}
TalentSpellPos const* GetTalentSpellPos(uint32 spellId)
{
TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId);
if(itr==sTalentSpellPosMap.end())
return NULL;
return &itr->second;
}
uint32 GetTalentSpellCost(uint32 spellId)
{
if(TalentSpellPos const* pos = GetTalentSpellPos(spellId))
return pos->rank+1;
return 0;
}
AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id)
{
AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id);
if(i == sAreaFlagByAreaID.end())
return NULL;
return sAreaStore.LookupEntry(i->second);
}
AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id)
{
if(area_flag)
return sAreaStore.LookupEntry(area_flag);
if(MapEntry const* mapEntry = sMapStore.LookupEntry(map_id))
return GetAreaEntryByAreaID(mapEntry->linked_zone);
return NULL;
}
uint32 GetAreaFlagByMapId(uint32 mapid)
{
AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid);
if(i == sAreaFlagByMapID.end())
return 0;
else
return i->second;
}
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
{
if(mapid != 530) // speed for most cases
return mapid;
if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId))
return wma->virtual_map_id >= 0 ? wma->virtual_map_id : wma->map_id;
return mapid;
}
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
{
mapid = GetVirtualMapForMapAndZone(mapid,zoneId);
if(mapid < 2)
return CONTENT_1_60;
MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
if(!mapEntry)
return CONTENT_1_60;
switch(mapEntry->Expansion())
{
default: return CONTENT_1_60;
case 1: return CONTENT_61_70;
case 2: return CONTENT_71_80;
}
}
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id)
{
// not sorted, numbering index from 0
for(uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
{
ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i);
if(ch && ch->ChannelID == channel_id)
return ch;
}
return NULL;
}
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
{
if(requiredTotemCategoryId==0)
return true;
if(itemTotemCategoryId==0)
return false;
TotemCategoryEntry const* itemEntry = sTotemCategoryStore.LookupEntry(itemTotemCategoryId);
if(!itemEntry)
return false;
TotemCategoryEntry const* reqEntry = sTotemCategoryStore.LookupEntry(requiredTotemCategoryId);
if(!reqEntry)
return false;
if(itemEntry->categoryType!=reqEntry->categoryType)
return false;
return (itemEntry->categoryMask & reqEntry->categoryMask)==reqEntry->categoryMask;
}
void Zone2MapCoordinates(float& x,float& y,uint32 zone)
{
WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
// if not listed then map coordinates (instance)
if(!maEntry)
return;
std::swap(x,y); // at client map coords swapped
x = x*((maEntry->x2-maEntry->x1)/100)+maEntry->x1;
y = y*((maEntry->y2-maEntry->y1)/100)+maEntry->y1; // client y coord from top to down
}
void Map2ZoneCoordinates(float& x,float& y,uint32 zone)
{
WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
// if not listed then map coordinates (instance)
if(!maEntry)
return;
x = (x-maEntry->x1)/((maEntry->x2-maEntry->x1)/100);
y = (y-maEntry->y1)/((maEntry->y2-maEntry->y1)/100); // client y coord from top to down
std::swap(x,y); // client have map coords swapped
}
uint32 GetTalentInspectBitPosInTab(uint32 talentId)
{
TalentInspectMap::const_iterator itr = sTalentPosInInspect.find(talentId);
if(itr == sTalentPosInInspect.end())
return 0;
return itr->second;
}
uint32 GetTalentTabInspectBitSize(uint32 talentTabId)
{
TalentInspectMap::const_iterator itr = sTalentTabSizeInInspect.find(talentTabId);
if(itr == sTalentTabSizeInInspect.end())
return 0;
return itr->second;
}
uint32 const* GetTalentTabPages(uint32 cls)
{
return sTalentTabPages[cls];
}
// script support functions
MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; }
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; }
MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() { return &sSpellRangeStore; }

View file

@ -0,0 +1,202 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DBCSTORES_H
#define DBCSTORES_H
#include "Common.h"
//#include "DataStore.h"
#include "dbcfile.h"
#include "DBCStructure.h"
#include <list>
typedef std::list<uint32> SimpleFactionsList;
SimpleFactionsList const* GetFactionTeamList(uint32 faction);
char* GetPetName(uint32 petfamily, uint32 dbclang);
uint32 GetTalentSpellCost(uint32 spellId);
TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id);
AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id);
uint32 GetAreaFlagByMapId(uint32 mapid);
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
enum ContentLevels
{
CONTENT_1_60 = 0,
CONTENT_61_70,
CONTENT_71_80
};
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id);
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
void Zone2MapCoordinates(float& x,float& y,uint32 zone);
void Map2ZoneCoordinates(float& x,float& y,uint32 zone);
uint32 GetTalentInspectBitPosInTab(uint32 talentId);
uint32 GetTalentTabInspectBitSize(uint32 talentTabId);
uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls);
template<class T>
class DBCStorage
{
typedef std::list<char*> StringPoolList;
public:
explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { }
~DBCStorage() { Clear(); }
T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; }
uint32 GetNumRows() const { return nCount; }
char const* GetFormat() const { return fmt; }
uint32 GetFieldCount() const { return fieldCount; }
bool Load(char const* fn)
{
DBCFile dbc;
// Check if load was sucessful, only then continue
if(!dbc.Load(fn, fmt))
return false;
fieldCount = dbc.GetCols();
m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable);
m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
// error in dbc file at loading if NULL
return indexTable!=NULL;
}
bool LoadStringsFrom(char const* fn)
{
// DBC must be already loaded using Load
if(!indexTable)
return false;
DBCFile dbc;
// Check if load was successful, only then continue
if(!dbc.Load(fn, fmt))
return false;
m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
return true;
}
void Clear()
{
if (!indexTable)
return;
delete[] ((char*)indexTable);
indexTable = NULL;
delete[] ((char*)m_dataTable);
m_dataTable = NULL;
while(!m_stringPoolList.empty())
{
delete[] m_stringPoolList.front();
m_stringPoolList.pop_front();
}
nCount = 0;
}
private:
uint32 nCount;
uint32 fieldCount;
char const* fmt;
T** indexTable;
T* m_dataTable;
StringPoolList m_stringPoolList;
};
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
//extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; -- accessed using function, no usable index
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
extern DBCStorage <ChrRacesEntry> sChrRacesStore;
extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore;
extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
extern DBCStorage <FactionEntry> sFactionStore;
extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore;
extern DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore;
extern DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore;
extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore;
extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore;
extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore;
extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
extern DBCStorage <ItemEntry> sItemStore;
//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
extern DBCStorage <ItemSetEntry> sItemSetStore;
extern DBCStorage <LockEntry> sLockStore;
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
extern DBCStorage <MapEntry> sMapStore;
extern DBCStorage <QuestSortEntry> sQuestSortStore;
extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
extern DBCStorage <SkillLineEntry> sSkillLineStore;
extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
extern DBCStorage <SpellDurationEntry> sSpellDurationStore;
extern DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore;
extern DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore;
extern DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore;
extern SpellCategoryStore sSpellCategoryStore;
extern PetFamilySpellsStore sPetFamilySpellsStore;
extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
extern DBCStorage <SpellEntry> sSpellStore;
extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
extern DBCStorage <TalentEntry> sTalentStore;
extern DBCStorage <TalentTabEntry> sTalentTabStore;
extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore;
extern DBCStorage <TaxiPathEntry> sTaxiPathStore;
extern TaxiMask sTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
//extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates
extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore;
void LoadDBCStores(std::string dataPath);
// script support functions
MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore();
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore();
MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore();
#endif

View file

@ -0,0 +1,868 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DBCSTRUCTURE_H
#define DBCSTRUCTURE_H
#include "DBCEnums.h"
#include "Platform/Define.h"
#include <map>
#include <set>
#include <vector>
// Structures using to access raw DBC data and required packing to portability
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack(1)
#else
#pragma pack(push,1)
#endif
struct AreaTableEntry
{
uint32 ID; // 0
uint32 mapid; // 1
uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area
uint32 exploreFlag; // 3, main index
uint32 flags; // 4, unknown value but 312 for all cities
// 5-9 unused
int32 area_level; // 10
char* area_name[16]; // 11-26
// 27, string flags, unused
uint32 team; // 28
};
struct AreaTriggerEntry
{
uint32 id; // 0
uint32 mapid; // 1
float x; // 2
float y; // 3
float z; // 4
float radius; // 5
float box_x; // 6 extent x edge
float box_y; // 7 extent y edge
float box_z; // 8 extent z edge
float box_orientation; // 9 extent rotation by about z axis
};
struct BankBagSlotPricesEntry
{
uint32 ID;
uint32 price;
};
struct BattlemasterListEntry
{
uint32 id; // 0
uint32 mapid[3]; // 1-3 mapid
// 4-8 unused
uint32 type; // 9 (3 - BG, 4 - arena)
uint32 minlvl; // 10
uint32 maxlvl; // 11
uint32 maxplayersperteam; // 12
// 13-14 unused
char* name[16]; // 15-30
// 31 string flag, unused
// 32 unused
};
struct CharTitlesEntry
{
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
//uint32 unk1; // 1 flags?
//char* name[16]; // 2-17, unused
// 18 string flag, unused
//char* name2[16]; // 19-34, unused
// 35 string flag, unused
uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
};
struct ChatChannelsEntry
{
uint32 ChannelID; // 0
uint32 flags; // 1
char* pattern[16]; // 3-18
// 19 string flags, unused
//char* name[16]; // 20-35 unused
// 36 string flag, unused
};
struct ChrClassesEntry
{
uint32 ClassID; // 0
// 1-2, unused
uint32 powerType; // 3
// 4, unused
//char* name[16]; // 5-20 unused
// 21 string flag, unused
//char* string1[16]; // 21-36 unused
// 37 string flag, unused
//char* string2[16]; // 38-53 unused
// 54 string flag, unused
// 55, unused
uint32 spellfamily; // 56
// 57, unused
};
struct ChrRacesEntry
{
uint32 RaceID; // 0
// 1 unused
uint32 FactionID; // 2 facton template id
// 3 unused
uint32 model_m; // 4
uint32 model_f; // 5
// 6-7 unused
uint32 TeamID; // 8 (7-Alliance 1-Horde)
// 9-12 unused
uint32 startmovie; // 13 id from CinematicCamera.dbc
char* name[16]; // 14-29 used for DBC language detection/selection
// 30 string flags, unused
//char* string1[16]; // 31-46 used for DBC language detection/selection
// 47 string flags, unused
//char* string2[16]; // 48-63 used for DBC language detection/selection
// 64 string flags, unused
// 65-67 unused
uint32 addon; // 68 (0 - original race, 1 - tbc addon, ...)
};
struct CreatureDisplayInfoEntry
{
uint32 Displayid; // 0
// 1-3,unused
float scale; // 4
// 5-13,unused
};
struct CreatureFamilyEntry
{
uint32 ID; // 0
float minScale; // 1
uint32 minScaleLevel; // 2 0/1
float maxScale; // 3
uint32 maxScaleLevel; // 4 0/60
uint32 skillLine[2]; // 5-6
uint32 petFoodMask; // 7
char* Name[16]; // 8-23
// 24 string flags, unused
// 25 icon, unused
};
struct CreatureSpellDataEntry
{
uint32 ID; // 0
//uint32 spellId[4]; // 1-4 hunter pet learned spell (for later use)
};
struct DurabilityCostsEntry
{
uint32 Itemlvl; // 0
uint32 multiplier[29]; // 1-29
};
struct DurabilityQualityEntry
{
uint32 Id; // 0
float quality_mod; // 1
};
struct EmotesTextEntry
{
uint32 Id;
uint32 textid;
};
struct FactionEntry
{
uint32 ID; // 0
int32 reputationListID; // 1
uint32 BaseRepRaceMask[4]; // 2-5 Base reputation race masks (see enum Races)
uint32 BaseRepClassMask[4]; // 6-9 Base reputation class masks (see enum Classes)
int32 BaseRepValue[4]; // 10-13 Base reputation values
uint32 ReputationFlags[4]; // 14-17 Default flags to apply
uint32 team; // 18 enum Team
char* name[16]; // 19-34
// 35 string flags, unused
//char* description[16]; // 36-51 unused
// 52 string flags, unused
};
struct FactionTemplateEntry
{
uint32 ID; // 0
uint32 faction; // 1
uint32 factionFlags; // 2 specific flags for that faction
uint32 ourMask; // 3 if mask set (see FactionMasks) then faction included in masked team
uint32 friendlyMask; // 4 if mask set (see FactionMasks) then faction friendly to masked team
uint32 hostileMask; // 5 if mask set (see FactionMasks) then faction hostile to masked team
uint32 enemyFaction1; // 6
uint32 enemyFaction2; // 7
uint32 enemyFaction3; // 8
uint32 enemyFaction4; // 9
uint32 friendFaction1; // 10
uint32 friendFaction2; // 11
uint32 friendFaction3; // 12
uint32 friendFaction4; // 13
//------------------------------------------------------- end structure
// helpers
bool IsFriendlyTo(FactionTemplateEntry const& entry) const
{
if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction )
return false;
if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction )
return true;
return (friendlyMask & entry.ourMask) || (ourMask & entry.friendlyMask);
}
bool IsHostileTo(FactionTemplateEntry const& entry) const
{
if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction )
return true;
if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction )
return false;
return (hostileMask & entry.ourMask) != 0;
}
bool IsHostileToPlayers() const { return (hostileMask & FACTION_MASK_PLAYER) !=0; }
bool IsNeutralToAll() const { return hostileMask == 0 && friendlyMask == 0 && enemyFaction1==0 && enemyFaction2==0 && enemyFaction3==0 && enemyFaction4==0; }
bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD)!=0; }
};
struct GemPropertiesEntry
{
uint32 ID;
uint32 spellitemenchantement;
uint32 color;
};
#define GT_MAX_LEVEL 100
struct GtCombatRatingsEntry
{
float ratio;
};
struct GtChanceToMeleeCritBaseEntry
{
float base;
};
struct GtChanceToMeleeCritEntry
{
float ratio;
};
struct GtChanceToSpellCritBaseEntry
{
float base;
};
struct GtChanceToSpellCritEntry
{
float ratio;
};
struct GtOCTRegenHPEntry
{
float ratio;
};
//struct GtOCTRegenMPEntry
//{
// float ratio;
//};
struct GtRegenHPPerSptEntry
{
float ratio;
};
struct GtRegenMPPerSptEntry
{
float ratio;
};
struct ItemEntry
{
uint32 ID;
uint32 DisplayId;
uint32 InventoryType;
uint32 Sheath;
};
struct ItemDisplayInfoEntry
{
uint32 ID;
uint32 randomPropertyChance;
};
//struct ItemCondExtCostsEntry
//{
// uint32 ID;
// uint32 condExtendedCost; // ItemPrototype::CondExtendedCost
// uint32 itemextendedcostentry; // ItemPrototype::ExtendedCost
// uint32 arenaseason; // arena season number(1-4)
//};
struct ItemExtendedCostEntry
{
uint32 ID; // 0 extended-cost entry id
uint32 reqhonorpoints; // 1 required honor points
uint32 reqarenapoints; // 2 required arena points
uint32 reqitem[5]; // 3-7 required item id
uint32 reqitemcount[5]; // 8-12 required count of 1st item
uint32 reqpersonalarenarating; // 13 required personal arena rating
};
struct ItemRandomPropertiesEntry
{
uint32 ID; // 0
//char* internalName // 1 unused
uint32 enchant_id[3]; // 2-4
// 5-6 unused, 0 only values, reserved for additional enchantments?
//char* nameSuffix[16] // 7-22, unused
// 23 nameSufix flags, unused
};
struct ItemRandomSuffixEntry
{
uint32 ID; // 0
//char* name[16] // 1-16 unused
// 17, name flags, unused
// 18 unused
uint32 enchant_id[3]; // 19-21
uint32 prefix[3]; // 22-24
};
struct ItemSetEntry
{
//uint32 id // 0 item set ID
char* name[16]; // 1-16
// 17 string flags, unused
// 18-28 items from set, but not have all items listed, use ItemPrototype::ItemSet instead
// 29-34 unused
uint32 spells[8]; // 35-42
uint32 items_to_triggerspell[8]; // 43-50
uint32 required_skill_id; // 51
uint32 required_skill_value; // 52
};
struct LockEntry
{
uint32 ID; // 0
uint32 keytype[5]; // 1-5
// 6-8, not used
uint32 key[5]; // 9-13
// 14-16, not used
uint32 requiredminingskill; // 17
uint32 requiredlockskill; // 18
// 19-32, not used
};
struct MailTemplateEntry
{
uint32 ID; // 0
//char* subject[16]; // 1-16
// 17 name flags, unused
//char* content[16]; // 18-33
};
struct MapEntry
{
uint32 MapID; // 0
//char* internalname; // 1 unused
uint32 map_type; // 2
// 3 unused
char* name[16]; // 4-19
// 20 name flags, unused
// 21-23 unused (something PvPZone related - levels?)
// 24-26
uint32 linked_zone; // 27 common zone for instance and continent map
//char* hordeIntro // 28-43 text for PvP Zones
// 44 intro text flags
//char* allianceIntro // 45-60 text for PvP Zones
// 46 intro text flags
// 47-61 not used
uint32 multimap_id; // 62
// 63-65 not used
//chat* unknownText1 // 66-81 unknown empty text fields, possible normal Intro text.
// 82 text flags
//chat* heroicIntroText // 83-98 heroic mode requirement text
// 99 text flags
//chat* unknownText2 // 100-115 unknown empty text fields
// 116 text flags
int32 parent_map; // 117 map_id of parent map
//float start_x // 118 enter x coordinate (if exist single entry)
//float start_y // 119 enter y coordinate (if exist single entry)
uint32 resetTimeRaid; // 120
uint32 resetTimeHeroic; // 121
// 122-123
uint32 addon; // 124 (0-original maps,1-tbc addon)
// Helpers
uint32 Expansion() const { return addon; }
bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
bool IsRaid() const { return map_type == MAP_RAID; }
bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }
bool IsBattleArena() const { return map_type == MAP_ARENA; }
bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
bool SupportsHeroicMode() const { return resetTimeHeroic && !resetTimeRaid; }
bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; }
bool IsMountAllowed() const
{
return !IsDungeon() ||
MapID==568 || MapID==309 || MapID==209 || MapID==534 ||
MapID==560 || MapID==509 || MapID==269;
}
};
struct QuestSortEntry
{
uint32 id; // 0, sort id
//char* name[16]; // 1-16, unused
// 17 name flags, unused
};
struct RandomPropertiesPointsEntry
{
//uint32 Id; // 0 hidden key
uint32 itemLevel; // 1
uint32 EpicPropertiesPoints[5]; // 2-6
uint32 RarePropertiesPoints[5]; // 7-11
uint32 UncommonPropertiesPoints[5]; // 12-16
};
//struct SkillLineCategoryEntry{
// uint32 id; // 0 hidden key
// char* name[16]; // 1 - 17 Category name
// // 18 string flag
// uint32 displayOrder; // Display order in character tab
//};
//struct SkillRaceClassInfoEntry{
// uint32 id; // 0
// uint32 skillId; // 1 present some refrences to unknown skill
// uint32 raceMask; // 2
// uint32 classMask; // 3
// uint32 flags; // 4 mask for some thing
// uint32 reqLevel; // 5
// uint32 skillTierId; // 6
// uint32 skillCostID; // 7
//};
//struct SkillTiersEntry{
// uint32 id; // 0
// uint32 skillValue[16]; // 1-17 unknown possibly add value on learn?
// uint32 maxSkillValue[16]; // Max value for rank
//};
struct SkillLineEntry
{
uint32 id; // 0
uint32 categoryId; // 1 (index from SkillLineCategory.dbc)
//uint32 skillCostID; // 2 not used
char* name[16]; // 3-18
// 19 string flags, not used
//char* description[16]; // 20-35, not used
// 36 string flags, not used
uint32 spellIcon; // 37
};
struct SkillLineAbilityEntry
{
uint32 id; // 0, INDEX
uint32 skillId; // 1
uint32 spellId; // 2
uint32 racemask; // 3
uint32 classmask; // 4
//uint32 racemaskNot; // 5 always 0 in 2.4.2
//uint32 classmaskNot; // 6 always 0 in 2.4.2
uint32 req_skill_value; // 7 for trade skill.not for training.
uint32 forward_spellid; // 8
uint32 learnOnGetSkill; // 9 can be 1 or 2 for spells learned on get skill
uint32 max_value; // 10
uint32 min_value; // 11
// 12-13, unknown, always 0
uint32 reqtrainpoints; // 14
};
struct SoundEntriesEntry
{
uint32 Id; // 0, sound id
//uint32 Type; // 1, sound type (10 generally for creature, etc)
//char* InternalName; // 2, internal name, for use in lookup command for example
//char* FileName[10]; // 3-12, file names
//uint32 Unk13[10]; // 13-22, linked with file names?
//char* Path; // 23
// 24-28, unknown
};
struct SpellEntry
{
uint32 Id; // 0 normally counted from 0 field (but some tools start counting from 1, check this before tool use for data view!)
uint32 Category; // 1
//uint32 castUI // 2 not used
uint32 Dispel; // 3
uint32 Mechanic; // 4
uint32 Attributes; // 5
uint32 AttributesEx; // 6
uint32 AttributesEx2; // 7
uint32 AttributesEx3; // 8
uint32 AttributesEx4; // 9
uint32 AttributesEx5; // 10
//uint32 AttributesEx6; // 11 not used
uint32 Stances; // 12
uint32 StancesNot; // 13
uint32 Targets; // 14
uint32 TargetCreatureType; // 15
uint32 RequiresSpellFocus; // 16
uint32 FacingCasterFlags; // 17
uint32 CasterAuraState; // 18
uint32 TargetAuraState; // 19
uint32 CasterAuraStateNot; // 20
uint32 TargetAuraStateNot; // 21
uint32 CastingTimeIndex; // 22
uint32 RecoveryTime; // 23
uint32 CategoryRecoveryTime; // 24
uint32 InterruptFlags; // 25
uint32 AuraInterruptFlags; // 26
uint32 ChannelInterruptFlags; // 27
uint32 procFlags; // 28
uint32 procChance; // 29
uint32 procCharges; // 30
uint32 maxLevel; // 31
uint32 baseLevel; // 32
uint32 spellLevel; // 33
uint32 DurationIndex; // 34
uint32 powerType; // 35
uint32 manaCost; // 36
uint32 manaCostPerlevel; // 37
uint32 manaPerSecond; // 38
uint32 manaPerSecondPerLevel; // 39
uint32 rangeIndex; // 40
float speed; // 41
//uint32 modalNextSpell; // 42
uint32 StackAmount; // 43
uint32 Totem[2]; // 44-45
int32 Reagent[8]; // 46-53
uint32 ReagentCount[8]; // 54-61
int32 EquippedItemClass; // 62 (value)
int32 EquippedItemSubClassMask; // 63 (mask)
int32 EquippedItemInventoryTypeMask; // 64 (mask)
uint32 Effect[3]; // 65-67
int32 EffectDieSides[3]; // 68-70
uint32 EffectBaseDice[3]; // 71-73
float EffectDicePerLevel[3]; // 74-76
float EffectRealPointsPerLevel[3]; // 77-79
int32 EffectBasePoints[3]; // 80-82 (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
uint32 EffectMechanic[3]; // 83-85
uint32 EffectImplicitTargetA[3]; // 86-88
uint32 EffectImplicitTargetB[3]; // 89-91
uint32 EffectRadiusIndex[3]; // 92-94 - spellradius.dbc
uint32 EffectApplyAuraName[3]; // 95-97
uint32 EffectAmplitude[3]; // 98-100
float EffectMultipleValue[3]; // 101-103
uint32 EffectChainTarget[3]; // 104-106
uint32 EffectItemType[3]; // 107-109
int32 EffectMiscValue[3]; // 110-112
int32 EffectMiscValueB[3]; // 113-115
uint32 EffectTriggerSpell[3]; // 116-118
float EffectPointsPerComboPoint[3]; // 119-121
uint32 SpellVisual; // 122
// 123 not used
uint32 SpellIconID; // 124
uint32 activeIconID; // 125
//uint32 spellPriority; // 126
char* SpellName[16]; // 127-142
//uint32 SpellNameFlag; // 143
char* Rank[16]; // 144-159
//uint32 RankFlags; // 160
//char* Description[16]; // 161-176 not used
//uint32 DescriptionFlags; // 177 not used
//char* ToolTip[16]; // 178-193 not used
//uint32 ToolTipFlags; // 194 not used
uint32 ManaCostPercentage; // 195
uint32 StartRecoveryCategory; // 196
uint32 StartRecoveryTime; // 197
uint32 MaxTargetLevel; // 198
uint32 SpellFamilyName; // 199
uint64 SpellFamilyFlags; // 200+201
uint32 MaxAffectedTargets; // 202
uint32 DmgClass; // 203 defenseType
uint32 PreventionType; // 204
//uint32 StanceBarOrder; // 205 not used
float DmgMultiplier[3]; // 206-208
//uint32 MinFactionId; // 209 not used, and 0 in 2.4.2
//uint32 MinReputation; // 210 not used, and 0 in 2.4.2
//uint32 RequiredAuraVision; // 211 not used
uint32 TotemCategory[2]; // 212-213
uint32 AreaId; // 214
uint32 SchoolMask; // 215 school mask
private:
// prevent creating custom entries (copy data from original in fact)
SpellEntry(SpellEntry const&); // DON'T must have implementation
};
typedef std::set<uint32> SpellCategorySet;
typedef std::map<uint32,SpellCategorySet > SpellCategoryStore;
typedef std::set<uint32> PetFamilySpellsSet;
typedef std::map<uint32,PetFamilySpellsSet > PetFamilySpellsStore;
struct SpellCastTimesEntry
{
uint32 ID; // 0
int32 CastTime; // 1
//float CastTimePerLevel; // 2 unsure / per skill?
//int32 MinCastTime; // 3 unsure
};
struct SpellFocusObjectEntry
{
uint32 ID; // 0
//char* Name[16]; // 1-15 unused
// 16 string flags, unused
};
// stored in SQL table
struct SpellThreatEntry
{
uint32 spellId;
int32 threat;
};
struct SpellRadiusEntry
{
uint32 ID;
float Radius;
float Radius2;
};
struct SpellRangeEntry
{
uint32 ID;
float minRange;
float maxRange;
};
struct SpellShapeshiftEntry
{
uint32 ID; // 0
//uint32 buttonPosition; // 1 unused
//char* Name[16]; // 2-17 unused
//uint32 NameFlags; // 18 unused
uint32 flags1; // 19
int32 creatureType; // 20 <=0 humanoid, other normal creature types
//uint32 unk1; // 21 unused
uint32 attackSpeed; // 22
//uint32 modelID; // 23 unused, alliance modelid (where horde case?)
//uint32 unk2; // 24 unused
//uint32 unk3; // 25 unused
//uint32 unk4; // 26 unused
//uint32 unk5; // 27 unused
//uint32 unk6; // 28 unused
//uint32 unk7; // 29 unused
//uint32 unk8; // 30 unused
//uint32 unk9; // 31 unused
//uint32 unk10; // 32 unused
//uint32 unk11; // 33 unused
//uint32 unk12; // 34 unused
};
struct SpellDurationEntry
{
uint32 ID;
int32 Duration[3];
};
struct SpellItemEnchantmentEntry
{
uint32 ID; // 0
uint32 type[3]; // 1-3
uint32 amount[3]; // 4-6
//uint32 amount2[3] // 7-9 always same as similar `amount` value
uint32 spellid[3]; // 10-12
char* description[16]; // 13-29
// 30 description flags
uint32 aura_id; // 31
uint32 slot; // 32
uint32 GemID; // 33
uint32 EnchantmentCondition; // 34
};
struct SpellItemEnchantmentConditionEntry
{
uint32 ID;
uint8 Color[5];
uint8 Comparator[5];
uint8 CompareColor[5];
uint32 Value[5];
};
struct StableSlotPricesEntry
{
uint32 Slot;
uint32 Price;
};
struct TalentEntry
{
uint32 TalentID; // 0
uint32 TalentTab; // 1 index in TalentTab.dbc (TalentTabEntry)
uint32 Row; // 2
uint32 Col; // 3
uint32 RankID[5]; // 4-8
// 9-12 not used, always 0, maybe not used high ranks
uint32 DependsOn; // 13 index in Talent.dbc (TalentEntry)
// 14-15 not used
uint32 DependsOnRank; // 16
// 17-19 not used
uint32 DependsOnSpell; // 20 req.spell
};
struct TalentTabEntry
{
uint32 TalentTabID; // 0
//char* name[16]; // 1-16, unused
//uint32 nameFlags; // 17, unused
//unit32 spellicon; // 18
// 19 not used
uint32 ClassMask; // 20
uint32 tabpage; // 21
//char* internalname; // 22
};
struct TaxiNodesEntry
{
uint32 ID; // 0
uint32 map_id; // 1
float x; // 2
float y; // 3
float z; // 4
//char* name[16]; // 5-21
// 22 string flags, unused
uint32 horde_mount_type; // 23
uint32 alliance_mount_type; // 24
};
struct TaxiPathEntry
{
uint32 ID;
uint32 from;
uint32 to;
uint32 price;
};
struct TaxiPathNodeEntry
{
uint32 path;
uint32 index;
uint32 mapid;
float x;
float y;
float z;
uint32 actionFlag;
uint32 delay;
};
struct TotemCategoryEntry
{
uint32 ID; // 0
//char* name[16]; // 1-16
// 17 string flags, unused
uint32 categoryType; // 18 (one for specialization)
uint32 categoryMask; // 19 (compatibility mask for same type: different for totems, compatible from high to low for rods)
};
struct WorldMapAreaEntry
{
//uint32 ID; // 0
uint32 map_id; // 1
uint32 area_id; // 2 index (continent 0 areas ignored)
//char* internal_name // 3
float y1; // 4
float y2; // 5
float x1; // 6
float x2; // 7
int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally)
};
struct WorldSafeLocsEntry
{
uint32 ID; // 0
uint32 map_id; // 1
float x; // 2
float y; // 3
float z; // 4
//char* name[16] // 5-20 name, unused
// 21 name flags, unused
};
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack()
#else
#pragma pack(pop)
#endif
// Structures not used for casting to loaded DBC data and not required then packing
struct TalentSpellPos
{
TalentSpellPos() : talent_id(0), rank(0) {}
TalentSpellPos(uint16 _talent_id, uint8 _rank) : talent_id(_talent_id), rank(_rank) {}
uint16 talent_id;
uint8 rank;
};
typedef std::map<uint32,TalentSpellPos> TalentSpellPosMap;
struct TaxiPathBySourceAndDestination
{
TaxiPathBySourceAndDestination() : ID(0),price(0) {}
TaxiPathBySourceAndDestination(uint32 _id,uint32 _price) : ID(_id),price(_price) {}
uint32 ID;
uint32 price;
};
typedef std::map<uint32,TaxiPathBySourceAndDestination> TaxiPathSetForSource;
typedef std::map<uint32,TaxiPathSetForSource> TaxiPathSetBySource;
struct TaxiPathNode
{
TaxiPathNode() : mapid(0), x(0),y(0),z(0),actionFlag(0),delay(0) {}
TaxiPathNode(uint32 _mapid, float _x, float _y, float _z, uint32 _actionFlag, uint32 _delay) : mapid(_mapid), x(_x),y(_y),z(_z),actionFlag(_actionFlag),delay(_delay) {}
uint32 mapid;
float x;
float y;
float z;
uint32 actionFlag;
uint32 delay;
};
typedef std::vector<TaxiPathNode> TaxiPathNodeList;
typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
#define TaxiMaskSize 16
typedef uint32 TaxiMask[TaxiMaskSize];
#endif

View file

@ -0,0 +1,78 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxx";
const char AreaTriggerEntryfmt[]="niffffffff";
const char BankBagSlotPricesEntryfmt[]="ni";
const char BattlemasterListEntryfmt[]="niiixxxxxiiiixxssssssssssssssssxx";
const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store)
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxx";
const char CreatureFamilyfmt[]="nfifiiiissssssssssssssssxx";
const char CreatureSpellDatafmt[]="nxxxxxxxx";
const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
const char DurabilityQualityfmt[]="nf";
const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx";
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiissssssssssssssssxxxxxxxxxxxxxxxxxx";
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
const char GemPropertiesEntryfmt[]="nixxi";
const char GtCombatRatingsfmt[]="f";
const char GtChanceToMeleeCritBasefmt[]="f";
const char GtChanceToMeleeCritfmt[]="f";
const char GtChanceToSpellCritBasefmt[]="f";
const char GtChanceToSpellCritfmt[]="f";
const char GtOCTRegenHPfmt[]="f";
//const char GtOCTRegenMPfmt[]="f";
const char GtRegenHPPerSptfmt[]="f";
const char GtRegenMPPerSptfmt[]="f";
const char Itemfmt[]="niii";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//const char ItemCondExtCostsEntryfmt[]="xiii";
const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiii";
const char ItemRandomPropertiesfmt[]="nxiiixxxxxxxxxxxxxxxxxxx";
const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiii";
const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii";
const char LockEntryfmt[]="niiiiixxxiiiiixxxiixxxxxxxxxxxxxx";
const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char MapEntryfmt[]="nxixssssssssssssssssxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxiixxi";
const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx";
const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii";
const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxi";
const char SkillLineAbilityfmt[]="niiiixxiiiiixxi";
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellCastTimefmt[]="nixx";
const char SpellDurationfmt[]="niii";
const char SpellEntryfmt[]="nixiiiiiiiixiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffixiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiixfffxxxiiii";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="niiiiiixxxiiissssssssssssssssxiiii";
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
const char SpellRadiusfmt[]="nfxf";
const char SpellRangefmt[]="nffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx";
const char StableSlotPricesfmt[] = "ni";
const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxi";
const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiix";
const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii";
const char TaxiPathEntryfmt[]="niii";
const char TaxiPathNodeEntryfmt[]="diiifffiixx";
const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
const char WorldMapAreaEntryfmt[]="xinxffffi";
const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx";

View file

@ -0,0 +1,171 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "DatabaseEnv.h"
#include "Config/ConfigEnv.h"
#include <ctime>
#include <iostream>
#include <fstream>
Database::~Database()
{
/*Delete objects*/
}
bool Database::Initialize(const char *)
{
// Enable logging of SQL commands (usally only GM commands)
// (See method: PExecuteLog)
m_logSQL = sConfig.GetBoolDefault("LogSQL", false);
m_logsDir = sConfig.GetStringDefault("LogsDir","");
if(!m_logsDir.empty())
{
if((m_logsDir.at(m_logsDir.length()-1)!='/') && (m_logsDir.at(m_logsDir.length()-1)!='\\'))
m_logsDir.append("/");
}
return true;
}
void Database::ThreadStart()
{
}
void Database::ThreadEnd()
{
}
void Database::escape_string(std::string& str)
{
if(str.empty())
return;
char* buf = new char[str.size()*2+1];
escape_string(buf,str.c_str(),str.size());
str = buf;
delete[] buf;
}
bool Database::PExecuteLog(const char * format,...)
{
if (!format)
return false;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
if( m_logSQL )
{
time_t curr;
tm local;
time(&curr); // get current time_t value
local=*(localtime(&curr)); // dereference and assign
char fName[128];
sprintf( fName, "%04d-%02d-%02d_logSQL.sql", local.tm_year+1900, local.tm_mon+1, local.tm_mday );
FILE* log_file;
std::string logsDir_fname = m_logsDir+fName;
log_file = fopen(logsDir_fname.c_str(), "a");
if (log_file)
{
fprintf(log_file, "%s;\n", szQuery);
fclose(log_file);
}
else
{
// The file could not be opened
sLog.outError("SQL-Logging is disabled - Log file for the SQL commands could not be openend: %s",fName);
}
}
return Execute(szQuery);
}
void Database::SetResultQueue(SqlResultQueue * queue)
{
m_queryQueues[ZThread::ThreadImpl::current()] = queue;
}
QueryResult* Database::PQuery(const char *format,...)
{
if(!format) return NULL;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return Query(szQuery);
}
bool Database::PExecute(const char * format,...)
{
if (!format)
return false;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return Execute(szQuery);
}
bool Database::DirectPExecute(const char * format,...)
{
if (!format)
return false;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return DirectExecute(szQuery);
}

View file

@ -0,0 +1,113 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DATABASE_H
#define DATABASE_H
#include "zthread/Thread.h"
#include "../src/zthread/ThreadImpl.h"
#include "Utilities/HashMap.h"
#include "Database/SqlDelayThread.h"
class SqlTransaction;
class SqlResultQueue;
class SqlQueryHolder;
typedef HM_NAMESPACE::hash_map<ZThread::ThreadImpl*, SqlTransaction*> TransactionQueues;
typedef HM_NAMESPACE::hash_map<ZThread::ThreadImpl*, SqlResultQueue*> QueryQueues;
#define MAX_QUERY_LEN 1024
class MANGOS_DLL_SPEC Database
{
protected:
Database() : m_threadBody(NULL), m_delayThread(NULL) {};
TransactionQueues m_tranQueues; ///< Transaction queues from diff. threads
QueryQueues m_queryQueues; ///< Query queues from diff threads
SqlDelayThread* m_threadBody; ///< Pointer to delay sql executer
ZThread::Thread* m_delayThread; ///< Pointer to executer thread
public:
virtual ~Database();
virtual bool Initialize(const char *infoString);
virtual void InitDelayThread() = 0;
virtual void HaltDelayThread() = 0;
virtual QueryResult* Query(const char *sql) = 0;
QueryResult* PQuery(const char *format,...) ATTR_PRINTF(2,3);
/// Async queries and query holders, implemented in DatabaseImpl.h
template<class Class>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql);
template<class Class, typename ParamType1>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql);
template<typename ParamType1>
bool AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql);
template<class Class>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5);
template<class Class, typename ParamType1>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
template<typename ParamType1>
bool AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
template<class Class>
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder);
template<class Class, typename ParamType1>
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1);
virtual bool Execute(const char *sql) = 0;
bool PExecute(const char *format,...) ATTR_PRINTF(2,3);
virtual bool DirectExecute(const char* sql) = 0;
bool DirectPExecute(const char *format,...) ATTR_PRINTF(2,3);
// Writes SQL commands to a LOG file (see mangosd.conf "LogSQL")
bool PExecuteLog(const char *format,...) ATTR_PRINTF(2,3);
virtual bool BeginTransaction() // nothing do if DB not support transactions
{
return true;
}
virtual bool CommitTransaction() // nothing do if DB not support transactions
{
return true;
}
virtual bool RollbackTransaction() // can't rollback without transaction support
{
return false;
}
virtual operator bool () const = 0;
virtual unsigned long escape_string(char *to, const char *from, unsigned long length) { strncpy(to,from,length); return length; }
void escape_string(std::string& str);
// must be called before first query in thread (one time for thread using one from existed Database objects)
virtual void ThreadStart();
// must be called before finish thread run (one time for thread using one from existed Database objects)
virtual void ThreadEnd();
// sets the result queue of the current thread, be careful what thread you call this from
void SetResultQueue(SqlResultQueue * queue);
private:
bool m_logSQL;
std::string m_logsDir;
};
#endif

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(DATABASEENV_H)
#define DATABASEENV_H
#include "Common.h"
#include "Log.h"
#include "Errors.h"
#include "Database/DBCStores.h"
#include "Database/Field.h"
#include "Database/QueryResult.h"
#ifdef DO_POSTGRESQL
#include "Database/QueryResultPostgre.h"
#include "Database/Database.h"
#include "Database/DatabasePostgre.h"
typedef DatabasePostgre DatabaseType;
#define _LIKE_ "ILIKE"
#define _TABLE_SIM_ "\""
#define _CONCAT3_(A,B,C) "( " A " || " B " || " C " )"
#else
#include "Database/QueryResultMysql.h"
#include "Database/QueryResultSqlite.h"
#include "Database/Database.h"
#include "Database/DatabaseMysql.h"
#include "Database/DatabaseSqlite.h"
typedef DatabaseMysql DatabaseType;
#define _LIKE_ "LIKE"
#define _TABLE_SIM_ "`"
#define _CONCAT3_(A,B,C) "CONCAT( " A " , " B " , " C " )"
#endif
extern DatabaseType WorldDatabase;
extern DatabaseType CharacterDatabase;
extern DatabaseType loginDatabase;
#endif

View file

@ -0,0 +1,145 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Database/Database.h"
#include "Database/SqlOperations.h"
/// Function body definitions for the template function members of the Database class
template<class Class>
bool
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql)
{
if (!sql) return false;
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
if (itr == m_queryQueues.end()) return false;
m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback<Class>(object, method), itr->second));
return true;
}
template<class Class, typename ParamType1>
bool
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql)
{
if (!sql) return false;
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
if (itr == m_queryQueues.end()) return false;
m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback<Class, ParamType1>(object, method, (QueryResult*)NULL, param1), itr->second));
return true;
}
template<typename ParamType1>
bool
Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql)
{
if (!sql) return false;
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
if (itr == m_queryQueues.end()) return false;
m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback<ParamType1>(method, (QueryResult*)NULL, param1), itr->second));
return true;
}
template<class Class>
bool
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...)
{
if(!format) return false;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return AsyncQuery(object, method, szQuery);
}
template<class Class, typename ParamType1>
bool
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...)
{
if(!format) return false;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return AsyncQuery(object, method, param1, szQuery);
}
template<typename ParamType1>
bool
Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...)
{
if(!format) return false;
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return AsyncQuery(method, param1, szQuery);
}
template<class Class>
bool
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder)
{
if (!holder) return false;
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
if (itr == m_queryQueues.end()) return false;
holder->Execute(new MaNGOS::QueryCallback<Class, SqlQueryHolder*>(object, method, (QueryResult*)NULL, holder), m_threadBody, itr->second);
return true;
}
template<class Class, typename ParamType1>
bool
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1)
{
if (!holder) return false;
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
if (itr == m_queryQueues.end()) return false;
holder->Execute(new MaNGOS::QueryCallback<Class, SqlQueryHolder*, ParamType1>(object, method, (QueryResult*)NULL, holder, param1), m_threadBody, itr->second);
return true;
}

View file

@ -0,0 +1,408 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#include "Util.h"
#include "Policies/SingletonImp.h"
#include "Platform/Define.h"
#include "../src/zthread/ThreadImpl.h"
#include "DatabaseEnv.h"
#include "Database/MySQLDelayThread.h"
#include "Database/SqlOperations.h"
#include "Timer.h"
void DatabaseMysql::ThreadStart()
{
mysql_thread_init();
}
void DatabaseMysql::ThreadEnd()
{
mysql_thread_end();
}
size_t DatabaseMysql::db_count = 0;
DatabaseMysql::DatabaseMysql() : Database(), mMysql(0)
{
// before first connection
if( db_count++ == 0 )
{
// Mysql Library Init
mysql_library_init(-1, NULL, NULL);
if (!mysql_thread_safe())
{
sLog.outError("FATAL ERROR: Used MySQL library isn't thread-safe.");
exit(1);
}
}
}
DatabaseMysql::~DatabaseMysql()
{
if (m_delayThread)
HaltDelayThread();
if (mMysql)
mysql_close(mMysql);
//Free Mysql library pointers for last ~DB
if(--db_count == 0)
mysql_library_end();
}
bool DatabaseMysql::Initialize(const char *infoString)
{
if(!Database::Initialize(infoString))
return false;
tranThread = NULL;
MYSQL *mysqlInit;
mysqlInit = mysql_init(NULL);
if (!mysqlInit)
{
sLog.outError( "Could not initialize Mysql connection" );
return false;
}
InitDelayThread();
Tokens tokens = StrSplit(infoString, ";");
Tokens::iterator iter;
std::string host, port_or_socket, user, password, database;
int port;
char const* unix_socket;
iter = tokens.begin();
if(iter != tokens.end())
host = *iter++;
if(iter != tokens.end())
port_or_socket = *iter++;
if(iter != tokens.end())
user = *iter++;
if(iter != tokens.end())
password = *iter++;
if(iter != tokens.end())
database = *iter++;
mysql_options(mysqlInit,MYSQL_SET_CHARSET_NAME,"utf8");
#ifdef WIN32
if(host==".") // named pipe use option (Windows)
{
unsigned int opt = MYSQL_PROTOCOL_PIPE;
mysql_options(mysqlInit,MYSQL_OPT_PROTOCOL,(char const*)&opt);
port = 0;
unix_socket = 0;
}
else // generic case
{
port = atoi(port_or_socket.c_str());
unix_socket = 0;
}
#else
if(host==".") // socket use option (Unix/Linux)
{
unsigned int opt = MYSQL_PROTOCOL_SOCKET;
mysql_options(mysqlInit,MYSQL_OPT_PROTOCOL,(char const*)&opt);
host = "localhost";
port = 0;
unix_socket = port_or_socket.c_str();
}
else // generic case
{
port = atoi(port_or_socket.c_str());
unix_socket = 0;
}
#endif
mMysql = mysql_real_connect(mysqlInit, host.c_str(), user.c_str(),
password.c_str(), database.c_str(), port, unix_socket, 0);
if (mMysql)
{
sLog.outDetail( "Connected to MySQL database at %s",
host.c_str());
sLog.outString( "MySQL client library: %s", mysql_get_client_info());
sLog.outString( "MySQL server ver: %s ", mysql_get_server_info( mMysql));
/*----------SET AUTOCOMMIT ON---------*/
// It seems mysql 5.0.x have enabled this feature
// by default. In crash case you can lose data!!!
// So better to turn this off
// ---
// This is wrong since mangos use transactions,
// autocommit is turned of during it.
// Setting it to on makes atomic updates work
if (!mysql_autocommit(mMysql, 1))
sLog.outDetail("AUTOCOMMIT SUCCESSFULLY SET TO 1");
else
sLog.outDetail("AUTOCOMMIT NOT SET TO 1");
/*-------------------------------------*/
// set connection properties to UTF8 to properly handle locales for different
// server configs - core sends data in UTF8, so MySQL must expect UTF8 too
PExecute("SET NAMES `utf8`");
PExecute("SET CHARACTER SET `utf8`");
return true;
}
else
{
sLog.outError( "Could not connect to MySQL database at %s: %s\n",
host.c_str(),mysql_error(mysqlInit));
mysql_close(mysqlInit);
return false;
}
}
QueryResult* DatabaseMysql::Query(const char *sql)
{
if (!mMysql)
return 0;
MYSQL_RES *result = 0;
uint64 rowCount = 0;
uint32 fieldCount = 0;
{
// guarded block for thread-safe mySQL request
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
#ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
if(mysql_query(mMysql, sql))
{
sLog.outErrorDb( "SQL: %s", sql );
sLog.outErrorDb("query ERROR: %s", mysql_error(mMysql));
return NULL;
}
else
{
#ifdef MANGOS_DEBUG
sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql );
#endif
}
result = mysql_store_result(mMysql);
rowCount = mysql_affected_rows(mMysql);
fieldCount = mysql_field_count(mMysql);
// end guarded block
}
if (!result )
return NULL;
if (!rowCount)
{
mysql_free_result(result);
return NULL;
}
QueryResultMysql *queryResult = new QueryResultMysql(result, rowCount, fieldCount);
queryResult->NextRow();
return queryResult;
}
bool DatabaseMysql::Execute(const char *sql)
{
if (!mMysql)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody) return DirectExecute(sql);
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{ // Statement for transaction
i->second->DelayExecute(sql);
}
else
{
// Simple sql statement
m_threadBody->Delay(new SqlStatement(sql));
}
return true;
}
bool DatabaseMysql::DirectExecute(const char* sql)
{
if (!mMysql)
return false;
{
// guarded block for thread-safe mySQL request
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
#ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
if(mysql_query(mMysql, sql))
{
sLog.outErrorDb("SQL: %s", sql);
sLog.outErrorDb("SQL ERROR: %s", mysql_error(mMysql));
return false;
}
else
{
#ifdef MANGOS_DEBUG
sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql );
#endif
}
// end guarded block
}
return true;
}
bool DatabaseMysql::_TransactionCmd(const char *sql)
{
if (mysql_query(mMysql, sql))
{
sLog.outError("SQL: %s", sql);
sLog.outError("SQL ERROR: %s", mysql_error(mMysql));
return false;
}
else
{
DEBUG_LOG("SQL: %s", sql);
}
return true;
}
bool DatabaseMysql::BeginTransaction()
{
if (!mMysql)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
if (tranThread==ZThread::ThreadImpl::current())
return false; // huh? this thread already started transaction
mMutex.acquire();
if (!_TransactionCmd("START TRANSACTION"))
{
mMutex.release(); // can't start transaction
return false;
}
return true; // transaction started
}
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
// If for thread exists queue and also contains transaction
// delete that transaction (not allow trans in trans)
delete i->second;
m_tranQueues[tranThread] = new SqlTransaction();
return true;
}
bool DatabaseMysql::CommitTransaction()
{
if (!mMysql)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
if (tranThread!=ZThread::ThreadImpl::current())
return false;
bool _res = _TransactionCmd("COMMIT");
tranThread = NULL;
mMutex.release();
return _res;
}
tranThread = ZThread::ThreadImpl::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
m_threadBody->Delay(i->second);
i->second = NULL;
return true;
}
else
return false;
}
bool DatabaseMysql::RollbackTransaction()
{
if (!mMysql)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
if (tranThread!=ZThread::ThreadImpl::current())
return false;
bool _res = _TransactionCmd("ROLLBACK");
tranThread = NULL;
mMutex.release();
return _res;
}
tranThread = ZThread::ThreadImpl::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
delete i->second;
i->second = NULL;
}
return true;
}
unsigned long DatabaseMysql::escape_string(char *to, const char *from, unsigned long length)
{
if (!mMysql || !to || !from || !length)
return 0;
return(mysql_real_escape_string(mMysql, to, from, length));
}
void DatabaseMysql::InitDelayThread()
{
assert(!m_delayThread);
//New delay thread for delay execute
m_delayThread = new ZThread::Thread(m_threadBody = new MySQLDelayThread(this));
}
void DatabaseMysql::HaltDelayThread()
{
if (!m_threadBody || !m_delayThread) return;
m_threadBody->Stop(); //Stop event
m_delayThread->wait(); //Wait for flush to DB
delete m_delayThread; //This also deletes m_threadBody
m_delayThread = NULL;
m_threadBody = NULL;
}
#endif

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#ifndef _DATABASEMYSQL_H
#define _DATABASEMYSQL_H
#include "Database.h"
#include "Policies/Singleton.h"
#include "zthread/FastMutex.h"
#ifdef WIN32
#define FD_SETSIZE 1024
#include <winsock2.h>
#include <mysql/mysql.h>
#else
#include <mysql.h>
#endif
class MANGOS_DLL_SPEC DatabaseMysql : public Database
{
friend class MaNGOS::OperatorNew<DatabaseMysql>;
public:
DatabaseMysql();
~DatabaseMysql();
//! Initializes Mysql and connects to a server.
/*! infoString should be formated like hostname;username;password;database. */
bool Initialize(const char *infoString);
void InitDelayThread();
void HaltDelayThread();
QueryResult* Query(const char *sql);
bool Execute(const char *sql);
bool DirectExecute(const char* sql);
bool BeginTransaction();
bool CommitTransaction();
bool RollbackTransaction();
operator bool () const { return mMysql != NULL; }
unsigned long escape_string(char *to, const char *from, unsigned long length);
using Database::escape_string;
// must be call before first query in thread
void ThreadStart();
// must be call before finish thread run
void ThreadEnd();
private:
ZThread::FastMutex mMutex;
ZThread::ThreadImpl* tranThread;
MYSQL *mMysql;
static size_t db_count;
bool _TransactionCmd(const char *sql);
};
#endif
#endif

View file

@ -0,0 +1,345 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef DO_POSTGRESQL
#include "Util.h"
#include "Policies/SingletonImp.h"
#include "Platform/Define.h"
#include "../src/zthread/ThreadImpl.h"
#include "DatabaseEnv.h"
#include "Database/PGSQLDelayThread.h"
#include "Database/SqlOperations.h"
#include "Timer.h"
void DatabasePostgre::ThreadStart()
{
}
void DatabasePostgre::ThreadEnd()
{
}
size_t DatabasePostgre::db_count = 0;
DatabasePostgre::DatabasePostgre() : Database(), mPGconn(NULL)
{
// before first connection
if( db_count++ == 0 )
{
if (!PQisthreadsafe())
{
sLog.outError("FATAL ERROR: PostgreSQL libpq isn't thread-safe.");
exit(1);
}
}
}
DatabasePostgre::~DatabasePostgre()
{
if (m_delayThread)
HaltDelayThread();
if( mPGconn )
{
PQfinish(mPGconn);
mPGconn = NULL;
}
}
bool DatabasePostgre::Initialize(const char *infoString)
{
if(!Database::Initialize(infoString))
return false;
tranThread = NULL;
InitDelayThread();
Tokens tokens = StrSplit(infoString, ";");
Tokens::iterator iter;
std::string host, port_or_socket, user, password, database;
iter = tokens.begin();
if(iter != tokens.end())
host = *iter++;
if(iter != tokens.end())
port_or_socket = *iter++;
if(iter != tokens.end())
user = *iter++;
if(iter != tokens.end())
password = *iter++;
if(iter != tokens.end())
database = *iter++;
mPGconn = PQsetdbLogin(host.c_str(), port_or_socket.c_str(), NULL, NULL, database.c_str(), user.c_str(), password.c_str());
/* check to see that the backend connection was successfully made */
if (PQstatus(mPGconn) != CONNECTION_OK)
{
sLog.outError( "Could not connect to Postgre database at %s: %s",
host.c_str(), PQerrorMessage(mPGconn));
PQfinish(mPGconn);
return false;
}
else
{
sLog.outDetail( "Connected to Postgre database at %s",
host.c_str());
sLog.outString( "PostgreSQL server ver: %d",PQserverVersion(mPGconn));
return true;
}
}
QueryResult* DatabasePostgre::Query(const char *sql)
{
if (!mPGconn)
return 0;
uint64 rowCount = 0;
uint32 fieldCount = 0;
// guarded block for thread-safe request
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
#ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
// Send the query
PGresult * result = PQexec(mPGconn, sql);
if (!result )
{
return NULL;
}
if (PQresultStatus(result) != PGRES_TUPLES_OK)
{
sLog.outErrorDb( "SQL : %s", sql );
sLog.outErrorDb( "SQL %s", PQerrorMessage(mPGconn));
PQclear(result);
return NULL;
}
else
{
#ifdef MANGOS_DEBUG
sLog.outDebug("[%u ms] SQL: %s", getMSTime() - _s, sql );
#endif
}
rowCount = PQntuples(result);
fieldCount = PQnfields(result);
// end guarded block
if (!rowCount)
{
PQclear(result);
return NULL;
}
QueryResultPostgre * queryResult = new QueryResultPostgre(result, rowCount, fieldCount);
queryResult->NextRow();
return queryResult;
}
bool DatabasePostgre::Execute(const char *sql)
{
if (!mPGconn)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody) return DirectExecute(sql);
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{ // Statement for transaction
i->second->DelayExecute(sql);
}
else
{
// Simple sql statement
m_threadBody->Delay(new SqlStatement(sql));
}
return true;
}
bool DatabasePostgre::DirectExecute(const char* sql)
{
if (!mPGconn)
return false;
{
// guarded block for thread-safe request
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
#ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
PGresult *res = PQexec(mPGconn, sql);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
sLog.outErrorDb( "SQL: %s", sql );
sLog.outErrorDb( "SQL %s", PQerrorMessage(mPGconn) );
return false;
}
else
{
#ifdef MANGOS_DEBUG
sLog.outDebug("[%u ms] SQL: %s", getMSTime() - _s, sql );
#endif
}
PQclear(res);
// end guarded block
}
return true;
}
bool DatabasePostgre::_TransactionCmd(const char *sql)
{
if (!mPGconn)
return false;
PGresult *res = PQexec(mPGconn, sql);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
sLog.outError("SQL: %s", sql);
sLog.outError("SQL ERROR: %s", PQerrorMessage(mPGconn));
return false;
}
else
{
DEBUG_LOG("SQL: %s", sql);
}
return true;
}
bool DatabasePostgre::BeginTransaction()
{
if (!mPGconn)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
if (tranThread==ZThread::ThreadImpl::current())
return false; // huh? this thread already started transaction
mMutex.acquire();
if (!_TransactionCmd("START TRANSACTION"))
{
mMutex.release(); // can't start transaction
return false;
}
return true;
}
// transaction started
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
// If for thread exists queue and also contains transaction
// delete that transaction (not allow trans in trans)
delete i->second;
m_tranQueues[tranThread] = new SqlTransaction();
return true;
}
bool DatabasePostgre::CommitTransaction()
{
if (!mPGconn)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
if (tranThread!=ZThread::ThreadImpl::current())
return false;
bool _res = _TransactionCmd("COMMIT");
tranThread = NULL;
mMutex.release();
return _res;
}
tranThread = ZThread::ThreadImpl::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
m_threadBody->Delay(i->second);
i->second = NULL;
return true;
}
else
return false;
}
bool DatabasePostgre::RollbackTransaction()
{
if (!mPGconn)
return false;
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
if (tranThread!=ZThread::ThreadImpl::current())
return false;
bool _res = _TransactionCmd("ROLLBACK");
tranThread = NULL;
mMutex.release();
return _res;
}
tranThread = ZThread::ThreadImpl::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
delete i->second;
i->second = NULL;
}
return true;
}
unsigned long DatabasePostgre::escape_string(char *to, const char *from, unsigned long length)
{
if (!mPGconn || !to || !from || !length)
return 0;
return PQescapeString(to, from, length);
}
void DatabasePostgre::InitDelayThread()
{
assert(!m_delayThread);
//New delay thread for delay execute
m_delayThread = new ZThread::Thread(m_threadBody = new PGSQLDelayThread(this));
}
void DatabasePostgre::HaltDelayThread()
{
if (!m_threadBody || !m_delayThread) return;
m_threadBody->Stop(); //Stop event
m_delayThread->wait(); //Wait for flush to DB
delete m_delayThread; //This also deletes m_threadBody
m_delayThread = NULL;
m_threadBody = NULL;
}
#endif

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _DatabasePostgre_H
#define _DatabasePostgre_H
#include "Policies/Singleton.h"
#include "zthread/FastMutex.h"
#include <stdarg.h>
#ifdef WIN32
#define FD_SETSIZE 1024
#include <winsock2.h>
#include <postgre/libpq-fe.h>
#else
#include <libpq-fe.h>
#endif
class DatabasePostgre : public Database
{
friend class MaNGOS::OperatorNew<DatabasePostgre>;
public:
DatabasePostgre();
~DatabasePostgre();
//! Initializes Postgres and connects to a server.
/*! infoString should be formated like hostname;username;password;database. */
bool Initialize(const char *infoString);
void InitDelayThread();
void HaltDelayThread();
QueryResult* Query(const char *sql);
bool Execute(const char *sql);
bool DirectExecute(const char* sql);
bool BeginTransaction();
bool CommitTransaction();
bool RollbackTransaction();
operator bool () const { return mPGconn != NULL; }
unsigned long escape_string(char *to, const char *from, unsigned long length);
using Database::escape_string;
// must be call before first query in thread
void ThreadStart();
// must be call before finish thread run
void ThreadEnd();
private:
ZThread::FastMutex mMutex;
ZThread::FastMutex tranMutex;
ZThread::ThreadImpl* tranThread;
PGconn *mPGconn;
static size_t db_count;
bool _TransactionCmd(const char *sql);
};
#endif

View file

@ -0,0 +1,101 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#include "DatabaseEnv.h"
DatabaseSqlite::DatabaseSqlite() : Database(), mSqlite(0)
{
}
DatabaseSqlite::~DatabaseSqlite()
{
if (mSqlite)
sqlite_close(mSqlite);
}
bool DatabaseSqlite::Initialize(const char *infoString)
{
if(!Database::Initialize(infoString))
return false;
char *errmsg;
mSqlite = sqlite_open(infoString, 0, &errmsg);
if (!mSqlite)
{
if (errmsg)
sqlite_freemem(errmsg);
return false;
}
return true;
}
QueryResult* DatabaseSqlite::Query(const char *sql)
{
char *errmsg;
if (!mSqlite)
return 0;
char **tableData;
int rowCount;
int fieldCount;
sqlite_get_table(mSqlite, sql, &tableData, &rowCount, &fieldCount, &errmsg);
if (!rowCount)
return 0;
if (!tableData)
{
if (errmsg)
sqlite_freemem(errmsg);
return 0;
}
QueryResultSqlite *queryResult = new QueryResultSqlite(tableData, rowCount, fieldCount);
if(!queryResult)
{
return 0;
}
queryResult->NextRow();
return queryResult;
}
bool DatabaseSqlite::Execute(const char *sql)
{
char *errmsg;
if (!mSqlite)
return false;
if(sqlite_exec(mSqlite, sql, NULL, NULL, &errmsg) != SQLITE_OK)
return false;
return true;
}
#endif

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#ifndef _DATABASESQLITE_H
#define _DATABASESQLITE_H
#include <sqlite/sqlite.h>
class DatabaseSqlite : public Database
{
public:
DatabaseSqlite();
~DatabaseSqlite();
bool Initialize(const char *infoString);
QueryResult* Query(const char *sql);
bool Execute(const char *sql);
operator bool () const { return mSqlite != NULL; }
private:
sqlite *mSqlite;
};
#endif
#endif

View file

@ -0,0 +1,65 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "DatabaseEnv.h"
Field::Field() :
mValue(NULL), mType(DB_TYPE_UNKNOWN)
{
}
Field::Field(Field &f)
{
const char *value;
value = f.GetString();
if (value && (mValue = new char[strlen(value) + 1]))
strcpy(mValue, value);
else
mValue = NULL;
mType = f.GetType();
}
Field::Field(const char *value, enum Field::DataTypes type) :
mType(type)
{
if (value && (mValue = new char[strlen(value) + 1]))
strcpy(mValue, value);
else
mValue = NULL;
}
Field::~Field()
{
if(mValue) delete [] mValue;
}
void Field::SetValue(const char *value)
{
if(mValue) delete [] mValue;
if (value)
{
mValue = new char[strlen(value) + 1];
strcpy(mValue, value);
}
else
mValue = NULL;
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(FIELD_H)
#define FIELD_H
class Field
{
public:
enum DataTypes
{
DB_TYPE_UNKNOWN = 0x00,
DB_TYPE_STRING = 0x01,
DB_TYPE_INTEGER = 0x02,
DB_TYPE_FLOAT = 0x03,
DB_TYPE_BOOL = 0x04
};
Field();
Field(Field &f);
Field(const char *value, enum DataTypes type);
~Field();
enum DataTypes GetType() const { return mType; }
const char *GetString() const { return mValue; }
std::string GetCppString() const
{
return mValue ? mValue : ""; // std::string s = 0 have undefine result in C++
}
float GetFloat() const { return mValue ? static_cast<float>(atof(mValue)) : 0.0f; }
bool GetBool() const { return mValue ? atoi(mValue) > 0 : false; }
int32 GetInt32() const { return mValue ? static_cast<int32>(atol(mValue)) : int32(0); }
uint8 GetUInt8() const { return mValue ? static_cast<uint8>(atol(mValue)) : uint8(0); }
uint16 GetUInt16() const { return mValue ? static_cast<uint16>(atol(mValue)) : uint16(0); }
int16 GetInt16() const { return mValue ? static_cast<int16>(atol(mValue)) : int16(0); }
uint32 GetUInt32() const { return mValue ? static_cast<uint32>(atol(mValue)) : uint32(0); }
uint64 GetUInt64() const
{
if(mValue)
{
uint64 value;
sscanf(mValue,I64FMTD,&value);
return value;
}
else
return 0;
}
void SetType(enum DataTypes type) { mType = type; }
void SetValue(const char *value);
private:
char *mValue;
enum DataTypes mType;
};
#endif

View file

@ -0,0 +1,63 @@
# Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
#
# 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.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## Process this file with automake to produce Makefile.in
## Sub-directories to parse
## CPP flags for includes, defines, etc.
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite
## Build MaNGOS shared library and its parts as convenience library.
# All libraries will be convenience libraries. Might be changed to shared
# later.
noinst_LIBRARIES = libmangosdatabase.a
libmangosdatabase_a_SOURCES = \
DBCStores.cpp \
DBCStores.h \
DBCStructure.h \
DBCfmt.cpp \
Database.cpp \
Database.h \
DatabaseEnv.h \
DatabaseImpl.h \
DatabaseMysql.cpp \
DatabasePostgre.cpp \
DatabaseMysql.h \
DatabasePostgre.h \
DatabaseSqlite.cpp \
DatabaseSqlite.h \
DBCEnums.h \
Field.cpp \
Field.h \
MySQLDelayThread.h \
PGSQLDelayThread.h \
QueryResult.h \
QueryResultMysql.cpp \
QueryResultMysql.h \
QueryResultPostgre.cpp \
QueryResultPostgre.h \
QueryResultSqlite.cpp \
QueryResultSqlite.h \
SQLStorage.cpp \
SQLStorage.h \
SqlDelayThread.cpp \
SqlDelayThread.h \
SqlOperations.cpp \
SqlOperations.h \
dbcfile.cpp \
dbcfile.h

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __MYSQLDELAYTHREAD_H
#define __MYSQLDELAYTHREAD_H
#include "Database/SqlDelayThread.h"
class MySQLDelayThread : public SqlDelayThread
{
public:
MySQLDelayThread(Database* db) : SqlDelayThread(db) {}
void Stop() { SqlDelayThread::Stop(); }
};
#endif //__MYSQLDELAYTHREAD_H

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PGSQLDELAYTHREAD_H
#define __PGSQLDELAYTHREAD_H
#include "Database/SqlDelayThread.h"
class PGSQLDelayThread : public SqlDelayThread
{
public:
PGSQLDelayThread(Database* db) : SqlDelayThread(db) {}
void Stop() { SqlDelayThread::Stop(); }
};
#endif //__PGSQLDELAYTHREAD_H

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(QUERYRESULT_H)
#define QUERYRESULT_H
class MANGOS_DLL_SPEC QueryResult
{
public:
QueryResult(uint64 rowCount, uint32 fieldCount)
: mFieldCount(fieldCount), mRowCount(rowCount) {}
virtual ~QueryResult() {}
virtual bool NextRow() = 0;
typedef std::map<uint32, std::string> FieldNames;
uint32 GetField_idx(const std::string &name) const
{
for(FieldNames::const_iterator iter = GetFiedNames().begin(); iter != GetFiedNames().end(); ++iter)
{
if(iter->second == name)
return iter->first;
}
assert(false && "unknown field name");
return uint32(-1);
}
Field *Fetch() const { return mCurrentRow; }
const Field & operator [] (int index) const { return mCurrentRow[index]; }
const Field & operator [] (const std::string &name) const
{
return mCurrentRow[GetField_idx(name)];
}
uint32 GetFieldCount() const { return mFieldCount; }
uint64 GetRowCount() const { return mRowCount; }
FieldNames const& GetFiedNames() const {return mFieldNames; }
protected:
Field *mCurrentRow;
uint32 mFieldCount;
uint64 mRowCount;
FieldNames mFieldNames;
};
#endif

View file

@ -0,0 +1,110 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#include "DatabaseEnv.h"
QueryResultMysql::QueryResultMysql(MYSQL_RES *result, uint64 rowCount, uint32 fieldCount) :
QueryResult(rowCount, fieldCount), mResult(result)
{
mCurrentRow = new Field[mFieldCount];
ASSERT(mCurrentRow);
MYSQL_FIELD *fields = mysql_fetch_fields(mResult);
for (uint32 i = 0; i < mFieldCount; i++)
{
mFieldNames[i] = fields[i].name;
mCurrentRow[i].SetType(ConvertNativeType(fields[i].type));
}
}
QueryResultMysql::~QueryResultMysql()
{
EndQuery();
}
bool QueryResultMysql::NextRow()
{
MYSQL_ROW row;
if (!mResult)
return false;
row = mysql_fetch_row(mResult);
if (!row)
{
EndQuery();
return false;
}
for (uint32 i = 0; i < mFieldCount; i++)
mCurrentRow[i].SetValue(row[i]);
return true;
}
void QueryResultMysql::EndQuery()
{
if (mCurrentRow)
{
delete [] mCurrentRow;
mCurrentRow = 0;
}
if (mResult)
{
mysql_free_result(mResult);
mResult = 0;
}
}
enum Field::DataTypes QueryResultMysql::ConvertNativeType(enum_field_types mysqlType) const
{
switch (mysqlType)
{
case FIELD_TYPE_TIMESTAMP:
case FIELD_TYPE_DATE:
case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME:
case FIELD_TYPE_YEAR:
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_BLOB:
case FIELD_TYPE_SET:
case FIELD_TYPE_NULL:
return Field::DB_TYPE_STRING;
case FIELD_TYPE_TINY:
case FIELD_TYPE_SHORT:
case FIELD_TYPE_LONG:
case FIELD_TYPE_INT24:
case FIELD_TYPE_LONGLONG:
case FIELD_TYPE_ENUM:
return Field::DB_TYPE_INTEGER;
case FIELD_TYPE_DECIMAL:
case FIELD_TYPE_FLOAT:
case FIELD_TYPE_DOUBLE:
return Field::DB_TYPE_FLOAT;
default:
return Field::DB_TYPE_UNKNOWN;
}
}
#endif

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#if !defined(QUERYRESULTMYSQL_H)
#define QUERYRESULTMYSQL_H
#ifdef WIN32
#define FD_SETSIZE 1024
#include <winsock2.h>
#include <mysql/mysql.h>
#else
#include <mysql.h>
#endif
class QueryResultMysql : public QueryResult
{
public:
QueryResultMysql(MYSQL_RES *result, uint64 rowCount, uint32 fieldCount);
~QueryResultMysql();
bool NextRow();
private:
enum Field::DataTypes ConvertNativeType(enum_field_types mysqlType) const;
void EndQuery();
MYSQL_RES *mResult;
};
#endif
#endif

View file

@ -0,0 +1,139 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef DO_POSTGRESQL
#include "DatabaseEnv.h"
QueryResultPostgre::QueryResultPostgre(PGresult *result, uint64 rowCount, uint32 fieldCount) :
QueryResult(rowCount, fieldCount), mResult(result), mTableIndex(0)
{
mCurrentRow = new Field[mFieldCount];
ASSERT(mCurrentRow);
for (uint32 i = 0; i < mFieldCount; i++)
{
mFieldNames[i] = PQfname(result, i);
mCurrentRow[i].SetType(ConvertNativeType(PQftype( result, i )));
}
}
QueryResultPostgre::~QueryResultPostgre()
{
EndQuery();
}
bool QueryResultPostgre::NextRow()
{
if (!mResult)
return false;
if (mTableIndex >= mRowCount)
{
EndQuery();
return false;
}
char* pPQgetvalue;
for (int j = 0; j < mFieldCount; j++)
{
pPQgetvalue = PQgetvalue(mResult, mTableIndex, j);
if(pPQgetvalue && !(*pPQgetvalue))
pPQgetvalue = NULL;
mCurrentRow[j].SetValue(pPQgetvalue);
}
++mTableIndex;
return true;
}
void QueryResultPostgre::EndQuery()
{
if (mCurrentRow)
{
delete [] mCurrentRow;
mCurrentRow = 0;
}
if (mResult)
{
PQclear(mResult);
mResult = 0;
}
}
// see types in #include <postgre/pg_type.h>
enum Field::DataTypes QueryResultPostgre::ConvertNativeType(Oid pOid ) const
{
switch (pOid)
{
case BPCHAROID:
case CIDOID:
case CIDROID:
case CIRCLEOID:
case INETOID:
case NAMEOID:
case TEXTOID:
case VARCHAROID:
return Field::DB_TYPE_STRING;
case CASHOID:
case FLOAT4OID:
case FLOAT8OID:
case NUMERICOID:
return Field::DB_TYPE_FLOAT;
case DATEOID: // Date
case RELTIMEOID: // Date
case TIMEOID: // Time
case TIMETZOID: // Time
case ABSTIMEOID: // DateTime
case INTERVALOID: // DateTime
case TIMESTAMPOID: // DateTime
case TIMESTAMPTZOID: // DateTime
case INT2OID: // Int
case INT2VECTOROID: // Int
case INT4OID: // Int
case OIDOID: // Int
case CHAROID: // UInt
case INT8OID: // LongLong
return Field::DB_TYPE_INTEGER;
case BOOLOID:
return Field::DB_TYPE_BOOL; // Bool
/*
case BOXOID: Rect;
case LINEOID: Rect;
case VARBITOID: BitArray;
case BYTEAOID: ByteArray;
*/
case LSEGOID:
case OIDVECTOROID:
case PATHOID:
case POINTOID:
case POLYGONOID:
case REGPROCOID:
case TIDOID:
case TINTERVALOID:
case UNKNOWNOID:
case XIDOID:
default:
return Field::DB_TYPE_UNKNOWN;
}
return Field::DB_TYPE_UNKNOWN;
}
#endif

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(QUERYRESULTPOSTGRE_H)
#define QUERYRESULTPOSTGRE_H
#ifdef WIN32
#define FD_SETSIZE 1024
#include <winsock2.h>
#include <postgre/libpq-fe.h>
#include <postgre/pg_type.h>
#else
#include <libpq-fe.h>
//#include <pg_type.h>
#endif
class QueryResultPostgre : public QueryResult
{
public:
QueryResultPostgre(PGresult *result, uint64 rowCount, uint32 fieldCount);
~QueryResultPostgre();
bool NextRow();
private:
enum Field::DataTypes ConvertNativeType(Oid pOid) const;
void EndQuery();
PGresult *mResult;
uint32 mTableIndex;
};
#endif

View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#include "DatabaseEnv.h"
QueryResultSqlite::QueryResultSqlite(char **tableData, uint32 rowCount, uint32 fieldCount) :
QueryResult(rowCount, fieldCount), mTableData(tableData), mTableIndex(0)
{
mCurrentRow = new Field[mFieldCount];
for (uint32 i = 0; i < mFieldCount; i++)
{
mFieldNames[i] = mTableData[i];
mCurrentRow[i].SetType(Field::DB_TYPE_UNKNOWN);
}
}
QueryResultSqlite::~QueryResultSqlite()
{
EndQuery();
}
bool QueryResultSqlite::NextRow()
{
int startIndex;
uint32 i;
if (!mTableData)
return false;
if (mTableIndex >= mRowCount)
{
EndQuery();
return false;
}
startIndex = (mTableIndex + 1) * mFieldCount;
for (i = 0; i < mFieldCount; i++)
{
mCurrentRow[i].SetValue(mTableData[startIndex + i]);
}
++mTableIndex;
return true;
}
void QueryResultSqlite::EndQuery()
{
if (mCurrentRow)
{
delete [] mCurrentRow;
mCurrentRow = NULL;
}
if (mTableData)
{
sqlite_free_table(mTableData);
mTableData = NULL;
}
}
enum Field::DataTypes QueryResultSqlite::ConvertNativeType(const char* sqliteType) const
{
if (sqliteType)
{
switch (*sqliteType)
{
case 'S':
return Field::DB_TYPE_STRING;
case 'I':
return Field::DB_TYPE_INTEGER;
case 'F':
return Field::DB_TYPE_FLOAT;
default:
return Field::DB_TYPE_UNKNOWN;
};
}
return Field::DB_TYPE_UNKNOWN;
}
#endif

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DO_POSTGRESQL
#if !defined(QUERYRESULTSQLITE_H)
#define QUERYRESULTSQLITE_H
#include <sqlite/sqlite.h>
class QueryResultSqlite : public QueryResult
{
public:
QueryResultSqlite(char **tableData, uint32 rowCount, uint32 fieldCount);
~QueryResultSqlite();
bool NextRow();
private:
enum Field::DataTypes ConvertNativeType(const char* sqliteType) const;
void EndQuery();
char **mTableData;
uint32 mTableIndex;
};
#endif
#endif

View file

@ -0,0 +1,191 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "SQLStorage.h"
#include "ProgressBar.h"
#include "Log.h"
#include "dbcfile.h"
#ifdef DO_POSTGRESQL
extern DatabasePostgre WorldDatabase;
#else
extern DatabaseMysql WorldDatabase;
#endif
const char CreatureInfofmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis";
const char CreatureDataAddonInfofmt[]="iiiiiiis";
const char CreatureModelfmt[]="iffbi";
const char CreatureInfoAddonInfofmt[]="iiiiiiis";
const char EquipmentInfofmt[]="iiiiiiiiii";
const char GameObjectInfofmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis";
const char ItemPrototypefmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiii";
const char PageTextfmt[]="isi";
const char SpellThreatfmt[]="ii";
const char InstanceTemplatefmt[]="iiiiiiffffs";
SQLStorage sCreatureStorage(CreatureInfofmt,"entry","creature_template");
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");
SQLStorage sCreatureModelStorage(CreatureModelfmt,"modelid","creature_model_info");
SQLStorage sCreatureInfoAddonStorage(CreatureInfoAddonInfofmt,"entry","creature_template_addon");
SQLStorage sEquipmentStorage(EquipmentInfofmt,"entry","creature_equip_template");
SQLStorage sGOStorage(GameObjectInfofmt,"entry","gameobject_template");
SQLStorage sItemStorage(ItemPrototypefmt,"entry","item_template");
SQLStorage sPageTextStore(PageTextfmt,"entry","page_text");
SQLStorage sSpellThreatStore(SpellThreatfmt,"entry","spell_threat");
SQLStorage sInstanceTemplate(InstanceTemplatefmt,"map","instance_template");
void SQLStorage::Free ()
{
uint32 offset=0;
for(uint32 x=0;x<iNumFields;x++)
if (format[x]==FT_STRING)
{
for(uint32 y=0;y<MaxEntry;y++)
if(pIndex[y])
delete [] *(char**)((char*)(pIndex[y])+offset);
offset+=sizeof(char*);
}
else if (format[x]==FT_LOGIC)
offset+=sizeof(bool);
else if (format[x]==FT_BYTE)
offset+=sizeof(char);
else
offset+=4;
delete [] pIndex;
delete [] data;
}
void SQLStorage::Load ()
{
uint32 maxi;
Field *fields;
QueryResult *result = WorldDatabase.PQuery("SELECT MAX(%s) FROM %s",entry_field,table);
if(!result)
{
sLog.outError("Error loading %s table (not exist?)\n",table);
exit(1); // Stop server at loading non exited table or not accessable table
}
maxi= (*result)[0].GetUInt32()+1;
delete result;
result = WorldDatabase.PQuery("SELECT COUNT(*) FROM %s",table);
if(result)
{
fields = result->Fetch();
RecordCount=fields[0].GetUInt32();
delete result;
}
else
RecordCount = 0;
result = WorldDatabase.PQuery("SELECT * FROM %s",table);
if(!result)
{
sLog.outError("%s table is empty!\n",table);
RecordCount = 0;
return;
}
uint32 recordsize=0;
uint32 offset=0;
if(iNumFields!=result->GetFieldCount())
{
RecordCount = 0;
sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n",table,iNumFields);
delete result;
exit(1); // Stop server at loading broken or non-compatible table.
}
//get struct size
uint32 sc=0;
uint32 bo=0;
uint32 bb=0;
for(uint32 x=0;x<iNumFields;x++)
if(format[x]==FT_STRING)
++sc;
else if (format[x]==FT_LOGIC)
++bo;
else if (format[x]==FT_BYTE)
++bb;
recordsize=(iNumFields-sc-bo-bb)*4+sc*sizeof(char*)+bo*sizeof(bool)+bb*sizeof(char);
char** newIndex=new char*[maxi];
memset(newIndex,0,maxi*sizeof(char*));
char * _data= new char[RecordCount *recordsize];
uint32 count=0;
barGoLink bar( RecordCount );
do
{
fields = result->Fetch();
bar.step();
char *p=(char*)&_data[recordsize*count];
newIndex[fields[0].GetUInt32()]=p;
offset=0;
for(uint32 x=0;x<iNumFields;x++)
switch(format[x])
{
case FT_LOGIC:
*((bool*)(&p[offset]))=(fields[x].GetUInt32()>0);
offset+=sizeof(bool);
break;
case FT_BYTE:
*((char*)(&p[offset]))=(fields[x].GetUInt8());
offset+=sizeof(char);
break;
case FT_INT:
*((uint32*)(&p[offset]))=fields[x].GetUInt32();
offset+=sizeof(uint32);
break;
case FT_FLOAT:
*((float*)(&p[offset]))=fields[x].GetFloat();
offset+=sizeof(float);
break;
case FT_STRING:
char const* tmp = fields[x].GetString();
char* st;
if(!tmp)
{
st=new char[1];
*st=0;
}
else
{
uint32 l=strlen(tmp)+1;
st=new char[l];
memcpy(st,tmp,l);
}
*((char**)(&p[offset]))=st;
offset+=sizeof(char*);
break;
}
++count;
}while( result->NextRow() );
delete result;
pIndex =newIndex;
MaxEntry=maxi;
data=_data;
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SQLSTORAGE_H
#define SQLSTORAGE_H
#include "Common.h"
#include "Database/DatabaseEnv.h"
class SQLStorage
{
public:
SQLStorage(const char*fmt,const char * _entry_field,const char * sqlname)
{
format=fmt;
entry_field = _entry_field;
table=sqlname;
data=NULL;
pIndex=NULL;
iNumFields =strlen(fmt);
MaxEntry = 0;
}
~SQLStorage()
{
Free();
}
template<class T>
T const* LookupEntry(uint32 id) const
{
if( id == 0 )
return NULL;
if(id >= MaxEntry)
return NULL;
return reinterpret_cast<T const*>(pIndex[id]);
}
uint32 RecordCount;
uint32 MaxEntry;
uint32 iNumFields;
void Load();
void Free();
private:
char** pIndex;
char *data;
const char *format;
const char *table;
const char *entry_field;
//bool HasString;
};
#endif

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Database/SqlDelayThread.h"
#include "Database/SqlOperations.h"
#include "DatabaseEnv.h"
SqlDelayThread::SqlDelayThread(Database* db) : m_dbEngine(db), m_running(true)
{
}
void SqlDelayThread::run()
{
SqlOperation* s;
#ifndef DO_POSTGRESQL
mysql_thread_init();
#endif
while (m_running)
{
// if the running state gets turned off while sleeping
// empty the queue before exiting
ZThread::Thread::sleep(10);
while (!m_sqlQueue.empty())
{
s = m_sqlQueue.next();
s->Execute(m_dbEngine);
delete s;
}
}
#ifndef DO_POSTGRESQL
mysql_thread_end();
#endif
}
void SqlDelayThread::Stop()
{
m_running = false;
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __SQLDELAYTHREAD_H
#define __SQLDELAYTHREAD_H
#include "zthread/Thread.h"
#include "zthread/Runnable.h"
#include "zthread/FastMutex.h"
#include "zthread/LockedQueue.h"
class Database;
class SqlOperation;
class SqlDelayThread : public ZThread::Runnable
{
typedef ZThread::LockedQueue<SqlOperation*, ZThread::FastMutex> SqlQueue;
private:
SqlQueue m_sqlQueue; ///< Queue of SQL statements
Database* m_dbEngine; ///< Pointer to used Database engine
bool m_running;
SqlDelayThread();
public:
SqlDelayThread(Database* db);
///< Put sql statement to delay queue
inline void Delay(SqlOperation* sql) { m_sqlQueue.add(sql); }
virtual void Stop(); ///< Stop event
virtual void run(); ///< Main Thread loop
};
#endif //__SQLDELAYTHREAD_H

View file

@ -0,0 +1,197 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "SqlOperations.h"
#include "SqlDelayThread.h"
#include "DatabaseEnv.h"
#include "DatabaseImpl.h"
/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
void SqlStatement::Execute(Database *db)
{
/// just do it
db->DirectExecute(m_sql);
}
void SqlTransaction::Execute(Database *db)
{
if(m_queue.empty())
return;
db->DirectExecute("START TRANSACTION");
while(!m_queue.empty())
{
char const *sql = m_queue.front();
m_queue.pop();
if(!db->DirectExecute(sql))
{
free((void*)const_cast<char*>(sql));
db->DirectExecute("ROLLBACK");
while(!m_queue.empty())
{
free((void*)const_cast<char*>(m_queue.front()));
m_queue.pop();
}
return;
}
free((void*)const_cast<char*>(sql));
}
db->DirectExecute("COMMIT");
}
/// ---- ASYNC QUERIES ----
void SqlQuery::Execute(Database *db)
{
if(!m_callback || !m_queue)
return;
/// execute the query and store the result in the callback
m_callback->SetResult(db->Query(m_sql));
/// add the callback to the sql result queue of the thread it originated from
m_queue->add(m_callback);
}
void SqlResultQueue::Update()
{
/// execute the callbacks waiting in the synchronization queue
while(!empty())
{
MaNGOS::IQueryCallback * callback = next();
callback->Execute();
delete callback;
}
}
void SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue)
{
if(!callback || !thread || !queue)
return;
/// delay the execution of the queries, sync them with the delay thread
/// which will in turn resync on execution (via the queue) and call back
SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue);
thread->Delay(holderEx);
}
bool SqlQueryHolder::SetQuery(size_t index, const char *sql)
{
if(m_queries.size() <= index)
{
sLog.outError("Query index (%u) out of range (size: %u) for query: %s",index,m_queries.size(),sql);
return false;
}
if(m_queries[index].first != NULL)
{
sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",index,m_queries.size(),m_queries[index].first,sql);
return false;
}
/// not executed yet, just stored (it's not called a holder for nothing)
m_queries[index] = SqlResultPair(strdup(sql), NULL);
return true;
}
bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...)
{
if(!format)
{
sLog.outError("Query (index: %u) is empty.",index);
return false;
}
va_list ap;
char szQuery [MAX_QUERY_LEN];
va_start(ap, format);
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
va_end(ap);
if(res==-1)
{
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
return false;
}
return SetQuery(index,szQuery);
}
QueryResult* SqlQueryHolder::GetResult(size_t index)
{
if(index < m_queries.size())
{
/// the query strings are freed on the first GetResult or in the destructor
if(m_queries[index].first != NULL)
{
free((void*)(const_cast<char*>(m_queries[index].first)));
m_queries[index].first = NULL;
}
/// when you get a result aways remember to delete it!
return m_queries[index].second;
}
else
return NULL;
}
void SqlQueryHolder::SetResult(size_t index, QueryResult *result)
{
/// store the result in the holder
if(index < m_queries.size())
m_queries[index].second = result;
}
SqlQueryHolder::~SqlQueryHolder()
{
for(size_t i = 0; i < m_queries.size(); i++)
{
/// if the result was never used, free the resources
/// results used already (getresult called) are expected to be deleted
if(m_queries[i].first != NULL)
{
free((void*)(const_cast<char*>(m_queries[i].first)));
if(m_queries[i].second)
delete m_queries[i].second;
}
}
}
void SqlQueryHolder::SetSize(size_t size)
{
/// to optimize push_back, reserve the number of queries about to be executed
m_queries.resize(size);
}
void SqlQueryHolderEx::Execute(Database *db)
{
if(!m_holder || !m_callback || !m_queue)
return;
/// we can do this, we are friends
std::vector<SqlQueryHolder::SqlResultPair> &queries = m_holder->m_queries;
for(size_t i = 0; i < queries.size(); i++)
{
/// execute all queries in the holder and pass the results
char const *sql = queries[i].first;
if(sql) m_holder->SetResult(i, db->Query(sql));
}
/// sync with the caller thread
m_queue->add(m_callback);
}

View file

@ -0,0 +1,121 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __SQLOPERATIONS_H
#define __SQLOPERATIONS_H
#include "Common.h"
#include "zthread/LockedQueue.h"
#include "zthread/FastMutex.h"
#include "zthread/Thread.h"
#include <queue>
#include "Utilities/Callback.h"
/// ---- BASE ---
class Database;
class SqlDelayThread;
class SqlOperation
{
public:
virtual void OnRemove() { delete this; }
virtual void Execute(Database *db) = 0;
virtual ~SqlOperation() {}
};
/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
class SqlStatement : public SqlOperation
{
private:
const char *m_sql;
public:
SqlStatement(const char *sql) : m_sql(strdup(sql)){}
~SqlStatement() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
void Execute(Database *db);
};
class SqlTransaction : public SqlOperation
{
private:
std::queue<const char *> m_queue;
public:
SqlTransaction() {}
void DelayExecute(const char *sql) { m_queue.push(strdup(sql)); }
void Execute(Database *db);
};
/// ---- ASYNC QUERIES ----
class SqlQuery; /// contains a single async query
class QueryResult; /// the result of one
class SqlResultQueue; /// queue for thread sync
class SqlQueryHolder; /// groups several async quries
class SqlQueryHolderEx; /// points to a holder, added to the delay thread
class SqlResultQueue : public ZThread::LockedQueue<MaNGOS::IQueryCallback*, ZThread::FastMutex>
{
public:
SqlResultQueue() {}
void Update();
};
class SqlQuery : public SqlOperation
{
private:
const char *m_sql;
MaNGOS::IQueryCallback * m_callback;
SqlResultQueue * m_queue;
public:
SqlQuery(const char *sql, MaNGOS::IQueryCallback * callback, SqlResultQueue * queue)
: m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {}
~SqlQuery() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
void Execute(Database *db);
};
class SqlQueryHolder
{
friend class SqlQueryHolderEx;
private:
typedef std::pair<const char*, QueryResult*> SqlResultPair;
std::vector<SqlResultPair> m_queries;
public:
SqlQueryHolder() {}
~SqlQueryHolder();
bool SetQuery(size_t index, const char *sql);
bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4);
void SetSize(size_t size);
QueryResult* GetResult(size_t index);
void SetResult(size_t index, QueryResult *result);
void Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue);
};
class SqlQueryHolderEx : public SqlOperation
{
private:
SqlQueryHolder * m_holder;
MaNGOS::IQueryCallback * m_callback;
SqlResultQueue * m_queue;
public:
SqlQueryHolderEx(SqlQueryHolder *holder, MaNGOS::IQueryCallback * callback, SqlResultQueue * queue)
: m_holder(holder), m_callback(callback), m_queue(queue) {}
void Execute(Database *db);
};
#endif //__SQLOPERATIONS_H

View file

@ -0,0 +1,243 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dbcfile.h"
DBCFile::DBCFile()
{
data = NULL;
fieldsOffset = NULL;
}
bool DBCFile::Load(const char *filename, const char *fmt)
{
uint32 header;
if(data)
{
delete [] data;
data=NULL;
}
FILE * f=fopen(filename,"rb");
if(!f)return false;
fread(&header,4,1,f); // Number of records
EndianConvert(header);
if(header!=0x43424457)
{
//printf("not dbc file");
return false; //'WDBC'
}
fread(&recordCount,4,1,f); // Number of records
EndianConvert(recordCount);
fread(&fieldCount,4,1,f); // Number of fields
EndianConvert(fieldCount);
fread(&recordSize,4,1,f); // Size of a record
EndianConvert(recordSize);
fread(&stringSize,4,1,f); // String size
EndianConvert(stringSize);
fieldsOffset = new uint32[fieldCount];
fieldsOffset[0] = 0;
for(uint32 i = 1; i < fieldCount; i++)
{
fieldsOffset[i] = fieldsOffset[i - 1];
if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
fieldsOffset[i] += 1;
else // 4 byte fields (int32/float/strings)
fieldsOffset[i] += 4;
}
data = new unsigned char[recordSize*recordCount+stringSize];
stringTable = data + recordSize*recordCount;
fread(data,recordSize*recordCount+stringSize,1,f);
fclose(f);
return true;
}
DBCFile::~DBCFile()
{
if(data)
delete [] data;
if(fieldsOffset)
delete [] fieldsOffset;
}
DBCFile::Record DBCFile::getRecord(size_t id)
{
assert(data);
return Record(*this, data + id*recordSize);
}
uint32 DBCFile::GetFormatRecordSize(const char * format,int32* index_pos)
{
uint32 recordsize = 0;
int32 i = -1;
for(uint32 x=0; format[x];++x)
switch(format[x])
{
case FT_FLOAT:
case FT_INT:
recordsize+=4;
break;
case FT_STRING:
recordsize+=sizeof(char*);
break;
case FT_SORT:
i=x;
break;
case FT_IND:
i=x;
recordsize+=4;
break;
case FT_BYTE:
recordsize += 1;
break;
}
if(index_pos)
*index_pos = i;
return recordsize;
}
char* DBCFile::AutoProduceData(const char* format, uint32& records, char**& indexTable)
{
/*
format STRING, NA, FLOAT,NA,INT <=>
struct{
char* field0,
float field1,
int field2
}entry;
this func will generate entry[rows] data;
*/
typedef char * ptr;
if(strlen(format)!=fieldCount)
return NULL;
//get struct size and index pos
int32 i;
uint32 recordsize=GetFormatRecordSize(format,&i);
if(i>=0)
{
uint32 maxi=0;
//find max index
for(uint32 y=0;y<recordCount;y++)
{
uint32 ind=getRecord(y).getUInt (i);
if(ind>maxi)maxi=ind;
}
++maxi;
records=maxi;
indexTable=new ptr[maxi];
memset(indexTable,0,maxi*sizeof(ptr));
}
else
{
records = recordCount;
indexTable = new ptr[recordCount];
}
char* dataTable= new char[recordCount*recordsize];
uint32 offset=0;
for(uint32 y =0;y<recordCount;y++)
{
if(i>=0)
{
indexTable[getRecord(y).getUInt(i)]=&dataTable[offset];
}
else
indexTable[y]=&dataTable[offset];
for(uint32 x=0;x<fieldCount;x++)
{
switch(format[x])
{
case FT_FLOAT:
*((float*)(&dataTable[offset]))=getRecord(y).getFloat(x);
offset+=4;
break;
case FT_IND:
case FT_INT:
*((uint32*)(&dataTable[offset]))=getRecord(y).getUInt(x);
offset+=4;
break;
case FT_BYTE:
*((uint8*)(&dataTable[offset]))=getRecord(y).getUInt8(x);
offset+=1;
break;
case FT_STRING:
*((char**)(&dataTable[offset]))=NULL; // will be replaces non-empty or "" strings in AutoProduceStrings
offset+=sizeof(char*);
break;
}
}
}
return dataTable;
}
char* DBCFile::AutoProduceStrings(const char* format, char* dataTable)
{
if(strlen(format)!=fieldCount)
return NULL;
char* stringPool= new char[stringSize];
memcpy(stringPool,stringTable,stringSize);
uint32 offset=0;
for(uint32 y =0;y<recordCount;y++)
{
for(uint32 x=0;x<fieldCount;x++)
switch(format[x])
{
case FT_FLOAT:
case FT_IND:
case FT_INT:
offset+=4;
break;
case FT_BYTE:
offset+=1;
break;
case FT_STRING:
// fill only not filled entries
char** slot = (char**)(&dataTable[offset]);
if(!*slot || !**slot)
{
const char * st = getRecord(y).getString(x);
*slot=stringPool+(st-(const char*)stringTable);
}
offset+=sizeof(char*);
break;
}
}
return stringPool;
}

View file

@ -0,0 +1,107 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DBCFILE_H
#define DBCFILE_H
#include "Platform/Define.h"
#include "Utilities/ByteConverter.h"
#include <cassert>
enum
{
FT_NA='x', //not used or unknown, 4 byte size
FT_NA_BYTE='X', //not used or unknown, byte
FT_STRING='s', //char*
FT_FLOAT='f', //float
FT_INT='i', //uint32
FT_BYTE='b', //uint8
FT_SORT='d', //sorted by this field, field is not included
FT_IND='n', //the same,but parsed to data
FT_LOGIC='l' //Logical (boolean)
};
class DBCFile
{
public:
DBCFile();
~DBCFile();
bool Load(const char *filename, const char *fmt);
class Record
{
public:
float getFloat(size_t field) const
{
assert(field < file.fieldCount);
float val = *reinterpret_cast<float*>(offset+file.GetOffset(field));
EndianConvert(val);
return val;
}
uint32 getUInt(size_t field) const
{
assert(field < file.fieldCount);
uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field));
EndianConvert(val);
return val;
}
uint8 getUInt8(size_t field) const
{
assert(field < file.fieldCount);
return *reinterpret_cast<uint8*>(offset+file.GetOffset(field));
}
const char *getString(size_t field) const
{
assert(field < file.fieldCount);
size_t stringOffset = getUInt(field);
assert(stringOffset < file.stringSize);
return reinterpret_cast<char*>(file.stringTable + stringOffset);
}
private:
Record(DBCFile &file_, unsigned char *offset_): offset(offset_), file(file_) {}
unsigned char *offset;
DBCFile &file;
friend class DBCFile;
};
// Get record by id
Record getRecord(size_t id);
/// Get begin iterator over records
uint32 GetNumRows() const { return recordCount;}
uint32 GetCols() const { return fieldCount; }
uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; }
bool IsLoaded() {return (data!=NULL);}
char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable);
char* AutoProduceStrings(const char* fmt, char* dataTable);
static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL);
private:
uint32 recordSize;
uint32 recordCount;
uint32 fieldCount;
uint32 stringSize;
uint32 *fieldsOffset;
unsigned char *data;
unsigned char *stringTable;
};
#endif