aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp3
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp157
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DB2Structure.h2
-rw-r--r--src/server/game/DataStores/DB2fmt.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp71
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp16
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h14
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h2
-rw-r--r--src/server/game/Tools/PlayerDump.cpp261
-rw-r--r--src/server/game/Tools/PlayerDump.h20
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/shared/DataStores/DB2StorageLoader.cpp58
-rw-r--r--src/server/shared/DataStores/DB2StorageLoader.h9
-rw-r--r--src/server/shared/DataStores/DB2Store.h58
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp9
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h5
19 files changed, 382 insertions, 313 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index fa9278fadc2..e499381ac3c 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -1135,8 +1135,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
- PhaseGroupEntry const* phase = sPhaseGroupStore.LookupEntry(phaseGroup);
- if (!phase)
+ if (sDB2Manager.GetPhasesForGroup(phaseGroup).empty())
{
TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SET_INGAME_PHASE_GROUP uses invalid phase group id %u for creature " SI64FMTD ", skipped", phaseGroup, e.entryOrGuid);
return false;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 3431f79e61f..3f389d00e20 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -23,39 +23,39 @@
#include "World.h"
#include <functional>
-DB2Storage<AreaGroupEntry> sAreaGroupStore(AreaGroupFormat, HOTFIX_SEL_AREA_GROUP);
-DB2Storage<AreaGroupMemberEntry> sAreaGroupMemberStore(AreaGroupMemberFormat, HOTFIX_SEL_AREA_GROUP_MEMBER);
-DB2Storage<BroadcastTextEntry> sBroadcastTextStore(BroadcastTextFormat, HOTFIX_SEL_BROADCAST_TEXT);
-DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesFormat, HOTFIX_SEL_CURRENCY_TYPES);
-DB2Storage<CurvePointEntry> sCurvePointStore(CurvePointFormat, HOTFIX_SEL_CURVE_POINT);
-DB2Storage<HolidaysEntry> sHolidaysStore(HolidaysEntryFormat, HOTFIX_SEL_HOLIDAYS);
-DB2Storage<ItemAppearanceEntry> sItemAppearanceStore(ItemAppearanceFormat, HOTFIX_SEL_ITEM_APPEARANCE);
-DB2Storage<ItemBonusEntry> sItemBonusStore(ItemBonusFormat, HOTFIX_SEL_ITEM_BONUS);
-DB2Storage<ItemBonusTreeNodeEntry> sItemBonusTreeNodeStore(ItemBonusTreeNodeFormat, HOTFIX_SEL_ITEM_BONUS_TREE_NODE);
-DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore(ItemCurrencyCostFormat, HOTFIX_SEL_ITEM_CURRENCY_COST);
-DB2Storage<ItemEffectEntry> sItemEffectStore(ItemEffectFormat, HOTFIX_SEL_ITEM_EFFECT);
-DB2Storage<ItemEntry> sItemStore(ItemFormat, HOTFIX_SEL_ITEM);
-DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostFormat, HOTFIX_SEL_ITEM_EXTENDED_COST);
-DB2Storage<ItemModifiedAppearanceEntry> sItemModifiedAppearanceStore(ItemModifiedAppearanceFormat, HOTFIX_SEL_ITEM_MODIFIED_APPEARANCE);
-DB2Storage<ItemSparseEntry> sItemSparseStore(ItemSparseFormat, HOTFIX_SEL_ITEM_SPARSE);
-DB2Storage<ItemXBonusTreeEntry> sItemXBonusTreeStore(ItemXBonusTreeFormat, HOTFIX_SEL_ITEM_X_BONUS_TREE);
-DB2Storage<KeyChainEntry> sKeyChainStore(KeyChainFormat, HOTFIX_SEL_KEY_CHAIN);
-DB2Storage<MountEntry> sMountStore(MountFormat, HOTFIX_SEL_MOUNT);
-DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDataFormat, HOTFIX_SEL_OVERRIDE_SPELL_DATA);
-DB2Storage<PhaseGroupEntry> sPhaseGroupStore(PhaseGroupFormat, HOTFIX_SEL_PHASE_GROUP);
-DB2Storage<SoundEntriesEntry> sSoundEntriesStore(SoundEntriesFormat, HOTFIX_SEL_SOUND_ENTRIES);
-DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore(SpellAuraRestrictionsFormat, HOTFIX_SEL_SPELL_AURA_RESTRICTIONS);
-DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore(SpellCastingRequirementsFormat, HOTFIX_SEL_SPELL_CASTING_REQUIREMENTS);
-DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore(SpellClassOptionsFormat, HOTFIX_SEL_SPELL_CLASS_OPTIONS);
-DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore(SpellLearnSpellFormat, HOTFIX_SEL_SPELL_LEARN_SPELL);
-DB2Storage<SpellMiscEntry> sSpellMiscStore(SpellMiscFormat, HOTFIX_SEL_SPELL_MISC);
-DB2Storage<SpellPowerEntry> sSpellPowerStore(SpellPowerFormat, HOTFIX_SEL_SPELL_POWER);
-DB2Storage<SpellReagentsEntry> sSpellReagentsStore(SpellReagentsFormat, HOTFIX_SEL_SPELL_REAGENTS);
-DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostFormat, HOTFIX_SEL_SPELL_RUNE_COST);
-DB2Storage<SpellTotemsEntry> sSpellTotemsStore(SpellTotemsFormat, HOTFIX_SEL_SPELL_TOTEMS);
-DB2Storage<TaxiNodesEntry> sTaxiNodesStore(TaxiNodesFormat, HOTFIX_SEL_TAXI_NODES);
-DB2Storage<TaxiPathEntry> sTaxiPathStore(TaxiPathFormat, HOTFIX_SEL_TAXI_PATH);
-DB2Storage<TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeFormat, HOTFIX_SEL_TAXI_PATH_NODE);
+DB2Storage<AreaGroupEntry> sAreaGroupStore("AreaGroup.db2", AreaGroupFormat, HOTFIX_SEL_AREA_GROUP);
+DB2Storage<AreaGroupMemberEntry> sAreaGroupMemberStore("AreaGroupMember.db2", AreaGroupMemberFormat, HOTFIX_SEL_AREA_GROUP_MEMBER);
+DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.db2", BroadcastTextFormat, HOTFIX_SEL_BROADCAST_TEXT);
+DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore("CurrencyTypes.db2", CurrencyTypesFormat, HOTFIX_SEL_CURRENCY_TYPES);
+DB2Storage<CurvePointEntry> sCurvePointStore("CurvePoint.db2", CurvePointFormat, HOTFIX_SEL_CURVE_POINT);
+DB2Storage<HolidaysEntry> sHolidaysStore("Holidays.db2", HolidaysEntryFormat, HOTFIX_SEL_HOLIDAYS);
+DB2Storage<ItemAppearanceEntry> sItemAppearanceStore("ItemAppearance.db2", ItemAppearanceFormat, HOTFIX_SEL_ITEM_APPEARANCE);
+DB2Storage<ItemBonusEntry> sItemBonusStore("ItemBonus.db2", ItemBonusFormat, HOTFIX_SEL_ITEM_BONUS);
+DB2Storage<ItemBonusTreeNodeEntry> sItemBonusTreeNodeStore("ItemBonusTreeNode.db2", ItemBonusTreeNodeFormat, HOTFIX_SEL_ITEM_BONUS_TREE_NODE);
+DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore("ItemCurrencyCost.db2", ItemCurrencyCostFormat, HOTFIX_SEL_ITEM_CURRENCY_COST);
+DB2Storage<ItemEffectEntry> sItemEffectStore("ItemEffect.db2", ItemEffectFormat, HOTFIX_SEL_ITEM_EFFECT);
+DB2Storage<ItemEntry> sItemStore("Item.db2", ItemFormat, HOTFIX_SEL_ITEM);
+DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore("ItemExtendedCost.db2", ItemExtendedCostFormat, HOTFIX_SEL_ITEM_EXTENDED_COST);
+DB2Storage<ItemModifiedAppearanceEntry> sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", ItemModifiedAppearanceFormat, HOTFIX_SEL_ITEM_MODIFIED_APPEARANCE);
+DB2Storage<ItemSparseEntry> sItemSparseStore("Item-sparse.db2", ItemSparseFormat, HOTFIX_SEL_ITEM_SPARSE);
+DB2Storage<ItemXBonusTreeEntry> sItemXBonusTreeStore("ItemXBonusTree.db2", ItemXBonusTreeFormat, HOTFIX_SEL_ITEM_X_BONUS_TREE);
+DB2Storage<KeyChainEntry> sKeyChainStore("KeyChain.db2", KeyChainFormat, HOTFIX_SEL_KEY_CHAIN);
+DB2Storage<MountEntry> sMountStore("Mount.db2", MountFormat, HOTFIX_SEL_MOUNT);
+DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore("OverrideSpellData.db2", OverrideSpellDataFormat, HOTFIX_SEL_OVERRIDE_SPELL_DATA);
+DB2Storage<PhaseXPhaseGroupEntry> sPhaseXPhaseGroupStore("PhaseXPhaseGroup.db2", PhaseXPhaseGroupFormat, HOTFIX_SEL_PHASE_GROUP);
+DB2Storage<SoundEntriesEntry> sSoundEntriesStore("SoundEntries.db2", SoundEntriesFormat, HOTFIX_SEL_SOUND_ENTRIES);
+DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore("SpellAuraRestrictions.db2", SpellAuraRestrictionsFormat, HOTFIX_SEL_SPELL_AURA_RESTRICTIONS);
+DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore("SpellCastingRequirements.db2", SpellCastingRequirementsFormat, HOTFIX_SEL_SPELL_CASTING_REQUIREMENTS);
+DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore("SpellClassOptions.db2", SpellClassOptionsFormat, HOTFIX_SEL_SPELL_CLASS_OPTIONS);
+DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore("SpellLearnSpell.db2", SpellLearnSpellFormat, HOTFIX_SEL_SPELL_LEARN_SPELL);
+DB2Storage<SpellMiscEntry> sSpellMiscStore("SpellMisc.db2", SpellMiscFormat, HOTFIX_SEL_SPELL_MISC);
+DB2Storage<SpellPowerEntry> sSpellPowerStore("SpellPower.db2", SpellPowerFormat, HOTFIX_SEL_SPELL_POWER);
+DB2Storage<SpellReagentsEntry> sSpellReagentsStore("SpellReagents.db2", SpellReagentsFormat, HOTFIX_SEL_SPELL_REAGENTS);
+DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore("SpellRuneCost.db2", SpellRuneCostFormat, HOTFIX_SEL_SPELL_RUNE_COST);
+DB2Storage<SpellTotemsEntry> sSpellTotemsStore("SpellTotems.db2", SpellTotemsFormat, HOTFIX_SEL_SPELL_TOTEMS);
+DB2Storage<TaxiNodesEntry> sTaxiNodesStore("TaxiNodes.db2", TaxiNodesFormat, HOTFIX_SEL_TAXI_NODES);
+DB2Storage<TaxiPathEntry> sTaxiPathStore("TaxiPath.db2", TaxiPathFormat, HOTFIX_SEL_TAXI_PATH);
+DB2Storage<TaxiPathNodeEntry> sTaxiPathNodeStore("TaxiPathNode.db2", TaxiPathNodeFormat, HOTFIX_SEL_TAXI_PATH_NODE);
SpellPowerBySpellIDMap sSpellPowerBySpellIDStore;
TaxiMask sTaxiNodesMask;
@@ -71,17 +71,16 @@ typedef std::list<std::string> DB2StoreProblemList;
uint32 DB2FilesCount = 0;
template<class T>
-inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Manager::StorageMap& stores, DB2Storage<T>* storage, std::string const& db2_path, std::string const& filename)
+inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Manager::StorageMap& stores, DB2Storage<T>* storage, std::string const& db2_path)
{
// compatibility format and C++ structure sizes
ASSERT(DB2FileLoader::GetFormatRecordSize(storage->GetFormat()) == sizeof(T),
"Size of '%s' set by format string (%u) not equal size of C++ structure (" SZFMTD ").",
- filename.c_str(), DB2FileLoader::GetFormatRecordSize(storage->GetFormat()), sizeof(T));
+ storage->GetFileName().c_str(), DB2FileLoader::GetFormatRecordSize(storage->GetFormat()), sizeof(T));
++DB2FilesCount;
- std::string db2_filename = db2_path + filename;
- if (storage->Load(db2_filename.c_str(), uint32(sWorld->GetDefaultDbcLocale())))
+ if (storage->Load(db2_path, uint32(sWorld->GetDefaultDbcLocale())))
{
storage->LoadFromDB();
@@ -91,15 +90,8 @@ inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, D
continue;
if (availableDb2Locales & (1 << i))
- {
- std::string localizedName(db2_path);
- localizedName.append(localeNames[i]);
- localizedName.push_back('/');
- localizedName.append(filename);
-
- if (!storage->LoadStringsFrom(localizedName.c_str(), i))
+ if (!storage->LoadStringsFrom((db2_path + localeNames[i] + '/'), i))
availableDb2Locales &= ~(1 << i); // mark as not available for speedup next checks
- }
storage->LoadStringsFromDB(i);
}
@@ -107,16 +99,17 @@ inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, D
else
{
// sort problematic db2 to (1) non compatible and (2) nonexistent
- if (FILE* f = fopen(db2_filename.c_str(), "rb"))
+ if (FILE* f = fopen((db2_path + storage->GetFileName()).c_str(), "rb"))
{
std::ostringstream stream;
- stream << db2_filename << " exists, and has " << storage->GetFieldCount() << " field(s) (expected " << strlen(storage->GetFormat()) << "). Extracted file might be from wrong client version.";
+ stream << storage->GetFileName() << " exists, and has " << storage->GetFieldCount() << " field(s) (expected " << strlen(storage->GetFormat())
+ << "). Extracted file might be from wrong client version.";
std::string buf = stream.str();
errlist.push_back(buf);
fclose(f);
}
else
- errlist.push_back(db2_filename);
+ errlist.push_back(storage->GetFileName());
}
stores[storage->GetHash()] = storage;
@@ -131,39 +124,39 @@ void DB2Manager::LoadStores(std::string const& dataPath)
DB2StoreProblemList bad_db2_files;
uint32 availableDb2Locales = 0xFF;
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupStore, db2Path, "AreaGroup.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupMemberStore, db2Path, "AreaGroupMember.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sBroadcastTextStore, db2Path, "BroadcastText.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurrencyTypesStore, db2Path, "CurrencyTypes.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurvePointStore, db2Path, "CurvePoint.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sHolidaysStore, db2Path, "Holidays.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemAppearanceStore, db2Path, "ItemAppearance.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusStore, db2Path, "ItemBonus.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusTreeNodeStore, db2Path, "ItemBonusTreeNode.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemCurrencyCostStore, db2Path, "ItemCurrencyCost.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemEffectStore, db2Path, "ItemEffect.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemExtendedCostStore, db2Path, "ItemExtendedCost.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemModifiedAppearanceStore, db2Path, "ItemModifiedAppearance.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemSparseStore, db2Path, "Item-sparse.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemStore, db2Path, "Item.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemXBonusTreeStore, db2Path, "ItemXBonusTree.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sKeyChainStore, db2Path, "KeyChain.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sMountStore, db2Path, "Mount.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sOverrideSpellDataStore, db2Path, "OverrideSpellData.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sPhaseGroupStore, db2Path, "PhaseXPhaseGroup.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSoundEntriesStore, db2Path, "SoundEntries.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellAuraRestrictionsStore, db2Path, "SpellAuraRestrictions.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellCastingRequirementsStore, db2Path, "SpellCastingRequirements.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellClassOptionsStore, db2Path, "SpellClassOptions.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellLearnSpellStore, db2Path, "SpellLearnSpell.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellMiscStore, db2Path, "SpellMisc.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellPowerStore, db2Path, "SpellPower.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellReagentsStore, db2Path, "SpellReagents.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellRuneCostStore, db2Path, "SpellRuneCost.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellTotemsStore, db2Path, "SpellTotems.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiNodesStore, db2Path, "TaxiNodes.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathNodeStore, db2Path, "TaxiPathNode.db2");
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathStore, db2Path, "TaxiPath.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupMemberStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sBroadcastTextStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurrencyTypesStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurvePointStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sHolidaysStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemAppearanceStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusTreeNodeStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemCurrencyCostStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemEffectStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemExtendedCostStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemModifiedAppearanceStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemSparseStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemXBonusTreeStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sKeyChainStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sMountStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sOverrideSpellDataStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sPhaseXPhaseGroupStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSoundEntriesStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellAuraRestrictionsStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellCastingRequirementsStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellClassOptionsStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellLearnSpellStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellMiscStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellPowerStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellReagentsStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellRuneCostStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellTotemsStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiNodesStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathNodeStore, db2Path);
+ LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathStore, db2Path);
for (AreaGroupMemberEntry const* areaGroupMember : sAreaGroupMemberStore)
_areaGroupMembers[areaGroupMember->AreaGroupID].push_back(areaGroupMember->AreaID);
@@ -201,7 +194,7 @@ void DB2Manager::LoadStores(std::string const& dataPath)
for (MountEntry const* mount : sMountStore)
_mountsBySpellId[mount->SpellId] = mount;
- for (PhaseGroupEntry const* group : sPhaseGroupStore)
+ for (PhaseXPhaseGroupEntry const* group : sPhaseXPhaseGroupStore)
if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseID))
_phasesByGroup[group->PhaseGroupID].insert(phase->ID);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 6fc9ab614b9..3dff3d2a4c0 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -31,7 +31,6 @@ extern DB2Storage<ItemEntry> sItemStore;
extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
extern DB2Storage<ItemSparseEntry> sItemSparseStore;
extern DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore;
-extern DB2Storage<PhaseGroupEntry> sPhaseGroupStore;
extern DB2Storage<SoundEntriesEntry> sSoundEntriesStore;
extern DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore;
extern DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 8145ae743a9..032d94425ef 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -289,7 +289,7 @@ struct OverrideSpellDataEntry
uint32 PlayerActionbarFileDataID; // 12
};
-struct PhaseGroupEntry
+struct PhaseXPhaseGroupEntry
{
uint32 ID;
uint32 PhaseID;
diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h
index e660adee257..1920f2b90b4 100644
--- a/src/server/game/DataStores/DB2fmt.h
+++ b/src/server/game/DataStores/DB2fmt.h
@@ -37,7 +37,7 @@ char const ItemXBonusTreeFormat[] = "nii";
char const KeyChainFormat[] = "nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
char const MountFormat[] = "niiisssiii";
char const OverrideSpellDataFormat[] = "niiiiiiiiiiii";
-char const PhaseGroupFormat[] = "nii";
+char const PhaseXPhaseGroupFormat[] = "nii";
char const SoundEntriesFormat[] = "nisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiififfiifffffii";
char const SpellAuraRestrictionsFormat[] = "niiiiiiii";
char const SpellCastingRequirementsFormat[] = "niiiiii";
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 299b68b9be1..3d4e7ad02cb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2904,21 +2904,27 @@ void Player::GiveLevel(uint8 level)
uint32 basehp = 0, basemana = 0;
sObjectMgr->GetPlayerClassLevelInfo(getClass(), level, basehp, basemana);
- // send levelup info to client
- WorldPacket data(SMSG_LEVELUP_INFO, (4+4+MAX_POWERS_PER_CLASS*4+MAX_STATS*4));
- data << uint32(level);
- data << uint32(int32(basehp) - int32(GetCreateHealth()));
- // for (int i = 0; i < MAX_STORED_POWERS; ++i) // Powers loop (0-10)
- data << uint32(int32(basemana) - int32(GetCreateMana()));
- data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- // end for
- for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4)
- data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i)));
+ WorldPackets::Misc::LevelUpInfo packet;
+ packet.Level = level;
+ packet.HealthDelta = int32(basehp) - int32(GetCreateHealth());
+
+ /// @todo find some better solution
+ // for (int i = 0; i < MAX_STORED_POWERS; ++i)
+ packet.PowerDelta[0] = int32(basemana) - int32(GetCreateMana());
+ packet.PowerDelta[1] = 0;
+ packet.PowerDelta[2] = 0;
+ packet.PowerDelta[3] = 0;
+ packet.PowerDelta[4] = 0;
+ packet.PowerDelta[5] = 0;
- GetSession()->SendPacket(&data);
+ for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ packet.StatDelta[i] = int32(info.stats[i]) - GetCreateStat(Stats(i));
+
+ uint32 const* rowLevels = (getClass() != CLASS_DEATH_KNIGHT) ? DefaultTalentRowLevels : DKTalentRowLevels;
+
+ packet.Cp = std::find(rowLevels, rowLevels + MAX_TALENT_TIERS, level) != (rowLevels + MAX_TALENT_TIERS);
+
+ GetSession()->SendPacket(packet.Write());
SetUInt32Value(PLAYER_NEXT_LEVEL_XP, sObjectMgr->GetXPForLevel(level));
@@ -4394,6 +4400,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_ARENA_STATS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_EFFECT);
stmt->setUInt64(0, guid);
trans->Append(stmt);
@@ -4402,6 +4412,22 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_BGDATA);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_CUF_PROFILES);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CURRENCY);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_GIFT);
stmt->setUInt64(0, guid);
trans->Append(stmt);
@@ -4499,10 +4525,6 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_BGDATA);
- stmt->setUInt64(0, guid);
- trans->Append(stmt);
-
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_GLYPHS);
stmt->setUInt64(0, guid);
trans->Append(stmt);
@@ -4531,6 +4553,14 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_STATS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
CharacterDatabase.CommitTransaction(trans);
sWorld->DeleteCharacterInfo(playerguid);
@@ -19276,7 +19306,7 @@ void Player::_SaveCUFProfiles(SQLTransaction& trans)
if (!_CUFProfiles[i]) // unused profile
{
// DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_CUF_PROFILES);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_CUF_PROFILES_BY_ID);
stmt->setUInt64(0, GetGUID().GetCounter());
stmt->setUInt8(1, i);
}
@@ -26613,9 +26643,6 @@ void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell)
uint32 Player::CalculateTalentsTiers() const
{
- static uint32 const DefaultTalentRowLevels[MAX_TALENT_TIERS] = { 15, 30, 45, 60, 75, 90, 100 };
- static uint32 const DKTalentRowLevels[MAX_TALENT_TIERS] = { 57, 58, 59, 60, 75, 90, 100 };
-
uint32 const* rowLevels = (getClass() != CLASS_DEATH_KNIGHT) ? DefaultTalentRowLevels : DKTalentRowLevels;
for (uint32 i = MAX_TALENT_TIERS; i; --i)
if (getLevel() >= rowLevels[i - 1])
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index a2d5ed72bd8..9d05aad8304 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1285,6 +1285,9 @@ private:
bool _isPvP;
};
+static uint32 const DefaultTalentRowLevels[MAX_TALENT_TIERS] = { 15, 30, 45, 60, 75, 90, 100 };
+static uint32 const DKTalentRowLevels[MAX_TALENT_TIERS] = { 57, 58, 59, 60, 75, 90, 100 };
+
struct PlayerTalentInfo
{
PlayerTalentInfo() :
diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp
index e273de90b7f..b597e6e5de2 100644
--- a/src/server/game/Server/Packets/MiscPackets.cpp
+++ b/src/server/game/Server/Packets/MiscPackets.cpp
@@ -338,3 +338,19 @@ WorldPacket const* WorldPackets::Misc::ExplorationExperience::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Misc::LevelUpInfo::Write()
+{
+ _worldPacket << int32(Level);
+ _worldPacket << int32(HealthDelta);
+
+ for (int32 power : PowerDelta)
+ _worldPacket << power;
+
+ for (int32 stat : StatDelta)
+ _worldPacket << stat;
+
+ _worldPacket << int32(Cp);
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h
index 08917034933..5511660eced 100644
--- a/src/server/game/Server/Packets/MiscPackets.h
+++ b/src/server/game/Server/Packets/MiscPackets.h
@@ -479,6 +479,20 @@ namespace WorldPackets
int32 Experience = 0;
int32 AreaID = 0;
};
+
+ class LevelUpInfo final : public ServerPacket
+ {
+ public:
+ LevelUpInfo() : ServerPacket(SMSG_LEVELUP_INFO, 56) { }
+
+ WorldPacket const* Write() override;
+
+ int32 Level = 0;
+ int32 HealthDelta = 0;
+ std::array<int32, 6> PowerDelta;
+ std::array<int32, MAX_STATS> StatDelta;
+ int32 Cp = 0;
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 10cc4473ccb..57234e69373 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1361,7 +1361,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_DANCE_MOVES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_TALENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEVELUP_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEVELUP_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_BOOT_PLAYER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index 8db861707a6..c9e014af70e 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -1295,7 +1295,7 @@ enum OpcodeServer : uint32
SMSG_LEARNED_DANCE_MOVES = 0xBADD,
SMSG_LEARNED_SPELLS = 0x08E9,
SMSG_LEARN_TALENT_FAILED = 0xBADD,
- SMSG_LEVELUP_INFO = 0xBADD,
+ SMSG_LEVELUP_INFO = 0x092C,
SMSG_LFG_BOOT_PLAYER = 0xBADD,
SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0xBADD,
SMSG_LFG_DISABLED = 0xBADD,
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index 8e3aff790d8..5497f4cc0e3 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -21,10 +21,11 @@
#include "DatabaseEnv.h"
#include "UpdateFields.h"
#include "ObjectMgr.h"
+#include "Player.h"
#include "AccountMgr.h"
#include "World.h"
-#define DUMP_TABLE_COUNT 29
+#define DUMP_TABLE_COUNT 30
struct DumpTable
{
char const* name;
@@ -38,9 +39,10 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "character_achievement", DTT_CHAR_TABLE },
{ "character_achievement_progress", DTT_CHAR_TABLE },
{ "character_action", DTT_CHAR_TABLE },
- { "character_aura", DTT_CHAR_TABLE },
- { "character_currency", DTT_CHAR_TABLE },
+ // { "character_aura", DTT_CHAR_TABLE }, /// @todo: reguid casterguid (full guid)
+ // { "character_aura_effect", DTT_CHAR_TABLE }, /// @todo: reguid casterguid (full guid)
{ "character_cuf_profiles", DTT_CHAR_TABLE },
+ { "character_currency", DTT_CURRENCY },
{ "character_declinedname", DTT_CHAR_TABLE },
{ "character_equipmentsets", DTT_EQSET_TABLE},
{ "character_glyphs", DTT_CHAR_TABLE },
@@ -49,27 +51,36 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "character_pet", DTT_PET },
{ "character_pet_declinedname", DTT_PET },
{ "character_queststatus", DTT_CHAR_TABLE },
+ { "character_queststatus_objectives", DTT_CHAR_TABLE },
{ "character_queststatus_rewarded", DTT_CHAR_TABLE },
{ "character_reputation", DTT_CHAR_TABLE },
{ "character_skills", DTT_CHAR_TABLE },
{ "character_spell", DTT_CHAR_TABLE },
+ { "character_spell_charges", DTT_CHAR_TABLE },
{ "character_spell_cooldown", DTT_CHAR_TABLE },
{ "character_talent", DTT_CHAR_TABLE },
+ /// @todo: character_void_storage
{ "mail", DTT_MAIL },
{ "mail_items", DTT_MAIL_ITEM }, // must be after mail
- { "pet_aura", DTT_PET_TABLE }, // must be after character_pet
+ // { "pet_aura", DTT_PET_TABLE }, // must be after character_pet /// @todo: reguid casterguid (full guid)
+ // { "pet_aura_effect", DTT_PET_TABLE }, // must be after character_pet /// @todo: reguid casterguid (full guid)
{ "pet_spell", DTT_PET_TABLE }, // must be after character_pet
+ { "pet_spell_charges", DTT_PET_TABLE }, // must be after character_pet
{ "pet_spell_cooldown", DTT_PET_TABLE }, // must be after character_pet
{ "item_instance", DTT_ITEM }, // must be after character_inventory and mail_items
{ "character_gifts", DTT_ITEM_GIFT }, // must be after item_instance
};
// Low level functions
-static bool findtoknth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e)
+static bool FindTokNth(std::string const& str, uint32 n, std::string::size_type& s, std::string::size_type& e)
{
- int i; s = e = 0;
- std::string::size_type size = str.size();
- for (i = 1; s < size && i < n; s++) if (str[s] == ' ') ++i;
+ s = e = 0;
+
+ uint32 i = 1;
+ for (; s < str.size() && i < n; ++s)
+ if (str[s] == ' ')
+ ++i;
+
if (i < n)
return false;
@@ -78,80 +89,86 @@ static bool findtoknth(std::string &str, int n, std::string::size_type &s, std::
return e != std::string::npos;
}
-std::string gettoknth(std::string &str, int n)
+std::string GetTokNth(std::string const& str, uint32 n)
{
std::string::size_type s = 0, e = 0;
- if (!findtoknth(str, n, s, e))
+ if (!FindTokNth(str, n, s, e))
return "";
- return str.substr(s, e-s);
+ return str.substr(s, e - s);
}
-bool findnth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e)
+bool FindNth(std::string const& str, uint32 n, std::string::size_type& s, std::string::size_type& e)
{
- s = str.find("VALUES ('")+9;
- if (s == std::string::npos) return false;
+ s = str.find("VALUES ('") + 9;
+ if (s == std::string::npos)
+ return false;
do
{
e = str.find('\'', s);
- if (e == std::string::npos) return false;
- } while (str[e-1] == '\\');
+ if (e == std::string::npos)
+ return false;
+ } while (str[e - 1] == '\\');
- for (int i = 1; i < n; ++i)
+ for (uint32 i = 1; i < n; ++i)
{
do
{
- s = e+4;
+ s = e + 4;
e = str.find('\'', s);
- if (e == std::string::npos) return false;
- } while (str[e-1] == '\\');
+ if (e == std::string::npos)
+ return false;
+ } while (str[e - 1] == '\\');
}
return true;
}
-std::string gettablename(std::string &str)
+std::string GetTableName(std::string const& str)
{
- std::string::size_type s = 13;
+ static std::string::size_type const s = 13;
std::string::size_type e = str.find(_TABLE_SIM_, s);
if (e == std::string::npos)
return "";
- return str.substr(s, e-s);
+ return str.substr(s, e - s);
}
-bool changenth(std::string &str, int n, char const* with, bool insert = false, bool nonzero = false)
+bool ChangeNth(std::string& str, uint32 n, char const* with, bool insert = false, bool allowZero = false)
{
std::string::size_type s, e;
- if (!findnth(str, n, s, e))
+ if (!FindNth(str, n, s, e))
return false;
- if (nonzero && str.substr(s, e-s) == "0")
+ if (allowZero && str.substr(s, e - s) == "0")
return true; // not an error
+
if (!insert)
- str.replace(s, e-s, with);
+ str.replace(s, e - s, with);
else
str.insert(s, with);
return true;
}
-std::string getnth(std::string &str, int n)
+std::string GetNth(std::string& str, uint32 n)
{
std::string::size_type s, e;
- if (!findnth(str, n, s, e))
+ if (!FindNth(str, n, s, e))
return "";
return str.substr(s, e-s);
}
-bool changetoknth(std::string &str, int n, char const* with, bool insert = false, bool nonzero = false)
+bool ChangeTokNth(std::string& str, uint32 n, char const* with, bool insert = false, bool allowZero = false)
{
std::string::size_type s = 0, e = 0;
- if (!findtoknth(str, n, s, e))
+ if (!FindTokNth(str, n, s, e))
return false;
- if (nonzero && str.substr(s, e-s) == "0")
+
+ if (allowZero && str.substr(s, e - s) == "0")
return true; // not an error
+
if (!insert)
str.replace(s, e-s, with);
else
@@ -160,28 +177,28 @@ bool changetoknth(std::string &str, int n, char const* with, bool insert = false
return true;
}
-uint64 registerNewGuid(uint64 oldGuid, std::map<uint64, uint64> &guidMap, uint64 hiGuid)
+ObjectGuid::LowType RegisterNewGuid(ObjectGuid::LowType oldGuid, PlayerDump::DumpGuidMap& guidMap, ObjectGuid::LowType guidOffset)
{
- std::map<uint64, uint64>::const_iterator itr = guidMap.find(oldGuid);
+ PlayerDumpWriter::DumpGuidMap::const_iterator itr = guidMap.find(oldGuid);
if (itr != guidMap.end())
return itr->second;
- uint64 newguid = hiGuid + guidMap.size();
+ ObjectGuid::LowType newguid = guidOffset + guidMap.size();
guidMap[oldGuid] = newguid;
return newguid;
}
-bool changeGuid(std::string &str, int n, std::map<uint64, uint64> &guidMap, uint64 hiGuid, bool nonzero = false)
+bool ChangeGuid(std::string& str, uint32 n, PlayerDump::DumpGuidMap& guidMap, ObjectGuid::LowType guidOffset, bool allowZero = false)
{
- char chritem[21];
- ObjectGuid::LowType oldGuid = strtoull(getnth(str, n).c_str(), nullptr, 10);
- if (nonzero && !oldGuid)
+ ObjectGuid::LowType oldGuid = strtoull(GetNth(str, n).c_str(), nullptr, 10);
+ if (allowZero && !oldGuid)
return true; // not an error
- uint64 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid);
+ char chritem[21];
+ ObjectGuid::LowType newGuid = RegisterNewGuid(oldGuid, guidMap, guidOffset);
snprintf(chritem, 21, UI64FMTD, newGuid);
- return changenth(str, n, chritem, false, nonzero);
+ return ChangeNth(str, n, chritem, false, allowZero);
}
std::string CreateDumpString(char const* tableName, QueryResult result)
@@ -212,29 +229,26 @@ std::string PlayerDumpWriter::GenerateWhereStr(char const* field, ObjectGuid::Lo
return wherestr.str();
}
-std::string PlayerDumpWriter::GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr)
+std::string PlayerDumpWriter::GenerateWhereStr(char const* field, DumpGuidSet const& guids, DumpGuidSet::const_iterator& itr)
{
std::ostringstream wherestr;
wherestr << field << " IN ('";
- for (; itr != guids.end(); ++itr)
+ for (; itr != guids.end();)
{
wherestr << *itr;
+ ++itr;
if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query
- {
- ++itr;
break;
- }
- GUIDs::const_iterator itr2 = itr;
- if (++itr2 != guids.end())
+ if (itr != guids.end())
wherestr << "', '";
}
wherestr << "')";
return wherestr.str();
}
-void StoreGUID(QueryResult result, uint32 field, PlayerDumpWriter::GUIDs &guids)
+void StoreGUID(QueryResult result, uint32 field, PlayerDump::DumpGuidSet &guids)
{
Field* fields = result->Fetch();
ObjectGuid::LowType guid = fields[field].GetUInt64();
@@ -242,23 +256,24 @@ void StoreGUID(QueryResult result, uint32 field, PlayerDumpWriter::GUIDs &guids)
guids.insert(guid);
}
-void StoreGUID(QueryResult result, uint32 data, uint32 field, PlayerDumpWriter::GUIDs& guids)
+void StoreGUID(QueryResult result, uint32 data, uint32 field, PlayerDump::DumpGuidSet& guids)
{
Field* fields = result->Fetch();
std::string dataStr = fields[data].GetString();
- ObjectGuid::LowType guid = strtoull(gettoknth(dataStr, field).c_str(), nullptr, 10);
+ ObjectGuid::LowType guid = strtoull(GetTokNth(dataStr, field).c_str(), nullptr, 10);
if (guid)
guids.insert(guid);
}
// Writing - High-level functions
-bool PlayerDumpWriter::DumpTable(std::string& dump, ObjectGuid::LowType guid, char const*tableFrom, char const*tableTo, DumpTableType type)
+bool PlayerDumpWriter::DumpTable(std::string& dump, ObjectGuid::LowType guid, char const* tableFrom, char const* tableTo, DumpTableType type)
{
- GUIDs const* guids = NULL;
- char const* fieldname = NULL;
+ DumpGuidSet const* guids = nullptr;
+ char const* fieldname = nullptr;
switch (type)
{
+ case DTT_CURRENCY: fieldname = "CharacterGuid"; break;
case DTT_ITEM: fieldname = "guid"; guids = &items; break;
case DTT_ITEM_GIFT: fieldname = "item_guid"; guids = &items; break;
case DTT_PET: fieldname = "owner"; break;
@@ -270,20 +285,20 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, ObjectGuid::LowType guid, ch
// for guid set stop if set is empty
if (guids && guids->empty())
- return true; // nothing to do
+ return true; // nothing to do
// setup for guids case start position
- GUIDs::const_iterator guids_itr;
+ DumpGuidSet::const_iterator guidsItr;
if (guids)
- guids_itr = guids->begin();
+ guidsItr = guids->begin();
do
{
std::string wherestr;
- if (guids) // set case, get next guids string
- wherestr = GenerateWhereStr(fieldname, *guids, guids_itr);
- else // not set case, get single guid string
+ if (guids) // set case, get next guids string
+ wherestr = GenerateWhereStr(fieldname, *guids, guidsItr);
+ else // not set case, get single guid string
wherestr = GenerateWhereStr(fieldname, guid);
QueryResult result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str());
@@ -328,7 +343,7 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, ObjectGuid::LowType guid, ch
}
while (result->NextRow());
}
- while (guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids
+ while (guids && guidsItr != guids->end()); // not set case iterate single time, set case iterate for all guids
return true;
}
@@ -337,7 +352,7 @@ bool PlayerDumpWriter::GetDump(ObjectGuid::LowType guid, std::string &dump)
dump = "IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n";
dump += "IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n";
- for (int i = 0; i < DUMP_TABLE_COUNT; ++i)
+ for (uint8 i = 0; i < DUMP_TABLE_COUNT; ++i)
if (!DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type))
return false;
@@ -352,12 +367,14 @@ DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, ObjectGuid::LowT
if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_PATHS))
if (strstr(file.c_str(), "\\") || strstr(file.c_str(), "/"))
return DUMP_FILE_OPEN_ERROR;
+
if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_OVERWRITE))
if (FILE* f = fopen(file.c_str(), "r"))
{
fclose(f);
return DUMP_FILE_OPEN_ERROR;
}
+
FILE* fout = fopen(file.c_str(), "w");
if (!fout)
return DUMP_FILE_OPEN_ERROR;
@@ -375,9 +392,9 @@ DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, ObjectGuid::LowT
// Reading - High-level functions
#define ROLLBACK(DR) {fclose(fin); return (DR);}
-void fixNULLfields(std::string &line)
+void fixNULLfields(std::string& line)
{
- std::string nullString("'NULL'");
+ static std::string const nullString("'NULL'");
size_t pos = line.find(nullString);
while (pos != std::string::npos)
{
@@ -396,7 +413,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
if (!fin)
return DUMP_FILE_OPEN_ERROR;
- char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20];
+ char newguid[20], chraccount[20];
// make sure the same guid doesn't already exist and is safe to use
bool incHighest = true;
@@ -408,7 +425,8 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
if (result)
guid = sObjectMgr->GetGenerator<HighGuid::Player>()->GetNextAfterMaxUsed(); // use first free if exists
- else incHighest = false;
+ else
+ incHighest = false;
}
else
guid = sObjectMgr->GetGenerator<HighGuid::Player>()->GetNextAfterMaxUsed();
@@ -433,22 +451,21 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
snprintf(newguid, 20, UI64FMTD, guid);
snprintf(chraccount, 20, "%u", account);
- snprintf(newpetid, 20, "%u", sObjectMgr->GeneratePetNumber());
- snprintf(lastpetid, 20, "%s", "");
- std::map<uint64, uint64> items;
- std::map<uint64, uint64> mails;
+ DumpGuidMap items;
+ DumpGuidMap mails;
char buf[32000] = "";
- typedef std::map<uint32, uint32> PetIds; // old->new petid relation
- typedef PetIds::value_type PetIdsPair;
- PetIds petids;
+ typedef std::map<uint32 /*old*/, uint32 /*new*/> PetIds;
+ PetIds petIds;
uint8 gender = GENDER_NONE;
uint8 race = RACE_NONE;
uint8 playerClass = 0;
uint8 level = 1;
+ ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed();
+
SQLTransaction trans = CharacterDatabase.BeginTransaction();
while (!feof(fin))
{
@@ -484,7 +501,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
*/
// determine table name and load type
- std::string tn = gettablename(line);
+ std::string tn = GetTableName(line);
if (tn.empty())
{
TC_LOG_ERROR("misc", "LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str());
@@ -513,142 +530,140 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
{
case DTT_CHARACTER:
{
- if (!changenth(line, 1, newguid)) // characters.guid update
+ if (!ChangeNth(line, 1, newguid)) // characters.guid update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 2, chraccount)) // characters.account update
+ if (!ChangeNth(line, 2, chraccount)) // characters.account update
ROLLBACK(DUMP_FILE_BROKEN);
- race = uint8(atoul(getnth(line, 4).c_str()));
- playerClass = uint8(atoul(getnth(line, 5).c_str()));
- gender = uint8(atoul(getnth(line, 6).c_str()));
- level = uint8(atoul(getnth(line, 7).c_str()));
+ race = uint8(atoul(GetNth(line, 4).c_str()));
+ playerClass = uint8(atoul(GetNth(line, 5).c_str()));
+ gender = uint8(atoul(GetNth(line, 6).c_str()));
+ level = uint8(atoul(GetNth(line, 7).c_str()));
if (name.empty())
{
// check if the original name already exists
- name = getnth(line, 3);
+ name = GetNth(line, 3);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, name);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
- if (!changenth(line, 38, "1")) // characters.at_login set to "rename on login"
+ if (!ChangeNth(line, 41, "1")) // characters.at_login set to "rename on login"
ROLLBACK(DUMP_FILE_BROKEN);
}
- else if (!changenth(line, 3, name.c_str())) // characters.name
+ else if (!ChangeNth(line, 3, name.c_str())) // characters.name
ROLLBACK(DUMP_FILE_BROKEN);
const char null[5] = "NULL";
- if (!changenth(line, 63, null)) // characters.deleteInfos_Account
+ if (!ChangeNth(line, 65, null)) // characters.deleteInfos_Account
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 64, null)) // characters.deleteInfos_Name
+ if (!ChangeNth(line, 66, null)) // characters.deleteInfos_Name
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 65, null)) // characters.deleteDate
+ if (!ChangeNth(line, 67, null)) // characters.deleteDate
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_CHAR_TABLE:
+ case DTT_CURRENCY:
{
- if (!changenth(line, 1, newguid)) // character_*.guid update
+ if (!ChangeNth(line, 1, newguid)) // character_*.guid update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_EQSET_TABLE:
{
- if (!changenth(line, 1, newguid))
+ if (!ChangeNth(line, 1, newguid))
ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid
char newSetGuid[24];
snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid());
- if (!changenth(line, 2, newSetGuid))
+ if (!ChangeNth(line, 2, newSetGuid))
ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid
+
+ for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
+ if (!ChangeGuid(line, 7 + slot, items, itemLowGuidOffset, true))
+ ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.item
break;
}
case DTT_INVENTORY:
{
- if (!changenth(line, 1, newguid)) // character_inventory.guid update
+ if (!ChangeNth(line, 1, newguid)) // character_inventory.guid update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changeGuid(line, 2, items, sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed(), true))
+ if (!ChangeGuid(line, 2, items, itemLowGuidOffset, true))
ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update
- if (!changeGuid(line, 4, items, sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed()))
+ if (!ChangeGuid(line, 4, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update
break;
}
case DTT_MAIL: // mail
{
- if (!changeGuid(line, 1, mails, sObjectMgr->_mailId))
+ if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId))
ROLLBACK(DUMP_FILE_BROKEN); // mail.id update
- if (!changenth(line, 6, newguid)) // mail.receiver update
+ if (!ChangeNth(line, 6, newguid)) // mail.receiver update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_MAIL_ITEM: // mail_items
{
- if (!changeGuid(line, 1, mails, sObjectMgr->_mailId))
+ if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId))
ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id
- if (!changeGuid(line, 2, items, sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed()))
+ if (!ChangeGuid(line, 2, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid
- if (!changenth(line, 3, newguid)) // mail_items.receiver
+ if (!ChangeNth(line, 3, newguid)) // mail_items.receiver
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_ITEM:
{
// item, owner, data field:item, owner guid
- if (!changeGuid(line, 1, items, sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed()))
+ if (!ChangeGuid(line, 1, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update
- if (!changenth(line, 3, newguid)) // item_instance.owner_guid update
+ if (!ChangeNth(line, 3, newguid)) // item_instance.owner_guid update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_ITEM_GIFT:
{
- if (!changenth(line, 1, newguid)) // character_gifts.guid update
+ if (!ChangeNth(line, 1, newguid)) // character_gifts.guid update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changeGuid(line, 2, items, sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed()))
+ if (!ChangeGuid(line, 2, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update
break;
}
case DTT_PET:
{
- //store a map of old pet id to new inserted pet id for use by type 5 tables
- snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
- if (*lastpetid == '\0')
- snprintf(lastpetid, 20, "%s", currpetid);
- if (strcmp(lastpetid, currpetid) != 0)
- {
- snprintf(newpetid, 20, "%u", sObjectMgr->GeneratePetNumber());
- snprintf(lastpetid, 20, "%s", currpetid);
- }
+ // store a map of old pet id to new inserted pet id for use by DTT_PET_TABLE tables
+ std::string petIdStr = GetNth(line, 1);
- std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
+ uint32 currentPetId = atoul(petIdStr.c_str());
- if (petids_iter == petids.end())
- {
- petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid)));
- }
+ PetIds::const_iterator petIdsItr = petIds.find(currentPetId);
+ if (petIdsItr != petIds.end()) // duplicate pets
+ ROLLBACK(DUMP_FILE_BROKEN);
+
+ uint32 newPetId = sObjectMgr->GeneratePetNumber();
+ petIds[currentPetId] = newPetId;
- if (!changenth(line, 1, newpetid)) // character_pet.id update
+ if (!ChangeNth(line, 1, std::to_string(newPetId).c_str())) // character_pet.id update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 3, newguid)) // character_pet.owner update
+ if (!ChangeNth(line, 3, newguid)) // character_pet.owner update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown
{
- snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
+ std::string petIdStr = GetNth(line, 1);
// lookup currpetid and match to new inserted pet id
- std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
- if (petids_iter == petids.end()) // couldn't find new inserted id
+ PetIds::const_iterator petIdsItr = petIds.find(atoul(petIdStr.c_str()));
+ if (petIdsItr == petIds.end()) // couldn't find new inserted id
ROLLBACK(DUMP_FILE_BROKEN);
- snprintf(newpetid, 20, "%d", petids_iter->second);
-
- if (!changenth(line, 1, newpetid))
+ if (!ChangeNth(line, 1, std::to_string(petIdsItr->second).c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
break;
diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h
index 1decdfa3aea..73adcd6d96e 100644
--- a/src/server/game/Tools/PlayerDump.h
+++ b/src/server/game/Tools/PlayerDump.h
@@ -32,7 +32,9 @@ enum DumpTableType
// character_action, character_aura, character_homebind,
// character_queststatus, character_queststatus_rewarded, character_reputation,
// character_spell, character_spell_cooldown, character_ticket, character_talent.
- // character_cuf_profiles, character_currency
+ // character_cuf_profiles
+
+ DTT_CURRENCY, // // character_currency
DTT_EQSET_TABLE, // <- guid // character_equipmentsets
@@ -65,6 +67,10 @@ enum DumpReturn
class PlayerDump
{
+ public:
+ typedef std::set<ObjectGuid::LowType> DumpGuidSet;
+ typedef std::map<ObjectGuid::LowType, ObjectGuid::LowType> DumpGuidMap;
+
protected:
PlayerDump() { }
};
@@ -74,18 +80,18 @@ class PlayerDumpWriter : public PlayerDump
public:
PlayerDumpWriter() { }
- typedef std::set<ObjectGuid::LowType> GUIDs;
bool GetDump(ObjectGuid::LowType guid, std::string& dump);
DumpReturn WriteDump(std::string const& file, ObjectGuid::LowType guid);
+
private:
- bool DumpTable(std::string& dump, ObjectGuid::LowType guid, char const*tableFrom, char const*tableTo, DumpTableType type);
- std::string GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr);
+ bool DumpTable(std::string& dump, ObjectGuid::LowType guid, char const* tableFrom, char const* tableTo, DumpTableType type);
+ std::string GenerateWhereStr(char const* field, DumpGuidSet const& guids, DumpGuidSet::const_iterator& itr);
std::string GenerateWhereStr(char const* field, ObjectGuid::LowType guid);
- GUIDs pets;
- GUIDs mails;
- GUIDs items;
+ DumpGuidSet pets;
+ DumpGuidSet mails;
+ DumpGuidSet items;
};
class PlayerDumpReader : public PlayerDump
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index e876823ea96..c51c9e3ecc4 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -3125,7 +3125,7 @@ void World::ResetRandomBG()
{
TC_LOG_INFO("misc", "Random BG status reset for all characters.");
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM_ALL);
CharacterDatabase.Execute(stmt);
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
diff --git a/src/server/shared/DataStores/DB2StorageLoader.cpp b/src/server/shared/DataStores/DB2StorageLoader.cpp
index 67bf3008ca2..062cc251450 100644
--- a/src/server/shared/DataStores/DB2StorageLoader.cpp
+++ b/src/server/shared/DataStores/DB2StorageLoader.cpp
@@ -18,10 +18,7 @@
#include "Common.h"
#include "DB2StorageLoader.h"
#include "Database/DatabaseEnv.h"
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
+#include "Log.h"
DB2FileLoader::DB2FileLoader()
{
@@ -422,7 +419,7 @@ char* DB2FileLoader::AutoProduceStrings(const char* format, char* dataTable, uin
return stringPool;
}
-char* DB2DatabaseLoader::Load(const char* format, int32 preparedStatement, uint32& records, char**& indexTable, char*& stringHolders, std::list<char*>& stringPool)
+char* DB2DatabaseLoader::Load(const char* format, uint32 preparedStatement, uint32& records, char**& indexTable, char*& stringHolders, std::list<char*>& stringPool)
{
// Even though this query is executed only once, prepared statement is used to send data from mysql server in binary format
PreparedQueryResult result = HotfixDatabase.Query(HotfixDatabase.GetPreparedStatement(preparedStatement));
@@ -563,7 +560,7 @@ char* DB2DatabaseLoader::Load(const char* format, int32 preparedStatement, uint3
return dataTable;
}
-void DB2DatabaseLoader::LoadStrings(const char* format, int32 preparedStatement, uint32 locale, char**& indexTable, std::list<char*>& stringPool)
+void DB2DatabaseLoader::LoadStrings(const char* format, uint32 preparedStatement, uint32 locale, char**& indexTable, std::list<char*>& stringPool)
{
PreparedStatement* stmt = HotfixDatabase.GetPreparedStatement(preparedStatement);
stmt->setString(0, localeNames[locale]);
@@ -588,35 +585,40 @@ void DB2DatabaseLoader::LoadStrings(const char* format, int32 preparedStatement,
uint32 indexValue = fields[0].GetUInt32();
// Attempt to overwrite existing data
- char* dataValue = indexTable[indexValue];
- for (uint32 x = 0; x < fieldCount; x++)
+ if (char* dataValue = indexTable[indexValue])
{
- switch (format[x])
+ for (uint32 x = 0; x < fieldCount; x++)
{
- case FT_FLOAT:
- case FT_IND:
- case FT_INT:
- offset += 4;
- break;
- case FT_BYTE:
- offset += 1;
- break;
- case FT_STRING:
+ switch (format[x])
{
- // fill only not filled entries
- LocalizedString* db2str = *(LocalizedString**)(&dataValue[offset]);
- if (db2str->Str[locale] == nullStr)
- if (char* str = AddLocaleString(db2str, locale, fields[1 + stringFieldNumInRecord].GetString()))
- stringPool.push_back(str);
-
- ++stringFieldNumInRecord;
- offset += sizeof(char*);
- break;
+ 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
+ LocalizedString* db2str = *(LocalizedString**)(&dataValue[offset]);
+ if (db2str->Str[locale] == nullStr)
+ if (char* str = AddLocaleString(db2str, locale, fields[1 + stringFieldNumInRecord].GetString()))
+ stringPool.push_back(str);
+
+ ++stringFieldNumInRecord;
+ offset += sizeof(char*);
+ break;
+ }
}
}
+
+ ASSERT(offset == recordSize);
}
+ else
+ TC_LOG_ERROR("sql.sql", "Hotfix locale table for storage %s references row that does not exist %u!", _storageName.c_str(), indexValue);
- ASSERT(offset == recordSize);
} while (result->NextRow());
return;
diff --git a/src/server/shared/DataStores/DB2StorageLoader.h b/src/server/shared/DataStores/DB2StorageLoader.h
index 0dc340868b7..31fc1d1e979 100644
--- a/src/server/shared/DataStores/DB2StorageLoader.h
+++ b/src/server/shared/DataStores/DB2StorageLoader.h
@@ -109,9 +109,14 @@ private:
class DB2DatabaseLoader
{
public:
- char* Load(const char* format, int32 preparedStatement, uint32& records, char**& indexTable, char*& stringHolders, std::list<char*>& stringPool);
- void LoadStrings(const char* format, int32 preparedStatement, uint32 locale, char**& indexTable, std::list<char*>& stringPool);
+ explicit DB2DatabaseLoader(std::string const& storageName) : _storageName(storageName) { }
+
+ char* Load(const char* format, uint32 preparedStatement, uint32& records, char**& indexTable, char*& stringHolders, std::list<char*>& stringPool);
+ void LoadStrings(const char* format, uint32 preparedStatement, uint32 locale, char**& indexTable, std::list<char*>& stringPool);
static char* AddLocaleString(LocalizedString* holder, uint32 locale, std::string const& value);
+
+private:
+ std::string _storageName;
};
#endif
diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h
index 4abec4f5386..4ce77c1cd28 100644
--- a/src/server/shared/DataStores/DB2Store.h
+++ b/src/server/shared/DataStores/DB2Store.h
@@ -48,13 +48,20 @@ class DB2Storage : public DB2StorageBase
public:
typedef DBStorageIterator<T> iterator;
- DB2Storage(char const* f, int32 preparedStmtIndex)
- : _indexTableSize(0), _fieldCount(0), _format(f), _dataTable(nullptr), _dataTableEx(nullptr), _hotfixStatement(preparedStmtIndex)
+ DB2Storage(char const* fileName, char const* format, uint32 preparedStmtIndex)
+ : _fileName(fileName), _indexTableSize(0), _fieldCount(0), _format(format), _dataTable(nullptr), _dataTableEx(nullptr), _hotfixStatement(preparedStmtIndex)
{
_indexTable.AsT = NULL;
}
- ~DB2Storage() { Clear(); }
+ ~DB2Storage()
+ {
+ delete[] reinterpret_cast<char*>(_indexTable.AsT);
+ delete[] reinterpret_cast<char*>(_dataTable);
+ delete[] reinterpret_cast<char*>(_dataTableEx);
+ for (char* stringPool : _stringPoolList)
+ delete[] stringPool;
+ }
bool HasRecord(uint32 id) const override { return id < _indexTableSize && _indexTable.AsT[id] != nullptr; }
void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const override
@@ -105,14 +112,15 @@ public:
void EraseRecord(uint32 id) override { if (id < _indexTableSize) _indexTable.AsT[id] = nullptr; }
T const* LookupEntry(uint32 id) const { return (id >= _indexTableSize) ? nullptr : _indexTable.AsT[id]; }
+ std::string const& GetFileName() const { return _fileName; }
uint32 GetNumRows() const { return _indexTableSize; }
char const* GetFormat() const { return _format; }
uint32 GetFieldCount() const { return _fieldCount; }
- bool Load(char const* fn, uint32 locale)
+ bool Load(std::string const& path, uint32 locale)
{
DB2FileLoader db2;
// Check if load was successful, only then continue
- if (!db2.Load(fn, _format))
+ if (!db2.Load((path + _fileName).c_str(), _format))
return false;
_fieldCount = db2.GetCols();
@@ -135,7 +143,7 @@ public:
return _indexTable.AsT != NULL;
}
- bool LoadStringsFrom(char const* fn, uint32 locale)
+ bool LoadStringsFrom(std::string const& path, uint32 locale)
{
// DB2 must be already loaded using Load
if (!_indexTable.AsT)
@@ -143,7 +151,7 @@ public:
DB2FileLoader db2;
// Check if load was successful, only then continue
- if (!db2.Load(fn, _format))
+ if (!db2.Load((path + _fileName).c_str(), _format))
return false;
// load strings from another locale db2 data
@@ -155,11 +163,8 @@ public:
void LoadFromDB()
{
- if (_hotfixStatement == -1)
- return;
-
char* extraStringHolders = nullptr;
- if (char* dataTable = DB2DatabaseLoader().Load(_format, _hotfixStatement, _indexTableSize, _indexTable.AsChar, extraStringHolders, _stringPoolList))
+ if (char* dataTable = DB2DatabaseLoader(_fileName).Load(_format, _hotfixStatement, _indexTableSize, _indexTable.AsChar, extraStringHolders, _stringPoolList))
_dataTableEx = reinterpret_cast<T*>(dataTable);
if (extraStringHolders)
@@ -168,42 +173,17 @@ public:
void LoadStringsFromDB(uint32 locale)
{
- if (_hotfixStatement == -1)
- return;
-
if (!DB2FileLoader::GetFormatStringFieldCount(_format))
return;
- DB2DatabaseLoader().LoadStrings(_format, _hotfixStatement + 1, locale, _indexTable.AsChar, _stringPoolList);
- }
-
- void Clear()
- {
- if (!_indexTable.AsT)
- return;
-
- delete[] reinterpret_cast<char*>(_indexTable.AsT);
- _indexTable.AsT = nullptr;
-
- delete[] reinterpret_cast<char*>(_dataTable);
- _dataTable = nullptr;
-
- delete[] reinterpret_cast<char*>(_dataTableEx);
- _dataTableEx = nullptr;
-
- while (!_stringPoolList.empty())
- {
- delete[] _stringPoolList.front();
- _stringPoolList.pop_front();
- }
-
- _indexTableSize = 0;
+ DB2DatabaseLoader(_fileName).LoadStrings(_format, _hotfixStatement + 1, locale, _indexTable.AsChar, _stringPoolList);
}
iterator begin() { return iterator(_indexTable.AsT, _indexTableSize); }
iterator end() { return iterator(_indexTable.AsT, _indexTableSize, _indexTableSize); }
private:
+ std::string _fileName;
uint32 _indexTableSize;
uint32 _fieldCount;
char const* _format;
@@ -215,7 +195,7 @@ private:
T* _dataTable;
T* _dataTableEx;
StringPoolList _stringPoolList;
- int32 _hotfixStatement;
+ uint32 _hotfixStatement;
};
#endif
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index e95b05bc418..012d1cc3938 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -69,7 +69,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM_ALL, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
@@ -270,6 +271,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_PLAYER_CURRENCY, "SELECT Currency, Quantity, WeeklyQuantity, TrackedQuantity, Flags FROM character_currency WHERE CharacterGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_PLAYER_CURRENCY, "UPDATE character_currency SET Quantity = ?, WeeklyQuantity = ?, TrackedQuantity = ?, Flags = ? WHERE CharacterGuid = ? AND Currency = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_PLAYER_CURRENCY, "REPLACE INTO character_currency (CharacterGuid, Currency, Quantity, WeeklyQuantity, TrackedQuantity, Flags) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_PLAYER_CURRENCY, "DELETE FROM character_currency WHERE CharacterGuid = ?", CONNECTION_ASYNC);
// Account data
PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_SYNCH);
@@ -319,6 +321,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_ARENA_TEAM_MEMBER, "DELETE FROM arena_team_member WHERE arenaTeamId = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ARENA_TEAM_STATS, "UPDATE arena_team SET rating = ?, weekGames = ?, weekWins = ?, seasonGames = ?, seasonWins = ?, rank = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ARENA_TEAM_MEMBER, "UPDATE arena_team_member SET personalRating = ?, weekGames = ?, weekWins = ?, seasonGames = ?, seasonWins = ? WHERE arenaTeamId = ? AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_ARENA_STATS, "DELETE FROM character_arena_stats WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_CHARACTER_ARENA_STATS, "REPLACE INTO character_arena_stats (guid, slot, matchMakerRating) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_PLAYER_ARENA_TEAMS, "SELECT arena_team_member.arenaTeamId FROM arena_team_member JOIN arena_team ON arena_team_member.arenaTeamId = arena_team.arenaTeamId WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_UPD_ARENA_TEAM_NAME, "UPDATE arena_team SET name = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC);
@@ -570,12 +573,14 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// Void Storage
PrepareStatement(CHAR_SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomProperty, suffixFactor FROM character_void_storage WHERE playerGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM, "REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomProperty, suffixFactor) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID, "DELETE FROM character_void_storage WHERE playerGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT, "DELETE FROM character_void_storage WHERE slot = ? AND playerGuid = ?", CONNECTION_ASYNC);
// CompactUnitFrame profiles
PrepareStatement(CHAR_SEL_CHAR_CUF_PROFILES, "SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_CHAR_CUF_PROFILES, "REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_CHAR_CUF_PROFILES, "DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_CUF_PROFILES_BY_ID, "DELETE FROM character_cuf_profiles WHERE guid = ? AND id = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_CUF_PROFILES, "DELETE FROM character_cuf_profiles WHERE guid = ?", CONNECTION_ASYNC);
// Guild Finder
PrepareStatement(CHAR_REP_GUILD_FINDER_APPLICANT, "REPLACE INTO guild_finder_applicant (guildId, playerGuid, availability, classRole, interests, comment, submitTime) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index 045a4c1fde6..6a9dc813386 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -72,6 +72,7 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHAR_POSITION_XYZ,
CHAR_SEL_CHAR_POSITION,
+ CHAR_DEL_BATTLEGROUND_RANDOM_ALL,
CHAR_DEL_BATTLEGROUND_RANDOM,
CHAR_INS_BATTLEGROUND_RANDOM,
@@ -234,6 +235,7 @@ enum CharacterDatabaseStatements
CHAR_SEL_PLAYER_CURRENCY,
CHAR_UPD_PLAYER_CURRENCY,
CHAR_REP_PLAYER_CURRENCY,
+ CHAR_DEL_PLAYER_CURRENCY,
CHAR_SEL_ACCOUNT_DATA,
CHAR_REP_ACCOUNT_DATA,
@@ -266,6 +268,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_ARENA_TEAM_MEMBER,
CHAR_UPD_ARENA_TEAM_STATS,
CHAR_UPD_ARENA_TEAM_MEMBER,
+ CHAR_DEL_CHARACTER_ARENA_STATS,
CHAR_REP_CHARACTER_ARENA_STATS,
CHAR_SEL_PLAYER_ARENA_TEAMS,
CHAR_UPD_ARENA_TEAM_NAME,
@@ -497,10 +500,12 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHAR_VOID_STORAGE,
CHAR_REP_CHAR_VOID_STORAGE_ITEM,
+ CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID,
CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT,
CHAR_SEL_CHAR_CUF_PROFILES,
CHAR_REP_CHAR_CUF_PROFILES,
+ CHAR_DEL_CHAR_CUF_PROFILES_BY_ID,
CHAR_DEL_CHAR_CUF_PROFILES,
CHAR_REP_GUILD_FINDER_APPLICANT,