From bf4b6fafc5cc3e5f9b91a00f800397f8bdb08a20 Mon Sep 17 00:00:00 2001 From: Antz Date: Thu, 24 Mar 2016 17:58:53 +0000 Subject: [PATCH] [Sync] Project Sync plus Revision changes The main revision system changes are based on FoeReapers work in: https://github.com/mangoszero/server/commit/b37de3b83e85a25f29e1bb15ae5dae8378de68f6 --- src/framework/Platform/Define.h | 2 + src/framework/Policies/CreationPolicy.h | 8 +- src/framework/Policies/ObjectLifeTime.h | 2 +- src/framework/Policies/Singleton.h | 10 +- src/framework/Policies/ThreadingModel.h | 10 +- src/framework/Utilities/UnorderedMapSet.h | 53 +++-- src/game/ChatCommands/Level0.cpp | 33 +-- src/game/Warden/Warden.cpp | 2 +- src/game/Warden/Warden.h | 3 + src/game/Warden/WardenCheckMgr.cpp | 98 ++++++++- src/game/Warden/WardenCheckMgr.h | 21 +- src/game/Warden/WardenMac.cpp | 2 +- src/game/Warden/WardenWin.cpp | 12 +- src/game/Warden/WardenWin.h | 2 +- src/game/WorldHandlers/World.cpp | 109 ++++++---- src/game/WorldHandlers/World.h | 4 +- src/mangosd/CMakeLists.txt | 4 +- src/mangosd/Comm/CliRunnable.cpp | 4 +- src/mangosd/Main.cpp | 1 + src/mangosd/Master.cpp | 10 +- src/mangosd/RA/RASocket.h | 4 +- src/mangosd/WorldRunnable.cpp | 2 +- src/mangosd/mangosd.conf.dist.in | 136 ++++++++----- src/realmd | 2 +- src/shared/Common/Common.h | 11 +- src/shared/DataStores/DBCFileLoader.cpp | 7 +- src/shared/Database/Database.cpp | 187 +++++++++-------- src/shared/Database/Database.h | 29 ++- src/shared/Database/Field.h | 30 +-- src/shared/Database/SQLStorage.cpp | 2 +- src/shared/SystemConfig.h.in | 2 +- src/shared/Threading/Threading.cpp | 12 +- src/shared/Threading/Threading.h | 2 +- src/shared/Utilities/ByteBuffer.cpp | 2 +- src/shared/Utilities/ProgressBar.h | 2 +- src/shared/Utilities/Util.cpp | 13 +- src/shared/Utilities/Util.h | 10 +- src/shared/revision.h | 20 +- src/tools/genrevision/genrevision.cpp | 237 +++++++++++++--------- 39 files changed, 684 insertions(+), 416 deletions(-) diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h index 6b7dd7100..54e8a899f 100644 --- a/src/framework/Platform/Define.h +++ b/src/framework/Platform/Define.h @@ -169,6 +169,7 @@ typedef uint32 DWORD; #define CONCAT1(x, y) x##y #define STATIC_ASSERT_WORKAROUND(expr, msg) typedef char CONCAT(static_assert_failed_at_line_, __LINE__) [(expr) ? 1 : -1] +#ifndef COMPILER_HAS_CPP11_SUPPORT #if COMPILER == COMPILER_GNU # if !defined(__GXX_EXPERIMENTAL_CXX0X__) || (__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) # define override @@ -184,6 +185,7 @@ typedef uint32 DWORD; # define static_assert(a, b) STATIC_ASSERT_WORKAROUND(a, b) # endif #endif +#endif /** * @brief diff --git a/src/framework/Policies/CreationPolicy.h b/src/framework/Policies/CreationPolicy.h index eec60bba7..94c68f3db 100644 --- a/src/framework/Policies/CreationPolicy.h +++ b/src/framework/Policies/CreationPolicy.h @@ -35,7 +35,7 @@ namespace MaNGOS * @brief OperatorNew policy creates an object on the heap using new. * */ - class OperatorNew + class OperatorNew { public: @@ -65,7 +65,7 @@ namespace MaNGOS * @brief LocalStaticCreation policy creates an object on the stack the first time call Create. * */ - class LocalStaticCreation + class LocalStaticCreation { /** * @brief @@ -123,7 +123,7 @@ namespace MaNGOS * @brief * */ - class CreateUsingMalloc + class CreateUsingMalloc { public: @@ -159,7 +159,7 @@ namespace MaNGOS * @brief CreateOnCallBack creates the object base on the call back. * */ - class CreateOnCallBack + class CreateOnCallBack { public: /** diff --git a/src/framework/Policies/ObjectLifeTime.h b/src/framework/Policies/ObjectLifeTime.h index 4e1730e4d..1b4b206af 100644 --- a/src/framework/Policies/ObjectLifeTime.h +++ b/src/framework/Policies/ObjectLifeTime.h @@ -48,7 +48,7 @@ namespace MaNGOS * @brief * */ - class ObjectLifeTime + class ObjectLifeTime { public: diff --git a/src/framework/Policies/Singleton.h b/src/framework/Policies/Singleton.h index 483a041d7..259ff0724 100644 --- a/src/framework/Policies/Singleton.h +++ b/src/framework/Policies/Singleton.h @@ -46,7 +46,7 @@ namespace MaNGOS * @brief * */ - class Singleton + class Singleton { public: @@ -147,15 +147,15 @@ namespace MaNGOS } #define INSTANTIATE_SINGLETON_1(TYPE) \ - template class MaNGOS::Singleton, MaNGOS::OperatorNew, MaNGOS::ObjectLifeTime >; + template class MaNGOS::Singleton, MaNGOS::OperatorNew, MaNGOS::ObjectLifeTime >; #define INSTANTIATE_SINGLETON_2(TYPE, THREADINGMODEL) \ - template class MaNGOS::Singleton, MaNGOS::ObjectLifeTime >; + template class MaNGOS::Singleton, MaNGOS::ObjectLifeTime >; #define INSTANTIATE_SINGLETON_3(TYPE, THREADINGMODEL, CREATIONPOLICY ) \ - template class MaNGOS::Singleton >; + template class MaNGOS::Singleton >; #define INSTANTIATE_SINGLETON_4(TYPE, THREADINGMODEL, CREATIONPOLICY, OBJECTLIFETIME) \ - template class MaNGOS::Singleton; + template class MaNGOS::Singleton; #endif diff --git a/src/framework/Policies/ThreadingModel.h b/src/framework/Policies/ThreadingModel.h index 58dbafd08..138319a2e 100644 --- a/src/framework/Policies/ThreadingModel.h +++ b/src/framework/Policies/ThreadingModel.h @@ -39,7 +39,7 @@ namespace MaNGOS * @brief * */ - class GeneralLock + class GeneralLock { public: @@ -86,7 +86,7 @@ namespace MaNGOS * @brief * */ - class SingleThreaded + class SingleThreaded { public: @@ -128,7 +128,7 @@ namespace MaNGOS * @brief * */ - class ObjectLevelLockable + class ObjectLevelLockable { public: @@ -193,7 +193,7 @@ namespace MaNGOS * @brief * */ - class ClassLevelLockable + class ClassLevelLockable { public: @@ -265,6 +265,6 @@ namespace MaNGOS template MUTEX MaNGOS::ClassLevelLockable::si_mtx; /**< TODO */ #define INSTANTIATE_CLASS_MUTEX(CTYPE, MUTEX) \ - template class MaNGOS::ClassLevelLockable + template class MaNGOS::ClassLevelLockable #endif diff --git a/src/framework/Utilities/UnorderedMapSet.h b/src/framework/Utilities/UnorderedMapSet.h index 22c8d21cb..639669cae 100644 --- a/src/framework/Utilities/UnorderedMapSet.h +++ b/src/framework/Utilities/UnorderedMapSet.h @@ -28,9 +28,18 @@ #include "Platform/CompilerDefs.h" #include "Platform/Define.h" +#if defined(__APPLE__) +#include +#endif + #if COMPILER == COMPILER_CLANG -# include -# include +# if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 +# include +# include +# else +# include +# include +# endif #elif COMPILER == COMPILER_INTEL # include # include @@ -97,20 +106,40 @@ HASH_NAMESPACE_END using std::hash_map; using std::hash_set; #elif COMPILER == COMPILER_CLANG && defined(__FreeBSD__) +# include # define UNORDERED_MAP std::unordered_map # define UNORDERED_SET std::unordered_set -# define HASH_NAMESPACE_START namespace std { namespace __1 { -# define HASH_NAMESPACE_END } } +# if __FreeBSD_version >= 1001000 +# define HASH_NAMESPACE_START namespace std { +# define HASH_NAMESPACE_END } +# else +# define HASH_NAMESPACE_START namespace std { namespace __1 { +# define HASH_NAMESPACE_END } } +# endif #elif COMPILER == COMPILER_CLANG -# define UNORDERED_MAP std::tr1::unordered_map -# define UNORDERED_SET std::tr1::unordered_set -# define HASH_NAMESPACE_START namespace std { namespace tr1 { -# define HASH_NAMESPACE_END } } +# if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 +# define UNORDERED_MAP std::unordered_map +# define UNORDERED_SET std::unordered_set +# define HASH_NAMESPACE_START namespace std { +# define HASH_NAMESPACE_END } +# else +# define UNORDERED_MAP std::tr1::unordered_map +# define UNORDERED_SET std::tr1::unordered_set +# define HASH_NAMESPACE_START namespace std { namespace tr1 { +# define HASH_NAMESPACE_END } } +# endif #elif COMPILER == COMPILER_GNU && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) -# define UNORDERED_MAP std::tr1::unordered_map -# define UNORDERED_SET std::tr1::unordered_set -# define HASH_NAMESPACE_START namespace std { namespace tr1 { -# define HASH_NAMESPACE_END } } +# if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 +# define UNORDERED_MAP std::unordered_map +# define UNORDERED_SET std::unordered_set +# define HASH_NAMESPACE_START namespace std { +# define HASH_NAMESPACE_END } +# else +# define UNORDERED_MAP std::tr1::unordered_map +# define UNORDERED_SET std::tr1::unordered_set +# define HASH_NAMESPACE_START namespace std { namespace tr1 { +# define HASH_NAMESPACE_END } } +# endif #elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 && (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 3) # define UNORDERED_MAP __gnu_cxx::hash_map # define UNORDERED_SET __gnu_cxx::hash_set diff --git a/src/game/ChatCommands/Level0.cpp b/src/game/ChatCommands/Level0.cpp index 1eeb441e3..dbd886f8e 100644 --- a/src/game/ChatCommands/Level0.cpp +++ b/src/game/ChatCommands/Level0.cpp @@ -46,7 +46,7 @@ bool ChatHandler::HandleHelpCommand(char* args) else { if (!ShowHelpForCommand(getCommandTable(), args)) - SendSysMessage(LANG_NO_CMD); + { SendSysMessage(LANG_NO_CMD); } } return true; @@ -62,7 +62,7 @@ bool ChatHandler::HandleAccountCommand(char* args) { // let show subcommands at unexpected data in args if (*args) - return false; + { return false; } AccountTypes gmlevel = GetAccessLevel(); PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); @@ -108,15 +108,14 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/) { char const* ver = sScriptMgr.GetScriptLibraryVersion(); if (ver && *ver) - PSendSysMessage(LANG_USING_SCRIPT_LIB, ver); + { PSendSysMessage(LANG_USING_SCRIPT_LIB, ver); } else - SendSysMessage(LANG_USING_SCRIPT_LIB_UNKNOWN); + { SendSysMessage(LANG_USING_SCRIPT_LIB_UNKNOWN); } } else - SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); + { SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); } PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion()); - PSendSysMessage(LANG_USING_EVENT_AI, sWorld.GetCreatureEventAIVersion()); PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); PSendSysMessage(LANG_UPTIME, str.c_str()); @@ -125,23 +124,25 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/) bool ChatHandler::HandleDismountCommand(char* /*args*/) { + Player* player = m_session->GetPlayer(); + // If player is not mounted, so go out :) - if (!m_session->GetPlayer()->IsMounted()) + if (!player->IsMounted()) { SendSysMessage(LANG_CHAR_NON_MOUNTED); SetSentErrorMessage(true); return false; } - if (m_session->GetPlayer()->IsTaxiFlying()) + if (player->IsTaxiFlying()) { SendSysMessage(LANG_YOU_IN_FLIGHT); SetSentErrorMessage(true); return false; } - m_session->GetPlayer()->Unmount(); - m_session->GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + player->Unmount(); + player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); return true; } @@ -160,7 +161,7 @@ bool ChatHandler::HandleSaveCommand(char* /*args*/) // save or plan save after 20 sec (logout delay) if current next save time more this value and _not_ output any messages to prevent cheat planning uint32 save_interval = sWorld.getConfig(CONFIG_UINT32_INTERVAL_SAVE); if (save_interval == 0 || (save_interval > 20 * IN_MILLISECONDS && player->GetSaveTimer() <= save_interval - 20 * IN_MILLISECONDS)) - player->SaveToDB(); + { player->SaveToDB(); } return true; } @@ -176,8 +177,8 @@ bool ChatHandler::HandleGMListIngameCommand(char* /*args*/) { AccountTypes itr_sec = itr->second->GetSession()->GetSecurity(); if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) && - (!m_session || itr->second->IsVisibleGloballyFor(m_session->GetPlayer()))) - names.push_back(std::make_pair(GetNameLink(itr->second), itr->second->isAcceptWhispers())); + (!m_session || itr->second->IsVisibleGloballyFor(m_session->GetPlayer()))) + { names.push_back(std::make_pair(GetNameLink(itr->second), itr->second->isAcceptWhispers())); } } } @@ -188,10 +189,10 @@ bool ChatHandler::HandleGMListIngameCommand(char* /*args*/) char const* accepts = GetMangosString(LANG_GM_ACCEPTS_WHISPER); char const* not_accept = GetMangosString(LANG_GM_NO_WHISPER); for (std::list >::const_iterator iter = names.begin(); iter != names.end(); ++iter) - PSendSysMessage("%s - %s", iter->first.c_str(), iter->second ? accepts : not_accept); + { PSendSysMessage("%s - %s", iter->first.c_str(), iter->second ? accepts : not_accept); } } else - SendSysMessage(LANG_GMS_NOT_LOGGED); + { SendSysMessage(LANG_GMS_NOT_LOGGED); } return true; } @@ -212,7 +213,7 @@ bool ChatHandler::HandleAccountPasswordCommand(char* args) char* new_pass_c = ExtractQuotedOrLiteralArg(&args); if (!old_pass || !new_pass || !new_pass_c) - return false; + { return false; } std::string password_old = old_pass; std::string password_new = new_pass; diff --git a/src/game/Warden/Warden.cpp b/src/game/Warden/Warden.cpp index d29248d4c..eec466158 100644 --- a/src/game/Warden/Warden.cpp +++ b/src/game/Warden/Warden.cpp @@ -230,7 +230,7 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/) banReason << "Warden Anticheat Violation"; // Check can be NULL, for example if the client sent a wrong signature in the warden packet (CHECKSUM FAIL) if (check) - banReason << ": " << check->Comment << " (CheckId: " << check->CheckId << ")"; + banReason << ": " << (check->Comment.empty() ? std::string("Undocumented Check") : check->Comment) << " (CheckId: " << check->CheckId << ")"; sWorld.BanAccount(BAN_ACCOUNT, accountName, sWorld.getConfig(CONFIG_UINT32_WARDEN_CLIENT_BAN_DURATION), banReason.str(), "Warden"); diff --git a/src/game/Warden/Warden.h b/src/game/Warden/Warden.h index 5ac88134e..213cba724 100644 --- a/src/game/Warden/Warden.h +++ b/src/game/Warden/Warden.h @@ -33,6 +33,9 @@ #include "WardenCheckMgr.h" #include "Database/DatabaseEnv.h" +// the default client version with info in warden_checks; for other version checks, see warden_build_specific +#define DEFAULT_CLIENT_BUILD 5875 + enum WardenOpcodes { // Client->Server diff --git a/src/game/Warden/WardenCheckMgr.cpp b/src/game/Warden/WardenCheckMgr.cpp index 003748df7..cb343dd3b 100644 --- a/src/game/Warden/WardenCheckMgr.cpp +++ b/src/game/Warden/WardenCheckMgr.cpp @@ -66,6 +66,7 @@ void WardenCheckMgr::LoadWardenChecks() CheckStore.resize(maxCheckId + 1); + delete result; // 0 1 2 3 4 5 6 7 result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC"); @@ -147,7 +148,7 @@ void WardenCheckMgr::LoadWardenChecks() } if (comment.empty()) - wardenCheck->Comment = "Undocumented Check"; + wardenCheck->Comment = ""; else wardenCheck->Comment = comment; @@ -155,6 +156,81 @@ void WardenCheckMgr::LoadWardenChecks() } while (result->NextRow()); sLog.outWarden(">> Loaded %u warden checks.", count); + + delete result; + // 0 1 2 3 4 5 6 + result = WorldDatabase.Query("SELECT id, build, data, result, address, length, str FROM warden_build_specific ORDER BY id ASC"); + + if (!result) + { + sLog.outString("[Warden]: >> Loaded 0 warden client build-specific data."); + return; + } + + count = 0; + do + { + fields = result->Fetch(); + + uint16 id = fields[0].GetUInt16(); + if (id >= CheckStore.size()) + { + sLog.outWarden("ERROR: Build-specific, check is missing in warden_checks, skipping id %u.", id); + continue; + } + + uint16 build = fields[1].GetUInt16(); + if (build == DEFAULT_CLIENT_BUILD) + { + sLog.outWarden("ERROR: Build-specific table may not contain checks for default %u build, skipping id %u.", DEFAULT_CLIENT_BUILD, id); + continue; + } + + //std::string data = fields[2].GetString(); //unused for now + std::string checkResult = fields[3].GetString(); + uint32 address = fields[4].GetUInt32(); + uint8 length = fields[5].GetUInt8(); + std::string str = fields[6].GetString(); + + WardenCheck* wardenCheck = new WardenCheck(); + wardenCheck->CheckId = id; + wardenCheck->Type = CheckStore[id]->Type; + + WardenCheckResult* wr = new WardenCheckResult(); + switch (wardenCheck->Type) + { + case MEM_CHECK: + wardenCheck->Address = address; + wardenCheck->Length = length; + wardenCheck->Str = str; + wr->Result.SetHexStr(checkResult.c_str()); + { + int len = checkResult.size() / 2; + if (wr->Result.GetNumBytes() < len) + { + uint8 *temp = new uint8[len]; + memset(temp, 0, len); + memcpy(temp, wr->Result.AsByteArray(), wr->Result.GetNumBytes()); + std::reverse(temp, temp + len); + wr->Result.SetBinary((uint8*)temp, len); + delete[] temp; + } + } + break; + default: + sLog.outWarden("The check type %u is considered as build-independent, skipping id %u.", wardenCheck->Type, id); + delete wr; + delete wardenCheck; + continue; + } + + MCheckStore[ComposeMultiCheckKey(build, id)] = wardenCheck; + MCheckResultStore[ComposeMultiCheckKey(build, id)] = wr; + ++count; + + } while (result->NextRow()); + + sLog.outString(">> Loaded %u warden client build-specific check overrides.", count); } void WardenCheckMgr::LoadWardenOverrides() @@ -203,18 +279,34 @@ void WardenCheckMgr::LoadWardenOverrides() sLog.outWarden(">> Loaded %u warden action overrides.", count); } -WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 Id) +WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 build, uint16 Id) { if (Id < CheckStore.size()) + { + if (build != DEFAULT_CLIENT_BUILD) + { + MultiCheckContainer::const_iterator it = MCheckStore.find(ComposeMultiCheckKey(build, Id)); + if (it != MCheckStore.end()) + return it->second; + } return CheckStore[Id]; + } return NULL; } -WardenCheckResult* WardenCheckMgr::GetWardenResultById(uint16 Id) +WardenCheckResult* WardenCheckMgr::GetWardenResultById(uint16 build, uint16 Id) { + if (build != DEFAULT_CLIENT_BUILD) + { + MultiResultContainer::const_iterator it = MCheckResultStore.find(ComposeMultiCheckKey(build, Id)); + if (it != MCheckResultStore.end()) + return it->second; + } + CheckResultContainer::const_iterator itr = CheckResultStore.find(Id); if (itr != CheckResultStore.end()) return itr->second; + return NULL; } diff --git a/src/game/Warden/WardenCheckMgr.h b/src/game/Warden/WardenCheckMgr.h index 2d20efb7d..92fb081c9 100644 --- a/src/game/Warden/WardenCheckMgr.h +++ b/src/game/Warden/WardenCheckMgr.h @@ -66,12 +66,8 @@ class WardenCheckMgr return &instance; } - // We have a linear key without any gaps, so we use vector for fast access - typedef std::vector CheckContainer; - typedef std::map CheckResultContainer; - - WardenCheck* GetWardenDataById(uint16 Id); - WardenCheckResult* GetWardenResultById(uint16 Id); + WardenCheck* GetWardenDataById(uint16 build, uint16 Id); + WardenCheckResult* GetWardenResultById(uint16 build, uint16 Id); std::vector MemChecksIdPool; std::vector OtherChecksIdPool; @@ -82,8 +78,21 @@ class WardenCheckMgr ACE_RW_Mutex _checkStoreLock; private: + uint32 inline ComposeMultiCheckKey(uint16 clientBuild, uint16 checkID) { return (uint32(checkID) << 16) | clientBuild; } + + // We have a linear key without any gaps, so we use vector for fast access + typedef std::vector CheckContainer; + typedef std::map CheckResultContainer; + CheckContainer CheckStore; CheckResultContainer CheckResultStore; + + // here we have just few checks, vector is not appropriate; key is from ComposeMultiCheckKey + typedef std::map MultiCheckContainer; + typedef std::map MultiResultContainer; + + MultiCheckContainer MCheckStore; + MultiResultContainer MCheckResultStore; }; #define sWardenCheckMgr WardenCheckMgr::instance() diff --git a/src/game/Warden/WardenMac.cpp b/src/game/Warden/WardenMac.cpp index 16e39d224..501a08d4b 100644 --- a/src/game/Warden/WardenMac.cpp +++ b/src/game/Warden/WardenMac.cpp @@ -61,7 +61,7 @@ void WardenMac::Init(WorldSession* pClient, BigNumber* K) _inputCrypto.Init(_inputKey); _outputCrypto.Init(_outputKey); - sLog.outWarden("Server side warden for client %u initializing...", pClient->GetAccountId()); + sLog.outWarden("Server side Mac warden for client %u (build %u) initializing...", pClient->GetAccountId(), _session->GetClientBuild()); sLog.outWarden("C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); sLog.outWarden("S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); sLog.outWarden(" Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); diff --git a/src/game/Warden/WardenWin.cpp b/src/game/Warden/WardenWin.cpp index 472950f04..c8f83a89f 100644 --- a/src/game/Warden/WardenWin.cpp +++ b/src/game/Warden/WardenWin.cpp @@ -56,7 +56,7 @@ void WardenWin::Init(WorldSession* session, BigNumber* k) _inputCrypto.Init(_inputKey); _outputCrypto.Init(_outputKey); - sLog.outWarden("Server side warden for client %u initializing...", session->GetAccountId()); + sLog.outWarden("Server side warden for client %u (build %u) initializing...", session->GetAccountId(), _session->GetClientBuild()); sLog.outWarden("C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); sLog.outWarden("S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); sLog.outWarden(" Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); @@ -210,7 +210,7 @@ void WardenWin::RequestData() // Add the id to the list sent in this cycle _currentChecks.push_back(id); - wd = sWardenCheckMgr->GetWardenDataById(id); + wd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), id); switch (wd->Type) { @@ -235,7 +235,7 @@ void WardenWin::RequestData() for (std::list::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) { - wd = sWardenCheckMgr->GetWardenDataById(*itr); + wd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), *itr); type = wd->Type; buff << uint8(type ^ xorByte); @@ -360,8 +360,8 @@ void WardenWin::HandleData(ByteBuffer &buff) for (std::list::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) { - rd = sWardenCheckMgr->GetWardenDataById(*itr); - rs = sWardenCheckMgr->GetWardenResultById(*itr); + rd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), *itr); + rs = sWardenCheckMgr->GetWardenResultById(_session->GetClientBuild(), *itr); type = rd->Type; switch (type) @@ -475,7 +475,7 @@ void WardenWin::HandleData(ByteBuffer &buff) if (checkFailed > 0) { - WardenCheck* check = sWardenCheckMgr->GetWardenDataById(checkFailed); //note it IS NOT NULL here + WardenCheck* check = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), checkFailed); //note it IS NOT NULL here sLog.outWarden("%s failed Warden check %u. Action: %s", _session->GetPlayerName(), checkFailed, Penalty(check).c_str()); LogPositiveToDB(check); } diff --git a/src/game/Warden/WardenWin.h b/src/game/Warden/WardenWin.h index 89d8ad86b..2eccebfff 100644 --- a/src/game/Warden/WardenWin.h +++ b/src/game/Warden/WardenWin.h @@ -71,7 +71,7 @@ struct WardenInitModuleRequest #endif class WorldSession; -class Warden; +//class Warden; class WardenWin : public Warden { diff --git a/src/game/WorldHandlers/World.cpp b/src/game/WorldHandlers/World.cpp index 3b8d12c00..206730338 100644 --- a/src/game/WorldHandlers/World.cpp +++ b/src/game/WorldHandlers/World.cpp @@ -84,6 +84,9 @@ // Warden #include "WardenCheckMgr.h" +#include +#include + INSTANTIATE_SINGLETON_1(World); extern void LoadGameObjectModelList(); @@ -122,16 +125,16 @@ World::World() m_availableDbcLocaleMask = 0; for (int i = 0; i < CONFIG_UINT32_VALUE_COUNT; ++i) - m_configUint32Values[i] = 0; + { m_configUint32Values[i] = 0; } for (int i = 0; i < CONFIG_INT32_VALUE_COUNT; ++i) - m_configInt32Values[i] = 0; + { m_configInt32Values[i] = 0; } for (int i = 0; i < CONFIG_FLOAT_VALUE_COUNT; ++i) - m_configFloatValues[i] = 0.0f; + { m_configFloatValues[i] = 0.0f; } for (int i = 0; i < CONFIG_BOOL_VALUE_COUNT; ++i) - m_configBoolValues[i] = false; + { m_configBoolValues[i] = false; } } /// World destructor @@ -153,7 +156,7 @@ World::~World() CliCommandHolder* command = NULL; while (cliCmdQueue.next(command)) - delete command; + { delete command; } VMAP::VMapFactory::clear(); MMAP::MMapFactory::clear(); @@ -167,6 +170,9 @@ void World::CleanupsBeforeStop() KickAll(); // save and kick all players UpdateSessions(1); // real players unload required UpdateSessions call sBattleGroundMgr.DeleteAllBattleGrounds(); // unload battleground templates before different singletons destroyed +#ifdef ENABLE_ELUNA + Eluna::Uninitialize(); +#endif } /// Find a player in a specified zone @@ -196,9 +202,9 @@ WorldSession* World::FindSession(uint32 id) const SessionMap::const_iterator itr = m_sessions.find(id); if (itr != m_sessions.end()) - return itr->second; // also can return NULL for kicked session + { return itr->second; } // also can return NULL for kicked session else - return NULL; + { return NULL; } } /// Remove a given session @@ -210,7 +216,7 @@ bool World::RemoveSession(uint32 id) if (itr != m_sessions.end() && itr->second) { if (itr->second->PlayerLoading()) - return false; + { return false; } itr->second->KickPlayer(); } @@ -250,7 +256,7 @@ World::AddSession_(WorldSession* s) { // prevent decrease sessions count if session queued if (RemoveQueuedSession(old->second)) - decrease_session = false; + { decrease_session = false; } // not remove replaced session form queue if listed delete old->second; } @@ -265,7 +271,7 @@ World::AddSession_(WorldSession* s) // so we don't count the user trying to // login as a session and queue the socket that we are using if (decrease_session) - --Sessions; + { --Sessions; } if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity() == SEC_PLAYER) { @@ -322,7 +328,7 @@ int32 World::GetQueuedSessionPos(WorldSession* sess) for (Queue::const_iterator iter = m_QueuedSessions.begin(); iter != m_QueuedSessions.end(); ++iter, ++position) if ((*iter) == sess) - return position; + { return position; } return 0; } @@ -378,7 +384,7 @@ bool World::RemoveQueuedSession(WorldSession* sess) // if session not queued then we need decrease sessions count if (!found && sessions) - --sessions; + { --sessions; } // accept first in queue if ((!m_playerLimit || (int32)sessions < m_playerLimit) && !m_QueuedSessions.empty()) @@ -405,7 +411,7 @@ bool World::RemoveQueuedSession(WorldSession* sess) // update position from iter to end() // iter point to first not updated socket, position store new position for (; iter != m_QueuedSessions.end(); ++iter, ++position) - (*iter)->SendAuthWaitQue(position); + { (*iter)->SendAuthWaitQue(position); } return found; } @@ -580,22 +586,22 @@ void World::LoadConfigSettings(bool reload) setConfigMin(CONFIG_UINT32_INTERVAL_GRIDCLEAN, "GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS, MIN_GRID_DELAY); if (reload) - sMapMgr.SetGridCleanUpDelay(getConfig(CONFIG_UINT32_INTERVAL_GRIDCLEAN)); + { sMapMgr.SetGridCleanUpDelay(getConfig(CONFIG_UINT32_INTERVAL_GRIDCLEAN)); } setConfigMin(CONFIG_UINT32_INTERVAL_MAPUPDATE, "MapUpdateInterval", 100, MIN_MAP_UPDATE_DELAY); if (reload) - sMapMgr.SetMapUpdateInterval(getConfig(CONFIG_UINT32_INTERVAL_MAPUPDATE)); + { sMapMgr.SetMapUpdateInterval(getConfig(CONFIG_UINT32_INTERVAL_MAPUPDATE)); } setConfig(CONFIG_UINT32_INTERVAL_CHANGEWEATHER, "ChangeWeatherInterval", 10 * MINUTE * IN_MILLISECONDS); if (configNoReload(reload, CONFIG_UINT32_PORT_WORLD, "WorldServerPort", DEFAULT_WORLDSERVER_PORT)) - setConfig(CONFIG_UINT32_PORT_WORLD, "WorldServerPort", DEFAULT_WORLDSERVER_PORT); + { setConfig(CONFIG_UINT32_PORT_WORLD, "WorldServerPort", DEFAULT_WORLDSERVER_PORT); } if (configNoReload(reload, CONFIG_UINT32_GAME_TYPE, "GameType", 0)) - setConfig(CONFIG_UINT32_GAME_TYPE, "GameType", 0); + { setConfig(CONFIG_UINT32_GAME_TYPE, "GameType", 0); } if (configNoReload(reload, CONFIG_UINT32_REALM_ZONE, "RealmZone", REALM_ZONE_DEVELOPMENT)) - setConfig(CONFIG_UINT32_REALM_ZONE, "RealmZone", REALM_ZONE_DEVELOPMENT); + { setConfig(CONFIG_UINT32_REALM_ZONE, "RealmZone", REALM_ZONE_DEVELOPMENT); } setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_ACCOUNTS, "AllowTwoSide.Accounts", true); setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT, "AllowTwoSide.Interaction.Chat", false); @@ -630,7 +636,7 @@ void World::LoadConfigSettings(bool reload) setConfigMinMax(CONFIG_UINT32_SKIP_CINEMATICS, "SkipCinematics", 0, 0, 2); if (configNoReload(reload, CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL)) - setConfigMinMax(CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL, 1, DEFAULT_MAX_LEVEL); + { setConfigMinMax(CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL, 1, DEFAULT_MAX_LEVEL); } setConfigMinMax(CONFIG_UINT32_START_PLAYER_LEVEL, "StartPlayerLevel", 1, 1, getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)); setConfigMinMax(CONFIG_UINT32_START_HEROIC_PLAYER_LEVEL, "StartHeroicPlayerLevel", 55, 1, getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)); @@ -904,9 +910,9 @@ void World::LoadConfigSettings(bool reload) setConfig(CONFIG_UINT32_CHARDELETE_KEEP_DAYS, "CharDelete.KeepDays", 30); if (configNoReload(reload, CONFIG_UINT32_GUID_RESERVE_SIZE_CREATURE, "GuidReserveSize.Creature", 100)) - setConfig(CONFIG_UINT32_GUID_RESERVE_SIZE_CREATURE, "GuidReserveSize.Creature", 100); + { setConfig(CONFIG_UINT32_GUID_RESERVE_SIZE_CREATURE, "GuidReserveSize.Creature", 100); } if (configNoReload(reload, CONFIG_UINT32_GUID_RESERVE_SIZE_GAMEOBJECT, "GuidReserveSize.GameObject", 100)) - setConfig(CONFIG_UINT32_GUID_RESERVE_SIZE_GAMEOBJECT, "GuidReserveSize.GameObject", 100); + { setConfig(CONFIG_UINT32_GUID_RESERVE_SIZE_GAMEOBJECT, "GuidReserveSize.GameObject", 100); } setConfig(CONFIG_UINT32_MIN_LEVEL_FOR_RAID, "Raid.MinLevel", 10); @@ -915,15 +921,15 @@ void World::LoadConfigSettings(bool reload) // for empty string use current dir as for absent case if (dataPath.empty()) - dataPath = "./"; + { dataPath = "./"; } // normalize dir path to path/ or path\ form else if (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\') - dataPath.append("/"); + { dataPath.append("/"); } if (reload) { if (dataPath != m_dataPath) - sLog.outError("DataDir option can't be changed at mangosd.conf reload, using current value (%s).", m_dataPath.c_str()); + { sLog.outError("DataDir option can't be changed at mangosd.conf reload, using current value (%s).", m_dataPath.c_str()); } } else { @@ -937,7 +943,7 @@ void World::LoadConfigSettings(bool reload) std::string ignoreSpellIds = sConfig.GetStringDefault("vmap.ignoreSpellIds", ""); if (!enableHeight) - sLog.outError("VMAP height use disabled! Creatures movements and other things will be in broken state."); + { sLog.outError("VMAP height use disabled! Creatures movements and other things will be in broken state."); } VMAP::VMapFactory::createOrGetVMapManager()->setEnableLineOfSightCalc(enableLOS); VMAP::VMapFactory::createOrGetVMapManager()->setEnableHeightCalc(enableHeight); @@ -950,6 +956,13 @@ void World::LoadConfigSettings(bool reload) std::string ignoreMapIds = sConfig.GetStringDefault("mmap.ignoreMapIds", ""); MMAP::MMapFactory::preventPathfindingOnMaps(ignoreMapIds.c_str()); sLog.outString("WORLD: mmap pathfinding %sabled", getConfig(CONFIG_BOOL_MMAP_ENABLED) ? "en" : "dis"); + + setConfig(CONFIG_BOOL_ELUNA_ENABLED, "Eluna.Enabled", true); + +#ifdef ENABLE_ELUNA + if (reload) + sEluna->OnConfigLoad(reload); +#endif /* ENABLE_ELUNA */ } /// Initialize the World @@ -2012,7 +2025,7 @@ void World::ShutdownMsg(bool show /*= false*/, Player* player /*= NULL*/) { // not show messages for idle shutdown mode if (m_ShutdownMask & SHUTDOWN_MASK_IDLE) - return; + { return; } ///- Display a message every 12 hours, 1 hour, 5 minutes, 1 minute and 15 seconds if (show || @@ -2036,7 +2049,7 @@ void World::ShutdownCancel() { // nothing cancel or too later if (!m_ShutdownTimer || m_stopEvent) - return; + { return; } ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED; @@ -2046,6 +2059,11 @@ void World::ShutdownCancel() SendServerMessage(msgid); DEBUG_LOG("Server %s cancelled.", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutdown")); + + ///- Used by Eluna +#ifdef ENABLE_ELUNA + sEluna->OnShutdownCancel(); +#endif /* ENABLE_ELUNA */ } void World::UpdateSessions(uint32 diff) @@ -2053,7 +2071,7 @@ void World::UpdateSessions(uint32 diff) ///- Add new sessions WorldSession* sess; while (addSessQueue.next(sess)) - AddSession_(sess); + { AddSession_(sess); } ///- Then send an update signal to remaining ones for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next) @@ -2088,7 +2106,7 @@ void World::ProcessCliCommands() handler.ParseCommands(command->m_command); if (command->m_commandFinished) - command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage()); + { command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage()); } delete command; } @@ -2400,24 +2418,27 @@ void World::UpdateMaxSessionCounters() void World::LoadDBVersion() { - QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version, cache_id FROM db_version LIMIT 1"); + QueryResult* result = WorldDatabase.Query("SELECT version, structure, content FROM db_version ORDER BY version DESC, structure DESC, content DESC LIMIT 1"); if (result) { Field* fields = result->Fetch(); - m_DBVersion = fields[0].GetCppString(); - m_CreatureEventAIVersion = fields[1].GetCppString(); + uint32 version = fields[0].GetUInt32(); + uint32 structure = fields[1].GetUInt32(); + uint32 content = fields[2].GetUInt32(); // will be overwrite by config values if different and non-0 setConfig(CONFIG_UINT32_CLIENTCACHE_VERSION, fields[2].GetUInt32()); delete result; + + std::stringstream ss; + ss << "Version: " << version << ", Structure: " << structure << ", Content: " << content; + + m_DBVersion = ss.str(); } if (m_DBVersion.empty()) - m_DBVersion = "Unknown world database."; - - if (m_CreatureEventAIVersion.empty()) - m_CreatureEventAIVersion = "Unknown creature EventAI."; + { m_DBVersion = "Unknown world database."; } } void World::setConfig(eConfigUInt64Values index, char const* fieldname, uint64 defvalue) @@ -2598,11 +2619,11 @@ void World::setConfigMinMax(eConfigFloatValues index, char const* fieldname, flo bool World::configNoReload(bool reload, eConfigUInt32Values index, char const* fieldname, uint32 defvalue) { if (!reload) - return true; + { return true; } uint32 val = sConfig.GetIntDefault(fieldname, defvalue); if (val != getConfig(index)) - sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%u).", fieldname, getConfig(index)); + { sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%u).", fieldname, getConfig(index)); } return false; } @@ -2610,11 +2631,11 @@ bool World::configNoReload(bool reload, eConfigUInt32Values index, char const* f bool World::configNoReload(bool reload, eConfigInt32Values index, char const* fieldname, int32 defvalue) { if (!reload) - return true; + { return true; } int32 val = sConfig.GetIntDefault(fieldname, defvalue); if (val != getConfig(index)) - sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%i).", fieldname, getConfig(index)); + { sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%i).", fieldname, getConfig(index)); } return false; } @@ -2622,11 +2643,11 @@ bool World::configNoReload(bool reload, eConfigInt32Values index, char const* fi bool World::configNoReload(bool reload, eConfigFloatValues index, char const* fieldname, float defvalue) { if (!reload) - return true; + { return true; } float val = sConfig.GetFloatDefault(fieldname, defvalue); if (val != getConfig(index)) - sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%f).", fieldname, getConfig(index)); + { sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%f).", fieldname, getConfig(index)); } return false; } @@ -2634,11 +2655,11 @@ bool World::configNoReload(bool reload, eConfigFloatValues index, char const* fi bool World::configNoReload(bool reload, eConfigBoolValues index, char const* fieldname, bool defvalue) { if (!reload) - return true; + { return true; } bool val = sConfig.GetBoolDefault(fieldname, defvalue); if (val != getConfig(index)) - sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%s).", fieldname, getConfig(index) ? "'true'" : "'false'"); + { sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%s).", fieldname, getConfig(index) ? "'true'" : "'false'"); } return false; } diff --git a/src/game/WorldHandlers/World.h b/src/game/WorldHandlers/World.h index 670416126..ecc1e74b3 100644 --- a/src/game/WorldHandlers/World.h +++ b/src/game/WorldHandlers/World.h @@ -39,6 +39,7 @@ #include class Object; +class ObjectGuid; class WorldPacket; class WorldSession; class Player; @@ -379,6 +380,7 @@ enum eConfigBoolValues CONFIG_BOOL_VMAP_INDOOR_CHECK, CONFIG_BOOL_PET_UNSUMMON_AT_MOUNT, CONFIG_BOOL_MMAP_ENABLED, + CONFIG_BOOL_ELUNA_ENABLED, CONFIG_BOOL_PLAYER_COMMANDS, CONFIG_BOOL_GUILD_LEVELING_ENABLED, // Warden @@ -641,7 +643,6 @@ class World // used World DB version void LoadDBVersion(); char const* GetDBVersion() { return m_DBVersion.c_str(); } - char const* GetCreatureEventAIVersion() { return m_CreatureEventAIVersion.c_str(); } void UpdatePhaseDefinitions(); @@ -748,7 +749,6 @@ class World // used versions std::string m_DBVersion; - std::string m_CreatureEventAIVersion; }; extern uint32 realmID; diff --git a/src/mangosd/CMakeLists.txt b/src/mangosd/CMakeLists.txt index 0fee6974a..ab2d6253f 100644 --- a/src/mangosd/CMakeLists.txt +++ b/src/mangosd/CMakeLists.txt @@ -168,12 +168,12 @@ if(WIN32) if(MSVC) add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${MYSQL_INCLUDE_DIR}/../lib/libmysql.dll" "${CMAKE_BINARY_DIR}/bin/$(Configuration)/" + COMMAND ${CMAKE_COMMAND} -E copy "${MYSQL_LIBRARY}" "${CMAKE_BINARY_DIR}/bin/$(Configuration)/" ) elseif(XCODE) add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${MYSQL_INCLUDE_DIR}/../lib/libmysql.dll" "${CMAKE_BINARY_DIR}/bin/" + COMMAND ${CMAKE_COMMAND} -E copy "${MYSQL_LIBRARY}" "${CMAKE_BINARY_DIR}/bin/" ) endif() endif() diff --git a/src/mangosd/Comm/CliRunnable.cpp b/src/mangosd/Comm/CliRunnable.cpp index 6bad4183e..2ab6bdfb1 100644 --- a/src/mangosd/Comm/CliRunnable.cpp +++ b/src/mangosd/Comm/CliRunnable.cpp @@ -580,7 +580,7 @@ bool ChatHandler::HandleServerLogLevelCommand(char* args) /// @} -#ifdef linux +#if (PLATFORM == PLATFORM_APPLE) || (PLATFORM == PLATFORM_UNIX) // Non-blocking keypress detector, when return pressed, return 1, else always return 0 int kb_hit_return() { @@ -617,7 +617,7 @@ void CliRunnable::run() while (!World::IsStopped()) { fflush(stdout); -#ifdef linux +#if (PLATFORM == PLATFORM_APPLE) || (PLATFORM == PLATFORM_UNIX) while (!kb_hit_return() && !World::IsStopped()) // With this, we limit CLI to 10commands/second { usleep(100); } diff --git a/src/mangosd/Main.cpp b/src/mangosd/Main.cpp index 779bbe351..d4904f923 100644 --- a/src/mangosd/Main.cpp +++ b/src/mangosd/Main.cpp @@ -45,6 +45,7 @@ char serviceName[] = "mangosd"; char serviceLongName[] = "MaNGOS world service"; char serviceDescription[] = "Massive Network Game Object Server"; +const char RAW_VMAP_MAGIC[] = "VMAPc06"; /**< used in extracted vmap files with raw data */ /* * -1 - not in service mode * 0 - stopped diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 92eec7db6..0075a3f26 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -465,7 +465,8 @@ bool Master::_StartDB() return false; } - if (!WorldDatabase.CheckRequiredField("db_version", REVISION_DB_MANGOS)) + ///- Check the World database version + if(!WorldDatabase.CheckDatabaseVersion(DATABASE_WORLD)) { ///- Wait for already started DB delay threads to end WorldDatabase.HaltDelayThread(); @@ -494,7 +495,8 @@ bool Master::_StartDB() return false; } - if (!CharacterDatabase.CheckRequiredField("character_db_version", REVISION_DB_CHARACTERS)) + ///- Check the Character database version + if (!CharacterDatabase.CheckDatabaseVersion(DATABASE_CHARACTER)) { ///- Wait for already started DB delay threads to end WorldDatabase.HaltDelayThread(); @@ -527,7 +529,8 @@ bool Master::_StartDB() return false; } - if (!LoginDatabase.CheckRequiredField("realmd_db_version", REVISION_DB_REALMD)) + ///- Check the Realm database version + if (!LoginDatabase.CheckDatabaseVersion(DATABASE_REALMD)) { ///- Wait for already started DB delay threads to end WorldDatabase.HaltDelayThread(); @@ -560,7 +563,6 @@ bool Master::_StartDB() sWorld.LoadDBVersion(); sLog.outString("Using World DB: %s", sWorld.GetDBVersion()); - sLog.outString("Using creature EventAI: %s", sWorld.GetCreatureEventAIVersion()); sLog.outString(); return true; } diff --git a/src/mangosd/RA/RASocket.h b/src/mangosd/RA/RASocket.h index a21cebe7c..4e85b6f8c 100644 --- a/src/mangosd/RA/RASocket.h +++ b/src/mangosd/RA/RASocket.h @@ -26,8 +26,8 @@ /// @{ /// \file -#ifndef _RASOCKET_H -#define _RASOCKET_H +#ifndef MANGOS_H_RASOCKET +#define MANGOS_H_RASOCKET #include "Common.h" #include diff --git a/src/mangosd/WorldRunnable.cpp b/src/mangosd/WorldRunnable.cpp index 612f6d078..8be8af668 100644 --- a/src/mangosd/WorldRunnable.cpp +++ b/src/mangosd/WorldRunnable.cpp @@ -57,7 +57,7 @@ void WorldRunnable::run() uint32 realCurrTime = 0; uint32 realPrevTime = WorldTimer::tick(); - uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST + uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST ///- While we have not World::m_stopEvent, update the world while (!World::IsStopped()) diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index d3f072b03..dcf4a517a 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -3,9 +3,9 @@ ################################################################################ [MangosdConf] -ConfVersion=2013122901 +ConfVersion=2016031901 -################################################################################################################### +################################################################################ # CONNECTIONS AND DIRECTORIES # # RealmID @@ -26,7 +26,6 @@ ConfVersion=2013122901 # LoginDatabaseInfo # WorldDatabaseInfo # CharacterDatabaseInfo -# ScriptDev2DatabaseInfo # Database connection settings for the world server. # Default: # ---MYSQL--- @@ -41,7 +40,6 @@ ConfVersion=2013122901 # LoginDatabaseConnections # WorldDatabaseConnections # CharacterDatabaseConnections -# ScriptDev2DatabaseConnections # Amount of connections to database which will be used for SELECT queries. Maximum 16 connections per database. # Please, note, for data consistency only one connection for each database is used for transactions and async SELECTs. # So formula to find out how many connections will be established: @@ -68,12 +66,10 @@ LogsDir = "" LoginDatabaseInfo = "127.0.0.1;3306;mangos;mangos;realmd" WorldDatabaseInfo = "127.0.0.1;3306;mangos;mangos;mangos" CharacterDatabaseInfo = "127.0.0.1;3306;mangos;mangos;characters" -ScriptDev2DatabaseInfo = "127.0.0.1;3306;mangos;mangos;mangos" LoginDatabaseConnections = 1 WorldDatabaseConnections = 1 CharacterDatabaseConnections = 1 -ScriptDev2DatabaseConnections= 1 -MaxPingTime = 30 +MaxPingTime = 5 WorldServerPort = 8085 BindIP = "0.0.0.0" @@ -310,6 +306,10 @@ CleanCharacterDB = 1 # Log file of DB errors detected at server run # Default: "DBErrors.log" # +# ElunaErrorLogFile +# Log file of Eluna errors detected at server run +# Default: "ElunaErrors.log" +# # EventAIErrorLogFile # Log file of EventAI errors detected at server run # Default: "EventAIErrors.log" @@ -352,6 +352,11 @@ CleanCharacterDB = 1 # Default: "Ra.log" # "" - Empty name for disable # +# WardenLogFile +# Log file for warden-related output +# Default: "" - no log file created +# "warden.log" - recommended name to create a log file +# # LogColors # Color for messages (format "normal_color details_color debug_color error_color") # Colors: 0 - BLACK, 1 - RED, 2 - GREEN, 3 - BROWN, 4 - BLUE, 5 - MAGENTA, 6 - CYAN, 7 - GREY, @@ -389,6 +394,7 @@ LogFilter_Calendar = 1 WorldLogFile = "world-packets.log" WorldLogTimestamp = 0 DBErrorLogFile = "world-database.log" +ElunaErrorLogFile = "ElunaErrors.log" EventAIErrorLogFile = "world-eventai.log" CharLogFile = "world-characters.log" CharLogTimestamp = 0 @@ -397,6 +403,8 @@ GmLogFile = "world-gamemaster.log" GmLogTimestamp = 0 GmLogPerAccount = 0 RaLogFile = "world-remote-access.log" +WardenLogFile = "warden.log" +WardenLogTimestamp = 0 LogColors = "13 7 11 9" SD2ErrorLogFile = "scriptdev2-errors.log" @@ -735,7 +743,7 @@ SD2ErrorLogFile = "scriptdev2-errors.log" # 1 - recheck offhand slot weapon at talent reset also # # PetUnsummonAtMount -# Persmanent pet will unsummoned at player mount +# Permanent pet will unsummoned at player mount # 0 - unsummon only for flying mounts # Default: 1 - unsummon for any mount # @@ -776,11 +784,11 @@ SD2ErrorLogFile = "scriptdev2-errors.log" # You can bypass this setting by typing "/script SetAllowLowLevelRaid(true/false)" command in chat # Default: 10 # -################################################################################################################### +################################################################################ GameType = 1 RealmZone = 1 -Expansion = 3 +Expansion = 3 DBC.Locale = 255 DeclinedNames = 0 StrictPlayerNames = 0 @@ -792,15 +800,15 @@ MinPetName = 2 CharactersCreatingDisabled = 0 CharactersPerAccount = 50 CharactersPerRealm = 10 -HeroicCharactersPerRealm = 1 -MinLevelForHeroicCharacterCreating = 55 +HeroicCharactersPerRealm = 1 +MinLevelForHeroicCharacterCreating = 55 SkipCinematics = 0 -MaxPlayerLevel = 85 +MaxPlayerLevel = 85 StartPlayerLevel = 1 -StartHeroicPlayerLevel = 55 +StartHeroicPlayerLevel = 55 StartPlayerMoney = 0 InstantLogout = 1 -DisableWaterBreath = 4 +DisableWaterBreath = 4 AllFlightPaths = 0 ActivateWeather = 1 CastUnstuck = 1 @@ -831,15 +839,15 @@ MaxPrimaryTradeSkill = 2 TradeSkill.GMIgnore.MaxPrimarySkillsCount = 4 TradeSkill.GMIgnore.Level = 4 TradeSkill.GMIgnore.Skill = 4 -MinPetitionSigns = 4 +MinPetitionSigns = 4 MaxGroupXPDistance = 74 MailDeliveryDelay = 3600 MassMailer.SendPerTick = 10 -SkillChance.Prospecting = 0 -SkillChance.Milling = 0 -OffhandCheckAtTalentsReset = 0 -PetUnsummonAtMount = 1 -ClientCacheVersion = 0 +SkillChance.Prospecting = 0 +SkillChance.Milling = 0 +OffhandCheckAtTalentsReset = 0 +PetUnsummonAtMount = 1 +ClientCacheVersion = 0 Event.Announce = 0 BeepAtStart = 1 ShowProgressBars = 1 @@ -1010,22 +1018,23 @@ Corpse.Decay.RARE = 900 Corpse.Decay.ELITE = 600 Corpse.Decay.RAREELITE = 1200 Corpse.Decay.WORLDBOSS = 3600 -Rate.Corpse.Decay.Looted = 0.0 -Rate.Creature.Normal.Damage = 1 +Rate.Corpse.Decay.Looted = 0.0 Rate.Creature.Elite.Elite.Damage = 1 -Rate.Creature.Elite.RAREELITE.Damage = 1 -Rate.Creature.Elite.WORLDBOSS.Damage = 1 +Rate.Creature.Elite.Elite.HP = 1 +Rate.Creature.Elite.Elite.SpellDamage = 1 Rate.Creature.Elite.RARE.Damage = 1 -Rate.Creature.Normal.SpellDamage = 1 -Rate.Creature.Elite.Elite.SpellDamage = 1 +Rate.Creature.Elite.RARE.HP = 1 +Rate.Creature.Elite.RARE.SpellDamage = 1 +Rate.Creature.Elite.RAREELITE.Damage = 1 +Rate.Creature.Elite.RAREELITE.HP = 1 Rate.Creature.Elite.RAREELITE.SpellDamage = 1 +Rate.Creature.Elite.WORLDBOSS.Damage = 1 +Rate.Creature.Elite.WORLDBOSS.HP = 1 Rate.Creature.Elite.WORLDBOSS.SpellDamage = 1 -Rate.Creature.Elite.RARE.SpellDamage = 1 +Rate.Creature.Normal.Damage = 1 Rate.Creature.Normal.HP = 1 -Rate.Creature.Elite.Elite.HP = 1 -Rate.Creature.Elite.RAREELITE.HP = 1 -Rate.Creature.Elite.WORLDBOSS.HP = 1 -Rate.Creature.Elite.RARE.HP = 1 +Rate.Creature.Normal.SpellDamage = 1 + ListenRange.Say = 40 ListenRange.TextEmote = 40 ListenRange.Yell = 300 @@ -1163,16 +1172,16 @@ Channel.SilentlyGMJoin = 0 # ################################################################################ -GM.LoginState = 2 -GM.Visible = 2 -GM.AcceptTickets = 2 -GM.Chat = 2 -GM.WhisperingTo = 2 -GM.InGMList.Level = 3 -GM.InWhoList.Level = 3 -GM.LogTrade = 1 -GM.StartLevel = 1 -GM.LowerSecurity = 0 +GM.LoginState = 2 +GM.Visible = 2 +GM.AcceptTickets = 2 +GM.Chat = 2 +GM.WhisperingTo = 2 +GM.InGMList.Level = 3 +GM.InWhoList.Level = 3 +GM.LogTrade = 1 +GM.StartLevel = 1 +GM.LowerSecurity = 0 GM.AllowAchievementGain = 1 GM.InvisibleAura = 37800 @@ -1393,8 +1402,8 @@ Rate.Health = 1 Rate.Mana = 1 Rate.Rage.Income = 1 Rate.Rage.Loss = 1 -Rate.RunicPower.Income = 1 -Rate.RunicPower.Loss = 1 +Rate.RunicPower.Income = 1 +Rate.RunicPower.Loss = 1 Rate.Focus = 1 Rate.Energy = 1 Rate.Skill.Discovery = 1 @@ -1407,8 +1416,8 @@ Rate.Drop.Item.Legendary = 1 Rate.Drop.Item.Artifact = 1 Rate.Drop.Item.Referenced = 1 Rate.Drop.Money = 1 -Rate.Drop.Currency = 1 -Rate.Drop.Currency.Amount = 1 +Rate.Drop.Currency = 1 +Rate.Drop.Currency.Amount = 1 Rate.XP.Kill = 1 Rate.XP.Quest = 1 Rate.XP.Explore = 1 @@ -1419,13 +1428,13 @@ Rate.Damage.Fall = 1 Rate.Auction.Time = 1 Rate.Auction.Deposit = 1 Rate.Auction.Cut = 1 -Auction.Deposit.Min = 100 +Auction.Deposit.Min = 100 Rate.Honor = 1 Rate.Mining.Amount = 1 Rate.Mining.Next = 1 Rate.Talent = 1 Rate.Reputation.Gain = 1 -Rate.Reputation.LowLevel.Kill = 1 +Rate.Reputation.LowLevel.Kill = 1 Rate.Reputation.LowLevel.Quest = 1 Rate.InstanceResetTime = 1 @@ -1439,9 +1448,9 @@ SkillChance.Grey = 0 SkillChance.MiningSteps = 0 SkillChance.SkinningSteps = 0 -SkillFail.Loot.Fishing = 1 -SkillFail.Gain.Fishing = 1 -SkillFail.Possible.FishingPool = 0 +SkillFail.Loot.Fishing = 1 +SkillFail.Gain.Fishing = 1 +SkillFail.Possible.FishingPool = 0 DurabilityLossChance.Damage = 0.5 DurabilityLossChance.Absorb = 0.5 @@ -1737,3 +1746,28 @@ Currency.ResetWeekDay = 3 Currency.ResetHour = 6 Currency.ConquestPointsDefaultWeekCap = 135000 Currency.ConquestPointsArenaReward = 12000 + +################################################################################################################### +# ELUNA SETTINGS +# +# Eluna.Enabled +# Enable Eluna LuaEngine +# Default: 1 (Enabled) +# 0 (Disabled) +# +# Eluna.TraceBack +# Description: Sets whether to use debug.traceback function on a lua error or not. +# Notice that you can redefine the function. +# Default: false - (use default error output) +# true - (use debug.traceback function) +# +# Eluna.ScriptPath +# Description: Sets the location of the script folder to load scripts from +# The path can be relative or absolute. +# Default: "lua_scripts" +# +################################################################################################################### + +Eluna.Enabled = 1 +Eluna.TraceBack = false +Eluna.ScriptPath = "lua_scripts" diff --git a/src/realmd b/src/realmd index 9c9e7ae79..15df5d42a 160000 --- a/src/realmd +++ b/src/realmd @@ -1 +1 @@ -Subproject commit 9c9e7ae7919e1cd5ce1f454520b9adf3316e2137 +Subproject commit 15df5d42ae03cabe9cebfbd7534df8af4f739ecb diff --git a/src/shared/Common/Common.h b/src/shared/Common/Common.h index 82f77978d..c53a4e3a2 100644 --- a/src/shared/Common/Common.h +++ b/src/shared/Common/Common.h @@ -149,7 +149,16 @@ typedef off_t ACE_OFF_T; #endif -#define UI64FMTD ACE_UINT64_FORMAT_SPECIFIER +#if defined(__APPLE__) +# ifdef I64FMT +# undef I64FMT +# endif +# define I64FMT "%016llX" +# define UI64FMTD "%llu" +#else +# define UI64FMTD ACE_UINT64_FORMAT_SPECIFIER +#endif + #define UI64LIT(N) ACE_UINT64_LITERAL(N) #define SI64FMTD ACE_INT64_FORMAT_SPECIFIER diff --git a/src/shared/DataStores/DBCFileLoader.cpp b/src/shared/DataStores/DBCFileLoader.cpp index a31a8a2ac..46e72d282 100644 --- a/src/shared/DataStores/DBCFileLoader.cpp +++ b/src/shared/DataStores/DBCFileLoader.cpp @@ -50,7 +50,6 @@ bool DBCFileLoader::Load(const char* filename, const char* fmt) } EndianConvert(header); - if (header != 0x43424457) //'WDBC' { fclose(f); @@ -366,11 +365,9 @@ char* DBCFileLoader::AutoProduceStrings(const char* format, char* dataTable, Loc break; case DBC_FF_STRING: { - char** holder = *((char***)(&dataTable[offset])); - char** slot = &holder[loc]; - // fill only not filled entries - if (*slot == nullStr) + char** slot = (char**)(&dataTable[offset]); + if (!*slot || !** slot) { const char* st = getRecord(y).getString(x); *slot = stringPool + (st - (const char*)stringTable); diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp index 15ef7eac3..715cb57cd 100644 --- a/src/shared/Database/Database.cpp +++ b/src/shared/Database/Database.cpp @@ -25,6 +25,7 @@ #include "DatabaseEnv.h" #include "Config/Config.h" #include "Database/SqlOperations.h" +#include "revision.h" #include #include @@ -34,6 +35,21 @@ #define MIN_CONNECTION_POOL_SIZE 1 #define MAX_CONNECTION_POOL_SIZE 16 +struct DBVersion +{ + std::string dbname; + uint32 expected_version; + uint32 expected_structure; + uint32 expected_content; + std::string description; +}; + +const DBVersion databaseVersions[COUNT_DATABASES] = { + { "World", WORLD_DB_VERSION_NR, WORLD_DB_STRUCTURE_NR, WORLD_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_WORLD + { "Realmd", REALMD_DB_VERSION_NR, REALMD_DB_STRUCTURE_NR, REALMD_DB_CONTENT_NR, REALMD_DB_UPDATE_DESCRIPTION }, // DATABASE_REALMD + { "Character", CHAR_DB_VERSION_NR, CHAR_DB_STRUCTURE_NR, CHAR_DB_CONTENT_NR, CHAR_DB_UPDATE_DESCRIPTION }, // DATABASE_CHARACTER +}; + ////////////////////////////////////////////////////////////////////////// SqlPreparedStatement* SqlConnection::CreateStatement(const std::string& fmt) { @@ -178,6 +194,7 @@ void Database::InitDelayThread() // New delay thread for delay execute m_threadBody = CreateDelayThread(); // will deleted at m_delayThread delete + m_TransStorage = new ACE_TSS(); m_delayThread = new ACE_Based::Thread(m_threadBody); } @@ -187,9 +204,11 @@ void Database::HaltDelayThread() m_threadBody->Stop(); // Stop event m_delayThread->wait(); // Wait for flush to DB + delete m_TransStorage; delete m_delayThread; // This also deletes m_threadBody m_delayThread = NULL; m_threadBody = NULL; + m_TransStorage=NULL; } void Database::ThreadStart() @@ -333,7 +352,7 @@ bool Database::Execute(const char* sql) if (!m_pAsyncConn) { return false; } - SqlTransaction* pTrans = m_TransStorage->get(); + SqlTransaction* pTrans = (*m_TransStorage)->get(); if (pTrans) { // add SQL request to trans queue @@ -399,7 +418,7 @@ bool Database::BeginTransaction() // initiate transaction on current thread // currently we do not support queued transactions - m_TransStorage->init(); + (*m_TransStorage)->init(); return true; } @@ -409,7 +428,7 @@ bool Database::CommitTransaction() { return false; } // check if we have pending transaction - if (!m_TransStorage->get()) + if (!(*m_TransStorage)->get()) { return false; } // if async execution is not available @@ -417,7 +436,7 @@ bool Database::CommitTransaction() { return CommitTransactionDirect(); } // add SqlTransaction to the async queue - m_threadBody->Delay(m_TransStorage->detach()); + m_threadBody->Delay((*m_TransStorage)->detach()); return true; } @@ -427,11 +446,11 @@ bool Database::CommitTransactionDirect() { return false; } // check if we have pending transaction - if (!m_TransStorage->get()) + if (!(*m_TransStorage)->get()) { return false; } // directly execute SqlTransaction - SqlTransaction* pTrans = m_TransStorage->detach(); + SqlTransaction* pTrans = (*m_TransStorage)->detach(); pTrans->Execute(m_pAsyncConn); delete pTrans; @@ -443,101 +462,93 @@ bool Database::RollbackTransaction() if (!m_pAsyncConn) { return false; } - if (!m_TransStorage->get()) + if (!(*m_TransStorage)->get()) { return false; } // remove scheduled transaction - m_TransStorage->reset(); + (*m_TransStorage)->reset(); return true; } -bool Database::CheckRequiredField(char const* table_name, char const* required_name) +bool Database::CheckDatabaseVersion(DatabaseTypes database) { - // check required field - QueryResult* result = PQuery("SELECT %s FROM %s LIMIT 1", required_name, table_name); - if (result) - { - delete result; - return true; - } + const DBVersion& dbversion = databaseVersions[database]; - // check fail, prepare readabale error message + // Fetch the database version table information + QueryResult* result = Query("SELECT version, structure, content, description FROM db_version ORDER BY version DESC, structure DESC, content DESC LIMIT 1"); - // search current required_* field in DB - const char* db_name; - if (!strcmp(table_name, "db_version")) - { db_name = "WORLD"; } - else if (!strcmp(table_name, "character_db_version")) - { db_name = "CHARACTER"; } - else if (!strcmp(table_name, "realmd_db_version")) - { db_name = "REALMD"; } - else - { db_name = "UNKNOWN"; } - - char const* req_sql_update_name = required_name + strlen("required_"); - - QueryNamedResult* result2 = PQueryNamed("SELECT * FROM %s LIMIT 1", table_name); - if (result2) - { - QueryFieldNames const& namesMap = result2->GetFieldNames(); - std::string reqName; - for (QueryFieldNames::const_iterator itr = namesMap.begin(); itr != namesMap.end(); ++itr) - { - if (itr->substr(0, 9) == "required_") - { - reqName = *itr; - break; - } - } - - delete result2; - - std::string cur_sql_update_name = reqName.substr(strlen("required_"), reqName.npos); - - if (!reqName.empty()) - { - sLog.outErrorDb("The table `%s` in your [%s] database indicates that this database is out of date!", table_name, db_name); - sLog.outErrorDb(); - sLog.outErrorDb(" [A] You have: --> `%s.sql`", cur_sql_update_name.c_str()); - sLog.outErrorDb(); - sLog.outErrorDb(" [B] You need: --> `%s.sql`", req_sql_update_name); - sLog.outErrorDb(); - sLog.outErrorDb("You must apply all updates after [A] to [B] to use mangos with this database."); - sLog.outErrorDb("These updates are included in the sql/updates folder."); - sLog.outErrorDb("Please read the included [README] in sql/updates for instructions on updating."); - } - else - { - sLog.outErrorDb("The table `%s` in your [%s] database is missing its version info.", table_name, db_name); - sLog.outErrorDb("MaNGOS can not find the version info needed to check that the db is up to date."); - sLog.outErrorDb(); - sLog.outErrorDb("This revision of MaNGOS requires a database updated to:"); - sLog.outErrorDb("`%s.sql`", req_sql_update_name); - sLog.outErrorDb(); - - if (!strcmp(db_name, "WORLD")) - { sLog.outErrorDb("Post this error to your database provider forum or find a solution there."); } - else - { sLog.outErrorDb("Reinstall your [%s] database with the included sql file in the sql folder.", db_name); } - } - } - else - { - sLog.outErrorDb("The table `%s` in your [%s] database is missing or corrupt.", table_name, db_name); - sLog.outErrorDb("MaNGOS can not find the version info needed to check that the db is up to date."); + // db_version table does not exist or is empty + if (!result) + { + sLog.outErrorDb("The table `db_version` in your [%s] database is missing or corrupt.", dbversion.dbname.c_str()); sLog.outErrorDb(); - sLog.outErrorDb("This revision of mangos requires a database updated to:"); - sLog.outErrorDb("`%s.sql`", req_sql_update_name); + sLog.outErrorDb(" [A] You have database Version: MaNGOS can not verify your database version or its existence!"); sLog.outErrorDb(); - - if (!strcmp(db_name, "WORLD")) - { sLog.outErrorDb("Post this error to your database provider forum or find a solution there."); } - else - { sLog.outErrorDb("Reinstall your [%s] database with the included sql file in the sql folder.", db_name); } + sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version); + sLog.outErrorDb(" Structure: %u", dbversion.expected_structure); + sLog.outErrorDb(" Content: %u", dbversion.expected_content); + sLog.outErrorDb(" Description: %s", dbversion.description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb("Please verify your database location or your database integrity."); + return false; } - return false; + Field* fields = result->Fetch(); + uint32 version = fields[0].GetUInt32(); + uint32 structure = fields[1].GetUInt32(); + uint32 content = fields[2].GetUInt32(); + std::string description = fields[3].GetCppString(); + + delete result; + + // Structure does not match the required version + if (version != dbversion.expected_version || structure != dbversion.expected_structure) + { + sLog.outErrorDb("The table `db_version` indicates that your [%s] database does not match the expected structure!", dbversion.dbname.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [A] You have database Version: %u", version); + sLog.outErrorDb(" Structure: %u", structure); + sLog.outErrorDb(" Content: %u", content); + sLog.outErrorDb(" Description: %s", description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version); + sLog.outErrorDb(" Structure: %u", dbversion.expected_structure); + sLog.outErrorDb(" Content: %u", dbversion.expected_content); + sLog.outErrorDb(" Description: %s", dbversion.description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb("You must apply all updates after [A] to [B] to use MaNGOS with this database."); + sLog.outErrorDb("These updates are included in the database/%s/Updates folder.", dbversion.dbname.c_str()); + return false; + } + + // DB is not up to date, but structure is correct. Send warning but start core + if (content > dbversion.expected_content) + { + sLog.outErrorDb("You have not updated the core for few DB [%s] updates!", dbversion.dbname.c_str()); + sLog.outErrorDb("Current DB content is %u, core expects %u", content, dbversion.expected_content); + sLog.outErrorDb("This is ok for now but should not last long."); + } + else if (content != dbversion.expected_content) + { + sLog.outErrorDb("The table `db_version` indicates that your [%s] database does not match the expected version!", dbversion.dbname.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [A] You have database Version: %u", version); + sLog.outErrorDb(" Structure: %u", structure); + sLog.outErrorDb(" Content: %u", content); + sLog.outErrorDb(" Description: %s", description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version); + sLog.outErrorDb(" Structure: %u", dbversion.expected_structure); + sLog.outErrorDb(" Content: %u", dbversion.expected_content); + sLog.outErrorDb(" Description: %s", dbversion.description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb("You are missing content updates or you have content updates beyond the expected core version."); + sLog.outErrorDb("It is recommended to run ALL database updates up to the required core version."); + sLog.outErrorDb("These updates are included in the database/%s/Updates folder.", dbversion.dbname.c_str()); + }; + + return true; } bool Database::ExecuteStmt(const SqlStatementID& id, SqlStmtParameters* params) @@ -545,7 +556,7 @@ bool Database::ExecuteStmt(const SqlStatementID& id, SqlStmtParameters* params) if (!m_pAsyncConn) { return false; } - SqlTransaction* pTrans = m_TransStorage->get(); + SqlTransaction* pTrans = (*m_TransStorage)->get(); if (pTrans) { // add SQL request to trans queue diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index 6250cc42f..6249ae942 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -43,6 +43,14 @@ class Database; #define MAX_QUERY_LEN (32*1024) +enum DatabaseTypes +{ + DATABASE_WORLD, + DATABASE_REALMD, + DATABASE_CHARACTER, + COUNT_DATABASES, +}; + /** * @brief * @@ -613,13 +621,12 @@ class Database void ProcessResultQueue(); /** - * @brief - * - * @param table_name - * @param required_name - * @return bool - */ - bool CheckRequiredField(char const* table_name, char const* required_name); + * @brief Function to check that the database version matches expected core version + * + * @param DatabaseTypes + * @return bool + */ + bool CheckDatabaseVersion(DatabaseTypes database); /** * @brief * @@ -651,7 +658,7 @@ class Database Database() : m_nQueryConnPoolSize(1), m_pAsyncConn(NULL), m_pResultQueue(NULL), m_threadBody(NULL), m_delayThread(NULL), m_bAllowAsyncTransactions(false), - m_iStmtIndex(-1), m_logSQL(false), m_pingIntervallms(0) + m_iStmtIndex(-1), m_logSQL(false), m_pingIntervallms(0), m_TransStorage(NULL) { m_nQueryCounter = -1; } @@ -679,7 +686,7 @@ class Database * @brief * */ - class TransHelper + class TransHelper { public: /** @@ -730,7 +737,7 @@ class Database * */ typedef ACE_TSS DBTransHelperTSS; - Database::DBTransHelperTSS m_TransStorage; /**< TODO */ + Database::DBTransHelperTSS *m_TransStorage; /**< TODO */ ///< DB connections /** @@ -781,7 +788,7 @@ class Database SqlResultQueue* m_pResultQueue; /**< Transaction queues from diff. threads */ SqlDelayThread* m_threadBody; /**< Pointer to delay sql executer (owned by m_delayThread) */ - ACE_Based::Thread* m_delayThread; /**< Pointer to executer thread */ + ACE_Based::Thread* m_delayThread; /**< Pointer to executer thread */ bool m_bAllowAsyncTransactions; /**< flag which specifies if async transactions are enabled */ diff --git a/src/shared/Database/Field.h b/src/shared/Database/Field.h index e8a10408e..4ebf2a78c 100644 --- a/src/shared/Database/Field.h +++ b/src/shared/Database/Field.h @@ -114,7 +114,7 @@ class Field * * @return int8 */ - int8 GetInt8() const { return mValue ? static_cast(atol(mValue)) : int8(0); } + int8 GetInt8() const { return mValue ? static_cast(atol(mValue)) : int8(0); } /** * @brief * @@ -154,29 +154,29 @@ class Field { uint64 value = 0; if (!mValue || sscanf(mValue, UI64FMTD, &value) == -1) - return 0; + { return 0; } return value; - } + } /** * @brief * * @return int64 */ - uint64 GetInt64() const - { - int64 value = 0; - if (!mValue || sscanf(mValue, SI64FMTD, &value) == -1) - return 0; + uint64 GetInt64() const + { + int64 value = 0; + if (!mValue || sscanf(mValue, SI64FMTD, &value) == -1) + return 0; - return value; - } + return value; + } - /** - * @brief - * - * @param type - */ + /** + * @brief + * + * @param type + */ void SetType(enum DataTypes type) { mType = type; } /** diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index 38c676520..7adabf311 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -162,7 +162,7 @@ void SQLStorage::prepareToLoad(uint32 maxRecordId, uint32 recordCount, uint32 re // Set index array m_Index = new char*[maxRecordId]; - memset(m_Index, NULL, maxRecordId * sizeof(char*)); + memset(m_Index, 0, maxRecordId * sizeof(char*)); SQLStorageBase::prepareToLoad(maxRecordId, recordCount, recordSize); } diff --git a/src/shared/SystemConfig.h.in b/src/shared/SystemConfig.h.in index a5151689a..22f685f7c 100644 --- a/src/shared/SystemConfig.h.in +++ b/src/shared/SystemConfig.h.in @@ -42,7 +42,7 @@ // Format is YYYYMMDDRR where RR is the change in the conf file // for that day. #ifndef MANGOSD_CONFIG_VERSION -# define MANGOSD_CONFIG_VERSION 2015010201 +# define MANGOSD_CONFIG_VERSION 2016031901 #endif #ifndef REALMD_CONFIG_VERSION # define REALMD_CONFIG_VERSION 2010062001 diff --git a/src/shared/Threading/Threading.cpp b/src/shared/Threading/Threading.cpp index b658f4f89..7e87a5edc 100644 --- a/src/shared/Threading/Threading.cpp +++ b/src/shared/Threading/Threading.cpp @@ -131,7 +131,7 @@ Thread::~Thread() } // initialize Thread's class static member -Thread::ThreadStorage Thread::m_ThreadStorage; +Thread::ThreadStorage *Thread::m_ThreadStorage = NULL; ThreadPriority Thread::m_TpEnum; bool Thread::start() @@ -142,6 +142,8 @@ bool Thread::start() // incRef before spawing the thread, otherwise Thread::ThreadTask() might call decRef and delete m_task m_task->incReference(); + m_ThreadStorage = new ACE_TSS(); + bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0); if (res) @@ -160,6 +162,8 @@ bool Thread::wait() m_iThreadId = 0; m_hThreadHandle = 0; + delete m_ThreadStorage; + m_ThreadStorage = NULL; return (_res == 0); } @@ -174,6 +178,8 @@ void Thread::destroy() m_iThreadId = 0; m_hThreadHandle = 0; + delete m_ThreadStorage; + m_ThreadStorage = NULL; // reference set at ACE_Thread::spawn m_task->decReference(); @@ -217,14 +223,14 @@ ACE_hthread_t Thread::currentHandle() Thread* Thread::current() { - Thread* _thread = m_ThreadStorage.ts_object(); + Thread* _thread = (*m_ThreadStorage).ts_object(); if (!_thread) { _thread = new Thread(); _thread->m_iThreadId = Thread::currentId(); _thread->m_hThreadHandle = Thread::currentHandle(); - Thread* _oldValue = m_ThreadStorage.ts_object(_thread); + Thread* _oldValue = (*m_ThreadStorage).ts_object(_thread); delete _oldValue; } diff --git a/src/shared/Threading/Threading.h b/src/shared/Threading/Threading.h index c6b3f0e9e..2b51b0261 100644 --- a/src/shared/Threading/Threading.h +++ b/src/shared/Threading/Threading.h @@ -226,7 +226,7 @@ namespace ACE_Based * */ typedef ACE_TSS ThreadStorage; - static ThreadStorage m_ThreadStorage; /**< global object - container for Thread class representation of every thread */ + static ThreadStorage *m_ThreadStorage; /**< global object - container for Thread class representation of every thread */ static ThreadPriority m_TpEnum; /**< use this object to determine current OS thread priority values mapped to enum Priority{} */ }; } diff --git a/src/shared/Utilities/ByteBuffer.cpp b/src/shared/Utilities/ByteBuffer.cpp index f3bdc412d..d9a3443d0 100644 --- a/src/shared/Utilities/ByteBuffer.cpp +++ b/src/shared/Utilities/ByteBuffer.cpp @@ -79,5 +79,5 @@ void BitStream::Print() for (uint32 i = 0; i < GetLength(); ++i) ss << uint32(GetBit(i)) << " "; - sLog.outDebug(ss.str().c_str()); + sLog.outDebug("%s", ss.str().c_str()); } diff --git a/src/shared/Utilities/ProgressBar.h b/src/shared/Utilities/ProgressBar.h index a295b7b52..e9249c3b0 100644 --- a/src/shared/Utilities/ProgressBar.h +++ b/src/shared/Utilities/ProgressBar.h @@ -41,7 +41,7 @@ class BarGoLink */ explicit BarGoLink(int row_count); explicit BarGoLink(uint32 row_count); // row_count < ACE_INT32_MAX - explicit BarGoLink(uint64 row_count); // row_count < ACE_INT32_MAX + explicit BarGoLink(uint64 row_count); // row_count < ACE_INT64_MAX /** * @brief * diff --git a/src/shared/Utilities/Util.cpp b/src/shared/Utilities/Util.cpp index 9128a216a..b28460e16 100644 --- a/src/shared/Utilities/Util.cpp +++ b/src/shared/Utilities/Util.cpp @@ -2,7 +2,7 @@ * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * - * Copyright (C) 2005-2016 MaNGOS project + * Copyright (C) 2005-2015 MaNGOS project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -422,17 +422,6 @@ bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr) return true; } -bool Utf8ToUpperOnlyLatin(std::string &utf8String) -{ - std::wstring wstr; - if (!Utf8toWStr(utf8String, wstr)) - return false; - - std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin); - - return WStrToUtf8(wstr, utf8String); -} - bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) { try diff --git a/src/shared/Utilities/Util.h b/src/shared/Utilities/Util.h index 42c8158ae..6891c9efd 100644 --- a/src/shared/Utilities/Util.h +++ b/src/shared/Utilities/Util.h @@ -2,7 +2,7 @@ * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * - * Copyright (C) 2005-2016 MaNGOS project + * Copyright (C) 2005-2015 MaNGOS project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -282,13 +282,7 @@ inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) { return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); } -/** -* @brief -* -* @param utf8String -* @return bool -*/ -bool Utf8ToUpperOnlyLatin(std::string &utf8String); + /** * @brief * diff --git a/src/shared/revision.h b/src/shared/revision.h index bba771168..51e536529 100644 --- a/src/shared/revision.h +++ b/src/shared/revision.h @@ -24,8 +24,20 @@ #ifndef MANGOS_H_REVISION #define MANGOS_H_REVISION -#define REVISION_NR "12778" -#define REVISION_DB_CHARACTERS "required_12712_01_characters_characters" -#define REVISION_DB_MANGOS "required_12752_01_mangos_reputation_spillover_template" -#define REVISION_DB_REALMD "required_20150722_01_realmcharacters_remove_constraint" + #define REVISION_NR "21000" + + #define REALMD_DB_VERSION_NR 21 + #define REALMD_DB_STRUCTURE_NR 1 + #define REALMD_DB_CONTENT_NR 2 + #define REALMD_DB_UPDATE_DESCRIPTION "dbdocs update" + + #define CHAR_DB_VERSION_NR 21 + #define CHAR_DB_STRUCTURE_NR 2 + #define CHAR_DB_CONTENT_NR 1 + #define CHAR_DB_UPDATE_DESCRIPTION "match_client_limits" + + #define WORLD_DB_VERSION_NR 21 + #define WORLD_DB_STRUCTURE_NR 1 + #define WORLD_DB_CONTENT_NR 0 + #define WORLD_DB_UPDATE_DESCRIPTION "revision_refactor" #endif // __REVISION_H__ diff --git a/src/tools/genrevision/genrevision.cpp b/src/tools/genrevision/genrevision.cpp index c75065e02..248d4ecc6 100644 --- a/src/tools/genrevision/genrevision.cpp +++ b/src/tools/genrevision/genrevision.cpp @@ -2,7 +2,7 @@ * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * - * Copyright (C) 2005-2015 MaNGOS project + * Copyright (C) 2005-2016 MaNGOS project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,90 +63,146 @@ void extractDataFromSvn(FILE* EntriesFile, bool url, RawData& data) { strcpy(data.rev_str, num_str); } } -void extractDataFromGit(FILE* EntriesFile, std::string path, bool url, RawData& data) +bool extractDataFromSvn(std::string filename, bool url, RawData& data) { - char buf[200]; + FILE* entriesFile = fopen(filename.c_str(), "r"); + if (!entriesFile) + { return false; } - char hash_str[200]; - char branch_str[200]; - char url_str[200]; + extractDataFromSvn(entriesFile, url, data); + fclose(entriesFile); + return true; +} - bool found = false; - while (fgets(buf, 200, EntriesFile)) +bool extractDataFromGit(std::string filename, std::string path, bool url, RawData& data) +{ + char buf[1024]; + + if (FILE* entriesFile = fopen(filename.c_str(), "r")) { - if (sscanf(buf, "%s\t\tbranch %s of %s", hash_str, branch_str, url_str) == 3) - { - found = true; - break; - } - } + char hash_str[200]; + char branch_str[200]; + char url_str[200]; - if (!found) - { - strcpy(data.rev_str, "*"); - strcpy(data.date_str, "*"); - strcpy(data.time_str, "*"); - return; - } - - if (url) - { - char* host_str = NULL; - char* acc_str = NULL; - char* repo_str = NULL; - - // parse URL like git@github.com:mangosthree/server - char url_buf[200]; - int res = sscanf(url_str, "git@%s", url_buf); - if (res) + bool found = false; + while (fgets(buf, 200, entriesFile)) { - host_str = strtok(url_buf, ":"); - acc_str = strtok(NULL, "/"); - repo_str = strtok(NULL, " "); - } - else - { - res = sscanf(url_str, "git://%s", url_buf); - if (res) + if (sscanf(buf, "%s\t\tbranch %s of %s", hash_str, branch_str, url_str) == 3) { - host_str = strtok(url_buf, "/"); - acc_str = strtok(NULL, "/"); - repo_str = strtok(NULL, "."); + found = true; + break; } } - // can generate nice link - if (res) - { sprintf(data.rev_str, "http://%s/%s/%s/commit/%s", host_str, acc_str, repo_str, hash_str); } - // unknonw URL format, use as-is + fclose(entriesFile); + + if (!found) + { + strcpy(data.rev_str, "*"); + strcpy(data.date_str, "*"); + strcpy(data.time_str, "*"); + return false; + } + + if (url) + { + char* host_str = NULL; + char* acc_str = NULL; + char* repo_str = NULL; + + // parse URL like git@github.com:mangosthree/server + char url_buf[200]; + int res = sscanf(url_str, "git@%s", url_buf); + if (res) + { + host_str = strtok(url_buf, ":"); + acc_str = strtok(NULL, "/"); + repo_str = strtok(NULL, " "); + } + else + { + res = sscanf(url_str, "git://%s", url_buf); + if (res) + { + host_str = strtok(url_buf, "/"); + acc_str = strtok(NULL, "/"); + repo_str = strtok(NULL, "."); + } + } + + // can generate nice link + if (res) + { sprintf(data.rev_str, "http://%s/%s/%s/commit/%s", host_str, acc_str, repo_str, hash_str); } + // unknonw URL format, use as-is + else + { sprintf(data.rev_str, "%s at %s", hash_str, url_str); } + } else - { sprintf(data.rev_str, "%s at %s", hash_str, url_str); } + { strcpy(data.rev_str, hash_str); } + } + else if (entriesFile = fopen((path + ".git/HEAD").c_str(), "r")) + { + if (!fgets(buf, sizeof(buf), entriesFile)) + { + fclose(entriesFile); + return false; + } + + char refBuff[200]; + if (!sscanf(buf, "ref: %s", refBuff)) + { + fclose(entriesFile); + return false; + } + + fclose(entriesFile); + + if (FILE *refFile = fopen((path + ".git/" + refBuff).c_str(), "r")) + { + char hash[41]; + + if (!fgets(hash, sizeof(hash), refFile)) + { + fclose(refFile); + return false; + } + + strcpy(data.rev_str, hash); + + fclose(refFile); + } + else + { return false; } } else - { strcpy(data.rev_str, hash_str); } + return false; time_t rev_time = 0; // extracting date/time - FILE* LogFile = fopen((path + ".git/logs/HEAD").c_str(), "r"); - if (LogFile) + if (FILE* logFile = fopen((path + ".git/logs/HEAD").c_str(), "r")) { - while (fgets(buf, 200, LogFile)) + while (fgets(buf, sizeof(buf), logFile)) { - char buf2[200]; - char new_hash[200]; - int unix_time = 0; - int res2 = sscanf(buf, "%s %s %s %s %i", buf2, new_hash, buf2, buf2, &unix_time); - if (res2 != 5) - { continue; } + char *hash = strchr(buf, ' ') + 1; + char *time = strchr(hash, ' '); + *(time++) = '\0'; - if (strcmp(hash_str, new_hash)) - { continue; } + if (!strcmp(data.rev_str, hash)) + { + char *tab = strchr(time, '\t'); + *tab = '\0'; - rev_time = unix_time; - break; + tab = strrchr(time, ' '); + *tab = '\0'; + + time = strrchr(time, ' ') + 1; + rev_time = atoi(time); + + break; + } } - fclose(LogFile); + fclose(logFile); if (rev_time) { @@ -171,31 +227,11 @@ void extractDataFromGit(FILE* EntriesFile, std::string path, bool url, RawData& strcpy(data.date_str, "*"); strcpy(data.time_str, "*"); } -} -bool extractDataFromSvn(std::string filename, bool url, RawData& data) -{ - FILE* EntriesFile = fopen(filename.c_str(), "r"); - if (!EntriesFile) - { return false; } - - extractDataFromSvn(EntriesFile, url, data); - fclose(EntriesFile); return true; } -bool extractDataFromGit(std::string filename, std::string path, bool url, RawData& data) -{ - FILE* EntriesFile = fopen(filename.c_str(), "r"); - if (!EntriesFile) - { return false; } - - extractDataFromGit(EntriesFile, path, url, data); - fclose(EntriesFile); - return true; -} - -std::string generateHeader(char const* rev_str, char const* date_str, char const* time_str) +std::string generateHeader(char const* rev_str, char const* date_str, char const* time_str, char const *ver_str) { std::ostringstream newData; newData << "#ifndef __REVISION_H__" << std::endl; @@ -203,6 +239,7 @@ std::string generateHeader(char const* rev_str, char const* date_str, char const newData << " #define REVISION_ID \"" << rev_str << "\"" << std::endl; newData << " #define REVISION_DATE \"" << date_str << "\"" << std::endl; newData << " #define REVISION_TIME \"" << time_str << "\"" << std::endl; + newData << " #define VERSION \"" << ver_str << "\"" << std::endl; newData << "#endif // __REVISION_H__" << std::endl; return newData.str(); } @@ -218,7 +255,7 @@ int main(int argc, char** argv) // -g use git prefered (default) // -s use svn prefered // -r use only revision (without repo URL) (default) - // -u include repositire URL as commit URL or "rev at URL" + // -u include repository URL as commit URL or "rev at URL" // -o write header to specified target file for (int k = 1; k <= argc; ++k) { @@ -260,6 +297,18 @@ int main(int argc, char** argv) } /// new data extraction + char version[200]; + if (FILE *versionFile = fopen((path + "/version.txt").c_str(), "r")) + { + if (!fgets(version, sizeof(version), versionFile)) + { + fclose(versionFile); + return 1; + } + + fclose(versionFile); + } + std::string newData; { @@ -289,34 +338,34 @@ int main(int argc, char** argv) } if (res) - { newData = generateHeader(data.rev_str, data.date_str, data.time_str); } + { newData = generateHeader(data.rev_str, data.date_str, data.time_str, version); } else - { newData = generateHeader("*", "*", "*"); } + { newData = generateHeader("*", "*", "*", "0.0"); } } /// get existed header data for compare std::string oldData; - if (FILE* HeaderFile = fopen(outfile.c_str(), "rb")) + if (FILE* headerFile = fopen(outfile.c_str(), "rb")) { - while (!feof(HeaderFile)) + while (!feof(headerFile)) { - int c = fgetc(HeaderFile); + int c = fgetc(headerFile); if (c < 0) { break; } oldData += (char)c; } - fclose(HeaderFile); + fclose(headerFile); } /// update header only if different data if (newData != oldData) { - if (FILE* OutputFile = fopen(outfile.c_str(), "wb")) + if (FILE* outputFile = fopen(outfile.c_str(), "w")) { - fprintf(OutputFile, "%s", newData.c_str()); - fclose(OutputFile); + fprintf(outputFile, "%s", newData.c_str()); + fclose(outputFile); } else { return 1; }