diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake
index 4dad4cb7820..261a55b285f 100644
--- a/cmake/compiler/clang/settings.cmake
+++ b/cmake/compiler/clang/settings.cmake
@@ -1,5 +1,5 @@
# Set build-directive (used in core to tell which buildtype we used)
-add_definitions(-D_BUILD_DIRECTIVE='"$(CONFIGURATION)"')
+add_definitions(-D_BUILD_DIRECTIVE='"${CMAKE_BUILD_TYPE}"')
if(WITH_WARNINGS)
set(WARNING_FLAGS "-W -Wall -Wextra -Winit-self -Wfatal-errors -Wno-mismatched-tags")
diff --git a/cmake/macros/FindPCHSupport.cmake b/cmake/macros/FindPCHSupport.cmake
index b068b69c26b..49d4be904d1 100644
--- a/cmake/macros/FindPCHSupport.cmake
+++ b/cmake/macros/FindPCHSupport.cmake
@@ -11,7 +11,7 @@ FUNCTION(GET_COMMON_PCH_PARAMS PCH_HEADER PCH_FE INCLUDE_PREFIX)
SET(INCLUDE_FLAGS ${INCLUDE_FLAGS_LIST} PARENT_SCOPE)
ENDFUNCTION(GET_COMMON_PCH_PARAMS)
-FUNCTION(GENERATE_CXX_PCH_COMMAND TARGET_NAME INCLUDE_FLAGS IN PCH_SRC OUT)
+FUNCTION(GENERATE_CXX_PCH_COMMAND TARGET_NAME_LIST INCLUDE_FLAGS IN PCH_SRC OUT)
IF (CMAKE_BUILD_TYPE)
STRING(TOUPPER _${CMAKE_BUILD_TYPE} CURRENT_BUILD_TYPE)
ENDIF ()
@@ -55,50 +55,69 @@ FUNCTION(GENERATE_CXX_PCH_COMMAND TARGET_NAME INCLUDE_FLAGS IN PCH_SRC OUT)
DEPENDS ${OUT}
)
- ADD_DEPENDENCIES(${TARGET_NAME} generate_${PCH_SRC_N})
+ FOREACH(TARGET_NAME ${TARGET_NAME_LIST})
+ ADD_DEPENDENCIES(${TARGET_NAME} generate_${PCH_SRC_N})
+ ENDFOREACH()
+
ENDFUNCTION(GENERATE_CXX_PCH_COMMAND)
-FUNCTION(ADD_CXX_PCH_GCC TARGET_NAME PCH_HEADER PCH_SOURCE)
+FUNCTION(ADD_CXX_PCH_GCC TARGET_NAME_LIST PCH_HEADER PCH_SOURCE)
GET_COMMON_PCH_PARAMS(${PCH_HEADER} "gch" "-I")
- GENERATE_CXX_PCH_COMMAND(${TARGET_NAME} "${INCLUDE_FLAGS}" ${PCH_HEADER} ${PCH_SOURCE} ${PCH_HEADER_OUT})
- SET_TARGET_PROPERTIES(
- ${TARGET_NAME} PROPERTIES
- COMPILE_FLAGS "-include ${CMAKE_CURRENT_BINARY_DIR}/${PCH_HEADER_NAME}"
- )
+ GENERATE_CXX_PCH_COMMAND("${TARGET_NAME_LIST}" "${INCLUDE_FLAGS}" ${PCH_HEADER} ${PCH_SOURCE} ${PCH_HEADER_OUT})
+
+ FOREACH(TARGET_NAME ${TARGET_NAME_LIST})
+ SET_TARGET_PROPERTIES(
+ ${TARGET_NAME} PROPERTIES
+ COMPILE_FLAGS "-include ${CMAKE_CURRENT_BINARY_DIR}/${PCH_HEADER_NAME}"
+ )
+ ENDFOREACH()
ENDFUNCTION(ADD_CXX_PCH_GCC)
-FUNCTION(ADD_CXX_PCH_CLANG TARGET_NAME PCH_HEADER PCH_SOURCE)
+FUNCTION(ADD_CXX_PCH_CLANG TARGET_NAME_LIST PCH_HEADER PCH_SOURCE)
GET_COMMON_PCH_PARAMS(${PCH_HEADER} "pch" "-I")
- GENERATE_CXX_PCH_COMMAND(${TARGET_NAME} "${INCLUDE_FLAGS}" ${PCH_HEADER} ${PCH_SOURCE} ${PCH_HEADER_OUT})
- SET_TARGET_PROPERTIES(
- ${TARGET_NAME} PROPERTIES
- COMPILE_FLAGS "-include-pch ${PCH_HEADER_OUT}"
- )
+ GENERATE_CXX_PCH_COMMAND("${TARGET_NAME_LIST}" "${INCLUDE_FLAGS}" ${PCH_HEADER} ${PCH_SOURCE} ${PCH_HEADER_OUT})
+
+ FOREACH(TARGET_NAME ${TARGET_NAME_LIST})
+ SET_TARGET_PROPERTIES(
+ ${TARGET_NAME} PROPERTIES
+ COMPILE_FLAGS "-include-pch ${PCH_HEADER_OUT}"
+ )
+ ENDFOREACH()
ENDFUNCTION(ADD_CXX_PCH_CLANG)
-FUNCTION(ADD_CXX_PCH_MSVC TARGET_NAME PCH_HEADER PCH_SOURCE)
+FUNCTION(ADD_CXX_PCH_MSVC TARGET_NAME_LIST PCH_HEADER PCH_SOURCE)
GET_COMMON_PCH_PARAMS(${PCH_HEADER} "pch" "/I")
- SET_TARGET_PROPERTIES(
- ${TARGET_NAME} PROPERTIES
- COMPILE_FLAGS "/FI${PCH_HEADER_NAME} /Yu${PCH_HEADER_NAME}"
- )
+
+ FOREACH(TARGET_NAME ${TARGET_NAME_LIST})
+ SET_TARGET_PROPERTIES(
+ ${TARGET_NAME} PROPERTIES
+ COMPILE_FLAGS "/FI${PCH_HEADER_NAME} /Yu${PCH_HEADER_NAME}"
+ )
+ ENDFOREACH()
+
SET_SOURCE_FILES_PROPERTIES(
${PCH_SOURCE} PROPERTIES
COMPILE_FLAGS "/Yc${PCH_HEADER_NAME}"
)
ENDFUNCTION(ADD_CXX_PCH_MSVC)
-FUNCTION(ADD_CXX_PCH TARGET_NAME PCH_HEADER PCH_SOURCE)
- IF (MSVC)
- ADD_CXX_PCH_MSVC(${TARGET_NAME} ${PCH_HEADER} ${PCH_SOURCE})
- ELSEIF ("${CMAKE_GENERATOR}" MATCHES "Xcode")
- SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+FUNCTION(ADD_CXX_PCH_XCODE TARGET_NAME_LIST PCH_HEADER PCH_SOURCE)
+ FOREACH(TARGET_NAME ${TARGET_NAME_LIST})
+ SET_TARGET_PROPERTIES("${TARGET_NAME}" PROPERTIES
XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER YES
XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/${PCH_HEADER}"
)
+ ENDFOREACH()
+ENDFUNCTION(ADD_CXX_PCH_XCODE)
+
+FUNCTION(ADD_CXX_PCH TARGET_NAME_LIST PCH_HEADER PCH_SOURCE)
+ IF (MSVC)
+ ADD_CXX_PCH_MSVC("${TARGET_NAME_LIST}" ${PCH_HEADER} ${PCH_SOURCE})
+ ELSEIF ("${CMAKE_GENERATOR}" MATCHES "Xcode")
+ ADD_CXX_PCH_XCODE("${TARGET_NAME_LIST}" ${PCH_HEADER} ${PCH_SOURCE})
ELSEIF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- ADD_CXX_PCH_CLANG(${TARGET_NAME} ${PCH_HEADER} ${PCH_SOURCE})
+ ADD_CXX_PCH_CLANG("${TARGET_NAME_LIST}" ${PCH_HEADER} ${PCH_SOURCE})
ELSEIF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
- ADD_CXX_PCH_GCC(${TARGET_NAME} ${PCH_HEADER} ${PCH_SOURCE})
+ ADD_CXX_PCH_GCC("${TARGET_NAME_LIST}" ${PCH_HEADER} ${PCH_SOURCE})
ENDIF ()
ENDFUNCTION(ADD_CXX_PCH)
diff --git a/contrib/extractor.bat b/contrib/extractor.bat
new file mode 100644
index 00000000000..eb7c99e5c0b
--- /dev/null
+++ b/contrib/extractor.bat
@@ -0,0 +1,51 @@
+@ECHO OFF
+CLS
+:MENU
+ECHO.
+ECHO ...............................................
+ECHO Trinitycore dbc/db2, maps, vmaps, mmaps extractor
+ECHO ...............................................
+ECHO PRESS 1, 2, 3 OR 4 to select your task, or 5 to EXIT.
+ECHO ...............................................
+ECHO.
+ECHO 1 - Extract dbc/db2 and maps
+ECHO 2 - Extract vmaps (needs maps to be extracted before you run this)
+ECHO 3 - Extract mmaps (needs vmaps to be extracted before you run this, may take hours)
+ECHO 4 - Extract all (may take hours)
+ECHO 5 - EXIT
+ECHO.
+SET /P M=Type 1, 2, 3, 4 or 5 then press ENTER:
+IF %M%==1 GOTO MAPS
+IF %M%==2 GOTO VMAPS
+IF %M%==3 GOTO MMAPS
+IF %M%==4 GOTO ALL
+IF %M%==5 GOTO EOF
+:MAPS
+start mapextractor.exe
+pause
+GOTO MENU
+:VMAPS
+start vmap4extractor.exe
+md vmaps
+start vmap4assembler.exe Buildings vmaps
+pause
+GOTO MENU
+:MMAPS
+md mmaps
+start mmaps_generator.exe
+pause
+GOTO MENU
+:ALL
+start mapextractor.exe
+ECHO wait before mapextractor.exe closes before continue
+pause
+start vmap4extractor.exe
+md vmaps
+start vmap4assembler.exe Buildings vmaps
+rmdir Buildings /s /q
+ECHO wait before vmap4assembler.exe closes before continue
+pause
+md mmaps
+start mmaps_generator.exe
+pause
+GOTO MENU
diff --git a/revision_data.h.in.cmake b/revision_data.h.in.cmake
index 2ac7e436566..1b861ddecb6 100644
--- a/revision_data.h.in.cmake
+++ b/revision_data.h.in.cmake
@@ -3,7 +3,9 @@
#define _HASH "@rev_hash@"
#define _DATE "@rev_date@"
#define _BRANCH "@rev_branch@"
+ #define _CMAKE_COMMAND "@CMAKE_COMMAND@"
#define _SOURCE_DIRECTORY "@CMAKE_SOURCE_DIR@"
+ #define _BUILD_DIRECTORY "@BUILDDIR@"
#define _MYSQL_EXECUTABLE "@MYSQL_EXECUTABLE@"
#define _FULL_DATABASE "TDB_full_434.10_2015_07_28.sql"
#define VER_COMPANYNAME_STR "TrinityCore Developers"
@@ -12,6 +14,4 @@
#define VER_FILEVERSION_STR "@rev_hash@ @rev_date@ (@rev_branch@ branch)"
#define VER_PRODUCTVERSION VER_FILEVERSION
#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR
- #define COMPILER_C_FLAGS "@CMAKE_C_FLAGS@"
- #define COMPILER_CXX_FLAGS "@CMAKE_CXX_FLAGS@"
#endif // __REVISION_DATA_H__
diff --git a/src/common/Configuration/BuiltInConfig.cpp b/src/common/Configuration/BuiltInConfig.cpp
new file mode 100644
index 00000000000..c2fc3b91766
--- /dev/null
+++ b/src/common/Configuration/BuiltInConfig.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#include "BuiltInConfig.h"
+#include "Config.h"
+#include "GitRevision.h"
+
+template
+static std::string GetStringWithDefaultValueFromFunction(
+ std::string const& key, Fn getter)
+{
+ std::string const value = sConfigMgr->GetStringDefault(key, "");
+ return value.empty() ? getter() : value;
+}
+
+std::string BuiltInConfig::GetCMakeCommand()
+{
+ return GetStringWithDefaultValueFromFunction(
+ "CMakeCommand", GitRevision::GetCMakeCommand);
+}
+
+std::string BuiltInConfig::GetBuildDirectory()
+{
+ return GetStringWithDefaultValueFromFunction(
+ "BuildDirectory", GitRevision::GetBuildDirectory);
+}
+
+std::string BuiltInConfig::GetSourceDirectory()
+{
+ return GetStringWithDefaultValueFromFunction(
+ "SourceDirectory", GitRevision::GetSourceDirectory);
+}
+
+std::string BuiltInConfig::GetMySQLExecutable()
+{
+ return GetStringWithDefaultValueFromFunction(
+ "MySQLExecutable", GitRevision::GetMySQLExecutable);
+}
diff --git a/src/common/Configuration/BuiltInConfig.h b/src/common/Configuration/BuiltInConfig.h
new file mode 100644
index 00000000000..4ae4ed40189
--- /dev/null
+++ b/src/common/Configuration/BuiltInConfig.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#ifndef BUILT_IN_CONFIG_H
+#define BUILT_IN_CONFIG_H
+
+#include
+
+/// Provides helper functions to access built-in values
+/// which can be overwritten in config
+namespace BuiltInConfig
+{
+ /// Returns the CMake command when any is specified in the config,
+ /// returns the built-in path otherwise
+ std::string GetCMakeCommand();
+ /// Returns the build directory path when any is specified in the config,
+ /// returns the built-in one otherwise
+ std::string GetBuildDirectory();
+ /// Returns the source directory path when any is specified in the config,
+ /// returns the built-in one otherwise
+ std::string GetSourceDirectory();
+ /// Returns the path to the mysql executable (`mysql`) when any is specified
+ /// in the config, returns the built-in one otherwise
+ std::string GetMySQLExecutable();
+
+} // namespace BuiltInConfig
+
+#endif // BUILT_IN_CONFIG_H
diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp
index 6ac04615315..5db333c8aff 100644
--- a/src/common/Configuration/Config.cpp
+++ b/src/common/Configuration/Config.cpp
@@ -61,7 +61,7 @@ bool ConfigMgr::Reload(std::string& error)
return LoadInitial(_filename, error);
}
-std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def)
+std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def) const
{
std::string value = _config.get(ptree::path_type(name, '/'), def);
@@ -70,7 +70,7 @@ std::string ConfigMgr::GetStringDefault(std::string const& name, const std::stri
return value;
}
-bool ConfigMgr::GetBoolDefault(std::string const& name, bool def)
+bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) const
{
try
{
@@ -84,12 +84,12 @@ bool ConfigMgr::GetBoolDefault(std::string const& name, bool def)
}
}
-int ConfigMgr::GetIntDefault(std::string const& name, int def)
+int ConfigMgr::GetIntDefault(std::string const& name, int def) const
{
return _config.get(ptree::path_type(name, '/'), def);
}
-float ConfigMgr::GetFloatDefault(std::string const& name, float def)
+float ConfigMgr::GetFloatDefault(std::string const& name, float def) const
{
return _config.get(ptree::path_type(name, '/'), def);
}
diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h
index 5b04212ed7c..ada910d8fcc 100644
--- a/src/common/Configuration/Config.h
+++ b/src/common/Configuration/Config.h
@@ -41,10 +41,10 @@ public:
bool Reload(std::string& error);
- std::string GetStringDefault(std::string const& name, const std::string& def);
- bool GetBoolDefault(std::string const& name, bool def);
- int GetIntDefault(std::string const& name, int def);
- float GetFloatDefault(std::string const& name, float def);
+ std::string GetStringDefault(std::string const& name, const std::string& def) const;
+ bool GetBoolDefault(std::string const& name, bool def) const;
+ int GetIntDefault(std::string const& name, int def) const;
+ float GetFloatDefault(std::string const& name, float def) const;
std::string const& GetFilename();
std::list GetKeysByString(std::string const& name);
diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp
index d0719c09959..5343fbd6531 100644
--- a/src/common/GitRevision.cpp
+++ b/src/common/GitRevision.cpp
@@ -17,6 +17,16 @@ char const* GitRevision::GetBranch()
return _BRANCH;
}
+char const* GitRevision::GetCMakeCommand()
+{
+ return _CMAKE_COMMAND;
+}
+
+char const* GitRevision::GetBuildDirectory()
+{
+ return _BUILD_DIRECTORY;
+}
+
char const* GitRevision::GetSourceDirectory()
{
return _SOURCE_DIRECTORY;
@@ -66,13 +76,3 @@ char const* GitRevision::GetProductVersionStr()
{
return VER_PRODUCTVERSION_STR;
}
-
-char const* GitRevision::GetCompilerCFlags()
-{
- return COMPILER_C_FLAGS;
-}
-
-char const* GitRevision::GetCompilerCXXFlags()
-{
- return COMPILER_CXX_FLAGS;
-}
diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h
index 8d2764ba861..7fddcb7605a 100644
--- a/src/common/GitRevision.h
+++ b/src/common/GitRevision.h
@@ -25,6 +25,8 @@ namespace GitRevision
char const* GetHash();
char const* GetDate();
char const* GetBranch();
+ char const* GetCMakeCommand();
+ char const* GetBuildDirectory();
char const* GetSourceDirectory();
char const* GetMySQLExecutable();
char const* GetFullDatabase();
@@ -33,8 +35,6 @@ namespace GitRevision
char const* GetLegalCopyrightStr();
char const* GetFileVersionStr();
char const* GetProductVersionStr();
- char const* GetCompilerCFlags();
- char const* GetCompilerCXXFlags();
}
#endif
diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp
index 4bd0487343d..a80a4671822 100644
--- a/src/common/Logging/Log.cpp
+++ b/src/common/Logging/Log.cpp
@@ -214,13 +214,13 @@ void Log::ReadLoggersFromConfig()
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs());
appenders[appender->getId()] = appender;
- Logger& logger = loggers[LOGGER_ROOT];
- logger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR);
- logger.addAppender(appender->getId(), appender);
+ Logger& rootLogger = loggers[LOGGER_ROOT];
+ rootLogger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR);
+ rootLogger.addAppender(appender->getId(), appender);
- logger = loggers["server"];
- logger.Create("server", LOG_LEVEL_ERROR);
- logger.addAppender(appender->getId(), appender);
+ Logger& serverLogger = loggers["server"];
+ serverLogger.Create("server", LOG_LEVEL_INFO);
+ serverLogger.addAppender(appender->getId(), appender);
}
}
diff --git a/src/common/Utilities/Random.cpp b/src/common/Utilities/Random.cpp
index cc013110b01..31318e8f52d 100644
--- a/src/common/Utilities/Random.cpp
+++ b/src/common/Utilities/Random.cpp
@@ -61,6 +61,14 @@ float frand(float min, float max)
return float(GetRng()->Random() * (max - min) + min);
}
+Milliseconds randtime(Milliseconds const& min, Milliseconds const& max)
+{
+ long long diff = max.count() - min.count();
+ ASSERT(diff >= 0);
+ ASSERT(diff <= (uint32)-1);
+ return min + Milliseconds(urand(0, diff));
+}
+
uint32 rand32()
{
return GetRng()->BRandom();
diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h
index 5610651a83b..5dea6117f97 100644
--- a/src/common/Utilities/Random.h
+++ b/src/common/Utilities/Random.h
@@ -19,6 +19,7 @@
#define Random_h__
#include "Define.h"
+#include "Duration.h"
#include
#include
@@ -34,6 +35,9 @@ uint32 urandms(uint32 min, uint32 max);
/* Return a random number in the range 0 .. UINT32_MAX. */
uint32 rand32();
+/* Return a random time in the range min..max (up to millisecond precision). Only works for values where millisecond difference is a valid uint32. */
+Milliseconds randtime(Milliseconds const& min, Milliseconds const& max);
+
/* Return a random number in the range min..max */
float frand(float min, float max);
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt
index a427f9c238f..891d529df72 100644
--- a/src/server/CMakeLists.txt
+++ b/src/server/CMakeLists.txt
@@ -25,8 +25,8 @@ set(sources_windows_Debugging
add_subdirectory(database)
add_subdirectory(shared)
add_subdirectory(game)
+add_subdirectory(ipc)
add_subdirectory(authserver)
- add_subdirectory(ipc)
- add_subdirectory(bnetserver)
+add_subdirectory(bnetserver)
add_subdirectory(scripts)
add_subdirectory(worldserver)
diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt
index c11deec39bb..34e7ed8a43f 100644
--- a/src/server/authserver/CMakeLists.txt
+++ b/src/server/authserver/CMakeLists.txt
@@ -57,6 +57,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/database
${CMAKE_SOURCE_DIR}/src/server/database/Database
${CMAKE_SOURCE_DIR}/src/server/database/Logging
+ ${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
${CMAKE_SOURCE_DIR}/src/server/shared/Service
@@ -79,10 +80,10 @@ if( NOT WIN32 )
endif()
target_link_libraries(authserver
- common
shared
- format
database
+ common
+ format
${MYSQL_LIBRARY}
${OPENSSL_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index 0618ec437b6..939d15ceca8 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -134,7 +134,7 @@ int main(int argc, char** argv)
// Get the list of realms for the server
sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
- if (sRealmList->size() == 0)
+ if (sRealmList->GetRealms().empty())
{
TC_LOG_ERROR("server.authserver", "No valid realms specified.");
StopDB();
@@ -194,6 +194,8 @@ int main(int argc, char** argv)
sAuthSocketMgr.StopNetwork();
+ sRealmList->Close();
+
// Close the Database Pool and library
StopDB();
diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp
index 081610f2af9..8cd87bd7930 100644
--- a/src/server/authserver/Realms/RealmList.cpp
+++ b/src/server/authserver/Realms/RealmList.cpp
@@ -16,104 +16,62 @@
* with this program. If not, see .
*/
-#include
#include "Common.h"
-#include "RealmList.h"
#include "Database/DatabaseEnv.h"
-#include "Util.h"
+#include "RealmList.h"
+#include
-ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const
-{
- ip::address realmIp;
-
- // Attempt to send best address for client
- if (clientAddr.is_loopback())
- {
- // Try guessing if realm is also connected locally
- if (LocalAddress.is_loopback() || ExternalAddress.is_loopback())
- realmIp = clientAddr;
- else
- {
- // Assume that user connecting from the machine that authserver is located on
- // has all realms available in his local network
- realmIp = LocalAddress;
- }
- }
- else
- {
- if (clientAddr.is_v4() &&
- (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) ==
- (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()))
- {
- realmIp = LocalAddress;
- }
- else
- realmIp = ExternalAddress;
- }
-
- ip::tcp::endpoint endpoint(realmIp, port);
-
- // Return external IP
- return endpoint;
-}
-
-RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)), _resolver(nullptr)
-{
-}
+namespace boost { namespace asio { namespace ip { class address; } } }
+RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) { }
RealmList::~RealmList()
{
delete _resolver;
+ delete _updateTimer;
}
// Load the realm list from the database
void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval)
{
+ _updateInterval = updateInterval;
+ _updateTimer = new boost::asio::deadline_timer(ioService);
_resolver = new boost::asio::ip::tcp::resolver(ioService);
- m_UpdateInterval = updateInterval;
// Get the content of the realmlist table in the database
- UpdateRealms(true);
+ UpdateRealms(true, boost::system::error_code());
}
-void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr,
- ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build)
+void RealmList::Close()
+{
+ _updateTimer->cancel();
+}
+
+void RealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
+ ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel,
+ float population)
{
// Create new if not exist or update existed
- Realm& realm = m_realms[name];
-
- realm.m_ID = id;
- realm.name = name;
- realm.icon = icon;
- realm.flag = flag;
- realm.timezone = timezone;
- realm.allowedSecurityLevel = allowedSecurityLevel;
- realm.populationLevel = population;
+ Realm& realm = _realms[id];
+ realm.Id = id;
+ realm.Build = build;
+ realm.Name = name;
+ realm.Type = icon;
+ realm.Flags = flag;
+ realm.Timezone = timezone;
+ realm.AllowedSecurityLevel = allowedSecurityLevel;
+ realm.PopulationLevel = population;
realm.ExternalAddress = address;
realm.LocalAddress = localAddr;
realm.LocalSubnetMask = localSubmask;
- realm.port = port;
- realm.gamebuild = build;
+ realm.Port = port;
}
-void RealmList::UpdateIfNeed()
+void RealmList::UpdateRealms(bool init, boost::system::error_code const& error)
{
- // maybe disabled or updated recently
- if (!m_UpdateInterval || m_NextUpdateTime > time(NULL))
+ if (error)
return;
- m_NextUpdateTime = time(NULL) + m_UpdateInterval;
-
- // Clears Realm list
- m_realms.clear();
-
- // Get the content of the realmlist table in the database
- UpdateRealms();
-}
-
-void RealmList::UpdateRealms(bool init)
-{
TC_LOG_INFO("server.authserver", "Updating Realm List...");
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
@@ -165,17 +123,25 @@ void RealmList::UpdateRealms(bool init)
uint16 port = fields[5].GetUInt16();
uint8 icon = fields[6].GetUInt8();
+ if (icon == REALM_TYPE_FFA_PVP)
+ icon = REALM_TYPE_PVP;
+ if (icon >= MAX_CLIENT_REALM_TYPE)
+ icon = REALM_TYPE_NORMAL;
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
uint8 timezone = fields[8].GetUInt8();
uint8 allowedSecurityLevel = fields[9].GetUInt8();
float pop = fields[10].GetFloat();
uint32 build = fields[11].GetUInt32();
+ uint8 region = fields[12].GetUInt8();
+ uint8 battlegroup = fields[13].GetUInt8();
- UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone,
- (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
+ Battlenet::RealmHandle id{ region, battlegroup, realmId };
+
+ UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag,
+ timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
if (init)
- TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port);
+ TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port);
}
catch (std::exception& ex)
{
@@ -185,4 +151,19 @@ void RealmList::UpdateRealms(bool init)
}
while (result->NextRow());
}
+
+ if (_updateInterval)
+ {
+ _updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
+ _updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, false, std::placeholders::_1));
+ }
+}
+
+Realm const* RealmList::GetRealm(Battlenet::RealmHandle const& id) const
+{
+ auto itr = _realms.find(id);
+ if (itr != _realms.end())
+ return &itr->second;
+
+ return NULL;
}
diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h
index 08735317714..e366a104644 100644
--- a/src/server/authserver/Realms/RealmList.h
+++ b/src/server/authserver/Realms/RealmList.h
@@ -19,50 +19,20 @@
#ifndef _REALMLIST_H
#define _REALMLIST_H
+#include "Common.h"
+#include "Realm/Realm.h"
#include
#include
#include
-#include "Common.h"
+#include
using namespace boost::asio;
-enum RealmFlags
-{
- REALM_FLAG_NONE = 0x00,
- REALM_FLAG_INVALID = 0x01,
- REALM_FLAG_OFFLINE = 0x02,
- REALM_FLAG_SPECIFYBUILD = 0x04,
- REALM_FLAG_UNK1 = 0x08,
- REALM_FLAG_UNK2 = 0x10,
- REALM_FLAG_RECOMMENDED = 0x20,
- REALM_FLAG_NEW = 0x40,
- REALM_FLAG_FULL = 0x80
-};
-
-// Storage object for a realm
-struct Realm
-{
- ip::address ExternalAddress;
- ip::address LocalAddress;
- ip::address LocalSubnetMask;
- uint16 port;
- std::string name;
- uint8 icon;
- RealmFlags flag;
- uint8 timezone;
- uint32 m_ID;
- AccountTypes allowedSecurityLevel;
- float populationLevel;
- uint32 gamebuild;
-
- ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
-};
-
/// Storage object for the list of realms on the server
class RealmList
{
public:
- typedef std::map RealmMap;
+ typedef std::map RealmMap;
static RealmList* instance()
{
@@ -73,25 +43,21 @@ public:
~RealmList();
void Initialize(boost::asio::io_service& ioService, uint32 updateInterval);
+ void Close();
- void UpdateIfNeed();
-
- void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; }
-
- RealmMap::const_iterator begin() const { return m_realms.begin(); }
- RealmMap::const_iterator end() const { return m_realms.end(); }
- uint32 size() const { return m_realms.size(); }
+ RealmMap const& GetRealms() const { return _realms; }
+ Realm const* GetRealm(Battlenet::RealmHandle const& id) const;
private:
RealmList();
- void UpdateRealms(bool init = false);
- void UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr,
- ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build);
+ void UpdateRealms(bool init, boost::system::error_code const& error);
+ void UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
+ ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
- RealmMap m_realms;
- uint32 m_UpdateInterval;
- time_t m_NextUpdateTime;
+ RealmMap _realms;
+ uint32 _updateInterval;
+ boost::asio::deadline_timer* _updateTimer;
boost::asio::ip::tcp::resolver* _resolver;
};
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index b909694c878..9097e09258e 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -571,6 +571,8 @@ bool AuthSession::HandleLogonProof()
TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str());
// Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
+ // No SQL injection (escaped user name) and IP address as received by socket
+
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
stmt->setString(0, K.AsHexStr());
stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
@@ -842,22 +844,19 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
} while (result->NextRow());
}
- // Update realm list if need
- sRealmList->UpdateIfNeed();
-
// Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
ByteBuffer pkt;
size_t RealmListSize = 0;
- for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
+ for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms())
{
- const Realm &realm = i->second;
+ const Realm &realm = i.second;
// don't work with realms which not compatible with the client
- bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.gamebuild));
+ bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.Build == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.Build));
// No SQL injection. id of realm is controlled by the database.
- uint32 flag = realm.flag;
- RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild);
+ uint32 flag = realm.Flags;
+ RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.Build);
if (!okBuild)
{
if (!buildInfo)
@@ -869,7 +868,7 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
if (!buildInfo)
flag &= ~REALM_FLAG_SPECIFYBUILD;
- std::string name = i->first;
+ std::string name = realm.Name;
if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
{
std::ostringstream ss;
@@ -877,19 +876,19 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
name = ss.str();
}
- uint8 lock = (realm.allowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
+ uint8 lock = (realm.AllowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
- pkt << uint8(realm.icon); // realm type
+ pkt << uint8(realm.Type); // realm type
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
pkt << uint8(lock); // if 1, then realm locked
pkt << uint8(flag); // RealmFlags
pkt << name;
pkt << boost::lexical_cast(realm.GetAddressForClient(GetRemoteIpAddress()));
- pkt << float(realm.populationLevel);
- pkt << uint8(characterCounts[realm.m_ID]);
- pkt << uint8(realm.timezone); // realm category
+ pkt << float(realm.PopulationLevel);
+ pkt << uint8(characterCounts[realm.Id.Realm]);
+ pkt << uint8(realm.Timezone); // realm category
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
- pkt << uint8(realm.m_ID);
+ pkt << uint8(realm.Id.Realm);
else
pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients
@@ -953,6 +952,7 @@ void AuthSession::SetVSFields(const std::string& rI)
x.SetBinary(sha.GetDigest(), sha.GetLength());
v = g.ModExp(x, N);
+ // No SQL injection (username escaped)
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_VS);
stmt->setString(0, v.AsHexStr());
stmt->setString(1, s.AsHexStr());
diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist
index 82c3cd47148..a97d75b3f57 100644
--- a/src/server/authserver/authserver.conf.dist
+++ b/src/server/authserver/authserver.conf.dist
@@ -137,6 +137,26 @@ WrongPass.Logging = 0
BanExpiryCheckInterval = 60
+#
+# SourceDirectory
+# Description: The path to your TrinityCore source directory.
+# If the path is left empty, the built-in CMAKE_SOURCE_DIR is used.
+# Example: "../TrinityCore"
+# Default: ""
+
+SourceDirectory = ""
+
+#
+# MySQLExecutable
+# Description: The path to your mysql cli binary.
+# If the path is left empty, built-in path from cmake is used.
+# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
+# "mysql.exe"
+# "/usr/bin/mysql"
+# Default: ""
+
+MySQLExecutable = ""
+
#
###################################################################################################
@@ -180,26 +200,6 @@ LoginDatabase.WorkerThreads = 1
Updates.EnableDatabases = 0
-#
-# Updates.SourcePath
-# Description: The path to your TrinityCore source directory.
-# If the path is left empty, built-in CMAKE_SOURCE_DIR is used.
-# Example: "../TrinityCore"
-# Default: ""
-
-Updates.SourcePath = ""
-
-#
-# Updates.MySqlCLIPath
-# Description: The path to your mysql cli binary.
-# If the path is left empty, built-in path from cmake is used.
-# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
-# "mysql.exe"
-# "/usr/bin/mysql"
-# Default: ""
-
-Updates.MySqlCLIPath = ""
-
#
# Updates.AutoSetup
# Description: Auto populate empty databases.
diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt
index 69a0d60cc66..9196f586287 100644
--- a/src/server/bnetserver/CMakeLists.txt
+++ b/src/server/bnetserver/CMakeLists.txt
@@ -47,9 +47,9 @@ include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Authentication
+ ${CMAKE_CURRENT_SOURCE_DIR}/Packets
${CMAKE_CURRENT_SOURCE_DIR}/Realms
${CMAKE_CURRENT_SOURCE_DIR}/Server
- ${CMAKE_CURRENT_SOURCE_DIR}/Packets
${CMAKE_SOURCE_DIR}/dep/cppformat
${CMAKE_SOURCE_DIR}/dep/zmqpp
${CMAKE_SOURCE_DIR}/src/common
@@ -64,9 +64,9 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/database/Database
${CMAKE_SOURCE_DIR}/src/server/database/Logging
${CMAKE_SOURCE_DIR}/src/server/ipc
+ ${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
- ${CMAKE_SOURCE_DIR}/src/server/shared/Realm
${CMAKE_SOURCE_DIR}/src/server/shared/Service
${MYSQL_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
@@ -86,12 +86,12 @@ if( NOT WIN32 )
endif()
target_link_libraries(bnetserver
- common
+ shared
database
ipc
- shared
- format
+ common
zmqpp
+ format
${MYSQL_LIBRARY}
${OPENSSL_LIBRARIES}
${ZMQ_LIBRARY}
diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.cpp b/src/server/bnetserver/Packets/WoWRealmPackets.cpp
index db544535515..9f4800583ab 100644
--- a/src/server/bnetserver/Packets/WoWRealmPackets.cpp
+++ b/src/server/bnetserver/Packets/WoWRealmPackets.cpp
@@ -42,8 +42,8 @@ void Battlenet::WoWRealm::ListUnsubscribe::CallHandler(Session* session)
void Battlenet::WoWRealm::JoinRequestV2::Read()
{
- Realm.Battlegroup = _stream.Read(8);
- Realm.Index = _stream.Read(32);
+ Realm.Site = _stream.Read(8);
+ Realm.Realm = _stream.Read(32);
Realm.Region = _stream.Read(8);
ClientSeed = _stream.Read(32);
}
@@ -51,7 +51,7 @@ void Battlenet::WoWRealm::JoinRequestV2::Read()
std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const
{
std::ostringstream stream;
- stream << "Battlenet::WoWRealm::JoinRequestV2 ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Battlegroup) << " Index " << Realm.Index;
+ stream << "Battlenet::WoWRealm::JoinRequestV2 ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Site) << " Index " << Realm.Realm;
return stream.str().c_str();
}
@@ -74,8 +74,8 @@ void Battlenet::WoWRealm::ListSubscribeResponse::Write()
_stream.Write(CharacterCounts.size(), 7);
for (CharacterCountEntry const& entry : CharacterCounts)
{
- _stream.Write(entry.Realm.Battlegroup, 8);
- _stream.Write(entry.Realm.Index, 32);
+ _stream.Write(entry.Realm.Site, 8);
+ _stream.Write(entry.Realm.Realm, 32);
_stream.Write(entry.Realm.Region, 8);
_stream.Write(entry.CharacterCount, 16);
}
@@ -100,7 +100,7 @@ std::string Battlenet::WoWRealm::ListSubscribeResponse::ToString() const
stream << " Realms " << CharacterCounts.size();
for (CharacterCountEntry const& entry : CharacterCounts)
- stream << std::endl << "Region " << uint32(entry.Realm.Region) << " Battlegroup " << uint32(entry.Realm.Region) << " Index " << entry.Realm.Index << " Characters " << entry.CharacterCount;
+ stream << std::endl << "Region " << uint32(entry.Realm.Region) << " Battlegroup " << uint32(entry.Realm.Region) << " Index " << entry.Realm.Realm << " Characters " << entry.CharacterCount;
for (ServerPacket* realmData : RealmData)
stream << std::endl << realmData->ToString();
@@ -125,7 +125,7 @@ void Battlenet::WoWRealm::ListUpdate::Write()
if (!Version.empty())
{
_stream.WriteString(Version, 5);
- _stream.Write(Id.Build, 32);
+ _stream.Write(Build, 32);
boost::asio::ip::address_v4::bytes_type ip = Address.address().to_v4().to_bytes();
uint16 port = Address.port();
@@ -140,8 +140,8 @@ void Battlenet::WoWRealm::ListUpdate::Write()
_stream.WriteString(Name, 10);
}
- _stream.Write(Id.Battlegroup, 8);
- _stream.Write(Id.Index, 32);
+ _stream.Write(Id.Site, 8);
+ _stream.Write(Id.Realm, 32);
_stream.Write(Id.Region, 8);
}
@@ -152,13 +152,13 @@ std::string Battlenet::WoWRealm::ListUpdate::ToString() const
if (UpdateState == UPDATE)
{
stream << " Timezone: " << Timezone << " Population: " << Population << " Lock: " << uint32(Lock) << " Type: " << Type << " Name: " << Name
- << " Flags: " << uint32(Flags) << " Region: " << uint32(Id.Region) << " Battlegroup: " << uint32(Id.Battlegroup) << " Index: " << Id.Index;
+ << " Flags: " << uint32(Flags) << " Region: " << uint32(Id.Region) << " Battlegroup: " << uint32(Id.Site) << " Index: " << Id.Realm;
if (!Version.empty())
stream << " Version: " << Version;
}
else
- stream << " Delete realm [Region: " << uint32(Id.Region) << " Battlegroup : " << uint32(Id.Battlegroup) << " Index : " << Id.Index << "]";
+ stream << " Delete realm [Region: " << uint32(Id.Region) << " Battlegroup : " << uint32(Id.Site) << " Index : " << Id.Realm << "]";
return stream.str().c_str();
}
@@ -167,7 +167,7 @@ void Battlenet::WoWRealm::ToonReady::Write()
{
_stream.Write(Realm.Region, 8);
_stream.WriteFourCC(Game);
- uint32 realmAddress = ((Realm.Battlegroup << 16) & 0xFF0000) | uint16(Realm.Index);
+ uint32 realmAddress = ((Realm.Site << 16) & 0xFF0000) | uint16(Realm.Realm);
_stream.Write(realmAddress, 32);
_stream.WriteString(Name, 7, -2);
_stream.WriteSkip(7);
@@ -185,7 +185,7 @@ std::string Battlenet::WoWRealm::ToonReady::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ToonReady" << " Game: " << Game
- << ", Region: " << uint32(Realm.Region) << ", Battlegroup: " << uint32(Realm.Battlegroup) << ", Index: " << Realm.Index
+ << ", Region: " << uint32(Realm.Region) << ", Battlegroup: " << uint32(Realm.Site) << ", Index: " << Realm.Realm
<< ", Guid: " << Guid << ", Name: " << Name;
return stream.str().c_str();
diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.h b/src/server/bnetserver/Packets/WoWRealmPackets.h
index 08bfab809b8..6950dece500 100644
--- a/src/server/bnetserver/Packets/WoWRealmPackets.h
+++ b/src/server/bnetserver/Packets/WoWRealmPackets.h
@@ -79,7 +79,7 @@ namespace Battlenet
void CallHandler(Session* session) override;
uint32 ClientSeed;
- RealmId Realm;
+ Battlenet::RealmHandle Realm;
};
class ListSubscribeResponse final : public ServerPacket
@@ -100,7 +100,7 @@ namespace Battlenet
struct CharacterCountEntry
{
- RealmId Realm;
+ Battlenet::RealmHandle Realm;
uint32 CharacterCount;
};
@@ -139,7 +139,8 @@ namespace Battlenet
std::string Version;
tcp::endpoint Address;
uint8 Flags;
- RealmId Id;
+ Battlenet::RealmHandle Id;
+ uint32 Build;
};
class ListComplete final : public ServerPacket
@@ -164,7 +165,7 @@ namespace Battlenet
std::string ToString() const override;
std::string Game;
- RealmId Realm;
+ Battlenet::RealmHandle Realm;
uint64 Guid;
std::string Name;
};
diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp
index 45e675bb51a..d3f40a8cc97 100644
--- a/src/server/bnetserver/Realms/RealmList.cpp
+++ b/src/server/bnetserver/Realms/RealmList.cpp
@@ -24,49 +24,6 @@
#include "RealmList.h"
#include
-Battlenet::RealmId& Battlenet::RealmId::operator=(Battlenet::RealmHandle const& handle)
-{
- Region = handle.Region;
- Battlegroup = handle.Battlegroup;
- Index = handle.Index;
- return *this;
-}
-
-ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const
-{
- ip::address realmIp;
-
- // Attempt to send best address for client
- if (clientAddr.is_loopback())
- {
- // Try guessing if realm is also connected locally
- if (LocalAddress.is_loopback() || ExternalAddress.is_loopback())
- realmIp = clientAddr;
- else
- {
- // Assume that user connecting from the machine that bnetserver is located on
- // has all realms available in his local network
- realmIp = LocalAddress;
- }
- }
- else
- {
- if (clientAddr.is_v4() &&
- (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) ==
- (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()))
- {
- realmIp = LocalAddress;
- }
- else
- realmIp = ExternalAddress;
- }
-
- ip::tcp::endpoint endpoint(realmIp, Port);
-
- // Return external IP
- return endpoint;
-}
-
RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr), _worldListener(nullptr)
{
}
@@ -95,6 +52,7 @@ void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInte
void RealmList::Close()
{
_worldListener->End();
+ _updateTimer->cancel();
}
template
@@ -107,7 +65,7 @@ inline void UpdateField(FieldType& out, FieldType const& in, bool& changed)
}
}
-void RealmList::UpdateRealm(Battlenet::RealmId const& id, const std::string& name, ip::address const& address, ip::address const& localAddr,
+void RealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel,
float population)
{
@@ -117,6 +75,7 @@ void RealmList::UpdateRealm(Battlenet::RealmId const& id, const std::string& nam
realm.Keep = true;
realm.Id = id;
+ UpdateField(realm.Build, build, realm.Updated);
UpdateField(realm.Name, name, realm.Updated);
UpdateField(realm.Type, icon, realm.Updated);
UpdateField(realm.Flags, flag, realm.Updated);
@@ -184,6 +143,10 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
uint16 port = fields[5].GetUInt16();
uint8 icon = fields[6].GetUInt8();
+ if (icon == REALM_TYPE_FFA_PVP)
+ icon = REALM_TYPE_PVP;
+ if (icon >= MAX_CLIENT_REALM_TYPE)
+ icon = REALM_TYPE_NORMAL;
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
uint8 timezone = fields[8].GetUInt8();
uint8 allowedSecurityLevel = fields[9].GetUInt8();
@@ -193,24 +156,24 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
uint8 region = fields[12].GetUInt8();
uint8 battlegroup = fields[13].GetUInt8();
- Battlenet::RealmId id{ region, battlegroup, realmId, build };
+ Battlenet::RealmHandle id{ region, battlegroup, realmId };
- UpdateRealm(id, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone,
- (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
+ UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag,
+ timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
TC_LOG_TRACE("realmlist", "Realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port);
}
catch (std::exception& ex)
{
TC_LOG_ERROR("realmlist", "Realmlist::UpdateRealms has thrown an exception: %s", ex.what());
- ASSERT(false);
+ ABORT();
}
}
while (result->NextRow());
}
std::vector updatedRealms;
- std::vector deletedRealms;
+ std::vector deletedRealms;
for (RealmMap::value_type& pair : _realms)
{
@@ -223,7 +186,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
pair.second.Keep = false;
}
- for (Battlenet::RealmId const& deleted : deletedRealms)
+ for (Battlenet::RealmHandle const& deleted : deletedRealms)
_realms.erase(deleted);
if (!updatedRealms.empty() || !deletedRealms.empty())
@@ -242,7 +205,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
}
}
-Realm const* RealmList::GetRealm(Battlenet::RealmId const& id) const
+Realm const* RealmList::GetRealm(Battlenet::RealmHandle const& id) const
{
auto itr = _realms.find(id);
if (itr != _realms.end())
diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h
index 5932a01103e..388d4d5e1aa 100644
--- a/src/server/bnetserver/Realms/RealmList.h
+++ b/src/server/bnetserver/Realms/RealmList.h
@@ -20,6 +20,7 @@
#define _REALMLIST_H
#include "Common.h"
+#include "Realm/Realm.h"
#include "WorldListener.h"
#include
#include
@@ -28,72 +29,11 @@
using namespace boost::asio;
-enum RealmFlags
-{
- REALM_FLAG_NONE = 0x00,
- REALM_FLAG_INVALID = 0x01,
- REALM_FLAG_OFFLINE = 0x02,
- REALM_FLAG_SPECIFYBUILD = 0x04,
- REALM_FLAG_UNK1 = 0x08,
- REALM_FLAG_UNK2 = 0x10,
- REALM_FLAG_RECOMMENDED = 0x20,
- REALM_FLAG_NEW = 0x40,
- REALM_FLAG_FULL = 0x80
-};
-
-#pragma pack(push, 1)
-
-namespace Battlenet
-{
- struct RealmHandle;
-
- struct RealmId
- {
- RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { }
- RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build)
- : Region(region), Battlegroup(battlegroup), Index(index), Build(build) { }
-
- uint8 Region;
- uint8 Battlegroup;
- uint32 Index;
- uint32 Build;
-
- bool operator<(RealmId const& r) const
- {
- return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0;
- }
-
- RealmId& operator=(RealmHandle const& handle);
- };
-}
-
-#pragma pack(pop)
-
-// Storage object for a realm
-struct Realm
-{
- Battlenet::RealmId Id;
- ip::address ExternalAddress;
- ip::address LocalAddress;
- ip::address LocalSubnetMask;
- uint16 Port;
- std::string Name;
- uint8 Type;
- RealmFlags Flags;
- uint8 Timezone;
- AccountTypes AllowedSecurityLevel;
- float PopulationLevel;
- bool Updated;
- bool Keep;
-
- ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
-};
-
/// Storage object for the list of realms on the server
class RealmList
{
public:
- typedef std::map RealmMap;
+ typedef std::map RealmMap;
static RealmList* instance()
{
@@ -107,13 +47,13 @@ public:
void Close();
RealmMap const& GetRealms() const { return _realms; }
- Realm const* GetRealm(Battlenet::RealmId const& id) const;
+ Realm const* GetRealm(Battlenet::RealmHandle const& id) const;
private:
RealmList();
void UpdateRealms(boost::system::error_code const& error);
- void UpdateRealm(Battlenet::RealmId const& id, const std::string& name, ip::address const& address, ip::address const& localAddr,
+ void UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
RealmMap _realms;
diff --git a/src/server/bnetserver/Realms/WorldListener.cpp b/src/server/bnetserver/Realms/WorldListener.cpp
index 33c01838aa4..b5cf3ce654d 100644
--- a/src/server/bnetserver/Realms/WorldListener.cpp
+++ b/src/server/bnetserver/Realms/WorldListener.cpp
@@ -76,7 +76,7 @@ void WorldListener::HandleClose()
void WorldListener::Dispatch(zmqpp::message& msg) const
{
- Battlenet::Header ipcHeader;
+ IPC::BattlenetComm::Header ipcHeader;
msg >> ipcHeader;
if (ipcHeader.Ipc.Channel != IPC_CHANNEL_BNET)
@@ -88,7 +88,7 @@ void WorldListener::Dispatch(zmqpp::message& msg) const
void WorldListener::HandleToonOnlineStatusChange(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const
{
- Battlenet::ToonHandle toonHandle;
+ IPC::BattlenetComm::ToonHandle toonHandle;
bool online;
msg >> toonHandle;
msg >> online;
diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp
index 5506634f38b..b51b83b728f 100644
--- a/src/server/bnetserver/Server/Session.cpp
+++ b/src/server/bnetserver/Server/Session.cpp
@@ -470,7 +470,7 @@ void Battlenet::Session::HandleListSubscribeRequestCallback(PreparedQueryResult
{
Field* fields = result->Fetch();
uint32 build = fields[4].GetUInt32();
- listSubscribeResponse->CharacterCounts.push_back({ RealmId(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0)), fields[0].GetUInt8() });
+ listSubscribeResponse->CharacterCounts.push_back({ Battlenet::RealmHandle(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32()), fields[0].GetUInt8() });
} while (result->NextRow());
}
@@ -493,7 +493,7 @@ void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& join
{
WoWRealm::JoinResponseV2* joinResponse = new WoWRealm::JoinResponseV2();
Realm const* realm = sRealmList->GetRealm(joinRequest.Realm);
- if (!realm || realm->Flags & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE))
+ if (!realm || realm->Flags & (REALM_FLAG_VERSION_MISMATCH | REALM_FLAG_OFFLINE))
{
joinResponse->Response = WoWRealm::JoinResponseV2::FAILURE;
AsyncWrite(joinResponse);
@@ -1114,12 +1114,12 @@ bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket
return false;
}
-void Battlenet::Session::UpdateRealms(std::vector& realms, std::vector& deletedRealms)
+void Battlenet::Session::UpdateRealms(std::vector& realms, std::vector& deletedRealms)
{
for (Realm const* realm : realms)
AsyncWrite(BuildListUpdate(realm));
- for (RealmId& deleted : deletedRealms)
+ for (Battlenet::RealmHandle& deleted : deletedRealms)
{
WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate();
listUpdate->UpdateState = WoWRealm::ListUpdate::DELETED;
@@ -1131,10 +1131,10 @@ void Battlenet::Session::UpdateRealms(std::vector& realms, std::ve
Battlenet::WoWRealm::ListUpdate* Battlenet::Session::BuildListUpdate(Realm const* realm) const
{
uint32 flag = realm->Flags & ~REALM_FLAG_SPECIFYBUILD;
- RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm->Id.Build);
- if (realm->Id.Build != _build)
+ RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm->Build);
+ if (realm->Build != _build)
{
- flag |= REALM_FLAG_INVALID;
+ flag |= REALM_FLAG_VERSION_MISMATCH;
if (buildInfo)
flag |= REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for
}
@@ -1153,6 +1153,7 @@ Battlenet::WoWRealm::ListUpdate* Battlenet::Session::BuildListUpdate(Realm const
listUpdate->Version = version.str();
listUpdate->Address = realm->GetAddressForClient(GetRemoteIpAddress());
+ listUpdate->Build = realm->Build;
}
listUpdate->Flags = flag;
diff --git a/src/server/bnetserver/Server/Session.h b/src/server/bnetserver/Server/Session.h
index e747e2b7407..fc9a446ec4a 100644
--- a/src/server/bnetserver/Server/Session.h
+++ b/src/server/bnetserver/Server/Session.h
@@ -115,7 +115,7 @@ namespace Battlenet
void Start() override;
bool Update() override;
- void UpdateRealms(std::vector& realms, std::vector& deletedRealms);
+ void UpdateRealms(std::vector& realms, std::vector& deletedRealms);
uint32 GetAccountId() const { return _accountInfo->Id; }
uint32 GetGameAccountId() const { return _gameAccountInfo->Id; }
diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp
index 92d8730cd12..6a8e86ffca9 100644
--- a/src/server/database/Database/DatabaseLoader.cpp
+++ b/src/server/database/Database/DatabaseLoader.cpp
@@ -32,7 +32,7 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::st
{
bool const updatesEnabledForThis = DBUpdater::IsEnabled(_updateFlags);
- _open.push(std::make_pair([this, name, updatesEnabledForThis, &pool]() -> bool
+ _open.push([this, name, updatesEnabledForThis, &pool]() -> bool
{
std::string const dbString = sConfigMgr->GetStringDefault(name + "DatabaseInfo", "");
if (dbString.empty())
@@ -71,12 +71,13 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::st
return false;
}
}
+ // Add the close operation
+ _close.push([&pool]
+ {
+ pool.Close();
+ });
return true;
- },
- [&pool]()
- {
- pool.Close();
- }));
+ });
// Populate and update only if updates are enabled for this pool
if (updatesEnabledForThis)
@@ -137,38 +138,7 @@ bool DatabaseLoader::Load()
bool DatabaseLoader::OpenDatabases()
{
- while (!_open.empty())
- {
- std::pair> const load = _open.top();
- if (load.first())
- _close.push(load.second);
- else
- {
- // Close all loaded databases
- while (!_close.empty())
- {
- _close.top()();
- _close.pop();
- }
- return false;
- }
-
- _open.pop();
- }
- return true;
-}
-
-// Processes the elements of the given stack until a predicate returned false.
-bool DatabaseLoader::Process(std::stack& stack)
-{
- while (!stack.empty())
- {
- if (!stack.top()())
- return false;
-
- stack.pop();
- }
- return true;
+ return Process(_open);
}
bool DatabaseLoader::PopulateDatabases()
@@ -186,6 +156,27 @@ bool DatabaseLoader::PrepareStatements()
return Process(_prepare);
}
+bool DatabaseLoader::Process(std::queue& queue)
+{
+ while (!queue.empty())
+ {
+ if (!queue.front()())
+ {
+ // Close all open databases which have a registered close operation
+ while (!_close.empty())
+ {
+ _close.top()();
+ _close.pop();
+ }
+
+ return false;
+ }
+
+ queue.pop();
+ }
+ return true;
+}
+
template
DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name);
template
diff --git a/src/server/database/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h
index da92cf85a9f..ec390a427ad 100644
--- a/src/server/database/Database/DatabaseLoader.h
+++ b/src/server/database/Database/DatabaseLoader.h
@@ -21,8 +21,9 @@
#include "DatabaseWorkerPool.h"
#include "DatabaseEnv.h"
-#include
#include
+#include
+#include
// A helper class to initiate all database worker pools,
// handles updating, delays preparing of statements and cleans up on failure.
@@ -56,16 +57,18 @@ private:
bool PrepareStatements();
using Predicate = std::function;
+ using Closer = std::function;
- static bool Process(std::stack& stack);
+ // Invokes all functions in the given queue and closes the databases on errors.
+ // Returns false when there was an error.
+ bool Process(std::queue& queue);
std::string const _logger;
bool const _autoSetup;
uint32 const _updateFlags;
- std::stack>> _open;
- std::stack> _close;
- std::stack _populate, _update, _prepare;
+ std::queue _open, _populate, _update, _prepare;
+ std::stack _close;
};
#endif // DatabaseLoader_h__
diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp
new file mode 100644
index 00000000000..5d914b6e0e8
--- /dev/null
+++ b/src/server/database/Database/DatabaseWorkerPool.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#include "DatabaseWorkerPool.h"
+#include "DatabaseEnv.h"
+
+#define MIN_MYSQL_SERVER_VERSION 50100u
+#define MIN_MYSQL_CLIENT_VERSION 50100u
+
+template
+DatabaseWorkerPool::DatabaseWorkerPool()
+ : _queue(new ProducerConsumerQueue()),
+ _async_threads(0), _synch_threads(0)
+{
+ WPFatal(mysql_thread_safe(), "Used MySQL library isn't thread-safe.");
+ WPFatal(mysql_get_client_version() >= MIN_MYSQL_CLIENT_VERSION, "TrinityCore does not support MySQL versions below 5.1");
+ WPFatal(mysql_get_client_version() == MYSQL_VERSION_ID, "Used MySQL library version (%s) does not match the version used to compile TrinityCore (%s).",
+ mysql_get_client_info(), MYSQL_SERVER_VERSION);
+}
+
+template
+void DatabaseWorkerPool::SetConnectionInfo(std::string const& infoString,
+ uint8 const asyncThreads, uint8 const synchThreads)
+{
+ _connectionInfo = Trinity::make_unique(infoString);
+
+ _async_threads = asyncThreads;
+ _synch_threads = synchThreads;
+}
+
+template
+uint32 DatabaseWorkerPool::Open()
+{
+ WPFatal(_connectionInfo.get(), "Connection info was not set!");
+
+ TC_LOG_INFO("sql.driver", "Opening DatabasePool '%s'. "
+ "Asynchronous connections: %u, synchronous connections: %u.",
+ GetDatabaseName(), _async_threads, _synch_threads);
+
+ uint32 error = OpenConnections(IDX_ASYNC, _async_threads);
+
+ if (error)
+ return error;
+
+ error = OpenConnections(IDX_SYNCH, _synch_threads);
+
+ if (!error)
+ {
+ TC_LOG_INFO("sql.driver", "DatabasePool '%s' opened successfully. " SZFMTD
+ " total connections running.", GetDatabaseName(),
+ (_connections[IDX_SYNCH].size() + _connections[IDX_ASYNC].size()));
+ }
+
+ return error;
+}
+
+template
+void DatabaseWorkerPool::Close()
+{
+ TC_LOG_INFO("sql.driver", "Closing down DatabasePool '%s'.", GetDatabaseName());
+
+ //! Closes the actualy MySQL connection.
+ _connections[IDX_ASYNC].clear();
+
+ TC_LOG_INFO("sql.driver", "Asynchronous connections on DatabasePool '%s' terminated. "
+ "Proceeding with synchronous connections.",
+ GetDatabaseName());
+
+ //! Shut down the synchronous connections
+ //! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
+ //! should only be called after any other thread tasks in the core have exited,
+ //! meaning there can be no concurrent access at this point.
+ _connections[IDX_SYNCH].clear();
+
+ TC_LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName());
+}
+
+template
+bool DatabaseWorkerPool::PrepareStatements()
+{
+ for (auto& connections : _connections)
+ for (auto& connection : connections)
+ {
+ connection->LockIfReady();
+ if (!connection->PrepareStatements())
+ {
+ connection->Unlock();
+ Close();
+ return false;
+ }
+ else
+ connection->Unlock();
+ }
+
+ return true;
+}
+
+template
+QueryResult DatabaseWorkerPool::Query(const char* sql, T* connection /*= nullptr*/)
+{
+ if (!connection)
+ connection = GetFreeConnection();
+
+ ResultSet* result = connection->Query(sql);
+ connection->Unlock();
+ if (!result || !result->GetRowCount() || !result->NextRow())
+ {
+ delete result;
+ return QueryResult(NULL);
+ }
+
+ return QueryResult(result);
+}
+
+template
+PreparedQueryResult DatabaseWorkerPool::Query(PreparedStatement* stmt)
+{
+ auto connection = GetFreeConnection();
+ PreparedResultSet* ret = connection->Query(stmt);
+ connection->Unlock();
+
+ //! Delete proxy-class. Not needed anymore
+ delete stmt;
+
+ if (!ret || !ret->GetRowCount())
+ {
+ delete ret;
+ return PreparedQueryResult(NULL);
+ }
+
+ return PreparedQueryResult(ret);
+}
+
+template
+QueryResultFuture DatabaseWorkerPool::AsyncQuery(const char* sql)
+{
+ BasicStatementTask* task = new BasicStatementTask(sql, true);
+ // Store future result before enqueueing - task might get already processed and deleted before returning from this method
+ QueryResultFuture result = task->GetFuture();
+ Enqueue(task);
+ return result;
+}
+
+template
+PreparedQueryResultFuture DatabaseWorkerPool::AsyncQuery(PreparedStatement* stmt)
+{
+ PreparedStatementTask* task = new PreparedStatementTask(stmt, true);
+ // Store future result before enqueueing - task might get already processed and deleted before returning from this method
+ PreparedQueryResultFuture result = task->GetFuture();
+ Enqueue(task);
+ return result;
+}
+
+template
+QueryResultHolderFuture DatabaseWorkerPool::DelayQueryHolder(SQLQueryHolder* holder)
+{
+ SQLQueryHolderTask* task = new SQLQueryHolderTask(holder);
+ // Store future result before enqueueing - task might get already processed and deleted before returning from this method
+ QueryResultHolderFuture result = task->GetFuture();
+ Enqueue(task);
+ return result;
+}
+
+template
+void DatabaseWorkerPool::CommitTransaction(SQLTransaction transaction)
+{
+#ifdef TRINITY_DEBUG
+ //! Only analyze transaction weaknesses in Debug mode.
+ //! Ideally we catch the faults in Debug mode and then correct them,
+ //! so there's no need to waste these CPU cycles in Release mode.
+ switch (transaction->GetSize())
+ {
+ case 0:
+ TC_LOG_DEBUG("sql.driver", "Transaction contains 0 queries. Not executing.");
+ return;
+ case 1:
+ TC_LOG_DEBUG("sql.driver", "Warning: Transaction only holds 1 query, consider removing Transaction context in code.");
+ break;
+ default:
+ break;
+ }
+#endif // TRINITY_DEBUG
+
+ Enqueue(new TransactionTask(transaction));
+}
+
+template
+void DatabaseWorkerPool::DirectCommitTransaction(SQLTransaction& transaction)
+{
+ T* connection = GetFreeConnection();
+ int errorCode = connection->ExecuteTransaction(transaction);
+ if (!errorCode)
+ {
+ connection->Unlock(); // OK, operation succesful
+ return;
+ }
+
+ //! Handle MySQL Errno 1213 without extending deadlock to the core itself
+ /// @todo More elegant way
+ if (errorCode == ER_LOCK_DEADLOCK)
+ {
+ uint8 loopBreaker = 5;
+ for (uint8 i = 0; i < loopBreaker; ++i)
+ {
+ if (!connection->ExecuteTransaction(transaction))
+ break;
+ }
+ }
+
+ //! Clean up now.
+ transaction->Cleanup();
+
+ connection->Unlock();
+}
+
+template
+void DatabaseWorkerPool::EscapeString(std::string& str)
+{
+ if (str.empty())
+ return;
+
+ char* buf = new char[str.size() * 2 + 1];
+ EscapeString(buf, str.c_str(), str.size());
+ str = buf;
+ delete[] buf;
+}
+
+template
+void DatabaseWorkerPool::KeepAlive()
+{
+ //! Ping synchronous connections
+ for (auto& connection : _connections[IDX_SYNCH])
+ {
+ if (connection->LockIfReady())
+ {
+ connection->Ping();
+ connection->Unlock();
+ }
+ }
+
+ //! Assuming all worker threads are free, every worker thread will receive 1 ping operation request
+ //! If one or more worker threads are busy, the ping operations will not be split evenly, but this doesn't matter
+ //! as the sole purpose is to prevent connections from idling.
+ auto const count = _connections[IDX_ASYNC].size();
+ for (uint8 i = 0; i < count; ++i)
+ Enqueue(new PingOperation);
+}
+
+template
+uint32 DatabaseWorkerPool::OpenConnections(InternalIndex type, uint8 numConnections)
+{
+ for (uint8 i = 0; i < numConnections; ++i)
+ {
+ // Create the connection
+ auto connection = [&] {
+ switch (type)
+ {
+ case IDX_ASYNC:
+ return Trinity::make_unique(_queue.get(), *_connectionInfo);
+ case IDX_SYNCH:
+ return Trinity::make_unique(*_connectionInfo);
+ default:
+ ABORT();
+ }
+ }();
+
+ if (uint32 error = connection->Open())
+ {
+ // Failed to open a connection or invalid version, abort and cleanup
+ _connections[type].clear();
+ return error;
+ }
+ else if (mysql_get_server_version(connection->GetHandle()) < MIN_MYSQL_SERVER_VERSION)
+ {
+ TC_LOG_ERROR("sql.driver", "TrinityCore does not support MySQL versions below 5.1");
+ return 1;
+ }
+ else
+ {
+ _connections[type].push_back(std::move(connection));
+ }
+ }
+
+ // Everything is fine
+ return 0;
+}
+
+template
+T* DatabaseWorkerPool::GetFreeConnection()
+{
+ uint8 i = 0;
+ auto const num_cons = _connections[IDX_SYNCH].size();
+ T* connection = nullptr;
+ //! Block forever until a connection is free
+ for (;;)
+ {
+ connection = _connections[IDX_SYNCH][++i % num_cons].get();
+ //! Must be matched with t->Unlock() or you will get deadlocks
+ if (connection->LockIfReady())
+ break;
+ }
+
+ return connection;
+}
+
+template class DatabaseWorkerPool;
+template class DatabaseWorkerPool;
+template class DatabaseWorkerPool;
diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h
index d5a254647eb..d883366237f 100644
--- a/src/server/database/Database/DatabaseWorkerPool.h
+++ b/src/server/database/Database/DatabaseWorkerPool.h
@@ -32,9 +32,7 @@
#include
#include
-
-#define MIN_MYSQL_SERVER_VERSION 50100u
-#define MIN_MYSQL_CLIENT_VERSION 50100u
+#include
class PingOperation : public SQLOperation
{
@@ -59,97 +57,21 @@ class DatabaseWorkerPool
public:
/* Activity state */
- DatabaseWorkerPool() : _queue(new ProducerConsumerQueue()),
- _async_threads(0), _synch_threads(0)
- {
- memset(_connectionCount, 0, sizeof(_connectionCount));
- _connections.resize(IDX_SIZE);
-
- WPFatal(mysql_thread_safe(), "Used MySQL library isn't thread-safe.");
- WPFatal(mysql_get_client_version() >= MIN_MYSQL_CLIENT_VERSION, "TrinityCore does not support MySQL versions below 5.1");
- WPFatal(mysql_get_client_version() == MYSQL_VERSION_ID, "Used MySQL library version (%s) does not match the version used to compile TrinityCore (%s).",
- mysql_get_client_info(), MYSQL_SERVER_VERSION);
- }
+ DatabaseWorkerPool();
~DatabaseWorkerPool()
{
_queue->Cancel();
}
- void SetConnectionInfo(std::string const& infoString, uint8 const asyncThreads, uint8 const synchThreads)
- {
- _connectionInfo.reset(new MySQLConnectionInfo(infoString));
+ void SetConnectionInfo(std::string const& infoString, uint8 const asyncThreads, uint8 const synchThreads);
- _async_threads = asyncThreads;
- _synch_threads = synchThreads;
- }
+ uint32 Open();
- uint32 Open()
- {
- WPFatal(_connectionInfo.get(), "Connection info was not set!");
-
- TC_LOG_INFO("sql.driver", "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
- GetDatabaseName(), _async_threads, _synch_threads);
-
- uint32 error = OpenConnections(IDX_ASYNC, _async_threads);
-
- if (error)
- return error;
-
- error = OpenConnections(IDX_SYNCH, _synch_threads);
-
- if (!error)
- {
- TC_LOG_INFO("sql.driver", "DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(),
- (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
- }
-
- return error;
- }
-
- void Close()
- {
- TC_LOG_INFO("sql.driver", "Closing down DatabasePool '%s'.", GetDatabaseName());
-
- for (uint8 i = 0; i < _connectionCount[IDX_ASYNC]; ++i)
- {
- T* t = _connections[IDX_ASYNC][i];
- t->Close(); //! Closes the actualy MySQL connection.
- }
-
- TC_LOG_INFO("sql.driver", "Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
- GetDatabaseName());
-
- //! Shut down the synchronous connections
- //! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
- //! should only be called after any other thread tasks in the core have exited,
- //! meaning there can be no concurrent access at this point.
- for (uint8 i = 0; i < _connectionCount[IDX_SYNCH]; ++i)
- _connections[IDX_SYNCH][i]->Close();
-
- TC_LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName());
- }
+ void Close();
//! Prepares all prepared statements
- bool PrepareStatements()
- {
- for (uint8 i = 0; i < IDX_SIZE; ++i)
- for (uint32 c = 0; c < _connectionCount[i]; ++c)
- {
- T* t = _connections[i][c];
- t->LockIfReady();
- if (!t->PrepareStatements())
- {
- t->Unlock();
- Close();
- return false;
- }
- else
- t->Unlock();
- }
-
- return true;
- }
+ bool PrepareStatements();
inline MySQLConnectionInfo const* GetConnectionInfo() const
{
@@ -201,9 +123,9 @@ class DatabaseWorkerPool
if (!sql)
return;
- T* t = GetFreeConnection();
- t->Execute(sql);
- t->Unlock();
+ T* connection = GetFreeConnection();
+ connection->Execute(sql);
+ connection->Unlock();
}
//! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished.
@@ -221,9 +143,9 @@ class DatabaseWorkerPool
//! Statement must be prepared with the CONNECTION_SYNCH flag.
void DirectExecute(PreparedStatement* stmt)
{
- T* t = GetFreeConnection();
- t->Execute(stmt);
- t->Unlock();
+ T* connection = GetFreeConnection();
+ connection->Execute(stmt);
+ connection->Unlock();
//! Delete proxy-class. Not needed anymore
delete stmt;
@@ -235,21 +157,7 @@ class DatabaseWorkerPool
//! Directly executes an SQL query in string format that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
- QueryResult Query(const char* sql, T* conn = nullptr)
- {
- if (!conn)
- conn = GetFreeConnection();
-
- ResultSet* result = conn->Query(sql);
- conn->Unlock();
- if (!result || !result->GetRowCount() || !result->NextRow())
- {
- delete result;
- return QueryResult(NULL);
- }
-
- return QueryResult(result);
- }
+ QueryResult Query(const char* sql, T* connection = nullptr);
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
@@ -276,23 +184,7 @@ class DatabaseWorkerPool
//! Directly executes an SQL query in prepared format that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
//! Statement must be prepared with CONNECTION_SYNCH flag.
- PreparedQueryResult Query(PreparedStatement* stmt)
- {
- T* t = GetFreeConnection();
- PreparedResultSet* ret = t->Query(stmt);
- t->Unlock();
-
- //! Delete proxy-class. Not needed anymore
- delete stmt;
-
- if (!ret || !ret->GetRowCount())
- {
- delete ret;
- return PreparedQueryResult(NULL);
- }
-
- return PreparedQueryResult(ret);
- }
+ PreparedQueryResult Query(PreparedStatement* stmt);
/**
Asynchronous query (with resultset) methods.
@@ -300,14 +192,7 @@ class DatabaseWorkerPool
//! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
- QueryResultFuture AsyncQuery(const char* sql)
- {
- BasicStatementTask* task = new BasicStatementTask(sql, true);
- // Store future result before enqueueing - task might get already processed and deleted before returning from this method
- QueryResultFuture result = task->GetFuture();
- Enqueue(task);
- return result;
- }
+ QueryResultFuture AsyncQuery(const char* sql);
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
@@ -320,27 +205,13 @@ class DatabaseWorkerPool
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
//! Statement must be prepared with CONNECTION_ASYNC flag.
- PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt)
- {
- PreparedStatementTask* task = new PreparedStatementTask(stmt, true);
- // Store future result before enqueueing - task might get already processed and deleted before returning from this method
- PreparedQueryResultFuture result = task->GetFuture();
- Enqueue(task);
- return result;
- }
+ PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt);
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
//! return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
//! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag.
- QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder)
- {
- SQLQueryHolderTask* task = new SQLQueryHolderTask(holder);
- // Store future result before enqueueing - task might get already processed and deleted before returning from this method
- QueryResultHolderFuture result = task->GetFuture();
- Enqueue(task);
- return result;
- }
+ QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder);
/**
Transaction context methods.
@@ -354,57 +225,11 @@ class DatabaseWorkerPool
//! Enqueues a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
//! were appended to the transaction will be respected during execution.
- void CommitTransaction(SQLTransaction transaction)
- {
- #ifdef TRINITY_DEBUG
- //! Only analyze transaction weaknesses in Debug mode.
- //! Ideally we catch the faults in Debug mode and then correct them,
- //! so there's no need to waste these CPU cycles in Release mode.
- switch (transaction->GetSize())
- {
- case 0:
- TC_LOG_DEBUG("sql.driver", "Transaction contains 0 queries. Not executing.");
- return;
- case 1:
- TC_LOG_DEBUG("sql.driver", "Warning: Transaction only holds 1 query, consider removing Transaction context in code.");
- break;
- default:
- break;
- }
- #endif // TRINITY_DEBUG
-
- Enqueue(new TransactionTask(transaction));
- }
+ void CommitTransaction(SQLTransaction transaction);
//! Directly executes a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
//! were appended to the transaction will be respected during execution.
- void DirectCommitTransaction(SQLTransaction& transaction)
- {
- T* con = GetFreeConnection();
- int errorCode = con->ExecuteTransaction(transaction);
- if (!errorCode)
- {
- con->Unlock(); // OK, operation succesful
- return;
- }
-
- //! Handle MySQL Errno 1213 without extending deadlock to the core itself
- /// @todo More elegant way
- if (errorCode == ER_LOCK_DEADLOCK)
- {
- uint8 loopBreaker = 5;
- for (uint8 i = 0; i < loopBreaker; ++i)
- {
- if (!con->ExecuteTransaction(transaction))
- break;
- }
- }
-
- //! Clean up now.
- transaction->Cleanup();
-
- con->Unlock();
- }
+ void DirectCommitTransaction(SQLTransaction& transaction);
//! Method used to execute prepared statements in a diverse context.
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
@@ -441,90 +266,21 @@ class DatabaseWorkerPool
}
//! Apply escape string'ing for current collation. (utf8)
- void EscapeString(std::string& str)
- {
- if (str.empty())
- return;
-
- char* buf = new char[str.size() * 2 + 1];
- EscapeString(buf, str.c_str(), str.size());
- str = buf;
- delete[] buf;
- }
+ void EscapeString(std::string& str);
//! Keeps all our MySQL connections alive, prevent the server from disconnecting us.
- void KeepAlive()
- {
- //! Ping synchronous connections
- for (uint8 i = 0; i < _connectionCount[IDX_SYNCH]; ++i)
- {
- T* t = _connections[IDX_SYNCH][i];
- if (t->LockIfReady())
- {
- t->Ping();
- t->Unlock();
- }
- }
-
- //! Assuming all worker threads are free, every worker thread will receive 1 ping operation request
- //! If one or more worker threads are busy, the ping operations will not be split evenly, but this doesn't matter
- //! as the sole purpose is to prevent connections from idling.
- for (size_t i = 0; i < _connections[IDX_ASYNC].size(); ++i)
- Enqueue(new PingOperation);
- }
+ void KeepAlive();
private:
- uint32 OpenConnections(InternalIndex type, uint8 numConnections)
- {
- _connections[type].resize(numConnections);
- for (uint8 i = 0; i < numConnections; ++i)
- {
- T* t;
-
- if (type == IDX_ASYNC)
- t = new T(_queue.get(), *_connectionInfo);
- else if (type == IDX_SYNCH)
- t = new T(*_connectionInfo);
- else
- ABORT();
-
- _connections[type][i] = t;
- ++_connectionCount[type];
-
- uint32 error = t->Open();
-
- if (!error)
- {
- if (mysql_get_server_version(t->GetHandle()) < MIN_MYSQL_SERVER_VERSION)
- {
- TC_LOG_ERROR("sql.driver", "TrinityCore does not support MySQL versions below 5.1");
- error = 1;
- }
- }
-
- // Failed to open a connection or invalid version, abort and cleanup
- if (error)
- {
- while (_connectionCount[type] != 0)
- {
- t = _connections[type][i--];
- delete t;
- --_connectionCount[type];
- }
- return error;
- }
- }
-
- // Everything is fine
- return 0;
- }
+ uint32 OpenConnections(InternalIndex type, uint8 numConnections);
unsigned long EscapeString(char *to, const char *from, unsigned long length)
{
if (!to || !from || !length)
return 0;
- return mysql_real_escape_string(_connections[IDX_SYNCH][0]->GetHandle(), to, from, length);
+ return mysql_real_escape_string(
+ _connections[IDX_SYNCH].front()->GetHandle(), to, from, length);
}
void Enqueue(SQLOperation* op)
@@ -534,22 +290,7 @@ class DatabaseWorkerPool
//! Gets a free connection in the synchronous connection pool.
//! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks.
- T* GetFreeConnection()
- {
- uint8 i = 0;
- size_t num_cons = _connectionCount[IDX_SYNCH];
- T* t = NULL;
- //! Block forever until a connection is free
- for (;;)
- {
- t = _connections[IDX_SYNCH][++i % num_cons];
- //! Must be matched with t->Unlock() or you will get deadlocks
- if (t->LockIfReady())
- break;
- }
-
- return t;
- }
+ T* GetFreeConnection();
char const* GetDatabaseName() const
{
@@ -558,9 +299,7 @@ class DatabaseWorkerPool
//! Queue shared by async worker threads.
std::unique_ptr> _queue;
- std::vector> _connections;
- //! Counter of MySQL connections;
- uint32 _connectionCount[IDX_SIZE];
+ std::array>, IDX_SIZE> _connections;
std::unique_ptr _connectionInfo;
uint8 _async_threads, _synch_threads;
};
diff --git a/src/server/database/Database/MySQLConnection.cpp b/src/server/database/Database/MySQLConnection.cpp
index 41dd61d3c3a..93d2a35f310 100644
--- a/src/server/database/Database/MySQLConnection.cpp
+++ b/src/server/database/Database/MySQLConnection.cpp
@@ -37,7 +37,6 @@ MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) :
m_reconnecting(false),
m_prepareError(false),
m_queue(NULL),
-m_worker(NULL),
m_Mysql(NULL),
m_connectionInfo(connInfo),
m_connectionFlags(CONNECTION_SYNCH) { }
@@ -50,24 +49,26 @@ m_Mysql(NULL),
m_connectionInfo(connInfo),
m_connectionFlags(CONNECTION_ASYNC)
{
- m_worker = new DatabaseWorker(m_queue, this);
+ m_worker = Trinity::make_unique(m_queue, this);
}
MySQLConnection::~MySQLConnection()
{
- delete m_worker;
-
- for (size_t i = 0; i < m_stmts.size(); ++i)
- delete m_stmts[i];
-
- if (m_Mysql)
- mysql_close(m_Mysql);
+ Close();
}
void MySQLConnection::Close()
{
- /// Only close us if we're not operating
- delete this;
+ // Stop the worker thread before the statements are cleared
+ m_worker.reset();
+
+ m_stmts.clear();
+
+ if (m_Mysql)
+ {
+ mysql_close(m_Mysql);
+ m_Mysql = nullptr;
+ }
}
uint32 MySQLConnection::Open()
@@ -412,7 +413,7 @@ int MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index)
{
ASSERT(index < m_stmts.size());
- MySQLPreparedStatement* ret = m_stmts[index];
+ MySQLPreparedStatement* ret = m_stmts[index].get();
if (!ret)
TC_LOG_ERROR("sql.sql", "Could not fetch prepared statement %u on database `%s`, connection type: %s.",
index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
@@ -424,16 +425,12 @@ void MySQLConnection::PrepareStatement(uint32 index, const char* sql, Connection
{
m_queries.insert(PreparedStatementMap::value_type(index, std::make_pair(sql, flags)));
- // For reconnection case
- if (m_reconnecting)
- delete m_stmts[index];
-
// Check if specified query should be prepared on this connection
// i.e. don't prepare async statements on synchronous connections
// to save memory that will not be used.
if (!(m_connectionFlags & flags))
{
- m_stmts[index] = NULL;
+ m_stmts[index].reset();
return;
}
@@ -455,8 +452,7 @@ void MySQLConnection::PrepareStatement(uint32 index, const char* sql, Connection
}
else
{
- MySQLPreparedStatement* mStmt = new MySQLPreparedStatement(stmt);
- m_stmts[index] = mStmt;
+ m_stmts[index] = Trinity::make_unique(stmt);
}
}
}
@@ -477,7 +473,7 @@ PreparedResultSet* MySQLConnection::Query(PreparedStatement* stmt)
return new PreparedResultSet(stmt->m_stmt->GetSTMT(), result, rowCount, fieldCount);
}
-bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
+bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/)
{
switch (errNo)
{
@@ -486,9 +482,21 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
case CR_INVALID_CONN_HANDLE:
case CR_SERVER_LOST_EXTENDED:
{
+ if (m_Mysql)
+ {
+ TC_LOG_ERROR("sql.sql", "Lost the connection to the MySQL server!");
+
+ mysql_close(GetHandle());
+ m_Mysql = nullptr;
+ }
+
+ /*no break*/
+ }
+ case CR_CONN_HOST_ERROR:
+ {
+ TC_LOG_INFO("sql.sql", "Attempting to reconnect to the MySQL server...");
+
m_reconnecting = true;
- uint64 oldThreadId = mysql_thread_id(GetHandle());
- mysql_close(GetHandle());
uint32 const lErrno = Open();
if (!lErrno)
@@ -496,24 +504,37 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
// Don't remove 'this' pointer unless you want to skip loading all prepared statements...
if (!this->PrepareStatements())
{
- TC_LOG_ERROR("sql.sql", "Could not re-prepare statements!");
- Close();
- return false;
+ TC_LOG_FATAL("sql.sql", "Could not re-prepare statements!");
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ std::abort();
}
- TC_LOG_INFO("sql.sql", "Connection to the MySQL server is active.");
- if (oldThreadId != mysql_thread_id(GetHandle()))
- TC_LOG_INFO("sql.sql", "Successfully reconnected to %s @%s:%s (%s).",
- m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
- (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
+ TC_LOG_INFO("sql.sql", "Successfully reconnected to %s @%s:%s (%s).",
+ m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
+ (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
m_reconnecting = false;
return true;
}
- // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
- std::this_thread::sleep_for(std::chrono::seconds(3)); // Sleep 3 seconds
- return _HandleMySQLErrno(lErrno); // Call self (recursive)
+ if ((--attempts) == 0)
+ {
+ // Shut down the server when the mysql server isn't
+ // reachable for some time
+ TC_LOG_FATAL("sql.sql", "Failed to reconnect to the MySQL server, "
+ "terminating the server to prevent data corruption!");
+
+ // We could also initiate a shutdown through using std::raise(SIGTERM)
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ std::abort();
+ }
+ else
+ {
+ // It's possible this attempted reconnect throws 2006 at us.
+ // To prevent crazy recursive calls, sleep here.
+ std::this_thread::sleep_for(std::chrono::seconds(3)); // Sleep 3 seconds
+ return _HandleMySQLErrno(lErrno, attempts); // Call self (recursive)
+ }
}
case ER_LOCK_DEADLOCK:
diff --git a/src/server/database/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h
index a981caa607e..a0b908593df 100644
--- a/src/server/database/Database/MySQLConnection.h
+++ b/src/server/database/Database/MySQLConnection.h
@@ -116,18 +116,18 @@ class MySQLConnection
virtual void DoPrepareStatements() = 0;
protected:
- std::vector m_stmts; //! PreparedStatements storage
+ std::vector> m_stmts; //! PreparedStatements storage
PreparedStatementMap m_queries; //! Query storage
bool m_reconnecting; //! Are we reconnecting?
bool m_prepareError; //! Was there any error while preparing statements?
private:
- bool _HandleMySQLErrno(uint32 errNo);
+ bool _HandleMySQLErrno(uint32 errNo, uint8 attempts = 5);
private:
ProducerConsumerQueue* m_queue; //! Queue shared with other asynchronous connections.
- DatabaseWorker* m_worker; //! Core worker task.
- MYSQL * m_Mysql; //! MySQL Handle.
+ std::unique_ptr m_worker; //! Core worker task.
+ MYSQL* m_Mysql; //! MySQL Handle.
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
std::mutex m_Mutex;
diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp
index 170954a86f4..b18d6c67612 100644
--- a/src/server/database/Updater/DBUpdater.cpp
+++ b/src/server/database/Updater/DBUpdater.cpp
@@ -21,6 +21,7 @@
#include "UpdateFetcher.h"
#include "DatabaseLoader.h"
#include "Config.h"
+#include "BuiltInConfig.h"
#include
#include
@@ -35,23 +36,17 @@ using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;
-std::string DBUpdaterUtil::GetMySqlCli()
+std::string DBUpdaterUtil::GetCorrectedMySQLExecutable()
{
if (!corrected_path().empty())
return corrected_path();
else
- {
- std::string const entry = sConfigMgr->GetStringDefault("Updates.MySqlCLIPath", "");
- if (!entry.empty())
- return entry;
- else
- return GitRevision::GetMySQLExecutable();
- }
+ return BuiltInConfig::GetMySQLExecutable();
}
bool DBUpdaterUtil::CheckExecutable()
{
- boost::filesystem::path exe(GetMySqlCli());
+ boost::filesystem::path exe(GetCorrectedMySQLExecutable());
if (!exists(exe))
{
exe.clear();
@@ -85,16 +80,6 @@ std::string& DBUpdaterUtil::corrected_path()
return path;
}
-template
-std::string DBUpdater::GetSourceDirectory()
-{
- std::string const entry = sConfigMgr->GetStringDefault("Updates.SourcePath", "");
- if (!entry.empty())
- return entry;
- else
- return GitRevision::GetSourceDirectory();
-}
-
// Auth Database
template<>
std::string DBUpdater::GetConfigEntry()
@@ -111,7 +96,8 @@ std::string DBUpdater::GetTableName()
template<>
std::string DBUpdater::GetBaseFile()
{
- return DBUpdater::GetSourceDirectory() + "/sql/base/auth_database.sql";
+ return BuiltInConfig::GetSourceDirectory() +
+ "/sql/base/auth_database.sql";
}
template<>
@@ -169,7 +155,8 @@ std::string DBUpdater::GetTableName()
template<>
std::string DBUpdater::GetBaseFile()
{
- return DBUpdater::GetSourceDirectory() + "/sql/base/characters_database.sql";
+ return BuiltInConfig::GetSourceDirectory() +
+ "/sql/base/characters_database.sql";
}
template<>
@@ -239,7 +226,7 @@ bool DBUpdater::Update(DatabaseWorkerPool& pool)
TC_LOG_INFO("sql.updates", "Updating %s database...", DBUpdater::GetTableName().c_str());
- Path const sourceDirectory(GetSourceDirectory());
+ Path const sourceDirectory(BuiltInConfig::GetSourceDirectory());
if (!is_directory(sourceDirectory))
{
@@ -410,7 +397,7 @@ void DBUpdater::ApplyFile(DatabaseWorkerPool& pool, std::string const& hos
boost::process::pipe errPipe = create_pipe();
child c = execute(run_exe(
- boost::filesystem::absolute(DBUpdaterUtil::GetMySqlCli()).generic_string()),
+ boost::filesystem::absolute(DBUpdaterUtil::GetCorrectedMySQLExecutable()).generic_string()),
set_args(args), bind_stdin(source), throw_on_error(),
bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)),
bind_stderr(file_descriptor_sink(errPipe.sink, close_handle)));
diff --git a/src/server/database/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h
index c9792ffe060..dbb897d2527 100644
--- a/src/server/database/Updater/DBUpdater.h
+++ b/src/server/database/Updater/DBUpdater.h
@@ -57,7 +57,7 @@ struct UpdateResult
class DBUpdaterUtil
{
public:
- static std::string GetMySqlCli();
+ static std::string GetCorrectedMySQLExecutable();
static bool CheckExecutable();
@@ -71,8 +71,6 @@ class DBUpdater
public:
using Path = boost::filesystem::path;
- static std::string GetSourceDirectory();
-
static inline std::string GetConfigEntry();
static inline std::string GetTableName();
diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp
index 001fdf20610..2d60cdb92ef 100644
--- a/src/server/database/Updater/UpdateFetcher.cpp
+++ b/src/server/database/Updater/UpdateFetcher.cpp
@@ -137,22 +137,33 @@ UpdateFetcher::AppliedFileStorage UpdateFetcher::ReceiveAppliedFiles() const
return map;
}
-UpdateFetcher::SQLUpdate UpdateFetcher::ReadSQLUpdate(boost::filesystem::path const& file) const
+std::string UpdateFetcher::ReadSQLUpdate(boost::filesystem::path const& file) const
{
std::ifstream in(file.c_str());
- WPFatal(in.is_open(), "Could not read an update file.");
+ if (!in.is_open())
+ {
+ TC_LOG_FATAL("sql.updates", "Failed to open the sql update \"%s\" for reading! "
+ "Stopping the server to keep the database integrity, "
+ "try to identify and solve the issue or disabled the database updater.",
+ file.generic_string().c_str());
+
+ throw UpdateException("Opening the sql update failed!");
+ }
auto update = [&in] {
std::ostringstream ss;
ss << in.rdbuf();
- return Trinity::make_unique(ss.str());
+ return ss.str();
}();
in.close();
return update;
}
-UpdateResult UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const
+UpdateResult UpdateFetcher::Update(bool const redundancyChecks,
+ bool const allowRehash,
+ bool const archivedRedundancy,
+ int32 const cleanDeadReferencesMaxCount) const
{
LocaleFileStorage const available = GetFileList();
AppliedFileStorage applied = ReceiveAppliedFiles();
@@ -198,11 +209,9 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, bool const allow
}
}
- // Read update from file
- SQLUpdate const update = ReadSQLUpdate(availableQuery.first);
-
// Calculate hash
- std::string const hash = CalculateHash(update);
+ std::string const hash =
+ CalculateHash(ReadSQLUpdate(availableQuery.first));
UpdateMode mode = MODE_APPLY;
@@ -325,11 +334,11 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, bool const allow
return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates);
}
-std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const
+std::string UpdateFetcher::CalculateHash(std::string const& query) const
{
// Calculate a Sha1 hash based on query content.
unsigned char digest[SHA_DIGEST_LENGTH];
- SHA1((unsigned char*)query->c_str(), query->length(), (unsigned char*)&digest);
+ SHA1((unsigned char*)query.c_str(), query.length(), (unsigned char*)&digest);
return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH);
}
diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h
index 32f8516413d..c87efea2b02 100644
--- a/src/server/database/Updater/UpdateFetcher.h
+++ b/src/server/database/Updater/UpdateFetcher.h
@@ -103,16 +103,16 @@ private:
typedef std::unordered_map HashToFileNameStorage;
typedef std::unordered_map AppliedFileStorage;
typedef std::vector DirectoryStorage;
- typedef std::unique_ptr SQLUpdate;
LocaleFileStorage GetFileList() const;
- void FillFileListRecursively(Path const& path, LocaleFileStorage& storage, State const state, uint32 const depth) const;
+ void FillFileListRecursively(Path const& path, LocaleFileStorage& storage,
+ State const state, uint32 const depth) const;
DirectoryStorage ReceiveIncludedDirectories() const;
AppliedFileStorage ReceiveAppliedFiles() const;
- SQLUpdate ReadSQLUpdate(Path const& file) const;
- std::string CalculateHash(SQLUpdate const& query) const;
+ std::string ReadSQLUpdate(Path const& file) const;
+ std::string CalculateHash(std::string const& query) const;
uint32 Apply(Path const& path) const;
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index a3a5e7f7663..3aadf6e59a0 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -259,36 +259,6 @@ void UnitAI::FillAISpellInfo()
}
}
-//Enable PlayerAI when charmed
-void PlayerAI::OnCharmed(bool apply)
-{
- me->IsAIEnabled = apply;
-}
-
-void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
-{
- Creature* charmer = me->GetCharmer()->ToCreature();
-
- //kill self if charm aura has infinite duration
- if (charmer->IsInEvadeMode())
- {
- Unit::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
- for (Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
- if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
- {
- charmer->Kill(me);
- return;
- }
- }
-
- if (!charmer->IsInCombat())
- me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, me->GetFollowAngle());
-
- Unit* target = me->GetVictim();
- if (!target || !charmer->IsValidAttackTarget(target))
- AttackStart(charmer->SelectNearestTargetInAttackDistance());
-}
-
SpellTargetSelector::SpellTargetSelector(Unit* caster, uint32 spellId) :
_caster(caster), _spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(sSpellMgr->GetSpellInfo(spellId), caster))
{
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 5dc5946b226..766e747d998 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -268,21 +268,4 @@ class UnitAI
UnitAI& operator=(UnitAI const& right) = delete;
};
-class PlayerAI : public UnitAI
-{
- protected:
- Player* const me;
- public:
- explicit PlayerAI(Player* player) : UnitAI((Unit*)player), me(player) { }
-
- void OnCharmed(bool apply) override;
-};
-
-class SimpleCharmedAI : public PlayerAI
-{
- public:
- void UpdateAI(uint32 diff) override;
- SimpleCharmedAI(Player* player): PlayerAI(player) { }
-};
-
#endif
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 239fda577a7..e009e2ed0b6 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -28,6 +28,7 @@ class WorldObject;
class Unit;
class Creature;
class Player;
+class PlayerAI;
class SpellInfo;
#define TIME_INTERVAL_LOOK 5000
@@ -186,6 +187,11 @@ class CreatureAI : public UnitAI
virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; }
+ // Called when a player is charmed by the creature
+ // If a PlayerAI* is returned, that AI is placed on the player instead of the default charm AI
+ // Object destruction is handled by Unit::RemoveCharmedBy
+ virtual PlayerAI* GetAIForCharmedPlayer(Player* /*who*/) { return nullptr; }
+
// intended for encounter design/debugging. do not use for other purposes. expensive.
int32 VisualizeBoundary(uint32 duration, Unit* owner=nullptr, bool fill=false) const;
virtual bool CheckInRoom();
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
new file mode 100644
index 00000000000..680ecfb9414
--- /dev/null
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2016-2016 TrinityCore
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#include "PlayerAI.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+
+enum Spells
+{
+ /* Generic */
+ SPELL_AUTO_SHOT = 75,
+ SPELL_SHOOT = 3018,
+ SPELL_THROW = 2764,
+ SPELL_SHOOT_WAND = 5019,
+
+ /* Paladin */
+ PASSIVE_ILLUMINATION = 20215,
+
+ /* Priest */
+ SPELL_SOUL_WARDING = 63574,
+ SPELL_SPIRIT_REDEMPTION = 20711,
+ SPELL_SHADOWFORM = 15473,
+
+ /* Shaman */
+ SPELL_TIDAL_FORCE = 582,
+ SPELL_MANA_TIDE_TOTEM = 590,
+ SPELL_SHA_NATURE_SWIFT = 591,
+ SPELL_STORMSTRIKE = 17364,
+
+ /* Druid */
+ SPELL_MOONKIN_FORM = 24858,
+ SPELL_SWIFTMEND = 18562,
+ SPELL_DRU_NATURE_SWIFT = 17116,
+ SPELL_TREE_OF_LIFE = 33891
+};
+
+bool PlayerAI::IsPlayerHealer(Player const* who)
+{
+ switch (who->getClass())
+ {
+ case CLASS_WARRIOR:
+ case CLASS_HUNTER:
+ case CLASS_ROGUE:
+ case CLASS_DEATH_KNIGHT:
+ case CLASS_MAGE:
+ case CLASS_WARLOCK:
+ default:
+ return false;
+ case CLASS_PALADIN:
+ return who->HasSpell(PASSIVE_ILLUMINATION);
+ case CLASS_PRIEST:
+ return who->HasSpell(SPELL_SOUL_WARDING) || who->HasSpell(SPELL_SPIRIT_REDEMPTION);
+ case CLASS_SHAMAN:
+ return who->HasSpell(SPELL_MANA_TIDE_TOTEM) || who->HasSpell(SPELL_SHA_NATURE_SWIFT) || who->HasSpell(SPELL_TIDAL_FORCE);
+ case CLASS_DRUID:
+ return who->HasSpell(SPELL_SWIFTMEND) || who->HasSpell(SPELL_DRU_NATURE_SWIFT) || who->HasSpell(SPELL_TREE_OF_LIFE);
+ }
+}
+
+bool PlayerAI::IsPlayerRangedAttacker(Player const* who)
+{
+ switch (who->getClass())
+ {
+ case CLASS_WARRIOR:
+ case CLASS_PALADIN:
+ case CLASS_ROGUE:
+ case CLASS_DEATH_KNIGHT:
+ default:
+ return false;
+ case CLASS_MAGE:
+ case CLASS_WARLOCK:
+ return true;
+ case CLASS_HUNTER:
+ {
+ // check if we have a ranged weapon equipped
+ Item const* rangedSlot = who->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
+ if (ItemTemplate const* rangedTemplate = rangedSlot ? rangedSlot->GetTemplate() : nullptr)
+ if ((1 << rangedTemplate->SubClass) & ITEM_SUBCLASS_MASK_WEAPON_RANGED)
+ return true;
+ return false;
+ }
+ case CLASS_PRIEST:
+ return who->HasSpell(SPELL_SHADOWFORM);
+ case CLASS_SHAMAN:
+ return !who->HasSpell(SPELL_STORMSTRIKE);
+ case CLASS_DRUID:
+ return who->HasSpell(SPELL_MOONKIN_FORM);
+ }
+}
+
+void PlayerAI::DoRangedAttackIfReady()
+{
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ if (!me->isAttackReady(RANGED_ATTACK))
+ return;
+
+ Unit* victim = me->GetVictim();
+ if (!victim)
+ return;
+
+ uint32 rangedAttackSpell = 0;
+
+ Item const* rangedItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
+ if (ItemTemplate const* rangedTemplate = rangedItem ? rangedItem->GetTemplate() : nullptr)
+ {
+ switch (rangedTemplate->SubClass)
+ {
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ rangedAttackSpell = SPELL_SHOOT;
+ break;
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ rangedAttackSpell = SPELL_THROW;
+ break;
+ case ITEM_SUBCLASS_WEAPON_WAND:
+ rangedAttackSpell = SPELL_SHOOT_WAND;
+ break;
+ }
+ }
+
+ if (!rangedAttackSpell)
+ return;
+
+ me->CastSpell(victim, rangedAttackSpell, TRIGGERED_CAST_DIRECTLY);
+ me->resetAttackTimer(RANGED_ATTACK);
+}
+
+void PlayerAI::DoAutoAttackIfReady()
+{
+ if (IsRangedAttacker())
+ DoRangedAttackIfReady();
+ else
+ DoMeleeAttackIfReady();
+}
+
+struct UncontrolledTargetSelectPredicate : public std::unary_function
+{
+ bool operator()(Unit const* target) const
+ {
+ return !target->HasBreakableByDamageCrowdControlAura();
+ }
+};
+Unit* SimpleCharmedPlayerAI::SelectAttackTarget() const
+{
+ if (Unit* charmer = me->GetCharmer())
+ return charmer->IsAIEnabled ? charmer->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, UncontrolledTargetSelectPredicate()) : charmer->GetVictim();
+ return nullptr;
+}
+
+void SimpleCharmedPlayerAI::UpdateAI(const uint32 /*diff*/)
+{
+ Creature* charmer = me->GetCharmer() ? me->GetCharmer()->ToCreature() : nullptr;
+ if (!charmer)
+ return;
+
+ //kill self if charm aura has infinite duration
+ if (charmer->IsInEvadeMode())
+ {
+ Player::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
+ for (Player::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
+ if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
+ {
+ me->Kill(me);
+ return;
+ }
+ }
+
+ if (charmer->IsInCombat())
+ {
+ Unit* target = me->GetVictim();
+ if (!target || !charmer->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura())
+ {
+ target = SelectAttackTarget();
+ if (!target)
+ return;
+
+ if (IsRangedAttacker())
+ AttackStartCaster(target, 28.0f);
+ else
+ AttackStart(target);
+ }
+ DoAutoAttackIfReady();
+ }
+ else
+ {
+ me->AttackStop();
+ me->CastStop();
+ me->StopMoving();
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ }
+}
+
+void SimpleCharmedPlayerAI::OnCharmed(bool apply)
+{
+ if (apply)
+ {
+ me->CastStop();
+ me->AttackStop();
+ }
+ else
+ {
+ me->CastStop();
+ me->AttackStop();
+ // @todo only voluntary movement (don't cancel stuff like death grip or charge mid-animation)
+ me->GetMotionMaster()->Clear();
+ me->StopMoving();
+ }
+}
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h
new file mode 100644
index 00000000000..1820bcf11c0
--- /dev/null
+++ b/src/server/game/AI/PlayerAI/PlayerAI.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016-2016 TrinityCore
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#ifndef TRINITY_PLAYERAI_H
+#define TRINITY_PLAYERAI_H
+
+#include "UnitAI.h"
+#include "Player.h"
+#include "Creature.h"
+
+class PlayerAI : public UnitAI
+{
+ public:
+ explicit PlayerAI(Player* player) : UnitAI(static_cast(player)), me(player), _isSelfHealer(PlayerAI::IsPlayerHealer(player)), _isSelfRangedAttacker(PlayerAI::IsPlayerRangedAttacker(player)) { }
+
+ void OnCharmed(bool /*apply*/) override { } // charm AI application for players is handled by Unit::SetCharmedBy / Unit::RemoveCharmedBy
+
+ // helper functions to determine player info
+ static bool IsPlayerHealer(Player const* who);
+ bool IsHealer(Player const* who = nullptr) const { return (!who || who == me) ? _isSelfHealer : IsPlayerHealer(who); }
+ static bool IsPlayerRangedAttacker(Player const* who);
+ bool IsRangedAttacker(Player const* who = nullptr) const { return (!who || who == me) ? _isSelfRangedAttacker : IsPlayerRangedAttacker(who); }
+
+ protected:
+ Player* const me;
+ void SetIsRangedAttacker(bool state) { _isSelfRangedAttacker = state; } // this allows overriding of the default ranged attacker detection
+
+ virtual Unit* SelectAttackTarget() const { return me->GetCharmer() ? me->GetCharmer()->GetVictim() : nullptr; }
+ void DoRangedAttackIfReady();
+ void DoAutoAttackIfReady();
+
+ private:
+ bool _isSelfHealer;
+ bool _isSelfRangedAttacker;
+};
+
+class SimpleCharmedPlayerAI : public PlayerAI
+{
+ public:
+ SimpleCharmedPlayerAI(Player* player) : PlayerAI(player) { }
+ void UpdateAI(uint32 diff) override;
+ void OnCharmed(bool apply) override;
+ Unit* SelectAttackTarget() const override;
+};
+
+#endif
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 0d5ed677b9c..da4408fc26a 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2340,6 +2340,21 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
}
}
+ case SMART_ACTION_SET_CORPSE_DELAY:
+ {
+ ObjectList* targets = GetTargets(e, unit);
+ if (!targets)
+ break;
+
+ for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
+ {
+ if (IsCreature(*itr))
+ (*itr)->ToCreature()->SetCorpseDelay(e.action.corpseDelay.timer);
+ }
+
+ delete targets;
+ break;
+ }
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index feede2deb59..7963414582e 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -1251,6 +1251,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_REMOVE_GO_FLAG:
case SMART_ACTION_SUMMON_CREATURE_GROUP:
case SMART_ACTION_RISE_UP:
+ case SMART_ACTION_SET_CORPSE_DELAY:
break;
default:
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 6e1fb5d81bb..c7359967008 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -552,8 +552,9 @@ enum SMART_ACTION
SMART_ACTION_START_CLOSEST_WAYPOINT = 113, // wp1, wp2, wp3, wp4, wp5, wp6, wp7
SMART_ACTION_RISE_UP = 114, // distance
SMART_ACTION_RANDOM_SOUND = 115, // soundId1, soundId2, soundId3, soundId4, soundId5, onlySelf
+ SMART_ACTION_SET_CORPSE_DELAY = 116, // timer
- SMART_ACTION_END = 116
+ SMART_ACTION_END = 117
};
struct SmartAction
@@ -1042,6 +1043,11 @@ struct SmartAction
uint32 onlySelf;
} randomSound;
+ struct
+ {
+ uint32 timer;
+ } corpseDelay;
+
//! Note for any new future actions
//! All parameters must have type uint32
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 8fcab9b7754..6b1837aa125 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -446,7 +446,7 @@ void AccountMgr::LoadRBAC()
while (result->NextRow());
TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions");
- result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realmHandle.Index);
+ result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realm.Id.Realm);
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty.");
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index b7015d750ea..11ddea00a06 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -679,8 +679,8 @@ enum RBACPermissions
RBAC_PERM_COMMAND_WP_UNLOAD = 772,
RBAC_PERM_COMMAND_WP_RELOAD = 773,
RBAC_PERM_COMMAND_WP_SHOW = 774,
- RBAC_PERM_COMMAND_MODIFY_CURRENCY = 775, // only 4.3.4
- RBAC_PERM_COMMAND_DEBUG_PHASE = 776, // only 4.3.4
+ RBAC_PERM_COMMAND_MODIFY_CURRENCY = 775, // only 6.x
+ RBAC_PERM_COMMAND_DEBUG_PHASE = 776, // only 6.x
RBAC_PERM_COMMAND_MAILBOX = 777,
RBAC_PERM_COMMAND_AHBOT = 778,
RBAC_PERM_COMMAND_AHBOT_ITEMS = 779,
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 16c65df4e7c..748fe343256 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -130,7 +130,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
else
{
bidderAccId = sObjectMgr->GetPlayerAccountIdByGUID(bidderGuid);
- logGmTrade = AccountMgr::HasPermission(bidderAccId, rbac::RBAC_PERM_LOG_GM_TRADE, realmHandle.Index);
+ logGmTrade = AccountMgr::HasPermission(bidderAccId, rbac::RBAC_PERM_LOG_GM_TRADE, realm.Id.Realm);
if (logGmTrade && !sObjectMgr->GetPlayerNameByGUID(bidderGuid, bidderName))
bidderName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 7930c899762..2162b5590a2 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -108,6 +108,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Addons
${CMAKE_CURRENT_SOURCE_DIR}/AI
${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI
+ ${CMAKE_CURRENT_SOURCE_DIR}/AI/PlayerAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts
${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse
@@ -198,6 +199,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Realm
${MYSQL_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
${VALGRIND_INCLUDE_DIR}
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 7c1e371f933..9f8685422e9 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -109,7 +109,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac
if (target)
target_sec = target->GetSecurity();
else if (target_account)
- target_sec = AccountMgr::GetSecurity(target_account, realmHandle.Index);
+ target_sec = AccountMgr::GetSecurity(target_account, realm.Id.Realm);
else
return true; // caller must report error for (target == nullptr && target_account == 0)
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 7a8cfb8a391..d2c97458b56 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -335,7 +335,7 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* attacker, HostileR
{
// current victim is a second choice target, so don't compare threat with it below
if (currentRef == currentVictim)
- currentVictim = NULL;
+ currentVictim = nullptr;
++iter;
continue;
}
@@ -437,12 +437,15 @@ void ThreatManager::_addThreat(Unit* victim, float threat)
if (!ref) // there was no ref => create a new one
{
+ bool isFirst = iThreatContainer.empty();
// threat has to be 0 here
HostileReference* hostileRef = new HostileReference(victim, this, 0);
iThreatContainer.addReference(hostileRef);
hostileRef->addThreat(threat); // now we add the real threat
if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->IsGameMaster())
hostileRef->setOnlineOfflineState(false); // GM is always offline
+ else if (isFirst)
+ setCurrentVictim(hostileRef);
}
}
diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h
index 7d20e99c128..0f4efdbeab9 100644
--- a/src/server/game/Combat/ThreatManager.h
+++ b/src/server/game/Combat/ThreatManager.h
@@ -169,7 +169,7 @@ class ThreatContainer
HostileReference* getMostHated() const
{
- return iThreatList.empty() ? NULL : iThreatList.front();
+ return iThreatList.empty() ? nullptr : iThreatList.front();
}
HostileReference* getReferenceByTarget(Unit* victim) const;
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index e682ff8332f..fc4ed6f864e 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -102,7 +102,8 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND
{ "Health Pct", true, true, false },
{ "Realm Achievement", true, false, false },
{ "In Water", false, false, false },
- { "Terrain Swap", true, false, false }
+ { "Terrain Swap", true, false, false },
+ { "Sit/stand state", true, true, false }
};
// Checks if object meets the condition
@@ -439,6 +440,19 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const
condMeets = unit->IsInWater();
break;
}
+ case CONDITION_STAND_STATE:
+ {
+ if (Unit* unit = object->ToUnit())
+ {
+ if (ConditionValue1 == 0)
+ condMeets = (unit->getStandState() == ConditionValue2);
+ else if (ConditionValue2 == 0)
+ condMeets = unit->IsStandState();
+ else if (ConditionValue2 == 1)
+ condMeets = unit->IsSitState();
+ }
+ break;
+ }
default:
condMeets = false;
break;
@@ -617,6 +631,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition() const
case CONDITION_IN_WATER:
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
break;
+ case CONDITION_STAND_STATE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
@@ -839,7 +856,6 @@ bool ConditionMgr::IsObjectMeetingNotGroupedConditions(ConditionSourceType sourc
bool ConditionMgr::HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const
{
- ConditionContainer spellCond;
if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
if (ConditionStore[sourceType].find(entry) != ConditionStore[sourceType].end())
return true;
@@ -1738,7 +1754,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
{
if (cond->ConditionType == CONDITION_NONE || cond->ConditionType >= CONDITION_MAX)
{
- TC_LOG_ERROR("sql.sql", "%s Invalid ConditionType in `condition` table, ignoring.", cond->ToString().c_str());
+ TC_LOG_ERROR("sql.sql", "%s Invalid ConditionType in `condition` table, ignoring.", cond->ToString(true).c_str());
return false;
}
@@ -2191,6 +2207,28 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
}
case CONDITION_IN_WATER:
break;
+ case CONDITION_STAND_STATE:
+ {
+ bool valid = false;
+ switch (cond->ConditionValue1)
+ {
+ case 0:
+ valid = cond->ConditionValue2 <= UNIT_STAND_STATE_SUBMERGED;
+ break;
+ case 1:
+ valid = cond->ConditionValue2 <= 1;
+ break;
+ default:
+ valid = false;
+ break;
+ }
+ if (!valid)
+ {
+ TC_LOG_ERROR("sql.sql", "%s has non-existing stand state (%u,%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1, cond->ConditionValue2);
+ return false;
+ }
+ break;
+ }
default:
break;
}
@@ -2212,17 +2250,17 @@ void ConditionMgr::LogUselessConditionValue(Condition* cond, uint8 index, uint32
void ConditionMgr::Clean()
{
- for (ConditionReferenceContainer::iterator it = ConditionReferenceStore.begin(); it != ConditionReferenceStore.end(); ++it)
- for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
- delete *i;
+ for (ConditionReferenceContainer::iterator itr = ConditionReferenceStore.begin(); itr != ConditionReferenceStore.end(); ++itr)
+ for (ConditionContainer::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ delete *it;
ConditionReferenceStore.clear();
for (uint32 i = 0; i < CONDITION_SOURCE_TYPE_MAX; ++i)
{
for (ConditionsByEntryMap::iterator it = ConditionStore[i].begin(); it != ConditionStore[i].end(); ++it)
- for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
- delete *i;
+ for (ConditionContainer::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr)
+ delete *itr;
ConditionStore[i].clear();
}
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index bd69ec7e27c..afc221fc0d7 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -72,7 +72,8 @@ enum ConditionTypes
CONDITION_REALM_ACHIEVEMENT = 39, // achievement_id 0 0 true if realm achievement is complete
CONDITION_IN_WATER = 40, // 0 0 0 true if unit in water
CONDITION_TERRAIN_SWAP = 41, // terrainSwap 0 0 true if object is in terrainswap
- CONDITION_MAX = 42 // MAX
+ CONDITION_STAND_STATE = 42, // stateType state 0 true if unit matches specified sitstate (0,x: has exactly state x; 1,0: any standing state; 1,1: any sitting state;)
+ CONDITION_MAX = 43 // MAX
};
/*! Documentation on implementing a new ConditionSourceType:
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 4c3f55ec5fc..cd9d96caed7 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -579,7 +579,8 @@ void Creature::Update(uint32 diff)
IsAIEnabled = true;
if (!IsInEvadeMode() && LastCharmerGUID)
if (Unit* charmer = ObjectAccessor::GetUnit(*this, LastCharmerGUID))
- i_AI->AttackStart(charmer);
+ if (CanStartAttack(charmer, true))
+ i_AI->AttackStart(charmer);
LastCharmerGUID.Clear();
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index fbf68e69152..c51a02ba1e1 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -487,7 +487,7 @@ class Creature : public Unit, public GridObject, public MapObject
bool AIM_Initialize(CreatureAI* ai = NULL);
void Motion_Initialize();
- CreatureAI* AI() const { return (CreatureAI*)i_AI; }
+ CreatureAI* AI() const { return reinterpret_cast(i_AI); }
SpellSchoolMask GetMeleeDamageSchoolMask() const override { return m_meleeDamageSchoolMask; }
void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); }
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index faa208fe79e..f8219dc5833 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -228,6 +228,11 @@ void TempSummon::InitSummon()
}
}
+void TempSummon::UpdateObjectVisibilityOnCreate()
+{
+ WorldObject::UpdateObjectVisibility(true);
+}
+
void TempSummon::SetTempSummonType(TempSummonType type)
{
m_type = type;
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index de4cc87e6fd..e18b83199dd 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -45,6 +45,7 @@ class TempSummon : public Creature
void Update(uint32 time) override;
virtual void InitStats(uint32 lifetime);
virtual void InitSummon();
+ void UpdateObjectVisibilityOnCreate() override;
virtual void UnSummon(uint32 msTime = 0);
void RemoveFromWorld() override;
void SetTempSummonType(TempSummonType type);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 3ed06be91b0..51eb2cd28ba 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2053,7 +2053,9 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
AddToMap(summon->ToCreature());
summon->InitSummon();
- //ObjectAccessor::UpdateObjectVisibility(summon);
+ // call MoveInLineOfSight for nearby creatures
+ Trinity::AIRelocationNotifier notifier(*summon);
+ summon->VisitNearbyObject(GetVisibilityRange(), notifier);
return summon;
}
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 2f6b506b55b..40defe76274 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -589,6 +589,11 @@ class WorldObject : public Object, public WorldLocation
void DestroyForNearbyPlayers();
virtual void UpdateObjectVisibility(bool forced = true);
+ virtual void UpdateObjectVisibilityOnCreate()
+ {
+ UpdateObjectVisibility(true);
+ }
+
void BuildUpdate(UpdateDataMapType&) override;
void AddToObjectUpdate() override;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index b2dcd7fbd8a..85d7dabb511 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1233,10 +1233,14 @@ void Player::Update(uint32 p_time)
UpdateAfkReport(now);
- if (IsCharmed())
- if (Unit* charmer = GetCharmer())
- if (charmer->GetTypeId() == TYPEID_UNIT && charmer->IsAlive())
- UpdateCharmedAI();
+ if (IsAIEnabled && GetAI())
+ GetAI()->UpdateAI(p_time);
+ else if (NeedChangeAI)
+ {
+ UpdateCharmAI();
+ NeedChangeAI = false;
+ IsAIEnabled = (GetAI() != nullptr);
+ }
// Update items that have just a limited lifetime
if (now > m_Last_tick)
@@ -14067,14 +14071,14 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
if (!optionBroadcastText)
{
/// Find localizations from database.
- if (GossipMenuItemsLocale const* gossipMenuLocale = sObjectMgr->GetGossipMenuItemsLocale(MAKE_PAIR32(menuId, menuId)))
+ if (GossipMenuItemsLocale const* gossipMenuLocale = sObjectMgr->GetGossipMenuItemsLocale(MAKE_PAIR32(menuId, itr->second.OptionIndex)))
ObjectMgr::GetLocaleString(gossipMenuLocale->OptionText, locale, strOptionText);
}
if (!boxBroadcastText)
{
/// Find localizations from database.
- if (GossipMenuItemsLocale const* gossipMenuLocale = sObjectMgr->GetGossipMenuItemsLocale(MAKE_PAIR32(menuId, menuId)))
+ if (GossipMenuItemsLocale const* gossipMenuLocale = sObjectMgr->GetGossipMenuItemsLocale(MAKE_PAIR32(menuId, itr->second.OptionIndex)))
ObjectMgr::GetLocaleString(gossipMenuLocale->BoxText, locale, strBoxText);
}
}
@@ -24619,38 +24623,6 @@ bool Player::isTotalImmunity()
return false;
}
-void Player::UpdateCharmedAI()
-{
- //This should only called in Player::Update
- Creature* charmer = GetCharmer()->ToCreature();
-
- //kill self if charm aura has infinite duration
- if (charmer->IsInEvadeMode())
- {
- AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
- for (AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
- if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
- {
- charmer->DealDamage(this, GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- return;
- }
- }
-
- if (!charmer->IsInCombat())
- GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
-
- Unit* target = GetVictim();
- if (!target || !charmer->IsValidAttackTarget(target))
- {
- target = charmer->SelectNearestTarget();
- if (!target)
- return;
-
- GetMotionMaster()->MoveChase(target);
- Attack(target, true);
- }
-}
-
uint32 Player::GetRuneTypeBaseCooldown(RuneType runeType) const
{
float cooldown = RUNE_BASE_COOLDOWN;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 12c3c033fe8..f476243cd64 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -55,6 +55,7 @@ class PlayerMenu;
class PlayerSocial;
class SpellCastTargets;
class UpdateMask;
+class PlayerAI;
struct CharacterCustomizeInfo;
@@ -1171,6 +1172,8 @@ class Player : public Unit, public GridObject
explicit Player(WorldSession* session);
~Player();
+ PlayerAI* AI() const { return reinterpret_cast(i_AI); }
+
void CleanupsBeforeDelete(bool finalCleanup = true) override;
void AddToWorld() override;
@@ -2769,8 +2772,6 @@ class Player : public Unit, public GridObject
MapReference m_mapRef;
- void UpdateCharmedAI();
-
uint32 m_lastFallTime;
float m_lastFallZ;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 0cebf955ef1..eaa96f2add4 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -44,6 +44,7 @@
#include "PetAI.h"
#include "Pet.h"
#include "Player.h"
+#include "PlayerAI.h"
#include "QuestDef.h"
#include "ReputationMgr.h"
#include "SpellAuraEffects.h"
@@ -3521,6 +3522,77 @@ void Unit::RemoveAura(Aura* aura, AuraRemoveMode mode)
RemoveAura(aurApp, mode);
}
+void Unit::RemoveAppliedAuras(std::function const& check)
+{
+ for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
+ {
+ if (check(iter->second))
+ {
+ RemoveAura(iter);
+ continue;
+ }
+ ++iter;
+ }
+}
+
+void Unit::RemoveOwnedAuras(std::function const& check)
+{
+ for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
+ {
+ if (check(iter->second))
+ {
+ RemoveOwnedAura(iter);
+ continue;
+ }
+ ++iter;
+ }
+}
+
+void Unit::RemoveAppliedAuras(uint32 spellId, std::function const& check)
+{
+ for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);)
+ {
+ if (check(iter->second))
+ {
+ RemoveAura(iter);
+ continue;
+ }
+ ++iter;
+ }
+}
+
+void Unit::RemoveOwnedAuras(uint32 spellId, std::function const& check)
+{
+ for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);)
+ {
+ if (check(iter->second))
+ {
+ RemoveOwnedAura(iter);
+ continue;
+ }
+ ++iter;
+ }
+}
+
+void Unit::RemoveAurasByType(AuraType auraType, std::function const& check)
+{
+ for (AuraEffectList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();)
+ {
+ Aura* aura = (*iter)->GetBase();
+ AuraApplication * aurApp = aura->GetApplicationOfTarget(GetGUID());
+ ASSERT(aurApp);
+
+ ++iter;
+ if (check(aurApp))
+ {
+ uint32 removedAuras = m_removedAurasCount;
+ RemoveAura(aurApp);
+ if (m_removedAurasCount > removedAuras + 1)
+ iter = m_modAuras[auraType].begin();
+ }
+ }
+}
+
void Unit::RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID, uint8 reqEffMask, AuraRemoveMode removeMode)
{
for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);)
@@ -7605,10 +7677,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (GetTypeId() == TYPEID_UNIT && !IsPet())
{
// should not let player enter combat by right clicking target - doesn't helps
+ AddThreat(victim, 0.0f);
SetInCombatWith(victim);
if (victim->GetTypeId() == TYPEID_PLAYER)
victim->SetInCombatWith(this);
- AddThreat(victim, 0.0f);
ToCreature()->SendAIReaction(AI_REACTION_HOSTILE);
ToCreature()->CallAssistance();
@@ -7852,7 +7924,7 @@ Unit* Unit::GetCharmer() const
if (ObjectGuid charmerGUID = GetCharmerGUID())
return ObjectAccessor::GetUnit(*this, charmerGUID);
- return NULL;
+ return nullptr;
}
Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() const
@@ -10798,7 +10870,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
if (Creature* creature = ToCreature())
{
uint32 immuneMask = creature->GetCreatureTemplate()->MechanicImmuneMask;
- if (immuneMask & (1 << MECHANIC_SNARE) || immuneMask & (1 << MECHANIC_DAZE))
+ if (immuneMask & (1 << (MECHANIC_SNARE - 1)) || immuneMask & (1 << (MECHANIC_DAZE - 1)))
break;
}
@@ -12084,28 +12156,76 @@ void Unit::CleanupsBeforeDelete(bool finalCleanup)
void Unit::UpdateCharmAI()
{
- if (GetTypeId() == TYPEID_PLAYER)
- return;
-
- if (i_disabledAI) // disabled AI must be primary AI
+ switch (GetTypeId())
{
- if (!IsCharmed())
- {
- delete i_AI;
- i_AI = i_disabledAI;
- i_disabledAI = NULL;
- }
- }
- else
- {
- if (IsCharmed())
- {
- i_disabledAI = i_AI;
- if (isPossessed() || IsVehicle())
- i_AI = new PossessedAI(ToCreature());
+ case TYPEID_UNIT:
+ if (i_disabledAI) // disabled AI must be primary AI
+ {
+ if (!IsCharmed())
+ {
+ delete i_AI;
+ i_AI = i_disabledAI;
+ i_disabledAI = nullptr;
+ }
+ }
else
- i_AI = new PetAI(ToCreature());
+ {
+ if (IsCharmed())
+ {
+ i_disabledAI = i_AI;
+ if (isPossessed() || IsVehicle())
+ i_AI = new PossessedAI(ToCreature());
+ else
+ i_AI = new PetAI(ToCreature());
+ }
+ }
+ break;
+ case TYPEID_PLAYER:
+ {
+ if (IsCharmed()) // if we are currently being charmed, then we should apply charm AI
+ {
+ i_disabledAI = i_AI;
+
+ UnitAI* newAI = nullptr;
+ // first, we check if the creature's own AI specifies an override playerai for its owned players
+ if (Unit* charmer = GetCharmer())
+ {
+ if (Creature* creatureCharmer = charmer->ToCreature())
+ {
+ if (PlayerAI* charmAI = creatureCharmer->IsAIEnabled ? creatureCharmer->AI()->GetAIForCharmedPlayer(ToPlayer()) : nullptr)
+ newAI = charmAI;
+ }
+ else
+ {
+ TC_LOG_ERROR("misc", "Attempt to assign charm AI to player %s who is charmed by non-creature %s.", GetGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str());
+ }
+ }
+ if (!newAI) // otherwise, we default to the generic one
+ newAI = new SimpleCharmedPlayerAI(ToPlayer());
+ i_AI = newAI;
+ }
+ else
+ {
+ if (i_AI)
+ {
+ // we allow the charmed PlayerAI to clean up
+ i_AI->OnCharmed(false);
+ // then delete it
+ delete i_AI;
+ }
+ else
+ {
+ TC_LOG_ERROR("misc", "Attempt to remove charm AI from player %s who doesn't currently have charm AI.", GetGUID().ToString().c_str());
+ }
+ // and restore our previous PlayerAI (if we had one)
+ i_AI = i_disabledAI;
+ i_disabledAI = nullptr;
+ // IsAIEnabled gets handled in the caller
+ }
+ break;
}
+ default:
+ TC_LOG_ERROR("misc", "Attempt to update charm AI for unit %s, which is neither player nor creature.", GetGUID().ToString().c_str());
}
}
@@ -14360,11 +14480,17 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
ToCreature()->AI()->OnCharmed(true);
GetMotionMaster()->MoveIdle();
}
- else
+ else if (Player* player = ToPlayer())
{
- Player* player = ToPlayer();
if (player->isAFK())
player->ToggleAFK();
+
+ if (charmer->GetTypeId() == TYPEID_UNIT) // we are charmed by a creature
+ {
+ // change AI to charmed AI on next Update tick
+ NeedChangeAI = true;
+ IsAIEnabled = false;
+ }
player->SetClientControl(this, false);
}
@@ -14522,7 +14648,14 @@ void Unit::RemoveCharmedBy(Unit* charmer)
}
if (Player* player = ToPlayer())
+ {
+ if (charmer->GetTypeId() == TYPEID_UNIT) // charmed by a creature, this means we had PlayerAI
+ {
+ NeedChangeAI = true;
+ IsAIEnabled = false;
+ }
player->SetClientControl(this, true);
+ }
// a guardian should always have charminfo
if (playerCharmer && this != charmer->GetFirstControlled())
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 4700a483a74..5c1e94872c1 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1719,6 +1719,16 @@ class Unit : public WorldObject
void RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(Aura* aur, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
+ // Convenience methods removing auras by predicate
+ void RemoveAppliedAuras(std::function const& check);
+ void RemoveOwnedAuras(std::function const& check);
+
+ // Optimized overloads taking advantage of map key
+ void RemoveAppliedAuras(uint32 spellId, std::function const& check);
+ void RemoveOwnedAuras(uint32 spellId, std::function const& check);
+
+ void RemoveAurasByType(AuraType auraType, std::function const& check);
+
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
void RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, ObjectGuid casterGUID, Unit* dispeller, uint8 chargesRemoved = 1);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 2aed865baa3..ff76321e7b0 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -654,13 +654,13 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
stmt->setUInt32(0, GetAccountId());
- stmt->setUInt32(1, realmHandle.Index);
+ stmt->setUInt32(1, realm.Id.Realm);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS);
stmt->setUInt32(0, createInfo->CharCount);
stmt->setUInt32(1, GetAccountId());
- stmt->setUInt32(2, realmHandle.Index);
+ stmt->setUInt32(2, realm.Id.Realm);
trans->Append(stmt);
LoginDatabase.CommitTransaction(trans);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 13216c6d489..95d0a88824c 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -599,7 +599,7 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std
team = Player::TeamForRace(fields[1].GetUInt8());
friendAccountId = fields[2].GetUInt32();
- if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmHandle.Index)))
+ if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
{
if (friendGuid)
{
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 7fe951e323d..333a9366695 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -590,7 +590,7 @@ bool Map::AddToMap(T* obj)
//something, such as vehicle, needs to be update immediately
//also, trigger needs to cast spell, if not update, cannot see visual
- obj->UpdateObjectVisibility(true);
+ obj->UpdateObjectVisibilityOnCreate();
return true;
}
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 82f03f537f9..ccc4c39ccd1 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -18,699 +18,28 @@
#include "ScriptLoader.h"
#include "World.h"
-// spells
-void AddSC_deathknight_spell_scripts();
-void AddSC_druid_spell_scripts();
-void AddSC_generic_spell_scripts();
-void AddSC_hunter_spell_scripts();
-void AddSC_mage_spell_scripts();
-void AddSC_paladin_spell_scripts();
-void AddSC_priest_spell_scripts();
-void AddSC_rogue_spell_scripts();
-void AddSC_shaman_spell_scripts();
-void AddSC_warlock_spell_scripts();
-void AddSC_warrior_spell_scripts();
-void AddSC_quest_spell_scripts();
-void AddSC_item_spell_scripts();
-void AddSC_holiday_spell_scripts();
-
+void AddSpellsScripts();
void AddSC_SmartScripts();
-
-//Commands
-void AddSC_account_commandscript();
-void AddSC_achievement_commandscript();
-void AddSC_ahbot_commandscript();
-void AddSC_arena_commandscript();
-void AddSC_ban_commandscript();
-void AddSC_battlenet_account_commandscript();
-void AddSC_bf_commandscript();
-void AddSC_cast_commandscript();
-void AddSC_character_commandscript();
-void AddSC_cheat_commandscript();
-void AddSC_debug_commandscript();
-void AddSC_deserter_commandscript();
-void AddSC_disable_commandscript();
-void AddSC_event_commandscript();
-void AddSC_gm_commandscript();
-void AddSC_go_commandscript();
-void AddSC_gobject_commandscript();
-void AddSC_group_commandscript();
-void AddSC_guild_commandscript();
-void AddSC_honor_commandscript();
-void AddSC_instance_commandscript();
-void AddSC_learn_commandscript();
-void AddSC_lfg_commandscript();
-void AddSC_list_commandscript();
-void AddSC_lookup_commandscript();
-void AddSC_message_commandscript();
-void AddSC_misc_commandscript();
-void AddSC_mmaps_commandscript();
-void AddSC_modify_commandscript();
-void AddSC_npc_commandscript();
-void AddSC_pet_commandscript();
-void AddSC_quest_commandscript();
-void AddSC_rbac_commandscript();
-void AddSC_reload_commandscript();
-void AddSC_reset_commandscript();
-void AddSC_send_commandscript();
-void AddSC_server_commandscript();
-void AddSC_tele_commandscript();
-void AddSC_ticket_commandscript();
-void AddSC_titles_commandscript();
-void AddSC_wp_commandscript();
+void AddCommandsScripts();
#ifdef SCRIPTS
-//world
-void AddSC_areatrigger_scripts();
-void AddSC_emerald_dragons();
-void AddSC_generic_creature();
-void AddSC_go_scripts();
-void AddSC_guards();
-void AddSC_item_scripts();
-void AddSC_npc_professions();
-void AddSC_npc_innkeeper();
-void AddSC_npcs_special();
-void AddSC_achievement_scripts();
-void AddSC_action_ip_logger();
-void AddSC_duel_reset();
-
-//eastern kingdoms
-void AddSC_alterac_valley(); //Alterac Valley
-void AddSC_boss_balinda();
-void AddSC_boss_drekthar();
-void AddSC_boss_galvangar();
-void AddSC_boss_vanndar();
-void AddSC_boss_alizabal(); //Baradin Hold
-void AddSC_boss_occuthar();
-void AddSC_boss_pit_lord_argaloth();
-void AddSC_instance_baradin_hold();
-void AddSC_boss_romogg_bonecrusher(); //Blackrock Caverns
-void AddSC_boss_corla();
-void AddSC_boss_karsh_steelbender();
-void AddSC_boss_beauty();
-void AddSC_boss_ascendant_lord_obsidius();
-void AddSC_blackrock_caverns();
-void AddSC_instance_blackrock_caverns();
-void AddSC_blackrock_depths(); //Blackrock Depths
-void AddSC_boss_ambassador_flamelash();
-void AddSC_boss_draganthaurissan();
-void AddSC_boss_general_angerforge();
-void AddSC_boss_high_interrogator_gerstahn();
-void AddSC_boss_magmus();
-void AddSC_boss_moira_bronzebeard();
-void AddSC_boss_tomb_of_seven();
-void AddSC_instance_blackrock_depths();
-void AddSC_boss_drakkisath(); //Blackrock Spire
-void AddSC_boss_halycon();
-void AddSC_boss_highlordomokk();
-void AddSC_boss_mothersmolderweb();
-void AddSC_boss_overlordwyrmthalak();
-void AddSC_boss_shadowvosh();
-void AddSC_boss_thebeast();
-void AddSC_boss_warmastervoone();
-void AddSC_boss_quatermasterzigris();
-void AddSC_boss_pyroguard_emberseer();
-void AddSC_boss_gyth();
-void AddSC_boss_rend_blackhand();
-void AddSC_boss_gizrul_the_slavener();
-void AddSC_boss_urok_doomhowl();
-void AddSC_boss_lord_valthalak();
-void AddSC_instance_blackrock_spire();
-void AddSC_boss_razorgore(); //Blackwing lair
-void AddSC_boss_vaelastrasz();
-void AddSC_boss_broodlord();
-void AddSC_boss_firemaw();
-void AddSC_boss_ebonroc();
-void AddSC_boss_flamegor();
-void AddSC_boss_chromaggus();
-void AddSC_boss_nefarian();
-void AddSC_instance_blackwing_lair();
-void AddSC_deadmines(); //Deadmines
-void AddSC_instance_deadmines();
-void AddSC_boss_mr_smite();
-void AddSC_gnomeregan(); //Gnomeregan
-void AddSC_instance_gnomeregan();
-void AddSC_boss_attumen(); //Karazhan
-void AddSC_boss_curator();
-void AddSC_boss_maiden_of_virtue();
-void AddSC_boss_shade_of_aran();
-void AddSC_boss_malchezaar();
-void AddSC_boss_terestian_illhoof();
-void AddSC_boss_moroes();
-void AddSC_bosses_opera();
-void AddSC_boss_netherspite();
-void AddSC_instance_karazhan();
-void AddSC_karazhan();
-void AddSC_boss_nightbane();
-void AddSC_boss_felblood_kaelthas(); // Magister's Terrace
-void AddSC_boss_selin_fireheart();
-void AddSC_boss_vexallus();
-void AddSC_boss_priestess_delrissa();
-void AddSC_instance_magisters_terrace();
-void AddSC_magisters_terrace();
-void AddSC_boss_lucifron(); //Molten core
-void AddSC_boss_magmadar();
-void AddSC_boss_gehennas();
-void AddSC_boss_garr();
-void AddSC_boss_baron_geddon();
-void AddSC_boss_shazzrah();
-void AddSC_boss_golemagg();
-void AddSC_boss_sulfuron();
-void AddSC_boss_majordomo();
-void AddSC_boss_ragnaros();
-void AddSC_instance_molten_core();
-void AddSC_instance_ragefire_chasm(); //Ragefire Chasm
-void AddSC_the_scarlet_enclave(); //Scarlet Enclave
-void AddSC_the_scarlet_enclave_c1();
-void AddSC_the_scarlet_enclave_c2();
-void AddSC_the_scarlet_enclave_c5();
-void AddSC_boss_arcanist_doan(); //Scarlet Monastery
-void AddSC_boss_azshir_the_sleepless();
-void AddSC_boss_bloodmage_thalnos();
-void AddSC_boss_headless_horseman();
-void AddSC_boss_herod();
-void AddSC_boss_high_inquisitor_fairbanks();
-void AddSC_boss_houndmaster_loksey();
-void AddSC_boss_interrogator_vishas();
-void AddSC_boss_scorn();
-void AddSC_instance_scarlet_monastery();
-void AddSC_boss_mograine_and_whitemane();
-void AddSC_boss_darkmaster_gandling(); //Scholomance
-void AddSC_boss_death_knight_darkreaver();
-void AddSC_boss_theolenkrastinov();
-void AddSC_boss_illuciabarov();
-void AddSC_boss_instructormalicia();
-void AddSC_boss_jandicebarov();
-void AddSC_boss_kormok();
-void AddSC_boss_lordalexeibarov();
-void AddSC_boss_lorekeeperpolkelt();
-void AddSC_boss_rasfrost();
-void AddSC_boss_theravenian();
-void AddSC_boss_vectus();
-void AddSC_boss_kirtonos_the_herald();
-void AddSC_instance_scholomance();
-void AddSC_shadowfang_keep(); //Shadowfang keep
-void AddSC_instance_shadowfang_keep();
-void AddSC_boss_magistrate_barthilas(); //Stratholme
-void AddSC_boss_maleki_the_pallid();
-void AddSC_boss_nerubenkan();
-void AddSC_boss_cannon_master_willey();
-void AddSC_boss_baroness_anastari();
-void AddSC_boss_ramstein_the_gorger();
-void AddSC_boss_timmy_the_cruel();
-void AddSC_boss_postmaster_malown();
-void AddSC_boss_baron_rivendare();
-void AddSC_boss_dathrohan_balnazzar();
-void AddSC_boss_order_of_silver_hand();
-void AddSC_instance_stratholme();
-void AddSC_stratholme();
-void AddSC_sunken_temple(); // Sunken Temple
-void AddSC_instance_sunken_temple();
-void AddSC_instance_sunwell_plateau(); //Sunwell Plateau
-void AddSC_boss_kalecgos();
-void AddSC_boss_brutallus();
-void AddSC_boss_felmyst();
-void AddSC_boss_eredar_twins();
-void AddSC_boss_muru();
-void AddSC_boss_kiljaeden();
-void AddSC_sunwell_plateau();
-void AddSC_boss_archaedas(); //Uldaman
-void AddSC_boss_ironaya();
-void AddSC_uldaman();
-void AddSC_instance_uldaman();
-void AddSC_instance_the_stockade(); //The Stockade
-void AddSC_boss_akilzon(); //Zul'Aman
-void AddSC_boss_halazzi();
-void AddSC_boss_hex_lord_malacrass();
-void AddSC_boss_janalai();
-void AddSC_boss_nalorakk();
-void AddSC_boss_daakara();
-void AddSC_instance_zulaman();
-void AddSC_zulaman();
-void AddSC_boss_grilek(); // Zul'Gurub
-void AddSC_boss_hazzarah();
-void AddSC_boss_jindo_the_godbreaker();
-void AddSC_boss_kilnara();
-void AddSC_boss_mandokir();
-void AddSC_boss_renataki();
-void AddSC_boss_venoxis();
-void AddSC_boss_wushoolay();
-void AddSC_boss_zanzil();
-void AddSC_instance_zulgurub();
-//void AddSC_alterac_mountains();
-void AddSC_arathi_highlands();
-void AddSC_blasted_lands();
-void AddSC_burning_steppes();
-void AddSC_duskwood();
-void AddSC_eastern_plaguelands();
-void AddSC_ghostlands();
-void AddSC_hinterlands();
-void AddSC_isle_of_queldanas();
-void AddSC_loch_modan();
-void AddSC_redridge_mountains();
-void AddSC_silverpine_forest();
-void AddSC_stormwind_city();
-void AddSC_stranglethorn_vale();
-void AddSC_swamp_of_sorrows();
-void AddSC_tirisfal_glades();
-void AddSC_undercity();
-void AddSC_western_plaguelands();
-void AddSC_wetlands();
-
-//kalimdor
-void AddSC_blackfathom_deeps(); //Blackfathom Depths
-void AddSC_boss_gelihast();
-void AddSC_boss_kelris();
-void AddSC_boss_aku_mai();
-void AddSC_instance_blackfathom_deeps();
-void AddSC_hyjal(); //CoT Battle for Mt. Hyjal
-void AddSC_boss_archimonde();
-void AddSC_instance_mount_hyjal();
-void AddSC_hyjal_trash();
-void AddSC_boss_rage_winterchill();
-void AddSC_boss_anetheron();
-void AddSC_boss_kazrogal();
-void AddSC_boss_azgalor();
-void AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad
-void AddSC_boss_epoch_hunter();
-void AddSC_boss_lieutenant_drake();
-void AddSC_instance_old_hillsbrad();
-void AddSC_old_hillsbrad();
-void AddSC_boss_aeonus(); //CoT The Black Morass
-void AddSC_boss_chrono_lord_deja();
-void AddSC_boss_temporus();
-void AddSC_the_black_morass();
-void AddSC_instance_the_black_morass();
-void AddSC_boss_epoch(); //CoT Culling Of Stratholme
-void AddSC_boss_infinite_corruptor();
-void AddSC_boss_salramm();
-void AddSC_boss_mal_ganis();
-void AddSC_boss_meathook();
-void AddSC_culling_of_stratholme();
-void AddSC_instance_culling_of_stratholme();
-void AddSC_instance_dire_maul(); //Dire Maul
-void AddSC_boss_celebras_the_cursed(); //Maraudon
-void AddSC_boss_landslide();
-void AddSC_boss_noxxion();
-void AddSC_boss_ptheradras();
-void AddSC_instance_maraudon();
-void AddSC_boss_onyxia(); //Onyxia's Lair
-void AddSC_instance_onyxias_lair();
-void AddSC_boss_tuten_kash(); //Razorfen Downs
-void AddSC_boss_mordresh_fire_eye();
-void AddSC_boss_glutton();
-void AddSC_boss_amnennar_the_coldbringer();
-void AddSC_razorfen_downs();
-void AddSC_instance_razorfen_downs();
-void AddSC_razorfen_kraul(); //Razorfen Kraul
-void AddSC_instance_razorfen_kraul();
-void AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj
-void AddSC_boss_rajaxx();
-void AddSC_boss_moam();
-void AddSC_boss_buru();
-void AddSC_boss_ayamiss();
-void AddSC_boss_ossirian();
-void AddSC_instance_ruins_of_ahnqiraj();
-void AddSC_boss_cthun(); //Temple of ahn'qiraj
-void AddSC_boss_viscidus();
-void AddSC_boss_fankriss();
-void AddSC_boss_huhuran();
-void AddSC_bug_trio();
-void AddSC_boss_sartura();
-void AddSC_boss_skeram();
-void AddSC_boss_twinemperors();
-void AddSC_boss_ouro();
-void AddSC_npc_anubisath_sentinel();
-void AddSC_instance_temple_of_ahnqiraj();
-void AddSC_wailing_caverns(); //Wailing caverns
-void AddSC_instance_wailing_caverns();
-void AddSC_boss_zum_rah(); //Zul'Farrak
-void AddSC_zulfarrak();
-void AddSC_instance_zulfarrak();
-void AddSC_instance_halls_of_origination();
-void AddSC_boss_temple_guardian_anhuur();
-void AddSC_boss_earthrager_ptah();
-void AddSC_boss_anraphet();
-void AddSC_instance_firelands();
-void AddSC_boss_alysrazor();
-
-void AddSC_ashenvale();
-void AddSC_azshara();
-void AddSC_azuremyst_isle();
-void AddSC_bloodmyst_isle();
-void AddSC_darkshore();
-void AddSC_desolace();
-void AddSC_durotar();
-void AddSC_felwood();
-void AddSC_feralas();
-void AddSC_moonglade();
-void AddSC_orgrimmar();
-void AddSC_silithus();
-void AddSC_stonetalon_mountains();
-void AddSC_tanaris();
-void AddSC_the_barrens();
-void AddSC_thousand_needles();
-void AddSC_thunder_bluff();
-void AddSC_ungoro_crater();
-void AddSC_winterspring();
-
-// Northrend
-
-void AddSC_boss_slad_ran();
-void AddSC_boss_moorabi();
-void AddSC_boss_drakkari_colossus();
-void AddSC_boss_gal_darah();
-void AddSC_boss_eck();
-void AddSC_instance_gundrak();
-
-// Azjol-Nerub - Azjol-Nerub
-void AddSC_boss_krik_thir();
-void AddSC_boss_hadronox();
-void AddSC_boss_anub_arak();
-void AddSC_instance_azjol_nerub();
-
-// Azjol-Nerub - Ahn'kahet
-void AddSC_boss_elder_nadox();
-void AddSC_boss_taldaram();
-void AddSC_boss_amanitar();
-void AddSC_boss_jedoga_shadowseeker();
-void AddSC_boss_volazj();
-void AddSC_instance_ahnkahet();
-
-// Drak'Tharon Keep
-void AddSC_boss_trollgore();
-void AddSC_boss_novos();
-void AddSC_boss_king_dred();
-void AddSC_boss_tharon_ja();
-void AddSC_instance_drak_tharon_keep();
-
-void AddSC_boss_argent_challenge(); //Trial of the Champion
-void AddSC_boss_black_knight();
-void AddSC_boss_grand_champions();
-void AddSC_instance_trial_of_the_champion();
-void AddSC_trial_of_the_champion();
-void AddSC_boss_anubarak_trial(); //Trial of the Crusader
-void AddSC_boss_faction_champions();
-void AddSC_boss_jaraxxus();
-void AddSC_boss_northrend_beasts();
-void AddSC_boss_twin_valkyr();
-void AddSC_trial_of_the_crusader();
-void AddSC_instance_trial_of_the_crusader();
-void AddSC_boss_anubrekhan(); //Naxxramas
-void AddSC_boss_maexxna();
-void AddSC_boss_patchwerk();
-void AddSC_boss_grobbulus();
-void AddSC_boss_razuvious();
-void AddSC_boss_kelthuzad();
-void AddSC_boss_loatheb();
-void AddSC_boss_noth();
-void AddSC_boss_gluth();
-void AddSC_boss_sapphiron();
-void AddSC_boss_four_horsemen();
-void AddSC_boss_faerlina();
-void AddSC_boss_heigan();
-void AddSC_boss_gothik();
-void AddSC_boss_thaddius();
-void AddSC_instance_naxxramas();
-void AddSC_boss_nexus_commanders(); // The Nexus Nexus
-void AddSC_boss_magus_telestra();
-void AddSC_boss_anomalus();
-void AddSC_boss_ormorok();
-void AddSC_boss_keristrasza();
-void AddSC_instance_nexus();
-void AddSC_boss_drakos(); //The Nexus The Oculus
-void AddSC_boss_urom();
-void AddSC_boss_varos();
-void AddSC_boss_eregos();
-void AddSC_instance_oculus();
-void AddSC_oculus();
-void AddSC_boss_malygos(); // The Nexus: Eye of Eternity
-void AddSC_instance_eye_of_eternity();
-void AddSC_boss_sartharion(); //Obsidian Sanctum
-void AddSC_obsidian_sanctum();
-void AddSC_instance_obsidian_sanctum();
-void AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning
-void AddSC_boss_loken();
-void AddSC_boss_ionar();
-void AddSC_boss_volkhan();
-void AddSC_instance_halls_of_lightning();
-void AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone
-void AddSC_boss_krystallus();
-void AddSC_boss_sjonnir();
-void AddSC_instance_halls_of_stone();
-void AddSC_halls_of_stone();
-void AddSC_boss_auriaya(); //Ulduar Ulduar
-void AddSC_boss_flame_leviathan();
-void AddSC_boss_ignis();
-void AddSC_boss_razorscale();
-void AddSC_boss_xt002();
-void AddSC_boss_kologarn();
-void AddSC_boss_assembly_of_iron();
-void AddSC_boss_general_vezax();
-void AddSC_boss_mimiron();
-void AddSC_boss_hodir();
-void AddSC_boss_freya();
-void AddSC_boss_yogg_saron();
-void AddSC_boss_algalon_the_observer();
-void AddSC_instance_ulduar();
-
-// Utgarde Keep - Utgarde Keep
-void AddSC_boss_keleseth();
-void AddSC_boss_skarvald_dalronn();
-void AddSC_boss_ingvar_the_plunderer();
-void AddSC_instance_utgarde_keep();
-void AddSC_utgarde_keep();
-
-// Utgarde Keep - Utgarde Pinnacle
-void AddSC_boss_svala();
-void AddSC_boss_palehoof();
-void AddSC_boss_skadi();
-void AddSC_boss_ymiron();
-void AddSC_instance_utgarde_pinnacle();
-
-// Vault of Archavon
-void AddSC_boss_archavon();
-void AddSC_boss_emalon();
-void AddSC_boss_koralon();
-void AddSC_boss_toravon();
-void AddSC_instance_vault_of_archavon();
-
-void AddSC_boss_cyanigosa(); //Violet Hold
-void AddSC_boss_erekem();
-void AddSC_boss_ichoron();
-void AddSC_boss_lavanthor();
-void AddSC_boss_moragg();
-void AddSC_boss_xevozz();
-void AddSC_boss_zuramat();
-void AddSC_instance_violet_hold();
-void AddSC_violet_hold();
-void AddSC_instance_forge_of_souls(); //Forge of Souls
-void AddSC_forge_of_souls();
-void AddSC_boss_bronjahm();
-void AddSC_boss_devourer_of_souls();
-void AddSC_instance_pit_of_saron(); //Pit of Saron
-void AddSC_pit_of_saron();
-void AddSC_boss_garfrost();
-void AddSC_boss_ick();
-void AddSC_boss_tyrannus();
-void AddSC_instance_halls_of_reflection(); // Halls of Reflection
-void AddSC_halls_of_reflection();
-void AddSC_boss_falric();
-void AddSC_boss_marwyn();
-void AddSC_boss_lord_marrowgar(); // Icecrown Citadel
-void AddSC_boss_lady_deathwhisper();
-void AddSC_boss_icecrown_gunship_battle();
-void AddSC_boss_deathbringer_saurfang();
-void AddSC_boss_festergut();
-void AddSC_boss_rotface();
-void AddSC_boss_professor_putricide();
-void AddSC_boss_blood_prince_council();
-void AddSC_boss_blood_queen_lana_thel();
-void AddSC_boss_valithria_dreamwalker();
-void AddSC_boss_sindragosa();
-void AddSC_boss_the_lich_king();
-void AddSC_icecrown_citadel_teleport();
-void AddSC_instance_icecrown_citadel();
-void AddSC_icecrown_citadel();
-void AddSC_instance_ruby_sanctum(); // Ruby Sanctum
-void AddSC_ruby_sanctum();
-void AddSC_boss_baltharus_the_warborn();
-void AddSC_boss_saviana_ragefire();
-void AddSC_boss_general_zarithrian();
-void AddSC_boss_halion();
-
-void AddSC_dalaran();
-void AddSC_borean_tundra();
-void AddSC_dragonblight();
-void AddSC_grizzly_hills();
-void AddSC_howling_fjord();
-void AddSC_icecrown();
-void AddSC_sholazar_basin();
-void AddSC_storm_peaks();
-void AddSC_wintergrasp();
-void AddSC_zuldrak();
-void AddSC_crystalsong_forest();
-void AddSC_isle_of_conquest();
-
-// Outland
-
-// Auchindoun - Auchenai Crypts
-void AddSC_boss_shirrak_the_dead_watcher();
-void AddSC_boss_exarch_maladaar();
-void AddSC_instance_auchenai_crypts();
-
-// Auchindoun - Mana Tombs
-void AddSC_boss_pandemonius();
-void AddSC_boss_nexusprince_shaffar();
-void AddSC_instance_mana_tombs();
-
-// Auchindoun - Sekketh Halls
-void AddSC_boss_darkweaver_syth();
-void AddSC_boss_talon_king_ikiss();
-void AddSC_boss_anzu();
-void AddSC_instance_sethekk_halls();
-
-// Auchindoun - Shadow Labyrinth
-void AddSC_boss_ambassador_hellmaw();
-void AddSC_boss_blackheart_the_inciter();
-void AddSC_boss_grandmaster_vorpil();
-void AddSC_boss_murmur();
-void AddSC_instance_shadow_labyrinth();
-
-// Black Temple
-void AddSC_black_temple();
-void AddSC_boss_illidan();
-void AddSC_boss_shade_of_akama();
-void AddSC_boss_supremus();
-void AddSC_boss_gurtogg_bloodboil();
-void AddSC_boss_mother_shahraz();
-void AddSC_boss_reliquary_of_souls();
-void AddSC_boss_teron_gorefiend();
-void AddSC_boss_najentus();
-void AddSC_boss_illidari_council();
-void AddSC_instance_black_temple();
-
-// Coilfang Reservoir - Serpent Shrine Cavern
-void AddSC_boss_fathomlord_karathress();
-void AddSC_boss_hydross_the_unstable();
-void AddSC_boss_lady_vashj();
-void AddSC_boss_leotheras_the_blind();
-void AddSC_boss_morogrim_tidewalker();
-void AddSC_instance_serpentshrine_cavern();
-void AddSC_boss_the_lurker_below();
-
-// Coilfang Reservoir - The Steam Vault
-void AddSC_boss_hydromancer_thespia();
-void AddSC_boss_mekgineer_steamrigger();
-void AddSC_boss_warlord_kalithresh();
-void AddSC_instance_steam_vault();
-
-// Coilfang Reservoir - The Slave Pens
-void AddSC_instance_the_slave_pens();
-void AddSC_boss_mennu_the_betrayer();
-void AddSC_boss_rokmar_the_crackler();
-void AddSC_boss_quagmirran();
-
-// Coilfang Reservoir - The Underbog
-void AddSC_instance_the_underbog();
-void AddSC_boss_hungarfen();
-void AddSC_boss_the_black_stalker();
-
-// Gruul's Lair
-void AddSC_boss_gruul();
-void AddSC_boss_high_king_maulgar();
-void AddSC_instance_gruuls_lair();
-void AddSC_boss_broggok(); //HC Blood Furnace
-void AddSC_boss_kelidan_the_breaker();
-void AddSC_boss_the_maker();
-void AddSC_instance_blood_furnace();
-void AddSC_boss_magtheridon(); //HC Magtheridon's Lair
-void AddSC_instance_magtheridons_lair();
-void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
-void AddSC_boss_warbringer_omrogg();
-void AddSC_boss_warchief_kargath_bladefist();
-void AddSC_shattered_halls();
-void AddSC_instance_shattered_halls();
-void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
-void AddSC_boss_omor_the_unscarred();
-void AddSC_boss_vazruden_the_herald();
-void AddSC_instance_ramparts();
-void AddSC_arcatraz(); //TK Arcatraz
-void AddSC_boss_zereketh_the_unbound();
-void AddSC_boss_dalliah_the_doomsayer();
-void AddSC_boss_wrath_scryer_soccothrates();
-void AddSC_boss_harbinger_skyriss();
-void AddSC_instance_arcatraz();
-void AddSC_boss_high_botanist_freywinn(); //TK Botanica
-void AddSC_boss_laj();
-void AddSC_boss_warp_splinter();
-void AddSC_boss_thorngrin_the_tender();
-void AddSC_boss_commander_sarannis();
-void AddSC_instance_the_botanica();
-void AddSC_boss_alar(); //TK The Eye
-void AddSC_boss_kaelthas();
-void AddSC_boss_void_reaver();
-void AddSC_boss_high_astromancer_solarian();
-void AddSC_instance_the_eye();
-void AddSC_the_eye();
-void AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar
-void AddSC_boss_gatewatcher_gyrokill();
-void AddSC_boss_nethermancer_sepethrea();
-void AddSC_boss_pathaleon_the_calculator();
-void AddSC_boss_mechano_lord_capacitus();
-void AddSC_instance_mechanar();
-
-void AddSC_blades_edge_mountains();
-void AddSC_boss_doomlordkazzak();
-void AddSC_boss_doomwalker();
-void AddSC_hellfire_peninsula();
-void AddSC_nagrand();
-void AddSC_netherstorm();
-void AddSC_shadowmoon_valley();
-void AddSC_shattrath_city();
-void AddSC_terokkar_forest();
-void AddSC_zangarmarsh();
-
-// Maelstrom
-void AddSC_kezan();
-void AddSC_instance_stonecore(); // Stonecore
-void AddSC_stonecore();
-void AddSC_boss_corborus();
-void AddSC_boss_slabhide();
-void AddSC_boss_ozruk();
-void AddSC_boss_high_priestess_azil();
-
-// Events
-void AddSC_event_childrens_week();
-
-// Pets
-void AddSC_deathknight_pet_scripts();
-void AddSC_generic_pet_scripts();
-void AddSC_hunter_pet_scripts();
-void AddSC_mage_pet_scripts();
-void AddSC_priest_pet_scripts();
-void AddSC_shaman_pet_scripts();
-
-// battlegrounds
-
-// outdoor pvp
-void AddSC_outdoorpvp_hp();
-void AddSC_outdoorpvp_na();
-void AddSC_outdoorpvp_si();
-void AddSC_outdoorpvp_tf();
-void AddSC_outdoorpvp_zm();
-
-// player
-void AddSC_chat_log();
-void AddSC_action_ip_logger();
-
+void AddWorldScripts();
+void AddEasternKingdomsScripts();
+void AddKalimdorScripts();
+void AddOutlandScripts();
+void AddNorthrendScripts();
+void AddMaelstromScripts();
+void AddEventsScripts();
+void AddPetScripts();
+void AddOutdoorPvPScripts();
+void AddCustomScripts();
#endif
void AddScripts()
{
- AddSpellScripts();
+ AddSpellsScripts();
AddSC_SmartScripts();
- AddCommandScripts();
+ AddCommandsScripts();
#ifdef SCRIPTS
AddWorldScripts();
AddEasternKingdomsScripts();
@@ -718,751 +47,9 @@ void AddScripts()
AddOutlandScripts();
AddNorthrendScripts();
AddMaelstromScripts();
- AddEventScripts();
+ AddEventsScripts();
AddPetScripts();
- AddBattlegroundScripts();
AddOutdoorPvPScripts();
AddCustomScripts();
#endif
}
-
-void AddSpellScripts()
-{
- AddSC_deathknight_spell_scripts();
- AddSC_druid_spell_scripts();
- AddSC_generic_spell_scripts();
- AddSC_hunter_spell_scripts();
- AddSC_mage_spell_scripts();
- AddSC_paladin_spell_scripts();
- AddSC_priest_spell_scripts();
- AddSC_rogue_spell_scripts();
- AddSC_shaman_spell_scripts();
- AddSC_warlock_spell_scripts();
- AddSC_warrior_spell_scripts();
- AddSC_quest_spell_scripts();
- AddSC_item_spell_scripts();
- AddSC_holiday_spell_scripts();
-}
-
-void AddCommandScripts()
-{
- AddSC_account_commandscript();
- AddSC_achievement_commandscript();
- AddSC_ahbot_commandscript();
- AddSC_arena_commandscript();
- AddSC_ban_commandscript();
- AddSC_battlenet_account_commandscript();
- AddSC_bf_commandscript();
- AddSC_cast_commandscript();
- AddSC_character_commandscript();
- AddSC_cheat_commandscript();
- AddSC_debug_commandscript();
- AddSC_deserter_commandscript();
- AddSC_disable_commandscript();
- AddSC_event_commandscript();
- AddSC_gm_commandscript();
- AddSC_go_commandscript();
- AddSC_gobject_commandscript();
- AddSC_group_commandscript();
- AddSC_guild_commandscript();
- AddSC_honor_commandscript();
- AddSC_instance_commandscript();
- AddSC_learn_commandscript();
- AddSC_lookup_commandscript();
- AddSC_lfg_commandscript();
- AddSC_list_commandscript();
- AddSC_message_commandscript();
- AddSC_misc_commandscript();
- AddSC_mmaps_commandscript();
- AddSC_modify_commandscript();
- AddSC_npc_commandscript();
- AddSC_quest_commandscript();
- AddSC_pet_commandscript();
- AddSC_rbac_commandscript();
- AddSC_reload_commandscript();
- AddSC_reset_commandscript();
- AddSC_send_commandscript();
- AddSC_server_commandscript();
- AddSC_tele_commandscript();
- AddSC_ticket_commandscript();
- AddSC_titles_commandscript();
- AddSC_wp_commandscript();
-}
-
-void AddWorldScripts()
-{
-#ifdef SCRIPTS
- AddSC_areatrigger_scripts();
- AddSC_emerald_dragons();
- AddSC_generic_creature();
- AddSC_go_scripts();
- AddSC_guards();
- AddSC_item_scripts();
- AddSC_npc_professions();
- AddSC_npc_innkeeper();
- AddSC_npcs_special();
- AddSC_achievement_scripts();
- AddSC_chat_log(); // location: scripts\World\chat_log.cpp
- // To avoid duplicate code, we check once /*ONLY*/ if logging is permitted or not.
- if (sWorld->getBoolConfig(CONFIG_IP_BASED_ACTION_LOGGING))
- AddSC_action_ip_logger(); // location: scripts\World\action_ip_logger.cpp
- AddSC_duel_reset();
-#endif
-}
-
-void AddEasternKingdomsScripts()
-{
-#ifdef SCRIPTS
- AddSC_alterac_valley(); //Alterac Valley
- AddSC_boss_balinda();
- AddSC_boss_drekthar();
- AddSC_boss_galvangar();
- AddSC_boss_vanndar();
- AddSC_boss_alizabal(); //Baradin Hold
- AddSC_boss_occuthar();
- AddSC_boss_pit_lord_argaloth();
- AddSC_instance_baradin_hold();
- AddSC_boss_romogg_bonecrusher(); //Blackrock Caverns
- AddSC_boss_corla();
- AddSC_boss_karsh_steelbender();
- AddSC_boss_beauty();
- AddSC_boss_ascendant_lord_obsidius();
- AddSC_blackrock_caverns();
- AddSC_instance_blackrock_caverns();
- AddSC_blackrock_depths(); //Blackrock Depths
- AddSC_boss_ambassador_flamelash();
- AddSC_boss_draganthaurissan();
- AddSC_boss_general_angerforge();
- AddSC_boss_high_interrogator_gerstahn();
- AddSC_boss_magmus();
- AddSC_boss_moira_bronzebeard();
- AddSC_boss_tomb_of_seven();
- AddSC_instance_blackrock_depths();
- AddSC_boss_drakkisath(); //Blackrock Spire
- AddSC_boss_halycon();
- AddSC_boss_highlordomokk();
- AddSC_boss_mothersmolderweb();
- AddSC_boss_overlordwyrmthalak();
- AddSC_boss_shadowvosh();
- AddSC_boss_thebeast();
- AddSC_boss_warmastervoone();
- AddSC_boss_quatermasterzigris();
- AddSC_boss_pyroguard_emberseer();
- AddSC_boss_gyth();
- AddSC_boss_rend_blackhand();
- AddSC_boss_gizrul_the_slavener();
- AddSC_boss_urok_doomhowl();
- AddSC_boss_lord_valthalak();
- AddSC_instance_blackrock_spire();
- AddSC_boss_razorgore(); //Blackwing lair
- AddSC_boss_vaelastrasz();
- AddSC_boss_broodlord();
- AddSC_boss_firemaw();
- AddSC_boss_ebonroc();
- AddSC_boss_flamegor();
- AddSC_boss_chromaggus();
- AddSC_boss_nefarian();
- AddSC_instance_blackwing_lair();
- AddSC_deadmines(); //Deadmines
- AddSC_boss_mr_smite();
- AddSC_instance_deadmines();
- AddSC_gnomeregan(); //Gnomeregan
- AddSC_instance_gnomeregan();
- AddSC_boss_attumen(); //Karazhan
- AddSC_boss_curator();
- AddSC_boss_maiden_of_virtue();
- AddSC_boss_shade_of_aran();
- AddSC_boss_malchezaar();
- AddSC_boss_terestian_illhoof();
- AddSC_boss_moroes();
- AddSC_bosses_opera();
- AddSC_boss_netherspite();
- AddSC_instance_karazhan();
- AddSC_karazhan();
- AddSC_boss_nightbane();
- AddSC_boss_felblood_kaelthas(); // Magister's Terrace
- AddSC_boss_selin_fireheart();
- AddSC_boss_vexallus();
- AddSC_boss_priestess_delrissa();
- AddSC_instance_magisters_terrace();
- AddSC_magisters_terrace();
- AddSC_boss_lucifron(); //Molten core
- AddSC_boss_magmadar();
- AddSC_boss_gehennas();
- AddSC_boss_garr();
- AddSC_boss_baron_geddon();
- AddSC_boss_shazzrah();
- AddSC_boss_golemagg();
- AddSC_boss_sulfuron();
- AddSC_boss_majordomo();
- AddSC_boss_ragnaros();
- AddSC_instance_molten_core();
- AddSC_instance_ragefire_chasm(); //Ragefire Chasm
- AddSC_the_scarlet_enclave(); //Scarlet Enclave
- AddSC_the_scarlet_enclave_c1();
- AddSC_the_scarlet_enclave_c2();
- AddSC_the_scarlet_enclave_c5();
- AddSC_boss_arcanist_doan(); //Scarlet Monastery
- AddSC_boss_azshir_the_sleepless();
- AddSC_boss_bloodmage_thalnos();
- AddSC_boss_headless_horseman();
- AddSC_boss_herod();
- AddSC_boss_high_inquisitor_fairbanks();
- AddSC_boss_houndmaster_loksey();
- AddSC_boss_interrogator_vishas();
- AddSC_boss_scorn();
- AddSC_instance_scarlet_monastery();
- AddSC_boss_mograine_and_whitemane();
- AddSC_boss_darkmaster_gandling(); //Scholomance
- AddSC_boss_death_knight_darkreaver();
- AddSC_boss_theolenkrastinov();
- AddSC_boss_illuciabarov();
- AddSC_boss_instructormalicia();
- AddSC_boss_jandicebarov();
- AddSC_boss_kormok();
- AddSC_boss_lordalexeibarov();
- AddSC_boss_lorekeeperpolkelt();
- AddSC_boss_rasfrost();
- AddSC_boss_theravenian();
- AddSC_boss_vectus();
- AddSC_boss_kirtonos_the_herald();
- AddSC_instance_scholomance();
- AddSC_shadowfang_keep(); //Shadowfang keep
- AddSC_instance_shadowfang_keep();
- AddSC_boss_magistrate_barthilas(); //Stratholme
- AddSC_boss_maleki_the_pallid();
- AddSC_boss_nerubenkan();
- AddSC_boss_cannon_master_willey();
- AddSC_boss_baroness_anastari();
- AddSC_boss_ramstein_the_gorger();
- AddSC_boss_timmy_the_cruel();
- AddSC_boss_postmaster_malown();
- AddSC_boss_baron_rivendare();
- AddSC_boss_dathrohan_balnazzar();
- AddSC_boss_order_of_silver_hand();
- AddSC_instance_stratholme();
- AddSC_stratholme();
- AddSC_sunken_temple(); // Sunken Temple
- AddSC_instance_sunken_temple();
- AddSC_instance_sunwell_plateau(); //Sunwell Plateau
- AddSC_boss_kalecgos();
- AddSC_boss_brutallus();
- AddSC_boss_felmyst();
- AddSC_boss_eredar_twins();
- AddSC_boss_muru();
- AddSC_boss_kiljaeden();
- AddSC_sunwell_plateau();
- AddSC_instance_the_stockade(); //The Stockade
- AddSC_boss_archaedas(); //Uldaman
- AddSC_boss_ironaya();
- AddSC_uldaman();
- AddSC_instance_uldaman();
- AddSC_boss_akilzon(); //Zul'Aman
- AddSC_boss_halazzi();
- AddSC_boss_hex_lord_malacrass();
- AddSC_boss_janalai();
- AddSC_boss_nalorakk();
- AddSC_boss_daakara();
- AddSC_instance_zulaman();
- AddSC_zulaman();
- AddSC_boss_grilek(); // Zul'Gurub
- AddSC_boss_hazzarah();
- AddSC_boss_jindo_the_godbreaker();
- AddSC_boss_kilnara();
- AddSC_boss_mandokir();
- AddSC_boss_renataki();
- AddSC_boss_venoxis();
- AddSC_boss_wushoolay();
- AddSC_boss_zanzil();
- AddSC_instance_zulgurub();
-
- //AddSC_alterac_mountains();
- AddSC_arathi_highlands();
- AddSC_blasted_lands();
- AddSC_burning_steppes();
- AddSC_duskwood();
- AddSC_eastern_plaguelands();
- AddSC_ghostlands();
- AddSC_hinterlands();
- AddSC_isle_of_queldanas();
- AddSC_loch_modan();
- AddSC_redridge_mountains();
- AddSC_silverpine_forest();
- AddSC_stormwind_city();
- AddSC_stranglethorn_vale();
- AddSC_swamp_of_sorrows();
- AddSC_tirisfal_glades();
- AddSC_undercity();
- AddSC_western_plaguelands();
- AddSC_wetlands();
-#endif
-}
-
-void AddKalimdorScripts()
-{
-#ifdef SCRIPTS
- AddSC_blackfathom_deeps(); //Blackfathom Depths
- AddSC_boss_gelihast();
- AddSC_boss_kelris();
- AddSC_boss_aku_mai();
- AddSC_instance_blackfathom_deeps();
- AddSC_hyjal(); //CoT Battle for Mt. Hyjal
- AddSC_boss_archimonde();
- AddSC_instance_mount_hyjal();
- AddSC_hyjal_trash();
- AddSC_boss_rage_winterchill();
- AddSC_boss_anetheron();
- AddSC_boss_kazrogal();
- AddSC_boss_azgalor();
- AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad
- AddSC_boss_epoch_hunter();
- AddSC_boss_lieutenant_drake();
- AddSC_instance_old_hillsbrad();
- AddSC_old_hillsbrad();
- AddSC_boss_aeonus(); //CoT The Black Morass
- AddSC_boss_chrono_lord_deja();
- AddSC_boss_temporus();
- AddSC_the_black_morass();
- AddSC_instance_the_black_morass();
- AddSC_boss_epoch(); //CoT Culling Of Stratholme
- AddSC_boss_infinite_corruptor();
- AddSC_boss_salramm();
- AddSC_boss_mal_ganis();
- AddSC_boss_meathook();
- AddSC_culling_of_stratholme();
- AddSC_instance_culling_of_stratholme();
- AddSC_instance_dire_maul(); //Dire Maul
- AddSC_boss_celebras_the_cursed(); //Maraudon
- AddSC_boss_landslide();
- AddSC_boss_noxxion();
- AddSC_boss_ptheradras();
- AddSC_instance_maraudon();
- AddSC_boss_onyxia(); //Onyxia's Lair
- AddSC_instance_onyxias_lair();
- AddSC_boss_tuten_kash(); //Razorfen Downs
- AddSC_boss_mordresh_fire_eye();
- AddSC_boss_glutton();
- AddSC_boss_amnennar_the_coldbringer();
- AddSC_razorfen_downs();
- AddSC_instance_razorfen_downs();
- AddSC_razorfen_kraul(); //Razorfen Kraul
- AddSC_instance_razorfen_kraul();
- AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj
- AddSC_boss_rajaxx();
- AddSC_boss_moam();
- AddSC_boss_buru();
- AddSC_boss_ayamiss();
- AddSC_boss_ossirian();
- AddSC_instance_ruins_of_ahnqiraj();
- AddSC_boss_cthun(); //Temple of ahn'qiraj
- AddSC_boss_viscidus();
- AddSC_boss_fankriss();
- AddSC_boss_huhuran();
- AddSC_bug_trio();
- AddSC_boss_sartura();
- AddSC_boss_skeram();
- AddSC_boss_twinemperors();
- AddSC_boss_ouro();
- AddSC_npc_anubisath_sentinel();
- AddSC_instance_temple_of_ahnqiraj();
- AddSC_wailing_caverns(); //Wailing caverns
- AddSC_instance_wailing_caverns();
- AddSC_boss_zum_rah(); //Zul'Farrak
- AddSC_zulfarrak();
- AddSC_instance_zulfarrak();
-
- AddSC_ashenvale();
- AddSC_azshara();
- AddSC_azuremyst_isle();
- AddSC_bloodmyst_isle();
- AddSC_darkshore();
- AddSC_desolace();
- AddSC_durotar();
- AddSC_felwood();
- AddSC_feralas();
- AddSC_moonglade();
- AddSC_orgrimmar();
- AddSC_silithus();
- AddSC_stonetalon_mountains();
- AddSC_tanaris();
- AddSC_the_barrens();
- AddSC_thousand_needles();
- AddSC_thunder_bluff();
- AddSC_ungoro_crater();
- AddSC_winterspring();
-
- AddSC_instance_halls_of_origination();
- AddSC_boss_temple_guardian_anhuur();
- AddSC_boss_earthrager_ptah();
- AddSC_boss_anraphet();
-
- AddSC_instance_firelands();
- AddSC_boss_alysrazor();
-#endif
-}
-
-void AddOutlandScripts()
-{
-#ifdef SCRIPTS
- // Auchindoun - Auchenai Crypts
- AddSC_boss_shirrak_the_dead_watcher();
- AddSC_boss_exarch_maladaar();
- AddSC_instance_auchenai_crypts();
-
- // Auchindoun - Mana Tombs
- AddSC_boss_pandemonius();
- AddSC_boss_nexusprince_shaffar();
- AddSC_instance_mana_tombs();
-
- // Auchindoun - Sekketh Halls
- AddSC_boss_darkweaver_syth();
- AddSC_boss_talon_king_ikiss();
- AddSC_boss_anzu();
- AddSC_instance_sethekk_halls();
-
- // Auchindoun - Shadow Labyrinth
- AddSC_boss_ambassador_hellmaw();
- AddSC_boss_blackheart_the_inciter();
- AddSC_boss_grandmaster_vorpil();
- AddSC_boss_murmur();
- AddSC_instance_shadow_labyrinth();
-
- // Black Temple
- AddSC_black_temple();
- AddSC_boss_illidan();
- AddSC_boss_shade_of_akama();
- AddSC_boss_supremus();
- AddSC_boss_gurtogg_bloodboil();
- AddSC_boss_mother_shahraz();
- AddSC_boss_reliquary_of_souls();
- AddSC_boss_teron_gorefiend();
- AddSC_boss_najentus();
- AddSC_boss_illidari_council();
- AddSC_instance_black_temple();
-
- // Coilfang Reservoir - Serpent Shrine Cavern
- AddSC_boss_fathomlord_karathress();
- AddSC_boss_hydross_the_unstable();
- AddSC_boss_lady_vashj();
- AddSC_boss_leotheras_the_blind();
- AddSC_boss_morogrim_tidewalker();
- AddSC_instance_serpentshrine_cavern();
- AddSC_boss_the_lurker_below();
-
- // Coilfang Reservoir - The Steam Vault
- AddSC_instance_steam_vault();
- AddSC_boss_hydromancer_thespia();
- AddSC_boss_mekgineer_steamrigger();
- AddSC_boss_warlord_kalithresh();
-
- // Coilfang Reservoir - The Slave Pens
- AddSC_instance_the_slave_pens();
- AddSC_boss_mennu_the_betrayer();
- AddSC_boss_rokmar_the_crackler();
- AddSC_boss_quagmirran();
-
- // Coilfang Reservoir - The Underbog
- AddSC_instance_the_underbog();
- AddSC_boss_hungarfen();
- AddSC_boss_the_black_stalker();
-
- // Gruul's Lair
- AddSC_boss_gruul();
- AddSC_boss_high_king_maulgar();
- AddSC_instance_gruuls_lair();
- AddSC_boss_broggok(); //HC Blood Furnace
- AddSC_boss_kelidan_the_breaker();
- AddSC_boss_the_maker();
- AddSC_instance_blood_furnace();
- AddSC_boss_magtheridon(); //HC Magtheridon's Lair
- AddSC_instance_magtheridons_lair();
- AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
- AddSC_boss_warbringer_omrogg();
- AddSC_boss_warchief_kargath_bladefist();
- AddSC_shattered_halls();
- AddSC_instance_shattered_halls();
- AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
- AddSC_boss_omor_the_unscarred();
- AddSC_boss_vazruden_the_herald();
- AddSC_instance_ramparts();
- AddSC_arcatraz(); //TK Arcatraz
- AddSC_boss_zereketh_the_unbound();
- AddSC_boss_dalliah_the_doomsayer();
- AddSC_boss_wrath_scryer_soccothrates();
- AddSC_boss_harbinger_skyriss();
- AddSC_instance_arcatraz();
- AddSC_boss_high_botanist_freywinn(); //TK Botanica
- AddSC_boss_laj();
- AddSC_boss_warp_splinter();
- AddSC_boss_thorngrin_the_tender();
- AddSC_boss_commander_sarannis();
- AddSC_instance_the_botanica();
- AddSC_boss_alar(); //TK The Eye
- AddSC_boss_kaelthas();
- AddSC_boss_void_reaver();
- AddSC_boss_high_astromancer_solarian();
- AddSC_instance_the_eye();
- AddSC_the_eye();
- AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar
- AddSC_boss_gatewatcher_gyrokill();
- AddSC_boss_nethermancer_sepethrea();
- AddSC_boss_pathaleon_the_calculator();
- AddSC_boss_mechano_lord_capacitus();
- AddSC_instance_mechanar();
-
- AddSC_blades_edge_mountains();
- AddSC_boss_doomlordkazzak();
- AddSC_boss_doomwalker();
- AddSC_hellfire_peninsula();
- AddSC_nagrand();
- AddSC_netherstorm();
- AddSC_shadowmoon_valley();
- AddSC_shattrath_city();
- AddSC_terokkar_forest();
- AddSC_zangarmarsh();
-#endif
-}
-
-void AddNorthrendScripts()
-{
-#ifdef SCRIPTS
- AddSC_boss_slad_ran(); //Gundrak
- AddSC_boss_moorabi();
- AddSC_boss_drakkari_colossus();
- AddSC_boss_gal_darah();
- AddSC_boss_eck();
- AddSC_instance_gundrak();
-
- // Azjol-Nerub - Ahn'kahet
- AddSC_boss_elder_nadox();
- AddSC_boss_taldaram();
- AddSC_boss_amanitar();
- AddSC_boss_jedoga_shadowseeker();
- AddSC_boss_volazj();
- AddSC_instance_ahnkahet();
-
- // Azjol-Nerub - Azjol-Nerub
- AddSC_boss_krik_thir();
- AddSC_boss_hadronox();
- AddSC_boss_anub_arak();
- AddSC_instance_azjol_nerub();
-
- // Drak'Tharon Keep
- AddSC_boss_trollgore();
- AddSC_boss_novos();
- AddSC_boss_king_dred();
- AddSC_boss_tharon_ja();
- AddSC_instance_drak_tharon_keep();
-
- AddSC_boss_argent_challenge(); //Trial of the Champion
- AddSC_boss_black_knight();
- AddSC_boss_grand_champions();
- AddSC_instance_trial_of_the_champion();
- AddSC_trial_of_the_champion();
- AddSC_boss_anubarak_trial(); //Trial of the Crusader
- AddSC_boss_faction_champions();
- AddSC_boss_jaraxxus();
- AddSC_trial_of_the_crusader();
- AddSC_boss_twin_valkyr();
- AddSC_boss_northrend_beasts();
- AddSC_instance_trial_of_the_crusader();
- AddSC_boss_anubrekhan(); //Naxxramas
- AddSC_boss_maexxna();
- AddSC_boss_patchwerk();
- AddSC_boss_grobbulus();
- AddSC_boss_razuvious();
- AddSC_boss_kelthuzad();
- AddSC_boss_loatheb();
- AddSC_boss_noth();
- AddSC_boss_gluth();
- AddSC_boss_sapphiron();
- AddSC_boss_four_horsemen();
- AddSC_boss_faerlina();
- AddSC_boss_heigan();
- AddSC_boss_gothik();
- AddSC_boss_thaddius();
- AddSC_instance_naxxramas();
- AddSC_boss_nexus_commanders(); // The Nexus Nexus
- AddSC_boss_magus_telestra();
- AddSC_boss_anomalus();
- AddSC_boss_ormorok();
- AddSC_boss_keristrasza();
- AddSC_instance_nexus();
- AddSC_boss_drakos(); //The Nexus The Oculus
- AddSC_boss_urom();
- AddSC_boss_varos();
- AddSC_boss_eregos();
- AddSC_instance_oculus();
- AddSC_oculus();
- AddSC_boss_malygos(); // The Nexus: Eye of Eternity
- AddSC_instance_eye_of_eternity();
- AddSC_boss_sartharion(); //Obsidian Sanctum
- AddSC_obsidian_sanctum();
- AddSC_instance_obsidian_sanctum();
- AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning
- AddSC_boss_loken();
- AddSC_boss_ionar();
- AddSC_boss_volkhan();
- AddSC_instance_halls_of_lightning();
- AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone
- AddSC_boss_krystallus();
- AddSC_boss_sjonnir();
- AddSC_instance_halls_of_stone();
- AddSC_halls_of_stone();
- AddSC_boss_auriaya(); //Ulduar Ulduar
- AddSC_boss_flame_leviathan();
- AddSC_boss_ignis();
- AddSC_boss_razorscale();
- AddSC_boss_xt002();
- AddSC_boss_general_vezax();
- AddSC_boss_assembly_of_iron();
- AddSC_boss_kologarn();
- AddSC_boss_mimiron();
- AddSC_boss_hodir();
- AddSC_boss_freya();
- AddSC_boss_yogg_saron();
- AddSC_boss_algalon_the_observer();
- AddSC_instance_ulduar();
-
- // Utgarde Keep - Utgarde Keep
- AddSC_boss_keleseth();
- AddSC_boss_skarvald_dalronn();
- AddSC_boss_ingvar_the_plunderer();
- AddSC_instance_utgarde_keep();
- AddSC_utgarde_keep();
-
- // Utgarde Keep - Utgarde Pinnacle
- AddSC_boss_svala();
- AddSC_boss_palehoof();
- AddSC_boss_skadi();
- AddSC_boss_ymiron();
- AddSC_instance_utgarde_pinnacle();
-
- // Vault of Archavon
- AddSC_boss_archavon();
- AddSC_boss_emalon();
- AddSC_boss_koralon();
- AddSC_boss_toravon();
- AddSC_instance_vault_of_archavon();
-
- AddSC_boss_cyanigosa(); //Violet Hold
- AddSC_boss_erekem();
- AddSC_boss_ichoron();
- AddSC_boss_lavanthor();
- AddSC_boss_moragg();
- AddSC_boss_xevozz();
- AddSC_boss_zuramat();
- AddSC_instance_violet_hold();
- AddSC_violet_hold();
- AddSC_instance_forge_of_souls(); //Forge of Souls
- AddSC_forge_of_souls();
- AddSC_boss_bronjahm();
- AddSC_boss_devourer_of_souls();
- AddSC_instance_pit_of_saron(); //Pit of Saron
- AddSC_pit_of_saron();
- AddSC_boss_garfrost();
- AddSC_boss_ick();
- AddSC_boss_tyrannus();
- AddSC_instance_halls_of_reflection(); // Halls of Reflection
- AddSC_halls_of_reflection();
- AddSC_boss_falric();
- AddSC_boss_marwyn();
- AddSC_boss_lord_marrowgar(); // Icecrown Citadel
- AddSC_boss_lady_deathwhisper();
- AddSC_boss_icecrown_gunship_battle();
- AddSC_boss_deathbringer_saurfang();
- AddSC_boss_festergut();
- AddSC_boss_rotface();
- AddSC_boss_professor_putricide();
- AddSC_boss_blood_prince_council();
- AddSC_boss_blood_queen_lana_thel();
- AddSC_boss_valithria_dreamwalker();
- AddSC_boss_sindragosa();
- AddSC_boss_the_lich_king();
- AddSC_icecrown_citadel_teleport();
- AddSC_instance_icecrown_citadel();
- AddSC_icecrown_citadel();
- AddSC_instance_ruby_sanctum(); // Ruby Sanctum
- AddSC_ruby_sanctum();
- AddSC_boss_baltharus_the_warborn();
- AddSC_boss_saviana_ragefire();
- AddSC_boss_general_zarithrian();
- AddSC_boss_halion();
-
- AddSC_dalaran();
- AddSC_borean_tundra();
- AddSC_dragonblight();
- AddSC_grizzly_hills();
- AddSC_howling_fjord();
- AddSC_icecrown();
- AddSC_sholazar_basin();
- AddSC_storm_peaks();
- AddSC_wintergrasp();
- AddSC_zuldrak();
- AddSC_crystalsong_forest();
- AddSC_isle_of_conquest();
-#endif
-}
-
-
-void AddMaelstromScripts()
-{
-#ifdef SCRIPTS
- AddSC_kezan();
- AddSC_instance_stonecore(); // Stonecore
- AddSC_stonecore();
- AddSC_boss_corborus();
- AddSC_boss_slabhide();
- AddSC_boss_ozruk();
- AddSC_boss_high_priestess_azil();
-#endif
-}
-
-void AddEventScripts()
-{
-#ifdef SCRIPTS
- AddSC_event_childrens_week();
-#endif
-}
-
-void AddPetScripts()
-{
-#ifdef SCRIPTS
- AddSC_deathknight_pet_scripts();
- AddSC_generic_pet_scripts();
- AddSC_hunter_pet_scripts();
- AddSC_mage_pet_scripts();
- AddSC_priest_pet_scripts();
- AddSC_shaman_pet_scripts();
-#endif
-}
-
-void AddOutdoorPvPScripts()
-{
-#ifdef SCRIPTS
- AddSC_outdoorpvp_hp();
- AddSC_outdoorpvp_na();
- AddSC_outdoorpvp_si();
- AddSC_outdoorpvp_tf();
- AddSC_outdoorpvp_zm();
-#endif
-}
-
-void AddBattlegroundScripts()
-{
-#ifdef SCRIPTS
-#endif
-}
-
-#ifdef SCRIPTS
-/* This is where custom scripts' loading functions should be declared. */
-
-#endif
-
-void AddCustomScripts()
-{
-#ifdef SCRIPTS
- /* This is where custom scripts should be added. */
-
-#endif
-}
diff --git a/src/server/game/Scripting/ScriptLoader.h b/src/server/game/Scripting/ScriptLoader.h
index 5236f09445c..57b62df22d1 100644
--- a/src/server/game/Scripting/ScriptLoader.h
+++ b/src/server/game/Scripting/ScriptLoader.h
@@ -19,18 +19,5 @@
#define SC_SCRIPTLOADER_H
void AddScripts();
-void AddSpellScripts();
-void AddCommandScripts();
-void AddWorldScripts();
-void AddEasternKingdomsScripts();
-void AddKalimdorScripts();
-void AddOutlandScripts();
-void AddNorthrendScripts();
-void AddMaelstromScripts();
-void AddEventScripts();
-void AddPetScripts();
-void AddBattlegroundScripts();
-void AddOutdoorPvPScripts();
-void AddCustomScripts();
#endif
diff --git a/src/server/game/Server/BattlenetServerManager.cpp b/src/server/game/Server/BattlenetServerManager.cpp
index 726f12e588b..1256943e565 100644
--- a/src/server/game/Server/BattlenetServerManager.cpp
+++ b/src/server/game/Server/BattlenetServerManager.cpp
@@ -20,7 +20,7 @@
#include "ZmqContext.h"
#include "BattlenetServerManager.h"
-void Battlenet::ServerManager::InitializeConnection()
+void IPC::BattlenetComm::ServerManager::InitializeConnection()
{
std::string bnetserverAddress = sConfigMgr->GetStringDefault("BnetServer.Address", "127.0.0.1");
int32 bnetserverPort = sConfigMgr->GetIntDefault("BnetServer.Port", 1118);
@@ -28,23 +28,29 @@ void Battlenet::ServerManager::InitializeConnection()
_socket->Start();
}
-void Battlenet::ServerManager::CloseConnection()
+void IPC::BattlenetComm::ServerManager::CloseConnection()
{
_socket->End();
delete _socket;
_socket = nullptr;
}
-Battlenet::Header Battlenet::ServerManager::CreateHeader(BnetCommands command)
+IPC::BattlenetComm::ServerManager& IPC::BattlenetComm::ServerManager::Instance()
+{
+ static ServerManager instance;
+ return instance;
+}
+
+IPC::BattlenetComm::Header IPC::BattlenetComm::ServerManager::CreateHeader(BnetCommands command)
{
Header header;
header.Ipc.Channel = IPC_CHANNEL_BNET;
header.Ipc.Command = command;
- header.Realm = realmHandle;
+ header.Realm = realm.Id;
return header;
}
-void Battlenet::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online)
+void IPC::BattlenetComm::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online)
{
// Do nothing for Grunt login
if (!battlenetAccountId)
@@ -54,7 +60,7 @@ void Battlenet::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccount
ToonHandle toon;
toon.AccountId = battlenetAccountId;
toon.GameAccountId = gameAccountId;
- toon.Guid = guid;
+ toon.Guid = guid.GetCounter();
toon.Name = name;
zmqpp::message msg;
@@ -62,5 +68,13 @@ void Battlenet::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccount
msg << toon;
msg << online;
- _socket->Send(&msg);
+ Send(&msg);
+}
+
+void IPC::BattlenetComm::ServerManager::Send(zmqpp::message* msg)
+{
+ if (!_socket)
+ return;
+
+ _socket->Send(msg);
}
diff --git a/src/server/game/Server/BattlenetServerManager.h b/src/server/game/Server/BattlenetServerManager.h
index f1b90e46061..3892ac5040f 100644
--- a/src/server/game/Server/BattlenetServerManager.h
+++ b/src/server/game/Server/BattlenetServerManager.h
@@ -24,32 +24,34 @@
namespace zmqpp
{
class socket;
+ class message;
}
-namespace Battlenet
+namespace IPC
{
- class ServerManager
+ namespace BattlenetComm
{
- ServerManager() : _socket(nullptr) { }
-
- public:
- void InitializeConnection();
- void CloseConnection();
-
- static ServerManager& Instance()
+ class ServerManager
{
- static ServerManager instance;
- return instance;
- }
+ ServerManager() : _socket(nullptr) { }
- void SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online);
+ public:
+ void InitializeConnection();
+ void CloseConnection();
- private:
- static Header CreateHeader(BnetCommands command);
- ZmqMux* _socket;
- };
+ static ServerManager& Instance();
+
+ void SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online);
+
+ private:
+ void Send(zmqpp::message* msg);
+
+ static Header CreateHeader(BnetCommands command);
+ ZmqMux* _socket;
+ };
+ }
}
-#define sBattlenetServer Battlenet::ServerManager::Instance()
+#define sBattlenetServer IPC::BattlenetComm::ServerManager::Instance()
#endif // BattlenetMgr_h__
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index ef25610c0a9..2195edd0718 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -1160,7 +1160,7 @@ void WorldSession::LoadPermissions()
uint32 id = GetAccountId();
uint8 secLevel = GetSecurity();
- _RBACData = new rbac::RBACData(id, _accountName, realmHandle.Index, secLevel);
+ _RBACData = new rbac::RBACData(id, _accountName, realm.Id.Realm, secLevel);
_RBACData->LoadFromDB();
}
@@ -1170,9 +1170,9 @@ PreparedQueryResultFuture WorldSession::LoadPermissionsAsync()
uint8 secLevel = GetSecurity();
TC_LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: %u, Name: %s, realmId: %d, secLevel: %u]",
- id, _accountName.c_str(), realmHandle.Index, secLevel);
+ id, _accountName.c_str(), realm.Id.Realm, secLevel);
- _RBACData = new rbac::RBACData(id, _accountName, realmHandle.Index, secLevel);
+ _RBACData = new rbac::RBACData(id, _accountName, realm.Id.Realm, secLevel);
return _RBACData->LoadFromDBAsync();
}
@@ -1250,7 +1250,7 @@ bool WorldSession::HasPermission(uint32 permission)
bool hasPermission = _RBACData->HasPermission(permission);
TC_LOG_DEBUG("rbac", "WorldSession::HasPermission [AccountId: %u, Name: %s, realmId: %d]",
- _RBACData->GetId(), _RBACData->GetName().c_str(), realmHandle.Index);
+ _RBACData->GetId(), _RBACData->GetName().c_str(), realm.Id.Realm);
return hasPermission;
}
@@ -1258,7 +1258,7 @@ bool WorldSession::HasPermission(uint32 permission)
void WorldSession::InvalidateRBACData()
{
TC_LOG_DEBUG("rbac", "WorldSession::Invalidaterbac::RBACData [AccountId: %u, Name: %s, realmId: %d]",
- _RBACData->GetId(), _RBACData->GetName().c_str(), realmHandle.Index);
+ _RBACData->GetId(), _RBACData->GetName().c_str(), realm.Id.Realm);
delete _RBACData;
_RBACData = NULL;
}
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index ebab1955d24..0ee6cd930df 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -513,7 +513,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
authSession->Account = recvPacket.ReadString(accountNameLength);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
- stmt->setInt32(0, realmHandle.Index);
+ stmt->setInt32(0, int32(realm.Id.Realm));
stmt->setString(1, authSession->Account);
_queryCallback = std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1);
@@ -556,7 +556,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr authSes
return;
}
- if (authSession->RealmID != realmHandle.Index)
+ if (authSession->RealmID != realm.Id.Realm)
{
SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm).");
diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp
index 997b95e7e54..b2884d9fef3 100644
--- a/src/server/game/Weather/Weather.cpp
+++ b/src/server/game/Weather/Weather.cpp
@@ -153,7 +153,7 @@ bool Weather::ReGenerate()
uint32 chance2 = chance1+ m_weatherChances->data[season].snowChance;
uint32 chance3 = chance2+ m_weatherChances->data[season].stormChance;
- uint32 rnd = urand(0, 99);
+ uint32 rnd = urand(1, 100);
if (rnd <= chance1)
m_type = WEATHER_TYPE_RAIN;
else if (rnd <= chance2)
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 516dc8e5b47..69116de30f3 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1411,7 +1411,7 @@ void World::SetInitialWorldSettings()
uint32 server_type = IsFFAPvPRealm() ? uint32(REALM_TYPE_PVP) : getIntConfig(CONFIG_GAME_TYPE);
uint32 realm_zone = getIntConfig(CONFIG_REALM_ZONE);
- LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmHandle.Index); // One-time query
+ LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realm.Id.Realm); // One-time query
///- Load the DBC files
TC_LOG_INFO("server.loading", "Initialize data stores...");
@@ -1860,7 +1860,7 @@ void World::SetInitialWorldSettings()
m_startTime = m_gameTime;
LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')",
- realmHandle.Index, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query
+ realm.Id.Realm, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query
m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS);
m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS);
@@ -2146,7 +2146,7 @@ void World::Update(uint32 diff)
stmt->setUInt32(0, tmpDiff);
stmt->setUInt16(1, uint16(maxOnlinePlayers));
- stmt->setUInt32(2, realmHandle.Index);
+ stmt->setUInt32(2, realm.Id.Realm);
stmt->setUInt32(3, uint32(m_startTime));
LoginDatabase.Execute(stmt);
@@ -2876,13 +2876,13 @@ void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount)
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
stmt->setUInt32(0, accountId);
- stmt->setUInt32(1, realmHandle.Index);
+ stmt->setUInt32(1, realm.Id.Realm);
LoginDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS);
stmt->setUInt8(0, charCount);
stmt->setUInt32(1, accountId);
- stmt->setUInt32(2, realmHandle.Index);
+ stmt->setUInt32(2, realm.Id.Realm);
LoginDatabase.Execute(stmt);
}
}
@@ -3051,7 +3051,7 @@ void World::ResetCurrencyWeekCap()
void World::LoadDBAllowedSecurityLevel()
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL);
- stmt->setInt32(0, int32(realmHandle.Index));
+ stmt->setInt32(0, int32(realm.Id.Realm));
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (result)
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 57f190612df..620f7d6f697 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -30,6 +30,7 @@
#include "SharedDefines.h"
#include "QueryResult.h"
#include "Callback.h"
+#include "Realm/Realm.h"
#include
#include