Core/ObjectMgr: Refactor sPageTextStore

This commit is contained in:
leak
2011-04-28 22:13:09 +02:00
parent 85a1e9e7ab
commit 19cab2c508
5 changed files with 73 additions and 64 deletions

View File

@@ -2489,7 +2489,7 @@ void ObjectMgr::LoadItemPrototypes()
if (proto->Bonding >= MAX_BIND_TYPE)
sLog->outErrorDb("Item (Entry: %u) has wrong Bonding value (%u)",i,proto->Bonding);
if (proto->PageText && !sPageTextStore.LookupEntry<PageText>(proto->PageText))
if (proto->PageText && !GetPageText(proto->PageText))
sLog->outErrorDb("Item (Entry: %u) has non existing first page (Id:%u)", i,proto->PageText);
if (proto->LockID && !sLockStore.LookupEntry(proto->LockID))
@@ -5505,49 +5505,57 @@ void ObjectMgr::LoadPageTexts()
{
uint32 oldMSTime = getMSTime();
sPageTextStore.Free(); // for reload case
QueryResult result = WorldDatabase.Query("SELECT entry, text, next_page FROM page_text");
sPageTextStore.Load();
for (uint32 i = 1; i < sPageTextStore.MaxEntry; ++i)
if (!result)
{
// check data correctness
PageText const* page = sPageTextStore.LookupEntry<PageText>(i);
if (!page)
continue;
sLog->outString(">> Loaded 0 page texts. DB table `page_text` is empty!");
sLog->outString();
return;
}
if (page->Next_Page && !sPageTextStore.LookupEntry<PageText>(page->Next_Page))
{
sLog->outErrorDb("Page text (Id: %u) has not existing next page (Id:%u)", i,page->Next_Page);
continue;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
// detect circular reference
std::set<uint32> checkedPages;
for (PageText const* pageItr = page; pageItr; pageItr = sPageTextStore.LookupEntry<PageText>(pageItr->Next_Page))
const char* text = fields[1].GetCString();
PageText pageText;
pageText.Text = fields[1].GetString();
pageText.NextPage = fields[2].GetInt16();
PageTextStore[fields[0].GetUInt32()] = pageText;
++count;
}
while (result->NextRow());
for (PageTextContainer::const_iterator itr = PageTextStore.begin(); itr != PageTextStore.end(); ++itr)
{
if (itr->second.NextPage)
{
if (!pageItr->Next_Page)
break;
checkedPages.insert(pageItr->Page_ID);
if (checkedPages.find(pageItr->Next_Page)!= checkedPages.end())
{
std::ostringstream ss;
ss << "The text page(s) ";
for (std::set<uint32>::iterator itr= checkedPages.begin(); itr != checkedPages.end(); ++itr)
ss << *itr << " ";
ss << "create(s) a circular reference, which can cause the server to freeze. Changing Next_Page of page "
<< pageItr->Page_ID <<" to 0";
sLog->outErrorDb("%s", ss.str().c_str());
const_cast<PageText*>(pageItr)->Next_Page = 0;
break;
}
PageTextContainer::const_iterator itr2 = PageTextStore.find(itr->second.NextPage);
if (itr2 == PageTextStore.end())
sLog->outErrorDb("Page text (Id: %u) has not existing next page (Id: %u)", itr->first, itr->second.NextPage);
}
}
sLog->outString(">> Loaded %u page texts in %u ms", sPageTextStore.RecordCount, GetMSTimeDiffToNow(oldMSTime));
sLog->outString(">> Loaded %u page texts in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
PageText const* ObjectMgr::GetPageText(uint32 pageEntry)
{
PageTextContainer::const_iterator itr = PageTextStore.find(pageEntry);
if (itr != PageTextStore.end())
return &(itr->second);
return NULL;
}
void ObjectMgr::LoadPageTextLocales()
{
uint32 oldMSTime = getMSTime();
@@ -7016,7 +7024,7 @@ void ObjectMgr::LoadGameobjectInfo()
if (goInfo->goober.pageId) // pageId
{
if (!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
if (!GetPageText(goInfo->goober.pageId))
sLog->outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.",
id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId);
}

View File

@@ -48,7 +48,6 @@ extern SQLStorage sCreatureDataAddonStorage;
extern SQLStorage sCreatureInfoAddonStorage;
extern SQLStorage sEquipmentStorage;
extern SQLStorage sGOStorage;
extern SQLStorage sPageTextStore;
extern SQLStorage sItemStorage;
extern SQLStorage sInstanceTemplate;
@@ -57,6 +56,29 @@ class Guild;
class ArenaTeam;
class Item;
// 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 PageText
{
std::string Text;
uint16 NextPage;
};
// 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
// Faster (insert/find) than UNORDERED_MAP in this case
typedef std::map<uint32, PageText> PageTextContainer;
struct GameTele
{
float position_x;
@@ -943,6 +965,7 @@ class ObjectMgr
void LoadGameObjectForQuests();
void LoadPageTexts();
PageText const* GetPageText(uint32 pageEntry);
void LoadPlayerInfo();
void LoadPetLevelInfo();
@@ -1343,6 +1366,8 @@ class ObjectMgr
LocaleConstant DBCLocaleIndex;
PageTextContainer PageTextStore;
private:
void LoadScripts(ScriptsType type);
void CheckScripts(ScriptsType type, std::set<int32>& ids);

View File

@@ -19,28 +19,6 @@
#ifndef __NPCHANDLER_H
#define __NPCHANDLER_H
// 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 PageText
{
uint32 Page_ID;
char * Text;
uint32 Next_Page;
};
// 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
struct QEmote
{
uint32 _Emote;

View File

@@ -411,12 +411,12 @@ void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data)
while (pageID)
{
PageText const *pPage = sPageTextStore.LookupEntry<PageText>(pageID);
PageText const* pageText = sObjectMgr->GetPageText(pageID);
// guess size
WorldPacket data(SMSG_PAGE_TEXT_QUERY_RESPONSE, 50);
data << pageID;
if (!pPage)
if (!pageText)
{
data << "Item page missing.";
data << uint32(0);
@@ -424,7 +424,7 @@ void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data)
}
else
{
std::string Text = pPage->Text;
std::string Text = pageText->Text;
int loc_idx = GetSessionDbLocaleIndex();
if (loc_idx >= 0)
@@ -432,8 +432,8 @@ void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data)
sObjectMgr->GetLocaleString(pl->Text, loc_idx, Text);
data << Text;
data << uint32(pPage->Next_Page);
pageID = pPage->Next_Page;
data << uint32(pageText->NextPage);
pageID = pageText->NextPage;
}
SendPacket(&data);

View File

@@ -28,7 +28,6 @@ const char GameObjectInfosrcfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiissi";
const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisii";
const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiisiiiii";
const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiii";
const char PageTextfmt[]="isii";
const char InstanceTemplatesrcfmt[]="iiffffsb";
const char InstanceTemplatedstfmt[]="iiffffib";
@@ -38,7 +37,6 @@ SQLStorage sCreatureInfoAddonStorage(CreatureInfoAddonInfofmt,"entry","creature_
SQLStorage sEquipmentStorage(EquipmentInfofmt,"entry","creature_equip_template");
SQLStorage sGOStorage(GameObjectInfosrcfmt, GameObjectInfodstfmt, "entry","gameobject_template");
SQLStorage sItemStorage(ItemPrototypesrcfmt, ItemPrototypedstfmt, "entry","item_template");
SQLStorage sPageTextStore(PageTextfmt,"entry","page_text");
SQLStorage sInstanceTemplate(InstanceTemplatesrcfmt, InstanceTemplatedstfmt, "map","instance_template");
void SQLStorage::Free ()