diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 148 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 2 | ||||
| -rw-r--r-- | src/server/game/Maps/TransportMgr.h | 2 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 8 | ||||
| -rw-r--r-- | src/server/shared/DataStores/DB2Store.cpp | 20 | ||||
| -rw-r--r-- | src/server/shared/DataStores/DB2Store.h | 16 |
6 files changed, 109 insertions, 87 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 85caeccd077..e37196cc3de 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -27,7 +27,9 @@ #include "Regex.h" #include "Timer.h" #include "Util.h" +#include <boost/filesystem/operations.hpp> #include <array> +#include <bitset> #include <numeric> #include <sstream> #include <cctype> @@ -438,7 +440,7 @@ namespace template<typename T> constexpr std::size_t GetCppRecordSize(DB2Storage<T> const&) { return sizeof(T); } -void LoadDB2(uint32& availableDb2Locales, std::vector<std::string>& errlist, StorageMap& stores, DB2StorageBase* storage, std::string const& db2Path, +void LoadDB2(std::bitset<TOTAL_LOCALES>& availableDb2Locales, std::vector<std::string>& errlist, StorageMap& stores, DB2StorageBase* storage, std::string const& db2Path, LocaleConstant defaultLocale, std::size_t cppRecordSize) { // validate structure @@ -472,42 +474,53 @@ void LoadDB2(uint32& availableDb2Locales, std::vector<std::string>& errlist, Sto storage->GetFileName().c_str(), loadInfo->Meta->GetRecordSize(), cppRecordSize); } - if (storage->Load(db2Path + localeNames[defaultLocale] + '/', defaultLocale)) + try { - storage->LoadFromDB(); - // LoadFromDB() always loads strings into enUS locale, other locales are expected to have data in corresponding _locale tables - // so we need to make additional call to load that data in case said locale is set as default by worldserver.conf (and we do not want to load all this data from .db2 file again) - if (defaultLocale != LOCALE_enUS) - storage->LoadStringsFromDB(defaultLocale); - - for (LocaleConstant i = LOCALE_enUS; i < TOTAL_LOCALES; i = LocaleConstant(i + 1)) + storage->Load(db2Path + localeNames[defaultLocale] + '/', defaultLocale); + } + catch (std::system_error const& e) + { + if (e.code() == std::errc::no_such_file_or_directory) { - if (defaultLocale == i || i == LOCALE_none) - continue; - - if (availableDb2Locales & (1 << i)) - if (!storage->LoadStringsFrom((db2Path + localeNames[i] + '/'), i)) - availableDb2Locales &= ~(1 << i); // mark as not available for speedup next checks - - storage->LoadStringsFromDB(i); + errlist.push_back(Trinity::StringFormat("File %s does not exist", db2Path + localeNames[defaultLocale] + '/' + storage->GetFileName())); } + else + throw; } - else + catch (std::exception const& e) { - // sort problematic db2 to (1) non compatible and (2) nonexistent - if (FILE* f = fopen((db2Path + localeNames[defaultLocale] + '/' + storage->GetFileName()).c_str(), "rb")) + errlist.emplace_back(e.what()); + return; + } + + // load additional data and enUS strings from db + storage->LoadFromDB(); + + for (LocaleConstant i = LOCALE_enUS; i < TOTAL_LOCALES; i = LocaleConstant(i + 1)) + { + if (defaultLocale == i || !availableDb2Locales[i]) + continue; + + try { - std::ostringstream stream; - stream << storage->GetFileName() << " exists, and has " << storage->GetFieldCount() << " field(s) (expected " << loadInfo->Meta->FieldCount - << "). Extracted file might be from wrong client version."; - std::string buf = stream.str(); - errlist.push_back(buf); - fclose(f); + storage->LoadStringsFrom((db2Path + localeNames[i] + '/'), i); + } + catch (std::system_error const& e) + { + if (e.code() != std::errc::no_such_file_or_directory) + throw; + + // locale db2 files are optional, do not error if nothing is found + } + catch (std::exception const& e) + { + errlist.emplace_back(e.what()); } - else - errlist.push_back(storage->GetFileName()); } + for (LocaleConstant i = LOCALE_koKR; i < TOTAL_LOCALES; i = LocaleConstant(i + 1)) + storage->LoadStringsFromDB(i); + stores[storage->GetTableHash()] = storage; } @@ -517,16 +530,32 @@ DB2Manager& DB2Manager::Instance() return instance; } -void DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaultLocale) +uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaultLocale) { uint32 oldMSTime = getMSTime(); std::string db2Path = dataPath + "dbc/"; - std::vector<std::string> bad_db2_files; - uint32 availableDb2Locales = 0xFF; + std::vector<std::string> loadErrors; + std::bitset<TOTAL_LOCALES> availableDb2Locales = [&]() + { + std::bitset<TOTAL_LOCALES> foundLocales; + boost::filesystem::directory_iterator db2PathItr(db2Path), end; + while (db2PathItr != end) + { + LocaleConstant locale = GetLocaleByName(db2PathItr->path().filename().string()); + if (IsValidLocale(locale)) + foundLocales[locale] = true; -#define LOAD_DB2(store) LoadDB2(availableDb2Locales, bad_db2_files, _stores, &store, db2Path, defaultLocale, GetCppRecordSize(store)) + ++db2PathItr; + } + return foundLocales; + }(); + + if (!availableDb2Locales[defaultLocale]) + return 0; + +#define LOAD_DB2(store) LoadDB2(availableDb2Locales, loadErrors, _stores, &store, db2Path, defaultLocale, GetCppRecordSize(store)) LOAD_DB2(sAchievementStore); LOAD_DB2(sAnimationDataStore); @@ -783,6 +812,30 @@ void DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaultL #undef LOAD_DB2 + // error checks + if (!loadErrors.empty()) + { + sLog->SetSynchronous(); // server will shut down after this, so set sync logging to prevent messages from getting lost + + for (std::string const& error : loadErrors) + TC_LOG_ERROR("misc", "%s", error.c_str()); + + return 0; + } + + // Check loaded DB2 files proper version + if (!sAreaTableStore.LookupEntry(13227) || // last area added in 8.3.0 (34769) + !sCharTitlesStore.LookupEntry(672) || // last char title added in 8.3.0 (34769) + !sGemPropertiesStore.LookupEntry(3802) || // last gem property added in 8.3.0 (34769) + !sItemStore.LookupEntry(175264) || // last item added in 8.3.0 (34769) + !sItemExtendedCostStore.LookupEntry(6716) || // last item extended cost added in 8.3.0 (34769) + !sMapStore.LookupEntry(2292) || // last map added in 8.3.0 (34769) + !sSpellNameStore.LookupEntry(319960)) // last spell added in 8.3.0 (34769) + { + TC_LOG_ERROR("misc", "You have _outdated_ DB2 files. Please extract correct versions from current using client."); + exit(1); + } + for (AreaGroupMemberEntry const* areaGroupMember : sAreaGroupMemberStore) _areaGroupMembers[areaGroupMember->AreaGroupID].push_back(areaGroupMember->AreaID); @@ -1322,36 +1375,9 @@ void DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaultL } } - // error checks - if (bad_db2_files.size() == _stores.size()) - { - TC_LOG_ERROR("misc", "\nIncorrect DataDir value in worldserver.conf or ALL required *.db2 files (" SZFMTD ") not found by path: %sdbc/%s/", _stores.size(), dataPath.c_str(), localeNames[defaultLocale]); - exit(1); - } - else if (!bad_db2_files.empty()) - { - std::string str; - for (auto const& bad_db2_file : bad_db2_files) - str += bad_db2_file + "\n"; - - TC_LOG_ERROR("misc", "\nSome required *.db2 files (" SZFMTD " from " SZFMTD ") not found or not compatible:\n%s", bad_db2_files.size(), _stores.size(), str.c_str()); - exit(1); - } - - // Check loaded DB2 files proper version - if (!sAreaTableStore.LookupEntry(10521) || // last area added in 8.1.5 (30706) - !sCharTitlesStore.LookupEntry(649) || // last char title added in 8.1.5 (30706) - !sGemPropertiesStore.LookupEntry(3746) || // last gem property added in 8.1.5 (30706) - !sItemStore.LookupEntry(168279) || // last item added in 8.1.5 (30706) - !sItemExtendedCostStore.LookupEntry(6545) || // last item extended cost added in 8.1.5 (30706) - !sMapStore.LookupEntry(2178) || // last map added in 8.1.5 (30706) - !sSpellNameStore.LookupEntry(296952)) // last spell added in 8.1.5 (30706) - { - TC_LOG_ERROR("misc", "You have _outdated_ DB2 files. Please extract correct versions from current using client."); - exit(1); - } - TC_LOG_INFO("server.loading", ">> Initialized " SZFMTD " DB2 data stores in %u ms", _stores.size(), GetMSTimeDiffToNow(oldMSTime)); + + return availableDb2Locales.to_ulong(); } DB2StorageBase const* DB2Manager::GetStorage(uint32 type) const diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index d33ba31ceac..95ac7eabf14 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -275,7 +275,7 @@ public: static DB2Manager& Instance(); - void LoadStores(std::string const& dataPath, LocaleConstant defaultLocale); + uint32 LoadStores(std::string const& dataPath, LocaleConstant defaultLocale); DB2StorageBase const* GetStorage(uint32 type) const; void LoadHotfixData(); diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index 49f1b2b0083..0005eed85a7 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -102,8 +102,6 @@ typedef std::map<uint32, TransportAnimation> TransportAnimationContainer; class TC_GAME_API TransportMgr { - friend void DB2Manager::LoadStores(std::string const&, LocaleConstant); - public: static TransportMgr* instance(); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 4567492bba0..3aa3fcde40b 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1571,7 +1571,13 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Initialize data stores..."); ///- Load DB2s - sDB2Manager.LoadStores(m_dataPath, m_defaultDbcLocale); + m_availableDbcLocaleMask = sDB2Manager.LoadStores(m_dataPath, m_defaultDbcLocale); + if (!(m_availableDbcLocaleMask & (1 << m_defaultDbcLocale))) + { + TC_LOG_FATAL("server.loading", "Unable to load db2 files for %s locale specified in DBC.Locale config!", localeNames[m_defaultDbcLocale]); + exit(1); + } + TC_LOG_INFO("misc", "Loading hotfix blobs..."); sDB2Manager.LoadHotfixBlob(); TC_LOG_INFO("misc", "Loading hotfix info..."); diff --git a/src/server/shared/DataStores/DB2Store.cpp b/src/server/shared/DataStores/DB2Store.cpp index b33e050f644..bfa333ec448 100644 --- a/src/server/shared/DataStores/DB2Store.cpp +++ b/src/server/shared/DataStores/DB2Store.cpp @@ -20,6 +20,7 @@ #include "DB2DatabaseLoader.h" #include "DB2FileSystemSource.h" #include "DB2Meta.h" +#include "StringFormat.h" DB2StorageBase::DB2StorageBase(char const* fileName, DB2LoadInfo const* loadInfo) : _tableHash(0), _layoutHash(0), _fileName(fileName), _fieldCount(0), _loadInfo(loadInfo), _dataTable(nullptr), _dataTableEx(), _indexTableSize(0) @@ -83,14 +84,13 @@ void DB2StorageBase::WriteRecordData(char const* entry, LocaleConstant locale, B } } -bool DB2StorageBase::Load(std::string const& path, LocaleConstant locale, char**& indexTable) +void DB2StorageBase::Load(std::string const& path, LocaleConstant locale, char**& indexTable) { indexTable = nullptr; DB2FileLoader db2; DB2FileSystemSource source(path + _fileName); // Check if load was successful, only then continue - if (!db2.Load(&source, _loadInfo)) - return false; + db2.Load(&source, _loadInfo); _fieldCount = db2.GetCols(); _tableHash = db2.GetTableHash(); @@ -98,37 +98,29 @@ bool DB2StorageBase::Load(std::string const& path, LocaleConstant locale, char** // load raw non-string data _dataTable = db2.AutoProduceData(_indexTableSize, indexTable); - if (!_dataTable) - return false; // load strings from db2 data if (char* stringBlock = db2.AutoProduceStrings(indexTable, _indexTableSize, locale)) _stringPool.push_back(stringBlock); db2.AutoProduceRecordCopies(_indexTableSize, indexTable, _dataTable); - - // error in db2 file at loading if NULL - return indexTable != nullptr; } -bool DB2StorageBase::LoadStringsFrom(std::string const& path, LocaleConstant locale, char** indexTable) +void DB2StorageBase::LoadStringsFrom(std::string const& path, LocaleConstant locale, char** indexTable) { // DB2 must be already loaded using Load if (!indexTable) - return false; + throw DB2FileLoadException(Trinity::StringFormat("%s was not loaded properly, cannot load strings", path.c_str())); DB2FileLoader db2; DB2FileSystemSource source(path + _fileName); // Check if load was successful, only then continue - if (!db2.Load(&source, _loadInfo)) - return false; + db2.Load(&source, _loadInfo); // load strings from another locale db2 data if (_loadInfo->GetStringFieldCount(true)) if (char* stringBlock = db2.AutoProduceStrings(indexTable, _indexTableSize, locale)) _stringPool.push_back(stringBlock); - - return true; } void DB2StorageBase::LoadFromDB(char**& indexTable) diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h index c670d418b13..faf12428251 100644 --- a/src/server/shared/DataStores/DB2Store.h +++ b/src/server/shared/DataStores/DB2Store.h @@ -44,15 +44,15 @@ public: uint32 GetFieldCount() const { return _fieldCount; } DB2LoadInfo const* GetLoadInfo() const { return _loadInfo; } - virtual bool Load(std::string const& path, LocaleConstant locale) = 0; - virtual bool LoadStringsFrom(std::string const& path, LocaleConstant locale) = 0; + virtual void Load(std::string const& path, LocaleConstant locale) = 0; + virtual void LoadStringsFrom(std::string const& path, LocaleConstant locale) = 0; virtual void LoadFromDB() = 0; virtual void LoadStringsFromDB(LocaleConstant locale) = 0; protected: void WriteRecordData(char const* entry, LocaleConstant locale, ByteBuffer& buffer) const; - bool Load(std::string const& path, LocaleConstant locale, char**& indexTable); - bool LoadStringsFrom(std::string const& path, LocaleConstant locale, char** indexTable); + void Load(std::string const& path, LocaleConstant locale, char**& indexTable); + void LoadStringsFrom(std::string const& path, LocaleConstant locale, char** indexTable); void LoadFromDB(char**& indexTable); void LoadStringsFromDB(LocaleConstant locale, char** indexTable); @@ -77,12 +77,12 @@ public: DB2Storage(char const* fileName, DB2LoadInfo const* loadInfo) : DB2StorageBase(fileName, loadInfo) { - _indexTable.AsT = nullptr; + _indexTable.AsChar = nullptr; } ~DB2Storage() { - delete[] reinterpret_cast<char*>(_indexTable.AsT); + delete[] _indexTable.AsChar; } bool HasRecord(uint32 id) const override { return id < _indexTableSize && _indexTable.AsT[id] != nullptr; } @@ -98,12 +98,12 @@ public: T const* operator[](uint32 id) const { return LookupEntry(id); } uint32 GetNumRows() const { return _indexTableSize; } - bool Load(std::string const& path, LocaleConstant locale) override + void Load(std::string const& path, LocaleConstant locale) override { return DB2StorageBase::Load(path, locale, _indexTable.AsChar); } - bool LoadStringsFrom(std::string const& path, LocaleConstant locale) override + void LoadStringsFrom(std::string const& path, LocaleConstant locale) override { return DB2StorageBase::LoadStringsFrom(path, locale, _indexTable.AsChar); } |
