diff --git a/data/sql/updates/pending_db_auth/rev_1635587640506554000.sql b/data/sql/updates/pending_db_auth/rev_1635587640506554000.sql new file mode 100644 index 000000000..ecb77b440 --- /dev/null +++ b/data/sql/updates/pending_db_auth/rev_1635587640506554000.sql @@ -0,0 +1,3 @@ +INSERT INTO `version_db_auth` (`sql_rev`) VALUES ('1635587640506554000'); + +ALTER TABLE `updates` CHANGE `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED') CHARSET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'RELEASED' NOT NULL COMMENT 'defines if an update is released or archived.'; diff --git a/data/sql/updates/pending_db_characters/rev_1635587652443122100.sql b/data/sql/updates/pending_db_characters/rev_1635587652443122100.sql new file mode 100644 index 000000000..dbc5c67ae --- /dev/null +++ b/data/sql/updates/pending_db_characters/rev_1635587652443122100.sql @@ -0,0 +1,3 @@ +INSERT INTO `version_db_characters` (`sql_rev`) VALUES ('1635587652443122100'); + +ALTER TABLE `updates` CHANGE `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED') CHARSET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'RELEASED' NOT NULL COMMENT 'defines if an update is released or archived.'; diff --git a/data/sql/updates/pending_db_world/rev_1635587662323293700.sql b/data/sql/updates/pending_db_world/rev_1635587662323293700.sql new file mode 100644 index 000000000..8c01eb0ba --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1635587662323293700.sql @@ -0,0 +1,3 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1635587662323293700'); + +ALTER TABLE `updates` CHANGE `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED') CHARSET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'RELEASED' NOT NULL COMMENT 'defines if an update is released or archived.'; diff --git a/src/server/database/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h index e3a61f942..f889fef78 100644 --- a/src/server/database/Database/DatabaseLoader.h +++ b/src/server/database/Database/DatabaseLoader.h @@ -52,7 +52,12 @@ public: DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD }; -private: + [[nodiscard]] uint32 GetUpdateFlags() const + { + return _updateFlags; + } + +private : bool OpenDatabases(); bool PopulateDatabases(); bool UpdateDatabases(); diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index 1c9ebcad2..298f2404c 100644 --- a/src/server/database/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -289,6 +289,67 @@ bool DBUpdater::Update(DatabaseWorkerPool& pool) return true; } +template +bool DBUpdater::Update(DatabaseWorkerPool& pool, std::vector const* setDirectories) +{ + if (!DBUpdaterUtil::CheckExecutable()) + { + return false; + } + + Path const sourceDirectory(BuiltInConfig::GetSourceDirectory()); + if (!is_directory(sourceDirectory)) + { + return false; + } + + auto CheckUpdateTable = [&](std::string const& tableName) + { + auto checkTable = DBUpdater::Retrieve(pool, Acore::StringFormat("SHOW TABLES LIKE '%s'", tableName.c_str())); + if (!checkTable) + { + Path const temp(GetBaseFilesDirectory() + tableName + ".sql"); + try + { + DBUpdater::ApplyFile(pool, temp); + } + catch (UpdateException&) + { + return false; + } + + return true; + } + + return true; + }; + + if (!CheckUpdateTable("updates") || !CheckUpdateTable("updates_include")) + { + return false; + } + + UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const & query) { DBUpdater::Apply(pool, query); }, + [&](Path const & file) { DBUpdater::ApplyFile(pool, file); }, + [&](std::string const & query) -> QueryResult { return DBUpdater::Retrieve(pool, query); }, DBUpdater::GetDBModuleName(), setDirectories); + + UpdateResult result; + try + { + result = updateFetcher.Update( + sConfigMgr->GetOption("Updates.Redundancy", true), + sConfigMgr->GetOption("Updates.AllowRehash", true), + sConfigMgr->GetOption("Updates.ArchivedRedundancy", false), + sConfigMgr->GetOption("Updates.CleanDeadRefMaxCount", 3)); + } + catch (UpdateException&) + { + return false; + } + + return true; +} + template bool DBUpdater::Populate(DatabaseWorkerPool& pool) { diff --git a/src/server/database/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h index 92a5b713c..7d7d88f53 100644 --- a/src/server/database/Updater/DBUpdater.h +++ b/src/server/database/Updater/DBUpdater.h @@ -76,6 +76,7 @@ public: static BaseLocation GetBaseLocationType(); static bool Create(DatabaseWorkerPool& pool); static bool Update(DatabaseWorkerPool& pool); + static bool Update(DatabaseWorkerPool& pool, std::vector const* setDirectories); static bool Populate(DatabaseWorkerPool& pool); // module diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index f03ea18aa..254615263 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -39,9 +39,9 @@ struct UpdateFetcher::DirectoryEntry UpdateFetcher::UpdateFetcher(Path const& sourceDirectory, std::function const& apply, std::function const& applyFile, - std::function const& retrieve, std::string const& dbModuleName_) : + std::function const& retrieve, std::string const& dbModuleName, std::vector const* setDirectories /*= nullptr*/) : _sourceDirectory(std::make_unique(sourceDirectory)), _apply(apply), _applyFile(applyFile), - _retrieve(retrieve), _dbModuleName(dbModuleName_) + _retrieve(retrieve), _dbModuleName(dbModuleName), _setDirectories(setDirectories) { } @@ -96,53 +96,71 @@ UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() cons { DirectoryStorage directories; - QueryResult const result = _retrieve("SELECT `path`, `state` FROM `updates_include`"); - if (!result) - return directories; - - do + if (_setDirectories) { - Field* fields = result->Fetch(); - - std::string path = fields[0].GetString(); - std::string state = fields[1].GetString(); - if (path.substr(0, 1) == "$") - path = _sourceDirectory->generic_string() + path.substr(1); - - Path const p(path); - - if (!is_directory(p)) + for (auto const& itr : *_setDirectories) { - LOG_WARN("sql.updates", "DBUpdater: Given update include directory \"%s\" does not exist, skipped!", p.generic_string().c_str()); - continue; + std::string path = _sourceDirectory->generic_string() + itr; + + Path const p(path); + if (!is_directory(p)) + continue; + + DirectoryEntry const entry = {p, AppliedFileEntry::StateConvert("MODULE")}; + directories.push_back(entry); + + LOG_TRACE("sql.updates", "Added applied extra file \"%s\" from remote.", p.filename().generic_string().c_str()); } - - DirectoryEntry const entry = { p, AppliedFileEntry::StateConvert(state) }; - directories.push_back(entry); - - LOG_TRACE("sql.updates", "Added applied file \"%s\" '%s' state from remote.", p.filename().generic_string().c_str(), state.c_str()); - - } while (result->NextRow()); - - std::vector moduleList; - - auto const& _modulesTokens = Acore::Tokenize(AC_MODULES_LIST, ',', true); - for (auto const& itr : _modulesTokens) - moduleList.emplace_back(itr); - - // data/sql - for (auto const& itr : moduleList) + } + else { - std::string path = _sourceDirectory->generic_string() + "/modules/" + itr + "/data/sql/" + _dbModuleName; // modules/mod-name/data/sql/db-world + QueryResult const result = _retrieve("SELECT `path`, `state` FROM `updates_include`"); + if (!result) + return directories; - Path const p(path); - if (!is_directory(p)) - continue; + do + { + Field* fields = result->Fetch(); - DirectoryEntry const entry = { p, AppliedFileEntry::StateConvert("CUSTOM") }; - directories.push_back(entry); + std::string path = fields[0].GetString(); + std::string state = fields[1].GetString(); + if (path.substr(0, 1) == "$") + path = _sourceDirectory->generic_string() + path.substr(1); - LOG_TRACE("sql.updates", "Added applied modules file \"%s\" from remote.", p.filename().generic_string().c_str()); + Path const p(path); + + if (!is_directory(p)) + { + LOG_WARN("sql.updates", "DBUpdater: Given update include directory \"%s\" does not exist, skipped!", p.generic_string().c_str()); + continue; + } + + DirectoryEntry const entry = {p, AppliedFileEntry::StateConvert(state)}; + directories.push_back(entry); + + LOG_TRACE("sql.updates", "Added applied file \"%s\" '%s' state from remote.", p.filename().generic_string().c_str(), state.c_str()); + + } while (result->NextRow()); + + std::vector moduleList; + + auto const& _modulesTokens = Acore::Tokenize(AC_MODULES_LIST, ',', true); + for (auto const& itr : _modulesTokens) moduleList.emplace_back(itr); + + // data/sql + for (auto const& itr : moduleList) + { + std::string path = _sourceDirectory->generic_string() + "/modules/" + itr + "/data/sql/" + _dbModuleName; // modules/mod-name/data/sql/db-world + + Path const p(path); + if (!is_directory(p)) + continue; + + DirectoryEntry const entry = {p, AppliedFileEntry::StateConvert("MODULE")}; + directories.push_back(entry); + + LOG_TRACE("sql.updates", "Added applied modules file \"%s\" from remote.", p.filename().generic_string().c_str()); + } } return directories; @@ -201,6 +219,11 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, int32 const cleanDeadReferencesMaxCount) const { LocaleFileStorage const available = GetFileList(); + if (_setDirectories && available.empty()) + { + return UpdateResult(); + } + AppliedFileStorage applied = ReceiveAppliedFiles(); size_t countRecentUpdates = 0; @@ -347,37 +370,51 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, // Apply default updates for (auto const& availableQuery : available) { - if (availableQuery.second != CUSTOM) + if (availableQuery.second != CUSTOM && availableQuery.second != MODULE) ApplyUpdateFile(availableQuery); } - // Apply only custom updates + // Apply only custom/module updates for (auto const& availableQuery : available) { - if (availableQuery.second == CUSTOM) + if (availableQuery.second == CUSTOM || availableQuery.second == MODULE) ApplyUpdateFile(availableQuery); } // Cleanup up orphaned entries (if enabled) - if (!applied.empty()) + if (!applied.empty() && !_setDirectories) { bool const doCleanup = (cleanDeadReferencesMaxCount < 0) || (applied.size() <= static_cast(cleanDeadReferencesMaxCount)); + AppliedFileStorage toCleanup; for (auto const& entry : applied) { - LOG_WARN("sql.updates", ">> The file \'%s\' was applied to the database, but is missing in" \ - " your update directory now!", entry.first.c_str()); + if (entry.second.state != MODULE) + { + LOG_WARN("sql.updates", + ">> The file \'%s\' was applied to the database, but is missing in" + " your update directory now!", + entry.first.c_str()); - if (doCleanup) - LOG_INFO("sql.updates", "Deleting orphaned entry \'%s\'...", entry.first.c_str()); + if (doCleanup) + { + LOG_INFO("sql.updates", "Deleting orphaned entry \'%s\'...", entry.first.c_str()); + toCleanup.insert(entry); + } + } } - if (doCleanup) - CleanUp(applied); - else + if (!toCleanup.empty()) { - LOG_ERROR("sql.updates", "Cleanup is disabled! There were " SZFMTD " dirty files applied to your database, " \ - "but they are now missing in your source directory!", applied.size()); + if (doCleanup) + CleanUp(toCleanup); + else + { + LOG_ERROR("sql.updates", + "Cleanup is disabled! There were " SZFMTD " dirty files applied to your database, " + "but they are now missing in your source directory!", + toCleanup.size()); + } } } diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index 047db483b..bb97e29f3 100644 --- a/src/server/database/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h @@ -47,7 +47,7 @@ public: UpdateFetcher(Path const& updateDirectory, std::function const& apply, std::function const& applyFile, - std::function const& retrieve, std::string const& dbModuleName); + std::function const& retrieve, std::string const& dbModuleName, std::vector const* setDirectories = nullptr); ~UpdateFetcher(); UpdateResult Update(bool const redundancyChecks, bool const allowRehash, @@ -64,6 +64,7 @@ private: { RELEASED, CUSTOM, + MODULE, ARCHIVED }; @@ -83,6 +84,8 @@ private: return RELEASED; else if (state == "CUSTOM") return CUSTOM; + else if (state == "MODULE") + return MODULE; return ARCHIVED; } @@ -91,14 +94,16 @@ private: { switch (state) { - case RELEASED: - return "RELEASED"; - case CUSTOM: - return "CUSTOM"; - case ARCHIVED: - return "ARCHIVED"; - default: - return ""; + case RELEASED: + return "RELEASED"; + case CUSTOM: + return "CUSTOM"; + case MODULE: + return "MODULE"; + case ARCHIVED: + return "ARCHIVED"; + default: + return ""; } } @@ -147,6 +152,7 @@ private: // modules std::string const _dbModuleName; + std::vector const* _setDirectories; }; #endif // UpdateFetcher_h__ diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index d7ce992aa..cd4bc46d2 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -117,6 +117,7 @@ void ScriptMgr::Unload() SCR_CLEAR(PetScript); SCR_CLEAR(ArenaScript); SCR_CLEAR(CommandSC); + SCR_CLEAR(DatabaseScript); #undef SCR_CLEAR @@ -190,7 +191,8 @@ void ScriptMgr::CheckIfScriptsInDatabaseExist() !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && - !ScriptRegistry::GetScriptById(sid)) + !ScriptRegistry::GetScriptById(sid) && + !ScriptRegistry::GetScriptById(sid)) { LOG_ERROR("sql.sql", "Script named '%s' is assigned in the database, but has no code!", scriptName.c_str()); } @@ -3148,6 +3150,11 @@ void ScriptMgr::OnHandleDevCommand(Player* player, std::string& argstr) FOREACH_SCRIPT(CommandSC)->OnHandleDevCommand(player, argstr); } +void ScriptMgr::OnAfterDatabasesLoaded(uint32 updateFlags) +{ + FOREACH_SCRIPT(DatabaseScript)->OnAfterDatabasesLoaded(updateFlags); +} + ///- AllMapScript::AllMapScript(const char* name) : ScriptObject(name) @@ -3426,6 +3433,11 @@ CommandSC::CommandSC(const char* name) ScriptRegistry::AddScript(this); } +DatabaseScript::DatabaseScript(const char* name) : ScriptObject(name) +{ + ScriptRegistry::AddScript(this); +} + // Specialize for each script type class like so: template class ScriptRegistry; template class ScriptRegistry; @@ -3467,3 +3479,4 @@ template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; +template class ScriptRegistry; diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 466337e82..de01f3a80 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -1453,7 +1453,20 @@ public: bool IsDatabaseBound() const { return false; } - virtual void OnHandleDevCommand(Player* /*player*/, std::string& /*argstr*/) { } + virtual void OnHandleDevCommand(Player* /*player*/, std::string& /*argstr*/) { } +}; + +class DatabaseScript : public ScriptObject +{ +protected: + + DatabaseScript(const char* name); + +public: + + bool IsDatabaseBound() const { return false; } + + virtual void OnAfterDatabasesLoaded(uint32 /*updateFlags*/) {} }; // Manages registration, loading, and execution of scripts. @@ -1938,6 +1951,10 @@ public: /* AchievementScript */ void OnHandleDevCommand(Player* player, std::string& argstr); + public: /* DatabaseScript */ + + void OnAfterDatabasesLoaded(uint32 updateFlags); + private: uint32 _scriptCount; @@ -2007,31 +2024,31 @@ public: if (id) { // Try to find an existing script. - bool existing = false; + TScript const* oldScript = nullptr; for (auto iterator = ScriptPointerList.begin(); iterator != ScriptPointerList.end(); ++iterator) { // If the script names match... if (iterator->second->GetName() == script->GetName()) { // ... It exists. - existing = true; + oldScript = iterator->second; break; } } - // If the script isn't assigned -> assign it! - if (!existing) + // If the script is already assigned -> delete it! + if (oldScript) { - ScriptPointerList[id] = script; - sScriptMgr->IncrementScriptCount(); + delete oldScript; } - else - { - // If the script is already assigned -> delete it! - LOG_ERROR("scripts", "Script named '%s' is already assigned (two or more scripts have the same name), so the script can't work, aborting...", - script->GetName().c_str()); - ABORT(); // Error that should be fixed ASAP. + // Assign new script! + ScriptPointerList[id] = script; + + // Increment script count only with new scripts + if (!oldScript) + { + sScriptMgr->IncrementScriptCount(); } } else diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index fbd209c39..a42bc627b 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1455,9 +1455,6 @@ void World::SetInitialWorldSettings() ///- Initialize detour memory management dtAllocSetCustom(dtCustomAlloc, dtCustomFree); - LOG_INFO("server.loading", "Initializing Scripts..."); - sScriptMgr->Initialize(); - ///- Initialize VMapMgr function pointers (to untangle game/collision circular deps) VMAP::VMapMgr2* vmmgr2 = VMAP::VMapFactory::createOrGetVMapMgr(); vmmgr2->GetLiquidFlagsPtr = &GetLiquidFlags; diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 09a9156ad..7b501ef49 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -239,7 +239,7 @@ endfunction() # Generates the actual script projects # Fills the STATIC_SCRIPT_MODULES and DYNAMIC_SCRIPT_MODULE_PROJECTS variables # which contain the names which scripts are linked statically/dynamically and -# adds the sources of the static modules to the PRIVATE_SOURCES variable. +# adds the sources of the static modules to the PRIVATE_SOURCES_SCRIPTS variable. foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) GetPathToScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PATH) ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) @@ -254,7 +254,7 @@ foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) # Add the module name to STATIC_SCRIPT_MODULES list(APPEND STATIC_SCRIPT_MODULES ${SCRIPT_MODULE}) # Add the module content to the whole static module - CollectSourceFiles(${SCRIPT_MODULE_PATH} PRIVATE_SOURCES) + CollectSourceFiles(${SCRIPT_MODULE_PATH} PRIVATE_SOURCES_SCRIPTS) endif() elseif(${SCRIPT_MODULE_VARIABLE} STREQUAL "dynamic") @@ -313,7 +313,7 @@ endforeach() # Generates the actual module projects # Fills the STATIC_SCRIPT_MODULES and DYNAMIC_SCRIPT_MODULE_PROJECTS variables # which contain the names which scripts are linked statically/dynamically and -# adds the sources of the static modules to the PRIVATE_SOURCES variable. +# adds the sources of the static modules to the PRIVATE_SOURCES_MODULES variable. foreach(SOURCE_MODULE ${MODULES_MODULE_LIST}) GetPathToModuleSource(${SOURCE_MODULE} MODULE_SOURCE_PATH) ModuleNameToVariable(${SOURCE_MODULE} MODULE_MODULE_VARIABLE) @@ -328,7 +328,8 @@ foreach(SOURCE_MODULE ${MODULES_MODULE_LIST}) if(${MODULE_MODULE_VARIABLE} STREQUAL "static") # Add the module content to the whole static module - CollectSourceFiles(${MODULE_SOURCE_PATH} PRIVATE_SOURCES) + CollectSourceFiles(${MODULE_SOURCE_PATH} PRIVATE_SOURCES_MODULES) + CollectIncludeDirectories(${MODULE_SOURCE_PATH} PUBLIC_INCLUDES) # Skip deprecated api loaders if (AC_SCRIPTS_INCLUDES MATCHES "${SOURCE_MODULE}") @@ -351,6 +352,7 @@ foreach(SOURCE_MODULE ${MODULES_MODULE_LIST}) # Add the module content to the whole static module unset(MODULE_SOURCE_PRIVATE_SOURCES) CollectSourceFiles(${MODULE_SOURCE_PATH} MODULE_SOURCE_PRIVATE_SOURCES) + CollectIncludeDirectories(${MODULE_SOURCE_PATH} PUBLIC_INCLUDES) # Configure the scriptloader ConfigureScriptLoader(${SOURCE_MODULE} SCRIPT_MODULE_PRIVATE_SCRIPTLOADER ON ${SOURCE_MODULE}) @@ -372,7 +374,8 @@ foreach(SOURCE_MODULE ${MODULES_MODULE_LIST}) target_include_directories(${MODULE_SOURCE_PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}) + ${CMAKE_CURRENT_SOURCE_DIR} + ${PUBLIC_INCLUDES}) set_target_properties(${MODULE_SOURCE_PROJECT_NAME} PROPERTIES @@ -409,7 +412,8 @@ list(REMOVE_DUPLICATES SCRIPT_MODULE_PRIVATE_SCRIPTLOADER) add_library(scripts STATIC ScriptLoader.h ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER} - ${PRIVATE_SOURCES}) + ${PRIVATE_SOURCES_SCRIPTS} + ${PRIVATE_SOURCES_MODULES}) target_link_libraries(scripts PRIVATE @@ -419,7 +423,8 @@ target_link_libraries(scripts target_include_directories(scripts PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}) + ${CMAKE_CURRENT_SOURCE_DIR} + ${PUBLIC_INCLUDES}) set_target_properties(scripts PROPERTIES @@ -445,4 +450,4 @@ if(DISABLED_SCRIPT_MODULE_PROJECTS) ") endif() -message("") \ No newline at end of file +message("") diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 37edfc1fd..de0f741ba 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -278,6 +278,16 @@ int main(int argc, char** argv) // Set process priority according to configuration settings SetProcessPriority("server.worldserver", sConfigMgr->GetOption(CONFIG_PROCESSOR_AFFINITY, 0), sConfigMgr->GetOption(CONFIG_HIGH_PRIORITY, false)); + sScriptMgr->SetScriptLoader(AddScripts); + std::shared_ptr sScriptMgrHandle(nullptr, [](void*) + { + sScriptMgr->Unload(); + //sScriptReloadMgr->Unload(); + }); + + LOG_INFO("server.loading", "Initializing Scripts..."); + sScriptMgr->Initialize(); + // Start the databases if (!StartDB()) return 1; @@ -308,13 +318,6 @@ int main(int argc, char** argv) // Loading modules configs sConfigMgr->PrintLoadedModulesConfigs(); - sScriptMgr->SetScriptLoader(AddScripts); - std::shared_ptr sScriptMgrHandle(nullptr, [](void*) - { - sScriptMgr->Unload(); - //sScriptReloadMgr->Unload(); - }); - ///- Initialize the World sSecretMgr->Initialize(); sWorld->SetInitialWorldSettings(); @@ -486,6 +489,8 @@ bool StartDB() LOG_INFO("server.loading", "> Version DB world: %s", sWorld->GetDBVersion()); + sScriptMgr->OnAfterDatabasesLoaded(loader.GetUpdateFlags()); + return true; }