diff options
668 files changed, 27056 insertions, 10735 deletions
diff --git a/.travis.yml b/.travis.yml index b53d4031a95..e71daad7408 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,13 +6,13 @@ git: depth: 1 before_install: - - echo "yes" | sudo add-apt-repository ppa:kalakris/cmake + - echo "yes" | sudo add-apt-repository ppa:george-edison55/precise-backports - echo "yes" | sudo add-apt-repository ppa:boost-latest/ppa - echo "yes" | sudo add-apt-repository ppa:ubuntu-toolchain-r/test - echo "yes" | sudo add-apt-repository 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.5 main' - wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - - sudo apt-get -qq update - - sudo apt-get -qq install build-essential libtool gcc-4.8 g++-4.8 make cmake openssl clang-3.5 + - sudo apt-get -qq install build-essential libtool gcc-4.8 g++-4.8 make cmake-data cmake openssl clang-3.5 - sudo apt-get -qq install libssl-dev libmysqlclient-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev libzmq3-dev - sudo apt-get -qq install libboost1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev libboost-iostreams1.55-dev libboost-regex1.55-dev - export CC=clang-3.5 CXX=clang++-3.5 @@ -21,7 +21,7 @@ install: - mysql -uroot -e 'create database test_mysql;' - mkdir bin - cd bin - - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" + - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DWITH_DYNAMIC_LINKING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" -DCMAKE_INSTALL_PREFIX=check_install - cd .. - sudo chmod +x contrib/check_updates.sh @@ -38,4 +38,7 @@ script: - cat sql/updates/hotfixes/*.sql | mysql -utrinity -ptrinity hotfixes - mysql -uroot < sql/create/drop_mysql.sql - cd bin - - make -j 8 -k + - make -j 8 -k && make install + - cd check_install/bin + - ./bnetserver --version + - ./worldserver --version diff --git a/CMakeLists.txt b/CMakeLists.txt index 5eeb5911ca9..dda8f242feb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,13 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# We require CMake >= 3.0 +cmake_minimum_required(VERSION 3.0) + # Set projectname (must be done AFTER setting configurationtypes) project(TrinityCore) # CMake policies (can not be handled elsewhere) -cmake_minimum_required(VERSION 2.8.9) cmake_policy(SET CMP0005 OLD) if(POLICY CMP0043) cmake_policy(SET CMP0043 OLD) # Disable 'Ignore COMPILE_DEFINITIONS_<Config> properties' @@ -51,23 +53,11 @@ endif() include(CheckPlatform) include(GroupSources) - -# basic packagesearching and setup (further support will be needed, this is a preliminary release!) -set(OPENSSL_EXPECTED_VERSION 1.0.0) +include(AutoCollect) find_package(PCHSupport) -find_package(OpenSSL REQUIRED) -find_package(Threads REQUIRED) find_package(MySQL) -include(ConfigureBoost) - -if( UNIX ) - find_package(Readline) - find_package(ZLIB) - find_package(BZip2) -endif() - if(NOT WITHOUT_GIT) find_package(Git) endif() diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake index 261a55b285f..9a8cb85275e 100644 --- a/cmake/compiler/clang/settings.cmake +++ b/cmake/compiler/clang/settings.cmake @@ -18,3 +18,16 @@ endif() # -Wno-deprecated-register is needed to suppress 185 gsoap warnings on Unix systems. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1") + +if (WITH_DYNAMIC_LINKING) + # -fPIC is needed to allow static linking in shared libs. + # -fvisibility=hidden sets the default visibility to hidden to prevent exporting of all symbols. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden") + + # --no-undefined to throw errors when there are undefined symbols + # (caused through missing TRINITY_*_API macros). + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --no-undefined") + + message(STATUS "Clang: Disallow undefined symbols") +endif() diff --git a/cmake/compiler/gcc/settings.cmake b/cmake/compiler/gcc/settings.cmake index acd71e82fd9..d9eda767b8e 100644 --- a/cmake/compiler/gcc/settings.cmake +++ b/cmake/compiler/gcc/settings.cmake @@ -34,3 +34,15 @@ if( WITH_COREDEBUG ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") message(STATUS "GCC: Debug-flags set (-g3)") endif() + +if (WITH_DYNAMIC_LINKING) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes") + + # Should break the build when there are TRINITY_*_API macros missing + # but it complains about missing references in precompiled headers. + # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--no-undefined") + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-undefined") + + message(STATUS "GCC: Enabled shared linking") +endif() diff --git a/cmake/compiler/msvc/settings.cmake b/cmake/compiler/msvc/settings.cmake index f4ed0e12786..86470f327c5 100644 --- a/cmake/compiler/msvc/settings.cmake +++ b/cmake/compiler/msvc/settings.cmake @@ -18,11 +18,6 @@ if(PLATFORM EQUAL 64) add_definitions("-D_WIN64") message(STATUS "MSVC: 64-bit platform, enforced -D_WIN64 parameter") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) - #Enable extended object support for debug compiles on X64 (not required on X86) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj") - message(STATUS "MSVC: Enabled increased number of sections in object files") - endif() else() # mark 32 bit executables large address aware so they can use > 2GB address space set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") @@ -41,15 +36,20 @@ add_definitions(-D_BUILD_DIRECTIVE=\\"$(ConfigurationName)\\") # multithreaded compiling on VS set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +if((PLATFORM EQUAL 64) OR (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) OR WITH_DYNAMIC_LINKING) + # Enable extended object support + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") + message(STATUS "MSVC: Enabled increased number of sections in object files") +endif() + # /Zc:throwingNew. # When you specify Zc:throwingNew on the command line, it instructs the compiler to assume # that the program will eventually be linked with a conforming operator new implementation, # and can omit all of these extra null checks from your program. # http://blogs.msdn.com/b/vcblog/archive/2015/08/06/new-in-vs-2015-zc-throwingnew.aspx if(NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0)) - # also enable /bigobj for ALL builds under visual studio 2015, increased number of templates in standard library # makes this flag a requirement to build TC at all - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew /bigobj") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew") endif() # Define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES - eliminates the warning by changing the strcpy call to strcpy_s, which prevents buffer overruns @@ -75,6 +75,13 @@ if(NOT WITH_WARNINGS) message(STATUS "MSVC: Disabled generic compiletime warnings") endif() +if (WITH_DYNAMIC_LINKING) + # C4251: needs to have dll-interface to be used by clients of class '...' + # C4275: non dll-interface class ...' used as base for dll-interface class '...' + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251 /wd4275") + message(STATUS "MSVC: Enabled shared linking") +endif() + # Specify the maximum PreCompiled Header memory allocation limit # Fixes a compiler-problem when using PCH - the /Ym flag is adjusted by the compiler in MSVC2012, hence we need to set an upper limit with /Zm to avoid discrepancies) # (And yes, this is a verified , unresolved bug with MSVC... *sigh*) @@ -85,3 +92,15 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm500") # 'function' : member function does not override any base class virtual member function # 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4263 /we4264") + +# Disable incremental linking in debug builds. +# To prevent linking getting stuck (which might be fixed in a later VS version). +macro(DisableIncrementalLinking variable) + string(REGEX REPLACE "/INCREMENTAL *" "" ${variable} "${${variable}}") + set(${variable} "${${variable}} /INCREMENTAL:NO") +endmacro() + +DisableIncrementalLinking(CMAKE_EXE_LINKER_FLAGS_DEBUG) +DisableIncrementalLinking(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO) +DisableIncrementalLinking(CMAKE_SHARED_LINKER_FLAGS_DEBUG) +DisableIncrementalLinking(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO) diff --git a/cmake/macros/AutoCollect.cmake b/cmake/macros/AutoCollect.cmake new file mode 100644 index 00000000000..cddd3a20290 --- /dev/null +++ b/cmake/macros/AutoCollect.cmake @@ -0,0 +1,71 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# Collects all source files into the given variable, +# which is useful to include all sources in subdirectories. +# Ignores full qualified directories listed in the variadic arguments. +# +# Use it like: +# CollectSourceFiles( +# ${CMAKE_CURRENT_SOURCE_DIR} +# COMMON_PRIVATE_SOURCES +# # Exclude +# ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders +# ${CMAKE_CURRENT_SOURCE_DIR}/Platform) +# +function(CollectSourceFiles current_dir variable) + list(FIND ARGN "${current_dir}" IS_EXCLUDED) + if(IS_EXCLUDED EQUAL -1) + file(GLOB COLLECTED_SOURCES + ${current_dir}/*.c + ${current_dir}/*.cc + ${current_dir}/*.cpp + ${current_dir}/*.inl + ${current_dir}/*.def + ${current_dir}/*.h + ${current_dir}/*.hh + ${current_dir}/*.hpp) + list(APPEND ${variable} ${COLLECTED_SOURCES}) + + file(GLOB SUB_DIRECTORIES ${current_dir}/*) + foreach(SUB_DIRECTORY ${SUB_DIRECTORIES}) + if (IS_DIRECTORY ${SUB_DIRECTORY}) + CollectSourceFiles("${SUB_DIRECTORY}" "${variable}" "${ARGN}") + endif() + endforeach() + set(${variable} ${${variable}} PARENT_SCOPE) + endif() +endfunction() + +# Collects all subdirectoroies into the given variable, +# which is useful to include all subdirectories. +# Ignores full qualified directories listed in the variadic arguments. +# +# Use it like: +# CollectIncludeDirectories( +# ${CMAKE_CURRENT_SOURCE_DIR} +# COMMON_PUBLIC_INCLUDES +# # Exclude +# ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders +# ${CMAKE_CURRENT_SOURCE_DIR}/Platform) +# +function(CollectIncludeDirectories current_dir variable) + list(FIND ARGN "${current_dir}" IS_EXCLUDED) + if(IS_EXCLUDED EQUAL -1) + list(APPEND ${variable} ${current_dir}) + file(GLOB SUB_DIRECTORIES ${current_dir}/*) + foreach(SUB_DIRECTORY ${SUB_DIRECTORIES}) + if (IS_DIRECTORY ${SUB_DIRECTORY}) + CollectIncludeDirectories("${SUB_DIRECTORY}" "${variable}" "${ARGN}") + endif() + endforeach() + set(${variable} ${${variable}} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/macros/FindPCHSupport.cmake b/cmake/macros/FindPCHSupport.cmake index 49d4be904d1..6edc8e92890 100644 --- a/cmake/macros/FindPCHSupport.cmake +++ b/cmake/macros/FindPCHSupport.cmake @@ -1,17 +1,49 @@ -FUNCTION(GET_COMMON_PCH_PARAMS PCH_HEADER PCH_FE INCLUDE_PREFIX) +FUNCTION(GET_COMMON_PCH_PARAMS TARGET_NAME_LIST PCH_HEADER PCH_FE INCLUDE_PREFIX) GET_FILENAME_COMPONENT(PCH_HEADER_N ${PCH_HEADER} NAME) GET_DIRECTORY_PROPERTY(TARGET_INCLUDES INCLUDE_DIRECTORIES) + # Stores the inherited dependency definitions and include directories + # from the given target into the given variables + MACRO(CollectIncludes target inherited_includes inherited_definitions) + # Append the includes and definitions of the current target to the list + get_property(included TARGET ${target} PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + LIST(APPEND "${inherited_includes}" ${included}) + get_property(definitions TARGET ${target} PROPERTY INTERFACE_COMPILE_DEFINITIONS) + FOREACH(def ${definitions}) + LIST(APPEND "${inherited_definitions}" "-D${def}") + ENDFOREACH() + # Add all inherited link targets which weren't included already + get_property(links TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES) + # TODO Maybe catch circular dependencies? + FOREACH(target_link ${links}) + IF(TARGET ${target_link}) + CollectIncludes(${target_link} "${inherited_includes}" "${inherited_definitions}") + ENDIF() + ENDFOREACH() + ENDMACRO() + + FOREACH(TARGET_NAME ${TARGET_NAME_LIST}) + CollectIncludes(${TARGET_NAME} TARGET_INCLUDES TARGET_DEFINITIONS) + ENDFOREACH() + + LIST(REMOVE_DUPLICATES TARGET_INCLUDES) + LIST(REMOVE_DUPLICATES TARGET_DEFINITIONS) + FOREACH(ITEM ${TARGET_INCLUDES}) LIST(APPEND INCLUDE_FLAGS_LIST "${INCLUDE_PREFIX}\"${ITEM}\" ") ENDFOREACH(ITEM) + SET(PCH_INCLUDES ${TARGET_INCLUDES} PARENT_SCOPE) + SET(PCH_DEFINITIONS ${TARGET_DEFINITIONS} PARENT_SCOPE) SET(PCH_HEADER_NAME ${PCH_HEADER_N} PARENT_SCOPE) SET(PCH_HEADER_OUT ${CMAKE_CURRENT_BINARY_DIR}/${PCH_HEADER_N}.${PCH_FE} PARENT_SCOPE) SET(INCLUDE_FLAGS ${INCLUDE_FLAGS_LIST} PARENT_SCOPE) ENDFUNCTION(GET_COMMON_PCH_PARAMS) FUNCTION(GENERATE_CXX_PCH_COMMAND TARGET_NAME_LIST INCLUDE_FLAGS IN PCH_SRC OUT) + include_directories(${PCH_INCLUDES}) + add_definitions(${PCH_DEFINITIONS}) + IF (CMAKE_BUILD_TYPE) STRING(TOUPPER _${CMAKE_BUILD_TYPE} CURRENT_BUILD_TYPE) ENDIF () @@ -62,7 +94,7 @@ FUNCTION(GENERATE_CXX_PCH_COMMAND TARGET_NAME_LIST INCLUDE_FLAGS IN PCH_SRC OUT) ENDFUNCTION(GENERATE_CXX_PCH_COMMAND) FUNCTION(ADD_CXX_PCH_GCC TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) - GET_COMMON_PCH_PARAMS(${PCH_HEADER} "gch" "-I") + GET_COMMON_PCH_PARAMS("${TARGET_NAME_LIST}" ${PCH_HEADER} "gch" "-I") GENERATE_CXX_PCH_COMMAND("${TARGET_NAME_LIST}" "${INCLUDE_FLAGS}" ${PCH_HEADER} ${PCH_SOURCE} ${PCH_HEADER_OUT}) FOREACH(TARGET_NAME ${TARGET_NAME_LIST}) @@ -74,7 +106,7 @@ FUNCTION(ADD_CXX_PCH_GCC TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) ENDFUNCTION(ADD_CXX_PCH_GCC) FUNCTION(ADD_CXX_PCH_CLANG TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) - GET_COMMON_PCH_PARAMS(${PCH_HEADER} "pch" "-I") + GET_COMMON_PCH_PARAMS("${TARGET_NAME_LIST}" ${PCH_HEADER} "pch" "-I") GENERATE_CXX_PCH_COMMAND("${TARGET_NAME_LIST}" "${INCLUDE_FLAGS}" ${PCH_HEADER} ${PCH_SOURCE} ${PCH_HEADER_OUT}) FOREACH(TARGET_NAME ${TARGET_NAME_LIST}) @@ -86,7 +118,7 @@ FUNCTION(ADD_CXX_PCH_CLANG TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) ENDFUNCTION(ADD_CXX_PCH_CLANG) FUNCTION(ADD_CXX_PCH_MSVC TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) - GET_COMMON_PCH_PARAMS(${PCH_HEADER} "pch" "/I") + GET_COMMON_PCH_PARAMS("${TARGET_NAME_LIST}" ${PCH_HEADER} "pch" "/I") FOREACH(TARGET_NAME ${TARGET_NAME_LIST}) SET_TARGET_PROPERTIES( diff --git a/cmake/macros/FindReadline.cmake b/cmake/macros/FindReadline.cmake deleted file mode 100644 index 34af35204b5..00000000000 --- a/cmake/macros/FindReadline.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# find Readline (terminal input library) includes and library -# -# READLINE_INCLUDE_DIR - where the directory containing the READLINE headers can be found -# READLINE_LIBRARY - full path to the READLINE library -# READLINE_FOUND - TRUE if READLINE was found - -FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h) -FIND_LIBRARY(READLINE_LIBRARY NAMES readline) - -IF (READLINE_INCLUDE_DIR AND READLINE_LIBRARY) - SET(READLINE_FOUND TRUE) - MESSAGE(STATUS "Found Readline library: ${READLINE_LIBRARY}") - MESSAGE(STATUS "Include dir is: ${READLINE_INCLUDE_DIR}") - INCLUDE_DIRECTORIES(${READLINE_INCLUDE_DIR}) -ELSE (READLINE_INCLUDE_DIR AND READLINE_LIBRARY) - SET(READLINE_FOUND FALSE) - MESSAGE(FATAL_ERROR "** Readline library not found!\n** Your distro may provide a binary for Readline e.g. for ubuntu try apt-get install libreadline5-dev") -ENDIF (READLINE_INCLUDE_DIR AND READLINE_LIBRARY) diff --git a/cmake/macros/FindZMQ.cmake b/cmake/macros/FindZMQ.cmake deleted file mode 100644 index 4f415c539bf..00000000000 --- a/cmake/macros/FindZMQ.cmake +++ /dev/null @@ -1,89 +0,0 @@ -# -# Find the ZMQ includes and library -# - -# This module defines -# ZMQ_INCLUDE_DIR, where to find zmq.h -# ZMQ_LIBRARY, the library needed to use ZMQ -# ZMQ_FOUND, if false, you cannot build anything that requires ZMQ. - -set(ZMQ_FOUND 0) - -if (PLATFORM EQUAL 64) - set(ZMQ_REGISTRY_PATH - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ (x64);DisplayIcon]" - ) -else() - set(ZMQ_REGISTRY_PATH - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayIcon]" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayIcon]" - ) -endif() - -find_path(ZMQ_ROOT_DIR - NAMES - include/zmq.h - HINTS - ${ZMQ_REGISTRY_PATH} - PATHS - /usr - /usr/local -) - -find_path(ZMQ_INCLUDE_DIR zmq.h ${ZMQ_ROOT_DIR}/include) - -if (MSVC) - # Read registry key holding version - if (PLATFORM EQUAL 64) - get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ (x64);DisplayVersion]" NAME) - else() - get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayVersion]" NAME) - if (${ZMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned - get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayVersion]" NAME) - endif() - endif() - - # Replace dots with underscores - string(REGEX REPLACE "\\." "_" ZMQ_NAME ${ZMQ_NAME}) - - # Get Visual studio version number - string(REGEX REPLACE "Visual Studio ([0-9]+).*" "\\1" ZMQ_VS_VERSION ${CMAKE_GENERATOR}) - - # HACK - zmq doesnt ship libs for VS 2015 - if (${ZMQ_VS_VERSION} EQUAL 14) - set(ZMQ_VS_VERSION 12) - endif() - - if (${ZMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned - set(_ZMQ_VERSIONS "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0" "3_2_5" "3_2_4" "3_2_3" "3_2_2" "3_2_1" "3_2_0" "3_1_0") - set(ZMQ_LIBRARY_NAME) - foreach(ver ${_ZMQ_VERSIONS}) - list(APPEND ZMQ_LIBRARY_NAME "libzmq-v${ZMQ_VS_VERSION}0-mt-${ver}") - endforeach() - else() - # Format ZMQ library file name - set(ZMQ_LIBRARY_NAME "libzmq-v${ZMQ_VS_VERSION}0-mt-${ZMQ_NAME}") - endif() -endif() - -find_library(ZMQ_LIBRARY - NAMES - zmq - ${ZMQ_LIBRARY_NAME} - PATHS - /lib - /usr/lib - /usr/local/lib - "${ZMQ_ROOT_DIR}/lib" -) - -if (ZMQ_INCLUDE_DIR AND ZMQ_LIBRARY AND NOT ZMQ_LIBRARY-NOTFOUND) - set(ZMQ_FOUND 1) - message(STATUS "Found ZMQ library: ${ZMQ_LIBRARY}") - message(STATUS "Found ZMQ headers: ${ZMQ_INCLUDE_DIR}") -else() - message(FATAL_ERROR "Could not find ZMQ libraries/headers! Please install ZMQ with libraries and headers") -endif() - -# show the ZMQ_INCLUDE_DIR and ZMQ_LIBRARY variables only in the advanced view -mark_as_advanced(ZMQ_ROOT_DIR ZMQ_INCLUDE_DIR ZMQ_LIBRARY ZMQ_FOUND) diff --git a/cmake/macros/GroupSources.cmake b/cmake/macros/GroupSources.cmake index 198d8c3e187..f8e252fe41a 100644 --- a/cmake/macros/GroupSources.cmake +++ b/cmake/macros/GroupSources.cmake @@ -10,7 +10,7 @@ macro(GroupSources dir) # Skip this if WITH_SOURCE_TREE is not set (empty string). - if (NOT ${_WITH_SOURCE_TREE} STREQUAL "") + if (NOT ${WITH_SOURCE_TREE} STREQUAL "") # Include all header and c files file(GLOB_RECURSE elements RELATIVE ${dir} *.h *.hpp *.c *.cpp *.cc) @@ -21,7 +21,7 @@ macro(GroupSources dir) if (NOT ${element_dir} STREQUAL "") # If the file is in a subdirectory use it as source group. - if (${_WITH_SOURCE_TREE} STREQUAL "flat") + if (${WITH_SOURCE_TREE} STREQUAL "flat") # Build flat structure by using only the first subdirectory. string(FIND ${element_dir} "/" delemiter_pos) if (NOT ${delemiter_pos} EQUAL -1) @@ -44,3 +44,8 @@ macro(GroupSources dir) endforeach() endif() endmacro() + +if (WITH_SOURCE_TREE STREQUAL "hierarchical-folders") + # Use folders + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() diff --git a/cmake/options.cmake b/cmake/options.cmake index 23c913363e1..1a028959047 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -13,8 +13,9 @@ option(SCRIPTS "Build core with scripts included" option(TOOLS "Build map/vmap/mmap extraction/assembler tools" 0) option(USE_SCRIPTPCH "Use precompiled headers when compiling scripts" 1) option(USE_COREPCH "Use precompiled headers when compiling servers" 1) +option(WITH_DYNAMIC_LINKING "Enable dynamic library linking." 0) option(WITH_WARNINGS "Show all warnings during compile" 0) option(WITH_COREDEBUG "Include additional debug-code in core" 0) -set(WITH_SOURCE_TREE "no" CACHE STRING "Build the source tree for IDE's.") -set_property(CACHE WITH_SOURCE_TREE PROPERTY STRINGS no flat hierarchical) +set(WITH_SOURCE_TREE "hierarchical" CACHE STRING "Build the source tree for IDE's.") +set_property(CACHE WITH_SOURCE_TREE PROPERTY STRINGS no flat hierarchical hierarchical-folders) option(WITHOUT_GIT "Disable the GIT testing routines" 0) diff --git a/cmake/platform/unix/settings.cmake b/cmake/platform/unix/settings.cmake index 754ff450fcc..79b426d7e03 100644 --- a/cmake/platform/unix/settings.cmake +++ b/cmake/platform/unix/settings.cmake @@ -1,12 +1,3 @@ -# Package overloads - Linux -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - if (NOT NOJEM) - set(JEMALLOC_LIBRARY "jemalloc") - add_definitions(-DNO_BUFFERPOOL) - message(STATUS "UNIX: Using jemalloc") - endif() -endif() - # set default configuration directory if( NOT CONF_DIR ) set(CONF_DIR ${CMAKE_INSTALL_PREFIX}/etc) @@ -38,7 +29,7 @@ if(CMAKE_C_COMPILER MATCHES "gcc" OR CMAKE_C_COMPILER_ID STREQUAL "GNU") include(${CMAKE_SOURCE_DIR}/cmake/compiler/gcc/settings.cmake) elseif(CMAKE_C_COMPILER MATCHES "icc") include(${CMAKE_SOURCE_DIR}/cmake/compiler/icc/settings.cmake) -elseif(CMAKE_C_COMPILER MATCHES "clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") +elseif(CMAKE_C_COMPILER MATCHES "clang" OR CMAKE_C_COMPILER_ID MATCHES "Clang") include(${CMAKE_SOURCE_DIR}/cmake/compiler/clang/settings.cmake) else() add_definitions(-D_BUILD_DIRECTIVE='"${CMAKE_BUILD_TYPE}"') diff --git a/cmake/platform/win/settings.cmake b/cmake/platform/win/settings.cmake index c68d7bc51cc..da66daf0832 100644 --- a/cmake/platform/win/settings.cmake +++ b/cmake/platform/win/settings.cmake @@ -1,7 +1,3 @@ -# Package overloads -set(BZIP2_LIBRARIES "bzip2") -set(ZLIB_LIBRARIES "zlib") - # check the CMake preload parameters (commented out by default) # overload CMAKE_INSTALL_PREFIX if not being set properly @@ -13,6 +9,10 @@ set(ZLIB_LIBRARIES "zlib") # endif() #endif() +if (WIN32) + add_definitions(-D_WIN32_WINNT=0x0601) +endif() + if ( MSVC ) include(${CMAKE_SOURCE_DIR}/cmake/compiler/msvc/settings.cmake) elseif ( MINGW ) diff --git a/cmake/showoptions.cmake b/cmake/showoptions.cmake index 51b22c3a863..b485cfe5ce6 100644 --- a/cmake/showoptions.cmake +++ b/cmake/showoptions.cmake @@ -69,27 +69,10 @@ else() message("* Use coreside debug : No (default)") endif() -if( WITH_SOURCE_TREE STREQUAL "flat" OR WITH_SOURCE_TREE STREQUAL "hierarchical" ) - # TODO: Remove this after Debian 8 is released and set general required version to 2.8.12 - # Debian 7 is shipped with CMake 2.8.9 . But DIRECTORY flag of get_filename_component requires 2.8.12 . - if (NOT CMAKE_VERSION VERSION_LESS 2.8.12) - message("* Show source tree : Yes - ${WITH_SOURCE_TREE}") - set(_WITH_SOURCE_TREE ${WITH_SOURCE_TREE} CACHE INTERNAL "WITH_SOURCE_TREE support enabled.") - else() - message("* Show source tree : No (default)") - - message("") - message(" *** WITH_SOURCE_TREE - WARNING!") - message(" *** This functionality is ONLY supported on CMake 2.8.12 or higher.") - message(" *** You are running ${CMAKE_VERSION}, which does not have the functions needed") - message(" *** to create a sourcetree - this option is thus forced to disabled!") - message("") - - set(_WITH_SOURCE_TREE "" CACHE INTERNAL "WITH_SOURCE_TREE support disabled.") - endif() +if( NOT WITH_SOURCE_TREE STREQUAL "no" ) + message("* Show source tree : Yes - \"${WITH_SOURCE_TREE}\"") else() - message("* Show source tree : No (default)") - set(_WITH_SOURCE_TREE "" CACHE INTERNAL "WITH_SOURCE_TREE support disabled.") + message("* Show source tree : No") endif() if ( WITHOUT_GIT ) @@ -130,5 +113,15 @@ if ( HELGRIND ) add_definitions(-DHELGRIND) endif() -message("") +if (WITH_DYNAMIC_LINKING) + message("") + message(" *** WITH_DYNAMIC_LINKING - INFO!") + message(" *** Will link against shared libraries!") + message(" *** Please note that this is an experimental feature!") + add_definitions(-DTRINITY_API_USE_DYNAMIC_LINKING) + set(BUILD_SHARED_LIBS ON) +else() + set(BUILD_SHARED_LIBS OFF) +endif() +message("") diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt index 6caa1e1e70c..acbef0ca106 100644 --- a/dep/CMakeLists.txt +++ b/dep/CMakeLists.txt @@ -14,32 +14,31 @@ else() add_definitions(-w) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - if(SERVERS AND NOT NOJEM) - add_subdirectory(jemalloc) - endif() -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Windows") - if(TOOLS) - add_subdirectory(bzip2) - endif() - if(SERVERS OR TOOLS) - add_subdirectory(zlib) - endif() -endif() +add_subdirectory(threads) if(SERVERS OR TOOLS) + add_subdirectory(boost) + add_subdirectory(zlib) add_subdirectory(g3dlite) add_subdirectory(recastnavigation) + add_subdirectory(jemalloc) add_subdirectory(cppformat) + add_subdirectory(SFMT) + add_subdirectory(utf8cpp) + add_subdirectory(valgrind) + add_subdirectory(openssl) endif() if(SERVERS) + add_subdirectory(mysql) + add_subdirectory(process) + add_subdirectory(readline) add_subdirectory(gsoap) - add_subdirectory(zmqpp) + add_subdirectory(rapidjson) + add_subdirectory(efsw) endif() if(TOOLS) + add_subdirectory(bzip2) add_subdirectory(CascLib) endif() diff --git a/dep/CascLib/CMakeLists.txt b/dep/CascLib/CMakeLists.txt index 83b7ea38493..79be0a0830c 100644 --- a/dep/CascLib/CMakeLists.txt +++ b/dep/CascLib/CMakeLists.txt @@ -44,6 +44,15 @@ set(TOMCRYPT_FILES src/libtomcrypt/src/misc/crypt_libc.c ) -include_directories(${CMAKE_SOURCE_DIR}/dep) - add_library(casc STATIC ${SRC_FILES} ${TOMCRYPT_FILES}) + +target_include_directories(casc + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + PRIVATE + ${CMAKE_SOURCE_DIR}/dep) + +set_target_properties(casc + PROPERTIES + FOLDER + "dep") diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 5ad9cef5982..1e45d515902 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -1,6 +1,6 @@ TrinityCore uses (parts of or in whole) the following opensource software : -Boost +Boost (external) http://www.boost.org Version: 1.55 @@ -14,7 +14,11 @@ bzip2 (a freely available, patent free, high-quality data compressor) cppformat (type safe format library) https://github.com/cppformat/cppformat - Version: 5c76d107cbaf5e851bd66b6c563e4fc7c90be7ad + Version: 5174b8ca281426af604b85fdf53be8a748b33f56 + +efws (Entropia File System Watcher - crossplatform file system watcher) + https://bitbucket.org/SpartanJ/efsw + ff0b69daeca1edf7785a8a580518e462be5a6f3d G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License) http://g3d.sourceforge.net/ @@ -24,6 +28,14 @@ jemalloc (a general-purpose scalable concurrent malloc-implementation) http://www.canonware.com/jemalloc/ Version: 3.6.0 +libreadline (command line editing library) + https://cnswww.cns.cwru.edu/php/chet/readline/rltop.html + Version: external + +OpenSSL (general-purpose cryptography library) + https://www.openssl.org/ + Version: external + SFMT (SIMD-oriented Fast Mersenne Twister) Based on http://agner.org/random/ Version: 2010-Aug-03 @@ -48,7 +60,6 @@ CascLib (An open-source implementation of library for reading CASC storage from https://github.com/ladislav-zezula/CascLib Version: 919a2d670cb749c501ee15887a88e9b9a538961b -zmqpp (C++ binding for 0mq/zmq is a 'high-level' library that hides most of the c-style interface core 0mq provides.) - https://github.com/zeromq/zmqpp - Version: 3.2.0 17e9f6afa98f56ecac1e3f3eecbfc112357a6732 - +rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/) + https://github.com/miloyip/rapidjson + Version: v1.0.2 diff --git a/dep/SFMT/CMakeLists.txt b/dep/SFMT/CMakeLists.txt new file mode 100644 index 00000000000..5cf1b9bf972 --- /dev/null +++ b/dep/SFMT/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library(sfmt INTERFACE) + +target_include_directories(sfmt + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/cmake/macros/ConfigureBoost.cmake b/dep/boost/CMakeLists.txt index 3db9fc54a8c..118635c85bd 100644 --- a/cmake/macros/ConfigureBoost.cmake +++ b/dep/boost/CMakeLists.txt @@ -1,3 +1,13 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + if(WIN32) set(BOOST_DEBUG ON) if(DEFINED ENV{BOOST_ROOT}) @@ -14,14 +24,9 @@ if(WIN32) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) - - add_definitions(-D_WIN32_WINNT=0x0601) endif() find_package(Boost 1.51 REQUIRED system filesystem thread program_options iostreams regex) -add_definitions(-DBOOST_DATE_TIME_NO_LIB) -add_definitions(-DBOOST_REGEX_NO_LIB) -add_definitions(-DBOOST_CHRONO_NO_LIB) # Find if Boost was compiled in C++03 mode because it requires -DBOOST_NO_CXX11_SCOPED_ENUMS @@ -41,9 +46,22 @@ unset(CMAKE_REQUIRED_LIBRARIES CACHE) unset(CMAKE_REQUIRED_FLAGS CACHE) if (NOT boost_filesystem_copy_links_without_NO_SCOPED_ENUM) - add_definitions(-DBOOST_NO_CXX11_SCOPED_ENUMS) + set(OPTIONAL_BOOST_NO_SCOPED_ENUMS -DBOOST_NO_CXX11_SCOPED_ENUMS) endif() -if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) -endif() +add_library(boost INTERFACE) + +target_link_libraries(boost + INTERFACE + ${Boost_LIBRARIES}) + +target_include_directories(boost + INTERFACE + ${Boost_INCLUDE_DIRS}) + +target_compile_definitions(boost + INTERFACE + -DBOOST_DATE_TIME_NO_LIB + -DBOOST_REGEX_NO_LIB + -DBOOST_CHRONO_NO_LIB + ${OPTIONAL_BOOST_NO_SCOPED_ENUMS}) diff --git a/dep/bzip2/CMakeLists.txt b/dep/bzip2/CMakeLists.txt index d3aadbe002e..d5a7414f383 100644 --- a/dep/bzip2/CMakeLists.txt +++ b/dep/bzip2/CMakeLists.txt @@ -8,15 +8,30 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB sources *.c) +if(UNIX) + # Look for an installed bzip2 on unix + find_package(BZip2 REQUIRED) -set(bzip2_STAT_SRCS - ${sources} -) + add_library(bzip2 SHARED IMPORTED GLOBAL) -include_directories( - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_CURRENT_SOURCE_DIR} -) + set_target_properties(bzip2 + PROPERTIES + IMPORTED_LOCATION + "${BZIP2_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES + "${BZIP2_INCLUDE_DIRS}") +else() + # Use the bundled source on windows + file(GLOB sources *.c) + add_library(bzip2 STATIC + ${sources}) -add_library(bzip2 STATIC ${bzip2_STAT_SRCS}) + target_include_directories(bzip2 + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + + set_target_properties(bzip2 + PROPERTIES + FOLDER + "dep") +endif() diff --git a/dep/cppformat/CMakeLists.txt b/dep/cppformat/CMakeLists.txt index 3be3e5f6dbb..1cbff49b871 100644 --- a/dep/cppformat/CMakeLists.txt +++ b/dep/cppformat/CMakeLists.txt @@ -1,31 +1,37 @@ -include(CheckCXXCompilerFlag) -include(CheckSymbolExists) - -set(FMT_SOURCES format.cc format.h) - -# Use variadic templates -add_definitions(-DFMT_VARIADIC_TEMPLATES=1) - -# Use deleted functions -add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1) - -# Use static assert -add_definitions(-DFMT_USE_STATIC_ASSERT=1) +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +include(CheckSymbolExists) if (WIN32) check_symbol_exists(open io.h HAVE_OPEN) else () check_symbol_exists(open fcntl.h HAVE_OPEN) endif () +set(FMT_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/format.h + ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/format.cc) + if (HAVE_OPEN) - add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1) - set(FMT_SOURCES ${FMT_SOURCES} posix.cc posix.h) -endif () + set(FMT_SOURCES ${FMT_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/posix.h + ${CMAKE_CURRENT_SOURCE_DIR}/cppformat/posix.cc) +endif() -add_library(format STATIC ${FMT_SOURCES}) +add_library(cppformat STATIC ${FMT_SOURCES}) -if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(format PROPERTIES COMPILE_FLAGS - "-Wall -Wextra -Wshadow -pedantic") -endif () +target_include_directories(cppformat + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +set_target_properties(cppformat + PROPERTIES + FOLDER + "dep") diff --git a/dep/cppformat/README.rst b/dep/cppformat/README.rst index fb4399f0af4..e859f909466 100644 --- a/dep/cppformat/README.rst +++ b/dep/cppformat/README.rst @@ -28,9 +28,9 @@ Features * Format API with `format string syntax <http://cppformat.github.io/latest/syntax.html>`_ similar to the one used by `str.format - <http://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python. + <https://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python. * Safe `printf implementation - <http://cppformat.github.io/latest/reference.html#printf-formatting-functions>`_ + <http://cppformat.github.io/latest/api.html#printf-formatting-functions>`_ including the POSIX extension for positional arguments. * Support for user-defined types. * High speed: performance of the format API is close to that of @@ -103,10 +103,10 @@ An object of any user-defined type for which there is an overloaded // s == "The date is 2012-12-9" You can use the `FMT_VARIADIC -<http://cppformat.github.io/latest/reference.html#utilities>`_ +<http://cppformat.github.io/latest/api.html#utilities>`_ macro to create your own functions similar to `format -<http://cppformat.github.io/latest/reference.html#format>`_ and -`print <http://cppformat.github.io/latest/reference.html#print>`_ +<http://cppformat.github.io/latest/api.html#format>`_ and +`print <http://cppformat.github.io/latest/api.html#print>`_ which take arbitrary arguments: .. code:: c++ @@ -132,13 +132,17 @@ Projects using this library * `AMPL/MP <https://github.com/ampl/mp>`_: An open-source library for mathematical programming -* `HarpyWar/pvpgn <https://github.com/HarpyWar/pvpgn>`_: +* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_: Player vs Player Gaming Network with tweaks -* `KBEngine <http://www.kbengine.org/>`_: An open-source MMOG server engine +* `KBEngine <http://kbengine.org/>`_: An open-source MMOG server engine + +* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows * `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game +* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets + * `PenUltima Online (POL) <http://www.polserver.com/>`_: An MMO server, compatible with most Ultima Online clients @@ -148,7 +152,7 @@ Projects using this library * `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster proxy -* `Saddy <https://code.google.com/p/saddy/>`_: +* `Saddy <https://github.com/mamontov-cpp/saddy-graphics-engine-2d>`_: Small crossplatform 2D graphic engine * `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_: @@ -188,7 +192,7 @@ doesn't support user-defined types. Printf also has safety issues although they are mostly solved with `__attribute__ ((format (printf, ...)) <http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC. There is a POSIX extension that adds positional arguments required for -`i18n <http://en.wikipedia.org/wiki/Internationalization_and_localization>`_ +`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_ to printf but it is not a part of C99 and may not be available on some platforms. @@ -376,18 +380,13 @@ C++ Format is distributed under the BSD `license The `Format String Syntax <http://cppformat.github.io/latest/syntax.html>`_ section in the documentation is based on the one from Python `string module -documentation <http://docs.python.org/3/library/string.html#module-string>`_ +documentation <https://docs.python.org/3/library/string.html#module-string>`_ adapted for the current library. For this reason the documentation is distributed under the Python Software Foundation license available in `doc/python-license.txt <https://raw.github.com/cppformat/cppformat/master/doc/python-license.txt>`_. It only applies if you distribute the documentation of C++ Format. -Links ------ - -`API changes/compatibility report <http://upstream-tracker.org/versions/cppformat.html>`_ - Acknowledgments --------------- diff --git a/dep/cppformat/format.cc b/dep/cppformat/cppformat/format.cc index 1970d53c500..daccd68f1da 100644 --- a/dep/cppformat/format.cc +++ b/dep/cppformat/cppformat/format.cc @@ -207,10 +207,15 @@ void format_error_code(fmt::Writer &out, int error_code, out.clear(); static const char SEP[] = ": "; static const char ERROR_STR[] = "error "; - fmt::internal::IntTraits<int>::MainType ec_value = error_code; // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; - error_code_size += fmt::internal::count_digits(ec_value); + typedef fmt::internal::IntTraits<int>::MainType MainType; + MainType abs_value = static_cast<MainType>(error_code); + if (internal::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += fmt::internal::count_digits(abs_value); if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size) out << message << SEP; out << ERROR_STR << error_code; @@ -252,7 +257,7 @@ class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> { template <typename T> unsigned visit_any_int(T value) { typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType; - UnsignedType width = value; + UnsignedType width = static_cast<UnsignedType>(value); if (fmt::internal::is_negative(value)) { spec_.align_ = fmt::ALIGN_LEFT; width = 0 - width; @@ -278,8 +283,21 @@ class PrecisionHandler : } }; -// Converts an integer argument to an integral type T for printf. +template <typename T, typename U> +struct is_same { + enum { value = 0 }; +}; + template <typename T> +struct is_same<T, T> { + enum { value = 1 }; +}; + +// An argument visitor that converts an integer argument to T for printf, +// if T is an integral type. If T is void, the argument is converted to +// corresponding signed or unsigned type depending on the type specifier: +// 'd' and 'i' - signed, other - unsigned) +template <typename T = void> class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> { private: fmt::internal::Arg &arg_; @@ -300,21 +318,25 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> { void visit_any_int(U value) { bool is_signed = type_ == 'd' || type_ == 'i'; using fmt::internal::Arg; - if (sizeof(T) <= sizeof(int)) { + typedef typename fmt::internal::Conditional< + is_same<T, void>::value, U, T>::type TargetType; + if (sizeof(TargetType) <= sizeof(int)) { // Extra casts are used to silence warnings. if (is_signed) { arg_.type = Arg::INT; - arg_.int_value = static_cast<int>(static_cast<T>(value)); + arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); } else { arg_.type = Arg::UINT; - arg_.uint_value = static_cast<unsigned>( - static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value)); + typedef typename fmt::internal::MakeUnsigned<TargetType>::Type Unsigned; + arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); } } else { if (is_signed) { arg_.type = Arg::LONG_LONG; - arg_.long_long_value = - static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value); + // glibc's printf doesn't sign extend arguments of smaller types: + // std::printf("%lld", -42); // prints "4294967254" + // but we don't have to do the same because it's a UB. + arg_.long_long_value = static_cast<fmt::LongLong>(value); } else { arg_.type = Arg::ULONG_LONG; arg_.ulong_long_value = @@ -340,6 +362,21 @@ class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> { arg_.int_value = static_cast<char>(value); } }; + +// Write the content of w to os. +void write(std::ostream &os, fmt::Writer &w) { + const char *data = w.data(); + typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize; + UnsignedStreamSize size = w.size(); + UnsignedStreamSize max_size = + internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); + do { + UnsignedStreamSize n = size <= max_size ? size : max_size; + os.write(data, static_cast<std::streamsize>(n)); + data += n; + size -= n; + } while (size != 0); +} } // namespace namespace internal { @@ -551,27 +588,25 @@ FMT_FUNC void fmt::WindowsError::init( FMT_FUNC void fmt::internal::format_windows_error( fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT { - class String { - private: - LPWSTR str_; - - public: - String() : str_() {} - ~String() { LocalFree(str_); } - LPWSTR *ptr() { return &str_; } - LPCWSTR c_str() const { return str_; } - }; FMT_TRY { - String system_message; - if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, - error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) { - UTF16ToUTF8 utf8_message; - if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) { - out << message << ": " << utf8_message; - return; + MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer; + buffer.resize(INLINE_BUFFER_SIZE); + for (;;) { + wchar_t *system_message = &buffer[0]; + int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + system_message, static_cast<uint32_t>(buffer.size()), 0); + if (result != 0) { + UTF16ToUTF8 utf8_message; + if (utf8_message.convert(system_message) == ERROR_SUCCESS) { + out << message << ": " << utf8_message; + return; + } + break; } + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; // Can't get error message, report error code instead. + buffer.resize(buffer.size() * 2); } } FMT_CATCH(...) {} fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. @@ -616,7 +651,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) { return; case internal::Arg::NAMED_ARG: named_arg = static_cast<const NamedArg*>(args.values_[i].pointer); - map_.insert(Pair(named_arg->name, *named_arg)); + map_.push_back(Pair(named_arg->name, *named_arg)); break; default: /*nothing*/; @@ -628,7 +663,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) { internal::Arg::Type arg_type = args.type(i); if (arg_type == internal::Arg::NAMED_ARG) { named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); - map_.insert(Pair(named_arg->name, *named_arg)); + map_.push_back(Pair(named_arg->name, *named_arg)); } } for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) { @@ -637,7 +672,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) { return; case internal::Arg::NAMED_ARG: named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); - map_.insert(Pair(named_arg->name, *named_arg)); + map_.push_back(Pair(named_arg->name, *named_arg)); break; default: /*nothing*/; @@ -659,6 +694,7 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( break; case Arg::NAMED_ARG: arg = *static_cast<const internal::Arg*>(arg.pointer); + break; default: /*nothing*/; } @@ -763,7 +799,7 @@ void fmt::internal::PrintfFormatter<Char>::format( if (*s == '.') { ++s; if ('0' <= *s && *s <= '9') { - spec.precision_ = parse_nonnegative_int(s); + spec.precision_ = static_cast<int>(parse_nonnegative_int(s)); } else if (*s == '*') { ++s; spec.precision_ = PrecisionHandler().visit(get_arg(s)); @@ -772,7 +808,7 @@ void fmt::internal::PrintfFormatter<Char>::format( Arg arg = get_arg(s, arg_index); if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg)) - spec.flags_ &= ~HASH_FLAG; + spec.flags_ &= ~to_unsigned<int>(HASH_FLAG); if (spec.fill_ == '0') { if (arg.type <= Arg::LAST_NUMERIC_TYPE) spec.align_ = ALIGN_NUMERIC; @@ -809,7 +845,7 @@ void fmt::internal::PrintfFormatter<Char>::format( break; default: --s; - ArgConverter<int>(arg, *s).visit(arg); + ArgConverter<void>(arg, *s).visit(arg); } // Parse type. @@ -861,10 +897,11 @@ FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { print(stdout, format_str, args); } -FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) { +FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, + ArgList args) { MemoryWriter w; w.write(format_str, args); - os.write(w.data(), w.size()); + write(os, w); } FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { @@ -882,6 +919,13 @@ FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) { return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size); } +FMT_FUNC int fmt::fprintf(std::ostream &os, CStringRef format, ArgList args) { + MemoryWriter w; + printf(w, format, args); + write(os, w); + return static_cast<int>(w.size()); +} + #ifndef FMT_HEADER_ONLY template struct fmt::internal::BasicData<void>; diff --git a/dep/cppformat/format.h b/dep/cppformat/cppformat/format.h index a98a166091b..08bb9b5d9e8 100644 --- a/dep/cppformat/format.h +++ b/dep/cppformat/cppformat/format.h @@ -28,14 +28,6 @@ #ifndef FMT_FORMAT_H_ #define FMT_FORMAT_H_ -#if defined _MSC_VER && _MSC_VER <= 1500 -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -typedef long long intmax_t; -#else -#include <stdint.h> -#endif - #include <cassert> #include <cmath> #include <cstdio> @@ -44,7 +36,8 @@ typedef long long intmax_t; #include <memory> #include <stdexcept> #include <string> -#include <map> +#include <vector> +#include <utility> #ifndef FMT_USE_IOSTREAMS # define FMT_USE_IOSTREAMS 1 @@ -64,40 +57,23 @@ typedef long long intmax_t; # include <iterator> #endif -#ifdef _MSC_VER -# include <intrin.h> // _BitScanReverse, _BitScanReverse64 - -namespace fmt { -namespace internal { -# pragma intrinsic(_BitScanReverse) -inline uint32_t clz(uint32_t x) { - unsigned long r = 0; - _BitScanReverse(&r, x); - return 31 - r; -} -# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n) - -# ifdef _WIN64 -# pragma intrinsic(_BitScanReverse64) -# endif - -inline uint32_t clzll(uint64_t x) { - unsigned long r = 0; -# ifdef _WIN64 - _BitScanReverse64(&r, x); -# else - // Scan the high 32 bits. - if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) - return 63 - (r + 32); +#if defined(_MSC_VER) && _MSC_VER <= 1500 +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +typedef __int64 intmax_t; +#else +#include <stdint.h> +#endif - // Scan the low 32 bits. - _BitScanReverse(&r, static_cast<uint32_t>(x)); +#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) +# ifdef FMT_EXPORT +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) # endif - return 63 - r; -} -# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n) -} -} +#endif +#ifndef FMT_API +# define FMT_API #endif #ifdef __GNUC__ @@ -174,21 +150,6 @@ inline uint32_t clzll(uint64_t x) { # include <utility> // for std::move #endif -// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature). -#ifndef FMT_USE_NOEXCEPT -# define FMT_USE_NOEXCEPT 0 -#endif - -#ifndef FMT_NOEXCEPT -# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ - (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - _MSC_VER >= 1900 -# define FMT_NOEXCEPT noexcept -# else -# define FMT_NOEXCEPT throw() -# endif -#endif - // Check if exceptions are disabled. #if defined(__GNUC__) && !defined(__EXCEPTIONS) # define FMT_EXCEPTIONS 0 @@ -208,6 +169,25 @@ inline uint32_t clzll(uint64_t x) { # endif #endif +// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature). +#ifndef FMT_USE_NOEXCEPT +# define FMT_USE_NOEXCEPT 0 +#endif + +#ifndef FMT_NOEXCEPT +# if FMT_EXCEPTIONS +# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ + _MSC_VER >= 1900 +# define FMT_NOEXCEPT noexcept +# else +# define FMT_NOEXCEPT throw() +# endif +# else +# define FMT_NOEXCEPT +# endif +#endif + // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #ifndef FMT_USE_DELETED_FUNCTIONS @@ -241,6 +221,67 @@ inline uint32_t clzll(uint64_t x) { # define FMT_ASSERT(condition, message) assert((condition) && message) #endif + +#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +#endif + +#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +#endif + +// Some compilers masquerade as both MSVC and GCC-likes or +// otherwise support __builtin_clz and __builtin_clzll, so +// only define FMT_BUILTIN_CLZ using the MSVC intrinsics +// if the clz and clzll builtins are not available. +#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL) +# include <intrin.h> // _BitScanReverse, _BitScanReverse64 + +namespace fmt { +namespace internal { +# pragma intrinsic(_BitScanReverse) +inline uint32_t clz(uint32_t x) { + unsigned long r = 0; + _BitScanReverse(&r, x); + + assert(x != 0); + // Static analysis complains about using uninitialized data + // "r", but the only way that can happen is if "x" is 0, + // which the callers guarantee to not happen. +# pragma warning(suppress: 6102) + return 31 - r; +} +# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n) + +# ifdef _WIN64 +# pragma intrinsic(_BitScanReverse64) +# endif + +inline uint32_t clzll(uint64_t x) { + unsigned long r = 0; +# ifdef _WIN64 + _BitScanReverse64(&r, x); +# else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) + return 63 - (r + 32); + + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast<uint32_t>(x)); +# endif + + assert(x != 0); + // Static analysis complains about using uninitialized data + // "r", but the only way that can happen is if "x" is 0, + // which the callers guarantee to not happen. +# pragma warning(suppress: 6102) + return 63 - r; +} +# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n) +} +} +#endif + namespace fmt { namespace internal { struct DummyInt { @@ -396,7 +437,7 @@ class BasicStringRef { return std::basic_string<Char>(data_, size_); } - /** Returns the pointer to a C string. */ + /** Returns a pointer to the string data. */ const Char *data() const { return data_; } /** Returns the string size. */ @@ -492,6 +533,29 @@ class FormatError : public std::runtime_error { }; namespace internal { + +// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T. +template <typename T> +struct MakeUnsigned { typedef T Type; }; + +#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \ + template <> \ + struct MakeUnsigned<T> { typedef U Type; } + +FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char); +FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char); +FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short); +FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned); +FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long); +FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong); + +// Casts nonnegative integer to unsigned. +template <typename Int> +inline typename MakeUnsigned<Int>::Type to_unsigned(Int value) { + FMT_ASSERT(value >= 0, "negative value"); + return static_cast<typename MakeUnsigned<Int>::Type>(value); +} + // The number of characters to store in the MemoryBuffer object itself // to avoid dynamic memory allocation. enum { INLINE_BUFFER_SIZE = 500 }; @@ -581,8 +645,7 @@ class Buffer { template <typename T> template <typename U> void Buffer<T>::append(const U *begin, const U *end) { - assert(begin <= end); - std::size_t new_size = size_ + (end - begin); + std::size_t new_size = size_ + internal::to_unsigned(end - begin); if (new_size > capacity_) grow(new_size); std::uninitialized_copy(begin, end, @@ -592,8 +655,8 @@ void Buffer<T>::append(const U *begin, const U *end) { namespace internal { -// A memory buffer for POD types with the first SIZE elements stored in -// the object itself. +// A memory buffer for trivially copyable/constructible types with the first SIZE +// elements stored in the object itself. template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> > class MemoryBuffer : private Allocator, public Buffer<T> { private: @@ -676,7 +739,7 @@ class FixedBuffer : public fmt::Buffer<Char> { FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {} protected: - void grow(std::size_t size); + FMT_API void grow(std::size_t size); }; template <typename Char> @@ -704,7 +767,7 @@ class CharTraits<char> : public BasicCharTraits<char> { // Formats a floating-point number. template <typename T> - static int format_float(char *buffer, std::size_t size, + FMT_API static int format_float(char *buffer, std::size_t size, const char *format, unsigned width, int precision, T value); }; @@ -715,7 +778,7 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> { static wchar_t convert(wchar_t value) { return value; } template <typename T> - static int format_float(wchar_t *buffer, std::size_t size, + FMT_API static int format_float(wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, T value); }; @@ -754,27 +817,12 @@ struct IntTraits { TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType; }; -// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T. -template <typename T> -struct MakeUnsigned { typedef T Type; }; - -#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \ - template <> \ - struct MakeUnsigned<T> { typedef U Type; } - -FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char); -FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char); -FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short); -FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned); -FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long); -FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong); - -void report_unknown_type(char code, const char *type); +FMT_API void report_unknown_type(char code, const char *type); // Static data is placed in this class template to allow header-only // configuration. template <typename T = void> -struct BasicData { +struct FMT_API BasicData { static const uint32_t POWERS_OF_10_32[]; static const uint64_t POWERS_OF_10_64[]; static const char DIGITS[]; @@ -782,22 +830,14 @@ struct BasicData { typedef BasicData<> Data; -#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) -# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) -#endif - -#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) -# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) -#endif - #ifdef FMT_BUILTIN_CLZLL // Returns the number of decimal digits in n. Leading zeros are not counted // except for n == 0 in which case count_digits returns 1. inline unsigned count_digits(uint64_t n) { // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits. - unsigned t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12; - return t - (n < Data::POWERS_OF_10_64[t]) + 1; + int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12; + return to_unsigned(t) - (n < Data::POWERS_OF_10_64[t]) + 1; } #else // Fallback version of count_digits used when __builtin_clz is not available. @@ -820,8 +860,8 @@ inline unsigned count_digits(uint64_t n) { #ifdef FMT_BUILTIN_CLZ // Optional version of count_digits for better performance on 32-bit platforms. inline unsigned count_digits(uint32_t n) { - uint32_t t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12; - return t - (n < Data::POWERS_OF_10_32[t]) + 1; + int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12; + return to_unsigned(t) - (n < Data::POWERS_OF_10_32[t]) + 1; } #endif @@ -863,7 +903,7 @@ class UTF8ToUTF16 { MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer_; public: - explicit UTF8ToUTF16(StringRef s); + FMT_API explicit UTF8ToUTF16(StringRef s); operator WStringRef() const { return WStringRef(&buffer_[0], size()); } size_t size() const { return buffer_.size() - 1; } const wchar_t *c_str() const { return &buffer_[0]; } @@ -878,7 +918,7 @@ class UTF16ToUTF8 { public: UTF16ToUTF8() {} - explicit UTF16ToUTF8(WStringRef s); + FMT_API explicit UTF16ToUTF8(WStringRef s); operator StringRef() const { return StringRef(&buffer_[0], size()); } size_t size() const { return buffer_.size() - 1; } const char *c_str() const { return &buffer_[0]; } @@ -887,15 +927,15 @@ class UTF16ToUTF8 { // Performs conversion returning a system error code instead of // throwing exception on conversion error. This method may still throw // in case of memory allocation error. - int convert(WStringRef s); + FMT_API int convert(WStringRef s); }; -void format_windows_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT; +FMT_API void format_windows_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT; #endif -void format_system_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT; +FMT_API void format_system_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT; // A formatting argument value. struct Value { @@ -938,8 +978,8 @@ struct Value { }; }; -// A formatting argument. It is a POD type to allow storage in -// internal::MemoryBuffer. +// A formatting argument. It is a trivially copyable/constructible type to +// allow storage in internal::MemoryBuffer. struct Arg : Value { Type type; }; @@ -976,6 +1016,7 @@ template <typename T> T &get(); struct DummyStream : std::ostream { + DummyStream(); // Suppress a bogus warning in MSVC. // Hide all operator<< overloads from std::ostream. void operator<<(Null<>); }; @@ -1199,17 +1240,27 @@ class MakeValue : public Arg { static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; } }; +template <typename Formatter> +class MakeArg : public Arg { +public: + MakeArg() { + type = Arg::NONE; + } + + template <typename T> + MakeArg(const T &value) + : Arg(MakeValue<Formatter>(value)) { + type = static_cast<Arg::Type>(MakeValue<Formatter>::type(value)); + } +}; + template <typename Char> struct NamedArg : Arg { BasicStringRef<Char> name; - typedef internal::MakeValue< BasicFormatter<Char> > MakeValue; - template <typename T> NamedArg(BasicStringRef<Char> argname, const T &value) - : Arg(MakeValue(value)), name(argname) { - type = static_cast<Arg::Type>(MakeValue::type(value)); - } + : Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {} }; #define FMT_DISPATCH(call) static_cast<Impl*>(this)->call @@ -1631,17 +1682,22 @@ namespace internal { template <typename Char> class ArgMap { private: - typedef std::map<fmt::BasicStringRef<Char>, internal::Arg> MapType; + typedef std::vector<std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType; typedef typename MapType::value_type Pair; MapType map_; public: - void init(const ArgList &args); + FMT_API void init(const ArgList &args); const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const { - typename MapType::const_iterator it = map_.find(name); - return it != map_.end() ? &it->second : 0; + // The list is unsorted, so just return the first matching name. + for (typename MapType::const_iterator it = map_.begin(), end = map_.end(); + it != end; ++it) { + if (it->first == name) + return &it->second; + } + return 0; } }; @@ -1767,7 +1823,7 @@ class FormatterBase { int next_arg_index_; // Returns the argument with specified index. - Arg do_get_arg(unsigned arg_index, const char *&error); + FMT_API Arg do_get_arg(unsigned arg_index, const char *&error); protected: const ArgList &args() const { return args_; } @@ -1780,7 +1836,7 @@ class FormatterBase { // Returns the next argument. Arg next_arg(const char *&error) { if (next_arg_index_ >= 0) - return do_get_arg(next_arg_index_++, error); + return do_get_arg(internal::to_unsigned(next_arg_index_++), error); error = "cannot switch from manual to automatic argument indexing"; return Arg(); } @@ -1803,7 +1859,7 @@ class FormatterBase { template <typename Char> void write(BasicWriter<Char> &w, const Char *start, const Char *end) { if (start != end) - w << BasicStringRef<Char>(start, end - start); + w << BasicStringRef<Char>(start, internal::to_unsigned(end - start)); } }; @@ -1823,14 +1879,16 @@ class PrintfFormatter : private FormatterBase { public: explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {} - void format(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str); + FMT_API void format(BasicWriter<Char> &writer, + BasicCStringRef<Char> format_str); }; } // namespace internal -// A formatter. +/** This template formats data and writes the output to a writer. */ template <typename CharType> class BasicFormatter : private internal::FormatterBase { public: + /** The character type for the output. */ typedef CharType Char; private: @@ -1852,13 +1910,23 @@ class BasicFormatter : private internal::FormatterBase { internal::Arg parse_arg_name(const Char *&s); public: + /** + \rst + Constructs a ``BasicFormatter`` object. References to the arguments and + the writer are stored in the formatter object so make sure they have + appropriate lifetimes. + \endrst + */ BasicFormatter(const ArgList &args, BasicWriter<Char> &w) : internal::FormatterBase(args), writer_(w) {} + /** Returns a reference to the writer associated with this formatter. */ BasicWriter<Char> &writer() { return writer_; } + /** Formats stored arguments and writes the output to the writer. */ void format(BasicCStringRef<Char> format_str); + // Formats a single argument and advances format_str, a format string pointer. const Char *format(const Char *&format_str, const internal::Arg &arg); }; @@ -1889,16 +1957,29 @@ inline uint64_t make_type(const T &arg) { return MakeValue< BasicFormatter<char> >::type(arg); } +template <unsigned N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)> +struct ArgArray; + +template <unsigned N> +struct ArgArray<N, true/*IsPacked*/> { + typedef Value Type[N > 0 ? N : 1]; + + template <typename Formatter, typename T> + static Value make(const T &value) { + Value result = MakeValue<Formatter>(value); + // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: + // https://github.com/cppformat/cppformat/issues/276 + (void)result.custom.format; + return result; + } +}; + template <unsigned N> -struct ArgArray { - // Computes the argument array size by adding 1 to N, which is the number of - // arguments, if N is zero, because array of zero size is invalid, or if N - // is greater than ArgList::MAX_PACKED_ARGS to accommodate for an extra - // argument that marks the end of the list. - enum { SIZE = N + (N == 0 || N >= ArgList::MAX_PACKED_ARGS ? 1 : 0) }; - - typedef typename Conditional< - (N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE]; +struct ArgArray<N, false/*IsPacked*/> { + typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE + + template <typename Formatter, typename T> + static Arg make(const T &value) { return MakeArg<Formatter>(value); } }; #if FMT_USE_VARIADIC_TEMPLATES @@ -1907,47 +1988,6 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) { return make_type(first) | (make_type(tail...) << 4); } -inline void do_set_types(Arg *) {} - -template <typename T, typename... Args> -inline void do_set_types(Arg *args, const T &arg, const Args & ... tail) { - args->type = static_cast<Arg::Type>( - MakeValue< BasicFormatter<char> >::type(arg)); - do_set_types(args + 1, tail...); -} - -template <typename... Args> -inline void set_types(Arg *array, const Args & ... args) { - if (check(sizeof...(Args) > ArgList::MAX_PACKED_ARGS)) - do_set_types(array, args...); - array[sizeof...(Args)].type = Arg::NONE; -} - -template <typename... Args> -inline void set_types(Value *, const Args & ...) { - // Do nothing as types are passed separately from values. -} - -template <typename Formatter, typename Value> -inline void store_args(Value *) {} - -template <typename Formatter, typename Arg, typename T, typename... Args> -inline void store_args(Arg *args, const T &arg, const Args & ... tail) { - // Assign only the Value subobject of Arg and don't overwrite type (if any) - // that is assigned by set_types. - Value &value = *args; - value = MakeValue<Formatter>(arg); - store_args<Formatter>(args + 1, tail...); -} - -template <typename Formatter, typename... Args> -ArgList make_arg_list(typename ArgArray<sizeof...(Args)>::Type array, - const Args & ... args) { - if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS)) - set_types(array, args...); - store_args<Formatter>(array, args...); - return ArgList(make_type(args...), array); -} #else struct ArgType { @@ -1985,7 +2025,7 @@ class FormatBuf : public std::basic_streambuf<Char> { int_type overflow(int_type ch = traits_type::eof()) { if (!traits_type::eq_int_type(ch, traits_type::eof())) { - size_t size = this->pptr() - start_; + size_t size = this->size(); buffer_.resize(size); buffer_.reserve(size * 2); @@ -1997,7 +2037,7 @@ class FormatBuf : public std::basic_streambuf<Char> { } size_t size() const { - return this->pptr() - start_; + return to_unsigned(this->pptr() - start_); } }; } // namespace internal @@ -2015,18 +2055,20 @@ class FormatBuf : public std::basic_streambuf<Char> { # define FMT_VARIADIC_VOID(func, arg_type) \ template <typename... Args> \ void func(arg_type arg0, const Args & ... args) { \ - typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \ - func(arg0, fmt::internal::make_arg_list< \ - fmt::BasicFormatter<Char> >(array, args...)); \ + typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \ + func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \ } // Defines a variadic constructor. # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ template <typename... Args> \ ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ - typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \ - func(arg0, arg1, fmt::internal::make_arg_list< \ - fmt::BasicFormatter<Char> >(array, args...)); \ + typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \ + func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \ } #else @@ -2207,7 +2249,8 @@ class BasicWriter { // Writes a decimal integer. template <typename Int> void write_decimal(Int value) { - typename internal::IntTraits<Int>::MainType abs_value = value; + typedef typename internal::IntTraits<Int>::MainType MainType; + MainType abs_value = static_cast<MainType>(value); if (internal::is_negative(value)) { abs_value = 0 - abs_value; *write_unsigned_decimal(abs_value, 1) = '-'; @@ -2474,9 +2517,9 @@ void BasicWriter<Char>::write_str( return; } } - std::size_t precision = spec.precision_; + std::size_t precision = static_cast<std::size_t>(spec.precision_); if (spec.precision_ >= 0 && precision < str_size) - str_size = spec.precision_; + str_size = precision; write_str(str_value, str_size, spec); } @@ -2510,7 +2553,8 @@ typename BasicWriter<Char>::CharPtr // is specified. if (prefix_size > 0 && prefix[prefix_size - 1] == '0') --prefix_size; - unsigned number_size = prefix_size + spec.precision(); + unsigned number_size = + prefix_size + internal::to_unsigned(spec.precision()); AlignSpec subspec(number_size, '0', ALIGN_NUMERIC); if (number_size >= width) return prepare_int_buffer(num_digits, subspec, prefix, prefix_size); @@ -2564,7 +2608,7 @@ template <typename T, typename Spec> void BasicWriter<Char>::write_int(T value, Spec spec) { unsigned prefix_size = 0; typedef typename internal::IntTraits<T>::MainType UnsignedType; - UnsignedType abs_value = value; + UnsignedType abs_value = static_cast<UnsignedType>(value); char prefix[4] = ""; if (internal::is_negative(value)) { prefix[0] = '-'; @@ -2643,8 +2687,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) { template <typename Char> template <typename T> -void BasicWriter<Char>::write_double( - T value, const FormatSpec &spec) { +void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) { // Check type. char type = spec.type(); bool upper = false; @@ -2744,6 +2787,8 @@ void BasicWriter<Char>::write_double( // Format using snprintf. Char fill = internal::CharTraits<Char>::cast(spec.fill()); + unsigned n = 0; + Char *start = 0; for (;;) { std::size_t buffer_size = buffer_.capacity() - offset; #ifdef _MSC_VER @@ -2755,41 +2800,44 @@ void BasicWriter<Char>::write_double( buffer_size = buffer_.capacity() - offset; } #endif - Char *start = &buffer_[offset]; - int n = internal::CharTraits<Char>::format_float( + start = &buffer_[offset]; + int result = internal::CharTraits<Char>::format_float( start, buffer_size, format, width_for_sprintf, spec.precision(), value); - if (n >= 0 && offset + n < buffer_.capacity()) { - if (sign) { - if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) || - *start != ' ') { - *(start - 1) = sign; - sign = 0; - } else { - *(start - 1) = fill; - } - ++n; - } - if (spec.align() == ALIGN_CENTER && - spec.width() > static_cast<unsigned>(n)) { - width = spec.width(); - CharPtr p = grow_buffer(width); - std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char)); - fill_padding(p, spec.width(), n, fill); - return; - } - if (spec.fill() != ' ' || sign) { - while (*start == ' ') - *start++ = fill; - if (sign) - *(start - 1) = sign; - } - grow_buffer(n); - return; + if (result >= 0) { + n = internal::to_unsigned(result); + if (offset + n < buffer_.capacity()) + break; // The buffer is large enough - continue with formatting. + buffer_.reserve(offset + n + 1); + } else { + // If result is negative we ask to increase the capacity by at least 1, + // but as std::vector, the buffer grows exponentially. + buffer_.reserve(buffer_.capacity() + 1); } - // If n is negative we ask to increase the capacity by at least 1, - // but as std::vector, the buffer grows exponentially. - buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1); } + if (sign) { + if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) || + *start != ' ') { + *(start - 1) = sign; + sign = 0; + } else { + *(start - 1) = fill; + } + ++n; + } + if (spec.align() == ALIGN_CENTER && spec.width() > n) { + width = spec.width(); + CharPtr p = grow_buffer(width); + std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char)); + fill_padding(p, spec.width(), n, fill); + return; + } + if (spec.fill() != ' ' || sign) { + while (*start == ' ') + *start++ = fill; + if (sign) + *(start - 1) = sign; + } + grow_buffer(n); } /** @@ -2920,22 +2968,21 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) { output << value; BasicStringRef<Char> str(&buffer[0], format_buf.size()); - typedef internal::MakeValue< BasicFormatter<Char> > MakeValue; - internal::Arg arg = MakeValue(str); - arg.type = static_cast<internal::Arg::Type>(MakeValue::type(str)); - format_str = f.format(format_str, arg); + typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; + format_str = f.format(format_str, MakeArg(str)); } // Reports a system error without throwing an exception. // Can be used to report errors from destructors. -void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT; +FMT_API void report_system_error(int error_code, + StringRef message) FMT_NOEXCEPT; #if FMT_USE_WINDOWS_H /** A Windows error. */ class WindowsError : public SystemError { private: - void init(int error_code, CStringRef format_str, ArgList args); + FMT_API void init(int error_code, CStringRef format_str, ArgList args); public: /** @@ -2974,7 +3021,8 @@ class WindowsError : public SystemError { // Reports a Windows error without throwing an exception. // Can be used to report errors from destructors. -void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT; +FMT_API void report_windows_error(int error_code, + StringRef message) FMT_NOEXCEPT; #endif @@ -2986,7 +3034,7 @@ enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; Example: print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23); */ -void print_colored(Color c, CStringRef format, ArgList args); +FMT_API void print_colored(Color c, CStringRef format, ArgList args); /** \rst @@ -3018,7 +3066,7 @@ inline std::wstring format(WCStringRef format_str, ArgList args) { print(stderr, "Don't {}!", "panic"); \endrst */ -void print(std::FILE *f, CStringRef format_str, ArgList args); +FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args); /** \rst @@ -3029,7 +3077,7 @@ void print(std::FILE *f, CStringRef format_str, ArgList args); print("Elapsed time: {0:.2f} seconds", 1.23); \endrst */ -void print(CStringRef format_str, ArgList args); +FMT_API void print(CStringRef format_str, ArgList args); template <typename Char> void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) { @@ -3066,7 +3114,7 @@ inline std::wstring sprintf(WCStringRef format, ArgList args) { fmt::fprintf(stderr, "Don't %s!", "panic"); \endrst */ -int fprintf(std::FILE *f, CStringRef format, ArgList args); +FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args); /** \rst @@ -3132,10 +3180,10 @@ class FormatInt { explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {} explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {} - /** - Returns the number of characters written to the output buffer. - */ - std::size_t size() const { return buffer_ - str_ + BUFFER_SIZE - 1; } + /** Returns the number of characters written to the output buffer. */ + std::size_t size() const { + return internal::to_unsigned(buffer_ - str_ + BUFFER_SIZE - 1); + } /** Returns a pointer to the output buffer content. No terminating null @@ -3165,7 +3213,8 @@ class FormatInt { // write a terminating null character. template <typename T> inline void format_decimal(char *&buffer, T value) { - typename internal::IntTraits<T>::MainType abs_value = value; + typedef typename internal::IntTraits<T>::MainType MainType; + MainType abs_value = static_cast<MainType>(value); if (internal::is_negative(value)) { *buffer++ = '-'; abs_value = 0 - abs_value; @@ -3245,10 +3294,11 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED; template <typename... Args> \ ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ const Args & ... args) { \ - typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \ + typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::internal::make_arg_list< \ - fmt::BasicFormatter<Char> >(array, args...)); \ + fmt::ArgList(fmt::internal::make_type(args...), array)); \ } #else // Defines a wrapper for a function taking __VA_ARGS__ arguments @@ -3361,8 +3411,20 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) print(cerr, "Don't {}!", "panic"); \endrst */ -void print(std::ostream &os, CStringRef format_str, ArgList args); +FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); FMT_VARIADIC(void, print, std::ostream &, CStringRef) + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + fprintf(cerr, "Don't %s!", "panic"); + \endrst + */ +FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) #endif namespace internal { @@ -3374,7 +3436,7 @@ inline bool is_name_start(Char c) { // Parses an unsigned integer advancing s to the end of the parsed input. // This function assumes that the first character of s is a digit. template <typename Char> -int parse_nonnegative_int(const Char *&s) { +unsigned parse_nonnegative_int(const Char *&s) { assert('0' <= *s && *s <= '9'); unsigned value = 0; do { @@ -3453,7 +3515,6 @@ inline internal::Arg BasicFormatter<Char>::parse_arg_name(const Char *&s) { return arg; } -// Should be after FormatSpec template <typename Char> const Char *BasicFormatter<Char>::format( const Char *&format_str, const internal::Arg &arg) { diff --git a/dep/cppformat/posix.cc b/dep/cppformat/cppformat/posix.cc index 756281a0ebd..c6c2ae2c413 100644 --- a/dep/cppformat/posix.cc +++ b/dep/cppformat/cppformat/posix.cc @@ -173,7 +173,7 @@ std::size_t fmt::File::read(void *buffer, std::size_t count) { FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count)))); if (result < 0) throw SystemError(errno, "cannot read from file"); - return result; + return internal::to_unsigned(result); } std::size_t fmt::File::write(const void *buffer, std::size_t count) { @@ -181,7 +181,7 @@ std::size_t fmt::File::write(const void *buffer, std::size_t count) { FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count)))); if (result < 0) throw SystemError(errno, "cannot write to file"); - return result; + return internal::to_unsigned(result); } fmt::File fmt::File::dup(int fd) { diff --git a/dep/cppformat/posix.h b/dep/cppformat/cppformat/posix.h index 88bcb4f557b..bfbd3851838 100644 --- a/dep/cppformat/posix.h +++ b/dep/cppformat/cppformat/posix.h @@ -34,11 +34,17 @@ #endif #include <errno.h> -#include <fcntl.h> // for O_RDONLY +#include <fcntl.h> // for O_RDONLY +#include <locale.h> // for locale_t #include <stdio.h> +#include <stdlib.h> // for strtod_l #include <cstddef> +#ifdef __APPLE__ +# include <xlocale.h> // for LC_NUMERIC_MASK on OS X +#endif + #include "format.h" #ifndef FMT_POSIX @@ -299,7 +305,8 @@ class File { // Closes the file. void close(); - // Returns the file size. + // Returns the file size. The size has signed type for consistency with + // stat::st_size. LongLong size() const; // Attempts to read count bytes from the file into the specified buffer. @@ -331,6 +338,58 @@ class File { // Returns the memory page size. long getpagesize(); + +#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER) +# define FMT_LOCALE +#endif + +#ifdef FMT_LOCALE +// A "C" numeric locale. +class Locale { + private: +# ifdef _MSC_VER + typedef _locale_t locale_t; + + enum { LC_NUMERIC_MASK = LC_NUMERIC }; + + static locale_t newlocale(int category_mask, const char *locale, locale_t) { + return _create_locale(category_mask, locale); + } + + static void freelocale(locale_t locale) { + _free_locale(locale); + } + + static double strtod_l(const char *nptr, char **endptr, _locale_t locale) { + return _strtod_l(nptr, endptr, locale); + } +# endif + + locale_t locale_; + + FMT_DISALLOW_COPY_AND_ASSIGN(Locale); + + public: + typedef locale_t Type; + + Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) { + if (!locale_) + throw fmt::SystemError(errno, "cannot create locale"); + } + ~Locale() { freelocale(locale_); } + + Type get() const { return locale_; } + + // Converts string to floating-point number and advances str past the end + // of the parsed input. + double strtod(const char *&str) const { + char *end = 0; + double result = strtod_l(str, &end, locale_); + str = end; + return result; + } +}; +#endif // FMT_LOCALE } // namespace fmt #if !FMT_USE_RVALUE_REFERENCES diff --git a/dep/efsw/.hg_archival.txt b/dep/efsw/.hg_archival.txt new file mode 100644 index 00000000000..19565afb668 --- /dev/null +++ b/dep/efsw/.hg_archival.txt @@ -0,0 +1,5 @@ +repo: 78c2ea8c48b213ee0078d6326a1dd719d0844764 +node: ff0b69daeca1edf7785a8a580518e462be5a6f3d +branch: default +latesttag: null +latesttagdistance: 144 diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt new file mode 100644 index 00000000000..81a1d20b204 --- /dev/null +++ b/dep/efsw/CMakeLists.txt @@ -0,0 +1,85 @@ +if (WITH_DYNAMIC_LINKING) + set(SRCS + src/efsw/DirectorySnapshot.cpp + src/efsw/DirectorySnapshotDiff.cpp + src/efsw/DirWatcherGeneric.cpp + src/efsw/FileInfo.cpp + src/efsw/FileSystem.cpp + src/efsw/FileWatcher.cpp + src/efsw/FileWatcherCWrapper.cpp + src/efsw/FileWatcherGeneric.cpp + src/efsw/FileWatcherImpl.cpp + src/efsw/Log.cpp + src/efsw/Mutex.cpp + src/efsw/String.cpp + src/efsw/System.cpp + src/efsw/Thread.cpp + src/efsw/Watcher.cpp + src/efsw/WatcherGeneric.cpp) + + if(WIN32) + list(APPEND SRCS + src/efsw/platform/win/FileSystemImpl.cpp + src/efsw/platform/win/MutexImpl.cpp + src/efsw/platform/win/SystemImpl.cpp + src/efsw/platform/win/ThreadImpl.cpp) + else() + list(APPEND SRCS + src/efsw/platform/posix/FileSystemImpl.cpp + src/efsw/platform/posix/MutexImpl.cpp + src/efsw/platform/posix/SystemImpl.cpp + src/efsw/platform/posix/ThreadImpl.cpp) + endif() + + if (WIN32) + list(APPEND SRCS + src/efsw/WatcherWin32.cpp + src/efsw/FileWatcherWin32.cpp) + elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + list(APPEND SRCS + src/efsw/FileWatcherInotify.cpp + src/efsw/WatcherInotify.cpp) + + if (NOT EXISTS "/usr/include/sys/inotify.h" AND NOT EXISTS "/usr/local/include/sys/inotify.h") + add_definitions(-DEFSW_INOTIFY_NOSYS) + endif() + elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR APPLE) + list(APPEND SRCS + src/efsw/FileWatcherKqueue.cpp + src/efsw/WatcherKqueue.cpp) + + if (APPLE) + list(APPEND SRCS + src/efsw/FileWatcherFSEvents.cpp + src/efsw/WatcherFSEvents.cpp) + + exec_program(uname ARGS -v OUTPUT_VARIABLE OSX_VERSION) + string(REGEX MATCH "[0-9]+" OSX_VERSION ${OSX_VERSION}) + if (NOT OSX_VERSION GREATER 9) + add_definitions(-DEFSW_FSEVENTS_NOT_SUPPORTED) + endif() + + set(OPTIONAL_MAC_LINK_LIBRARIES "-framework CoreFoundation" "-framework CoreServices") + endif() + endif() + + add_library(efsw STATIC ${SRCS}) + + target_include_directories(efsw + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src) + + target_link_libraries(efsw + PUBLIC + threads + ${OPTIONAL_MAC_LINK_LIBRARIES}) + + set_target_properties(efsw + PROPERTIES + FOLDER + "dep") +else() + add_library(efsw INTERFACE) +endif() diff --git a/dep/efsw/LICENSE b/dep/efsw/LICENSE new file mode 100644 index 00000000000..ac8ac28988d --- /dev/null +++ b/dep/efsw/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 MartÃn Lucas Golini + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) +http://code.google.com/p/simplefilewatcher/ also MIT licensed.
\ No newline at end of file diff --git a/dep/efsw/README.md b/dep/efsw/README.md new file mode 100644 index 00000000000..fda0bb599aa --- /dev/null +++ b/dep/efsw/README.md @@ -0,0 +1,138 @@ +Entropia File System Watcher +============================ +**efsw** is a C++ cross-platform file system watcher and notifier. + +**efsw** monitors the file system asynchronously for changes to files and directories by watching a list of specified paths, and raises events when a directory or file change. + +**efsw** supports recursive directories watch, tracking the entire sub directory tree. + +**efsw** currently supports the following platforms: + +* Linux via [inotify](http://en.wikipedia.org/wiki/Inotify) + +* Windows via [I/O Completion Ports](http://en.wikipedia.org/wiki/IOCP) + +* Mac OS X via [FSEvents](http://en.wikipedia.org/wiki/FSEvents) or [kqueue](http://en.wikipedia.org/wiki/Kqueue) + +* FreeBSD/BSD via [kqueue](http://en.wikipedia.org/wiki/Kqueue) + +* OS-independent generic watcher +(polling the disk for directory snapshots and comparing them periodically) + +If any of the backend fails to start by any reason, it will fallback to the OS-independent implementation. +This should never happen, except for the Kqueue implementation, see `Platform limitations and clarifications`. + +**Code License** +-------------- +[MIT License](http://www.opensource.org/licenses/mit-license.php) + +**Some example code:** +-------------------- + + :::c++ + // Inherits from the abstract listener class, and implements the the file action handler + class UpdateListener : public efsw::FileWatchListener + { + public: + UpdateListener() {} + + void handleFileAction( efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "" ) + { + switch( action ) + { + case efsw::Actions::Add: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Added" << std::endl; + break; + case efsw::Actions::Delete: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Delete" << std::endl; + break; + case efsw::Actions::Modified: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Modified" << std::endl; + break; + case efsw::Actions::Moved: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Moved from (" << oldFilename << ")" << std::endl; + break; + default: + std::cout << "Should never happen!" << std::endl; + } + } + }; + + // Create the file system watcher instance + // efsw::FileWatcher allow a first boolean parameter that indicates if it should start with the generic file watcher instead of the platform specific backend + efsw::FileWatcher * fileWatcher = new efsw::FileWatcher(); + + // Create the instance of your efsw::FileWatcherListener implementation + UpdateListener * listener = new UpdateListener(); + + // Add a folder to watch, and get the efsw::WatchID + // It will watch the /tmp folder recursively ( the third parameter indicates that is recursive ) + // Reporting the files and directories changes to the instance of the listener + efsw::WatchID watchID = fileWatcher->addWatch( "/tmp", listener, true ); + + // Adds another directory to watch. This time as non-recursive. + efsw::WatchID watchID2 = fileWatcher->addWatch( "/usr", listener, false ); + + // Start watching asynchronously the directories + fileWatcher.watch(); + + // Remove the second watcher added + // You can also call removeWatch by passing the watch path ( it must end with an slash or backslash in windows, since that's how internally it's saved ) + fileWatcher->removeWatch( watchID2 ); + +**Dependencies** +-------------- +None :) + +**Compiling** +------------ +To generate project files you will need to [download and install](http://industriousone.com/premake/download) [Premake](http://industriousone.com/what-premake) + +Then you can generate the project for your platform just going to the project directory where the premake4.lua file is located and then execute: + +`premake4 gmake` to generate project Makefiles, then `cd make/*YOURPLATFORM*/`, and finally `make` or `make config=release` ( it will generate the static lib, the shared lib and the test application ). + +or + +`premake4 vs2010` to generate Visual Studio 2010 project. + +or + +`premake4 xcode4` to generate Xcode 4 project. + +There is also a cmake file that i don't oficially support but it works just fine, provided by [Mohammed Nafees](https://bitbucket.org/binaryking). + +**Platform limitations and clarifications** +------------------------------------------- + +Directory paths are expected to be encoded as UTF-8 strings in all platforms. + +handleFileAction returns UTF-8 strings in all platforms. + +Windows and FSEvents Mac OS X implementation can't follow symlinks ( it will ignore followSymlinks() and allowOutOfScopeLinks() ). + +Kqueue implementation is limited by the maximun number of file descriptors allowed per process by the OS, in the case of reaching the file descriptors limit ( in BSD around 18000 and in OS X around 10240 ) it will fallback to the generic file watcher. + +OS X will only use Kqueue if OS X version is below to 10.5, and this implementation needs to be compiled separately from the OS X >= 10.5 implementation. Since there's no way to compile FSEvents backend in OS X below 10.5. + +FSEvents for OS X Lion and beyond in some cases will generate more actions that in reality ocurred, since fine-grained implementation of FSEvents doesn't give the order of the actions retrieved, in some cases i need to guess/aproximate the order of them. + +Generic watcher relies on the inode information to detect file and directories renames/move. Since Windows has no concept of inodes as Unix platforms do, there is no current reliable way of determining file/directory movement on Windows without help from the Windows API ( this is replaced with Add/Delete events ). + +Linux versions below 2.6.13 are not supported, since inotify wasn't implemented yet. I'm not interested in support older kernels, since i don't see the point. If someone needs this open an issue in the issue tracker and i may consider implenent a dnotify backend. + +OS-independent watcher, Kqueue and FSEvents for OS X below 10.5 keep cache of the directories structures, to be able to detect changes in the directories. This means that there's a memory overhead for this backends. + +**Useful information** +-------------------- +The project also comes with a C API wrapper, contributed by [Sepul Sepehr Taghdisian](https://bitbucket.org/sepul). + +There's a string manipulation class not exposed in the efsw header ( efsw::String ) that can be used to make string encoding conversion. + + +**Clarifications** +---------------- + +This software started as a fork of the [simplefilewatcher](http://code.google.com/p/simplefilewatcher/) by James Wynn (james[at]jameswynn.com), [MIT licensed](http://www.opensource.org/licenses/mit-license.html). + +The icon used for the project is part of the [Haiku®'s Icons](http://www.haiku-inc.org/haiku-icons.html), [MIT licensed](http://www.opensource.org/licenses/mit-license.html). diff --git a/dep/efsw/include/efsw/efsw.h b/dep/efsw/include/efsw/efsw.h new file mode 100644 index 00000000000..28e63e2139e --- /dev/null +++ b/dep/efsw/include/efsw/efsw.h @@ -0,0 +1,151 @@ +/** + @author Sepul Sepehr Taghdisian + + Copyright (c) 2013 Martin Lucas Golini + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) + http://code.google.com/p/simplefilewatcher/ also MIT licensed. +*/ +/** This is the C API wrapper of EFSW */ +#ifndef ESFW_H +#define ESFW_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) + #ifdef EFSW_DYNAMIC + // Windows platforms + #ifdef EFSW_EXPORTS + // From DLL side, we must export + #define EFSW_API __declspec(dllexport) + #else + // From client application side, we must import + #define EFSW_API __declspec(dllimport) + #endif + #else + // No specific directive needed for static build + #ifndef EFSW_API + #define EFSW_API + #endif + #endif +#else + #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) + #define EFSW_API __attribute__ ((visibility("default"))) + #endif + + // Other platforms don't need to define anything + #ifndef EFSW_API + #define EFSW_API + #endif +#endif + +/// Type for a watch id +typedef long efsw_watchid; + +/// Type for watcher +typedef void* efsw_watcher; + +enum efsw_action +{ + EFSW_ADD = 1, /// Sent when a file is created or renamed + EFSW_DELETE = 2, /// Sent when a file is deleted or renamed + EFSW_MODIFIED = 3, /// Sent when a file is modified + EFSW_MOVED = 4 /// Sent when a file is moved +}; + +enum efsw_error +{ + EFSW_NOTFOUND = -1, + EFSW_REPEATED = -2, + EFSW_OUTOFSCOPE = -3, + EFSW_NOTREADABLE = -4, + EFSW_REMOTE = -5, + EFSW_UNSPECIFIED = -6 +}; + +/// Basic interface for listening for file events. +typedef void (*efsw_pfn_fileaction_callback) ( + efsw_watcher watcher, + efsw_watchid watchid, + const char* dir, + const char* filename, + enum efsw_action action, + const char* old_filename, + void* param +); + +/** + * Creates a new file-watcher + * @param generic_mode Force the use of the Generic file watcher + */ +efsw_watcher EFSW_API efsw_create(int generic_mode); + +/// Release the file-watcher and unwatch any directories +void EFSW_API efsw_release(efsw_watcher watcher); + +/// Retreive last error occured by file-watcher +EFSW_API const char* efsw_getlasterror(); + +/// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. +/// For backwards compatibility. +/// On error returns WatchID with Error type. +efsw_watchid EFSW_API efsw_addwatch(efsw_watcher watcher, const char* directory, + efsw_pfn_fileaction_callback callback_fn, int recursive, void* param); + +/// Remove a directory watch. This is a brute force search O(nlogn). +void EFSW_API efsw_removewatch(efsw_watcher watcher, const char* directory); + +/// Remove a directory watch. This is a map lookup O(logn). +void EFSW_API efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid); + +/// Starts watching ( in other thread ) +void EFSW_API efsw_watch(efsw_watcher watcher); + +/** + * Allow recursive watchers to follow symbolic links to other directories + * followSymlinks is disabled by default + */ +void EFSW_API efsw_follow_symlinks(efsw_watcher watcher, int enable); + +/** @return If can follow symbolic links to directorioes */ +int EFSW_API efsw_follow_symlinks_isenabled(efsw_watcher watcher); + +/** + * When enable this it will allow symlinks to watch recursively out of the pointed directory. + * follorSymlinks must be enabled to this work. + * For example, added symlink to /home/folder, and the symlink points to /, this by default is not allowed, + * it's only allowed to symlink anything from /home/ and deeper. This is to avoid great levels of recursion. + * Enabling this could lead in infinite recursion, and crash the watcher ( it will try not to avoid this ). + * Buy enabling out of scope links, it will allow this behavior. + * allowOutOfScopeLinks are disabled by default. + */ +void EFSW_API efsw_allow_outofscopelinks(efsw_watcher watcher, int allow); + +/// @return Returns if out of scope links are allowed +int EFSW_API efsw_outofscopelinks_isallowed(efsw_watcher watcher); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/efsw/include/efsw/efsw.hpp b/dep/efsw/include/efsw/efsw.hpp new file mode 100644 index 00000000000..0693bb296f0 --- /dev/null +++ b/dep/efsw/include/efsw/efsw.hpp @@ -0,0 +1,197 @@ +/** + @author MartÃn Lucas Golini + + Copyright (c) 2013 MartÃn Lucas Golini + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) + http://code.google.com/p/simplefilewatcher/ also MIT licensed. +*/ + +#ifndef ESFW_HPP +#define ESFW_HPP + +#include <string> +#include <list> + +#if defined(_WIN32) + #ifdef EFSW_DYNAMIC + // Windows platforms + #ifdef EFSW_EXPORTS + // From DLL side, we must export + #define EFSW_API __declspec(dllexport) + #else + // From client application side, we must import + #define EFSW_API __declspec(dllimport) + #endif + #else + // No specific directive needed for static build + #ifndef EFSW_API + #define EFSW_API + #endif + #endif +#else + #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) + #define EFSW_API __attribute__ ((visibility("default"))) + #endif + + // Other platforms don't need to define anything + #ifndef EFSW_API + #define EFSW_API + #endif +#endif + +namespace efsw { + +/// Type for a watch id +typedef long WatchID; + +// forward declarations +class FileWatcherImpl; +class FileWatchListener; + +/// Actions to listen for. Rename will send two events, one for +/// the deletion of the old file, and one for the creation of the +/// new file. +namespace Actions { + enum Action + { + /// Sent when a file is created or renamed + Add = 1, + /// Sent when a file is deleted or renamed + Delete = 2, + /// Sent when a file is modified + Modified = 3, + /// Sent when a file is moved + Moved = 4 + }; +} +typedef Actions::Action Action; + +/// Errors log namespace +namespace Errors { + +enum Error +{ + FileNotFound = -1, + FileRepeated = -2, + FileOutOfScope = -3, + FileNotReadable = -4, + FileRemote = -5, /** Directory in remote file system ( create a generic FileWatcher instance to watch this directory ). */ + Unspecified = -6 +}; + +class EFSW_API Log +{ + public: + /// @return The last error logged + static std::string getLastErrorLog(); + + /// Creates an error of the type specified + static Error createLastError( Error err, std::string log ); +}; + +} +typedef Errors::Error Error; + +/// Listens to files and directories and dispatches events +/// to notify the listener of files and directories changes. +/// @class FileWatcher +class EFSW_API FileWatcher +{ + public: + /// Default constructor, will use the default platform file watcher + FileWatcher(); + + /// Constructor that lets you force the use of the Generic File Watcher + FileWatcher( bool useGenericFileWatcher ); + + virtual ~FileWatcher(); + + /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. + /// For backwards compatibility. + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + + /// Remove a directory watch. This is a brute force search O(nlogn). + void removeWatch(const std::string& directory); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch(WatchID watchid); + + /// Starts watching ( in other thread ) + void watch(); + + /// @return Returns a list of the directories that are being watched + std::list<std::string> directories(); + + /** Allow recursive watchers to follow symbolic links to other directories + * followSymlinks is disabled by default + */ + void followSymlinks( bool follow ); + + /** @return If can follow symbolic links to directorioes */ + const bool& followSymlinks() const; + + /** When enable this it will allow symlinks to watch recursively out of the pointed directory. + * follorSymlinks must be enabled to this work. + * For example, added symlink to /home/folder, and the symlink points to /, this by default is not allowed, + * it's only allowed to symlink anything from /home/ and deeper. This is to avoid great levels of recursion. + * Enabling this could lead in infinite recursion, and crash the watcher ( it will try not to avoid this ). + * Buy enabling out of scope links, it will allow this behavior. + * allowOutOfScopeLinks are disabled by default. + */ + void allowOutOfScopeLinks( bool allow ); + + /// @return Returns if out of scope links are allowed + const bool& allowOutOfScopeLinks() const; + private: + /// The implementation + FileWatcherImpl * mImpl; + bool mFollowSymlinks; + bool mOutOfScopeLinks; +}; + +/// Basic interface for listening for file events. +/// @class FileWatchListener +class FileWatchListener +{ + public: + FileWatchListener() {} + + virtual ~FileWatchListener() {} + + /// Handles the action file action + /// @param watchid The watch id for the directory + /// @param dir The directory + /// @param filename The filename that was accessed (not full path) + /// @param action Action that was performed + /// @param oldFilename The name of the file or directory moved + virtual void handleFileAction(WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename = "" ) = 0; + +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/Debug.cpp b/dep/efsw/src/efsw/Debug.cpp new file mode 100644 index 00000000000..9c4ee02e5b6 --- /dev/null +++ b/dep/efsw/src/efsw/Debug.cpp @@ -0,0 +1,85 @@ +#include <efsw/Debug.hpp> +#include <iostream> + +#ifdef EFSW_COMPILER_MSVC +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <crtdbg.h> +#endif + +#include <cassert> +#include <cstdio> +#include <cstdarg> + +namespace efsw { + +#ifdef DEBUG + +void efREPORT_ASSERT( const char * File, int Line, const char * Exp ) +{ + #ifdef EFSW_COMPILER_MSVC + _CrtDbgReport( _CRT_ASSERT, File, Line, "", Exp); + + DebugBreak(); + #else + std::cout << "ASSERT: " << Exp << " file: " << File << " line: " << Line << std::endl; + + #if defined(EFSW_COMPILER_GCC) && defined(EFSW_32BIT) && !defined(EFSW_ARM) + asm("int3"); + #else + assert( false ); + #endif + #endif +} + +void efPRINT( const char * format, ... ) +{ + char buf[2048]; + va_list args; + + va_start( args, format ); + + #ifdef EFSW_COMPILER_MSVC + _vsnprintf_s( buf, sizeof( buf ), sizeof( buf ) / sizeof( buf[0]), format, args ); + #else + vsnprintf( buf, sizeof( buf ) / sizeof( buf[0]), format, args ); + #endif + + va_end( args ); + + #ifdef EFSW_COMPILER_MSVC + OutputDebugStringA( buf ); + #else + std::cout << buf; + #endif +} + +void efPRINTC( unsigned int cond, const char * format, ...) +{ + if ( 0 == cond ) + return; + + char buf[2048]; + va_list args; + + va_start( args, format ); + + #ifdef EFSW_COMPILER_MSVC + _vsnprintf_s( buf, efARRAY_SIZE( buf ), efARRAY_SIZE( buf ), format, args ); + #else + vsnprintf( buf, sizeof( buf ) / sizeof( buf[0]), format, args ); + #endif + + va_end( args ); + + #ifdef EFSW_COMPILER_MSVC + OutputDebugStringA( buf ); + #else + std::cout << buf; + #endif +} + +#endif + +} + diff --git a/dep/efsw/src/efsw/Debug.hpp b/dep/efsw/src/efsw/Debug.hpp new file mode 100644 index 00000000000..75d6dce0466 --- /dev/null +++ b/dep/efsw/src/efsw/Debug.hpp @@ -0,0 +1,50 @@ +#ifndef EFSW_DEBUG_HPP +#define EFSW_DEBUG_HPP + +#include <efsw/base.hpp> + +namespace efsw { + +#ifdef DEBUG + +void efREPORT_ASSERT( const char * File, const int Line, const char * Exp ); + +#define efASSERT( expr ) if ( !(expr) ) { efREPORT_ASSERT( __FILE__, __LINE__, #expr ); } +#define efASSERTM( expr, msg ) if ( !(expr) ) { efREPORT_ASSERT( __FILE__, __LINE__, #msg ); } + +void efPRINT ( const char * format, ... ); +void efPRINTC ( unsigned int cond, const char * format, ... ); + +#else + +#define efASSERT( expr ) +#define efASSERTM( expr, msg ) + +#ifndef EFSW_COMPILER_MSVC + #define efPRINT( format, args... ) {} + #define efPRINTC( cond, format, args... ) {} +#else + #define efPRINT + #define efPRINTC +#endif + +#endif + +#ifdef EFSW_VERBOSE + #define efDEBUG efPRINT + #define efDEBUGC efPRINTC +#else + + #ifndef EFSW_COMPILER_MSVC + #define efDEBUG( format, args... ) {} + #define efDEBUGC( cond, format, args... ) {} + #else + #define efDEBUG + #define efDEBUGC + #endif + +#endif + +} + +#endif diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.cpp b/dep/efsw/src/efsw/DirWatcherGeneric.cpp new file mode 100644 index 00000000000..b80c14d24ce --- /dev/null +++ b/dep/efsw/src/efsw/DirWatcherGeneric.cpp @@ -0,0 +1,451 @@ +#include <efsw/DirWatcherGeneric.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/Debug.hpp> +#include <efsw/String.hpp> + +namespace efsw { + +DirWatcherGeneric::DirWatcherGeneric( DirWatcherGeneric * parent, WatcherGeneric * ws, const std::string& directory, bool recursive, bool reportNewFiles ) : + Parent( parent ), + Watch( ws ), + Recursive( recursive ), + Deleted( false ) +{ + resetDirectory( directory ); + + if ( !reportNewFiles ) + { + DirSnap.scan(); + } + else + { + DirectorySnapshotDiff Diff = DirSnap.scan(); + + if ( Diff.changed() ) + { + FileInfoList::iterator it; + + DiffIterator( FilesCreated ) + { + handleAction( ( *it ).Filepath, Actions::Add ); + } + } + } +} + +DirWatcherGeneric::~DirWatcherGeneric() +{ + /// If the directory was deleted mark the files as deleted + if ( Deleted ) + { + DirectorySnapshotDiff Diff = DirSnap.scan(); + + if ( !DirSnap.exists() ) + { + FileInfoList::iterator it; + + DiffIterator( FilesDeleted ) + { + handleAction( (*it).Filepath, Actions::Delete ); + } + + DiffIterator( DirsDeleted ) + { + handleAction( (*it).Filepath, Actions::Delete ); + } + } + } + + DirWatchMap::iterator it = Directories.begin(); + + for ( ; it != Directories.end(); it++ ) + { + if ( Deleted ) + { + /// If the directory was deleted, mark the flag for file deletion + it->second->Deleted = true; + } + + efSAFE_DELETE( it->second ); + } +} + +void DirWatcherGeneric::resetDirectory( std::string directory ) +{ + std::string dir( directory ); + + /// Is this a recursive watch? + if ( Watch->Directory != directory ) + { + if ( !( directory.size() && ( directory.at(0) == FileSystem::getOSSlash() || directory.at( directory.size() - 1 ) == FileSystem::getOSSlash() ) ) ) + { + /// Get the real directory + if ( NULL != Parent ) + { + FileSystem::dirAddSlashAtEnd(directory); + + dir = Parent->DirSnap.DirectoryInfo.Filepath + directory; + } + else + { + efDEBUG( "resetDirectory(): Parent is NULL. Fatal error." ); + } + } + } + + DirSnap.setDirectoryInfo( dir ); +} + +void DirWatcherGeneric::handleAction( const std::string &filename, unsigned long action, std::string oldFilename) +{ + Watch->Listener->handleFileAction( Watch->ID, DirSnap.DirectoryInfo.Filepath, FileSystem::fileNameFromPath( filename ), (Action)action, oldFilename ); +} + +void DirWatcherGeneric::addChilds( bool reportNewFiles ) +{ + if ( Recursive ) + { + /// Create the subdirectories watchers + std::string dir; + + for ( FileInfoMap::iterator it = DirSnap.Files.begin(); it != DirSnap.Files.end(); it++ ) + { + if ( it->second.isDirectory() && it->second.isReadable() && !FileSystem::isRemoteFS( it->second.Filepath ) ) + { + /// Check if the directory is a symbolic link + std::string curPath; + std::string link( FileSystem::getLinkRealPath( it->second.Filepath, curPath ) ); + + dir = it->first; + + if ( "" != link ) + { + /// Avoid adding symlinks directories if it's now enabled + if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() ) + { + continue; + } + + /// If it's a symlink check if the realpath exists as a watcher, or + /// if the path is outside the current dir + if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || !Watch->WatcherImpl->linkAllowed( curPath, link ) ) + { + continue; + } + else + { + dir = link; + } + } + else + { + if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) ) + { + continue; + } + } + + if ( reportNewFiles ) + { + handleAction( dir, Actions::Add ); + } + + Directories[dir] = new DirWatcherGeneric( this, Watch, dir, Recursive, reportNewFiles ); + + Directories[dir]->addChilds( reportNewFiles ); + } + } + } +} + +void DirWatcherGeneric::watch( bool reportOwnChange ) +{ + DirectorySnapshotDiff Diff = DirSnap.scan(); + + if ( reportOwnChange && Diff.DirChanged && NULL != Parent ) + { + Watch->Listener->handleFileAction( Watch->ID, FileSystem::pathRemoveFileName( DirSnap.DirectoryInfo.Filepath ), FileSystem::fileNameFromPath( DirSnap.DirectoryInfo.Filepath ), Actions::Modified ); + } + + if ( Diff.changed() ) + { + FileInfoList::iterator it; + MovedList::iterator mit; + + /// Files + DiffIterator( FilesCreated ) + { + handleAction( (*it).Filepath, Actions::Add ); + } + + DiffIterator( FilesModified ) + { + handleAction( (*it).Filepath, Actions::Modified ); + } + + DiffIterator( FilesDeleted ) + { + handleAction( (*it).Filepath, Actions::Delete ); + } + + DiffMovedIterator( FilesMoved ) + { + handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first ); + } + + /// Directories + DiffIterator( DirsCreated ) + { + createDirectory( (*it).Filepath ); + } + + DiffIterator( DirsModified ) + { + handleAction( (*it).Filepath, Actions::Modified ); + } + + DiffIterator( DirsDeleted ) + { + handleAction( (*it).Filepath, Actions::Delete ); + removeDirectory( (*it).Filepath ); + } + + DiffMovedIterator( DirsMoved ) + { + handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first ); + moveDirectory( (*mit).first, (*mit).second.Filepath ); + } + } + + /// Process the subdirectories looking for changes + for ( DirWatchMap::iterator dit = Directories.begin(); dit != Directories.end(); dit++ ) + { + /// Just watch + dit->second->watch(); + } +} + +void DirWatcherGeneric::watchDir( std::string &dir ) +{ + DirWatcherGeneric * watcher = Watch->WatcherImpl->mFileWatcher->allowOutOfScopeLinks() ? + findDirWatcher( dir ) : + findDirWatcherFast( dir ); + + if ( NULL != watcher ) + { + watcher->watch( true ); + } +} + +DirWatcherGeneric * DirWatcherGeneric::findDirWatcherFast( std::string dir ) +{ + // remove the common base ( dir should always start with the same base as the watcher ) + efASSERT( !dir.empty() ); + efASSERT( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() ); + efASSERT( DirSnap.DirectoryInfo.Filepath == dir.substr( 0, DirSnap.DirectoryInfo.Filepath.size() ) ); + + if ( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() ) + { + dir = dir.substr( DirSnap.DirectoryInfo.Filepath.size() - 1 ); + } + + if ( dir.size() == 1 ) + { + efASSERT( dir[0] == FileSystem::getOSSlash() ); + return this; + } + + size_t level = 0; + std::vector<std::string> dirv = String::split( dir, FileSystem::getOSSlash(), false ); + + DirWatcherGeneric * watcher = this; + + while ( level < dirv.size() ) + { + // search the dir level in the current watcher + DirWatchMap::iterator it = watcher->Directories.find( dirv[ level ] ); + + // found? continue with the next level + if ( it != watcher->Directories.end() ) + { + watcher = it->second; + + level++; + } + else + { + // couldn't found the folder level? + // directory not watched + return NULL; + } + } + + return watcher; +} + +DirWatcherGeneric * DirWatcherGeneric::findDirWatcher( std::string dir ) +{ + if ( DirSnap.DirectoryInfo.Filepath == dir ) + { + return this; + } + else + { + DirWatcherGeneric * watcher = NULL; + + for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); it++ ) + { + watcher = it->second->findDirWatcher( dir ); + + if ( NULL != watcher ) + { + return watcher; + } + } + } + + return NULL; +} + +DirWatcherGeneric * DirWatcherGeneric::createDirectory( std::string newdir ) +{ + FileSystem::dirRemoveSlashAtEnd( newdir ); + newdir = FileSystem::fileNameFromPath( newdir ); + + DirWatcherGeneric * dw = NULL; + + /// Check if the directory is a symbolic link + std::string dir( DirSnap.DirectoryInfo.Filepath + newdir ); + + FileSystem::dirAddSlashAtEnd( dir ); + + FileInfo fi( dir ); + + if ( !fi.isDirectory() || !fi.isReadable() || FileSystem::isRemoteFS( dir ) ) + { + return NULL; + } + + std::string curPath; + std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); + bool skip = false; + + if ( "" != link ) + { + /// Avoid adding symlinks directories if it's now enabled + if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() ) + { + skip = true; + } + + /// If it's a symlink check if the realpath exists as a watcher, or + /// if the path is outside the current dir + if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || !Watch->WatcherImpl->linkAllowed( curPath, link ) ) + { + skip = true; + } + else + { + dir = link; + } + } + else + { + if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) ) + { + skip = true; + } + } + + if ( !skip ) + { + handleAction( newdir, Actions::Add ); + + /// Creates the new directory watcher of the subfolder and check for new files + dw = new DirWatcherGeneric( this, Watch, dir, Recursive ); + + dw->addChilds(); + + dw->watch(); + + /// Add it to the list of directories + Directories[ newdir ] = dw; + } + + return dw; +} + +void DirWatcherGeneric::removeDirectory( std::string dir ) +{ + FileSystem::dirRemoveSlashAtEnd( dir ); + dir = FileSystem::fileNameFromPath( dir ); + + DirWatcherGeneric * dw = NULL; + DirWatchMap::iterator dit; + + /// Folder deleted + + /// Search the folder, it should exists + dit = Directories.find( dir ); + + if ( dit != Directories.end() ) + { + dw = dit->second; + + /// Flag it as deleted so it fire the event for every file inside deleted + dw->Deleted = true; + + /// Delete the DirWatcherGeneric + efSAFE_DELETE( dw ); + + /// Remove the directory from the map + Directories.erase( dit->first ); + } +} + +void DirWatcherGeneric::moveDirectory( std::string oldDir, std::string newDir ) +{ + FileSystem::dirRemoveSlashAtEnd( oldDir ); + oldDir = FileSystem::fileNameFromPath( oldDir ); + + FileSystem::dirRemoveSlashAtEnd( newDir ); + newDir = FileSystem::fileNameFromPath( newDir ); + + DirWatcherGeneric * dw = NULL; + DirWatchMap::iterator dit; + + /// Directory existed? + dit = Directories.find( oldDir ); + + if ( dit != Directories.end() ) + { + dw = dit->second; + + /// Remove the directory from the map + Directories.erase( dit->first ); + + Directories[ newDir ] = dw; + + dw->resetDirectory( newDir ); + } +} + +bool DirWatcherGeneric::pathInWatches( std::string path ) +{ + if ( DirSnap.DirectoryInfo.Filepath == path ) + { + return true; + } + + for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); it++ ) + { + if ( it->second->pathInWatches( path ) ) + { + return true; + } + } + + return false; +} + +} diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.hpp b/dep/efsw/src/efsw/DirWatcherGeneric.hpp new file mode 100644 index 00000000000..a7581904422 --- /dev/null +++ b/dep/efsw/src/efsw/DirWatcherGeneric.hpp @@ -0,0 +1,55 @@ +#ifndef EFSW_DIRWATCHERGENERIC_HPP +#define EFSW_DIRWATCHERGENERIC_HPP + +#include <efsw/WatcherGeneric.hpp> +#include <efsw/FileInfo.hpp> +#include <efsw/DirectorySnapshot.hpp> +#include <map> + +namespace efsw { + +class DirWatcherGeneric +{ + public: + typedef std::map<std::string, DirWatcherGeneric*> DirWatchMap; + + DirWatcherGeneric * Parent; + WatcherGeneric * Watch; + DirectorySnapshot DirSnap; + DirWatchMap Directories; + bool Recursive; + + DirWatcherGeneric( DirWatcherGeneric * parent, WatcherGeneric * ws, const std::string& directory, bool recursive, bool reportNewFiles = false ); + + ~DirWatcherGeneric(); + + void watch( bool reportOwnChange = false ); + + void watchDir( std::string& dir ); + + static bool isDir( const std::string& directory ); + + bool pathInWatches( std::string path ); + + void addChilds( bool reportNewFiles = true ); + + DirWatcherGeneric * findDirWatcher( std::string dir ); + + DirWatcherGeneric * findDirWatcherFast( std::string dir ); + protected: + bool Deleted; + + DirWatcherGeneric * createDirectory( std::string newdir ); + + void removeDirectory( std::string dir ); + + void moveDirectory( std::string oldDir, std::string newDir ); + + void resetDirectory( std::string directory ); + + void handleAction( const std::string& filename, unsigned long action, std::string oldFilename = ""); +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/DirectorySnapshot.cpp b/dep/efsw/src/efsw/DirectorySnapshot.cpp new file mode 100644 index 00000000000..c0ef747548a --- /dev/null +++ b/dep/efsw/src/efsw/DirectorySnapshot.cpp @@ -0,0 +1,261 @@ +#include <efsw/DirectorySnapshot.hpp> +#include <efsw/FileSystem.hpp> + +namespace efsw { + +DirectorySnapshot::DirectorySnapshot() +{ +} + +DirectorySnapshot::DirectorySnapshot( std::string directory ) +{ + init( directory ); +} + +DirectorySnapshot::~DirectorySnapshot() +{ +} + +void DirectorySnapshot::init( std::string directory ) +{ + setDirectoryInfo( directory ); + initFiles(); +} + +bool DirectorySnapshot::exists() +{ + return DirectoryInfo.exists(); +} + +void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff ) +{ + FileInfo fi; + + for ( FileInfoMap::iterator it = Files.begin(); it != Files.end(); it++ ) + { + fi = it->second; + + if ( fi.isDirectory() ) + { + Diff.DirsDeleted.push_back( fi ); + } + else + { + Diff.FilesDeleted.push_back( fi ); + } + } +} + +void DirectorySnapshot::setDirectoryInfo( std::string directory ) +{ + DirectoryInfo = FileInfo( directory ); +} + +void DirectorySnapshot::initFiles() +{ + Files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); + + FileInfoMap::iterator it = Files.begin(); + std::list<std::string> eraseFiles; + + /// Remove all non regular files and non directories + for ( ; it != Files.end(); it++ ) + { + if ( !it->second.isRegularFile() && !it->second.isDirectory() ) + { + eraseFiles.push_back( it->first ); + } + } + + for ( std::list<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); eit++ ) + { + Files.erase( *eit ); + } +} + +DirectorySnapshotDiff DirectorySnapshot::scan() +{ + DirectorySnapshotDiff Diff; + + Diff.clear(); + + FileInfo curFI( DirectoryInfo.Filepath ); + + Diff.DirChanged = DirectoryInfo != curFI; + + if ( Diff.DirChanged ) + { + DirectoryInfo = curFI; + } + + /// If the directory was erased, create the events for files and directories deletion + if ( !curFI.exists() ) + { + deleteAll( Diff ); + + return Diff; + } + + FileInfoMap files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); + + if ( files.empty() && Files.empty() ) + { + return Diff; + } + + FileInfo fi; + FileInfoMap FilesCpy; + FileInfoMap::iterator it; + FileInfoMap::iterator fiIt; + + if ( Diff.DirChanged ) + { + FilesCpy = Files; + } + + for ( it = files.begin(); it != files.end(); it++ ) + { + fi = it->second; + + /// File existed before? + fiIt = Files.find( it->first ); + + if ( fiIt != Files.end() ) + { + /// Erase from the file list copy + FilesCpy.erase( it->first ); + + /// File changed? + if ( (*fiIt).second != fi ) + { + /// Update the new file info + Files[ it->first ] = fi; + + /// handle modified event + if ( fi.isDirectory() ) + { + Diff.DirsModified.push_back( fi ); + } + else + { + Diff.FilesModified.push_back( fi ); + } + } + } + /// Only add regular files or directories + else if ( fi.isRegularFile() || fi.isDirectory() ) + { + /// New file found + Files[ it->first ] = fi; + + FileInfoMap::iterator fit; + std::string oldFile = ""; + + /// Check if the same inode already existed + if ( ( fit = nodeInFiles( fi ) ) != Files.end() ) + { + oldFile = fit->first; + + /// Avoid firing a Delete event + FilesCpy.erase( fit->first ); + + /// Delete the old file name + Files.erase( fit->first ); + + if ( fi.isDirectory() ) + { + Diff.DirsMoved.push_back( std::make_pair( oldFile, fi ) ); + } + else + { + Diff.FilesMoved.push_back( std::make_pair( oldFile, fi ) ); + } + } + else + { + if ( fi.isDirectory() ) + { + Diff.DirsCreated.push_back( fi ); + } + else + { + Diff.FilesCreated.push_back( fi ); + } + } + } + } + + if ( !Diff.DirChanged ) + { + return Diff; + } + + /// The files or directories that remains were deleted + for ( it = FilesCpy.begin(); it != FilesCpy.end(); it++ ) + { + fi = it->second; + + if ( fi.isDirectory() ) + { + Diff.DirsDeleted.push_back( fi ); + } + else + { + Diff.FilesDeleted.push_back( fi ); + } + + /// Remove the file or directory from the list of files + Files.erase( it->first ); + } + + return Diff; +} + +FileInfoMap::iterator DirectorySnapshot::nodeInFiles( FileInfo& fi ) +{ + FileInfoMap::iterator it; + + if ( FileInfo::inodeSupported() ) + { + for ( it = Files.begin(); it != Files.end(); it++ ) + { + if ( it->second.sameInode( fi ) && it->second.Filepath != fi.Filepath ) + { + return it; + } + } + } + + return Files.end(); +} + +void DirectorySnapshot::addFile( std::string path ) +{ + std::string name( FileSystem::fileNameFromPath( path ) ); + Files[ name ] = FileInfo( path ); +} + +void DirectorySnapshot::removeFile( std::string path ) +{ + std::string name( FileSystem::fileNameFromPath( path ) ); + + FileInfoMap::iterator it = Files.find( name ); + + if ( Files.end() != it ) + { + Files.erase( it ); + } +} + +void DirectorySnapshot::moveFile( std::string oldPath, std::string newPath ) +{ + removeFile( oldPath ); + addFile( newPath ); +} + +void DirectorySnapshot::updateFile(std::string path) +{ + addFile( path ); +} + +} diff --git a/dep/efsw/src/efsw/DirectorySnapshot.hpp b/dep/efsw/src/efsw/DirectorySnapshot.hpp new file mode 100644 index 00000000000..1ada66fe980 --- /dev/null +++ b/dep/efsw/src/efsw/DirectorySnapshot.hpp @@ -0,0 +1,46 @@ +#ifndef EFSW_DIRECTORYSNAPSHOT_HPP +#define EFSW_DIRECTORYSNAPSHOT_HPP + +#include <efsw/DirectorySnapshotDiff.hpp> + +namespace efsw { + +class DirectorySnapshot +{ + public: + FileInfo DirectoryInfo; + FileInfoMap Files; + + void setDirectoryInfo( std::string directory ); + + DirectorySnapshot(); + + DirectorySnapshot( std::string directory ); + + ~DirectorySnapshot(); + + void init( std::string directory ); + + bool exists(); + + DirectorySnapshotDiff scan(); + + FileInfoMap::iterator nodeInFiles( FileInfo& fi ); + + void addFile( std::string path ); + + void removeFile( std::string path ); + + void moveFile( std::string oldPath, std::string newPath ); + + void updateFile( std::string path ); + protected: + void initFiles(); + + void deleteAll( DirectorySnapshotDiff &Diff ); +}; + +} + +#endif + diff --git a/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp b/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp new file mode 100644 index 00000000000..eabc6fdbda1 --- /dev/null +++ b/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp @@ -0,0 +1,29 @@ +#include <efsw/DirectorySnapshotDiff.hpp> + +namespace efsw { + +void DirectorySnapshotDiff::clear() +{ + FilesCreated.clear(); + FilesModified.clear(); + FilesMoved.clear(); + FilesDeleted.clear(); + DirsCreated.clear(); + DirsModified.clear(); + DirsMoved.clear(); + DirsDeleted.clear(); +} + +bool DirectorySnapshotDiff::changed() +{ + return !FilesCreated.empty() || + !FilesModified.empty() || + !FilesMoved.empty() || + !FilesDeleted.empty() || + !DirsCreated.empty() || + !DirsModified.empty() || + !DirsMoved.empty() || + !DirsDeleted.empty(); +} + +} diff --git a/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp b/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp new file mode 100644 index 00000000000..042de9ce02c --- /dev/null +++ b/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp @@ -0,0 +1,35 @@ +#ifndef EFSW_DIRECTORYSNAPSHOTDIFF_HPP +#define EFSW_DIRECTORYSNAPSHOTDIFF_HPP + +#include <efsw/FileInfo.hpp> + +namespace efsw { + +class DirectorySnapshotDiff +{ + public: + FileInfoList FilesDeleted; + FileInfoList FilesCreated; + FileInfoList FilesModified; + MovedList FilesMoved; + FileInfoList DirsDeleted; + FileInfoList DirsCreated; + FileInfoList DirsModified; + MovedList DirsMoved; + bool DirChanged; + + void clear(); + + bool changed(); +}; + +#define DiffIterator( FileInfoListName ) it = Diff.FileInfoListName.begin(); \ + for ( ; it != Diff.FileInfoListName.end(); it++ ) + +#define DiffMovedIterator( MovedListName ) mit = Diff.MovedListName.begin(); \ + for ( ; mit != Diff.MovedListName.end(); mit++ ) + +} + +#endif + diff --git a/dep/efsw/src/efsw/FileInfo.cpp b/dep/efsw/src/efsw/FileInfo.cpp new file mode 100644 index 00000000000..7003afc2a15 --- /dev/null +++ b/dep/efsw/src/efsw/FileInfo.cpp @@ -0,0 +1,274 @@ +#include <efsw/FileInfo.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/String.hpp> + +#ifndef _DARWIN_FEATURE_64_BIT_INODE +#define _DARWIN_FEATURE_64_BIT_INODE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#include <sys/stat.h> + +#include <limits.h> +#include <stdlib.h> + +#ifdef EFSW_COMPILER_MSVC + #ifndef S_ISDIR + #define S_ISDIR(f) ((f)&_S_IFDIR) + #endif + + #ifndef S_ISREG + #define S_ISREG(f) ((f)&_S_IFREG) + #endif + + #ifndef S_ISRDBL + #define S_ISRDBL(f) ((f)&_S_IREAD) + #endif +#else + #include <unistd.h> + + #ifndef S_ISRDBL + #define S_ISRDBL(f) ((f)&S_IRUSR) + #endif +#endif + +namespace efsw { + +bool FileInfo::exists( const std::string& filePath ) +{ + FileInfo fi( filePath ); + return fi.exists(); +} + +bool FileInfo::isLink( const std::string& filePath ) +{ + FileInfo fi( filePath, true ); + return fi.isLink(); +} + +bool FileInfo::inodeSupported() +{ + #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + return true; + #else + return false; + #endif +} + +FileInfo::FileInfo() : + ModificationTime(0), + OwnerId(0), + GroupId(0), + Permissions(0), + Inode(0) +{} + +FileInfo::FileInfo( const std::string& filepath ) : + Filepath( filepath ), + ModificationTime(0), + OwnerId(0), + GroupId(0), + Permissions(0), + Inode(0) +{ + getInfo(); +} + +FileInfo::FileInfo( const std::string& filepath, bool linkInfo ) : + Filepath( filepath ), + ModificationTime(0), + OwnerId(0), + GroupId(0), + Permissions(0), + Inode(0) +{ + if ( linkInfo ) + { + getRealInfo(); + } + else + { + getInfo(); + } +} + +void FileInfo::getInfo() +{ + #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + if ( Filepath.size() == 3 && Filepath[1] == ':' && Filepath[2] == FileSystem::getOSSlash() ) + { + Filepath += FileSystem::getOSSlash(); + } + #endif + + /// Why i'm doing this? stat in mingw32 doesn't work for directories if the dir path ends with a path slash + bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); + + if ( slashAtEnd ) + { + FileSystem::dirRemoveSlashAtEnd( Filepath ); + } + + #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + struct stat st; + int res = stat( Filepath.c_str(), &st ); + #else + struct _stat st; + int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); + #endif + + if ( 0 == res ) + { + ModificationTime = st.st_mtime; + Size = st.st_size; + OwnerId = st.st_uid; + GroupId = st.st_gid; + Permissions = st.st_mode; + Inode = st.st_ino; + } + + if ( slashAtEnd ) + { + FileSystem::dirAddSlashAtEnd( Filepath ); + } +} + +void FileInfo::getRealInfo() +{ + bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); + + if ( slashAtEnd ) + { + FileSystem::dirRemoveSlashAtEnd( Filepath ); + } + + #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + struct stat st; + int res = lstat( Filepath.c_str(), &st ); + #else + struct _stat st; + int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); + #endif + + if ( 0 == res ) + { + ModificationTime = st.st_mtime; + Size = st.st_size; + OwnerId = st.st_uid; + GroupId = st.st_gid; + Permissions = st.st_mode; + Inode = st.st_ino; + } + + if ( slashAtEnd ) + { + FileSystem::dirAddSlashAtEnd( Filepath ); + } +} + +bool FileInfo::operator==( const FileInfo& Other ) const +{ + return ( ModificationTime == Other.ModificationTime && + Size == Other.Size && + OwnerId == Other.OwnerId && + GroupId == Other.GroupId && + Permissions == Other.Permissions && + Inode == Other.Inode + ); +} + +bool FileInfo::isDirectory() +{ + return 0 != S_ISDIR(Permissions); +} + +bool FileInfo::isRegularFile() +{ + return 0 != S_ISREG(Permissions); +} + +bool FileInfo::isReadable() +{ + return 0 != S_ISRDBL(Permissions); +} + +bool FileInfo::isLink() +{ +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + return S_ISLNK(Permissions); +#else + return false; +#endif +} + +std::string FileInfo::linksTo() +{ +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + if ( isLink() ) + { + char * ch = realpath( Filepath.c_str(), NULL); + + if ( NULL != ch ) + { + std::string tstr( ch ); + + free( ch ); + + return tstr; + } + } +#endif + return std::string(""); +} + +bool FileInfo::exists() +{ + bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); + + if ( slashAtEnd ) + { + FileSystem::dirRemoveSlashAtEnd(Filepath); + } + +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + struct stat st; + int res = stat( Filepath.c_str(), &st ); +#else + struct _stat st; + int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); +#endif + + if (slashAtEnd) + { + FileSystem::dirAddSlashAtEnd(Filepath); + } + + return 0 == res; +} + +FileInfo& FileInfo::operator=( const FileInfo& Other ) +{ + this->Filepath = Other.Filepath; + this->Size = Other.Size; + this->ModificationTime = Other.ModificationTime; + this->GroupId = Other.GroupId; + this->OwnerId = Other.OwnerId; + this->Permissions = Other.Permissions; + this->Inode = Other.Inode; + return *this; +} + +bool FileInfo::sameInode( const FileInfo& Other ) const +{ + return inodeSupported() && Inode == Other.Inode; +} + +bool FileInfo::operator!=( const FileInfo& Other ) const +{ + return !(*this == Other); +} + +} diff --git a/dep/efsw/src/efsw/FileInfo.hpp b/dep/efsw/src/efsw/FileInfo.hpp new file mode 100644 index 00000000000..45cca6a7953 --- /dev/null +++ b/dep/efsw/src/efsw/FileInfo.hpp @@ -0,0 +1,66 @@ +#ifndef EFSW_FILEINFO_HPP +#define EFSW_FILEINFO_HPP + +#include <efsw/base.hpp> +#include <string> +#include <map> +#include <list> + +namespace efsw { + +class FileInfo +{ + public: + static bool exists( const std::string& filePath ); + + static bool isLink( const std::string& filePath ); + + static bool inodeSupported(); + + FileInfo(); + + FileInfo( const std::string& filepath ); + + FileInfo( const std::string& filepath, bool linkInfo ); + + bool operator==( const FileInfo& Other ) const; + + bool operator!=( const FileInfo& Other ) const; + + FileInfo& operator=( const FileInfo& Other ); + + bool isDirectory(); + + bool isRegularFile(); + + bool isReadable(); + + bool sameInode( const FileInfo& Other ) const; + + bool isLink(); + + std::string linksTo(); + + bool exists(); + + void getInfo(); + + void getRealInfo(); + + std::string Filepath; + Uint64 ModificationTime; + Uint64 Size; + Uint32 OwnerId; + Uint32 GroupId; + Uint32 Permissions; + Uint64 Inode; +}; + +typedef std::map<std::string, FileInfo> FileInfoMap; +typedef std::list<FileInfo> FileInfoList; +typedef std::list< std::pair< std::string, FileInfo> > MovedList; + +} + +#endif + diff --git a/dep/efsw/src/efsw/FileSystem.cpp b/dep/efsw/src/efsw/FileSystem.cpp new file mode 100644 index 00000000000..e3afa0b4046 --- /dev/null +++ b/dep/efsw/src/efsw/FileSystem.cpp @@ -0,0 +1,124 @@ +#include <efsw/FileSystem.hpp> +#include <efsw/platform/platformimpl.hpp> + +#if EFSW_OS == EFSW_OS_MACOSX +#include <CoreFoundation/CoreFoundation.h> +#endif + +namespace efsw { + +bool FileSystem::isDirectory( const std::string& path ) +{ + return Platform::FileSystem::isDirectory( path ); +} + +FileInfoMap FileSystem::filesInfoFromPath( std::string path ) { + dirAddSlashAtEnd( path ); + + return Platform::FileSystem::filesInfoFromPath( path ); +} + +char FileSystem::getOSSlash() +{ + return Platform::FileSystem::getOSSlash(); +} + +bool FileSystem::slashAtEnd( std::string &dir ) +{ + return ( dir.size() && dir[ dir.size() - 1 ] == getOSSlash() ); +} + +void FileSystem::dirAddSlashAtEnd( std::string& dir ) +{ + if ( dir.size() > 1 && dir[ dir.size() - 1 ] != getOSSlash() ) + { + dir.push_back( getOSSlash() ); + } +} + +void FileSystem::dirRemoveSlashAtEnd( std::string& dir ) +{ + if ( dir.size() > 1 && dir[ dir.size() - 1 ] == getOSSlash() ) + { + dir.erase( dir.size() - 1 ); + } +} + +std::string FileSystem::fileNameFromPath( std::string filepath ) +{ + dirRemoveSlashAtEnd( filepath ); + + size_t pos = filepath.find_last_of( getOSSlash() ); + + if ( pos != std::string::npos ) + { + return filepath.substr( pos + 1 ); + } + + return filepath; +} + +std::string FileSystem::pathRemoveFileName( std::string filepath ) +{ + dirRemoveSlashAtEnd( filepath ); + + size_t pos = filepath.find_last_of( getOSSlash() ); + + if ( pos != std::string::npos ) + { + return filepath.substr( 0, pos + 1 ); + } + + return filepath; +} + +std::string FileSystem::getLinkRealPath( std::string dir, std::string& curPath ) +{ + FileSystem::dirRemoveSlashAtEnd( dir ); + FileInfo fi( dir, true ); + + /// Check with lstat and see if it's a link + if ( fi.isLink() ) + { + /// get the real path of the link + std::string link( fi.linksTo() ); + + /// get the current path of the directory without the link dir path + curPath = FileSystem::pathRemoveFileName( dir ); + + /// ensure that ends with the os directory slash + FileSystem::dirAddSlashAtEnd( link ); + + return link; + } + + /// if it's not a link return nothing + return ""; +} + +std::string FileSystem::precomposeFileName( const std::string& name ) +{ +#if EFSW_OS == EFSW_OS_MACOSX + CFStringRef cfStringRef = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingUTF8); + CFMutableStringRef cfMutable = CFStringCreateMutableCopy(NULL, 0, cfStringRef); + + CFStringNormalize(cfMutable,kCFStringNormalizationFormC); + + char c_str[255 + 1]; + CFStringGetCString(cfMutable, c_str, sizeof(c_str)-1, kCFStringEncodingUTF8); + + CFRelease(cfStringRef); + CFRelease(cfMutable); + + return std::string(c_str); +#else + return name; +#endif +} + +bool FileSystem::isRemoteFS( const std::string& directory ) +{ + return Platform::FileSystem::isRemoteFS( directory ); +} + +} diff --git a/dep/efsw/src/efsw/FileSystem.hpp b/dep/efsw/src/efsw/FileSystem.hpp new file mode 100644 index 00000000000..4e2e1aeb7cd --- /dev/null +++ b/dep/efsw/src/efsw/FileSystem.hpp @@ -0,0 +1,40 @@ +#ifndef EFSW_FILESYSTEM_HPP +#define EFSW_FILESYSTEM_HPP + +#include <efsw/base.hpp> +#include <efsw/FileInfo.hpp> +#include <map> + +namespace efsw { + +class FileSystem +{ + public: + static bool isDirectory( const std::string& path ); + + static FileInfoMap filesInfoFromPath( std::string path ); + + static char getOSSlash(); + + static bool slashAtEnd( std::string& dir ); + + static void dirAddSlashAtEnd( std::string& dir ); + + static void dirRemoveSlashAtEnd( std::string& dir ); + + static std::string fileNameFromPath( std::string filepath ); + + static std::string pathRemoveFileName( std::string filepath ); + + static void realPath( std::string curdir, std::string& path ); + + static std::string getLinkRealPath( std::string dir, std::string& curPath ); + + static std::string precomposeFileName(const std::string& name); + + static bool isRemoteFS( const std::string& directory ); +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcher.cpp b/dep/efsw/src/efsw/FileWatcher.cpp new file mode 100644 index 00000000000..e33d5ec46fb --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcher.cpp @@ -0,0 +1,145 @@ +#include <efsw/efsw.hpp> +#include <efsw/FileWatcherImpl.hpp> +#include <efsw/FileWatcherGeneric.hpp> +#include <efsw/FileSystem.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 +# include <efsw/FileWatcherWin32.hpp> +# define FILEWATCHER_IMPL FileWatcherWin32 +# define BACKEND_NAME "Win32" +#elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY +# include <efsw/FileWatcherInotify.hpp> +# define FILEWATCHER_IMPL FileWatcherInotify +# define BACKEND_NAME "Inotify" +#elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE +# include <efsw/FileWatcherKqueue.hpp> +# define FILEWATCHER_IMPL FileWatcherKqueue +# define BACKEND_NAME "Kqueue" +#elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS +# include <efsw/FileWatcherFSEvents.hpp> +# define FILEWATCHER_IMPL FileWatcherFSEvents +# define BACKEND_NAME "FSEvents" +#else +# define FILEWATCHER_IMPL FileWatcherGeneric +# define BACKEND_NAME "Generic" +#endif + +#include <efsw/Debug.hpp> + +namespace efsw { + +FileWatcher::FileWatcher() : + mFollowSymlinks(false), + mOutOfScopeLinks(false) +{ + efDEBUG( "Using backend: %s\n", BACKEND_NAME ); + + mImpl = new FILEWATCHER_IMPL( this ); + + if ( !mImpl->initOK() ) + { + efSAFE_DELETE( mImpl ); + + efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); + + mImpl = new FileWatcherGeneric( this ); + } +} + +FileWatcher::FileWatcher( bool useGenericFileWatcher ) : + mFollowSymlinks(false), + mOutOfScopeLinks(false) +{ + if ( useGenericFileWatcher ) + { + efDEBUG( "Using backend: Generic\n" ); + + mImpl = new FileWatcherGeneric( this ); + } + else + { + efDEBUG( "Using backend: %s\n", BACKEND_NAME ); + + mImpl = new FILEWATCHER_IMPL( this ); + + if ( !mImpl->initOK() ) + { + efSAFE_DELETE( mImpl ); + + efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); + + mImpl = new FileWatcherGeneric( this ); + } + } +} + +FileWatcher::~FileWatcher() +{ + efSAFE_DELETE( mImpl ); +} + +WatchID FileWatcher::addWatch(const std::string& directory, FileWatchListener* watcher) +{ + if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) + { + return mImpl->addWatch(directory, watcher, false); + } + else + { + return Errors::Log::createLastError( Errors::FileRemote, directory ); + } +} + +WatchID FileWatcher::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) +{ + if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) + { + return mImpl->addWatch(directory, watcher, recursive); + } + else + { + return Errors::Log::createLastError( Errors::FileRemote, directory ); + } +} + +void FileWatcher::removeWatch(const std::string& directory) +{ + mImpl->removeWatch(directory); +} + +void FileWatcher::removeWatch(WatchID watchid) +{ + mImpl->removeWatch(watchid); +} + +void FileWatcher::watch() +{ + mImpl->watch(); +} + +std::list<std::string> FileWatcher::directories() +{ + return mImpl->directories(); +} + +void FileWatcher::followSymlinks( bool follow ) +{ + mFollowSymlinks = follow; +} + +const bool& FileWatcher::followSymlinks() const +{ + return mFollowSymlinks; +} + +void FileWatcher::allowOutOfScopeLinks( bool allow ) +{ + mOutOfScopeLinks = allow; +} + +const bool& FileWatcher::allowOutOfScopeLinks() const +{ + return mOutOfScopeLinks; +} + +} diff --git a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp new file mode 100644 index 00000000000..2739e756bb2 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp @@ -0,0 +1,132 @@ +#include <efsw/efsw.h> +#include <efsw/efsw.hpp> +#include <vector> + +#define TOBOOL(i) ((i) == 0 ? false : true) + +/*************************************************************************************************/ +class Watcher_CAPI : public efsw::FileWatchListener +{ +public: + efsw_watcher mWatcher; + efsw_pfn_fileaction_callback mFn; + void* mParam; +public: + Watcher_CAPI(efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param) + { + mWatcher = watcher; + mFn = fn; + mParam = param; + } + + void handleFileAction(efsw::WatchID watchid, const std::string& dir, const std::string& filename, + efsw::Action action, std::string oldFilename = "") + { + mFn(mWatcher, watchid, dir.c_str(), filename.c_str(), (enum efsw_action)action, + oldFilename.c_str(), mParam ); + } +}; + +/************************************************************************************************* + * globals + */ +static std::vector<Watcher_CAPI*> g_callbacks; + +Watcher_CAPI* find_callback(efsw_watcher watcher, efsw_pfn_fileaction_callback fn) +{ + for (std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); i++ ) + { + Watcher_CAPI* callback = *i; + + if (callback->mFn == fn && callback->mWatcher == watcher) + return *i; + } + + return NULL; +} + +Watcher_CAPI* remove_callback(efsw_watcher watcher) +{ + std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); + + while (i != g_callbacks.end()) { + Watcher_CAPI* callback = *i; + + if (callback->mWatcher == watcher) + i = g_callbacks.erase(i); + else + i++; + } + + return NULL; +} + + +/*************************************************************************************************/ +efsw_watcher efsw_create(int generic_mode) +{ + return (efsw_watcher)new efsw::FileWatcher(TOBOOL(generic_mode)); +} + +void efsw_release(efsw_watcher watcher) +{ + remove_callback(watcher); + delete (efsw::FileWatcher*)watcher; +} + +const char* efsw_getlasterror() +{ + static std::string log_str; + log_str = efsw::Errors::Log::getLastErrorLog(); + return log_str.c_str(); +} + +efsw_watchid efsw_addwatch(efsw_watcher watcher, const char* directory, + efsw_pfn_fileaction_callback callback_fn, int recursive, void * param) +{ + Watcher_CAPI* callback = find_callback(watcher, callback_fn); + + if (callback == NULL) { + callback = new Watcher_CAPI(watcher, callback_fn, param); + g_callbacks.push_back(callback); + } + + return ((efsw::FileWatcher*)watcher)->addWatch(std::string(directory), callback, + TOBOOL(recursive)); +} + +void efsw_removewatch(efsw_watcher watcher, const char* directory) +{ + ((efsw::FileWatcher*)watcher)->removeWatch(std::string(directory)); +} + +void efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid) +{ + ((efsw::FileWatcher*)watcher)->removeWatch(watchid); +} + +void efsw_watch(efsw_watcher watcher) +{ + ((efsw::FileWatcher*)watcher)->watch(); +} + +void efsw_follow_symlinks(efsw_watcher watcher, int enable) +{ + ((efsw::FileWatcher*)watcher)->followSymlinks(TOBOOL(enable)); +} + +int efsw_follow_symlinks_isenabled(efsw_watcher watcher) +{ + return (int)((efsw::FileWatcher*)watcher)->followSymlinks(); +} + +void efsw_allow_outofscopelinks(efsw_watcher watcher, int allow) +{ + ((efsw::FileWatcher*)watcher)->allowOutOfScopeLinks(TOBOOL(allow)); +} + +int efsw_outofscopelinks_isallowed(efsw_watcher watcher) +{ + return (int)((efsw::FileWatcher*)watcher)->allowOutOfScopeLinks(); +} + diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp new file mode 100644 index 00000000000..40156674132 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp @@ -0,0 +1,278 @@ +#include <efsw/FileWatcherFSEvents.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/System.hpp> +#include <efsw/Debug.hpp> +#include <efsw/String.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <sys/utsname.h> + +namespace efsw +{ + +int getOSXReleaseNumber() +{ + static int osxR = -1; + + if ( -1 == osxR ) + { + struct utsname os; + + if ( -1 != uname( &os ) ) { + std::string release( os.release ); + + size_t pos = release.find_first_of( '.' ); + + if ( pos != std::string::npos ) + { + release = release.substr( 0, pos ); + } + + int rel = 0; + + if ( String::fromString<int>( rel, release ) ) + { + osxR = rel; + } + } + } + + return osxR; +} + +bool FileWatcherFSEvents::isGranular() +{ + return getOSXReleaseNumber() >= 11; +} + +void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, + void *userData, + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[] ) +{ + WatcherFSEvents * watcher = static_cast<WatcherFSEvents*>( userData ); + + std::vector<FSEvent> events; + events.reserve( numEvents ); + + for ( size_t i = 0; i < numEvents; i++ ) + { + events.push_back( FSEvent( std::string( ((char**)eventPaths)[i] ), (long)eventFlags[i], (Uint64)eventIds[i] ) ); + } + + watcher->handleActions( events ); + + watcher->process(); + + efDEBUG( "\n" ); +} + +FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher * parent ) : + FileWatcherImpl( parent ), + mRunLoopRef( NULL ), + mLastWatchID(0), + mThread( NULL ) +{ + mInitOK = true; + + watch(); +} + +FileWatcherFSEvents::~FileWatcherFSEvents() +{ + WatchMap::iterator iter = mWatches.begin(); + + for( ; iter != mWatches.end(); ++iter ) + { + WatcherFSEvents * watch = iter->second; + + efSAFE_DELETE( watch ); + } + + mWatches.clear(); + + mInitOK = false; + + if ( NULL != mRunLoopRef ) + { + CFRunLoopStop( mRunLoopRef ); + } + + efSAFE_DELETE( mThread ); +} + +WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ) +{ + /// Wait to the RunLoopRef to be ready + while ( NULL == mRunLoopRef ) + { + System::sleep( 1 ); + } + + std::string dir( directory ); + + FileInfo fi( dir ); + + if ( !fi.isDirectory() ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else if ( !fi.isReadable() ) + { + return Errors::Log::createLastError( Errors::FileNotReadable, dir ); + } + + FileSystem::dirAddSlashAtEnd( dir ); + + if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + + /// Check if the directory is a symbolic link + std::string curPath; + std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); + + if ( "" != link ) + { + /// If it's a symlink check if the realpath exists as a watcher, or + /// if the path is outside the current dir + if ( pathInWatches( link ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + else if ( !linkAllowed( curPath, link ) ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); + } + else + { + dir = link; + } + } + + mLastWatchID++; + + WatcherFSEvents * pWatch = new WatcherFSEvents(); + pWatch->Listener = watcher; + pWatch->ID = mLastWatchID; + pWatch->Directory = dir; + pWatch->Recursive = recursive; + pWatch->FWatcher = this; + + pWatch->init(); + + mWatchesLock.lock(); + mWatches.insert(std::make_pair(mLastWatchID, pWatch)); + mWatchesLock.unlock(); + + return pWatch->ID; +} + +void FileWatcherFSEvents::removeWatch(const std::string& directory) +{ + mWatchesLock.lock(); + + WatchMap::iterator iter = mWatches.begin(); + + for(; iter != mWatches.end(); ++iter) + { + if( directory == iter->second->Directory ) + { + removeWatch( iter->second->ID ); + return; + } + } + + mWatchesLock.unlock(); +} + +void FileWatcherFSEvents::removeWatch(WatchID watchid) +{ + mWatchesLock.lock(); + + WatchMap::iterator iter = mWatches.find( watchid ); + + if( iter == mWatches.end() ) + return; + + WatcherFSEvents * watch = iter->second; + + mWatches.erase( iter ); + + efDEBUG( "Removed watch %s\n", watch->Directory.c_str() ); + + efSAFE_DELETE( watch ); + + mWatchesLock.unlock(); +} + +void FileWatcherFSEvents::watch() +{ + if ( NULL == mThread ) + { + mThread = new Thread( &FileWatcherFSEvents::run, this ); + mThread->launch(); + } +} + +void FileWatcherFSEvents::run() +{ + mRunLoopRef = CFRunLoopGetCurrent(); + + while ( mInitOK ) + { + if ( !mNeedInit.empty() ) + { + for ( std::list<WatcherFSEvents*>::iterator it = mNeedInit.begin(); it != mNeedInit.end(); it++ ) + { + (*it)->initAsync(); + } + + mNeedInit.clear(); + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.5, kCFRunLoopRunTimedOut ); + } +} + +void FileWatcherFSEvents::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) +{ + /// Not used +} + +std::list<std::string> FileWatcherFSEvents::directories() +{ + std::list<std::string> dirs; + + mWatchesLock.lock(); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + dirs.push_back( std::string( it->second->Directory ) ); + } + + mWatchesLock.unlock(); + + return dirs; +} + +bool FileWatcherFSEvents::pathInWatches( const std::string& path ) +{ + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + if ( it->second->Directory == path ) + { + return true; + } + } + + return false; +} + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp new file mode 100644 index 00000000000..6aafbc0b5ea --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp @@ -0,0 +1,107 @@ +#ifndef EFSW_FILEWATCHERFSEVENTS_HPP +#define EFSW_FILEWATCHERFSEVENTS_HPP + +#include <efsw/FileWatcherImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <CoreFoundation/CoreFoundation.h> +#include <CoreServices/CoreServices.h> +#include <efsw/WatcherFSEvents.hpp> +#include <map> +#include <list> +#include <vector> + +namespace efsw +{ + +/* OSX < 10.7 has no file events */ +/* So i declare the events constants */ +enum FSEventEvents +{ + efswFSEventStreamCreateFlagFileEvents = 0x00000010, + efswFSEventStreamEventFlagItemCreated = 0x00000100, + efswFSEventStreamEventFlagItemRemoved = 0x00000200, + efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, + efswFSEventStreamEventFlagItemRenamed = 0x00000800, + efswFSEventStreamEventFlagItemModified = 0x00001000, + efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, + efswFSEventStreamEventFlagItemChangeOwner = 0x00004000, + efswFSEventStreamEventFlagItemXattrMod = 0x00008000, + efswFSEventStreamEventFlagItemIsFile = 0x00010000, + efswFSEventStreamEventFlagItemIsDir = 0x00020000, + efswFSEventStreamEventFlagItemIsSymlink = 0x00040000, + efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod | + efswFSEventStreamEventFlagItemModified | + efswFSEventStreamEventFlagItemInodeMetaMod | + efswFSEventStreamEventFlagItemChangeOwner | + efswFSEventStreamEventFlagItemXattrMod +}; + +/// Implementation for Win32 based on ReadDirectoryChangesW. +/// @class FileWatcherFSEvents +class FileWatcherFSEvents : public FileWatcherImpl +{ + friend class WatcherFSEvents; + public: + /// @return If FSEvents supports file-level notifications ( true if OS X >= 10.7 ) + static bool isGranular(); + + /// type for a map from WatchID to WatcherWin32 pointer + typedef std::map<WatchID, WatcherFSEvents*> WatchMap; + + FileWatcherFSEvents( FileWatcher * parent ); + + virtual ~FileWatcherFSEvents(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch(const std::string& directory); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch(WatchID watchid); + + /// Updates the watcher. Must be called often. + void watch(); + + /// Handles the action + void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + + /// @return Returns a list of the directories that are being watched + std::list<std::string> directories(); + protected: + static void FSEventCallback( ConstFSEventStreamRef streamRef, + void *userData, + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[] + ); + + CFRunLoopRef mRunLoopRef; + + /// Vector of WatcherWin32 pointers + WatchMap mWatches; + + /// The last watchid + WatchID mLastWatchID; + + Thread * mThread; + + Mutex mWatchesLock; + + bool pathInWatches( const std::string& path ); + + std::list<WatcherFSEvents*> mNeedInit; + private: + void run(); +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.cpp b/dep/efsw/src/efsw/FileWatcherGeneric.cpp new file mode 100644 index 00000000000..1534b6a9279 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherGeneric.cpp @@ -0,0 +1,197 @@ +#include <efsw/FileWatcherGeneric.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/System.hpp> + +namespace efsw +{ + +FileWatcherGeneric::FileWatcherGeneric( FileWatcher * parent ) : + FileWatcherImpl( parent ), + mThread( NULL ), + mLastWatchID( 0 ) +{ + mInitOK = true; + mIsGeneric = true; +} + +FileWatcherGeneric::~FileWatcherGeneric() +{ + mInitOK = false; + + mThread->wait(); + + efSAFE_DELETE( mThread ); + + /// Delete the watches + WatchList::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + efSAFE_DELETE( (*it) ); + } +} + +WatchID FileWatcherGeneric::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) +{ + std::string dir( directory ); + + FileSystem::dirAddSlashAtEnd( dir ); + + FileInfo fi( dir ); + + if ( !fi.isDirectory() ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else if ( !fi.isReadable() ) + { + return Errors::Log::createLastError( Errors::FileNotReadable, dir ); + } + else if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, dir ); + } + + std::string curPath; + std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); + + if ( "" != link ) + { + if ( pathInWatches( link ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, dir ); + } + else if ( !linkAllowed( curPath, link ) ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); + } + else + { + dir = link; + } + } + + mLastWatchID++; + + WatcherGeneric * pWatch = new WatcherGeneric( mLastWatchID, dir, watcher, this, recursive ); + + mWatchesLock.lock(); + mWatches.push_back(pWatch); + mWatchesLock.unlock(); + + return pWatch->ID; +} + +void FileWatcherGeneric::removeWatch( const std::string& directory ) +{ + WatchList::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + if ( (*it)->Directory == directory ) + { + WatcherGeneric * watch = (*it); + + mWatchesLock.lock(); + + mWatches.erase( it ); + + efSAFE_DELETE( watch ) ; + + mWatchesLock.unlock(); + + return; + } + } +} + +void FileWatcherGeneric::removeWatch(WatchID watchid) +{ + WatchList::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + if ( (*it)->ID == watchid ) + { + WatcherGeneric * watch = (*it); + + mWatchesLock.lock(); + + mWatches.erase( it ); + + efSAFE_DELETE( watch ) ; + + mWatchesLock.unlock(); + + return; + } + } +} + +void FileWatcherGeneric::watch() +{ + if ( NULL == mThread ) + { + mThread = new Thread( &FileWatcherGeneric::run, this ); + mThread->launch(); + } +} + +void FileWatcherGeneric::run() +{ + do + { + mWatchesLock.lock(); + + WatchList::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + (*it)->watch(); + } + + mWatchesLock.unlock(); + + if ( mInitOK ) System::sleep( 1000 ); + } while ( mInitOK ); +} + +void FileWatcherGeneric::handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename) +{ + /// Not used +} + +std::list<std::string> FileWatcherGeneric::directories() +{ + std::list<std::string> dirs; + + mWatchesLock.lock(); + + WatchList::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + dirs.push_back( (*it)->Directory ); + } + + mWatchesLock.unlock(); + + return dirs; +} + +bool FileWatcherGeneric::pathInWatches( const std::string& path ) +{ + WatchList::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + if ( (*it)->Directory == path || (*it)->pathInWatches( path ) ) + { + return true; + } + } + + return false; +} + +} diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.hpp b/dep/efsw/src/efsw/FileWatcherGeneric.hpp new file mode 100644 index 00000000000..fc9826580ab --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherGeneric.hpp @@ -0,0 +1,59 @@ +#ifndef EFSW_FILEWATCHERGENERIC_HPP +#define EFSW_FILEWATCHERGENERIC_HPP + +#include <efsw/FileWatcherImpl.hpp> +#include <efsw/WatcherGeneric.hpp> +#include <efsw/DirWatcherGeneric.hpp> +#include <list> + +namespace efsw +{ + +/// Implementation for Generic File Watcher. +/// @class FileWatcherGeneric +class FileWatcherGeneric : public FileWatcherImpl +{ + public: + typedef std::list<WatcherGeneric*> WatchList; + + FileWatcherGeneric( FileWatcher * parent ); + + virtual ~FileWatcherGeneric(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch(const std::string& directory); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch(WatchID watchid); + + /// Updates the watcher. Must be called often. + void watch(); + + /// Handles the action + void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + + /// @return Returns a list of the directories that are being watched + std::list<std::string> directories(); + protected: + Thread * mThread; + + /// The last watchid + WatchID mLastWatchID; + + /// Map of WatchID to WatchStruct pointers + WatchList mWatches; + + Mutex mWatchesLock; + + bool pathInWatches( const std::string& path ); + private: + void run(); +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherImpl.cpp b/dep/efsw/src/efsw/FileWatcherImpl.cpp new file mode 100644 index 00000000000..e6e0fc72a13 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherImpl.cpp @@ -0,0 +1,29 @@ +#include <efsw/FileWatcherImpl.hpp> +#include <efsw/String.hpp> +#include <efsw/System.hpp> + +namespace efsw { + +FileWatcherImpl::FileWatcherImpl( FileWatcher * parent ) : + mFileWatcher( parent ), + mInitOK( false ), + mIsGeneric( false ) +{ + System::maxFD(); +} + +FileWatcherImpl::~FileWatcherImpl() +{ +} + +bool FileWatcherImpl::initOK() +{ + return mInitOK; +} + +bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) +{ + return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || -1 != String::strStartsWith( curPath, link ); +} + +} diff --git a/dep/efsw/src/efsw/FileWatcherImpl.hpp b/dep/efsw/src/efsw/FileWatcherImpl.hpp new file mode 100644 index 00000000000..8f472bf56c5 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherImpl.hpp @@ -0,0 +1,54 @@ +#ifndef EFSW_FILEWATCHERIMPL_HPP +#define EFSW_FILEWATCHERIMPL_HPP + +#include <efsw/base.hpp> +#include <efsw/efsw.hpp> +#include <efsw/Watcher.hpp> +#include <efsw/Thread.hpp> +#include <efsw/Mutex.hpp> + +namespace efsw { + +class FileWatcherImpl +{ + public: + FileWatcherImpl( FileWatcher * parent ); + + virtual ~FileWatcherImpl(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + virtual WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) = 0; + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + virtual void removeWatch(const std::string& directory) = 0; + + /// Remove a directory watch. This is a map lookup O(logn). + virtual void removeWatch(WatchID watchid) = 0; + + /// Updates the watcher. Must be called often. + virtual void watch() = 0; + + /// Handles the action + virtual void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = "") = 0; + + /// @return Returns a list of the directories that are being watched + virtual std::list<std::string> directories() = 0; + + /// @return true if the backend init successfully + virtual bool initOK(); + + /// @return If the link is allowed according to the current path and the state of out scope links + virtual bool linkAllowed( const std::string& curPath, const std::string& link ); + + /// Search if a directory already exists in the watches + virtual bool pathInWatches( const std::string& path ) = 0; + + FileWatcher * mFileWatcher; + bool mInitOK; + bool mIsGeneric; +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp new file mode 100644 index 00000000000..19c20761663 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp @@ -0,0 +1,531 @@ +#include <efsw/FileWatcherInotify.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY + +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> + +#ifdef EFSW_INOTIFY_NOSYS +#include <efsw/inotify-nosys.h> +#else +#include <sys/inotify.h> +#endif + +#include <efsw/FileSystem.hpp> +#include <efsw/System.hpp> +#include <efsw/Debug.hpp> + +#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024) + +namespace efsw +{ + +FileWatcherInotify::FileWatcherInotify( FileWatcher * parent ) : + FileWatcherImpl( parent ), + mFD(-1), + mThread(NULL) +{ + mFD = inotify_init(); + + if (mFD < 0) + { + efDEBUG( "Error: %s\n", strerror(errno) ); + } + else + { + mInitOK = true; + } +} + +FileWatcherInotify::~FileWatcherInotify() +{ + mInitOK = false; + + efSAFE_DELETE( mThread ); + + WatchMap::iterator iter = mWatches.begin(); + WatchMap::iterator end = mWatches.end(); + + for(; iter != end; ++iter) + { + efSAFE_DELETE( iter->second ); + } + + mWatches.clear(); + + if ( mFD != -1 ) + { + close(mFD); + mFD = -1; + } +} + +WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ) +{ + return addWatch( directory, watcher, recursive, NULL ); +} + +WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherInotify * parent ) +{ + std::string dir( directory ); + + FileSystem::dirAddSlashAtEnd( dir ); + + FileInfo fi( dir ); + + if ( !fi.isDirectory() ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else if ( !fi.isReadable() ) + { + return Errors::Log::createLastError( Errors::FileNotReadable, dir ); + } + else if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + else if ( NULL != parent && FileSystem::isRemoteFS( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRemote, dir ); + } + + /// Check if the directory is a symbolic link + std::string curPath; + std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); + + if ( "" != link ) + { + /// Avoid adding symlinks directories if it's now enabled + if ( NULL != parent && !mFileWatcher->followSymlinks() ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); + } + + /// If it's a symlink check if the realpath exists as a watcher, or + /// if the path is outside the current dir + if ( pathInWatches( link ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + else if ( !linkAllowed( curPath, link ) ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); + } + else + { + dir = link; + } + } + + int wd = inotify_add_watch (mFD, dir.c_str(), IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE | IN_MOVED_FROM | IN_DELETE | IN_MODIFY); + + if ( wd < 0 ) + { + if( errno == ENOENT ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else + { + return Errors::Log::createLastError( Errors::Unspecified, std::string(strerror(errno)) ); + } + } + + efDEBUG( "Added watch %s with id: %d\n", dir.c_str(), wd ); + + WatcherInotify * pWatch = new WatcherInotify(); + pWatch->Listener = watcher; + pWatch->ID = wd; + pWatch->Directory = dir; + pWatch->Recursive = recursive; + pWatch->Parent = parent; + + mWatchesLock.lock(); + mWatches.insert(std::make_pair(wd, pWatch)); + mWatchesLock.unlock(); + + if ( NULL == pWatch->Parent ) + { + mRealWatches[ pWatch->ID ] = pWatch; + } + + if ( pWatch->Recursive ) + { + std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory ); + std::map<std::string, FileInfo>::iterator it = files.begin(); + + for ( ; it != files.end(); it++ ) + { + FileInfo fi = it->second; + + if ( fi.isDirectory() && fi.isReadable() ) + { + addWatch( fi.Filepath, watcher, recursive, pWatch ); + } + } + } + + return wd; +} + +void FileWatcherInotify::removeWatchLocked(WatchID watchid) +{ + WatchMap::iterator iter = mWatches.find( watchid ); + + WatcherInotify * watch = iter->second; + + if ( watch->Recursive ) + { + WatchMap::iterator it = mWatches.begin(); + std::list<WatchID> eraseWatches; + + for(; it != mWatches.end(); ++it) + { + if ( it->second != watch && + it->second->inParentTree( watch ) + ) + { + eraseWatches.push_back( it->second->ID ); + } + } + + for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ ) + { + removeWatch( *eit ); + } + } + + mWatches.erase( iter ); + + if ( NULL == watch->Parent ) + { + WatchMap::iterator eraseit = mRealWatches.find( watch->ID ); + + if ( eraseit != mRealWatches.end() ) + { + mRealWatches.erase( eraseit ); + } + } + + int err = inotify_rm_watch(mFD, watchid); + + if ( err < 0 ) + { + efDEBUG( "Error removing watch %d: %s\n", watchid, strerror(errno) ); + } + else + { + efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), watchid ); + } + + efSAFE_DELETE( watch ); +} + +void FileWatcherInotify::removeWatch(const std::string& directory) +{ + mWatchesLock.lock(); + + WatchMap::iterator iter = mWatches.begin(); + + for(; iter != mWatches.end(); ++iter) + { + if( directory == iter->second->Directory ) + { + WatcherInotify * watch = iter->second; + + if ( watch->Recursive ) + { + WatchMap::iterator it = mWatches.begin(); + std::list<WatchID> eraseWatches; + + for(; it != mWatches.end(); ++it) + { + if ( it->second->inParentTree( watch ) ) + { + eraseWatches.push_back( it->second->ID ); + } + } + + for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ ) + { + removeWatchLocked( *eit ); + } + } + + mWatches.erase( iter ); + + if ( NULL == watch->Parent ) + { + WatchMap::iterator eraseit = mRealWatches.find( watch->ID ); + + if ( eraseit != mRealWatches.end() ) + { + mRealWatches.erase( eraseit ); + } + } + + int err = inotify_rm_watch(mFD, watch->ID); + + if ( err < 0 ) + { + efDEBUG( "Error removing watch %d: %s\n", watch->ID, strerror(errno) ); + } + else + { + efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), watch->ID ); + } + + efSAFE_DELETE( watch ); + + break; + } + } + + mWatchesLock.unlock(); +} + +void FileWatcherInotify::removeWatch( WatchID watchid ) +{ + mWatchesLock.lock(); + + WatchMap::iterator iter = mWatches.find( watchid ); + + if( iter == mWatches.end() ) + { + mWatchesLock.unlock(); + + return; + } + + removeWatchLocked( watchid ); + + mWatchesLock.unlock(); +} + +void FileWatcherInotify::watch() +{ + if ( NULL == mThread ) + { + mThread = new Thread( &FileWatcherInotify::run, this ); + mThread->launch(); + } +} + +void FileWatcherInotify::run() +{ + static char buff[BUFF_SIZE] = {0}; + WatchMap::iterator wit; + std::list<WatcherInotify*> movedOutsideWatches; + + do + { + fd_set rfds; + FD_ZERO (&rfds); + FD_SET (mFD, &rfds); + timeval timeout; + timeout.tv_sec=0; + timeout.tv_usec=100000; + + if( select (FD_SETSIZE, &rfds, NULL, NULL, &timeout) > 0 ) + { + ssize_t len, i = 0; + + len = read (mFD, buff, BUFF_SIZE); + + if (len != -1) + { + while (i < len) + { + struct inotify_event *pevent = (struct inotify_event *)&buff[i]; + + mWatchesLock.lock(); + + wit = mWatches.find( pevent->wd ); + + if ( wit != mWatches.end() ) + { + handleAction(wit->second, pevent->name, pevent->mask); + + /// Keep track of the IN_MOVED_FROM events to known if the IN_MOVED_TO event is also fired + if ( !wit->second->OldFileName.empty() ) + { + movedOutsideWatches.push_back( wit->second ); + } + } + + mWatchesLock.unlock(); + + i += sizeof(struct inotify_event) + pevent->len; + } + + if ( !movedOutsideWatches.empty() ) + { + /// In case that the IN_MOVED_TO is never fired means that the file was moved to other folder + for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); it++ ) + { + if ( !(*it)->OldFileName.empty() ) + { + /// So we send a IN_DELETE event for files that where moved outside of our scope + handleAction( *it, (*it)->OldFileName, IN_DELETE ); + + /// Remove the OldFileName + (*it)->OldFileName = ""; + } + } + + movedOutsideWatches.clear(); + } + } + } + } while( mInitOK ); +} + +void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) +{ + FileSystem::dirAddSlashAtEnd( fpath ); + + /// If the watcher is recursive, checks if the new file is a folder, and creates a watcher + if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) + { + bool found = false; + + /// First check if exists + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + if ( it->second->Directory == fpath ) + { + found = true; + break; + } + } + + if ( !found ) + { + addWatch( fpath, watch->Listener, watch->Recursive, static_cast<WatcherInotify*>( watch ) ); + } + } +} + +void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename ) +{ + if ( !watch || !watch->Listener ) + { + return; + } + + std::string fpath( watch->Directory + filename ); + + if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) + { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified ); + } + else if( IN_MOVED_TO & action ) + { + /// If OldFileName doesn't exist means that the file has been moved from other folder, so we just send the Add event + if ( watch->OldFileName.empty() ) + { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Add ); + + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified ); + + checkForNewWatcher( watch, fpath ); + } + else + { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Moved, watch->OldFileName ); + } + + if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) + { + /// Update the new directory path + std::string opath( watch->Directory + watch->OldFileName ); + FileSystem::dirAddSlashAtEnd( opath ); + FileSystem::dirAddSlashAtEnd( fpath ); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + if ( it->second->Directory == opath && it->second->DirInfo.Inode == FileInfo( opath ).Inode ) + { + it->second->Directory = fpath; + it->second->DirInfo = FileInfo( fpath ); + + break; + } + } + } + + watch->OldFileName = ""; + } + else if( IN_CREATE & action ) + { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Add ); + + checkForNewWatcher( watch, fpath ); + } + else if ( IN_MOVED_FROM & action ) + { + watch->OldFileName = filename; + } + else if( IN_DELETE & action ) + { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Delete ); + + FileSystem::dirAddSlashAtEnd( fpath ); + + /// If the file erased is a directory and recursive is enabled, removes the directory erased + if ( watch->Recursive ) + { + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + if ( it->second->Directory == fpath ) + { + removeWatch( it->second->ID ); + break; + } + } + } + } +} + +std::list<std::string> FileWatcherInotify::directories() +{ + std::list<std::string> dirs; + + mWatchesLock.lock(); + + WatchMap::iterator it = mRealWatches.begin(); + + for ( ; it != mRealWatches.end(); it++ ) + { + dirs.push_back( it->second->Directory ); + } + + mWatchesLock.unlock(); + + return dirs; +} + +bool FileWatcherInotify::pathInWatches( const std::string& path ) +{ + /// Search in the real watches, since it must allow adding a watch already watched as a subdir + WatchMap::iterator it = mRealWatches.begin(); + + for ( ; it != mRealWatches.end(); it++ ) + { + if ( it->second->Directory == path ) + { + return true; + } + } + + return false; +} + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherInotify.hpp b/dep/efsw/src/efsw/FileWatcherInotify.hpp new file mode 100644 index 00000000000..43ee9ca6afc --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherInotify.hpp @@ -0,0 +1,73 @@ +#ifndef EFSW_FILEWATCHERLINUX_HPP +#define EFSW_FILEWATCHERLINUX_HPP + +#include <efsw/FileWatcherImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY + +#include <efsw/WatcherInotify.hpp> +#include <map> + +namespace efsw +{ + +/// Implementation for Linux based on inotify. +/// @class FileWatcherInotify +class FileWatcherInotify : public FileWatcherImpl +{ + public: + /// type for a map from WatchID to WatchStruct pointer + typedef std::map<WatchID, WatcherInotify*> WatchMap; + + FileWatcherInotify( FileWatcher * parent ); + + virtual ~FileWatcherInotify(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch(const std::string& directory); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch(WatchID watchid); + + /// Updates the watcher. Must be called often. + void watch(); + + /// Handles the action + void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + + /// @return Returns a list of the directories that are being watched + std::list<std::string> directories(); + protected: + /// Map of WatchID to WatchStruct pointers + WatchMap mWatches; + + /// User added watches + WatchMap mRealWatches; + + /// inotify file descriptor + int mFD; + + Thread * mThread; + + Mutex mWatchesLock; + + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherInotify * parent = NULL ); + + bool pathInWatches( const std::string& path ); + private: + void run(); + + void removeWatchLocked(WatchID watchid); + + void checkForNewWatcher( Watcher* watch, std::string fpath ); +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.cpp b/dep/efsw/src/efsw/FileWatcherKqueue.cpp new file mode 100644 index 00000000000..600fd085b35 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherKqueue.cpp @@ -0,0 +1,274 @@ +#include <efsw/FileWatcherKqueue.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <sys/time.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <dirent.h> +#include <string.h> +#include <efsw/FileSystem.hpp> +#include <efsw/System.hpp> +#include <efsw/Debug.hpp> +#include <efsw/WatcherGeneric.hpp> + +namespace efsw +{ + +FileWatcherKqueue::FileWatcherKqueue( FileWatcher * parent ) : + FileWatcherImpl( parent ), + mLastWatchID(0), + mThread( NULL ), + mFileDescriptorCount( 1 ), + mAddingWatcher( false ) +{ + mTimeOut.tv_sec = 0; + mTimeOut.tv_nsec = 0; + mInitOK = true; +} + +FileWatcherKqueue::~FileWatcherKqueue() +{ + WatchMap::iterator iter = mWatches.begin(); + + for(; iter != mWatches.end(); ++iter) + { + efSAFE_DELETE( iter->second ); + } + + mWatches.clear(); + + mInitOK = false; + + mThread->wait(); + + efSAFE_DELETE( mThread ); +} + +WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) +{ + static bool s_ug = false; + + std::string dir( directory ); + + FileSystem::dirAddSlashAtEnd( dir ); + + FileInfo fi( dir ); + + if ( !fi.isDirectory() ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else if ( !fi.isReadable() ) + { + return Errors::Log::createLastError( Errors::FileNotReadable, dir ); + } + else if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + + std::string curPath; + std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); + + if ( "" != link ) + { + if ( pathInWatches( link ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + else if ( !linkAllowed( curPath, link ) ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); + } + else + { + dir = link; + } + } + + /// Check first if are enough file descriptors available to create another kqueue watcher, otherwise it creates a generic watcher + if ( availablesFD() ) + { + mAddingWatcher = true; + + WatcherKqueue * watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, this ); + + mWatchesLock.lock(); + mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatchesLock.unlock(); + + watch->addAll(); + + // if failed to open the directory... erase the watcher + if ( !watch->initOK() ) + { + int le = watch->lastErrno(); + + mWatches.erase( watch->ID ); + + efSAFE_DELETE( watch ); + + mLastWatchID--; + + // Probably the folder has too many files, create a generic watcher + if ( EACCES != le ) + { + WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); + + mWatchesLock.lock(); + mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatchesLock.unlock(); + } + else + { + return Errors::Log::createLastError( Errors::Unspecified, link ); + } + } + + mAddingWatcher = false; + } + else + { + if ( !s_ug ) + { + efDEBUG( "Started using generic watcher, file descriptor limit reached: %ld\n", mFileDescriptorCount ); + s_ug = true; + } + + WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); + + mWatchesLock.lock(); + mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatchesLock.unlock(); + } + + return mLastWatchID; +} + +void FileWatcherKqueue::removeWatch(const std::string& directory) +{ + mWatchesLock.lock(); + + WatchMap::iterator iter = mWatches.begin(); + + for(; iter != mWatches.end(); ++iter) + { + if(directory == iter->second->Directory) + { + removeWatch(iter->first); + return; + } + } + + mWatchesLock.unlock(); +} + +void FileWatcherKqueue::removeWatch(WatchID watchid) +{ + mWatchesLock.lock(); + + WatchMap::iterator iter = mWatches.find(watchid); + + if(iter == mWatches.end()) + return; + + Watcher* watch = iter->second; + + mWatches.erase(iter); + + efSAFE_DELETE( watch ); + + mWatchesLock.unlock(); +} + +bool FileWatcherKqueue::isAddingWatcher() const +{ + return mAddingWatcher; +} + +void FileWatcherKqueue::watch() +{ + if ( NULL == mThread ) + { + mThread = new Thread( &FileWatcherKqueue::run, this ); + mThread->launch(); + } +} + +void FileWatcherKqueue::run() +{ + do + { + mWatchesLock.lock(); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) + { + it->second->watch(); + } + + mWatchesLock.unlock(); + + System::sleep( 500 ); + } while( mInitOK ); +} + +void FileWatcherKqueue::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) +{ +} + +std::list<std::string> FileWatcherKqueue::directories() +{ + std::list<std::string> dirs; + + mWatchesLock.lock(); + + WatchMap::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + dirs.push_back( it->second->Directory ); + } + + mWatchesLock.unlock(); + + return dirs; +} + +bool FileWatcherKqueue::pathInWatches( const std::string& path ) +{ + WatchMap::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + if ( it->second->Directory == path ) + { + return true; + } + } + + return false; +} + +void FileWatcherKqueue::addFD() +{ + mFileDescriptorCount++; +} + +void FileWatcherKqueue::removeFD() +{ + mFileDescriptorCount--; +} + +bool FileWatcherKqueue::availablesFD() +{ + return mFileDescriptorCount <= (Int64)System::getMaxFD() - 500; +} + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.hpp b/dep/efsw/src/efsw/FileWatcherKqueue.hpp new file mode 100644 index 00000000000..0a2431e3777 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherKqueue.hpp @@ -0,0 +1,78 @@ +#ifndef EFSW_FILEWATCHEROSX_HPP +#define EFSW_FILEWATCHEROSX_HPP + +#include <efsw/FileWatcherImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <efsw/WatcherKqueue.hpp> + +namespace efsw +{ + +/// Implementation for OSX based on kqueue. +/// @class FileWatcherKqueue +class FileWatcherKqueue : public FileWatcherImpl +{ + friend class WatcherKqueue; + public: + FileWatcherKqueue( FileWatcher * parent ); + + virtual ~FileWatcherKqueue(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch(const std::string& directory); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch(WatchID watchid); + + /// Updates the watcher. Must be called often. + void watch(); + + /// Handles the action + void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + + /// @return Returns a list of the directories that are being watched + std::list<std::string> directories(); + protected: + /// Map of WatchID to WatchStruct pointers + WatchMap mWatches; + + /// time out data + struct timespec mTimeOut; + + /// WatchID allocator + int mLastWatchID; + + Thread * mThread; + + Mutex mWatchesLock; + + std::list<WatchID> mRemoveList; + + long mFileDescriptorCount; + + bool mAddingWatcher; + + bool isAddingWatcher() const; + + bool pathInWatches( const std::string& path ); + + void addFD(); + + void removeFD(); + + bool availablesFD(); + private: + void run(); +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherWin32.cpp b/dep/efsw/src/efsw/FileWatcherWin32.cpp new file mode 100644 index 00000000000..fe78dd122cf --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherWin32.cpp @@ -0,0 +1,291 @@ +#include <efsw/FileWatcherWin32.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/System.hpp> +#include <efsw/String.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +namespace efsw +{ + +FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) : + FileWatcherImpl( parent ), + mLastWatchID(0), + mThread( NULL ) +{ + mInitOK = true; +} + +FileWatcherWin32::~FileWatcherWin32() +{ + WatchVector::iterator iter = mWatches.begin(); + + mWatchesLock.lock(); + + for(; iter != mWatches.end(); ++iter) + { + DestroyWatch((*iter)); + } + + mHandles.clear(); + mWatches.clear(); + + mInitOK = false; + + mWatchesLock.unlock(); + + efSAFE_DELETE( mThread ); +} + +WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) +{ + std::string dir( directory ); + + FileInfo fi( dir ); + + if ( !fi.isDirectory() ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else if ( !fi.isReadable() ) + { + return Errors::Log::createLastError( Errors::FileNotReadable, dir ); + } + + FileSystem::dirAddSlashAtEnd( dir ); + + WatchID watchid = ++mLastWatchID; + + mWatchesLock.lock(); + + WatcherStructWin32 * watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), recursive, FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_SIZE + ); + + if( NULL == watch ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + + if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, dir ); + } + + // Add the handle to the handles vector + watch->Watch->ID = watchid; + watch->Watch->Watch = this; + watch->Watch->Listener = watcher; + watch->Watch->DirName = new char[dir.length()+1]; + strcpy(watch->Watch->DirName, dir.c_str()); + + mHandles.push_back( watch->Watch->DirHandle ); + mWatches.push_back( watch ); + mWatchesLock.unlock(); + + return watchid; +} + +void FileWatcherWin32::removeWatch(const std::string& directory) +{ + mWatchesLock.lock(); + + WatchVector::iterator iter = mWatches.begin(); + + for(; iter != mWatches.end(); ++iter) + { + if(directory == (*iter)->Watch->DirName) + { + removeWatch((*iter)->Watch->ID); + return; + } + } + + mWatchesLock.unlock(); +} + +void FileWatcherWin32::removeWatch(WatchID watchid) +{ + mWatchesLock.lock(); + + WatchVector::iterator iter = mWatches.begin(); + + WatcherStructWin32* watch = NULL; + + for(; iter != mWatches.end(); ++iter) + { + // Find the watch ID + if ( (*iter)->Watch->ID == watchid ) + { + watch = (*iter); + + mWatches.erase( iter ); + + // Remove handle from the handle vector + HandleVector::iterator it = mHandles.begin(); + + for ( ; it != mHandles.end(); it++ ) + { + if ( watch->Watch->DirHandle == (*it) ) + { + mHandles.erase( it ); + break; + } + } + + DestroyWatch(watch); + + break; + } + } + + mWatchesLock.unlock(); +} + +void FileWatcherWin32::watch() +{ + if ( NULL == mThread ) + { + mThread = new Thread( &FileWatcherWin32::run, this ); + mThread->launch(); + } +} + +void FileWatcherWin32::run() +{ + if ( mHandles.empty() ) + { + return; + } + + do + { + if ( !mHandles.empty() ) + { + mWatchesLock.lock(); + + for ( std::size_t i = 0; i < mWatches.size(); i++ ) + { + WatcherStructWin32 * watch = mWatches[ i ]; + + // If the overlapped struct was cancelled ( because the creator thread doesn't exists anymore ), + // we recreate the overlapped in the current thread and refresh the watch + if ( /*STATUS_CANCELED*/0xC0000120 == watch->Overlapped.Internal ) + { + watch->Overlapped = OVERLAPPED(); + RefreshWatch(watch); + } + + // First ensure that the handle is the same, this means that the watch was not removed. + if ( HasOverlappedIoCompleted( &watch->Overlapped ) && mHandles[ i ] == watch->Watch->DirHandle ) + { + DWORD bytes; + + if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) + { + WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); + } + } + } + + mWatchesLock.unlock(); + + if ( mInitOK ) + { + System::sleep( 10 ); + } + } + else + { + // Wait for a new handle to be added + System::sleep( 10 ); + } + } while ( mInitOK ); +} + +void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) +{ + Action fwAction; + + switch(action) + { + case FILE_ACTION_RENAMED_OLD_NAME: + watch->OldFileName = filename; + return; + case FILE_ACTION_ADDED: + fwAction = Actions::Add; + break; + case FILE_ACTION_RENAMED_NEW_NAME: + { + fwAction = Actions::Moved; + + std::string fpath( watch->Directory + filename ); + + // Update the directory path + if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) + { + // Update the new directory path + std::string opath( watch->Directory + watch->OldFileName ); + FileSystem::dirAddSlashAtEnd( opath ); + FileSystem::dirAddSlashAtEnd( fpath ); + + for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + if ( (*it)->Watch->Directory == opath ) + { + (*it)->Watch->Directory = fpath; + + break; + } + } + } + + watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction, watch->OldFileName); + return; + } + case FILE_ACTION_REMOVED: + fwAction = Actions::Delete; + break; + case FILE_ACTION_MODIFIED: + fwAction = Actions::Modified; + break; + }; + + watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction); +} + +std::list<std::string> FileWatcherWin32::directories() +{ + std::list<std::string> dirs; + + mWatchesLock.lock(); + + for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + dirs.push_back( std::string( (*it)->Watch->DirName ) ); + } + + mWatchesLock.unlock(); + + return dirs; +} + +bool FileWatcherWin32::pathInWatches( const std::string& path ) +{ + for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + if ( (*it)->Watch->DirName == path ) + { + return true; + } + } + + return false; +} + +} + +#endif diff --git a/dep/efsw/src/efsw/FileWatcherWin32.hpp b/dep/efsw/src/efsw/FileWatcherWin32.hpp new file mode 100644 index 00000000000..505cd772b82 --- /dev/null +++ b/dep/efsw/src/efsw/FileWatcherWin32.hpp @@ -0,0 +1,69 @@ +#ifndef EFSW_FILEWATCHERWIN32_HPP +#define EFSW_FILEWATCHERWIN32_HPP + +#include <efsw/base.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#include <efsw/WatcherWin32.hpp> +#include <vector> +#include <map> + +namespace efsw +{ + +/// Implementation for Win32 based on ReadDirectoryChangesW. +/// @class FileWatcherWin32 +class FileWatcherWin32 : public FileWatcherImpl +{ + public: + /// type for a map from WatchID to WatcherWin32 pointer + typedef std::vector<WatcherStructWin32*> WatchVector; + typedef std::vector<HANDLE> HandleVector; + + FileWatcherWin32( FileWatcher * parent ); + + virtual ~FileWatcherWin32(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch(const std::string& directory); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch(WatchID watchid); + + /// Updates the watcher. Must be called often. + void watch(); + + /// Handles the action + void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + + /// @return Returns a list of the directories that are being watched + std::list<std::string> directories(); + protected: + /// Vector of WatcherWin32 pointers + WatchVector mWatches; + + /// Keeps an updated handles vector + HandleVector mHandles; + + /// The last watchid + WatchID mLastWatchID; + + Thread * mThread; + + Mutex mWatchesLock; + + bool pathInWatches( const std::string& path ); + private: + void run(); +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/Log.cpp b/dep/efsw/src/efsw/Log.cpp new file mode 100644 index 00000000000..8e2860ac099 --- /dev/null +++ b/dep/efsw/src/efsw/Log.cpp @@ -0,0 +1,27 @@ +#include <efsw/efsw.hpp> + +namespace efsw { namespace Errors { + +static std::string LastError; + +std::string Log::getLastErrorLog() +{ + return LastError; +} + +Error Log::createLastError( Error err, std::string log ) +{ + switch ( err ) + { + case FileNotFound: LastError = "File not found ( " + log + " )"; break; + case FileRepeated: LastError = "File reapeated in watches ( " + log + " )"; break; + case FileOutOfScope: LastError = "Symlink file out of scope ( " + log + " )"; break; + case FileRemote: LastError = "File is located in a remote file system, use a generic watcher. ( " + log + " )"; break; + case Unspecified: + default: LastError = log; + } + + return err; +} + +}} diff --git a/dep/efsw/src/efsw/Mutex.cpp b/dep/efsw/src/efsw/Mutex.cpp new file mode 100644 index 00000000000..b34ba066ee9 --- /dev/null +++ b/dep/efsw/src/efsw/Mutex.cpp @@ -0,0 +1,26 @@ +#include <efsw/Mutex.hpp> +#include <efsw/platform/platformimpl.hpp> + +namespace efsw { + +Mutex::Mutex() : + mMutexImpl( new Platform::MutexImpl() ) +{ +} + +Mutex::~Mutex() +{ + efSAFE_DELETE( mMutexImpl ); +} + +void Mutex::lock() +{ + mMutexImpl->lock(); +} + +void Mutex::unlock() +{ + mMutexImpl->unlock(); +} + +} diff --git a/dep/efsw/src/efsw/Mutex.hpp b/dep/efsw/src/efsw/Mutex.hpp new file mode 100644 index 00000000000..e6e89def175 --- /dev/null +++ b/dep/efsw/src/efsw/Mutex.hpp @@ -0,0 +1,28 @@ +#ifndef EFSW_MUTEX_HPP +#define EFSW_MUTEX_HPP + +#include <efsw/base.hpp> + +namespace efsw { + +namespace Platform { class MutexImpl; } + +/** Simple mutex class */ +class Mutex { + public: + Mutex(); + + ~Mutex(); + + /** Lock the mutex */ + void lock(); + + /** Unlock the mutex */ + void unlock(); + private: + Platform::MutexImpl * mMutexImpl; +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/String.cpp b/dep/efsw/src/efsw/String.cpp new file mode 100644 index 00000000000..f703d25cb35 --- /dev/null +++ b/dep/efsw/src/efsw/String.cpp @@ -0,0 +1,813 @@ +#include <iterator> +#include <efsw/String.hpp> +#include <efsw/Utf.hpp> + +namespace efsw { + +const std::size_t String::InvalidPos = StringType::npos; + +std::vector < std::string > String::split ( const std::string& str, const char& splitchar, const bool& pushEmptyString ) +{ + std::vector < std::string > tmp; + std::string tmpstr; + + for ( size_t i = 0; i < str.size(); i++ ) + { + if ( str[i] == splitchar ) + { + if ( pushEmptyString || tmpstr.size() ) + { + tmp.push_back(tmpstr); + tmpstr = ""; + } + } + else + { + tmpstr += str[i]; + } + } + + if ( tmpstr.size() ) + { + tmp.push_back( tmpstr ); + } + + return tmp; +} + +std::vector < String > String::split ( const String& str, const Uint32& splitchar, const bool& pushEmptyString ) +{ + std::vector < String > tmp; + String tmpstr; + + for ( size_t i = 0; i < str.size(); i++ ) + { + if ( str[i] == splitchar ) + { + if ( pushEmptyString || tmpstr.size() ) + { + tmp.push_back(tmpstr); + tmpstr = ""; + } + } + else + { + tmpstr += str[i]; + } + } + + if ( tmpstr.size() ) + { + tmp.push_back( tmpstr ); + } + + return tmp; +} + +int String::strStartsWith( const std::string& start, const std::string& str ) +{ + int pos = -1; + size_t size = start.size(); + + if ( str.size() >= size ) + { + for ( std::size_t i = 0; i < size; i++ ) + { + if ( start[i] == str[i] ) + { + pos = (int)i; + } + else + { + pos = -1; + break; + } + } + } + + return pos; +} + +int String::strStartsWith( const String& start, const String& str ) +{ + int pos = -1; + size_t size = start.size(); + + if ( str.size() >= size ) + { + for ( std::size_t i = 0; i < size; i++ ) + { + if ( start[i] == str[i] ) + { + pos = (int)i; + } + else + { + pos = -1; + break; + } + } + } + + return pos; +} + +String::String() +{ +} + +String::String(char ansiChar, const std::locale& locale) +{ + mString += Utf32::DecodeAnsi(ansiChar, locale); +} + +#ifndef EFSW_NO_WIDECHAR +String::String(wchar_t wideChar) +{ + mString += Utf32::DecodeWide(wideChar); +} +#endif + +String::String(StringBaseType utf32Char) +{ + mString += utf32Char; +} + +String::String( const char* uf8String ) { + if (uf8String) + { + std::size_t length = strlen(uf8String); + + if (length > 0) + { + mString.reserve(length + 1); + + Utf8::ToUtf32(uf8String, uf8String + length, std::back_inserter(mString)); + } + } +} + +String::String( const std::string& utf8String ) { + mString.reserve( utf8String.length() + 1 ); + + Utf8::ToUtf32( utf8String.begin(), utf8String.end(), std::back_inserter( mString ) ); +} + +String::String(const char* ansiString, const std::locale& locale) +{ + if (ansiString) + { + std::size_t length = strlen(ansiString); + if (length > 0) + { + mString.reserve(length + 1); + Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(mString), locale); + } + } +} + +String::String(const std::string& ansiString, const std::locale& locale) +{ + mString.reserve(ansiString.length() + 1); + Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(mString), locale); +} + +#ifndef EFSW_NO_WIDECHAR +String::String(const wchar_t* wideString) +{ + if (wideString) + { + std::size_t length = std::wcslen(wideString); + if (length > 0) + { + mString.reserve(length + 1); + Utf32::FromWide(wideString, wideString + length, std::back_inserter(mString)); + } + } +} + +String::String(const std::wstring& wideString) +{ + mString.reserve(wideString.length() + 1); + Utf32::FromWide(wideString.begin(), wideString.end(), std::back_inserter(mString)); +} +#endif + +String::String(const StringBaseType* utf32String) +{ + if (utf32String) + mString = utf32String; +} + +String::String(const StringType& utf32String) : +mString(utf32String) +{ +} + +String::String(const String& str) : +mString(str.mString) +{ +} + +String String::fromUtf8( const std::string& utf8String ) +{ + String::StringType utf32; + + utf32.reserve( utf8String.length() + 1 ); + + Utf8::ToUtf32( utf8String.begin(), utf8String.end(), std::back_inserter( utf32 ) ); + + return String( utf32 ); +} + +String::operator std::string() const +{ + return toAnsiString(); +} + +std::string String::toAnsiString(const std::locale& locale) const +{ + // Prepare the output string + std::string output; + output.reserve(mString.length() + 1); + + // Convert + Utf32::ToAnsi(mString.begin(), mString.end(), std::back_inserter(output), 0, locale); + + return output; +} + +#ifndef EFSW_NO_WIDECHAR +std::wstring String::toWideString() const +{ + // Prepare the output string + std::wstring output; + output.reserve(mString.length() + 1); + + // Convert + Utf32::ToWide(mString.begin(), mString.end(), std::back_inserter(output), 0); + + return output; +} +#endif + +std::string String::toUtf8() const { + // Prepare the output string + std::string output; + output.reserve(mString.length() + 1); + + // Convert + Utf32::toUtf8(mString.begin(), mString.end(), std::back_inserter(output) ); + + return output; +} + +String& String::operator =(const String& right) +{ + mString = right.mString; + return *this; +} + +String& String::operator =( const StringBaseType& right ) +{ + mString = right; + return *this; +} + +String& String::operator +=(const String& right) +{ + mString += right.mString; + return *this; +} + +String& String::operator +=( const StringBaseType& right ) +{ + mString += right; + return *this; +} + + +String::StringBaseType String::operator [](std::size_t index) const +{ + return mString[index]; +} + +String::StringBaseType& String::operator [](std::size_t index) +{ + return mString[index]; +} + +String::StringBaseType String::at( std::size_t index ) const +{ + return mString.at( index ); +} + +void String::push_back( StringBaseType c ) +{ + mString.push_back( c ); +} + +void String::swap ( String& str ) +{ + mString.swap( str.mString ); +} + +void String::clear() +{ + mString.clear(); +} + +std::size_t String::size() const +{ + return mString.size(); +} + +std::size_t String::length() const +{ + return mString.length(); +} + +bool String::empty() const +{ + return mString.empty(); +} + +void String::erase(std::size_t position, std::size_t count) +{ + mString.erase(position, count); +} + +String& String::insert(std::size_t position, const String& str) +{ + mString.insert(position, str.mString); + return *this; +} + +String& String::insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n ) +{ + mString.insert( pos1, str.mString, pos2, n ); + return *this; +} + +String& String::insert ( size_t pos1, const char* s, size_t n ) +{ + String tmp( s ); + + mString.insert( pos1, tmp.data(), n ); + + return *this; +} + +String& String::insert ( size_t pos1, size_t n, char c ) +{ + mString.insert( pos1, n, c ); + return *this; +} + +String& String::insert ( size_t pos1, const char* s ) +{ + String tmp( s ); + + mString.insert( pos1, tmp.data() ); + + return *this; +} + +String::Iterator String::insert ( Iterator p, char c ) +{ + return mString.insert( p, c ); +} + +void String::insert ( Iterator p, size_t n, char c ) +{ + mString.insert( p, n, c ); +} + +const String::StringBaseType* String::c_str() const +{ + return mString.c_str(); +} + +const String::StringBaseType* String::data() const +{ + return mString.data(); +} + +String::Iterator String::begin() +{ + return mString.begin(); +} + +String::ConstIterator String::begin() const +{ + return mString.begin(); +} + +String::Iterator String::end() +{ + return mString.end(); +} + +String::ConstIterator String::end() const +{ + return mString.end(); +} + +String::ReverseIterator String::rbegin() +{ + return mString.rbegin(); +} + +String::ConstReverseIterator String::rbegin() const +{ + return mString.rbegin(); +} + +String::ReverseIterator String::rend() +{ + return mString.rend(); +} + +String::ConstReverseIterator String::rend() const +{ + return mString.rend(); +} + +void String::resize( std::size_t n, StringBaseType c ) +{ + mString.resize( n, c ); +} + +void String::resize( std::size_t n ) +{ + mString.resize( n ); +} + +std::size_t String::max_size() const +{ + return mString.max_size(); +} + +void String::reserve( size_t res_arg ) +{ + mString.reserve( res_arg ); +} + +std::size_t String::capacity() const +{ + return mString.capacity(); +} + +String& String::assign ( const String& str ) +{ + mString.assign( str.mString ); + return *this; +} + +String& String::assign ( const String& str, size_t pos, size_t n ) +{ + mString.assign( str.mString, pos, n ); + return *this; +} + +String& String::assign ( const char* s, size_t n ) +{ + String tmp( s ); + + mString.assign( tmp.mString ); + + return *this; +} + +String& String::assign ( const char* s ) +{ + String tmp( s ); + + mString.assign( tmp.mString ); + + return *this; +} + +String& String::assign ( size_t n, char c ) +{ + mString.assign( n, c ); + + return *this; +} + +String& String::append ( const String& str ) +{ + mString.append( str.mString ); + + return *this; +} + +String& String::append ( const String& str, size_t pos, size_t n ) +{ + mString.append( str.mString, pos, n ); + + return *this; +} + +String& String::append ( const char* s, size_t n ) +{ + String tmp( s ); + + mString.append( tmp.mString ); + + return *this; +} + +String& String::append ( const char* s ) +{ + String tmp( s ); + + mString.append( tmp.mString ); + + return *this; +} + +String& String::append ( size_t n, char c ) +{ + mString.append( n, c ); + + return *this; +} + +String& String::append ( std::size_t n, StringBaseType c ) +{ + mString.append( n, c ); + + return *this; +} + +String& String::replace ( size_t pos1, size_t n1, const String& str ) +{ + mString.replace( pos1, n1, str.mString ); + + return *this; +} + +String& String::replace ( Iterator i1, Iterator i2, const String& str ) +{ + mString.replace( i1, i2, str.mString ); + + return *this; +} + +String& String::replace ( size_t pos1, size_t n1, const String& str, size_t pos2, size_t n2 ) +{ + mString.replace( pos1, n1, str.mString, pos2, n2 ); + + return *this; +} + +String& String::replace ( size_t pos1, size_t n1, const char* s, size_t n2 ) +{ + String tmp( s ); + + mString.replace( pos1, n1, tmp.data(), n2 ); + + return *this; +} + +String& String::replace ( Iterator i1, Iterator i2, const char* s, size_t n2 ) +{ + String tmp( s ); + + mString.replace( i1, i2, tmp.data(), n2 ); + + return *this; +} + +String& String::replace ( size_t pos1, size_t n1, const char* s ) +{ + String tmp( s ); + + mString.replace( pos1, n1, tmp.mString ); + + return *this; +} + +String& String::replace ( Iterator i1, Iterator i2, const char* s ) +{ + String tmp( s ); + + mString.replace( i1, i2, tmp.mString ); + + return *this; +} + +String& String::replace ( size_t pos1, size_t n1, size_t n2, char c ) +{ + mString.replace( pos1, n1, n2, (StringBaseType)c ); + + return *this; +} + +String& String::replace ( Iterator i1, Iterator i2, size_t n2, char c ) +{ + mString.replace( i1, i2, n2, (StringBaseType)c ); + + return *this; +} + +std::size_t String::find( const String& str, std::size_t start ) const +{ + return mString.find( str.mString, start ); +} + +std::size_t String::find ( const char* s, std::size_t pos, std::size_t n ) const +{ + return find( String( s ), pos ); +} + +std::size_t String::find ( const char* s, std::size_t pos ) const +{ + return find( String( s ), pos ); +} + +size_t String::find ( char c, std::size_t pos ) const +{ + return mString.find( (StringBaseType)c, pos ); +} + +std::size_t String::rfind ( const String& str, std::size_t pos ) const +{ + return mString.rfind( str.mString, pos ); +} + +std::size_t String::rfind ( const char* s, std::size_t pos, std::size_t n ) const +{ + return rfind( String( s ), pos ); +} + +std::size_t String::rfind ( const char* s, std::size_t pos ) const +{ + return rfind( String( s ), pos ); +} + +std::size_t String::rfind ( char c, std::size_t pos ) const +{ + return mString.rfind( c, pos ); +} + +std::size_t String::copy ( StringBaseType* s, std::size_t n, std::size_t pos ) const +{ + return mString.copy( s, n, pos ); +} + +String String::substr ( std::size_t pos, std::size_t n ) const +{ + return String( mString.substr( pos, n ) ); +} + +int String::compare ( const String& str ) const +{ + return mString.compare( str.mString ); +} + +int String::compare ( const char* s ) const +{ + return compare( String( s ) ); +} + +int String::compare ( std::size_t pos1, std::size_t n1, const String& str ) const +{ + return mString.compare( pos1, n1, str.mString ); +} + +int String::compare ( std::size_t pos1, std::size_t n1, const char* s) const +{ + return compare( pos1, n1, String( s ) ); +} + +int String::compare ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ) const +{ + return mString.compare( pos1, n1, str.mString, pos2, n2 ); +} + +int String::compare ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2) const +{ + return compare( pos1, n1, String( s ), 0, n2 ); +} + +std::size_t String::find_first_of ( const String& str, std::size_t pos ) const +{ + return mString.find_first_of( str.mString, pos ); +} + +std::size_t String::find_first_of ( const char* s, std::size_t pos, std::size_t n ) const +{ + return find_first_of( String( s ), pos ); +} + +std::size_t String::find_first_of ( const char* s, std::size_t pos ) const +{ + return find_first_of( String( s ), pos ); +} + +std::size_t String::find_first_of ( StringBaseType c, std::size_t pos ) const +{ + return mString.find_first_of( c, pos ); +} + +std::size_t String::find_last_of ( const String& str, std::size_t pos ) const +{ + return mString.find_last_of( str.mString, pos ); +} + +std::size_t String::find_last_of ( const char* s, std::size_t pos, std::size_t n ) const +{ + return find_last_of( String( s ), pos ); +} + +std::size_t String::find_last_of ( const char* s, std::size_t pos ) const +{ + return find_last_of( String( s ), pos ); +} + +std::size_t String::find_last_of ( StringBaseType c, std::size_t pos) const +{ + return mString.find_last_of( c, pos ); +} + +std::size_t String::find_first_not_of ( const String& str, std::size_t pos ) const +{ + return mString.find_first_not_of( str.mString, pos ); +} + +std::size_t String::find_first_not_of ( const char* s, std::size_t pos, std::size_t n ) const +{ + return find_first_not_of( String( s ), pos ); +} + +std::size_t String::find_first_not_of ( const char* s, std::size_t pos ) const +{ + return find_first_not_of( String( s ), pos ); +} + +std::size_t String::find_first_not_of ( StringBaseType c, std::size_t pos ) const +{ + return mString.find_first_not_of( c, pos ); +} + +std::size_t String::find_last_not_of ( const String& str, std::size_t pos ) const +{ + return mString.find_last_not_of( str.mString, pos ); +} + +std::size_t String::find_last_not_of ( const char* s, std::size_t pos, std::size_t n ) const +{ + return find_last_not_of( String( s ), pos ); +} + +std::size_t String::find_last_not_of ( const char* s, std::size_t pos ) const +{ + return find_last_not_of( String( s ), pos ); +} + +std::size_t String::find_last_not_of ( StringBaseType c, std::size_t pos ) const +{ + return mString.find_last_not_of( c, pos ); +} + +bool operator ==(const String& left, const String& right) +{ + return left.mString == right.mString; +} + +bool operator !=(const String& left, const String& right) +{ + return !(left == right); +} + +bool operator <(const String& left, const String& right) +{ + return left.mString < right.mString; +} + +bool operator >(const String& left, const String& right) +{ + return right < left; +} + +bool operator <=(const String& left, const String& right) +{ + return !(right < left); +} + +bool operator >=(const String& left, const String& right) +{ + return !(left < right); +} + +String operator +(const String& left, const String& right) +{ + String string = left; + string += right; + + return string; +} + +} diff --git a/dep/efsw/src/efsw/String.hpp b/dep/efsw/src/efsw/String.hpp new file mode 100644 index 00000000000..ce7e3b75f89 --- /dev/null +++ b/dep/efsw/src/efsw/String.hpp @@ -0,0 +1,629 @@ +/** NOTE: +* This code is based on the Utf implementation from SFML2. License zlib/png ( http://www.sfml-dev.org/license.php ) +* The class was modified to fit efsw own needs. This is not the original implementation from SFML2. +* Functions and methods are the same that in std::string to facilitate portability. +**/ + +#ifndef EFSW_STRING_HPP +#define EFSW_STRING_HPP + +#include <efsw/base.hpp> +#include <locale> +#include <string> +#include <cstring> +#include <cstdlib> +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> + +namespace efsw { + +/** @brief Utility string class that automatically handles conversions between types and encodings **/ +class String +{ + public : + typedef Uint32 StringBaseType; + typedef std::basic_string<StringBaseType> StringType; + typedef StringType::iterator Iterator; //! Iterator type + typedef StringType::const_iterator ConstIterator; //! Constant iterator type + typedef StringType::reverse_iterator ReverseIterator; //! Reverse Iterator type + typedef StringType::const_reverse_iterator ConstReverseIterator; //! Constant iterator type + + static const std::size_t InvalidPos; ///< Represents an invalid position in the string + + template <class T> + static std::string toStr(const T& i) { + std::ostringstream ss; + ss << i; + return ss.str(); + } + + /** Converts from a string to type */ + template <class T> + static bool fromString(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&) = std::dec ) { + std::istringstream iss(s); + return !(iss >> f >> t).fail(); + } + + /** Converts from a String to type */ + template <class T> + static bool fromString(T& t, const String& s, std::ios_base& (*f)(std::ios_base&) = std::dec ) { + std::istringstream iss( s.toUtf8() ); + return !(iss >> f >> t).fail(); + } + + /** Split a string and hold it on a vector */ + static std::vector < std::string > split( const std::string& str, const char& splitchar, const bool& pushEmptyString = false ); + + /** Split a string and hold it on a vector */ + static std::vector < String > split( const String& str, const Uint32& splitchar, const bool& pushEmptyString = false ); + + /** Determine if a string starts with the string passed + ** @param start The substring expected to start + ** @param str The string to compare + ** @return -1 if the substring is no in str, otherwise the size of the substring + */ + static int strStartsWith( const std::string& start, const std::string& str ); + + static int strStartsWith( const String& start, const String& str ); + + /** @brief Construct from an UTF-8 string to UTF-32 according + ** @param uf8String UTF-8 string to convert + **/ + static String fromUtf8( const std::string& utf8String ); + + /** @brief Default constructor + ** This constructor creates an empty string. + **/ + String(); + + /** @brief Construct from a single ANSI character and a locale + ** The source character is converted to UTF-32 according + ** to the given locale. If you want to use the current global + ** locale, rather use the other constructor. + ** @param ansiChar ANSI character to convert + ** @param locale Locale to use for conversion + **/ + String( char ansiChar, const std::locale& locale = std::locale() ); + +#ifndef EFSW_NO_WIDECHAR + /** @brief Construct from single wide character + ** @param wideChar Wide character to convert + **/ + String( wchar_t wideChar ); +#endif + + /** @brief Construct from single UTF-32 character + ** @param utf32Char UTF-32 character to convert + **/ + String( StringBaseType utf32Char ); + + /** @brief Construct from an from a null-terminated C-style UTF-8 string to UTF-32 + ** @param uf8String UTF-8 string to convert + **/ + String( const char* uf8String ); + + /** @brief Construct from an UTF-8 string to UTF-32 according + ** @param uf8String UTF-8 string to convert + **/ + String( const std::string& utf8String ); + + /** @brief Construct from a null-terminated C-style ANSI string and a locale + ** The source string is converted to UTF-32 according + ** to the given locale. If you want to use the current global + ** locale, rather use the other constructor. + ** @param ansiString ANSI string to convert + ** @param locale Locale to use for conversion + **/ + String( const char* ansiString, const std::locale& locale ); + + /** @brief Construct from an ANSI string and a locale + ** The source string is converted to UTF-32 according + ** to the given locale. If you want to use the current global + ** locale, rather use the other constructor. + ** @param ansiString ANSI string to convert + ** @param locale Locale to use for conversion + **/ + String( const std::string& ansiString, const std::locale& locale ); + +#ifndef EFSW_NO_WIDECHAR + /** @brief Construct from null-terminated C-style wide string + ** @param wideString Wide string to convert + **/ + String( const wchar_t* wideString ); + + /** @brief Construct from a wide string + ** @param wideString Wide string to convert + **/ + String( const std::wstring& wideString ); +#endif + + /** @brief Construct from a null-terminated C-style UTF-32 string + ** @param utf32String UTF-32 string to assign + **/ + String( const StringBaseType* utf32String ); + + /** @brief Construct from an UTF-32 string + ** @param utf32String UTF-32 string to assign + **/ + String( const StringType& utf32String ); + + + /** @brief Copy constructor + ** @param str Instance to copy + **/ + String( const String& str ); + + /** @brief Implicit cast operator to std::string (ANSI string) + ** The current global locale is used for conversion. If you + ** want to explicitely specify a locale, see toAnsiString. + ** Characters that do not fit in the target encoding are + ** discarded from the returned string. + ** This operator is defined for convenience, and is equivalent + ** to calling toAnsiString(). + ** @return Converted ANSI string + ** @see toAnsiString, operator String + **/ + operator std::string() const; + + /** @brief Convert the unicode string to an ANSI string + ** The UTF-32 string is converted to an ANSI string in + ** the encoding defined by \a locale. If you want to use + ** the current global locale, see the other overload + ** of toAnsiString. + ** Characters that do not fit in the target encoding are + ** discarded from the returned string. + ** @param locale Locale to use for conversion + ** @return Converted ANSI string + ** @see toWideString, operator std::string + **/ + std::string toAnsiString( const std::locale& locale = std::locale() ) const; + +#ifndef EFSW_NO_WIDECHAR + /** @brief Convert the unicode string to a wide string + ** Characters that do not fit in the target encoding are + ** discarded from the returned string. + ** @return Converted wide string + ** @see toAnsiString, operator String + **/ + std::wstring toWideString() const; +#endif + + std::string toUtf8() const; + + /** @brief Overload of assignment operator + ** @param right Instance to assign + ** @return Reference to self + **/ + String& operator =(const String& right); + + String& operator =( const StringBaseType& right ); + + /** @brief Overload of += operator to append an UTF-32 string + ** @param right String to append + ** @return Reference to self + **/ + String& operator +=(const String& right); + + String& operator +=( const StringBaseType& right ); + + /** @brief Overload of [] operator to access a character by its position + ** This function provides read-only access to characters. + ** Note: this function doesn't throw if \a index is out of range. + ** @param index Index of the character to get + ** @return Character at position \a index + **/ + StringBaseType operator [](std::size_t index) const; + + /** @brief Overload of [] operator to access a character by its position + ** This function provides read and write access to characters. + ** Note: this function doesn't throw if \a index is out of range. + ** @param index Index of the character to get + ** @return Reference to the character at position \a index + **/ + + StringBaseType& operator [](std::size_t index); + + /** @brief Get character in string + ** Performs a range check, throwing an exception of type out_of_range in case that pos is not an actual position in the string. + ** @return The character at position pos in the string. + */ + StringBaseType at( std::size_t index ) const; + + /** @brief clear the string + ** This function removes all the characters from the string. + ** @see empty, erase + **/ + void clear(); + + /** @brief Get the size of the string + ** @return Number of characters in the string + ** @see empty + **/ + std::size_t size() const; + + /** @see size() */ + std::size_t length() const; + + /** @brief Check whether the string is empty or not + ** @return True if the string is empty (i.e. contains no character) + ** @see clear, size + **/ + bool empty() const; + + /** @brief Erase one or more characters from the string + ** This function removes a sequence of \a count characters + ** starting from \a position. + ** @param position Position of the first character to erase + ** @param count Number of characters to erase + **/ + void erase(std::size_t position, std::size_t count = 1); + + + /** @brief Insert one or more characters into the string + ** This function inserts the characters of \a str + ** into the string, starting from \a position. + ** @param position Position of insertion + ** @param str Characters to insert + **/ + String& insert(std::size_t position, const String& str); + + String& insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n ); + + String& insert ( std::size_t pos1, const char* s, std::size_t n ); + + String& insert ( std::size_t pos1, const char* s ); + + String& insert ( std::size_t pos1, size_t n, char c ); + + Iterator insert ( Iterator p, char c ); + + void insert ( Iterator p, std::size_t n, char c ); + + template<class InputIterator> + void insert ( Iterator p, InputIterator first, InputIterator last ) + { + mString.insert( p, first, last ); + } + + /** @brief Find a sequence of one or more characters in the string + ** This function searches for the characters of \a str + ** into the string, starting from \a start. + ** @param str Characters to find + ** @param start Where to begin searching + ** @return Position of \a str in the string, or String::InvalidPos if not found + **/ + std::size_t find( const String& str, std::size_t start = 0 ) const; + + std::size_t find ( const char* s, std::size_t pos, std::size_t n ) const; + + std::size_t find ( const char* s, std::size_t pos = 0 ) const; + + std::size_t find ( char c, std::size_t pos = 0 ) const; + + /** @brief Get a pointer to the C-style array of characters + ** This functions provides a read-only access to a + ** null-terminated C-style representation of the string. + ** The returned pointer is temporary and is meant only for + ** immediate use, thus it is not recommended to store it. + ** @return Read-only pointer to the array of characters + **/ + const StringBaseType* c_str() const; + + /** @brief Get string data + ** Notice that no terminating null character is appended (see member c_str for such a functionality). + ** The returned array points to an internal location which should not be modified directly in the program. + ** Its contents are guaranteed to remain unchanged only until the next call to a non-constant member function of the string object. + ** @return Pointer to an internal array containing the same content as the string. + **/ + const StringBaseType* data() const; + + /** @brief Return an iterator to the beginning of the string + ** @return Read-write iterator to the beginning of the string characters + ** @see end + **/ + Iterator begin(); + + /** @brief Return an iterator to the beginning of the string + ** @return Read-only iterator to the beginning of the string characters + ** @see end + **/ + ConstIterator begin() const; + + /** @brief Return an iterator to the beginning of the string + ** The end iterator refers to 1 position past the last character; + ** thus it represents an invalid character and should never be + ** accessed. + ** @return Read-write iterator to the end of the string characters + ** @see begin + **/ + Iterator end(); + + /** @brief Return an iterator to the beginning of the string + ** The end iterator refers to 1 position past the last character; + ** thus it represents an invalid character and should never be + ** accessed. + ** @return Read-only iterator to the end of the string characters + ** @see begin + **/ + ConstIterator end() const; + + /** @brief Return an reverse iterator to the beginning of the string + ** @return Read-write reverse iterator to the beginning of the string characters + ** @see end + **/ + ReverseIterator rbegin(); + + /** @brief Return an reverse iterator to the beginning of the string + ** @return Read-only reverse iterator to the beginning of the string characters + ** @see end + **/ + ConstReverseIterator rbegin() const; + + /** @brief Return an reverse iterator to the beginning of the string + ** The end reverse iterator refers to 1 position past the last character; + ** thus it represents an invalid character and should never be + ** accessed. + ** @return Read-write reverse iterator to the end of the string characters + ** @see begin + **/ + ReverseIterator rend(); + + + /** @brief Return an reverse iterator to the beginning of the string + ** The end reverse iterator refers to 1 position past the last character; + ** thus it represents an invalid character and should never be + ** accessed. + ** @return Read-only reverse iterator to the end of the string characters + ** @see begin + **/ + ConstReverseIterator rend() const; + + /** @brief Resize String */ + void resize ( std::size_t n, StringBaseType c ); + + /** @brief Resize String */ + void resize ( std::size_t n ); + + /** @return Maximum size of string */ + std::size_t max_size() const; + + /** @brief Request a change in capacity */ + void reserve ( size_t res_arg=0 ); + + /** @return Size of allocated storage */ + std::size_t capacity() const; + + /** @brief Append character to string */ + void push_back( StringBaseType c ); + + /** @brief Swap contents with another string */ + void swap ( String& str ); + + String& assign ( const String& str ); + + String& assign ( const String& str, std::size_t pos, std::size_t n ); + + String& assign ( const char* s, std::size_t n ); + + String& assign ( const char* s ); + + String& assign ( std::size_t n, char c ); + + template <class InputIterator> + String& assign ( InputIterator first, InputIterator last ) + { + mString.assign( first, last ); + return *this; + } + + String& append ( const String& str ); + + String& append ( const String& str, std::size_t pos, std::size_t n ); + + String& append ( const char* s, std::size_t n ); + + String& append ( const char* s ); + + String& append ( std::size_t n, char c ); + + String& append ( std::size_t n, StringBaseType c ); + + template <class InputIterator> + String& append ( InputIterator first, InputIterator last ) + { + mString.append( first, last ); + return *this; + } + + String& replace ( std::size_t pos1, std::size_t n1, const String& str ); + + String& replace ( Iterator i1, Iterator i2, const String& str ); + + String& replace ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ); + + String& replace ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2 ); + + String& replace ( Iterator i1, Iterator i2, const char* s, std::size_t n2 ); + + String& replace ( std::size_t pos1, std::size_t n1, const char* s ); + + String& replace ( Iterator i1, Iterator i2, const char* s ); + + String& replace ( std::size_t pos1, std::size_t n1, std::size_t n2, char c ); + + String& replace ( Iterator i1, Iterator i2, std::size_t n2, char c ); + + template<class InputIterator> + String& replace ( Iterator i1, Iterator i2, InputIterator j1, InputIterator j2 ) + { + mString.replace( i1, i2, j1, j2 ); + return *this; + } + + std::size_t rfind ( const String& str, std::size_t pos = StringType::npos ) const; + + std::size_t rfind ( const char* s, std::size_t pos, std::size_t n ) const; + + std::size_t rfind ( const char* s, std::size_t pos = StringType::npos ) const; + + std::size_t rfind ( char c, std::size_t pos = StringType::npos ) const; + + String substr ( std::size_t pos = 0, std::size_t n = StringType::npos ) const; + + std::size_t copy ( StringBaseType* s, std::size_t n, std::size_t pos = 0 ) const; + + int compare ( const String& str ) const; + + int compare ( const char* s ) const; + + int compare ( std::size_t pos1, std::size_t n1, const String& str ) const; + + int compare ( std::size_t pos1, std::size_t n1, const char* s) const; + + int compare ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ) const; + + int compare ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2) const; + + std::size_t find_first_of ( const String& str, std::size_t pos = 0 ) const; + + std::size_t find_first_of ( const char* s, std::size_t pos, std::size_t n ) const; + + std::size_t find_first_of ( const char* s, std::size_t pos = 0 ) const; + + std::size_t find_first_of ( StringBaseType c, std::size_t pos = 0 ) const; + + std::size_t find_last_of ( const String& str, std::size_t pos = StringType::npos ) const; + + std::size_t find_last_of ( const char* s, std::size_t pos, std::size_t n ) const; + + std::size_t find_last_of ( const char* s, std::size_t pos = StringType::npos ) const; + + std::size_t find_last_of ( StringBaseType c, std::size_t pos = StringType::npos ) const; + + std::size_t find_first_not_of ( const String& str, std::size_t pos = 0 ) const; + + std::size_t find_first_not_of ( const char* s, std::size_t pos, std::size_t n ) const; + + std::size_t find_first_not_of ( const char* s, std::size_t pos = 0 ) const; + + std::size_t find_first_not_of ( StringBaseType c, std::size_t pos = 0 ) const; + + std::size_t find_last_not_of ( const String& str, std::size_t pos = StringType::npos ) const; + + std::size_t find_last_not_of ( const char* s, std::size_t pos, std::size_t n ) const; + + std::size_t find_last_not_of ( const char* s, std::size_t pos = StringType::npos ) const; + + std::size_t find_last_not_of ( StringBaseType c, std::size_t pos = StringType::npos ) const; +private : + friend bool operator ==(const String& left, const String& right); + friend bool operator <(const String& left, const String& right); + + StringType mString; ///< Internal string of UTF-32 characters +}; + +/** @relates String +** @brief Overload of == operator to compare two UTF-32 strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return True if both strings are equal +**/ + bool operator ==(const String& left, const String& right); + +/** @relates String +** @brief Overload of != operator to compare two UTF-32 strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return True if both strings are different +**/ + bool operator !=(const String& left, const String& right); + +/** @relates String +** @brief Overload of < operator to compare two UTF-32 strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return True if \a left is alphabetically lesser than \a right +**/ + bool operator <(const String& left, const String& right); + +/** @relates String +** @brief Overload of > operator to compare two UTF-32 strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return True if \a left is alphabetically greater than \a right +**/ + bool operator >(const String& left, const String& right); + +/** @relates String +** @brief Overload of <= operator to compare two UTF-32 strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return True if \a left is alphabetically lesser or equal than \a right +**/ + bool operator <=(const String& left, const String& right); + +/** @relates String +** @brief Overload of >= operator to compare two UTF-32 strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return True if \a left is alphabetically greater or equal than \a right +**/ + bool operator >=(const String& left, const String& right); + +/** @relates String +** @brief Overload of binary + operator to concatenate two strings +** @param left Left operand (a string) +** @param right Right operand (a string) +** @return Concatenated string +**/ + String operator +( const String& left, const String& right ); + +} + +#endif + +/** @class efsw::String +** @ingroup system +** efsw::String is a utility string class defined mainly for +** convenience. It is a Unicode string (implemented using +** UTF-32), thus it can store any character in the world +** (european, chinese, arabic, hebrew, etc.). +** It automatically handles conversions from/to ANSI and +** wide strings, so that you can work with standard string +** classes and still be compatible with functions taking a +** efsw::String. +** @code +** efsw::String s; +** std::string s1 = s; // automatically converted to ANSI string +** String s2 = s; // automatically converted to wide string +** s = "hello"; // automatically converted from ANSI string +** s = L"hello"; // automatically converted from wide string +** s += 'a'; // automatically converted from ANSI string +** s += L'a'; // automatically converted from wide string +** @endcode +** Conversions involving ANSI strings use the default user locale. However +** it is possible to use a custom locale if necessary: +** @code +** std::locale locale; +** efsw::String s; +** ... +** std::string s1 = s.toAnsiString(locale); +** s = efsw::String("hello", locale); +** @endcode +** +** efsw::String defines the most important functions of the +** standard std::string class: removing, random access, iterating, +** appending, comparing, etc. However it is a simple class +** provided for convenience, and you may have to consider using +** a more optimized class if your program requires complex string +** handling. The automatic conversion functions will then take +** care of converting your string to efsw::String whenever EE +** requires it. +** +** Please note that EE also defines a low-level, generic +** interface for Unicode handling, see the efsw::Utf classes. +** +** All credits to Laurent Gomila, i just modified and expanded a little bit the implementation. +**/ diff --git a/dep/efsw/src/efsw/System.cpp b/dep/efsw/src/efsw/System.cpp new file mode 100644 index 00000000000..f8767cbc58f --- /dev/null +++ b/dep/efsw/src/efsw/System.cpp @@ -0,0 +1,26 @@ +#include <efsw/System.hpp> +#include <efsw/platform/platformimpl.hpp> + +namespace efsw { + +void System::sleep( const unsigned long& ms ) +{ + Platform::System::sleep( ms ); +} + +std::string System::getProcessPath() +{ + return Platform::System::getProcessPath(); +} + +void System::maxFD() +{ + Platform::System::maxFD(); +} + +Uint64 System::getMaxFD() +{ + return Platform::System::getMaxFD(); +} + +} diff --git a/dep/efsw/src/efsw/System.hpp b/dep/efsw/src/efsw/System.hpp new file mode 100644 index 00000000000..1d6f4a70f91 --- /dev/null +++ b/dep/efsw/src/efsw/System.hpp @@ -0,0 +1,26 @@ +#ifndef EFSW_SYSTEM_HPP +#define EFSW_SYSTEM_HPP + +#include <efsw/base.hpp> + +namespace efsw { + +class System +{ + public: + /// Sleep for x milliseconds + static void sleep( const unsigned long& ms ); + + /// @return The process binary path + static std::string getProcessPath(); + + /// Maximize the number of file descriptors allowed per process in the current OS + static void maxFD(); + + /// @return The number of supported file descriptors for the process + static Uint64 getMaxFD(); +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/Thread.cpp b/dep/efsw/src/efsw/Thread.cpp new file mode 100644 index 00000000000..fff41517dc1 --- /dev/null +++ b/dep/efsw/src/efsw/Thread.cpp @@ -0,0 +1,51 @@ +#include <efsw/Thread.hpp> +#include <efsw/platform/platformimpl.hpp> + +namespace efsw { + +Thread::Thread() : + mThreadImpl(NULL), + mEntryPoint(NULL) +{ +} + +Thread::~Thread() +{ + wait(); + + efSAFE_DELETE( mEntryPoint ); +} + +void Thread::launch() +{ + wait(); + + mThreadImpl = new Platform::ThreadImpl( this ); +} + +void Thread::wait() +{ + if ( mThreadImpl ) + { + mThreadImpl->wait(); + + efSAFE_DELETE( mThreadImpl ); + } +} + +void Thread::terminate() +{ + if ( mThreadImpl ) + { + mThreadImpl->terminate(); + + efSAFE_DELETE( mThreadImpl ); + } +} + +void Thread::run() +{ + mEntryPoint->run(); +} + +} diff --git a/dep/efsw/src/efsw/Thread.hpp b/dep/efsw/src/efsw/Thread.hpp new file mode 100644 index 00000000000..c7da9e8b33c --- /dev/null +++ b/dep/efsw/src/efsw/Thread.hpp @@ -0,0 +1,111 @@ +#ifndef EFSW_THREAD_HPP +#define EFSW_THREAD_HPP + +#include <efsw/base.hpp> + +namespace efsw { + +namespace Platform { class ThreadImpl; } +namespace Private { struct ThreadFunc; } + +/** @brief Thread manager class */ +class Thread { + public: + typedef void (*FuncType)(void*); + + template <typename F> + Thread( F function ); + + template <typename F, typename A> + Thread( F function, A argument ); + + template <typename C> + Thread( void(C::*function)(), C* object ); + + virtual ~Thread(); + + /** Launch the thread */ + virtual void launch(); + + /** Wait the thread until end */ + void wait(); + + /** Terminate the thread */ + void terminate(); + protected: + Thread(); + private: + friend class Platform::ThreadImpl; + + /** The virtual function to run in the thread */ + virtual void run(); + + Platform::ThreadImpl * mThreadImpl; ///< OS-specific implementation of the thread + Private::ThreadFunc * mEntryPoint; ///< Abstraction of the function to run +}; + +//! NOTE: Taken from SFML2 threads +namespace Private { + +// Base class for abstract thread functions +struct ThreadFunc +{ + virtual ~ThreadFunc() {} + virtual void run() = 0; +}; + +// Specialization using a functor (including free functions) with no argument +template <typename T> +struct ThreadFunctor : ThreadFunc +{ + ThreadFunctor(T functor) : m_functor(functor) {} + virtual void run() {m_functor();} + T m_functor; +}; + +// Specialization using a functor (including free functions) with one argument +template <typename F, typename A> +struct ThreadFunctorWithArg : ThreadFunc +{ + ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {} + virtual void run() {m_function(m_arg);} + F m_function; + A m_arg; +}; + +// Specialization using a member function +template <typename C> +struct ThreadMemberFunc : ThreadFunc +{ + ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {} + virtual void run() {(m_object->*m_function)();} + void(C::*m_function)(); + C* m_object; +}; + +} + +template <typename F> +Thread::Thread(F functor) : + mThreadImpl (NULL), + mEntryPoint( new Private::ThreadFunctor<F>(functor) ) +{ +} + +template <typename F, typename A> +Thread::Thread(F function, A argument) : + mThreadImpl(NULL), + mEntryPoint( new Private::ThreadFunctorWithArg<F efCOMMA A>(function, argument) ) +{ +} + +template <typename C> +Thread::Thread(void(C::*function)(), C* object) : + mThreadImpl(NULL), + mEntryPoint( new Private::ThreadMemberFunc<C>(function, object) ) +{ +} + +} + +#endif diff --git a/dep/efsw/src/efsw/Utf.hpp b/dep/efsw/src/efsw/Utf.hpp new file mode 100644 index 00000000000..925a7cc149b --- /dev/null +++ b/dep/efsw/src/efsw/Utf.hpp @@ -0,0 +1,748 @@ +/** NOTE: +* This code is based on the Utf implementation from SFML2. License zlib/png ( http://www.sfml-dev.org/license.php ) +* The class was modified to fit efsw own needs. This is not the original implementation from SFML2. +* */ + +#ifndef EFSW_UTF_HPP +#define EFSW_UTF_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <locale> +#include <string> +#include <cstdlib> +#include <efsw/base.hpp> + +namespace efsw { + +template <unsigned int N> +class Utf; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-8 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<8> { +public : + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-8 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-8 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-8 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-8. + /// + /// \param input Codepoint to encode as UTF-8 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out Encode(Uint32 input, Out output, Uint8 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-8 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-8 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static std::size_t Count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-8 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + +#ifndef EFSW_NO_WIDECHAR + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0); +#endif + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-8 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the efsw::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToUtf32(In begin, In end, Out output); +}; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-16 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<16> +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-16 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-16 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-16 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-16. + /// + /// \param input Codepoint to encode as UTF-16 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out Encode(Uint32 input, Out output, Uint16 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-16 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-16 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static std::size_t Count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-16 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + +#ifndef EFSW_NO_WIDECHAR + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0); +#endif + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-16 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the efsw::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToUtf32(In begin, In end, Out output); +}; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-32 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<32> +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-32 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// For UTF-32, the character value is the same as the codepoint. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-32 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-32. + /// For UTF-32, the codepoint is the same as the character value. + /// + /// \param input Codepoint to encode as UTF-32 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out Encode(Uint32 input, Out output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-32 character + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-32 sequence + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static std::size_t Count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-32 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + +#ifndef EFSW_NO_WIDECHAR + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0); +#endif + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-32 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the efsw::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToUtf32(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single ANSI character to UTF-32 + /// + /// This function does not exist in other specializations + /// of efsw::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param input Input ANSI character + /// \param locale Locale to use for conversion + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template <typename In> + static Uint32 DecodeAnsi(In input, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single wide character to UTF-32 + /// + /// This function does not exist in other specializations + /// of efsw::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param input Input wide character + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template <typename In> + static Uint32 DecodeWide(In input); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to ANSI + /// + /// This function does not exist in other specializations + /// of efsw::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out EncodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale()); + +#ifndef EFSW_NO_WIDECHAR + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to wide + /// + /// This function does not exist in other specializations + /// of efsw::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out EncodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0); +#endif +}; + +#include "Utf.inl" + +// Make typedefs to get rid of the template syntax +typedef Utf<8> Utf8; +typedef Utf<16> Utf16; +typedef Utf<32> Utf32; + +} +#endif + +//////////////////////////////////////////////////////////// +/// \class efsw::Utf +/// \ingroup system +/// +/// Utility class providing generic functions for UTF conversions. +/// +/// efsw::Utf is a low-level, generic interface for counting, iterating, +/// encoding and decoding Unicode characters and strings. It is able +/// to handle ANSI, wide, UTF-8, UTF-16 and UTF-32 encodings. +/// +/// efsw::Utf<X> functions are all static, these classes are not meant to +/// be instanciated. All the functions are template, so that you +/// can use any character / string type for a given encoding. +/// +/// It has 3 specializations: +/// \li efsw::Utf<8> (typedef'd to efsw::Utf8) +/// \li efsw::Utf<16> (typedef'd to efsw::Utf16) +/// \li efsw::Utf<32> (typedef'd to efsw::Utf32) +/// +//////////////////////////////////////////////////////////// diff --git a/dep/efsw/src/efsw/Utf.inl b/dep/efsw/src/efsw/Utf.inl new file mode 100644 index 00000000000..db8fd5d61ee --- /dev/null +++ b/dep/efsw/src/efsw/Utf.inl @@ -0,0 +1,671 @@ +// References : +// http://www.unicode.org/ +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h +// http://people.w3.org/rishida/scripts/uniview/conversion +//////////////////////////////////////////////////////////// + +template <typename In> +In Utf<8>::Decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + // Some useful precomputed data + static const int trailing[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 + }; + static const Uint32 offsets[6] = + { + 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080 + }; + + // Decode the character + int trailingBytes = trailing[static_cast<Uint8>(*begin)]; + if (begin + trailingBytes < end) + { + output = 0; + switch (trailingBytes) + { + case 5 : output += static_cast<Uint8>(*begin++); output <<= 6; + case 4 : output += static_cast<Uint8>(*begin++); output <<= 6; + case 3 : output += static_cast<Uint8>(*begin++); output <<= 6; + case 2 : output += static_cast<Uint8>(*begin++); output <<= 6; + case 1 : output += static_cast<Uint8>(*begin++); output <<= 6; + case 0 : output += static_cast<Uint8>(*begin++); + } + output -= offsets[trailingBytes]; + } + else + { + // Incomplete character + begin = end; + output = replacement; + } + + return begin; +} + +template <typename Out> +Out Utf<8>::Encode(Uint32 input, Out output, Uint8 replacement) +{ + // Some useful precomputed data + static const Uint8 firstBytes[7] = + { + 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC + }; + + // Encode the character + if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF))) + { + // Invalid character + if (replacement) + *output++ = replacement; + } + else + { + // Valid character + + // Get the number of bytes to write + int bytesToWrite = 1; + if (input < 0x80) bytesToWrite = 1; + else if (input < 0x800) bytesToWrite = 2; + else if (input < 0x10000) bytesToWrite = 3; + else if (input <= 0x0010FFFF) bytesToWrite = 4; + + // Extract the bytes to write + Uint8 bytes[4]; + switch (bytesToWrite) + { + case 4 : bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; + case 3 : bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; + case 2 : bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; + case 1 : bytes[0] = static_cast<Uint8> (input | firstBytes[bytesToWrite]); + } + + // Add them to the output + const Uint8* currentByte = bytes; + switch (bytesToWrite) + { + case 4 : *output++ = *currentByte++; + case 3 : *output++ = *currentByte++; + case 2 : *output++ = *currentByte++; + case 1 : *output++ = *currentByte++; + } + } + + return output; +} + +template <typename In> +In Utf<8>::Next(In begin, In end) +{ + Uint32 codepoint; + return Decode(begin, end, codepoint); +} + +template <typename In> +std::size_t Utf<8>::Count(In begin, In end) +{ + std::size_t length = 0; + while (begin < end) + { + begin = Next(begin, end); + ++length; + } + + return length; +} + +template <typename In, typename Out> +Out Utf<8>::FromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale); + output = Encode(codepoint, output); + } + + return output; +} + +template <typename In, typename Out> +Out Utf<8>::FromWide(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::DecodeWide(*begin++); + output = Encode(codepoint, output); + } + + return output; +} + +template <typename In, typename Out> +Out Utf<8>::FromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + output = Encode(*begin++, output); + + return output; +} + +template <typename In, typename Out> +Out Utf<8>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale); + } + + return output; +} + +#ifndef EFSW_NO_WIDECHAR +template <typename In, typename Out> +Out Utf<8>::ToWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + output = Utf<32>::EncodeWide(codepoint, output, replacement); + } + + return output; +} +#endif + +template <typename In, typename Out> +Out Utf<8>::ToLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + *output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement; + } + + return output; +} + +template <typename In, typename Out> +Out Utf<8>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + *output++ = *begin++; + + return output; +} + +template <typename In, typename Out> +Out Utf<8>::ToUtf16(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + output = Utf<16>::Encode(codepoint, output); + } + + return output; +} + +template <typename In, typename Out> +Out Utf<8>::ToUtf32(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + *output++ = codepoint; + } + + return output; +} + +template <typename In> +In Utf<16>::Decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + Uint16 first = *begin++; + + // If it's a surrogate pair, first convert to a single UTF-32 character + if ((first >= 0xD800) && (first <= 0xDBFF)) + { + if (begin < end) + { + Uint32 second = *begin++; + if ((second >= 0xDC00) && (second <= 0xDFFF)) + { + // The second element is valid: convert the two elements to a UTF-32 character + output = static_cast<Uint32>(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000); + } + else + { + // Invalid character + output = replacement; + } + } + else + { + // Invalid character + begin = end; + output = replacement; + } + } + else + { + // We can make a direct copy + output = first; + } + + return begin; +} + +template <typename Out> +Out Utf<16>::Encode(Uint32 input, Out output, Uint16 replacement) +{ + if (input < 0xFFFF) + { + // The character can be copied directly, we just need to check if it's in the valid range + if ((input >= 0xD800) && (input <= 0xDFFF)) + { + // Invalid character (this range is reserved) + if (replacement) + *output++ = replacement; + } + else + { + // Valid character directly convertible to a single UTF-16 character + *output++ = static_cast<Uint16>(input); + } + } + else if (input > 0x0010FFFF) + { + // Invalid character (greater than the maximum unicode value) + if (replacement) + *output++ = replacement; + } + else + { + // The input character will be converted to two UTF-16 elements + input -= 0x0010000; + *output++ = static_cast<Uint16>((input >> 10) + 0xD800); + *output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00); + } + + return output; +} + +template <typename In> +In Utf<16>::Next(In begin, In end) +{ + Uint32 codepoint; + return Decode(begin, end, codepoint); +} + +template <typename In> +std::size_t Utf<16>::Count(In begin, In end) +{ + std::size_t length = 0; + while (begin < end) + { + begin = Next(begin, end); + ++length; + } + + return length; +} + +template <typename In, typename Out> +Out Utf<16>::FromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale); + output = Encode(codepoint, output); + } + + return output; +} + +template <typename In, typename Out> +Out Utf<16>::FromWide(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::DecodeWide(*begin++); + output = Encode(codepoint, output); + } + + return output; +} + +template <typename In, typename Out> +Out Utf<16>::FromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + *output++ = *begin++; + + return output; +} + +template <typename In, typename Out> +Out Utf<16>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale); + } + + return output; +} + +#ifndef EFSW_NO_WIDECHAR +template <typename In, typename Out> +Out Utf<16>::ToWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + output = Utf<32>::EncodeWide(codepoint, output, replacement); + } + + return output; +} +#endif + +template <typename In, typename Out> +Out Utf<16>::ToLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement; + begin++; + } + + return output; +} + +template <typename In, typename Out> +Out Utf<16>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + output = Utf<8>::Encode(codepoint, output); + } + + return output; +} + +template <typename In, typename Out> +Out Utf<16>::ToUtf16(In begin, In end, Out output) +{ + while (begin < end) + *output++ = *begin++; + + return output; +} + +template <typename In, typename Out> +Out Utf<16>::ToUtf32(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = Decode(begin, end, codepoint); + *output++ = codepoint; + } + + return output; +} + +template <typename In> +In Utf<32>::Decode(In begin, In end, Uint32& output, Uint32) +{ + output = *begin++; + return begin; +} + +template <typename Out> +Out Utf<32>::Encode(Uint32 input, Out output, Uint32 replacement) +{ + *output++ = input; + return output; +} + +template <typename In> +In Utf<32>::Next(In begin, In end) +{ + return ++begin; +} + +template <typename In> +std::size_t Utf<32>::Count(In begin, In end) +{ + return begin - end; +} + +template <typename In, typename Out> +Out Utf<32>::FromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + *output++ = DecodeAnsi(*begin++, locale); + + return output; +} + +template <typename In, typename Out> +Out Utf<32>::FromWide(In begin, In end, Out output) +{ + while (begin < end) + *output++ = DecodeWide(*begin++); + + return output; +} + +template <typename In, typename Out> +Out Utf<32>::FromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + *output++ = *begin++; + + return output; +} + +template <typename In, typename Out> +Out Utf<32>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + output = EncodeAnsi(*begin++, output, replacement, locale); + + return output; +} + +#ifndef EFSW_NO_WIDECHAR +template <typename In, typename Out> +Out Utf<32>::ToWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + output = EncodeWide(*begin++, output, replacement); + + return output; +} +#endif + +template <typename In, typename Out> +Out Utf<32>::ToLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement; + begin++; + } + + return output; +} + +template <typename In, typename Out> +Out Utf<32>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<8>::Encode(*begin++, output); + + return output; +} + +template <typename In, typename Out> +Out Utf<32>::ToUtf16(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<16>::Encode(*begin++, output); + + return output; +} + +template <typename In, typename Out> +Out Utf<32>::ToUtf32(In begin, In end, Out output) +{ + while (begin < end) + *output++ = *begin++; + + return output; +} + +template <typename In> +Uint32 Utf<32>::DecodeAnsi(In input, const std::locale& locale) +{ + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + + #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ + (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ + !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ + + wchar_t character = 0; + mbtowc(&character, &input, 1); + return static_cast<Uint32>(character); + + #else + // Get the facet of the locale which deals with character conversion + #ifndef EFSW_NO_WIDECHAR + const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale); + #else + const std::ctype<char>& facet = std::use_facet< std::ctype<char> >(locale); + #endif + + // Use the facet to convert each character of the input string + return static_cast<Uint32>(facet.widen(input)); + + #endif +} + +template <typename In> +Uint32 Utf<32>::DecodeWide(In input) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, + // and UCS-4 *is* UTF-32). + + return input; +} + +template <typename Out> +Out Utf<32>::EncodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale) +{ + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + + #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ + (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ + !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ + + char character = 0; + if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0) + *output++ = character; + else if (replacement) + *output++ = replacement; + + return output; + + #else + // Get the facet of the locale which deals with character conversion + #ifndef EFSW_NO_WIDECHAR + const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale); + #else + const std::ctype<char>& facet = std::use_facet< std::ctype<char> >(locale); + #endif + + // Use the facet to convert each character of the input string + *output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement); + + return output; + + #endif +} + +#ifndef EFSW_NO_WIDECHAR +template <typename Out> +Out Utf<32>::EncodeWide(Uint32 codepoint, Out output, wchar_t replacement) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). + // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). + + switch (sizeof(wchar_t)) + { + case 4: + { + *output++ = static_cast<wchar_t>(codepoint); + break; + } + + default: + { + if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) + { + *output++ = static_cast<wchar_t>(codepoint); + } + else if (replacement) + { + *output++ = replacement; + } + break; + } + } + + return output; +} +#endif diff --git a/dep/efsw/src/efsw/Watcher.cpp b/dep/efsw/src/efsw/Watcher.cpp new file mode 100644 index 00000000000..d81c84228ad --- /dev/null +++ b/dep/efsw/src/efsw/Watcher.cpp @@ -0,0 +1,21 @@ +#include <efsw/Watcher.hpp> + +namespace efsw { + +Watcher::Watcher() : + ID(0), + Directory(""), + Listener(NULL), + Recursive(false) +{ +} + +Watcher::Watcher( WatchID id, std::string directory, FileWatchListener * listener, bool recursive ) : + ID( id ), + Directory( directory ), + Listener( listener ), + Recursive( recursive ) +{ +} + +} diff --git a/dep/efsw/src/efsw/Watcher.hpp b/dep/efsw/src/efsw/Watcher.hpp new file mode 100644 index 00000000000..5a35cb9a2ac --- /dev/null +++ b/dep/efsw/src/efsw/Watcher.hpp @@ -0,0 +1,30 @@ +#ifndef EFSW_WATCHERIMPL_HPP +#define EFSW_WATCHERIMPL_HPP + +#include <efsw/base.hpp> +#include <efsw/efsw.hpp> + +namespace efsw { + +/** @brief Base Watcher class */ +class Watcher +{ + public: + Watcher(); + + Watcher( WatchID id, std::string directory, FileWatchListener * listener, bool recursive ); + + virtual ~Watcher() {} + + virtual void watch() {} + + WatchID ID; + std::string Directory; + FileWatchListener * Listener; + bool Recursive; + std::string OldFileName; +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/WatcherFSEvents.cpp b/dep/efsw/src/efsw/WatcherFSEvents.cpp new file mode 100644 index 00000000000..3a9700c77ec --- /dev/null +++ b/dep/efsw/src/efsw/WatcherFSEvents.cpp @@ -0,0 +1,264 @@ +#include <efsw/WatcherFSEvents.hpp> +#include <efsw/FileWatcherFSEvents.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/Debug.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +namespace efsw { + +WatcherFSEvents::WatcherFSEvents() : + Watcher(), + FWatcher( NULL ), + FSStream( NULL ), + WatcherGen( NULL ), + initializedAsync( false ) +{ +} + +WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherFSEvents * parent ) : + Watcher( id, directory, listener, recursive ), + FWatcher( NULL ), + FSStream( NULL ), + WatcherGen( NULL ), + initializedAsync( false ) +{ +} + +WatcherFSEvents::~WatcherFSEvents() +{ + if ( initializedAsync ) + { + FSEventStreamStop( FSStream ); + FSEventStreamInvalidate( FSStream ); + } + + if ( NULL != FSStream ) + { + FSEventStreamRelease( FSStream ); + } + + efSAFE_DELETE( WatcherGen ); +} + +void WatcherFSEvents::init() +{ + CFStringRef CFDirectory = CFStringCreateWithCString( NULL, Directory.c_str(), kCFStringEncodingUTF8 ); + CFArrayRef CFDirectoryArray = CFArrayCreate( NULL, (const void **)&CFDirectory, 1, NULL ); + + Uint32 streamFlags = kFSEventStreamCreateFlagNone; + + if ( FileWatcherFSEvents::isGranular() ) + { + streamFlags = efswFSEventStreamCreateFlagFileEvents; + } + else + { + WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher, Recursive ); + } + + FSEventStreamContext ctx; + /* Initialize context */ + ctx.version = 0; + ctx.info = this; + ctx.retain = NULL; + ctx.release = NULL; + ctx.copyDescription = NULL; + + FSStream = FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx, CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0.25, streamFlags ); + + FWatcher->mNeedInit.push_back( this ); + + CFRelease( CFDirectoryArray ); + CFRelease( CFDirectory ); +} + +void WatcherFSEvents::initAsync() +{ + FSEventStreamScheduleWithRunLoop( FSStream, FWatcher->mRunLoopRef, kCFRunLoopDefaultMode ); + FSEventStreamStart( FSStream ); + initializedAsync = true; +} + +void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename ) +{ + Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ), FileSystem::precomposeFileName( filename ), action, oldFilename ); +} + +void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath, std::string& filePath ) +{ + if ( flags & efswFSEventStreamEventFlagItemCreated ) + { + if ( FileInfo::exists( path ) ) + { + sendFileAction( ID, dirPath, filePath, Actions::Add ); + } + } + + if ( flags & efswFSEventsModified ) + { + sendFileAction( ID, dirPath, filePath, Actions::Modified ); + } + + if ( flags & efswFSEventStreamEventFlagItemRemoved ) + { + // Since i don't know the order, at least i try to keep the data consistent with the real state + if ( !FileInfo::exists( path ) ) + { + sendFileAction( ID, dirPath, filePath, Actions::Delete ); + } + } +} + +void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) +{ + size_t esize = events.size(); + + for ( size_t i = 0; i < esize; i++ ) + { + FSEvent& event = events[i]; + + if ( event.Flags & ( kFSEventStreamEventFlagUserDropped | + kFSEventStreamEventFlagKernelDropped | + kFSEventStreamEventFlagEventIdsWrapped | + kFSEventStreamEventFlagHistoryDone | + kFSEventStreamEventFlagMount | + kFSEventStreamEventFlagUnmount | + kFSEventStreamEventFlagRootChanged ) ) + { + continue; + } + + if ( !Recursive ) + { + /** In case that is not recursive the watcher, ignore the events from subfolders */ + if ( event.Path.find_last_of( FileSystem::getOSSlash() ) != Directory.size() - 1 ) + { + continue; + } + } + + if ( FileWatcherFSEvents::isGranular() ) + { + std::string dirPath( FileSystem::pathRemoveFileName( event.Path ) ); + std::string filePath( FileSystem::fileNameFromPath( event.Path ) ); + + if ( event.Flags & ( efswFSEventStreamEventFlagItemCreated | + efswFSEventStreamEventFlagItemRemoved | + efswFSEventStreamEventFlagItemRenamed ) + ) + { + if ( dirPath != Directory ) + { + DirsChanged.insert( dirPath ); + } + } + + // This is a mess. But it's FSEvents faults, because shrinks events from the same file in one single event ( so there's no order for them ) + // For example a file could have been added modified and erased, but i can't know if first was erased and then added and modified, or added, then modified and then erased. + // I don't know what they were thinking by doing this... + efDEBUG( "Event in: %s - flags: %ld\n", path.c_str(), event.Flags ); + + if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) + { + if ( ( i + 1 < esize ) && + ( events[ i + 1 ].Flags & efswFSEventStreamEventFlagItemRenamed ) && + ( events[ i + 1 ].Id == event.Id + 1 ) + ) + { + FSEvent& nEvent = events[ i + 1 ]; + std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) ); + std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) ); + + if ( event.Path != nEvent.Path ) + { + if ( dirPath == newDir ) + { + if ( !FileInfo::exists( event.Path ) ) + { + sendFileAction( ID, dirPath, newFilepath, Actions::Moved, filePath ); + } + else + { + sendFileAction( ID, dirPath, filePath, Actions::Moved, newFilepath ); + } + } + else + { + sendFileAction( ID, dirPath, filePath, Actions::Delete ); + sendFileAction( ID, newDir, newFilepath, Actions::Add ); + + if ( nEvent.Flags & efswFSEventsModified ) + { + sendFileAction( ID, newDir, newFilepath, Actions::Modified ); + } + } + } + else + { + handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath ); + } + + if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated | + efswFSEventStreamEventFlagItemRemoved | + efswFSEventStreamEventFlagItemRenamed ) + ) + { + if ( newDir != Directory ) + { + DirsChanged.insert( newDir ); + } + } + + // Skip the renamed file + i++; + } + else if ( FileInfo::exists( event.Path ) ) + { + sendFileAction( ID, dirPath, filePath, Actions::Add ); + + if ( event.Flags & efswFSEventsModified ) + { + sendFileAction( ID, dirPath, filePath, Actions::Modified ); + } + } + else + { + sendFileAction( ID, dirPath, filePath, Actions::Delete ); + } + } + else + { + handleAddModDel( event.Flags, event.Path, dirPath, filePath ); + } + } + else + { + efDEBUG( "Directory: %s changed\n", event.Path.c_str() ); + DirsChanged.insert( event.Path ); + } + } +} + +void WatcherFSEvents::process() +{ + std::set<std::string>::iterator it = DirsChanged.begin(); + + for ( ; it != DirsChanged.end(); it++ ) + { + if ( !FileWatcherFSEvents::isGranular() ) + { + WatcherGen->watchDir( (*it) ); + } + else + { + sendFileAction( ID, FileSystem::pathRemoveFileName( (*it) ), FileSystem::fileNameFromPath( (*it) ), Actions::Modified ); + } + } + + DirsChanged.clear(); +} + +} + +#endif diff --git a/dep/efsw/src/efsw/WatcherFSEvents.hpp b/dep/efsw/src/efsw/WatcherFSEvents.hpp new file mode 100644 index 00000000000..d4fc5c9a8d3 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherFSEvents.hpp @@ -0,0 +1,70 @@ +#ifndef EFSW_WATCHERINOTIFY_HPP +#define EFSW_WATCHERINOTIFY_HPP + +#include <efsw/FileWatcherImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <efsw/WatcherGeneric.hpp> +#include <efsw/FileInfo.hpp> +#include <CoreFoundation/CoreFoundation.h> +#include <CoreServices/CoreServices.h> +#include <set> +#include <vector> + +namespace efsw { + +class FileWatcherFSEvents; + +class FSEvent +{ + public: + FSEvent( std::string path, long flags, Uint64 id ) : + Path( path ), + Flags( flags ), + Id ( id ) + { + } + + std::string Path; + long Flags; + Uint64 Id; +}; + +class WatcherFSEvents : public Watcher +{ + public: + WatcherFSEvents(); + + WatcherFSEvents( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherFSEvents * parent = NULL ); + + ~WatcherFSEvents(); + + void init(); + + void initAsync(); + + void handleActions( std::vector<FSEvent> & events ); + + void process(); + + FileWatcherFSEvents * FWatcher; + + FSEventStreamRef FSStream; + protected: + void handleAddModDel( const Uint32 &flags, const std::string &path, std::string &dirPath, std::string &filePath ); + + WatcherGeneric * WatcherGen; + + bool initializedAsync; + + std::set<std::string> DirsChanged; + + void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename = "" ); +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/WatcherGeneric.cpp b/dep/efsw/src/efsw/WatcherGeneric.cpp new file mode 100644 index 00000000000..94170d3ce87 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherGeneric.cpp @@ -0,0 +1,40 @@ +#include <efsw/WatcherGeneric.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/DirWatcherGeneric.hpp> + +namespace efsw +{ + +WatcherGeneric::WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener * fwl, FileWatcherImpl * fw, bool recursive ) : + Watcher( id, directory, fwl, recursive ), + WatcherImpl( fw ), + DirWatch( NULL ) +{ + FileSystem::dirAddSlashAtEnd( Directory ); + + DirWatch = new DirWatcherGeneric( NULL, this, directory, recursive, false ); + + DirWatch->addChilds( false ); +} + +WatcherGeneric::~WatcherGeneric() +{ + efSAFE_DELETE( DirWatch ); +} + +void WatcherGeneric::watch() +{ + DirWatch->watch(); +} + +void WatcherGeneric::watchDir( std::string dir ) +{ + DirWatch->watchDir( dir ); +} + +bool WatcherGeneric::pathInWatches( std::string path ) +{ + return DirWatch->pathInWatches( path ); +} + +} diff --git a/dep/efsw/src/efsw/WatcherGeneric.hpp b/dep/efsw/src/efsw/WatcherGeneric.hpp new file mode 100644 index 00000000000..8794e921b40 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherGeneric.hpp @@ -0,0 +1,30 @@ +#ifndef EFSW_WATCHERGENERIC_HPP +#define EFSW_WATCHERGENERIC_HPP + +#include <efsw/FileWatcherImpl.hpp> + +namespace efsw +{ + +class DirWatcherGeneric; + +class WatcherGeneric : public Watcher +{ + public: + FileWatcherImpl * WatcherImpl; + DirWatcherGeneric * DirWatch; + + WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener * fwl, FileWatcherImpl * fw, bool recursive ); + + ~WatcherGeneric(); + + void watch(); + + void watchDir( std::string dir ); + + bool pathInWatches( std::string path ); +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/WatcherInotify.cpp b/dep/efsw/src/efsw/WatcherInotify.cpp new file mode 100644 index 00000000000..741641bf43c --- /dev/null +++ b/dep/efsw/src/efsw/WatcherInotify.cpp @@ -0,0 +1,35 @@ +#include <efsw/WatcherInotify.hpp> + +namespace efsw { + +WatcherInotify::WatcherInotify() : + Watcher(), + Parent( NULL ) +{ +} + +WatcherInotify::WatcherInotify( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherInotify * parent ) : + Watcher( id, directory, listener, recursive ), + Parent( parent ), + DirInfo( directory ) +{ +} + +bool WatcherInotify::inParentTree( WatcherInotify * parent ) +{ + WatcherInotify * tNext = Parent; + + while ( NULL != tNext ) + { + if ( tNext == parent ) + { + return true; + } + + tNext = tNext->Parent; + } + + return false; +} + +} diff --git a/dep/efsw/src/efsw/WatcherInotify.hpp b/dep/efsw/src/efsw/WatcherInotify.hpp new file mode 100644 index 00000000000..1caf399679b --- /dev/null +++ b/dep/efsw/src/efsw/WatcherInotify.hpp @@ -0,0 +1,25 @@ +#ifndef EFSW_WATCHERINOTIFY_HPP +#define EFSW_WATCHERINOTIFY_HPP + +#include <efsw/FileWatcherImpl.hpp> +#include <efsw/FileInfo.hpp> + +namespace efsw { + +class WatcherInotify : public Watcher +{ + public: + WatcherInotify(); + + WatcherInotify( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherInotify * parent = NULL ); + + bool inParentTree( WatcherInotify * parent ); + + WatcherInotify * Parent; + + FileInfo DirInfo; +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/WatcherKqueue.cpp b/dep/efsw/src/efsw/WatcherKqueue.cpp new file mode 100644 index 00000000000..8347fb53439 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherKqueue.cpp @@ -0,0 +1,667 @@ +#include <efsw/WatcherKqueue.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <efsw/Debug.hpp> +#include <efsw/String.hpp> +#include <efsw/System.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/WatcherGeneric.hpp> +#include <efsw/FileWatcherKqueue.hpp> + +#define KEVENT_RESERVE_VALUE (10) + +#ifndef O_EVTONLY +#define O_EVTONLY (O_RDONLY | O_NONBLOCK) +#endif + +namespace efsw { + +int comparator(const void* ke1, const void* ke2) +{ + const KEvent * kev1 = reinterpret_cast<const KEvent*>( ke1 ); + const KEvent * kev2 = reinterpret_cast<const KEvent*>( ke2 ); + + if ( NULL != kev2->udata ) + { + FileInfo * fi1 = reinterpret_cast<FileInfo*>( kev1->udata ); + FileInfo * fi2 = reinterpret_cast<FileInfo*>( kev2->udata ); + + return strcmp( fi1->Filepath.c_str(), fi2->Filepath.c_str() ); + } + + return 1; +} + +WatcherKqueue::WatcherKqueue(WatchID watchid, const std::string& dirname, FileWatchListener* listener, bool recursive, FileWatcherKqueue * watcher, WatcherKqueue * parent ) : + Watcher( watchid, dirname, listener, recursive ), + mLastWatchID(0), + mChangeListCount( 0 ), + mKqueue( kqueue() ), + mWatcher( watcher ), + mParent( parent ), + mInitOK( true ), + mErrno(0) +{ + if ( -1 == mKqueue ) + { + efDEBUG( "kqueue() returned invalid descriptor for directory %s. File descriptors count: %ld\n", Directory.c_str(), mWatcher->mFileDescriptorCount ); + + mInitOK = false; + mErrno = errno; + } + else + { + mWatcher->addFD(); + } +} + +WatcherKqueue::~WatcherKqueue() +{ + // Remove the childs watchers ( sub-folders watches ) + removeAll(); + + for ( size_t i = 0; i < mChangeListCount; i++ ) + { + if ( NULL != mChangeList[i].udata ) + { + FileInfo * fi = reinterpret_cast<FileInfo*>( mChangeList[i].udata ); + + efSAFE_DELETE( fi ); + } + } + + close( mKqueue ); + + mWatcher->removeFD(); +} + +void WatcherKqueue::addAll() +{ + if ( -1 == mKqueue ) + { + return; + } + + // scan directory and call addFile(name, false) on each file + FileSystem::dirAddSlashAtEnd( Directory ); + + efDEBUG( "addAll(): Added folder: %s\n", Directory.c_str()); + + // add base dir + int fd = open( Directory.c_str(), O_EVTONLY ); + + if ( -1 == fd ) + { + efDEBUG( "addAll(): Couldn't open folder: %s\n", Directory.c_str() ); + + if ( EACCES != errno ) + { + mInitOK = false; + } + + mErrno = errno; + + return; + } + + mDirSnap.setDirectoryInfo( Directory ); + mDirSnap.scan(); + + mChangeList.resize( KEVENT_RESERVE_VALUE ); + + // Creates the kevent for the folder + EV_SET( + &mChangeList[0], + fd, + EVFILT_VNODE, + EV_ADD | EV_ENABLE | EV_ONESHOT, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, + 0, + 0 + ); + + mWatcher->addFD(); + + // Get the files and directories from the directory + FileInfoMap files = FileSystem::filesInfoFromPath( Directory ); + + for ( FileInfoMap::iterator it = files.begin(); it != files.end(); it++ ) + { + FileInfo& fi = it->second; + + if ( fi.isRegularFile() ) + { + // Add the regular files kevent + addFile( fi.Filepath , false ); + } + else if ( Recursive && fi.isDirectory() && fi.isReadable() ) + { + // Create another watcher for the subfolders ( if recursive ) + WatchID id = addWatch( fi.Filepath, Listener, Recursive, this ); + + // If the watcher is not adding the watcher means that the directory was created + if ( id > 0 && !mWatcher->isAddingWatcher() ) + { + handleFolderAction( fi.Filepath, Actions::Add ); + } + } + } +} + +void WatcherKqueue::removeAll() +{ + efDEBUG( "removeAll(): Removing all child watchers\n" ); + + std::list<WatchID> erase; + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + { + efDEBUG( "removeAll(): Removed child watcher %s\n", it->second->Directory.c_str() ); + + erase.push_back( it->second->ID ); + } + + for ( std::list<WatchID>::iterator eit = erase.begin(); eit != erase.end(); eit++ ) + { + removeWatch( *eit ); + } +} + +void WatcherKqueue::addFile(const std::string& name, bool emitEvents) +{ + efDEBUG( "addFile(): Added: %s\n", name.c_str() ); + + // Open the file to get the file descriptor + int fd = open( name.c_str(), O_EVTONLY ); + + if( fd == -1 ) + { + efDEBUG( "addFile(): Could open file descriptor for %s. File descriptor count: %ld\n", name.c_str(), mWatcher->mFileDescriptorCount ); + + Errors::Log::createLastError( Errors::FileNotReadable, name ); + + if ( EACCES != errno ) + { + mInitOK = false; + } + + mErrno = errno; + + return; + } + + mWatcher->addFD(); + + // increase the file kevent file count + mChangeListCount++; + + if ( mChangeListCount + KEVENT_RESERVE_VALUE > mChangeList.size() && + mChangeListCount % KEVENT_RESERVE_VALUE == 0 ) + { + size_t reserve_size = mChangeList.size() + KEVENT_RESERVE_VALUE; + mChangeList.resize( reserve_size ); + efDEBUG( "addFile(): Reserverd more KEvents space for %s, space reserved %ld, list actual size %ld.\n", Directory.c_str(), reserve_size, mChangeListCount ); + } + + // create entry + FileInfo * entry = new FileInfo( name ); + + // set the event data at the end of the list + EV_SET( + &mChangeList[mChangeListCount], + fd, + EVFILT_VNODE, + EV_ADD | EV_ENABLE | EV_ONESHOT, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, + 0, + (void*)entry + ); + + // qsort sort the list by name + qsort(&mChangeList[1], mChangeListCount, sizeof(KEvent), comparator); + + // handle action + if( emitEvents ) + { + handleAction(name, Actions::Add); + } +} + +void WatcherKqueue::removeFile( const std::string& name, bool emitEvents ) +{ + efDEBUG( "removeFile(): Trying to remove file: %s\n", name.c_str() ); + + // bsearch + KEvent target; + + // Create a temporary file info to search the kevent ( searching the directory ) + FileInfo tempEntry( name ); + + target.udata = &tempEntry; + + // Search the kevent + KEvent * ke = (KEvent*)bsearch(&target, &mChangeList[0], mChangeListCount + 1, sizeof(KEvent), comparator); + + // Trying to remove a non-existing file? + if( !ke ) + { + Errors::Log::createLastError( Errors::FileNotFound, name ); + efDEBUG( "File not removed\n" ); + return; + } + + efDEBUG( "File removed\n" ); + + // handle action + if ( emitEvents ) + { + handleAction( name, Actions::Delete ); + } + + // Delete the user data ( FileInfo ) from the kevent closed + FileInfo * del = reinterpret_cast<FileInfo*>( ke->udata ); + + efSAFE_DELETE( del ); + + // close the file descriptor from the kevent + close( ke->ident ); + + mWatcher->removeFD(); + + memset(ke, 0, sizeof(KEvent)); + + // move end to current + memcpy(ke, &mChangeList[mChangeListCount], sizeof(KEvent)); + memset(&mChangeList[mChangeListCount], 0, sizeof(KEvent)); + --mChangeListCount; +} + +void WatcherKqueue::rescan() +{ + efDEBUG( "rescan(): Rescanning: %s\n", Directory.c_str() ); + + DirectorySnapshotDiff Diff = mDirSnap.scan(); + + if ( Diff.DirChanged ) + { + sendDirChanged(); + } + + if ( Diff.changed() ) + { + FileInfoList::iterator it; + MovedList::iterator mit; + + /// Files + DiffIterator( FilesCreated ) + { + addFile( (*it).Filepath ); + } + + DiffIterator( FilesModified ) + { + handleAction( (*it).Filepath, Actions::Modified ); + } + + DiffIterator( FilesDeleted ) + { + removeFile( (*it).Filepath ); + } + + DiffMovedIterator( FilesMoved ) + { + handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first ); + removeFile( Directory + (*mit).first, false ); + addFile( (*mit).second.Filepath, false ); + } + + /// Directories + DiffIterator( DirsCreated ) + { + handleFolderAction( (*it).Filepath, Actions::Add ); + addWatch( (*it).Filepath, Listener, Recursive, this ); + } + + DiffIterator( DirsModified ) + { + handleFolderAction( (*it).Filepath, Actions::Modified ); + } + + DiffIterator( DirsDeleted ) + { + handleFolderAction( (*it).Filepath, Actions::Delete ); + + Watcher * watch = findWatcher( (*it).Filepath ); + + if ( NULL != watch ) + { + removeWatch( watch->ID ); + + } + } + + DiffMovedIterator( DirsMoved ) + { + moveDirectory( Directory + (*mit).first, (*mit).second.Filepath ); + } + } +} + +WatchID WatcherKqueue::watchingDirectory( std::string dir ) +{ + Watcher * watch = findWatcher( dir ); + + if ( NULL != watch ) + { + return watch->ID; + } + + return Errors::FileNotFound; +} + +void WatcherKqueue::handleAction( const std::string& filename, efsw::Action action, const std::string& oldFilename ) +{ + Listener->handleFileAction( ID, Directory, FileSystem::fileNameFromPath( filename ), action, FileSystem::fileNameFromPath( oldFilename ) ); +} + +void WatcherKqueue::handleFolderAction( std::string filename, efsw::Action action , const std::string &oldFilename ) +{ + FileSystem::dirRemoveSlashAtEnd( filename ); + + handleAction( filename, action, oldFilename ); +} + +void WatcherKqueue::sendDirChanged() +{ + if ( NULL != mParent ) + { + Listener->handleFileAction( mParent->ID, mParent->Directory, FileSystem::fileNameFromPath( Directory ), Actions::Modified ); + } +} + +void WatcherKqueue::watch() +{ + if ( -1 == mKqueue ) + { + return; + } + + int nev = 0; + KEvent event; + + // First iterate the childs, to get the events from the deepest folder, to the watcher childs + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) + { + it->second->watch(); + } + + bool needScan = false; + + // Then we get the the events of the current folder + while( ( nev = kevent( mKqueue, &mChangeList[0], mChangeListCount + 1, &event, 1, &mWatcher->mTimeOut ) ) != 0 ) + { + // An error ocurred? + if( nev == -1 ) + { + efDEBUG( "watch(): Error on directory %s\n", Directory.c_str() ); + perror("kevent"); + break; + } + else + { + FileInfo * entry = NULL; + + // If udate == NULL means that it is the fisrt element of the change list, the folder. + // otherwise it is an event of some file inside the folder + if( ( entry = reinterpret_cast<FileInfo*> ( event.udata ) ) != NULL ) + { + efDEBUG( "watch(): File: %s ", entry->Filepath.c_str() ); + + // If the event flag is delete... the file was deleted + if ( event.fflags & NOTE_DELETE ) + { + efDEBUG( "deleted\n" ); + + mDirSnap.removeFile( entry->Filepath ); + + removeFile( entry->Filepath ); + } + else if ( event.fflags & NOTE_EXTEND || + event.fflags & NOTE_WRITE || + event.fflags & NOTE_ATTRIB + ) + { + // The file was modified + efDEBUG( "modified\n" ); + + FileInfo fi( entry->Filepath ); + + if ( fi != *entry ) + { + *entry = fi; + + mDirSnap.updateFile( entry->Filepath ); + + handleAction( entry->Filepath, efsw::Actions::Modified ); + } + } + else if ( event.fflags & NOTE_RENAME ) + { + efDEBUG( "moved\n" ); + + needScan = true; + } + } + else + { + needScan = true; + } + } + } + + if ( needScan ) + { + rescan(); + } +} + +Watcher * WatcherKqueue::findWatcher( const std::string path ) +{ + WatchMap::iterator it = mWatches.begin(); + + for ( ; it != mWatches.end(); it++ ) + { + if ( it->second->Directory == path ) + { + return it->second; + } + } + + return NULL; +} + +void WatcherKqueue::moveDirectory( std::string oldPath, std::string newPath, bool emitEvents ) +{ + // Update the directory path if it's a watcher + std::string opath2( oldPath ); + FileSystem::dirAddSlashAtEnd( opath2 ); + + Watcher * watch = findWatcher( opath2 ); + + if ( NULL != watch ) + { + watch->Directory = opath2; + } + + if ( emitEvents ) + { + handleFolderAction( newPath, efsw::Actions::Moved, oldPath ); + } +} + +WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive , WatcherKqueue *parent) +{ + static long s_fc = 0; + static bool s_ug = false; + + std::string dir( directory ); + + FileSystem::dirAddSlashAtEnd( dir ); + + // This should never happen here + if( !FileSystem::isDirectory( dir ) ) + { + return Errors::Log::createLastError( Errors::FileNotFound, dir ); + } + else if ( pathInWatches( dir ) || pathInParent( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, directory ); + } + else if ( NULL != parent && FileSystem::isRemoteFS( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRemote, dir ); + } + + std::string curPath; + std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); + + if ( "" != link ) + { + /// Avoid adding symlinks directories if it's now enabled + if ( NULL != parent && !mWatcher->mFileWatcher->followSymlinks() ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); + } + + if ( pathInWatches( link ) || pathInParent( link ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, link ); + } + else if ( !mWatcher->linkAllowed( curPath, link ) ) + { + return Errors::Log::createLastError( Errors::FileOutOfScope, link ); + } + else + { + dir = link; + } + } + + if ( mWatcher->availablesFD() ) + { + WatcherKqueue* watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, mWatcher, parent ); + + mWatches.insert(std::make_pair(mLastWatchID, watch)); + + watch->addAll(); + + s_fc++; + + // if failed to open the directory... erase the watcher + if ( !watch->initOK() ) + { + int le = watch->lastErrno(); + + mWatches.erase( watch->ID ); + + efSAFE_DELETE( watch ); + + mLastWatchID--; + + // Probably the folder has too many files, create a generic watcher + if ( EACCES != le ) + { + WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive ); + + mWatches.insert(std::make_pair(mLastWatchID, watch)); + } + else + { + return Errors::Log::createLastError( Errors::Unspecified, link ); + } + } + } + else + { + if ( !s_ug ) + { + efDEBUG( "Started using WatcherGeneric, reached file descriptors limit: %ld. Folders added: %ld\n", mWatcher->mFileDescriptorCount, s_fc ); + s_ug = true; + } + + WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive ); + + mWatches.insert(std::make_pair(mLastWatchID, watch)); + } + + return mLastWatchID; +} + +bool WatcherKqueue::initOK() +{ + return mInitOK; +} + +void WatcherKqueue::removeWatch( WatchID watchid ) +{ + WatchMap::iterator iter = mWatches.find(watchid); + + if(iter == mWatches.end()) + return; + + Watcher * watch = iter->second; + + mWatches.erase(iter); + + efSAFE_DELETE( watch ); +} + +bool WatcherKqueue::pathInWatches( const std::string& path ) +{ + return NULL != findWatcher( path ); +} + +bool WatcherKqueue::pathInParent( const std::string &path ) +{ + WatcherKqueue * pNext = mParent; + + while ( NULL != pNext ) + { + if ( pNext->pathInWatches( path ) ) + { + return true; + } + + pNext = pNext->mParent; + } + + if ( mWatcher->pathInWatches( path ) ) + { + return true; + } + + if ( path == Directory ) + { + return true; + } + + return false; +} + +int WatcherKqueue::lastErrno() +{ + return mErrno; +} + +} + +#endif diff --git a/dep/efsw/src/efsw/WatcherKqueue.hpp b/dep/efsw/src/efsw/WatcherKqueue.hpp new file mode 100644 index 00000000000..4babbe73354 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherKqueue.hpp @@ -0,0 +1,94 @@ +#ifndef EFSW_WATCHEROSX_HPP +#define EFSW_WATCHEROSX_HPP + +#include <efsw/FileWatcherImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS + +#include <map> +#include <vector> +#include <sys/types.h> +#include <sys/event.h> +#include <efsw/DirectorySnapshot.hpp> + +namespace efsw +{ + +class FileWatcherKqueue; +class WatcherKqueue; + +typedef struct kevent KEvent; + +/// type for a map from WatchID to WatcherKqueue pointer +typedef std::map<WatchID, Watcher*> WatchMap; + +class WatcherKqueue : public Watcher +{ + public: + WatcherKqueue( WatchID watchid, const std::string& dirname, FileWatchListener* listener, bool recursive, FileWatcherKqueue * watcher, WatcherKqueue * parent = NULL ); + + virtual ~WatcherKqueue(); + + void addFile( const std::string& name, bool emitEvents = true ); + + void removeFile( const std::string& name, bool emitEvents = true ); + + // called when the directory is actually changed + // means a file has been added or removed + // rescans the watched directory adding/removing files and sending notices + void rescan(); + + void handleAction( const std::string& filename, efsw::Action action, const std::string& oldFilename = "" ); + + void handleFolderAction( std::string filename, efsw::Action action, const std::string& oldFilename = "" ); + + void addAll(); + + void removeAll(); + + WatchID watchingDirectory( std::string dir ); + + void watch(); + + WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherKqueue * parent); + + void removeWatch (WatchID watchid ); + + bool initOK(); + + int lastErrno(); + protected: + WatchMap mWatches; + int mLastWatchID; + + // index 0 is always the directory + std::vector<KEvent> mChangeList; + size_t mChangeListCount; + DirectorySnapshot mDirSnap; + + /// The descriptor for the kqueue + int mKqueue; + + FileWatcherKqueue * mWatcher; + + WatcherKqueue * mParent; + + bool mInitOK; + int mErrno; + + bool pathInWatches( const std::string& path ); + + bool pathInParent( const std::string& path ); + + Watcher * findWatcher( const std::string path ); + + void moveDirectory( std::string oldPath, std::string newPath, bool emitEvents = true ); + + void sendDirChanged(); +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/WatcherWin32.cpp b/dep/efsw/src/efsw/WatcherWin32.cpp new file mode 100644 index 00000000000..01d7b0fcd99 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherWin32.cpp @@ -0,0 +1,150 @@ +#include <efsw/WatcherWin32.hpp> +#include <efsw/String.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +namespace efsw +{ + +/// Unpacks events and passes them to a user defined callback. +void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) +{ + char szFile[MAX_PATH]; + PFILE_NOTIFY_INFORMATION pNotify; + WatcherStructWin32 * tWatch = (WatcherStructWin32*) lpOverlapped; + WatcherWin32 * pWatch = tWatch->Watch; + size_t offset = 0; + + if (dwNumberOfBytesTransfered == 0) + { + RefreshWatch(tWatch); // If dwNumberOfBytesTransfered == 0, it means the buffer overflowed (too many changes between GetOverlappedResults calls). Those events are lost, but at least we can refresh so subsequent changes are seen again. + return; + } + + if (dwErrorCode == ERROR_SUCCESS) + { + do + { + bool skip = false; + + pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset]; + offset += pNotify->NextEntryOffset; + + int count = WideCharToMultiByte(CP_UTF8, 0, pNotify->FileName, + pNotify->FileNameLength / sizeof(WCHAR), + szFile, MAX_PATH - 1, NULL, NULL); + szFile[count] = TEXT('\0'); + + std::string nfile( szFile ); + + if ( FILE_ACTION_MODIFIED == pNotify->Action ) + { + FileInfo fifile( std::string( pWatch->DirName ) + nfile ); + + if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime && pWatch->LastModifiedEvent.file.Size == fifile.Size && pWatch->LastModifiedEvent.fileName == nfile ) + { + skip = true; + } + + pWatch->LastModifiedEvent.fileName = nfile; + pWatch->LastModifiedEvent.file = fifile; + } + + if ( !skip ) + { + pWatch->Watch->handleAction(pWatch, nfile, pNotify->Action); + } + } while (pNotify->NextEntryOffset != 0); + } + + if (!pWatch->StopNow) + { + RefreshWatch(tWatch); + } +} + +/// Refreshes the directory monitoring. +bool RefreshWatch(WatcherStructWin32* pWatch) +{ + return ReadDirectoryChangesW( + pWatch->Watch->DirHandle, + pWatch->Watch->mBuffer, + sizeof(pWatch->Watch->mBuffer), + pWatch->Watch->Recursive, + pWatch->Watch->NotifyFilter, + NULL, + &pWatch->Overlapped, + NULL + ) != 0; +} + +/// Stops monitoring a directory. +void DestroyWatch(WatcherStructWin32* pWatch) +{ + if (pWatch) + { + WatcherWin32 * tWatch = pWatch->Watch; + + tWatch->StopNow = true; + + CancelIo(tWatch->DirHandle); + + RefreshWatch(pWatch); + + if (!HasOverlappedIoCompleted(&pWatch->Overlapped)) + { + SleepEx(5, TRUE); + } + + CloseHandle(pWatch->Overlapped.hEvent); + CloseHandle(pWatch->Watch->DirHandle); + efSAFE_DELETE_ARRAY( pWatch->Watch->DirName ); + efSAFE_DELETE( pWatch->Watch ); + HeapFree(GetProcessHeap(), 0, pWatch); + } +} + +/// Starts monitoring a directory. +WatcherStructWin32* CreateWatch(LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter) +{ + WatcherStructWin32 * tWatch; + size_t ptrsize = sizeof(*tWatch); + tWatch = static_cast<WatcherStructWin32*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize)); + + WatcherWin32 * pWatch = new WatcherWin32(); + tWatch->Watch = pWatch; + + pWatch->DirHandle = CreateFileW( + szDirectory, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, + NULL + ); + + if (pWatch->DirHandle != INVALID_HANDLE_VALUE) + { + tWatch->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + pWatch->NotifyFilter = NotifyFilter; + pWatch->Recursive = recursive; + + if (RefreshWatch(tWatch)) + { + return tWatch; + } + else + { + CloseHandle(tWatch->Overlapped.hEvent); + CloseHandle(pWatch->DirHandle); + } + } + + HeapFree(GetProcessHeap(), 0, tWatch); + return NULL; +} + +} + + #endif diff --git a/dep/efsw/src/efsw/WatcherWin32.hpp b/dep/efsw/src/efsw/WatcherWin32.hpp new file mode 100644 index 00000000000..3c6d988fbf4 --- /dev/null +++ b/dep/efsw/src/efsw/WatcherWin32.hpp @@ -0,0 +1,77 @@ +#ifndef EFSW_WATCHERWIN32_HPP +#define EFSW_WATCHERWIN32_HPP + +#include <efsw/FileWatcherImpl.hpp> +#include <efsw/FileInfo.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#include <windows.h> + +#ifdef EFSW_COMPILER_MSVC + #pragma comment(lib, "comctl32.lib") + #pragma comment(lib, "user32.lib") + #pragma comment(lib, "ole32.lib") + + // disable secure warnings + #pragma warning (disable: 4996) +#endif + +namespace efsw +{ + +class WatcherWin32; + +/// Internal watch data +struct WatcherStructWin32 +{ + OVERLAPPED Overlapped; + WatcherWin32 * Watch; +}; + +class cLastModifiedEvent +{ + public: + cLastModifiedEvent() {} + FileInfo file; + std::string fileName; +}; + +bool RefreshWatch(WatcherStructWin32* pWatch); + +void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped); + +void DestroyWatch(WatcherStructWin32* pWatch); + +WatcherStructWin32* CreateWatch(LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter); + +class WatcherWin32 : public Watcher +{ + public: + WatcherWin32() : + Struct( NULL ), + DirHandle( NULL ), + lParam( 0 ), + NotifyFilter( 0 ), + StopNow( false ), + Watch( NULL ), + DirName( NULL ) + { + } + + WatcherStructWin32 * Struct; + HANDLE DirHandle; + BYTE mBuffer[63 * 1024]; // do NOT make this bigger than 64K because it will fail if the folder being watched is on the network! (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) + LPARAM lParam; + DWORD NotifyFilter; + bool StopNow; + FileWatcherImpl* Watch; + char* DirName; + cLastModifiedEvent LastModifiedEvent; +}; + +} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/base.hpp b/dep/efsw/src/efsw/base.hpp new file mode 100644 index 00000000000..26108c76985 --- /dev/null +++ b/dep/efsw/src/efsw/base.hpp @@ -0,0 +1,110 @@ +#ifndef EFSW_BASE +#define EFSW_BASE + +#include <efsw/sophist.h> +#include <efsw/efsw.hpp> + +namespace efsw { + +typedef SOPHIST_int8 Int8; +typedef SOPHIST_uint8 Uint8; +typedef SOPHIST_int16 Int16; +typedef SOPHIST_uint16 Uint16; +typedef SOPHIST_int32 Int32; +typedef SOPHIST_uint32 Uint32; +typedef SOPHIST_int64 Int64; +typedef SOPHIST_uint64 Uint64; + +#define EFSW_OS_WIN 1 +#define EFSW_OS_LINUX 2 +#define EFSW_OS_MACOSX 3 +#define EFSW_OS_BSD 4 +#define EFSW_OS_SOLARIS 5 +#define EFSW_OS_HAIKU 6 +#define EFSW_OS_ANDROID 7 +#define EFSW_OS_IOS 8 + +#define EFSW_PLATFORM_WIN32 1 +#define EFSW_PLATFORM_INOTIFY 2 +#define EFSW_PLATFORM_KQUEUE 3 +#define EFSW_PLATFORM_FSEVENTS 4 +#define EFSW_PLATFORM_GENERIC 5 + +#if defined(_WIN32) + /// Any Windows platform + #define EFSW_OS EFSW_OS_WIN + #define EFSW_PLATFORM EFSW_PLATFORM_WIN32 + + #if ( defined( _MSCVER ) || defined( _MSC_VER ) ) + #define EFSW_COMPILER_MSVC + #endif + +#elif defined( __FreeBSD__ ) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined( __DragonFly__ ) + #define EFSW_OS EFSW_OS_BSD + #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE + +#elif defined( __APPLE_CC__ ) || defined ( __APPLE__ ) + #include <TargetConditionals.h> + + #if defined( __IPHONE__ ) || ( defined( TARGET_OS_IPHONE ) && TARGET_OS_IPHONE ) || ( defined( TARGET_IPHONE_SIMULATOR ) && TARGET_IPHONE_SIMULATOR ) + #define EFSW_OS EFSW_OS_IOS + #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE + #else + #define EFSW_OS EFSW_OS_MACOSX + + #if defined(EFSW_FSEVENTS_NOT_SUPPORTED) + #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE + #else + #define EFSW_PLATFORM EFSW_PLATFORM_FSEVENTS + #endif + #endif + +#elif defined(__linux__) + /// This includes Linux and Android + #ifndef EFSW_KQUEUE + #define EFSW_PLATFORM EFSW_PLATFORM_INOTIFY + #else + /// This is for testing libkqueue, sadly it doesnt work + #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE + #endif + + #if defined( __ANDROID__ ) || defined( ANDROID ) + #define EFSW_OS EFSW_OS_ANDROID + #else + #define EFSW_OS EFSW_OS_LINUX + #endif + +#else + #if defined( __SVR4 ) + #define EFSW_OS EFSW_OS_SOLARIS + #elif defined( __HAIKU__ ) || defined( __BEOS__ ) + #define EFSW_OS EFSW_OS_HAIKU + #endif + + /// Everything else + #define EFSW_PLATFORM EFSW_PLATFORM_GENERIC +#endif + +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + #define EFSW_PLATFORM_POSIX +#endif + +#if 1 == SOPHIST_pointer64 + #define EFSW_64BIT +#else + #define EFSW_32BIT +#endif + +#if defined(arm) || defined(__arm__) + #define EFSW_ARM +#endif + +#define efCOMMA , + +#define efSAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define efSAFE_DELETE_ARRAY(p) { if(p) { delete [] (p); (p)=NULL; } } +#define efARRAY_SIZE(__array) ( sizeof(__array) / sizeof(__array[0]) ) + +} + +#endif diff --git a/dep/efsw/src/efsw/inotify-nosys.h b/dep/efsw/src/efsw/inotify-nosys.h new file mode 100644 index 00000000000..75df5d3ced3 --- /dev/null +++ b/dep/efsw/src/efsw/inotify-nosys.h @@ -0,0 +1,159 @@ +#ifndef _LINUX_INOTIFY_H +#define _LINUX_INOTIFY_H + +#include <stdint.h> +#include <sys/syscall.h> +#include <unistd.h> + +/* + * struct inotify_event - structure read from the inotify device for each event + * + * When you are watching a directory, you will receive the filename for events + * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd. + */ +struct inotify_event { + int wd; /* watch descriptor */ + uint32_t mask; /* watch mask */ + uint32_t cookie; /* cookie to synchronize two events */ + uint32_t len; /* length (including nulls) of name */ + char name __flexarr; /* stub for possible name */ +}; + +/* the following are legal, implemented events that user-space can watch for */ +#define IN_ACCESS 0x00000001 /* File was accessed */ +#define IN_MODIFY 0x00000002 /* File was modified */ +#define IN_ATTRIB 0x00000004 /* Metadata changed */ +#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */ +#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ +#define IN_OPEN 0x00000020 /* File was opened */ +#define IN_MOVED_FROM 0x00000040 /* File was moved from X */ +#define IN_MOVED_TO 0x00000080 /* File was moved to Y */ +#define IN_CREATE 0x00000100 /* Subfile was created */ +#define IN_DELETE 0x00000200 /* Subfile was deleted */ +#define IN_DELETE_SELF 0x00000400 /* Self was deleted */ +#define IN_MOVE_SELF 0x00000800 /* Self was moved */ + +/* the following are legal events. they are sent as needed to any watch */ +#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */ +#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ +#define IN_IGNORED 0x00008000 /* File was ignored */ + +/* helper events */ +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */ +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ + +/* special flags */ +#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */ +#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */ +#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ +#define IN_ISDIR 0x40000000 /* event occurred against dir */ +#define IN_ONESHOT 0x80000000 /* only send event once */ + +/* + * All of the events - we build the list by hand so that we can add flags in + * the future and not break backward compatibility. Apps will get only the + * events that they originally wanted. Be sure to add new events here! + */ +#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ + IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ + IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \ + IN_MOVE_SELF) + +#if defined (__alpha__) +# define __NR_inotify_init 444 +# define __NR_inotify_add_watch 445 +# define __NR_inotify_rm_watch 446 + +#elif defined (__arm__) +# define __NR_inotify_init (__NR_SYSCALL_BASE+316) +# define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317) +# define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318) + +#elif defined (__frv__) +# define __NR_inotify_init 291 +# define __NR_inotify_add_watch 292 +# define __NR_inotify_rm_watch 293 + +#elif defined(__i386__) +# define __NR_inotify_init 291 +# define __NR_inotify_add_watch 292 +# define __NR_inotify_rm_watch 293 + +#elif defined (__ia64__) +# define __NR_inotify_init 1277 +# define __NR_inotify_add_watch 1278 +# define __NR_inotify_rm_watch 1279 + +#elif defined (__mips__) +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define __NR_inotify_init (__NR_Linux + 284) +# define __NR_inotify_add_watch (__NR_Linux + 285) +# define __NR_inotify_rm_watch (__NR_Linux + 286) +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR_inotify_init (__NR_Linux + 243) +# define __NR_inotify_add_watch (__NR_Linux + 243) +# define __NR_inotify_rm_watch (__NR_Linux + 243) +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define __NR_inotify_init (__NR_Linux + 247) +# define __NR_inotify_add_watch (__NR_Linux + 248) +# define __NR_inotify_rm_watch (__NR_Linux + 249) +# endif + +#elif defined(__parisc__) +# define __NR_inotify_init (__NR_Linux + 269) +# define __NR_inotify_add_watch (__NR_Linux + 270) +# define __NR_inotify_rm_watch (__NR_Linux + 271) + +#elif defined(__powerpc__) || defined(__powerpc64__) +# define __NR_inotify_init 275 +# define __NR_inotify_add_watch 276 +# define __NR_inotify_rm_watch 277 + +#elif defined (__s390__) +# define __NR_inotify_init 284 +# define __NR_inotify_add_watch 285 +# define __NR_inotify_rm_watch 286 + +#elif defined (__sh__) +# define __NR_inotify_init 290 +# define __NR_inotify_add_watch 291 +# define __NR_inotify_rm_watch 292 + +#elif defined (__sh64__) +# define __NR_inotify_init 318 +# define __NR_inotify_add_watch 319 +# define __NR_inotify_rm_watch 320 + +#elif defined (__sparc__) || defined (__sparc64__) +# define __NR_inotify_init 151 +# define __NR_inotify_add_watch 152 +# define __NR_inotify_rm_watch 156 + +#elif defined(__x86_64__) +# define __NR_inotify_init 253 +# define __NR_inotify_add_watch 254 +# define __NR_inotify_rm_watch 255 + +#else +# error "Unsupported architecture!" +#endif + +static inline int inotify_init (void) +{ + return syscall (__NR_inotify_init); +} + +static inline int inotify_add_watch (int fd, const char *name, uint32_t mask) +{ + return syscall (__NR_inotify_add_watch, fd, name, mask); +} + +static inline int inotify_rm_watch (int fd, uint32_t wd) +{ + return syscall (__NR_inotify_rm_watch, fd, wd); +} + + +#endif /* _LINUX_INOTIFY_H */ diff --git a/dep/efsw/src/efsw/platform/platformimpl.hpp b/dep/efsw/src/efsw/platform/platformimpl.hpp new file mode 100644 index 00000000000..86a74eee0c8 --- /dev/null +++ b/dep/efsw/src/efsw/platform/platformimpl.hpp @@ -0,0 +1,20 @@ +#ifndef EFSW_PLATFORMIMPL_HPP +#define EFSW_PLATFORMIMPL_HPP + +#include <efsw/base.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + #include <efsw/platform/posix/ThreadImpl.hpp> + #include <efsw/platform/posix/MutexImpl.hpp> + #include <efsw/platform/posix/SystemImpl.hpp> + #include <efsw/platform/posix/FileSystemImpl.hpp> +#elif EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + #include <efsw/platform/win/ThreadImpl.hpp> + #include <efsw/platform/win/MutexImpl.hpp> + #include <efsw/platform/win/SystemImpl.hpp> + #include <efsw/platform/win/FileSystemImpl.hpp> +#else + #error Thread, Mutex, and System not implemented for this platform. +#endif + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp new file mode 100644 index 00000000000..e061b25d56b --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp @@ -0,0 +1,144 @@ +#include <efsw/platform/posix/FileSystemImpl.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +#include <efsw/FileInfo.hpp> +#include <efsw/FileSystem.hpp> +#include <dirent.h> +#include <cstring> + +#ifndef _DARWIN_FEATURE_64_BIT_INODE +#define _DARWIN_FEATURE_64_BIT_INODE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#include <sys/stat.h> +#include <cstdlib> + +#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID +#include <sys/vfs.h> +#elif EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_IOS +#include <sys/param.h> +#include <sys/mount.h> +#endif + +/** Remote file systems codes */ +#define S_MAGIC_AFS 0x5346414F +#define S_MAGIC_AUFS 0x61756673 +#define S_MAGIC_CEPH 0x00C36400 +#define S_MAGIC_CIFS 0xFF534D42 +#define S_MAGIC_CODA 0x73757245 +#define S_MAGIC_FHGFS 0x19830326 +#define S_MAGIC_FUSEBLK 0x65735546 +#define S_MAGIC_FUSECTL 0x65735543 +#define S_MAGIC_GFS 0x01161970 +#define S_MAGIC_GPFS 0x47504653 +#define S_MAGIC_KAFS 0x6B414653 +#define S_MAGIC_LUSTRE 0x0BD00BD0 +#define S_MAGIC_NCP 0x564C +#define S_MAGIC_NFS 0x6969 +#define S_MAGIC_NFSD 0x6E667364 +#define S_MAGIC_OCFS2 0x7461636F +#define S_MAGIC_PANFS 0xAAD7AAEA +#define S_MAGIC_PIPEFS 0x50495045 +#define S_MAGIC_SMB 0x517B +#define S_MAGIC_SNFS 0xBEEFDEAD +#define S_MAGIC_VMHGFS 0xBACBACBC +#define S_MAGIC_VXFS 0xA501FCF5 + +namespace efsw { namespace Platform { + +FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) +{ + FileInfoMap files; + + DIR *dp; + struct dirent *dirp; + + if( ( dp = opendir( path.c_str() ) ) == NULL) + return files; + + while ( ( dirp = readdir(dp) ) != NULL) + { + if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 ) + { + std::string name( dirp->d_name ); + std::string fpath( path + name ); + + files[ name ] = FileInfo( fpath ); + } + } + + closedir(dp); + + return files; +} + +char FileSystem::getOSSlash() +{ + return '/'; +} + +bool FileSystem::isDirectory( const std::string& path ) +{ + struct stat st; + int res = stat( path.c_str(), &st ); + + if ( 0 == res ) + { + return static_cast<bool>( S_ISDIR(st.st_mode) ); + } + + return false; +} + +bool FileSystem::isRemoteFS( const std::string& directory ) +{ +#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID || EFSW_OS == EFSW_OS_IOS + struct statfs statfsbuf; + + statfs( directory.c_str(), &statfsbuf ); + + switch ( statfsbuf.f_type | 0UL ) + { + case S_MAGIC_AFS: /* 0x5346414F remote */ + case S_MAGIC_AUFS: /* 0x61756673 remote */ + case S_MAGIC_CEPH: /* 0x00C36400 remote */ + case S_MAGIC_CIFS: /* 0xFF534D42 remote */ + case S_MAGIC_CODA: /* 0x73757245 remote */ + case S_MAGIC_FHGFS: /* 0x19830326 remote */ + case S_MAGIC_FUSEBLK: /* 0x65735546 remote */ + case S_MAGIC_FUSECTL: /* 0x65735543 remote */ + case S_MAGIC_GFS: /* 0x01161970 remote */ + case S_MAGIC_GPFS: /* 0x47504653 remote */ + case S_MAGIC_KAFS: /* 0x6B414653 remote */ + case S_MAGIC_LUSTRE: /* 0x0BD00BD0 remote */ + case S_MAGIC_NCP: /* 0x564C remote */ + case S_MAGIC_NFS: /* 0x6969 remote */ + case S_MAGIC_NFSD: /* 0x6E667364 remote */ + case S_MAGIC_OCFS2: /* 0x7461636F remote */ + case S_MAGIC_PANFS: /* 0xAAD7AAEA remote */ + case S_MAGIC_PIPEFS: /* 0x50495045 remote */ + case S_MAGIC_SMB: /* 0x517B remote */ + case S_MAGIC_SNFS: /* 0xBEEFDEAD remote */ + case S_MAGIC_VMHGFS: /* 0xBACBACBC remote */ + case S_MAGIC_VXFS: /* 0xA501FCF5 remote */ + { + return true; + } + default: + { + return false; + } + } +#endif + + return false; +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp new file mode 100644 index 00000000000..865b3f8dfdf --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp @@ -0,0 +1,27 @@ +#ifndef EFSW_FILESYSTEMIMPLPOSIX_HPP +#define EFSW_FILESYSTEMIMPLPOSIX_HPP + +#include <efsw/base.hpp> +#include <efsw/FileInfo.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +namespace efsw { namespace Platform { + +class FileSystem +{ + public: + static FileInfoMap filesInfoFromPath( const std::string& path ); + + static char getOSSlash(); + + static bool isDirectory( const std::string& path ); + + static bool isRemoteFS( const std::string& directory ); +}; + +}} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp new file mode 100644 index 00000000000..6f2af5abc61 --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp @@ -0,0 +1,32 @@ +#include <efsw/platform/posix/MutexImpl.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +namespace efsw { namespace Platform { + +MutexImpl::MutexImpl() +{ + pthread_mutexattr_t attributes; + pthread_mutexattr_init(&attributes); + pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mMutex, &attributes); +} + +MutexImpl::~MutexImpl() +{ + pthread_mutex_destroy(&mMutex); +} + +void MutexImpl::lock() +{ + pthread_mutex_lock(&mMutex); +} + +void MutexImpl::unlock() +{ + pthread_mutex_unlock(&mMutex); +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp new file mode 100644 index 00000000000..d51eecb16aa --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp @@ -0,0 +1,31 @@ +#ifndef EFSW_MUTEXIMPLPOSIX_HPP +#define EFSW_MUTEXIMPLPOSIX_HPP + +#include <efsw/base.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +#include <pthread.h> + +namespace efsw { namespace Platform { + +class MutexImpl +{ + public: + MutexImpl(); + + ~MutexImpl(); + + void lock(); + + void unlock(); + private: + pthread_mutex_t mMutex; +}; + +}} + +#endif + +#endif + diff --git a/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp new file mode 100644 index 00000000000..22e37095afd --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp @@ -0,0 +1,180 @@ +#include <efsw/platform/posix/SystemImpl.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +#include <cstdio> +#include <pthread.h> +#include <sys/time.h> +#include <limits.h> +#include <sys/resource.h> + +#include <efsw/FileSystem.hpp> +#include <efsw/Debug.hpp> + +#if EFSW_OS == EFSW_OS_MACOSX + #include <CoreFoundation/CoreFoundation.h> +#elif EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_ANDROID + #include <libgen.h> + #include <unistd.h> +#elif EFSW_OS == EFSW_OS_HAIKU + #include <kernel/OS.h> + #include <kernel/image.h> +#elif EFSW_OS == EFSW_OS_SOLARIS + #include <stdlib.h> +#elif EFSW_OS == EFSW_OS_BSD + #include <sys/sysctl.h> +#endif + +namespace efsw { namespace Platform { + +void System::sleep( const unsigned long& ms ) +{ + // usleep( static_cast<unsigned long>( ms * 1000 ) ); + + // usleep is not reliable enough (it might block the + // whole process instead of just the current thread) + // so we must use pthread_cond_timedwait instead + + // this implementation is inspired from Qt + // and taken from SFML + + unsigned long long usecs = ms * 1000; + + // get the current time + timeval tv; + gettimeofday(&tv, NULL); + + // construct the time limit (current time + time to wait) + timespec ti; + ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000; + ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000); + ti.tv_nsec %= 1000000000; + + // create a mutex and thread condition + pthread_mutex_t mutex; + pthread_mutex_init(&mutex, 0); + pthread_cond_t condition; + pthread_cond_init(&condition, 0); + + // wait... + pthread_mutex_lock(&mutex); + pthread_cond_timedwait(&condition, &mutex, &ti); + pthread_mutex_unlock(&mutex); + + // destroy the mutex and condition + pthread_cond_destroy(&condition); +} + +std::string System::getProcessPath() +{ +#if EFSW_OS == EFSW_OS_MACOSX + char exe_file[FILENAME_MAX + 1]; + + CFBundleRef mainBundle = CFBundleGetMainBundle(); + + if (mainBundle) + { + CFURLRef mainURL = CFBundleCopyBundleURL(mainBundle); + + if (mainURL) + { + int ok = CFURLGetFileSystemRepresentation ( mainURL, (Boolean) true, (UInt8*)exe_file, FILENAME_MAX ); + + if (ok) + { + return std::string(exe_file) + "/"; + } + } + } + + return "./"; +#elif EFSW_OS == EFSW_OS_LINUX + char exe_file[FILENAME_MAX + 1]; + + int size; + + size = readlink("/proc/self/exe", exe_file, FILENAME_MAX); + + if (size < 0) + { + return std::string( "./" ); + } + else + { + exe_file[size] = '\0'; + return std::string( dirname( exe_file ) ) + "/"; + } + +#elif EFSW_OS == EFSW_OS_BSD + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + char buf[1024]; + size_t cb = sizeof(buf); + sysctl(mib, 4, buf, &cb, NULL, 0); + + return FileSystem::pathRemoveFileName( std::string( buf ) ); + +#elif EFSW_OS == EFSW_OS_SOLARIS + return FileSystem::pathRemoveFileName( std::string( getexecname() ) ); + +#elif EFSW_OS == EFSW_OS_HAIKU + image_info info; + int32 cookie = 0; + + while ( B_OK == get_next_image_info( 0, &cookie, &info ) ) + { + if ( info.type == B_APP_IMAGE ) + break; + } + + return FileSystem::pathRemoveFileName( std::string( info.name ) ); + +#elif EFSW_OS == EFSW_OS_ANDROID + return "/sdcard/"; + +#else + #warning getProcessPath() not implemented on this platform. ( will return "./" ) + return "./"; + +#endif +} + +void System::maxFD() +{ + static bool maxed = false; + + if ( !maxed ) + { + struct rlimit limit; + getrlimit( RLIMIT_NOFILE, &limit ); + limit.rlim_cur = limit.rlim_max; + setrlimit( RLIMIT_NOFILE, &limit ); + + getrlimit( RLIMIT_NOFILE, &limit ); + + efDEBUG( "File descriptor limit %ld\n", limit.rlim_cur ); + + maxed = true; + } +} + +Uint64 System::getMaxFD() +{ + static rlim_t max_fd = 0; + + if ( max_fd == 0 ) + { + struct rlimit limit; + getrlimit( RLIMIT_NOFILE, &limit ); + max_fd = limit.rlim_cur; + } + + return max_fd; +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp new file mode 100644 index 00000000000..34734104467 --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp @@ -0,0 +1,26 @@ +#ifndef EFSW_SYSTEMIMPLPOSIX_HPP +#define EFSW_SYSTEMIMPLPOSIX_HPP + +#include <efsw/base.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +namespace efsw { namespace Platform { + +class System +{ + public: + static void sleep( const unsigned long& ms ); + + static std::string getProcessPath(); + + static void maxFD(); + + static Uint64 getMaxFD(); +}; + +}} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp new file mode 100644 index 00000000000..2d3671db9b8 --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp @@ -0,0 +1,68 @@ +#include <efsw/platform/posix/ThreadImpl.hpp> +#include <efsw/Thread.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +#include <cassert> +#include <iostream> +#include <efsw/Debug.hpp> + +namespace efsw { namespace Platform { + +ThreadImpl::ThreadImpl( Thread * owner ) : + mIsActive(false) +{ + mIsActive = pthread_create( &mThread, NULL, &ThreadImpl::entryPoint, owner ) == 0; + + if ( !mIsActive ) + { + efDEBUG( "Failed to create thread\n" ); + } +} + +void ThreadImpl::wait() +{ + // Wait for the thread to finish, no timeout + if ( mIsActive ) + { + assert( pthread_equal( pthread_self(), mThread ) == 0 ); + + pthread_join( mThread, NULL ); + + mIsActive = false; // Reset the thread state + } +} + +void ThreadImpl::terminate() +{ + if ( mIsActive ) + { + #if !defined( __ANDROID__ ) && !defined( ANDROID ) + pthread_cancel( mThread ); + #else + pthread_kill( mThread , SIGUSR1 ); + #endif + + mIsActive = false; + } +} + +void * ThreadImpl::entryPoint( void * userData ) +{ + // The Thread instance is stored in the user data + Thread * owner = static_cast<Thread*>( userData ); + + // Tell the thread to handle cancel requests immediatly + #ifdef PTHREAD_CANCEL_ASYNCHRONOUS + pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); + #endif + + // Forward to the owner + owner->run(); + + return NULL; +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp new file mode 100644 index 00000000000..be6dc1b3e58 --- /dev/null +++ b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp @@ -0,0 +1,35 @@ +#ifndef EFSW_THREADIMPLPOSIX_HPP +#define EFSW_THREADIMPLPOSIX_HPP + +#include <efsw/base.hpp> + +#if defined( EFSW_PLATFORM_POSIX ) + +#include <pthread.h> + +namespace efsw { + +class Thread; + +namespace Platform { + +class ThreadImpl +{ + public: + ThreadImpl( Thread * owner ); + + void wait(); + + void terminate(); + protected: + static void * entryPoint( void* userData ); + + pthread_t mThread; + bool mIsActive; +}; + +}} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp new file mode 100644 index 00000000000..376a474e662 --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp @@ -0,0 +1,89 @@ +#include <efsw/platform/win/FileSystemImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#ifndef EFSW_COMPILER_MSVC +#include <dirent.h> +#endif + +namespace efsw { namespace Platform { + +FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) +{ + FileInfoMap files; + + String tpath( path ); + + if ( tpath[ tpath.size() - 1 ] == '/' || tpath[ tpath.size() - 1 ] == '\\' ) + { + tpath += "*"; + } + else + { + tpath += "\\*"; + } + + WIN32_FIND_DATAW findFileData; + HANDLE hFind = FindFirstFileW( (LPCWSTR)tpath.toWideString().c_str(), &findFileData ); + + if( hFind != INVALID_HANDLE_VALUE ) + { + std::string name( String( findFileData.cFileName ).toUtf8() ); + std::string fpath( path + name ); + + if ( name != "." && name != ".." ) + { + files[ name ] = FileInfo( fpath ); + } + + while( FindNextFileW( hFind, &findFileData ) ) + { + name = String( findFileData.cFileName ).toUtf8(); + fpath = path + name; + + if ( name != "." && name != ".." ) + { + files[ name ] = FileInfo( fpath ); + } + } + + FindClose( hFind ); + } + + return files; +} + +char FileSystem::getOSSlash() +{ + return '\\'; +} + +bool FileSystem::isDirectory( const std::string& path ) +{ + return 0 != ( GetFileAttributesW( String( path ).toWideString().c_str() ) & FILE_ATTRIBUTE_DIRECTORY ); +} + +bool FileSystem::isRemoteFS( const std::string& directory ) +{ + if ((directory[0] == '\\' || directory[0] == '/') && + (directory[1] == '\\' || directory[1] == '/')) + { + return true; + } + + if ( directory.size() >= 3 ) + { + return 4 == GetDriveTypeA( directory.substr( 0, 3 ).c_str() ); + } + + return false; +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp new file mode 100644 index 00000000000..597edc4a647 --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp @@ -0,0 +1,28 @@ +#ifndef EFSW_FILESYSTEMIMPLWIN_HPP +#define EFSW_FILESYSTEMIMPLWIN_HPP + +#include <efsw/base.hpp> +#include <efsw/String.hpp> +#include <efsw/FileInfo.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +namespace efsw { namespace Platform { + +class FileSystem +{ + public: + static FileInfoMap filesInfoFromPath( const std::string& path ); + + static char getOSSlash(); + + static bool isDirectory( const std::string& path ); + + static bool isRemoteFS( const std::string& directory ); +}; + +}} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.cpp b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp new file mode 100644 index 00000000000..0c8c36d8b39 --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp @@ -0,0 +1,29 @@ +#include <efsw/platform/win/MutexImpl.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +namespace efsw { namespace Platform { + +MutexImpl::MutexImpl() +{ + InitializeCriticalSection(&mMutex); +} + +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection(&mMutex); +} + +void MutexImpl::lock() +{ + EnterCriticalSection(&mMutex); +} + +void MutexImpl::unlock() +{ + LeaveCriticalSection(&mMutex); +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.hpp b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp new file mode 100644 index 00000000000..da1e20c5fa9 --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp @@ -0,0 +1,34 @@ +#ifndef EFSW_MUTEXIMPLWIN_HPP +#define EFSW_MUTEXIMPLWIN_HPP + +#include <efsw/base.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +namespace efsw { namespace Platform { + +class MutexImpl +{ + public: + MutexImpl(); + + ~MutexImpl(); + + void lock(); + + void unlock(); + private: + CRITICAL_SECTION mMutex; +}; + +}} + +#endif + +#endif + diff --git a/dep/efsw/src/efsw/platform/win/SystemImpl.cpp b/dep/efsw/src/efsw/platform/win/SystemImpl.cpp new file mode 100644 index 00000000000..ddbe1e5c45c --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/SystemImpl.cpp @@ -0,0 +1,50 @@ +#include <efsw/platform/win/SystemImpl.hpp> +#include <efsw/String.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <cstdlib> + +namespace efsw { namespace Platform { + +void System::sleep( const unsigned long& ms ) +{ + ::Sleep( ms ); +} + +std::string System::getProcessPath() +{ + // Get path to executable: + WCHAR szDrive[_MAX_DRIVE]; + WCHAR szDir[_MAX_DIR]; + WCHAR szFilename[_MAX_DIR]; + WCHAR szExt[_MAX_DIR]; + std::wstring dllName( _MAX_DIR, 0 ); + + GetModuleFileNameW(0, &dllName[0], _MAX_PATH); + + #ifdef EFSW_COMPILER_MSVC + _wsplitpath_s( dllName.c_str(), szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFilename, _MAX_DIR, szExt, _MAX_DIR ); + #else + _wsplitpath( dllName.c_str(), szDrive, szDir, szFilename, szExt); + #endif + + return String( szDrive ).toUtf8() + String( szDir ).toUtf8(); +} + +void System::maxFD() +{ +} + +Uint64 System::getMaxFD() +{ // Number of ReadDirectory per thread + return 60; +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/win/SystemImpl.hpp b/dep/efsw/src/efsw/platform/win/SystemImpl.hpp new file mode 100644 index 00000000000..2f785e3565c --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/SystemImpl.hpp @@ -0,0 +1,26 @@ +#ifndef EFSW_SYSTEMIMPLWIN_HPP +#define EFSW_SYSTEMIMPLWIN_HPP + +#include <efsw/base.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +namespace efsw { namespace Platform { + +class System +{ + public: + static void sleep( const unsigned long& ms ); + + static std::string getProcessPath(); + + static void maxFD(); + + static Uint64 getMaxFD(); +}; + +}} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp new file mode 100644 index 00000000000..2fa30f30060 --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp @@ -0,0 +1,56 @@ +#include <efsw/platform/win/ThreadImpl.hpp> +#include <efsw/Thread.hpp> +#include <assert.h> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#include <efsw/Debug.hpp> + +namespace efsw { namespace Platform { + +ThreadImpl::ThreadImpl( Thread *owner ) +{ + mThread = reinterpret_cast<HANDLE>( _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) ); + + if ( !mThread ) + { + efDEBUG( "Failed to create thread\n" ); + } +} + +void ThreadImpl::wait() +{ + // Wait for the thread to finish, no timeout + if ( mThread ) + { + assert( mThreadId != GetCurrentThreadId() ); // A thread cannot wait for itself! + + WaitForSingleObject( mThread, INFINITE ); + } +} + +void ThreadImpl::terminate() +{ + if ( mThread ) + { + TerminateThread( mThread, 0 ); + } +} + +unsigned int __stdcall ThreadImpl::entryPoint( void * userData ) +{ + // The Thread instance is stored in the user data + Thread * owner = static_cast<Thread*>( userData ); + + // Forward to the owner + owner->run(); + + // Optional, but it is cleaner + _endthreadex(0); + + return 0; +} + +}} + +#endif diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp new file mode 100644 index 00000000000..506c659c675 --- /dev/null +++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp @@ -0,0 +1,39 @@ +#ifndef EFSW_THREADIMPLWIN_HPP +#define EFSW_THREADIMPLWIN_HPP + +#include <efsw/base.hpp> + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <process.h> + +namespace efsw { + +class Thread; + +namespace Platform { + +class ThreadImpl +{ + public: + ThreadImpl( Thread * owner ); + + void wait(); + + void terminate(); + protected: + static unsigned int __stdcall entryPoint(void* userData); + + HANDLE mThread; + unsigned int mThreadId; +}; + +}} + +#endif + +#endif diff --git a/dep/efsw/src/efsw/sophist.h b/dep/efsw/src/efsw/sophist.h new file mode 100644 index 00000000000..3a645040e2f --- /dev/null +++ b/dep/efsw/src/efsw/sophist.h @@ -0,0 +1,147 @@ +/* sophist.h - 0.3 - public domain - Sean Barrett 2010 +** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net +** Sophist provides portable types; you typedef/#define them to your own names +** +** defines: +** - SOPHIST_endian - either SOPHIST_little_endian or SOPHIST_big_endian +** - SOPHIST_has_64 - either 0 or 1; if 0, int64 types aren't defined +** - SOPHIST_pointer64 - either 0 or 1; if 1, pointer is 64-bit +** +** - SOPHIST_intptr, SOPHIST_uintptr - integer same size as pointer +** - SOPHIST_int8, SOPHIST_uint8, SOPHIST_int16, SOPHIST_uint16 +** - SOPHIST_int32, SOPHIST_uint32, SOPHIST_int64, SOPHIST_uint64 +** - SOPHIST_int64_constant(number) - macros for creating 64-bit +** - SOPHIST_uint64_constant(number) integer constants +** - SOPHIST_printf_format64 - string for printf format for int64 +*/ + +#ifndef __INCLUDE_SOPHIST_H__ +#define __INCLUDE_SOPHIST_H__ + +#define SOPHIST_compiletime_assert(name,val) \ + typedef int SOPHIST__assert##name[(val) ? 1 : -1] + +/* define a couple synthetic rules to make code more readable */ +#if (defined(__sparc__) || defined(__sparc)) && \ + (defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)) + #define SOPHIST_sparc64 +#endif + +#if (defined(linux) || defined(__linux__)) && \ + (defined(__alpha)||defined(__alpha__)||defined(__x86_64__)||defined(_M_X64)) + #define SOPHIST_linux64 +#endif + +/* basic types */ +typedef signed char SOPHIST_int8; +typedef unsigned char SOPHIST_uint8; + +typedef signed short SOPHIST_int16; +typedef unsigned short SOPHIST_uint16; + +#ifdef __palmos__ + typedef signed long SOPHIST_int32; + typedef unsigned long SOPHIST_uint32; +#else + typedef signed int SOPHIST_int32; + typedef unsigned int SOPHIST_uint32; +#endif + +#ifndef SOPHIST_NO_64 + #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \ + || (defined(__alpha) && defined(__DECC)) + + typedef signed __int64 SOPHIST_int64; + typedef unsigned __int64 SOPHIST_uint64; + #define SOPHIST_has_64 1 + #define SOPHIST_int64_constant(x) (x##i64) + #define SOPHIST_uint64_constant(x) (x##ui64) + #define SOPHIST_printf_format64 "I64" + + #elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64) + + typedef signed long SOPHIST_int64; + typedef unsigned long SOPHIST_uint64; + + #define SOPHIST_has_64 1 + #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x) + #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x) + #define SOPHIST_printf_format64 "l" + + #elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ + || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \ + || defined(sgi) || defined (__sgi) || defined(__sgi__) \ + || defined(_CRAYC) + + typedef signed long long SOPHIST_int64; + typedef unsigned long long SOPHIST_uint64; + + #define SOPHIST_has_64 1 + #define SOPHIST_int64_constant(x) (x##LL) + #define SOPHIST_uint64_constant(x) (x##ULL) + #define SOPHIST_printf_format64 "ll" + #endif +#endif + +#ifndef SOPHIST_has_64 +#define SOPHIST_has_64 0 +#endif + +SOPHIST_compiletime_assert( int8 , sizeof(SOPHIST_int8 ) == 1); +SOPHIST_compiletime_assert(uint16, sizeof(SOPHIST_int16) == 2); +SOPHIST_compiletime_assert( int32, sizeof(SOPHIST_int32 ) == 4); +SOPHIST_compiletime_assert(uint32, sizeof(SOPHIST_uint32) == 4); + +#if SOPHIST_has_64 + SOPHIST_compiletime_assert( int64, sizeof(SOPHIST_int64 ) == 8); + SOPHIST_compiletime_assert(uint64, sizeof(SOPHIST_uint64) == 8); +#endif + +/* determine whether pointers are 64-bit */ + +#if defined(SOPHIST_linux64) || defined(SOPHIST_sparc64) \ + || defined(__osf__) || (defined(_WIN64) && !defined(_XBOX)) \ + || defined(__64BIT__) \ + || defined(__LP64) || defined(__LP64__) || defined(_LP64) \ + || defined(_ADDR64) || defined(_CRAYC) \ + + #define SOPHIST_pointer64 1 + + SOPHIST_compiletime_assert(pointer64, sizeof(void*) == 8); + + typedef SOPHIST_int64 SOPHIST_intptr; + typedef SOPHIST_uint64 SOPHIST_uintptr; +#else + + #define SOPHIST_pointer64 0 + + SOPHIST_compiletime_assert(pointer64, sizeof(void*) <= 4); + + /* do we care about pointers that are only 16-bit? */ + typedef SOPHIST_int32 SOPHIST_intptr; + typedef SOPHIST_uint32 SOPHIST_uintptr; + +#endif + +SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *)); + +/* enumerate known little endian cases; fallback to big-endian */ + +#define SOPHIST_little_endian 1 +#define SOPHIST_big_endian 2 + +#if defined(__386__) || defined(i386) || defined(__i386__) \ + || defined(__X86) || defined(_M_IX86) \ + || defined(_M_X64) || defined(__x86_64__) \ + || defined(alpha) || defined(__alpha) || defined(__alpha__) \ + || defined(_M_ALPHA) \ + || defined(ARM) || defined(_ARM) || defined(__arm__) \ + || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(_WIN32_WCE) || defined(__NT__) \ + || defined(__MIPSEL__) + #define SOPHIST_endian SOPHIST_little_endian +#else + #define SOPHIST_endian SOPHIST_big_endian +#endif + +#endif /* __INCLUDE_SOPHIST_H__ */ diff --git a/dep/efsw/src/test/efsw-test.cpp b/dep/efsw/src/test/efsw-test.cpp new file mode 100644 index 00000000000..a49e3414fcc --- /dev/null +++ b/dep/efsw/src/test/efsw-test.cpp @@ -0,0 +1,151 @@ +#include <efsw/efsw.hpp> +#include <efsw/System.hpp> +#include <efsw/FileSystem.hpp> +#include <signal.h> +#include <iostream> + +bool STOP = false; + +void sigend(int signal) +{ + std::cout << std::endl << "Bye bye" << std::endl; + STOP = true; +} + +/// Processes a file action +class UpdateListener : public efsw::FileWatchListener +{ + public: + UpdateListener() {} + + std::string getActionName( efsw::Action action ) + { + switch ( action ) + { + case efsw::Actions::Add: return "Add"; + case efsw::Actions::Modified: return "Modified"; + case efsw::Actions::Delete: return "Delete"; + case efsw::Actions::Moved: return "Moved"; + default: return "Bad Action"; + } + } + + void handleFileAction( efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "" ) + { + std::cout << "DIR (" << dir + ") FILE (" + ( oldFilename.empty() ? "" : "from file " + oldFilename + " to " ) + filename + ") has event " << getActionName( action ) << std::endl; + } +}; + +efsw::WatchID handleWatchID( efsw::WatchID watchid ) +{ + switch ( watchid ) + { + case efsw::Errors::FileNotFound: + case efsw::Errors::FileRepeated: + case efsw::Errors::FileOutOfScope: + case efsw::Errors::FileRemote: + case efsw::Errors::Unspecified: + { + std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl; + break; + } + default: + { + std::cout << "Added WatchID: " << watchid << std::endl; + } + } + + return watchid; +} + +int main(int argc, char **argv) +{ + signal( SIGABRT , sigend ); + signal( SIGINT , sigend ); + signal( SIGTERM , sigend ); + + std::cout << "Press ^C to exit demo" << std::endl; + + bool commonTest = true; + bool useGeneric = false; + std::string path; + + if ( argc >= 2 ) + { + path = std::string( argv[1] ); + + if ( efsw::FileSystem::isDirectory( path ) ) + { + commonTest = false; + } + + if ( argc >= 3 ) + { + if ( std::string( argv[2] ) == "true" ) + { + useGeneric = true; + } + } + } + + UpdateListener * ul = new UpdateListener(); + + /// create the file watcher object + efsw::FileWatcher fileWatcher( useGeneric ); + + fileWatcher.followSymlinks( false ); + fileWatcher.allowOutOfScopeLinks( false ); + + if ( commonTest ) + { + std::string CurPath( efsw::System::getProcessPath() ); + + std::cout << "CurPath: " << CurPath.c_str() << std::endl; + + /// add a watch to the system + handleWatchID( fileWatcher.addWatch( CurPath + "test", ul, true ) ); + + /// starts watching + fileWatcher.watch(); + + /// adds another watch after started watching... + efsw::System::sleep( 100 ); + + efsw::WatchID watchID = handleWatchID( fileWatcher.addWatch( CurPath + "test2", ul, true ) ); + + /// delete the watch + if ( watchID > 0 ) + { + efsw::System::sleep( 1000 ); + fileWatcher.removeWatch( watchID ); + } + } + else + { + efsw::WatchID err; + + if ( ( err = fileWatcher.addWatch( path, ul, true ) ) > 0 ) + { + fileWatcher.watch(); + + std::cout << "Watching directory: " << path.c_str() << std::endl; + + if ( useGeneric ) + { + std::cout << "Using generic backend watcher" << std::endl; + } + } + else + { + std::cout << "Error trying to watch directory: " << path.c_str() << std::endl; + std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl; + } + } + + while( !STOP ) + { + efsw::System::sleep( 100 ); + } + + return 0; +} diff --git a/dep/g3dlite/CMakeLists.txt b/dep/g3dlite/CMakeLists.txt index f1166c72e6d..4e579951d63 100644 --- a/dep/g3dlite/CMakeLists.txt +++ b/dep/g3dlite/CMakeLists.txt @@ -8,7 +8,6 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - set(g3dlib_STAT_SRCS source/AABox.cpp source/Any.cpp @@ -55,20 +54,18 @@ set(g3dlib_STAT_SRCS source/Vector4.cpp ) -if(WIN32) - include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_SOURCE_DIR}/dep/zlib - ) -else() - include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ) -endif() - add_library(g3dlib STATIC ${g3dlib_STAT_SRCS}) +target_include_directories(g3dlib + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include) + target_link_libraries(g3dlib - ${ZLIB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) + PUBLIC + zlib + threads) + +set_target_properties(g3dlib + PROPERTIES + FOLDER + "dep") diff --git a/dep/gsoap/CMakeLists.txt b/dep/gsoap/CMakeLists.txt index b5fed7809af..bdcadf6e4dc 100644 --- a/dep/gsoap/CMakeLists.txt +++ b/dep/gsoap/CMakeLists.txt @@ -10,17 +10,22 @@ file(GLOB sources *.cpp *.h) -set(gsoap_STAT_SRCS - ${sources} -) +add_library(gsoap STATIC ${sources}) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} -) +set_target_properties(gsoap PROPERTIES LINKER_LANGUAGE CXX) -# Little fix for MSVC / Windows platforms -add_definitions(-D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=0) +target_include_directories(gsoap + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) -add_library(gsoap STATIC ${gsoap_STAT_SRCS}) +set_target_properties(gsoap + PROPERTIES + FOLDER + "dep") -set_target_properties(gsoap PROPERTIES LINKER_LANGUAGE CXX) +if (MSVC) + # Little fix for MSVC / Windows platforms + target_compile_definitions(gsoap + PRIVATE + -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=0) +endif() diff --git a/dep/jemalloc/CMakeLists.txt b/dep/jemalloc/CMakeLists.txt index cf0ac435f0a..6774e5a75d2 100644 --- a/dep/jemalloc/CMakeLists.txt +++ b/dep/jemalloc/CMakeLists.txt @@ -8,54 +8,79 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# We need to generate the jemalloc_def.h header based on platform-specific settings -if (PLATFORM EQUAL 32) - set(JEM_SIZEDEF 2) - set(JEM_TLSMODEL) +if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT NOJEM) + # We need to generate the jemalloc_def.h header based on platform-specific settings + if (PLATFORM EQUAL 32) + set(JEM_SIZEDEF 2) + set(JEM_TLSMODEL) + else() + set(JEM_SIZEDEF 3) + set(JEM_TLSMODEL "__attribute__\(\(tls_model\(\"initial-exec\"\)\)\)") + endif() + + # Create the header, so we can use it + configure_file( + "${CMAKE_SOURCE_DIR}/dep/jemalloc/jemalloc_defs.h.in.cmake" + "${BUILDDIR}/jemalloc_defs.h" + @ONLY + ) + + # Done, let's continue + set(jemalloc_STAT_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/arena.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/atomic.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/base.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/bitmap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_dss.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_mmap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ckh.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ctl.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/extent.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hash.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/huge.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jemalloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mb.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mutex.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/prof.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/quarantine.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/rtree.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/stats.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tcache.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tsd.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/util.c + ) + + add_library(jemalloc STATIC ${jemalloc_STAT_SRC}) + + target_include_directories(jemalloc + PRIVATE + ${BUILDDIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include) + + target_compile_definitions(jemalloc + PUBLIC + -DNO_BUFFERPOOL + PRIVATE + -D_GNU_SOURCE + -D_REENTRAN) + + target_link_libraries(jemalloc + PUBLIC + threads + valgrind) + + set_target_properties(jemalloc + PROPERTIES + FOLDER + "dep") + else() - set(JEM_SIZEDEF 3) - set(JEM_TLSMODEL "__attribute__\(\(tls_model\(\"initial-exec\"\)\)\)") -endif() + # Provide a dummy target for jemalloc which is used when jemalloc + # is disabled or not supported. + add_library(jemalloc INTERFACE) + target_link_libraries(jemalloc + INTERFACE + valgrind) -# Create the header, so we can use it -configure_file( - "${CMAKE_SOURCE_DIR}/dep/jemalloc/jemalloc_defs.h.in.cmake" - "${BUILDDIR}/jemalloc_defs.h" - @ONLY -) - -# Done, let's continue -set(jemalloc_STAT_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/src/arena.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/atomic.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/base.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/bitmap.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_dss.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_mmap.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ckh.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ctl.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/extent.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/hash.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/huge.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/jemalloc.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/mb.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/mutex.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/prof.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/quarantine.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/rtree.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/stats.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/tcache.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/tsd.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/util.c -) - -include_directories( - ${BUILDDIR}/ - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${VALGRIND_INCLUDE_DIR} -) - -add_definitions(-D_GNU_SOURCE -D_REENTRANT) - -add_library(jemalloc STATIC ${jemalloc_STAT_SRC}) +endif() diff --git a/dep/zmqpp/CMakeLists.txt b/dep/mysql/CMakeLists.txt index 24b1d08c265..472535b0356 100644 --- a/dep/zmqpp/CMakeLists.txt +++ b/dep/mysql/CMakeLists.txt @@ -8,24 +8,15 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources_zmqpp zmqpp/*.cpp zmqpp/*.hpp zmqpp/*.h) - -set(zmqpp_STAT_SRCS - ${sources_zmqpp} -) - -include_directories(${ZMQ_INCLUDE_DIR}) - -add_library(zmqpp STATIC - ${zmqpp_STAT_SRCS} -) - -if (WIN32) - add_definitions(-DBUILD_VERSION=\\"3.2.0\\") -else() - add_definitions(-DBUILD_VERSION='"3.2.0"') +if (NOT MYSQL_FOUND) + message(FATAL_ERROR "MySQL wasn't found on your system but it's required to build the servers!") endif() -add_definitions(-DBUILD_VERSION_MAJOR=3) -add_definitions(-DBUILD_VERSION_MINOR=2) -add_definitions(-DBUILD_VERSION_REVISION=0) +add_library(mysql STATIC IMPORTED GLOBAL) + +set_target_properties(mysql + PROPERTIES + IMPORTED_LOCATION + "${MYSQL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${MYSQL_INCLUDE_DIR}") diff --git a/dep/openssl/CMakeLists.txt b/dep/openssl/CMakeLists.txt new file mode 100644 index 00000000000..98561b2a0ed --- /dev/null +++ b/dep/openssl/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +# basic packagesearching and setup +# (further support will be needed, this is a preliminary release!) +set(OPENSSL_EXPECTED_VERSION 1.0.0) + +find_package(OpenSSL REQUIRED) + +add_library(openssl INTERFACE) + +target_link_libraries(openssl + INTERFACE + ${OPENSSL_LIBRARIES}) + +target_include_directories(openssl + INTERFACE + ${OPENSSL_INCLUDE_DIR}) diff --git a/src/server/ipc/CMakeLists.txt b/dep/process/CMakeLists.txt index ca29ebe61b3..5a51917a00c 100644 --- a/src/server/ipc/CMakeLists.txt +++ b/dep/process/CMakeLists.txt @@ -8,20 +8,12 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -find_package(ZMQ REQUIRED) +add_library(process INTERFACE) -file(GLOB_RECURSE sources_ipc *.cpp *.h) +target_include_directories(process + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}) -set(ipc_SRCS - ${sources_ipc} -) - -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/server/shared - ${ZMQ_INCLUDE_DIR} -) - -add_library(ipc STATIC ${ipc_SRCS}) +target_link_libraries(process + INTERFACE + boost) diff --git a/dep/rapidjson/CMakeLists.txt b/dep/rapidjson/CMakeLists.txt new file mode 100644 index 00000000000..de1466a41a6 --- /dev/null +++ b/dep/rapidjson/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library(rapidjson INTERFACE) + +target_include_directories(rapidjson + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}) + +target_compile_definitions(rapidjson + INTERFACE + -DRAPIDJSON_HAS_STDSTRING + -DRAPIDJSON_SSE2) diff --git a/dep/rapidjson/rapidjson/allocators.h b/dep/rapidjson/rapidjson/allocators.h new file mode 100644 index 00000000000..d74a67155b4 --- /dev/null +++ b/dep/rapidjson/rapidjson/allocators.h @@ -0,0 +1,261 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return std::malloc(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + std::free(originalPtr); + return NULL; + } + return std::realloc(originalPtr, newSize); + } + static void Free(void *ptr) { std::free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template <typename BaseAllocator = CrtAllocator> +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer); + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + RAPIDJSON_DELETE(ownBaseAllocator_); + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while (chunkHead_ && chunkHead_ != userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + if (chunkHead_ && chunkHead_ == userBuffer_) + chunkHead_->size = 0; // Clear user buffer + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); + + void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + if (newSize == 0) + return NULL; + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { + size_t increment = static_cast<size_t>(newSize - originalSize); + increment = RAPIDJSON_ALIGN(increment); + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + void* newBuffer = Malloc(newSize); + RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) { (void)ptr; } // Do nothing + +private: + //! Copy constructor is not permitted. + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; + //! Copy assignment operator is not permitted. + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; + + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + */ + void AddChunk(size_t capacity) { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); + ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity)); + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + void *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/dep/rapidjson/rapidjson/document.h b/dep/rapidjson/rapidjson/document.h new file mode 100644 index 00000000000..c6acbd907ab --- /dev/null +++ b/dep/rapidjson/rapidjson/document.h @@ -0,0 +1,2014 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include <new> // placement new + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include <string> +#endif // RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include <iterator> // std::iterator, std::random_access_iterator_tag +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include <utility> // std::move +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template <typename Encoding, typename Allocator> +class GenericValue; + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template <typename Encoding, typename Allocator> +struct GenericMember { + GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) + GenericValue<Encoding, Allocator> value; //!< value of member. +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ <iterator> header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator + : public std::iterator<std::random_access_iterator_tag + , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> { + + friend class GenericValue<Encoding,Allocator>; + template <bool, typename, typename> friend class GenericMemberIterator; + + typedef GenericMember<Encoding,Allocator> PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } + bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } + bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } + bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } + bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } + bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template <bool Const, typename Encoding, typename Allocator> +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template <typename Encoding, typename Allocator> +struct GenericMemberIterator<false,Encoding,Allocator> { + //! use plain pointer as iterator type + typedef GenericMember<Encoding,Allocator>* Iterator; +}; +//! const GenericMemberIterator +template <typename Encoding, typename Allocator> +struct GenericMemberIterator<true,Encoding,Allocator> { + //! use plain const pointer as iterator type + typedef const GenericMember<Encoding,Allocator>* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template<typename CharType> +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ + template<SizeType N> + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } + + //! Create constant string reference from pointer and length + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + //! Disallow copy-assignment + GenericStringRef operator=(const GenericStringRef&); + //! Disallow construction from non-const array + template<SizeType N> + GenericStringRef(CharType (&str)[N]) /* = delete */; +}; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str) { + return GenericStringRef<CharType>(str, internal::StrLen(str)); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) { + return GenericStringRef<CharType>(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) { + return GenericStringRef<CharType>(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template <typename T, typename Encoding = void, typename Allocator = void> +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type> + : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember<Encoding, Allocator> Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself. + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) { + rhs.flags_ = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { + static const unsigned defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + flags_ = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template< typename SourceAllocator > + GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator); + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template <typename T> + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_(), flags_(b ? kTrueFlag : kFalseFlag) { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value)); + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) { + data_.n.i64 = i; + if (i >= 0) + flags_ |= kUintFlag | kUint64Flag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) { + data_.n.u64 = u; + if (!(u & 0x80000000)) + flags_ |= kIntFlag | kInt64Flag; + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) { + data_.n.i64 = i64; + if (i64 >= 0) { + flags_ |= kNumberUint64Flag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + flags_ |= kUintFlag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) { + data_.n.u64 = u64; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + flags_ |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + flags_ |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(flags_) { + case kArrayFlag: + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(data_.a.elements); + break; + + case kObjectFlag: + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(data_.o.members); + break; + + case kCopyStringFlag: + Allocator::Free(const_cast<Ch*>(data_.s.str)); + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template <typename SourceAllocator> + GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT((void*)this != (void const*)&rhs); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template <typename SourceAllocator> + bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const { + typedef GenericValue<Encoding, SourceAllocator> RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: // kTrueType, kFalseType, kNullType + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template <typename SourceAllocator> + bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); } + bool IsNull() const { return flags_ == kNullFlag; } + bool IsFalse() const { return flags_ == kFalseFlag; } + bool IsTrue() const { return flags_ == kTrueFlag; } + bool IsBool() const { return (flags_ & kBoolFlag) != 0; } + bool IsObject() const { return flags_ == kObjectFlag; } + bool IsArray() const { return flags_ == kArrayFlag; } + bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } + bool IsInt() const { return (flags_ & kIntFlag) != 0; } + bool IsUint() const { return (flags_ & kUintFlag) != 0; } + bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } + bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } + bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } + bool IsString() const { return (flags_ & kStringFlag) != 0; } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template <typename SourceAllocator> + GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + static GenericValue NullValue; + return NullValue; + } + } + template <typename SourceAllocator> + const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template <typename SourceAllocator> + bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template <typename SourceAllocator> + MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); } + ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + + Object& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); + } + } + o.members[o.size].name.RawAssign(name); + o.members[o.size].value.RawAssign(value); + o.size++; + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + + MemberIterator last(data_.o.members + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) { + // Move the last one to this place + *m = *last; + } + else { + // Only one left, just destroy + m->~Member(); + } + --data_.o.size; + return m; + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + + MemberIterator pos = MemberBegin() + (first - MemberBegin()); + for (MemberIterator itr = pos; itr != last; ++itr) + itr->~Member(); + std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member)); + data_.o.size -= (last - first); + return pos; + } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + for (SizeType i = 0; i < data_.a.size; ++i) + data_.a.elements[i].~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return data_.a.elements[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + data_.a.elements[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack<StringRefType>(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + data_.a.elements[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(data_.a.elements != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(pos, last, (End() - last) * sizeof(GenericValue)); + data_.a.size -= (last - first); + return pos; + } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; } + + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } +#endif + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template <typename Handler> + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (!handler.StartObject()) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) + return false; + if (!m->value.Accept(handler)) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (!handler.StartArray()) + return false; + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + if (!v->Accept(handler)) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else if (IsUint64()) return handler.Uint64(data_.n.u64); + else return handler.Double(data_.n.d); + } + } + +private: + template <typename, typename> friend class GenericValue; + template <typename, typename, typename> friend class GenericDocument; + + enum { + kBoolFlag = 0x100, + kNumberFlag = 0x200, + kIntFlag = 0x400, + kUintFlag = 0x800, + kInt64Flag = 0x1000, + kUint64Flag = 0x2000, + kDoubleFlag = 0x4000, + kStringFlag = 0x100000, + kCopyFlag = 0x200000, + kInlineStrFlag = 0x400000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct String { + const Ch* str; + SizeType length; + unsigned hashcode; //!< reserved + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode + // inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); } + inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct Object { + Member* members; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct Array { + GenericValue* elements; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + Object o; + Array a; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + flags_ = kArrayFlag; + if (count) { + data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); + std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + } + else + data_.a.elements = NULL; + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + flags_ = kObjectFlag; + if (count) { + data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); + std::memcpy(data_.o.members, members, count * sizeof(Member)); + } + else + data_.o.members = NULL; + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = NULL; + if(ShortString::Usable(s.length)) { + flags_ = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + flags_ = kCopyStringFlag; + data_.s.length = s.length; + str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch)); + data_.s.str = str; + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + flags_ = rhs.flags_; + rhs.flags_ = kNullFlag; + } + + template <typename SourceAllocator> + bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; + unsigned flags_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue<UTF8<> > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator> +class GenericDocument : public GenericValue<Encoding, Allocator> { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::move(rhs)), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward<ValueType>(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags, typename SourceEncoding, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + ValueType::SetNull(); // Remove existing root if exist + GenericReader<SourceEncoding, Encoding, StackAllocator> reader(&stack_.GetAllocator()); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse<parseFlags>(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13. + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<parseFlags, Encoding, InputStream>(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags> + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream<Encoding> s(str); + return ParseStream<parseFlags | kParseInsituFlag>(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu<kParseDefaultFlags>(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream<SourceEncoding> s(str); + return ParseStream<parseFlags, SourceEncoding>(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template <unsigned parseFlags> + GenericDocument& Parse(const Ch* str) { + return Parse<parseFlags, Encoding>(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse<kParseDefaultFlags>(str); + } + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { return *allocator_; } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + template <typename,typename,typename> friend class GenericReader; // for parsing + template <typename, typename> friend class GenericValue; // for deep copying + + // Implementation of Handler + bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount); + stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop<ValueType>(elementCount); + stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop<ValueType>(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack<StackAllocator> stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument<UTF8<> > Document; + +// defined here due to the dependency on GenericDocument +template <typename Encoding, typename Allocator> +template <typename SourceAllocator> +inline +GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator) +{ + switch (rhs.GetType()) { + case kObjectType: + case kArrayType: { // perform deep copy via SAX Handler + GenericDocument<Encoding,Allocator> d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop<GenericValue>(1)); + } + break; + case kStringType: + if (rhs.flags_ == kConstStringFlag) { + flags_ = rhs.flags_; + data_ = *reinterpret_cast<const Data*>(&rhs.data_); + } else { + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + } + break; + default: // kNumberType, kTrueType, kFalseType, kNullType + flags_ = rhs.flags_; + data_ = *reinterpret_cast<const Data*>(&rhs.data_); + } +} + +RAPIDJSON_NAMESPACE_END + +#if defined(_MSC_VER) || defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/dep/rapidjson/rapidjson/encodedstream.h b/dep/rapidjson/rapidjson/encodedstream.h new file mode 100644 index 00000000000..7c8863fee2f --- /dev/null +++ b/dep/rapidjson/rapidjson/encodedstream.h @@ -0,0 +1,261 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template <typename Encoding, typename InputByteStream> +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template <typename Encoding, typename OutputByteStream> +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); } + Ch Take() { RAPIDJSON_ASSERT(false); } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template <typename CharType, typename InputByteStream> +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = (const unsigned char *)is_->Peek4(); + if (!c) + return; + + unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam InputByteStream type of output byte stream to be wrapped. +*/ +template <typename CharType, typename OutputByteStream> +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); } + Ch Take() { RAPIDJSON_ASSERT(false); } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/dep/rapidjson/rapidjson/encodings.h b/dep/rapidjson/rapidjson/encodings.h new file mode 100644 index 00000000000..90b46ed325b --- /dev/null +++ b/dep/rapidjson/rapidjson/encodings.h @@ -0,0 +1,625 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template <typename InputByteStream> + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template<typename CharType = char> +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) +#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = (unsigned char)c; + return true; + } + + unsigned char type = GetRange((unsigned char)c); + *codepoint = (0xFF >> type) & (unsigned char)c; + bool result = true; + switch (type) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { +#define COPY() os.Put(c = is.Take()) +#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c; + COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange((unsigned char)c)) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + Ch c = Take(is); + if ((unsigned char)c != 0xEFu) return c; + c = is.Take(); + if ((unsigned char)c != 0xBBu) return c; + c = is.Take(); + if ((unsigned char)c != 0xBFu) return c; + c = is.Take(); + return c; + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return is.Take(); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template<typename CharType = wchar_t> +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + os.Put((v & 0x3FF) | 0xDC00); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = c; + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (c & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (c & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + Ch c; + os.Put(c = is.Take()); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template<typename CharType = wchar_t> +struct UTF16LE : UTF16<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned short)c == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take(); + c |= (unsigned char)is.Take() << 8; + return c; + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFFu); os.Put(0xFEu); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(c & 0xFFu); + os.Put((c >> 8) & 0xFFu); + } +}; + +//! UTF-16 big endian encoding. +template<typename CharType = wchar_t> +struct UTF16BE : UTF16<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned short)c == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take(); + return c; + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFEu); os.Put(0xFFu); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put((c >> 8) & 0xFFu); + os.Put(c & 0xFFu); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template<typename CharType = unsigned> +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template<typename CharType = unsigned> +struct UTF32LE : UTF32<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take(); + c |= (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take() << 16; + c |= (unsigned char)is.Take() << 24; + return c; + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(c & 0xFFu); + os.Put((c >> 8) & 0xFFu); + os.Put((c >> 16) & 0xFFu); + os.Put((c >> 24) & 0xFFu); + } +}; + +//! UTF-32 big endian encoding. +template<typename CharType = unsigned> +struct UTF32BE : UTF32<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take() << 24; + c |= (unsigned char)is.Take() << 16; + c |= (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take(); + return c; + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put((c >> 24) & 0xFFu); + os.Put((c >> 16) & 0xFFu); + os.Put((c >> 8) & 0xFFu); + os.Put(c & 0xFFu); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template<typename CharType = char> +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast<Ch>(codepoint & 0xFF)); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + unsigned char c = static_cast<unsigned char>(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + unsigned char c = is.Take(); + os.Put(c); + return c <= 0x7F; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + Ch c = Take(is); + return c; + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return is.Take(); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template<typename CharType> +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x + + template<typename OutputStream> + RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template <typename InputStream> + RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template <typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template<typename SourceEncoding, typename TargetEncoding> +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +//! Specialization of Transcoder with same source and target encoding. +template<typename Encoding> +struct Transcoder<Encoding, Encoding> { + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(_MSV_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/dep/rapidjson/rapidjson/error/en.h b/dep/rapidjson/rapidjson/error/en.h new file mode 100644 index 00000000000..d5f9caab8e9 --- /dev/null +++ b/dep/rapidjson/rapidjson/error/en.h @@ -0,0 +1,65 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_EN_H__ +#define RAPIDJSON_ERROR_EN_H__ + +#include "error.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: + return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ERROR_EN_H__ diff --git a/dep/rapidjson/rapidjson/error/error.h b/dep/rapidjson/rapidjson/error/error.h new file mode 100644 index 00000000000..f9094fb9594 --- /dev/null +++ b/dep/rapidjson/rapidjson/error/error.h @@ -0,0 +1,146 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_ERROR_H__ +#define RAPIDJSON_ERROR_ERROR_H__ + +#include "../rapidjson.h" + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { + + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Conversion to \c bool, returns \c true, iff !\ref IsError(). + operator bool() const { return !IsError(); } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ERROR_ERROR_H__ diff --git a/dep/rapidjson/rapidjson/filereadstream.h b/dep/rapidjson/rapidjson/filereadstream.h new file mode 100644 index 00000000000..3913eb74b0d --- /dev/null +++ b/dep/rapidjson/rapidjson/filereadstream.h @@ -0,0 +1,88 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "rapidjson.h" +#include <cstdio> + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/dep/rapidjson/rapidjson/filewritestream.h b/dep/rapidjson/rapidjson/filewritestream.h new file mode 100644 index 00000000000..dfb9cbd02a9 --- /dev/null +++ b/dep/rapidjson/rapidjson/filewritestream.h @@ -0,0 +1,91 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "rapidjson.h" +#include <cstdio> + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast<size_t>(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast<size_t>(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_); + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/dep/rapidjson/rapidjson/internal/biginteger.h b/dep/rapidjson/rapidjson/internal/biginteger.h new file mode 100644 index 00000000000..99a30acf613 --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/biginteger.h @@ -0,0 +1,280 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include <intrin.h> // for _umul128 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + BigInteger(const char* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + void AppendDecimal64(const char* begin, const char* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast<unsigned>(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + static uint64_t ParseUint64(const char* begin, const char* end) { + uint64_t r = 0; + for (const char* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); + r = r * 10 + (*p - '0'); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b); + p += k; + *outHigh = static_cast<uint64_t>(p >> 64); + return static_cast<uint64_t>(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast<uint64_t>(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/dep/rapidjson/rapidjson/internal/diyfp.h b/dep/rapidjson/rapidjson/internal/diyfp.h new file mode 100644 index 00000000000..3b6c4238c1f --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/diyfp.h @@ -0,0 +1,247 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include <intrin.h> +#pragma intrinsic(_BitScanReverse64) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +struct DiyFp { + DiyFp() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f); + uint64_t h = static_cast<uint64_t>(p >> 64); + uint64_t l = static_cast<uint64_t>(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, f); + return DiyFp(f << (63 - index), e - (63 - index)); +#elif defined(__GNUC__) && __GNUC__ >= 4 + int s = __builtin_clzll(f); + return DiyFp(f << s, e - s); +#else + DiyFp res = *this; + while (!(res.f & (static_cast<uint64_t>(1) << 63))) { + res.f <<= 1; + res.e--; + } + return res; +#endif + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast<uint64_t>(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast<int>(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast<unsigned>((k >> 3) + 1); + *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + unsigned index = (exp + 348) / 8; + *outExp = -348 + index * 8; + return GetCachedPowerByIndex(index); + } + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/dep/rapidjson/rapidjson/internal/dtoa.h b/dep/rapidjson/rapidjson/internal/dtoa.h new file mode 100644 index 00000000000..2d8d2e46a3f --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/dtoa.h @@ -0,0 +1,217 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d)); + kappa--; + uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast<char>(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast<char>('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast<char>('0' + static_cast<char>(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], length - kk); + buffer[kk] = '.'; + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], length); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + return &buffer[length + offset]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], length - 1); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer) { + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/dep/rapidjson/rapidjson/internal/ieee754.h b/dep/rapidjson/rapidjson/internal/ieee754.h new file mode 100644 index 00000000000..e3f03364c60 --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/ieee754.h @@ -0,0 +1,77 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static unsigned EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return order + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/dep/rapidjson/rapidjson/internal/itoa.h b/dep/rapidjson/rapidjson/internal/itoa.h new file mode 100644 index 00000000000..01a4e7e72d7 --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/itoa.h @@ -0,0 +1,304 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast<char>('0' + static_cast<char>(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + uint32_t u = static_cast<uint32_t>(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast<uint32_t>(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast<uint32_t>(value / kTen8); + const uint32_t v1 = static_cast<uint32_t>(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + if (value >= kTen8) + *buffer++ = cDigitsLut[d4 + 1]; + + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast<char>('0' + static_cast<char>(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast<uint32_t>(value / kTen8); + const uint32_t v1 = static_cast<uint32_t>(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + uint64_t u = static_cast<uint64_t>(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/dep/rapidjson/rapidjson/internal/meta.h b/dep/rapidjson/rapidjson/internal/meta.h new file mode 100644 index 00000000000..5a9aaa42866 --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/meta.h @@ -0,0 +1,181 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif +#if defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include <type_traits> +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template <typename T> struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template <bool Cond> struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType<true> TrueType; +typedef BoolType<false> FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; +template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; +template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; + +template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; +template <> struct AndExprCond<true, true> : TrueType {}; +template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; +template <> struct OrExprCond<false, false> : FalseType {}; + +template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; +template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; +template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; +template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template <typename T> struct AddConst { typedef const T Type; }; +template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; +template <typename T> struct RemoveConst { typedef T Type; }; +template <typename T> struct RemoveConst<const T> { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template <typename T, typename U> struct IsSame : FalseType {}; +template <typename T> struct IsSame<T, T> : TrueType {}; + +template <typename T> struct IsConst : FalseType {}; +template <typename T> struct IsConst<const T> : TrueType {}; + +template <typename CT, typename T> +struct IsMoreConst + : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, + BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; + +template <typename T> struct IsPointer : FalseType {}; +template <typename T> struct IsPointer<T*> : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template <typename B, typename D> struct IsBaseOf + : BoolType< ::std::is_base_of<B,D>::value> {}; + +#else // simplified version adopted from Boost + +template<typename B, typename D> struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template <typename T> + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template <typename B, typename D> struct IsBaseOf + : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; +template <typename T> struct EnableIfCond<false, T> { /* empty */ }; + +template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; +template <typename T> struct DisableIfCond<true, T> { /* empty */ }; + +template <typename Condition, typename T = void> +struct EnableIf : EnableIfCond<Condition::Value, T> {}; + +template <typename Condition, typename T = void> +struct DisableIf : DisableIfCond<Condition::Value, T> {}; + +// SFINAE helpers +struct SfinaeTag {}; +template <typename T> struct RemoveSfinaeTag; +template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + <RAPIDJSON_REMOVEFPTR_(cond), \ + RAPIDJSON_REMOVEFPTR_(returntype)>::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + <RAPIDJSON_REMOVEFPTR_(cond), \ + RAPIDJSON_REMOVEFPTR_(returntype)>::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/dep/rapidjson/rapidjson/internal/pow10.h b/dep/rapidjson/rapidjson/internal/pow10.h new file mode 100644 index 00000000000..02f475d705f --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/dep/rapidjson/rapidjson/internal/stack.h b/dep/rapidjson/rapidjson/internal/stack.h new file mode 100644 index 00000000000..722d569230b --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/stack.h @@ -0,0 +1,179 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template <typename Allocator> +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + RAPIDJSON_ASSERT(stackCapacity > 0); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template<typename T> + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + // Expand the stack if needed + if (stackTop_ + sizeof(T) * count >= stackEnd_) + Expand<T>(count); + + T* ret = reinterpret_cast<T*>(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template<typename T> + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast<T*>(stackTop_); + } + + template<typename T> + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + T* Bottom() { return (T*)stack_; } + + Allocator& GetAllocator() { return *allocator_; } + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } + +private: + template<typename T> + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STACK_H_ diff --git a/dep/rapidjson/rapidjson/internal/strfunc.h b/dep/rapidjson/rapidjson/internal/strfunc.h new file mode 100644 index 00000000000..84405065a27 --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/strfunc.h @@ -0,0 +1,39 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template <typename Ch> +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/dep/rapidjson/rapidjson/internal/strtod.h b/dep/rapidjson/rapidjson/internal/strtod.h new file mode 100644 index 00000000000..ace65f6773f --- /dev/null +++ b/dep/rapidjson/rapidjson/internal/strtod.h @@ -0,0 +1,270 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "../rapidjson.h" +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template <typename T> +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; + + BigInteger bS(bInt); + bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; + + BigInteger hS(1); + hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { + uint64_t significand = 0; + size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < length; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + break; + significand = significand * 10 + (decimals[i] - '0'); + } + + if (i < length && decimals[i] >= '5') // Rounding + significand++; + + size_t remaining = length - i; + const unsigned kUlpShift = 3; + const unsigned kUlp = 1 << kUlpShift; + int error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + const int dExp = (int)decimalPosition - (int)i + exp; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp - 1; + RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); + v = v * kPow10[adjustment]; + if (length + adjustment > 19) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + unsigned precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + unsigned scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + kUlp; + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + error) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - error >= precisionBits || precisionBits >= halfWay + error; +} + +inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { + const BigInteger dInt(decimals, length); + const int dExp = (int)decimalPosition - (int)length + exp; + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result; + if (StrtodFast(d, p, &result)) + return result; + + // Trim leading zeros + while (*decimals == '0' && length > 1) { + length--; + decimals++; + decimalPosition--; + } + + // Trim trailing zeros + while (decimals[length - 1] == '0' && length > 1) { + length--; + decimalPosition--; + exp++; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 780; + if ((int)length > kMaxDecimalDigit) { + int delta = (int(length) - kMaxDecimalDigit); + exp += delta; + decimalPosition -= delta; + length = kMaxDecimalDigit; + } + + // If too small, underflow to zero + if (int(length) + exp < -324) + return 0.0; + + if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, length, decimalPosition, exp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/dep/rapidjson/rapidjson/memorybuffer.h b/dep/rapidjson/rapidjson/memorybuffer.h new file mode 100644 index 00000000000..2484b2185a8 --- /dev/null +++ b/dep/rapidjson/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template <typename Allocator = CrtAllocator> +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push<Ch>() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom<Ch>(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack<Allocator> stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/dep/rapidjson/rapidjson/memorystream.h b/dep/rapidjson/rapidjson/memorystream.h new file mode 100644 index 00000000000..99feae5d7f8 --- /dev/null +++ b/dep/rapidjson/rapidjson/memorystream.h @@ -0,0 +1,61 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } + Ch Take() { return (src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast<size_t>(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/dep/rapidjson/rapidjson/msinttypes/inttypes.h b/dep/rapidjson/rapidjson/msinttypes/inttypes.h new file mode 100644 index 00000000000..18111286bf5 --- /dev/null +++ b/dep/rapidjson/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include <inttypes.h> +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/dep/rapidjson/rapidjson/msinttypes/stdint.h b/dep/rapidjson/rapidjson/msinttypes/stdint.h new file mode 100644 index 00000000000..a26fff4bf45 --- /dev/null +++ b/dep/rapidjson/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include <stdint.h> + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include <wchar.h> +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/dep/rapidjson/rapidjson/prettywriter.h b/dep/rapidjson/rapidjson/prettywriter.h new file mode 100644 index 00000000000..416dd492e34 --- /dev/null +++ b/dep/rapidjson/rapidjson/prettywriter.h @@ -0,0 +1,207 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of ouptut os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> { +public: + typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); + bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndObject(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); + bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndArray(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + Base::os_->Put('\n'); + } + else + Base::os_->Put('\n'); + WriteIndent(); + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, indentChar_, count); + } + + Ch indentChar_; + unsigned indentCharCount_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/dep/rapidjson/rapidjson/rapidjson.h b/dep/rapidjson/rapidjson/rapidjson.h new file mode 100644 index 00000000000..f22130d3cb8 --- /dev/null +++ b/dep/rapidjson/rapidjson/rapidjson.h @@ -0,0 +1,654 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overriden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include <cstdlib> // malloc(), realloc(), free(), size_t +#include <cstring> // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 0 +#define RAPIDJSON_PATCH_VERSION 2 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#ifdef _MSC_VER +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include <stdint.h> +#include <inttypes.h> +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && !defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include <endian.h> +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || defined(_WIN64) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. Currently the default uses 4 bytes + alignment. User can customize by defining the RAPIDJSON_ALIGN function macro., +*/ +#ifndef RAPIDJSON_ALIGN +#if RAPIDJSON_64BIT == 1 +#define RAPIDJSON_ALIGN(x) ((x + 7u) & ~7u) +#else +#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2 optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible + processors. + + To enable these optimizations, two different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + \c RAPIDJSON_SSE42 takes precedence, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include <cassert> +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Adopt from boost +#ifndef RAPIDJSON_STATIC_ASSERT +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +RAPIDJSON_NAMESPACE_BEGIN +template <bool x> struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; +template<int x> struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y + +#if defined(__GNUC__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +//!@endcond + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \ + (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(x) new x +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Allocators and Encodings + +#include "allocators.h" +#include "encodings.h" + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template<typename Stream> +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits<StringStream>. + */ + enum { copyOptimization = 0 }; +}; + +//! Put N copies of a character to a stream. +template<typename Stream, typename Ch> +inline void PutN(Stream& stream, Ch c, size_t n) { + for (size_t i = 0; i < n; i++) + stream.Put(c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template <typename Encoding> +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast<size_t>(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template <typename Encoding> +struct StreamTraits<GenericStringStream<Encoding> > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream<UTF8<> > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template <typename Encoding> +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast<size_t>(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template <typename Encoding> +struct StreamTraits<GenericInsituStringStream<Encoding> > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream<UTF8<> > InsituStringStream; + +/////////////////////////////////////////////////////////////////////////////// +// Type + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/dep/rapidjson/rapidjson/reader.h b/dep/rapidjson/rapidjson/reader.h new file mode 100644 index 00000000000..c5ecf4be595 --- /dev/null +++ b/dep/rapidjson/rapidjson/reader.h @@ -0,0 +1,1452 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "rapidjson.h" +#include "encodings.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include <nmmintrin.h> +#elif defined(RAPIDJSON_SSE2) +#include <emmintrin.h> +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (HasParseError()) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include <stdexcept> // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template<typename Encoding = UTF8<>, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast<Override&>(*this).Default(); } + bool Bool(bool) { return static_cast<Override&>(*this).Default(); } + bool Int(int) { return static_cast<Override&>(*this).Default(); } + bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); } + bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); } + bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); } + bool Double(double) { return static_cast<Override&>(*this).Default(); } + bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); } + bool StartObject() { return static_cast<Override&>(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); } + bool StartArray() { return static_cast<Override&>(*this).Default(); } + bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template<typename Stream, int = StreamTraits<Stream>::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template<typename Stream> +class StreamLocalCopy<Stream, 1> { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template<typename Stream> +class StreamLocalCopy<Stream, 0> { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template<typename InputStream> +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy<InputStream> copy(is); + InputStream& s(copy.s); + + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]); + + for (;; p += 16) { + const __m128i s = _mm_load_si128((const __m128i *)p); + const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + static const char whitespaces[4][17] = { + " ", + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + + const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); + const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); + const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + + for (;; p += 16) { + const __m128i s = _mm_load_si128((const __m128i *)p); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = (unsigned short)~_mm_movemask_epi8(x); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator> +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse<parseFlags>(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespace(is); + + if (is.Peek() == '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespace(is); + + if (is.Peek() != '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse<kParseDefaultFlags>(is, handler); + } + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + // Parse object: { string : value, ... } + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (!handler.StartObject()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespace(is); + + if (is.Peek() == '}') { + is.Take(); + if (!handler.EndObject(0)) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (is.Peek() != '"') + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString<parseFlags>(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespace(is); + + if (is.Take() != ':') + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespace(is); + + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespace(is); + + ++memberCount; + + switch (is.Take()) { + case ',': SkipWhitespace(is); break; + case '}': + if (!handler.EndObject(memberCount)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + } + } + } + + // Parse array: [ value, ... ] + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (!handler.StartArray()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespace(is); + + if (is.Peek() == ']') { + is.Take(); + if (!handler.EndArray(0)) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespace(is); + + switch (is.Take()) { + case ',': SkipWhitespace(is); break; + case ']': + if (!handler.EndArray(elementCount)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + } + } + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') { + if (!handler.Null()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') { + if (!handler.Bool(true)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') { + if (!handler.Bool(false)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template<typename InputStream> + unsigned ParseHex4(InputStream& is) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Take(); + codepoint <<= 4; + codepoint += static_cast<unsigned>(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + } + return codepoint; + } + + template <typename CharType> + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push<Ch>() = c; + ++length_; + } + size_t Length() const { return length_; } + Ch* Pop() { + return stack_.template Pop<Ch>(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack<StackAllocator>& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy<InputStream> copy(is); + InputStream& s(copy.s); + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head; + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream<typename TargetEncoding::Ch> stackStream(stack_); + ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast<SizeType>(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (!success) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + RAPIDJSON_ASSERT(is.Peek() == '\"'); + is.Take(); // Skip '\"' + + for (;;) { + Ch c = is.Peek(); + if (c == '\\') { // Escape + is.Take(); + Ch e = is.Take(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) { + os.Put(escape[(unsigned char)e]); + } + else if (e == 'u') { // Unicode + unsigned codepoint = ParseHex4(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { + // Handle UTF-16 surrogate pair + if (is.Take() != '\\' || is.Take() != 'u') + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + unsigned codepoint2 = ParseHex4(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + } + else if (c == '"') { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1); + else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + else { + if (parseFlags & kParseValidateEncodingFlag ? + !Transcoder<SEncoding, TEncoding>::Validate(is, os) : + !Transcoder<SEncoding, TEncoding>::Transcode(is, os)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + } + } + + template<typename InputStream, bool backup> + class NumberStream; + + template<typename InputStream> + class NumberStream<InputStream, false> { + public: + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template<typename InputStream> + class NumberStream<InputStream, true> : public NumberStream<InputStream, false> { + typedef NumberStream<InputStream, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put((char)Base::is.Peek()); + return Base::is.Take(); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream<char> stackStream; + }; + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy<InputStream> copy(is); + NumberStream<InputStream, (parseFlags & kParseFullPrecisionFlag) != 0> s(*this, copy.s); + + // Parse minus + bool minus = false; + if (s.Peek() == '-') { + minus = true; + s.Take(); + } + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (s.Peek() == '0') { + i = 0; + s.TakePush(); + } + else if (s.Peek() >= '1' && s.Peek() <= '9') { + i = static_cast<unsigned>(s.TakePush() - '0'); + + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 214748364) { // 2^31 = 2147483648 + if (i != 214748364 || s.Peek() > '8') { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 429496729) { // 2^32 - 1 = 4294967295 + if (i != 429496729 || s.Peek() > '5') { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + double d = 0.0; + if (use64bit) { + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808 + if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') { + d = i64; + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615 + if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') { + d = i64; + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (s.Peek() == '.') { + s.Take(); + decimalPosition = s.Length(); + + if (!(s.Peek() >= '0' && s.Peek() <= '9')) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = (double)i64; +#else + // Use double to store significand in 32-bit architecture + d = use64bit ? (double)i64 : (double)i; +#endif + useDouble = true; + } + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (d > 0.0) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (s.Peek() == 'e' || s.Peek() == 'E') { + if (!useDouble) { + d = use64bit ? i64 : i; + useDouble = true; + } + s.Take(); + + bool expMinus = false; + if (s.Peek() == '+') + s.Take(); + else if (s.Peek() == '-') { + s.Take(); + expMinus = true; + } + + if (s.Peek() >= '0' && s.Peek() <= '9') { + exp = s.Take() - '0'; + if (expMinus) { + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp >= 214748364) { // Issue #313: prevent overflow exponent + while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp > maxExp) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(-(int64_t)i64); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(-(int)i); + else + cont = handler.Uint(i); + } + } + if (!cont) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse any JSON value + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull <parseFlags>(is, handler); break; + case 't': ParseTrue <parseFlags>(is, handler); break; + case 'f': ParseFalse <parseFlags>(is, handler); break; + case '"': ParseString<parseFlags>(is, handler); break; + case '{': ParseObject<parseFlags>(is, handler); break; + case '[': ParseArray <parseFlags>(is, handler); break; + default : ParseNumber<parseFlags>(is, handler); + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingStartState = 0, + IterativeParsingFinishState, + IterativeParsingErrorState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, + IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || unsigned(c) < 256) + return (Token)tokenMap[(unsigned char)c]; + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + } + }; // End of G + + return (IterativeParsingState)G[state][token]; + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template <unsigned parseFlags, typename InputStream, typename Handler> + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push<SizeType>(1) = n; + // Initialize and push the member/element count. + *stack_.template Push<SizeType>(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString<parseFlags>(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Get member count. + SizeType c = *stack_.template Pop<SizeType>(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Get element count. + SizeType c = *stack_.template Pop<SizeType>(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template <typename InputStream> + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + } + } + + template <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespace(is); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespace(is); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader<UTF8<>, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/dep/rapidjson/rapidjson/stringbuffer.h b/dep/rapidjson/rapidjson/stringbuffer.h new file mode 100644 index 00000000000..1c9c80b7993 --- /dev/null +++ b/dep/rapidjson/rapidjson/stringbuffer.h @@ -0,0 +1,93 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "rapidjson.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include <utility> // std::move +#endif + +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template <typename Encoding, typename Allocator = CrtAllocator> +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push<Ch>() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop<Ch>(1); + } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.template Pop<Ch>(1); + + return stack_.template Bottom<Ch>(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack<Allocator> stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer<UTF8<> > StringBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { + std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/dep/rapidjson/rapidjson/writer.h b/dep/rapidjson/rapidjson/writer.h new file mode 100644 index 00000000000..e1eea38b987 --- /dev/null +++ b/dep/rapidjson/rapidjson/writer.h @@ -0,0 +1,395 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include <new> // placement new + +#if RAPIDJSON_HAS_STDSTRING +#include <string> +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer<OutputStream> writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return WriteNull(); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); } + bool Int(int i) { Prefix(kNumberType); return WriteInt(i); } + bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); } + bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kStringType); + return WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push<Level>()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + bool ret = WriteEndObject(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push<Level>()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + bool ret = WriteEndArray(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + static const size_t kDefaultLevelDepth = 32; + + bool WriteNull() { + os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); + } + else { + os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteDouble(double d) { + char buffer[25]; + char* end = internal::dtoa(d, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + os_->Put('\"'); + GenericStringStream<SourceEncoding> is(str); + while (is.Tell() < length) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + os_->Put('\\'); + os_->Put('u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + os_->Put(hexDigits[(codepoint >> 12) & 15]); + os_->Put(hexDigits[(codepoint >> 8) & 15]); + os_->Put(hexDigits[(codepoint >> 4) & 15]); + os_->Put(hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + os_->Put(hexDigits[(lead >> 12) & 15]); + os_->Put(hexDigits[(lead >> 8) & 15]); + os_->Put(hexDigits[(lead >> 4) & 15]); + os_->Put(hexDigits[(lead ) & 15]); + os_->Put('\\'); + os_->Put('u'); + os_->Put(hexDigits[(trail >> 12) & 15]); + os_->Put(hexDigits[(trail >> 8) & 15]); + os_->Put(hexDigits[(trail >> 4) & 15]); + os_->Put(hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { + is.Take(); + os_->Put('\\'); + os_->Put(escape[(unsigned char)c]); + if (escape[(unsigned char)c] == 'u') { + os_->Put('0'); + os_->Put('0'); + os_->Put(hexDigits[(unsigned char)c >> 4]); + os_->Put(hexDigits[(unsigned char)c & 0xF]); + } + } + else + if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_)) + return false; + } + os_->Put('\"'); + return true; + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + void Prefix(Type type) { + (void)type; + if (level_stack_.GetSize() != 0) { // this value is not at root + Level* level = level_stack_.template Top<Level>(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + OutputStream* os_; + internal::Stack<StackAllocator> level_stack_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer<StringBuffer>::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(11 - (end - buffer)); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(10 - (end - buffer)); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(21 - (end - buffer)); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(20 - (end - buffer)); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteDouble(double d) { + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer); + os_->Pop(25 - (end - buffer)); + return true; +} + +RAPIDJSON_NAMESPACE_END + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/dep/readline/CMakeLists.txt b/dep/readline/CMakeLists.txt new file mode 100644 index 00000000000..0e8679ba718 --- /dev/null +++ b/dep/readline/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +if( UNIX ) + # find Readline (terminal input library) includes and library + # + # READLINE_INCLUDE_DIR - where the directory containing the READLINE headers can be found + # READLINE_LIBRARY - full path to the READLINE library + find_path(READLINE_INCLUDE_DIR readline/readline.h) + find_library(READLINE_LIBRARY NAMES readline) + + message(STATUS "Found Readline library: ${READLINE_LIBRARY}") + message(STATUS "Include dir is: ${READLINE_INCLUDE_DIR}") + + if (NOT READLINE_INCLUDE_DIR OR NOT READLINE_LIBRARY) + message(FATAL_ERROR "** Readline library not found!\n** Your distro may provide a binary for Readline e.g. for ubuntu try apt-get install libreadline5-dev") + endif () + + add_library(readline SHARED IMPORTED GLOBAL) + + set_target_properties(readline + PROPERTIES + IMPORTED_LOCATION + "${READLINE_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${READLINE_INCLUDE_DIR}") + +else() + # Provide a dummy target + add_library(readline INTERFACE) +endif() diff --git a/dep/recastnavigation/Detour/CMakeLists.txt b/dep/recastnavigation/Detour/CMakeLists.txt index b21e4ca6273..12be71d32b4 100644 --- a/dep/recastnavigation/Detour/CMakeLists.txt +++ b/dep/recastnavigation/Detour/CMakeLists.txt @@ -16,14 +16,18 @@ set(Detour_STAT_SRCS Source/DetourNavMeshQuery.cpp Source/DetourNode.cpp ) -include_directories(Include) - -if(WIN32) - include_directories( - ${CMAKE_SOURCE_DIR}/dep/zlib - ) -endif() add_library(Detour STATIC ${Detour_STAT_SRCS}) -target_link_libraries(Detour ${ZLIB_LIBRARIES}) +target_include_directories(Detour + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/Include) + +target_link_libraries(Detour + PUBLIC + zlib) + +set_target_properties(Detour + PROPERTIES + FOLDER + "dep") diff --git a/dep/recastnavigation/Recast/CMakeLists.txt b/dep/recastnavigation/Recast/CMakeLists.txt index 738c010eb05..1eac4e75399 100644 --- a/dep/recastnavigation/Recast/CMakeLists.txt +++ b/dep/recastnavigation/Recast/CMakeLists.txt @@ -14,21 +14,24 @@ set(Recast_STAT_SRCS Source/RecastArea.cpp Source/RecastContour.cpp Source/RecastFilter.cpp - Source/RecastLayers.cpp + Source/RecastLayers.cpp Source/RecastMesh.cpp Source/RecastMeshDetail.cpp Source/RecastRasterization.cpp Source/RecastRegion.cpp ) -include_directories(Include) +add_library(Recast STATIC ${Recast_STAT_SRCS}) -if(WIN32) - include_directories( - ${CMAKE_SOURCE_DIR}/dep/zlib - ) -endif() +target_include_directories(Recast + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/Include) -add_library(Recast STATIC ${Recast_STAT_SRCS}) +target_link_libraries(Recast + PUBLIC + zlib) -target_link_libraries(Recast ${ZLIB_LIBRARIES})
\ No newline at end of file +set_target_properties(Recast + PROPERTIES + FOLDER + "dep") diff --git a/dep/threads/CMakeLists.txt b/dep/threads/CMakeLists.txt new file mode 100644 index 00000000000..48e5eb00723 --- /dev/null +++ b/dep/threads/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +find_package(Threads REQUIRED) + +add_library(threads INTERFACE) +target_link_libraries(threads + INTERFACE + ${CMAKE_THREAD_LIBS_INIT}) diff --git a/dep/utf8cpp/CMakeLists.txt b/dep/utf8cpp/CMakeLists.txt new file mode 100644 index 00000000000..edf8604d44c --- /dev/null +++ b/dep/utf8cpp/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library(utf8cpp INTERFACE) + +target_include_directories(utf8cpp + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/dep/valgrind/CMakeLists.txt b/dep/valgrind/CMakeLists.txt new file mode 100644 index 00000000000..d67cd33b426 --- /dev/null +++ b/dep/valgrind/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library(valgrind INTERFACE) + +target_include_directories(valgrind + INTERFACE + "${VALGRIND_INCLUDE_DIR}") diff --git a/dep/zlib/CMakeLists.txt b/dep/zlib/CMakeLists.txt index 7feb134bcd5..b3e3d58fe55 100644 --- a/dep/zlib/CMakeLists.txt +++ b/dep/zlib/CMakeLists.txt @@ -8,22 +8,43 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -SET(zlib_STAT_SRCS - adler32.c - compress.c - crc32.c - deflate.c - infback.c - inffast.c - inflate.c - inftrees.c - trees.c - uncompr.c - zutil.c -) +if(UNIX) + # Look for an installed zlib on unix + find_package(ZLIB REQUIRED) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} -) + add_library(zlib SHARED IMPORTED GLOBAL) -add_library(zlib STATIC ${zlib_STAT_SRCS}) + set_target_properties(zlib + PROPERTIES + IMPORTED_LOCATION + "${ZLIB_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES + "${ZLIB_INCLUDE_DIRS}") +else() + # Use the bundled source on windows + SET(zlib_STAT_SRCS + adler32.c + compress.c + crc32.c + deflate.c + infback.c + inffast.c + inflate.c + inftrees.c + trees.c + uncompr.c + zutil.c + ) + + add_library(zlib STATIC + ${zlib_STAT_SRCS}) + + target_include_directories(zlib + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + + set_target_properties(zlib + PROPERTIES + FOLDER + "dep") +endif() diff --git a/dep/zmqpp/zmqpp/compatibility.hpp b/dep/zmqpp/zmqpp/compatibility.hpp deleted file mode 100644 index 103b2c82ebd..00000000000 --- a/dep/zmqpp/zmqpp/compatibility.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/** - * \file - * - * \date 10 Sep 2011 - * \author ron - * \author Ben Gray (\@benjamg) - * - * A fair number of C++0x (or more accurately C++11) features are used in this - * library and as this project is used where I work on older compilers this - * file was created to help. - * - * C++ features and their workaround where not supported: - * \li lambda functions - disabled, these are only used in the test anyway. - * \li typesafe enums - replaced with enum where comparisons needed. - * \li nullptr - defined to null. - * - * As of the port to version 3.1 (libzmqpp version 1.1.0) this file will also - * be used to maintain compatablity with multiple versions of 0mq - */ - -#ifndef ZMQPP_COMPATIBILITY_HPP_ -#define ZMQPP_COMPATIBILITY_HPP_ - -#include <zmq.h> -#include <cstdint> - -// Currently we require at least 0mq version 2.2.x -#define ZMQPP_REQUIRED_ZMQ_MAJOR 2 -#define ZMQPP_REQUIRED_ZMQ_MINOR 2 - -#if (ZMQ_VERSION_MAJOR < ZMQPP_REQUIRED_ZMQ_MAJOR) || ((ZMQ_VERSION_MAJOR == ZMQPP_REQUIRED_ZMQ_MAJOR) && (ZMQ_VERSION_MINOR < ZMQPP_REQUIRED_ZMQ_MINOR)) -#error zmqpp requires a later version of 0mq -#endif - -// Experimental feature support -#if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 0) -#define ZMQ_EXPERIMENTAL_LABELS -#endif - -// Deal with older versions of gcc -#if defined(__GNUC__) && !defined(__clang__) -#if __GNUC__ == 4 - -// Deal with older gcc not supporting C++0x typesafe enum class name {} comparison -#if __GNUC_MINOR__ < 4 -#define ZMQPP_COMPARABLE_ENUM enum -#endif - -#if __GNUC_MINOR__ == 4 -#if __GNUC_PATCHLEVEL__ < 1 -#undef ZMQPP_COMPARABLE_ENUM -#define ZMQPP_COMPARABLE_ENUM enum -#endif // if __GNUC_PATCHLEVEL__ < 1 -#endif // if __GNUC_MINOR__ == 4 - -// Deal with older gcc not supporting C++0x lambda function -#if __GNUC_MINOR__ < 5 -#define ZMQPP_IGNORE_LAMBDA_FUNCTION_TESTS -#define ZMQPP_EXPLICITLY_DELETED -#endif // if __GNUC_MINOR__ < 5 - -// Deal with older gcc not supporting C++0x nullptr -#if __GNUC_MINOR__ < 6 -#define nullptr NULL -#define NOEXCEPT -#endif // if __GNUC_MINOR__ < 6 - -#endif // if __GNUC_ == 4 -#endif // if defined(__GNUC__) && !defined(__clang__) - -#if defined(_MSC_VER) -#define NOEXCEPT throw() -#if _MSC_VER < 1800 -#define ZMQPP_EXPLICITLY_DELETED -#endif // if _MSC_VER < 1800 -#if _MSC_VER < 1600 -#define nullptr NULL -#define ZMQPP_IGNORE_LAMBDA_FUNCTION_TESTS -#define ZMQPP_COMPARABLE_ENUM enum -#endif // if _MSC_VER < 1600 -#endif // if defined(_MSC_VER) - -// Generic state, assume a modern compiler -#ifndef ZMQPP_COMPARABLE_ENUM -#define ZMQPP_COMPARABLE_ENUM enum class -#endif - -#ifndef ZMQPP_EXPLICITLY_DELETED -#define ZMQPP_EXPLICITLY_DELETED = delete -#endif - -#ifndef NOEXCEPT -#define NOEXCEPT noexcept -#endif - -#endif /* ZMQPP_COMPATIBILITY_HPP_ */ - diff --git a/dep/zmqpp/zmqpp/context.cpp b/dep/zmqpp/zmqpp/context.cpp deleted file mode 100644 index 32c657199dc..00000000000 --- a/dep/zmqpp/zmqpp/context.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#include "context.hpp" - -namespace zmqpp -{ - -void context::terminate() -{ - int result; - do - { -#if (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - result = zmq_term(_context); -#else - result = zmq_ctx_destroy(_context); -#endif - } while (result != 0 && zmq_errno() == EINTR); - if (result != 0) { throw zmq_internal_exception(); } - _context = nullptr; -} - -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -void context::set(context_option const option, int const value) -{ - if (nullptr == _context) { throw invalid_instance("context is invalid"); } - - if (0 != zmq_ctx_set(_context, static_cast<int>(option), value)) - { - throw zmq_internal_exception(); - } -} - -int context::get(context_option const option) -{ - if (nullptr == _context) { throw invalid_instance("context is invalid"); } - - int result = zmq_ctx_get(_context, static_cast<int>(option)); - - if (result < 0) - { - throw zmq_internal_exception(); - } - - return result; -} -#endif - -} diff --git a/dep/zmqpp/zmqpp/context.hpp b/dep/zmqpp/zmqpp/context.hpp deleted file mode 100644 index 3ffaf791440..00000000000 --- a/dep/zmqpp/zmqpp/context.hpp +++ /dev/null @@ -1,184 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_CONTEXT_HPP_ -#define ZMQPP_CONTEXT_HPP_ - -#include <cassert> - -#include <zmq.h> - -#include "compatibility.hpp" -#include "exception.hpp" -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -#include "context_options.hpp" -#endif - -namespace zmqpp -{ - -/*! - * The context class represents internal zmq context and io threads. - * - * By default the context class will create one thread, however this can be - * overridden in the constructor. - * - * The context class is the only object that can be considered thread safe. - * - * All sockets using endpoints other than inproc require the context to have - * at least one thread. - * - * This class is c++0x move supporting and cannot be copied. - */ -class context -{ -public: - -#if (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - /*! - * Initialise the 0mq context. - * - * If only inproc is used then the context may be created with zero threads. - * Any inproc endpoint using sockets must be created using the same context. - * - * The context is thread safe an may be used anywhere in your application, - * however there is no requirement (other than inproc restrictions) for you - * to do this. - * - * \param threads an integer argument for the number of required threads. Defaults to 1. - */ - context(int const& threads = 1) -#else - /*! - * Initialise the 0mq context. - * - * The context is thread safe an may be used anywhere in your application, - * however there is no requirement (other than inproc restrictions) for you - * to do this. - */ - context() -#endif - : _context(nullptr) - { -#if (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - _context = zmq_init(threads); -#else - _context = zmq_ctx_new(); -#endif - - if (nullptr == _context) - { - throw zmq_internal_exception(); - } - } - - /*! - * Closes the 0mq context. - * - * Any blocking calls other than a socket close will return with an error. - * - * If there are open sockets will block while zmq internal buffers are - * processed up to a limit specified by that sockets linger option. - */ - ~context() NOEXCEPT - { - if (nullptr != _context) - { - terminate(); - } - } - - /*! - * Move supporting constructor. - * - * Allows zero-copy move semantics to be used with this class. - * - * \param source a rvalue instance of the object who's internals we wish to steal. - */ - context(context&& source) NOEXCEPT - : _context(source._context) - { - source._context = nullptr; - } - - /*! - * Move supporting operator. - * - * Allows zero-copy move semantics to be used with this class. - * - * \param source an rvalue instance of the context who's internals we wish to steal. - */ - context& operator=(context&& source) NOEXCEPT - { - std::swap( _context, source._context ); - return *this; - } - - /*! - * Terminate the current context. - * - * Any blocking calls other than a socket close will return with an error. - * - * If there are open sockets will block while zmq internal buffers are - * processed up to a limit specified by that sockets linger option. - */ - void terminate(); - -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) - /*! - * Set the value of an option in the underlaying zmq context. - * - * \param option a valid ::context_option - * \param value to set the option to - */ - void set(context_option const option, int const value); - - /*! - * Get a context option from the underlaying zmq context. - * - * \param option a valid ::context_option - * \return context option value - */ - int get(context_option const option); -#endif - - /*! - * Validity checking of the context - * - * Checks if the underlying 0mq context for this instance is valid. - * - * Contexts should always be valid unless people are doing 'fun' things with - * std::move. - * - * \return boolean true if the object is valid. - */ - operator bool() const NOEXCEPT - { - return nullptr != _context; - } - - /*! - * Access to the raw 0mq context - * - * \return void pointer to the underlying 0mq context. - */ - operator void*() const NOEXCEPT - { - return _context; - } - -private: - void* _context; - - // No copy - private and not implemented - context(context const&) ZMQPP_EXPLICITLY_DELETED; - context& operator=(context const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; -}; - -} - -#endif /* ZMQPP_CONTEXT_HPP_ */ diff --git a/dep/zmqpp/zmqpp/context_options.hpp b/dep/zmqpp/zmqpp/context_options.hpp deleted file mode 100644 index b2e2cf4805f..00000000000 --- a/dep/zmqpp/zmqpp/context_options.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/** - * \file - * - * \date 3 Jul 2013 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_CONTEXT_OPTIONS_HPP_ -#define ZMQPP_CONTEXT_OPTIONS_HPP_ - -namespace zmqpp -{ - -/** \todo Expand the information on the options to make it actually useful. */ -/*! - * \brief possible Context options in zmq - */ - -enum class context_option { - io_threads = ZMQ_IO_THREADS, /*!< I/O thread count */ - max_sockets = ZMQ_MAX_SOCKETS, /*!< Maximum supported sockets */ -}; - -} - -#endif /* ZMQPP_CONTEXT_OPTIONS_HPP_ */ diff --git a/dep/zmqpp/zmqpp/exception.hpp b/dep/zmqpp/zmqpp/exception.hpp deleted file mode 100644 index a0b234769ce..00000000000 --- a/dep/zmqpp/zmqpp/exception.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_EXCEPTION_HPP_ -#define ZMQPP_EXCEPTION_HPP_ - -#include <stdexcept> -#include <string> - -#include <zmq.h> - -namespace zmqpp -{ - -/** \todo Have a larger variety of exceptions with better state debug information */ - -/*! - * Represents the base zmqpp exception. - * - * All zmqpp runtime exceptions are children of this class. - * The class itself does not provide any special access fields but it only - * for convince when catching exceptions. - * - * The class extends std::runtime_error. - * - */ -class exception : public std::runtime_error -{ -public: - /*! - * Standard exception constructor. - * - * \param message a string representing the error message. - */ - exception(std::string const& message) - : std::runtime_error(message) - { } -}; - -/*! - * Represents an attempt to use an invalid object. - * - * Objects may be invalid initially or after a shutdown or close. - */ -class invalid_instance : public exception -{ -public: - invalid_instance(std::string const& message) - : exception(message) - { } -}; - -/*! - * Represents internal zmq errors. - * - * Any error response from the zmq bindings will be wrapped in this error. - * - * The class provides access to the zmq error number via zmq_error(). - */ -class zmq_internal_exception : public exception -{ -public: - /*! - * Uses the zmq functions to pull out error messages and numbers. - */ - zmq_internal_exception() - : exception(zmq_strerror(zmq_errno())) - , _error(zmq_errno()) - { } - - /*! - * Retrieve the zmq error number associated with this exception. - * \return zmq error number - */ - int zmq_error() const { return _error; } - -private: - int _error; -}; - -} - -#endif /* ZMQPP_EXCEPTION_HPP_ */ diff --git a/dep/zmqpp/zmqpp/frame.cpp b/dep/zmqpp/zmqpp/frame.cpp deleted file mode 100644 index 4c512ae1010..00000000000 --- a/dep/zmqpp/zmqpp/frame.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/** - * \file - * - * \date 8 Jan 2014 - * \author Ben Gray (\@benjamg) - */ - -#include <cassert> -#include <cstring> - -#include "exception.hpp" -#include "frame.hpp" - -namespace zmqpp { - -frame::frame() - : _sent( false ) -{ - if( 0 != zmq_msg_init( &_msg ) ) - { - throw zmq_internal_exception(); - } -} - -frame::frame(size_t const size) - : _sent( false ) -{ - if( 0 != zmq_msg_init_size( &_msg, size ) ) - { - throw zmq_internal_exception(); - } -} - -frame::frame(void const* part, size_t const size) - : _sent( false ) -{ - if( 0 != zmq_msg_init_size( &_msg, size ) ) - { - throw zmq_internal_exception(); - } - - void* msg_data = zmq_msg_data( &_msg ); - memcpy( msg_data, part, size ); -} - -frame::frame(void* part, size_t const size, zmq_free_fn *ffn, void *hint) - : _sent( false ) -{ - if( 0 != zmq_msg_init_data( &_msg, part, size, ffn, hint ) ) - { - throw zmq_internal_exception(); - } -} - -frame::~frame() -{ -#ifndef NDEBUG // unused assert variable in release - int result = zmq_msg_close( &_msg ); - assert(0 == result); -#else - zmq_msg_close( &_msg ); -#endif // NDEBUG -} - -frame::frame(frame&& other) - : _sent( other._sent ) -{ - zmq_msg_init( &_msg ); - zmq_msg_move( &_msg, &other._msg ); - other._sent = false; -} - -frame& frame::operator=(frame&& other) -{ - zmq_msg_init( &_msg ); - zmq_msg_move( &_msg, &other._msg ); - std::swap( _sent, other._sent ); - - return *this; -} - -frame frame::copy() const -{ - frame other( size() ); - other._sent = _sent; - - if( 0 != zmq_msg_copy( &other._msg, const_cast<zmq_msg_t*>(&_msg) ) ) - { - throw zmq_internal_exception(); - } - - return other; -} - -} // namespace zmqpp diff --git a/dep/zmqpp/zmqpp/frame.hpp b/dep/zmqpp/zmqpp/frame.hpp deleted file mode 100644 index c9e4b9b7d82..00000000000 --- a/dep/zmqpp/zmqpp/frame.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * \file - * - * \date 8 Jan 2014 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_MESSAGE_FRAME_HPP_ -#define ZMQPP_MESSAGE_FRAME_HPP_ - -#include <zmq.h> - -#include "compatibility.hpp" - -namespace zmqpp { - -/*! - * \brief an internal frame wrapper for a single zmq message - * - * This frame wrapper consists of a zmq message and meta data it is used - * by the zmqpp message class to keep track of parts in the internal - * queue. It is unlikely you need to use this class. - */ -class frame -{ -public: - frame(); - frame(size_t const size); - frame(void const* part, size_t const size); - frame(void* part, size_t const size, zmq_free_fn *ffn, void *hint); - - ~frame(); - - bool is_sent() const { return _sent; } - void const* data() const { return zmq_msg_data( const_cast<zmq_msg_t*>(&_msg) ); } - size_t size() const { return zmq_msg_size( const_cast<zmq_msg_t*>(&_msg) ); } - - void mark_sent() { _sent = true; } - zmq_msg_t& msg() { return _msg; } - - // Move operators - frame(frame&& other); - frame& operator=(frame&& other); - - frame copy() const; - -private: - bool _sent; - zmq_msg_t _msg; - - // Disable implicit copy support, code must request a copy to clone - frame(frame const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; - frame& operator=(frame const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; -}; - -} // namespace zmqpp - -#endif /* ZMQPP_MESSAGE_FRAME_HPP_ */ diff --git a/dep/zmqpp/zmqpp/inet.hpp b/dep/zmqpp/zmqpp/inet.hpp deleted file mode 100644 index e0c3b146e37..00000000000 --- a/dep/zmqpp/zmqpp/inet.hpp +++ /dev/null @@ -1,175 +0,0 @@ -/** - * \file - * - * \date 10 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_INET_HPP_ -#define ZMQPP_INET_HPP_ - -/** \todo cross-platform version of including headers. */ -// We get htons and htonl from here -#ifdef _WIN32 -#include <WinSock2.h> -#else -#include <netinet/in.h> -#endif - -#include "compatibility.hpp" - -namespace zmqpp -{ - -/*! - * \brief Possible byte order types. - * - * An enumeration of all the known order types, all two of them. - * There is also an entry for unknown which is just used as a default. - */ -ZMQPP_COMPARABLE_ENUM order { - big_endian, /*!< byte order is big endian */ - little_endian /*!< byte order is little endian */ -}; - -/*! - * Common code for the 64bit versions of htons/htons and ntohs/ntohl - * - * As htons and ntohs (or htonl and ntohs) always just do the same thing, ie - * swap bytes if the host order differs from network order or otherwise don't - * do anything, it seemed silly to type the code twice. - * - * \note This code assumes network order is always big endian. Which it is. - * \note The host endian is only checked once and afterwards assumed to remain - * the same. - * - * \param value_to_check unsigned 64 bit integer to swap - * \return swapped (or not) unsigned 64 bit integer - */ -inline uint64_t swap_if_needed(uint64_t const value_to_check) -{ - static order host_order = (htonl(42) == 42) ? order::big_endian : order::little_endian; - - if (order::big_endian == host_order) - { - return value_to_check; - } - - union { - uint64_t integer; - uint8_t bytes[8]; - } value { value_to_check }; - - std::swap(value.bytes[0], value.bytes[7]); - std::swap(value.bytes[1], value.bytes[6]); - std::swap(value.bytes[2], value.bytes[5]); - std::swap(value.bytes[3], value.bytes[4]); - - return value.integer; -} - -/*! - * 64 bit version of the htons/htonl - * - * I've used the name htonll to try and keep with the htonl naming scheme. - * - * \param hostlonglong unsigned 64 bit host order integer - * \return unsigned 64 bit network order integer - */ -#ifndef htonll -inline uint64_t htonll(uint64_t const hostlonglong) -{ - return zmqpp::swap_if_needed(hostlonglong); -} -#endif - -/*! - * 64 bit version of the ntohs/ntohl - * - * I've used the name htonll to try and keep with the htonl naming scheme. - * - * \param networklonglong unsigned 64 bit network order integer - * \return unsigned 64 bit host order integer - */ -#ifndef ntohll -inline uint64_t ntohll(uint64_t const networklonglong) -{ - return zmqpp::swap_if_needed(networklonglong); -} -#endif - -/*! - * floating point version of the htons/htonl - * - * \param value host order floating point - * \returns network order floating point - */ -inline float htonf(float value) -{ - assert(sizeof(float) == sizeof(uint32_t)); - - uint32_t temp; - memcpy(&temp, &value, sizeof(uint32_t)); - temp = htonl( temp ); - memcpy(&value, &temp, sizeof(uint32_t)); - - return value; -} - -/*! - * floating point version of the ntohs/ntohl - * - * \param value network order float - * \returns host order float - */ -inline float ntohf(float value) -{ - assert(sizeof(float) == sizeof(uint32_t)); - - uint32_t temp; - memcpy(&temp, &value, sizeof(uint32_t)); - temp = ntohl( temp ); - memcpy(&value, &temp, sizeof(uint32_t)); - - return value; -} - -/*! - * double precision floating point version of the htons/htonl - * - * \param value host order double precision floating point - * \returns network order double precision floating point - */ -inline double htond(double value) -{ - assert(sizeof(double) == sizeof(uint64_t)); - - uint64_t temp; - memcpy(&temp, &value, sizeof(uint64_t)); - temp = htonll(temp); - memcpy(&value, &temp, sizeof(uint64_t)); - - return value; -} - -/*! - * double precision floating point version of the ntohs/ntohl - * - * \param value network order double precision floating point - * \returns host order double precision floating point - */ -inline double ntohd(double value) -{ - assert(sizeof(double) == sizeof(uint64_t)); - - uint64_t temp; - memcpy(&temp, &value, sizeof(uint64_t)); - temp = ntohll(temp); - memcpy(&value, &temp, sizeof(uint64_t)); - - return value; -} - -} - -#endif /* INET_HPP_ */ diff --git a/dep/zmqpp/zmqpp/message.cpp b/dep/zmqpp/zmqpp/message.cpp deleted file mode 100644 index 4d81d247c62..00000000000 --- a/dep/zmqpp/zmqpp/message.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Created on: 9 Aug 2011 - * Author: Ben Gray (@benjamg) - */ - -#include <cassert> -#include <cstring> - -#include "exception.hpp" -#include "inet.hpp" -#include "message.hpp" - -namespace zmqpp -{ - -/*! - * \brief internal construct - * \internal handles bubbling callback from zmq c style to the c++ functor provided - */ -struct callback_releaser -{ - message::release_function func; -}; - -message::message() - : _parts() - , _read_cursor(0) -{ -} - -message::~message() -{ - _parts.clear(); -} - -size_t message::parts() const -{ - return _parts.size(); -} - -/* - * The two const_casts in size and raw_data are a little bit hacky - * but neither of these methods called this way actually modify data - * so accurately represent the intent of these calls. - */ - -size_t message::size(size_t const part /* = 0 */) const -{ - if(part >= _parts.size()) - { - throw exception("attempting to request a message part outside the valid range"); - } - - return _parts[part].size(); -} - -void const* message::raw_data(size_t const part /* = 0 */) const -{ - if(part >= _parts.size()) - { - throw exception("attempting to request a message part outside the valid range"); - } - - return _parts[part].data(); -} - -zmq_msg_t& message::raw_msg(size_t const part /* = 0 */) -{ - if(part >= _parts.size()) - { - throw exception("attempting to request a message part outside the valid range"); - } - - return _parts[part].msg(); -} - -zmq_msg_t& message::raw_new_msg() -{ - _parts.push_back( frame() ); - - return _parts.back().msg(); -} - -zmq_msg_t& message::raw_new_msg(size_t const reserve_data_size) -{ - _parts.push_back( frame(reserve_data_size) ); - - return _parts.back().msg(); -} - -std::string message::get(size_t const part /* = 0 */) const -{ - return std::string(static_cast<char const*>(raw_data(part)), size(part)); -} - - -// Move operators will take ownership of message parts without copying -void message::move(void* part, size_t const size, release_function const& release) -{ - callback_releaser* hint = new callback_releaser(); - hint->func = release; - - _parts.push_back( frame( part, size, &message::release_callback, hint ) ); -} - -// Stream reader style -void message::reset_read_cursor() -{ - _read_cursor = 0; -} - -void message::get(int8_t& integer, size_t const part) const -{ - assert(sizeof(int8_t) == size(part)); - - int8_t const* byte = static_cast<int8_t const*>(raw_data(part)); - integer = *byte; -} - -void message::get(int16_t& integer, size_t const part) const -{ - assert(sizeof(int16_t) == size(part)); - - uint16_t const* network_order = static_cast<uint16_t const*>(raw_data(part)); - integer = static_cast<int16_t>(ntohs(*network_order)); -} - -void message::get(int32_t& integer, size_t const part) const -{ - assert(sizeof(int32_t) == size(part)); - - uint32_t const* network_order = static_cast<uint32_t const*>(raw_data(part)); - integer = static_cast<int32_t>(htonl(*network_order)); -} - -void message::get(int64_t& integer, size_t const part) const -{ - assert(sizeof(int64_t) == size(part)); - - uint64_t const* network_order = static_cast<uint64_t const*>(raw_data(part)); - integer = static_cast<int64_t>(htonll(*network_order)); -} - -void message::get(uint8_t& unsigned_integer, size_t const part) const -{ - assert(sizeof(uint8_t) == size(part)); - - uint8_t const* byte = static_cast<uint8_t const*>(raw_data(part)); - unsigned_integer = *byte; -} - -void message::get(uint16_t& unsigned_integer, size_t const part) const -{ - assert(sizeof(uint16_t) == size(part)); - - uint16_t const* network_order = static_cast<uint16_t const*>(raw_data(part)); - unsigned_integer = ntohs(*network_order); -} - -void message::get(uint32_t& unsigned_integer, size_t const part) const -{ - assert(sizeof(uint32_t) == size(part)); - - uint32_t const* network_order = static_cast<uint32_t const*>(raw_data(part)); - unsigned_integer = ntohl(*network_order); -} - -void message::get(uint64_t& unsigned_integer, size_t const part) const -{ - assert(sizeof(uint64_t) == size(part)); - - uint64_t const* network_order = static_cast<uint64_t const*>(raw_data(part)); - unsigned_integer = ntohll(*network_order); -} - -void message::get(float& floating_point, size_t const part) const -{ - assert(sizeof(float) == size(part)); - - float const* network_order = static_cast<float const*>(raw_data(part)); - floating_point = zmqpp::ntohf(*network_order); -} - -void message::get(double& double_precision, size_t const part) const -{ - assert(sizeof(double) == size(part)); - - double const* network_order = static_cast<double const*>(raw_data(part)); - double_precision = zmqpp::ntohd(*network_order); -} - -void message::get(bool& boolean, size_t const part) const -{ - assert(sizeof(uint8_t) == size(part)); - - uint8_t const* byte = static_cast<uint8_t const*>(raw_data(part)); - boolean = (*byte != 0); -} - -void message::get(std::string& string, size_t const part) const -{ - string.assign( get(part) ); -} - - -// Stream writer style - these all use copy styles -message& message::operator<<(int8_t const integer) -{ - add(reinterpret_cast<void const*>(&integer), sizeof(int8_t)); - return *this; -} - -message& message::operator<<(int16_t const integer) -{ - uint16_t network_order = htons(static_cast<uint16_t>(integer)); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint16_t)); - - return *this; -} - -message& message::operator<<(int32_t const integer) -{ - uint32_t network_order = htonl(static_cast<uint32_t>(integer)); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint32_t)); - - return *this; -} - -message& message::operator<<(int64_t const integer) -{ - uint64_t network_order = htonll(static_cast<uint64_t>(integer)); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint64_t)); - - return *this; -} - - -message& message::operator<<(uint8_t const unsigned_integer) -{ - add(reinterpret_cast<void const*>(&unsigned_integer), sizeof(uint8_t)); - return *this; -} - -message& message::operator<<(uint16_t const unsigned_integer) -{ - uint16_t network_order = htons(unsigned_integer); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint16_t)); - - return *this; -} - -message& message::operator<<(uint32_t const unsigned_integer) -{ - uint32_t network_order = htonl(unsigned_integer); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint32_t)); - - return *this; -} - -message& message::operator<<(uint64_t const unsigned_integer) -{ - uint64_t network_order = htonll(unsigned_integer); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint64_t)); - - return *this; -} - -message& message::operator<<(float const floating_point) -{ - assert(sizeof(float) == 4); - - float network_order = zmqpp::htonf(floating_point); - add(&network_order, sizeof(float)); - - return *this; -} - -message& message::operator<<(double const double_precision) -{ - assert(sizeof(double) == 8); - - double network_order = zmqpp::htond(double_precision); - add(&network_order, sizeof(double)); - - return *this; -} - -message& message::operator<<(bool const boolean) -{ - uint8_t byte = (boolean) ? 1 : 0; - add(reinterpret_cast<void const*>(&byte), sizeof(uint8_t)); - - return *this; -} - -message& message::operator<<(char const* c_string) -{ - add(reinterpret_cast<void const*>(c_string), strlen(c_string)); - return *this; -} - -message& message::operator<<(std::string const& string) -{ - add(reinterpret_cast<void const*>(string.data()), string.size()); - return *this; -} - -void message::push_front(void const* part, size_t const size) -{ - _parts.emplace( _parts.begin(), part, size ); -} - -void message::push_front(int8_t const integer) -{ - push_front(&integer, sizeof(int8_t)); -} - -void message::push_front(int16_t const integer) -{ - uint16_t network_order = htons(static_cast<uint16_t>(integer)); - push_front(&network_order, sizeof(uint16_t)); -} - -void message::push_front(int32_t const integer) -{ - uint32_t network_order = htonl(static_cast<uint32_t>(integer)); - push_front(&network_order, sizeof(uint32_t)); -} - -void message::push_front(int64_t const integer) -{ - uint64_t network_order = htonll(static_cast<uint64_t>(integer)); - push_front(&network_order, sizeof(uint64_t)); -} - - -void message::push_front(uint8_t const unsigned_integer) -{ - push_front(&unsigned_integer, sizeof(uint8_t)); -} - -void message::push_front(uint16_t const unsigned_integer) -{ - uint16_t network_order = htons(unsigned_integer); - push_front(&network_order, sizeof(uint16_t)); -} - -void message::push_front(uint32_t const unsigned_integer) -{ - uint32_t network_order = htonl(unsigned_integer); - push_front(&network_order, sizeof(uint32_t)); -} - -void message::push_front(uint64_t const unsigned_integer) -{ - uint64_t network_order = htonll(unsigned_integer); - push_front(&network_order, sizeof(uint64_t)); -} - -void message::push_front(float const floating_point) -{ - assert(sizeof(float) == 4); - - float network_order = zmqpp::htonf(floating_point); - push_front(&network_order, sizeof(float)); -} - -void message::push_front(double const double_precision) -{ - assert(sizeof(double) == 8); - - double network_order = zmqpp::htond(double_precision); - push_front(&network_order, sizeof(double)); -} - -void message::push_front(bool const boolean) -{ - uint8_t byte = (boolean) ? 1 : 0; - push_front(&byte, sizeof(uint8_t)); -} - -void message::push_front(char const* c_string) -{ - push_front(c_string, strlen(c_string)); -} - -void message::push_front(std::string const& string) -{ - push_front(string.data(), string.size()); -} - -void message::pop_front() -{ - _parts.erase( _parts.begin() ); -} - -void message::pop_back() -{ - _parts.pop_back(); -} - -message::message(message&& source) NOEXCEPT - : _parts() - , _read_cursor(0) -{ - std::swap(_parts, source._parts); -} - -message& message::operator=(message&& source) NOEXCEPT -{ - std::swap(_parts, source._parts); - return *this; -} - -message message::copy() const -{ - message msg; - msg.copy(*this); - return msg; -} - -void message::copy(message const& source) -{ - _parts.resize( source._parts.size() ); - for(size_t i = 0; i < source._parts.size(); ++i) - { - _parts[i] = source._parts[i].copy(); - } - - // we don't need a copy of the releasers as we did data copies of the internal data, - //_releasers = source._releasers; - //_strings = source._strings -} - -// Used for internal tracking -void message::sent(size_t const part) -{ - // sanity check - assert(!_parts[part].is_sent()); - _parts[part].mark_sent(); -} - -// Note that these releasers are not thread safe, the only safety is provided by -// the socket class taking ownership so no updates can happen while zmq does it's thing -// If used in a custom class this has to be dealt with. -void message::release_callback(void* data, void* hint) -{ - callback_releaser* releaser = static_cast<callback_releaser*>(hint); - releaser->func(data); - - delete releaser; -} - -} diff --git a/dep/zmqpp/zmqpp/message.hpp b/dep/zmqpp/zmqpp/message.hpp deleted file mode 100644 index 2a747bfd1db..00000000000 --- a/dep/zmqpp/zmqpp/message.hpp +++ /dev/null @@ -1,254 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_MESSAGE_HPP_ -#define ZMQPP_MESSAGE_HPP_ - -#include <functional> -#include <string> -#include <unordered_map> -#include <vector> -#include <utility> -#include <cassert> - -#include <zmq.h> - -#include "compatibility.hpp" -#include "frame.hpp" - -namespace zmqpp -{ - -/*! - * \brief a zmq message with optional multipart support - * - * A zmq message is made up of one or more parts which are sent together to - * the target endpoints. zmq guarantees either the whole message or none - * of the message will be delivered. - */ -class message -{ -public: - /*! - * \brief callback to release user allocated data. - * - * The release function will be called on any void* moved part. - * It must be thread safe to the extent that the callback may occur on - * one of the context threads. - * - * The function called will be passed a single variable which is the - * pointer to the memory allocated. - */ - typedef std::function<void (void*)> release_function; - - message(); - ~message(); - - template <typename T, typename ...Args> - message(T const &part, Args &&...args) - : message() - { - add(part, std::forward<Args>(args)...); - } - - size_t parts() const; - size_t size(size_t const part) const; - std::string get(size_t const part) const; - - void get(int8_t& integer, size_t const part) const; - void get(int16_t& integer, size_t const part) const; - void get(int32_t& integer, size_t const part) const; - void get(int64_t& integer, size_t const part) const; - - void get(uint8_t& unsigned_integer, size_t const part) const; - void get(uint16_t& unsigned_integer, size_t const part) const; - void get(uint32_t& unsigned_integer, size_t const part) const; - void get(uint64_t& unsigned_integer, size_t const part) const; - - void get(float& floating_point, size_t const part) const; - void get(double& double_precision, size_t const part) const; - void get(bool& boolean, size_t const part) const; - - void get(std::string& string, size_t const part) const; - - // Warn: If a pointer type is requested the message (well zmq) still 'owns' - // the data and will release it when the message object is freed. - template<typename Type> - Type get(size_t const part) - { - Type value; - get(value, part); - return value; - } - - template<int part=0, typename T, typename ...Args> - void extract(T &nextpart, Args &...args) - { - assert(part < parts()); - get(nextpart,part); - extract<part+1>(args...); - } - - template<int part=0, typename T> - void extract(T &nextpart) - { - assert(part < parts()); - get(nextpart,part); - } - - // Raw get data operations, useful with data structures more than anything else - // Warn: The message (well zmq) still 'owns' the data and will release it - // when the message object is freed. - template<typename Type> - void get(Type*& value, size_t const part) const - { - value = static_cast<Type*>(raw_data(part)); - } - - // Warn: The message (well zmq) still 'owns' the data and will release it - // when the message object is freed. - template<typename Type> - void get(Type** value, size_t const part) const - { - *value = static_cast<Type*>(raw_data(part)); - } - - // Move operators will take ownership of message parts without copying - void move(void* part, size_t const size, release_function const& release); - - // Raw move data operation, useful with data structures more than anything else - template<typename Object> - void move(Object *part) - { - move(part, sizeof(Object), &deleter_callback<Object>); - } - - // Copy operators will take copies of any data - template<typename Type> - void add(Type *part, size_t const size) - { - _parts.push_back( frame( part, size ) ); - } - - - template<typename Type, typename ...Args> - void add(Type const& part, Args &&...args) - { - *this << part; - add(std::forward<Args>(args)...); - } - - template<typename Type> - void add(Type const part) - { - *this << part; - } - - // Stream reader style - void reset_read_cursor(); - - template<typename Type> - message& operator>>(Type& value) - { - get(value, _read_cursor++); - return *this; - } - - // Stream writer style - these all use copy styles - message& operator<<(int8_t const integer); - message& operator<<(int16_t const integer); - message& operator<<(int32_t const integer); - message& operator<<(int64_t const integer); - - message& operator<<(uint8_t const unsigned_integer); - message& operator<<(uint16_t const unsigned_integer); - message& operator<<(uint32_t const unsigned_integer); - message& operator<<(uint64_t const unsigned_integer); - - message& operator<<(float const floating_point); - message& operator<<(double const double_precision); - message& operator<<(bool const boolean); - - message& operator<<(char const* c_string); - message& operator<<(std::string const& string); - - // Queue manipulation - void push_front(void const* part, size_t const size); - - // TODO: unify conversion of types with the stream operators - void push_front(int8_t const integer); - void push_front(int16_t const integer); - void push_front(int32_t const integer); - void push_front(int64_t const integer); - - void push_front(uint8_t const unsigned_integer); - void push_front(uint16_t const unsigned_integer); - void push_front(uint32_t const unsigned_integer); - void push_front(uint64_t const unsigned_integer); - - void push_front(float const floating_point); - void push_front(double const double_precision); - void push_front(bool const boolean); - - void push_front(char const* c_string); - void push_front(std::string const& string); - - void pop_front(); - - void push_back(void const* part, size_t const size) - { - add( part, size ); - } - - template<typename Type> - void push_back(Type const part) - { - *this << part; - } - - void pop_back(); - - void remove(size_t const part); - - // Move supporting - message(message&& source) NOEXCEPT; - message& operator=(message&& source) NOEXCEPT; - - // Copy support - message copy() const; - void copy(message const& source); - - // Used for internal tracking - void sent(size_t const part); - - // Access to raw zmq details - void const* raw_data(size_t const part = 0) const; - zmq_msg_t& raw_msg(size_t const part = 0); - zmq_msg_t& raw_new_msg(); - zmq_msg_t& raw_new_msg(size_t const reserve_data_size); - -private: - typedef std::vector<frame> parts_type; - parts_type _parts; - size_t _read_cursor; - - // Disable implicit copy support, code must request a copy to clone - message(message const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; - message& operator=(message const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; - - static void release_callback(void* data, void* hint); - - template<typename Object> - static void deleter_callback(void* data) - { - delete static_cast<Object*>(data); - } -}; - -} - -#endif /* ZMQPP_MESSAGE_HPP_ */ diff --git a/dep/zmqpp/zmqpp/poller.cpp b/dep/zmqpp/zmqpp/poller.cpp deleted file mode 100644 index a6340c9bd61..00000000000 --- a/dep/zmqpp/zmqpp/poller.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Created on: 16 Aug 2011 - * Author: Ben Gray (@benjamg) - */ - -#include "exception.hpp" -#include "socket.hpp" -#include "poller.hpp" - -#include <zmq.h> - -namespace zmqpp -{ - -const long poller::wait_forever = -1; -const short poller::poll_none = 0; -const short poller::poll_in = ZMQ_POLLIN; -const short poller::poll_out = ZMQ_POLLOUT; -const short poller::poll_error = ZMQ_POLLERR; - -poller::poller() - : _items() - , _index() - , _fdindex() -{ - -} - -poller::~poller() -{ - _items.clear(); - _index.clear(); - _fdindex.clear(); -} - -void poller::add(socket& socket, short const event /* = POLL_IN */) -{ - zmq_pollitem_t item { socket, 0, event, 0 }; - - size_t index = _items.size(); - _items.push_back(item); - _index[socket] = index; -} - -void poller::add(int const descriptor, short const event /* = POLL_IN */) -{ - zmq_pollitem_t item { nullptr, descriptor, event, 0 }; - - size_t index = _items.size(); - _items.push_back(item); - _fdindex[descriptor] = index; -} - -bool poller::has(socket_t const& socket) -{ - return _index.find(socket) != _index.end(); -} - -bool poller::has(int const descriptor) -{ - return _fdindex.find(descriptor) != _fdindex.end(); -} - -void poller::reindex(size_t const index) -{ - if ( nullptr != _items[index].socket ) - { - auto found = _index.find( _items[index].socket ); - if (_index.end() == found) { throw exception("unable to reindex socket in poller"); } - found->second = index; - } - else - { - auto found = _fdindex.find( _items[index].fd ); - if (_fdindex.end() == found) { throw exception("unable to reindex file descriptor in poller"); } - found->second = index; - } -} - -void poller::remove(socket_t const& socket) -{ - auto found = _index.find(socket); - if (_index.end() == found) { return; } - - if ( _items.size() - 1 == found->second ) - { - _items.pop_back(); - _index.erase(found); - return; - } - - std::swap(_items[found->second], _items.back()); - _items.pop_back(); - - auto index = found->second; - _index.erase(found); - - reindex( index ); -} - -void poller::remove(int const descriptor) -{ - auto found = _fdindex.find(descriptor); - if (_fdindex.end() == found) { return; } - - if ( _items.size() - 1 == found->second ) - { - _items.pop_back(); - _fdindex.erase(found); - return; - } - - std::swap(_items[found->second], _items.back()); - _items.pop_back(); - - auto index = found->second; - _fdindex.erase(found); - - reindex( index ); -} - -void poller::check_for(socket const& socket, short const event) -{ - auto found = _index.find(socket); - if (_index.end() == found) - { - throw exception("this socket is not represented within this poller"); - } - - _items[found->second].events = event; -} - -void poller::check_for(int const descriptor, short const event) -{ - auto found = _fdindex.find(descriptor); - if (_fdindex.end() == found) - { - throw exception("this socket is not represented within this poller"); - } - - _items[found->second].events = event; -} - -bool poller::poll(long timeout /* = WAIT_FOREVER */) -{ - int result = zmq_poll(_items.data(), _items.size(), timeout); - if (result < 0) - { - if(EINTR == zmq_errno()) - { - return false; - } - - throw zmq_internal_exception(); - } - - return (result > 0); -} - -short poller::events(socket const& socket) const -{ - auto found = _index.find(socket); - if (_index.end() == found) - { - throw exception("this socket is not represented within this poller"); - } - - return _items[found->second].revents; -} - -short poller::events(int const descriptor) const -{ - auto found = _fdindex.find(descriptor); - if (_fdindex.end() == found) - { - throw exception("this file descriptor is not represented within this poller"); - } - - return _items[found->second].revents; -} - -} diff --git a/dep/zmqpp/zmqpp/poller.hpp b/dep/zmqpp/zmqpp/poller.hpp deleted file mode 100644 index a19063a091d..00000000000 --- a/dep/zmqpp/zmqpp/poller.hpp +++ /dev/null @@ -1,186 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_POLLER_HPP_ -#define ZMQPP_POLLER_HPP_ - -#include <unordered_map> -#include <vector> - -#include "compatibility.hpp" - -namespace zmqpp -{ - -class socket; -typedef socket socket_t; - -/*! - * Polling wrapper. - * - * Allows access to polling for any number of sockets or file descriptors. - */ -class poller -{ -public: - static const long wait_forever; /*!< Block forever flag, default setting. */ - - static const short poll_none; /*!< No polling flags set. */ - static const short poll_in; /*!< Monitor inbound flag. */ - static const short poll_out; /*!< Monitor output flag. */ - static const short poll_error; /*!< Monitor error flag.\n Only for file descriptors. */ - - /*! - * Construct an empty polling model. - */ - poller(); - - /*! - * Cleanup poller. - * - * Any sockets will need to be closed separately. - */ - ~poller(); - - /*! - * Add a socket to the polling model and set which events to monitor. - * - * \param socket the socket to monitor. - * \param event the event flags to monitor on the socket. - */ - void add(socket_t& socket, short const event = poll_in); - - /*! - * Add a file descriptor to the polling model and set which events to monitor. - * - * \param descriptor the file descriptor to monitor. - * \param event the event flags to monitor. - */ - void add(int const descriptor, short const event = poll_in | poll_error); - - /*! - * Check if we are monitoring a given socket with this poller. - * - * \param socket the socket to check. - * \return true if it is there. - */ - bool has(socket_t const& socket); - - /*! - * Check if we are monitoring a given file descriptor with this poller. - * - * \param descriptor the file descriptor to check. - * \return true if it is there. - */ - bool has(int const descriptor); - - /*! - * Stop monitoring a socket. - * - * \param socket the socket to stop monitoring. - */ - void remove(socket_t const& socket); - - /*! - * Stop monitoring a file descriptor. - * - * \param descriptor the file descriptor to stop monitoring. - */ - void remove(int const descriptor); - - /*! - * Update the monitored event flags for a given socket. - * - * \param socket the socket to update event flags. - * \param event the event flags to monitor on the socket. - */ - void check_for(socket_t const& socket, short const event); - - /*! - * Update the monitored event flags for a given file descriptor. - * - * \param descriptor the file descriptor to update event flags. - * \param event the event flags to monitor on the socket. - */ - void check_for(int const descriptor, short const event); - - /*! - * Poll for monitored events. - * - * By default this method will block forever or until at least one of the monitored - * sockets or file descriptors has events. - * - * If a timeout is set and was reached then this function returns false. - * - * \param timeout milliseconds to timeout. - * \return true if there is an event.. - */ - bool poll(long timeout = wait_forever); - - /*! - * Get the event flags triggered for a socket. - * - * \param socket the socket to get triggered event flags for. - * \return the event flags. - */ - short events(socket_t const& socket) const; - - /*! - * Get the event flags triggered for a file descriptor. - * - * \param descriptor the file descriptor to get triggered event flags for. - * \return the event flags. - */ - short events(int const descriptor) const; - - /*! - * Check either a file descriptor or socket for input events. - * - * Templated helper method that calls through to event and checks for a given flag - * - * \param watchable either a file descriptor or socket known to the poller. - * \return true if there is input. - */ - template<typename Watched> - bool has_input(Watched const& watchable) const { return events(watchable) & poll_in; } - - /*! - * Check either a file descriptor or socket for output events. - * - * Templated helper method that calls through to event and checks for a given flag - * - * \param watchable either a file descriptor or socket known to the poller. - * \return true if there is output. - */ - template<typename Watched> - bool has_output(Watched const& watchable) const { return events(watchable) & poll_out; } - - /*! - * Check a file descriptor. - * - * Templated helper method that calls through to event and checks for a given flag - * - * Technically this template works for sockets as well but the error flag is never set for - * sockets so I have no idea why someone would call it. - * - * \param watchable a file descriptor know to the poller. - * \return true if there is an error. - */ - template<typename Watched> - bool has_error(Watched const& watchable) const { return events(watchable) & poll_error; } - -private: - std::vector<zmq_pollitem_t> _items; - std::unordered_map<void *, size_t> _index; - std::unordered_map<int, size_t> _fdindex; - - void reindex(size_t const index); -}; - -} - -#endif /* ZMQPP_POLLER_HPP_ */ diff --git a/dep/zmqpp/zmqpp/socket.cpp b/dep/zmqpp/zmqpp/socket.cpp deleted file mode 100644 index 8b4efe4f1d2..00000000000 --- a/dep/zmqpp/zmqpp/socket.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Created on: 9 Aug 2011 - * Author: Ben Gray (@benjamg) - */ - -#include <array> -#include <cassert> -#include <cstring> -#include <functional> - -#include "context.hpp" -#include "exception.hpp" -#include "message.hpp" -#include "socket.hpp" - -namespace zmqpp -{ - -const int socket::normal = 0; -#if (ZMQ_VERSION_MAJOR == 2) -const int socket::dont_wait = ZMQ_NOBLOCK; -#else -const int socket::dont_wait = ZMQ_DONTWAIT; -#endif -const int socket::send_more = ZMQ_SNDMORE; -#ifdef ZMQ_EXPERIMENTAL_LABELS -const int socket::send_label = ZMQ_SNDLABEL; -#endif - -const int max_socket_option_buffer_size = 256; -const int max_stream_buffer_size = 4096; - -socket::socket(const context& context, socket_type const type) - : _socket(nullptr) - , _type(type) - , _recv_buffer() -{ - _socket = zmq_socket(context, static_cast<int>(type)); - if(nullptr == _socket) - { - throw zmq_internal_exception(); - } - - zmq_msg_init(&_recv_buffer); -} - -socket::~socket() -{ - zmq_msg_close(&_recv_buffer); - - if (nullptr != _socket) - { - -#ifndef NDEBUG // unused assert variable in release - int result = zmq_close(_socket); - assert(0 == result); -#else - zmq_close(_socket); -#endif // NDEBUG - - _socket = nullptr; - } -} - -void socket::bind(endpoint_t const& endpoint) -{ - int result = zmq_bind(_socket, endpoint.c_str()); - - if (0 != result) - { - throw zmq_internal_exception(); - } -} - -void socket::unbind(endpoint_t const& endpoint) -{ -#if (ZMQ_VERSION_MAJOR > 3 || (ZMQ_VERSION_MAJOR == 3 && ZMQ_VERSION_MINOR >= 2)) - int result = zmq_unbind(_socket, endpoint.c_str()); - - if (0 != result) - { - throw zmq_internal_exception(); - } -#endif -} - -void socket::connect(endpoint_t const& endpoint) -{ - int result = zmq_connect(_socket, endpoint.c_str()); - - if (0 != result) - { - throw zmq_internal_exception(); - } -} - -void socket::disconnect(endpoint_t const& endpoint) -{ -#if (ZMQ_VERSION_MAJOR > 3 || (ZMQ_VERSION_MAJOR == 3 && ZMQ_VERSION_MINOR >= 2)) - int result = zmq_disconnect(_socket, endpoint.c_str()); - - if (0 != result) - { - throw zmq_internal_exception(); - } -#endif -} - -void socket::close() -{ - int result = zmq_close(_socket); - - if (0 != result) - { - throw zmq_internal_exception(); - } - - _socket = nullptr; -} - -bool socket::send(message& message, bool const dont_block /* = false */) -{ - size_t parts = message.parts(); - if (parts == 0) - { - throw std::invalid_argument("sending requires messages have at least one part"); - } - - bool dont_wait = dont_block; - for(size_t i = 0; i < parts; ++i) - { - int flag = socket::normal; - if(dont_wait) { flag |= socket::dont_wait; } - if(i < (parts - 1)) { flag |= socket::send_more; } - -#if (ZMQ_VERSION_MAJOR == 2) - int result = zmq_send( _socket, &message.raw_msg(i), flag ); -#elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - int result = zmq_sendmsg( _socket, &message.raw_msg(i), flag ); -#else - int result = zmq_msg_send( &message.raw_msg(i), _socket, flag ); -#endif - - if (result < 0) - { - // the zmq framework should not block if the first part is accepted - // so we should only ever get this error on the first part - if((0 == i) && (EAGAIN == zmq_errno())) - { - return false; - } - - if(EINTR == zmq_errno()) - { - if (0 == message.parts()) - { - return false; - } - - // If we have an interrupt but it's not on the first part then we - // know we can safely send out the rest of the message as we can - // enforce that it won't wait on a blocking action - dont_wait = true; - continue; - } - - // sanity checking - assert(EAGAIN != zmq_errno()); - - throw zmq_internal_exception(); - } - - message.sent(i); - } - - // Leave message reference in a stable state - zmqpp::message local; - std::swap(local, message); - return true; -} - -bool socket::receive(message& message, bool const dont_block /* = false */) -{ - if (message.parts() > 0) - { - // swap and discard old message - zmqpp::message local; - std::swap(local, message); - } - - int flags = (dont_block) ? socket::dont_wait : socket::normal; - bool more = true; - - while(more) - { -#if (ZMQ_VERSION_MAJOR == 2) - int result = zmq_recv( _socket, &_recv_buffer, flags ); -#elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - int result = zmq_recvmsg( _socket, &_recv_buffer, flags ); -#else - int result = zmq_msg_recv( &_recv_buffer, _socket, flags ); -#endif - - if(result < 0) - { - if ((0 == message.parts()) && (EAGAIN == zmq_errno())) - { - return false; - } - - if(EINTR == zmq_errno()) - { - if (0 == message.parts()) - { - return false; - } - - // If we have an interrupt but it's not on the first part then we - // know we can safely pull out the rest of the message as it will - // not be blocking - continue; - } - - assert(EAGAIN != zmq_errno()); - - throw zmq_internal_exception(); - } - - zmq_msg_t& dest = message.raw_new_msg(); - zmq_msg_move(&dest, &_recv_buffer); - - get(socket_option::receive_more, more); - } - - return true; -} - - -bool socket::send(std::string const& string, int const flags /* = NORMAL */) -{ - return send_raw(string.data(), string.size(), flags); -} - -bool socket::receive(std::string& string, int const flags /* = NORMAL */) -{ -#if (ZMQ_VERSION_MAJOR == 2) - int result = zmq_recv( _socket, &_recv_buffer, flags ); -#elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - int result = zmq_recvmsg( _socket, &_recv_buffer, flags ); -#else - int result = zmq_msg_recv( &_recv_buffer, _socket, flags ); -#endif - - if(result >= 0) - { - string.reserve(zmq_msg_size(&_recv_buffer)); - string.assign(static_cast<char*>(zmq_msg_data(&_recv_buffer)), zmq_msg_size(&_recv_buffer)); - - return true; - } - - if (EAGAIN == zmq_errno() || EINTR == zmq_errno()) - { - return false; - } - - throw zmq_internal_exception(); -} - - -bool socket::send_raw(char const* buffer, int const length, int const flags /* = NORMAL */) -{ -#if (ZMQ_VERSION_MAJOR == 2) - zmq_msg_t msg; - int result = zmq_msg_init_size(&msg, length); - if (result != 0) - { - zmq_internal_exception(); - } - - memcpy(zmq_msg_data(&msg), buffer, length); - result = zmq_send(_socket, &msg, flags); -#else - int result = zmq_send(_socket, buffer, length, flags); -#endif - if(result >= 0) - { - return true; - } - -#if (ZMQ_VERSION_MAJOR == 2) - // only actually need to close this on error - zmq_msg_close(&msg); -#endif - - if (EAGAIN == zmq_errno() || EINTR == zmq_errno()) - { - return false; - } - - throw zmq_internal_exception(); -} - -bool socket::receive_raw(char* buffer, int& length, int const flags /* = NORMAL */) -{ -#if (ZMQ_VERSION_MAJOR == 2) - int result = zmq_recv( _socket, &_recv_buffer, flags ); -#elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2)) - int result = zmq_recvmsg( _socket, &_recv_buffer, flags ); -#else - int result = zmq_msg_recv( &_recv_buffer, _socket, flags ); -#endif - - if(result >= 0) - { - length = zmq_msg_size(&_recv_buffer); - memcpy(buffer, zmq_msg_data(&_recv_buffer), length); - - return true; - } - - if (EAGAIN == zmq_errno() || EINTR == zmq_errno()) - { - return false; - } - - throw zmq_internal_exception(); -} - - -// Helper -void socket::subscribe(std::string const& topic) -{ - set(socket_option::subscribe, topic); -} - -void socket::unsubscribe(std::string const& topic) -{ - set(socket_option::unsubscribe, topic); -} - -bool socket::has_more_parts() const -{ - return get<bool>(socket_option::receive_more); -} - - -// Set socket options for different types of option -void socket::set(socket_option const option, int const value) -{ - switch(option) - { - // unsigned 64bit Integers -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::high_water_mark: - case socket_option::send_buffer_size: - case socket_option::receive_buffer_size: -#endif - case socket_option::affinity: - if (value < 0) { throw exception("attempting to set an unsigned 64 bit integer option with a negative integer"); } - set(option, static_cast<uint64_t>(value)); - break; - - // 64bit Integers -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::rate: - case socket_option::recovery_interval: - case socket_option::recovery_interval_seconds: - case socket_option::swap_size: -#else - case socket_option::max_messsage_size: -#endif - set(option, static_cast<int64_t>(value)); - break; - - // Boolean -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1)) - case socket_option::ipv4_only: -#endif -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::multicast_loopback: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -#if (ZMQ_VERSION_MINOR == 2) - case socket_option::delay_attach_on_connect: -#else - case socket_option::immediate: -#endif - case socket_option::router_mandatory: - case socket_option::xpub_verbose: -#endif - if (value == 0) { set(option, false); } - else if (value == 1) { set(option, true); } - else { throw exception("attempting to set a boolean option with a non 0 or 1 integer"); } - break; - - // Default or Boolean -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) - case socket_option::tcp_keepalive: - if (value < -1 || value > 1) { throw exception("attempting to set a default or boolean option with a non -1, 0 or 1 integer"); } - if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value))) - { - throw zmq_internal_exception(); - } - break; -#endif - - // Integers that require +ve numbers -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::reconnect_interval_max: -#else - case socket_option::reconnect_interval_max: - case socket_option::send_buffer_size: - case socket_option::recovery_interval: - case socket_option::receive_buffer_size: - case socket_option::send_high_water_mark: - case socket_option::receive_high_water_mark: - case socket_option::multicast_hops: - case socket_option::rate: -#endif - case socket_option::backlog: - if (value < 0) { throw exception("attempting to set a positive only integer option with a negative integer"); } - // Integers - case socket_option::reconnect_interval: - case socket_option::linger: - case socket_option::receive_timeout: - case socket_option::send_timeout: -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) - case socket_option::tcp_keepalive_idle: - case socket_option::tcp_keepalive_count: - case socket_option::tcp_keepalive_interval: -#endif - if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value))) - { - throw zmq_internal_exception(); - } - break; - default: - throw exception("attempting to set a non signed integer option with a signed integer value"); - } -} - -void socket::set(socket_option const option, bool const value) -{ - switch(option) - { -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::multicast_loopback: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1)) - case socket_option::ipv4_only: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -#if (ZMQ_VERSION_MINOR == 2) - case socket_option::delay_attach_on_connect: -#else - case socket_option::immediate: -#endif - case socket_option::router_mandatory: - case socket_option::xpub_verbose: -#endif - { - int ivalue = value ? 1 : 0; - if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &ivalue, sizeof(ivalue))) - { - throw zmq_internal_exception(); - } - break; - } - default: - throw exception("attempting to set a non boolean option with a boolean value"); - } -} - -void socket::set(socket_option const option, uint64_t const value) -{ - switch(option) - { -#if (ZMQ_VERSION_MAJOR == 2) - // unsigned 64bit Integers - case socket_option::high_water_mark: - case socket_option::send_buffer_size: - case socket_option::receive_buffer_size: -#endif - case socket_option::affinity: - if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value))) - { - throw zmq_internal_exception(); - } - break; - default: - throw exception("attempting to set a non unsigned 64 bit integer option with a unsigned 64 bit integer value"); - } -} - -void socket::set(socket_option const option, int64_t const value) -{ - switch(option) - { -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::rate: - case socket_option::recovery_interval: - case socket_option::recovery_interval_seconds: - case socket_option::swap_size: -#else - case socket_option::max_messsage_size: -#endif - // zmq only allowed +ve int64_t options - if (value < 0) { throw exception("attempting to set a positive only 64 bit integer option with a negative 64bit integer"); } - if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value))) - { - throw zmq_internal_exception(); - } - break; - default: - throw exception("attempting to set a non 64 bit integer option with a 64 bit integer value"); - } -} - -void socket::set(socket_option const option, char const* value, size_t const length) -{ - switch(option) - { - case socket_option::identity: - case socket_option::subscribe: - case socket_option::unsubscribe: -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) - case socket_option::tcp_accept_filter: -#endif - if (0 != zmq_setsockopt(_socket, static_cast<int>(option), value, length)) - { - throw zmq_internal_exception(); - } - break; - default: - throw exception("attempting to set a non string option with a string value"); - } -} - -// Get socket options, multiple versions for easy of use -void socket::get(socket_option const option, int& value) const -{ - size_t value_size = sizeof(int); - - switch(option) - { -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::receive_more: - case socket_option::multicast_loopback: - value = static_cast<int>(get<int64_t>(option)); - break; -#endif - case socket_option::type: - case socket_option::linger: - case socket_option::backlog: - case socket_option::reconnect_interval: - case socket_option::reconnect_interval_max: - case socket_option::receive_timeout: - case socket_option::send_timeout: - case socket_option::file_descriptor: - case socket_option::events: -#if (ZMQ_VERSION_MAJOR > 2) - case socket_option::receive_more: - case socket_option::send_buffer_size: - case socket_option::receive_buffer_size: - case socket_option::rate: - case socket_option::recovery_interval: - case socket_option::send_high_water_mark: - case socket_option::receive_high_water_mark: - case socket_option::multicast_hops: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1)) - case socket_option::ipv4_only: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -#if (ZMQ_VERSION_MINOR == 2) - case socket_option::delay_attach_on_connect: -#else - case socket_option::immediate: -#endif - case socket_option::tcp_keepalive: - case socket_option::tcp_keepalive_idle: - case socket_option::tcp_keepalive_count: - case socket_option::tcp_keepalive_interval: -#endif -#ifdef ZMQ_EXPERIMENTAL_LABELS - case socket_option::receive_label: -#endif - if (0 != zmq_getsockopt(_socket, static_cast<int>(option), &value, &value_size)) - { - throw zmq_internal_exception(); - } - - // sanity check - assert(value_size <= sizeof(int)); - break; - default: - throw exception("attempting to get a non integer option with an integer value"); - } -} - -void socket::get(socket_option const option, bool& value) const -{ -#if (ZMQ_VERSION_MAJOR == 2) - int64_t int_value = 0; - size_t value_size = sizeof(int64_t); -#else - int int_value = 0; - size_t value_size = sizeof(int); -#endif - - switch(option) - { - case socket_option::receive_more: -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::multicast_loopback: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1)) - case socket_option::ipv4_only: -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -#if (ZMQ_VERSION_MINOR == 2) - case socket_option::delay_attach_on_connect: -#else - case socket_option::immediate: -#endif -#endif -#ifdef ZMQ_EXPERIMENTAL_LABELS - case socket_option::receive_label: -#endif - if (0 != zmq_getsockopt(_socket, static_cast<int>(option), &int_value, &value_size)) - { - throw zmq_internal_exception(); - } - - value = (int_value == 1) ? true : false; - break; - default: - throw exception("attempting to get a non boolean option with a boolean value"); - } -} - -void socket::get(socket_option const option, uint64_t& value) const -{ - size_t value_size = sizeof(uint64_t); - - switch(option) - { -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::high_water_mark: - case socket_option::send_buffer_size: - case socket_option::receive_buffer_size: -#endif - case socket_option::affinity: - if(0 != zmq_getsockopt(_socket, static_cast<int>(option), &value, &value_size)) - { - throw zmq_internal_exception(); - } - break; - default: - throw exception("attempting to get a non unsigned 64 bit integer option with an unsigned 64 bit integer value"); - } -} - -void socket::get(socket_option const option, int64_t& value) const -{ - size_t value_size = sizeof(int64_t); - - switch(option) - { -#if (ZMQ_VERSION_MAJOR == 2) - case socket_option::rate: - case socket_option::recovery_interval: - case socket_option::recovery_interval_seconds: - case socket_option::swap_size: - case socket_option::receive_more: - case socket_option::multicast_loopback: -#else - case socket_option::max_messsage_size: -#endif - if(0 != zmq_getsockopt(_socket, static_cast<int>(option), &value, &value_size)) - { - throw zmq_internal_exception(); - } - break; - default: - throw exception("attempting to get a non 64 bit integer option with an 64 bit integer value"); - } -} - -void socket::get(socket_option const option, std::string& value) const -{ - static std::array<char, max_socket_option_buffer_size> buffer; - size_t size = max_socket_option_buffer_size; - - switch(option) - { - case socket_option::identity: -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) - case socket_option::last_endpoint: -#endif - if(0 != zmq_getsockopt(_socket, static_cast<int>(option), buffer.data(), &size)) - { - throw zmq_internal_exception(); - } - - value.assign(buffer.data(), size); - break; - default: - throw exception("attempting to get a non string option with a string value"); - } -} - -socket::socket(socket&& source) NOEXCEPT - : _socket(source._socket) - , _type(source._type) - , _recv_buffer() -{ - // we steal the zmq_msg_t from the valid socket, we only init our own because it's cheap - // and zmq_msg_move does a valid check - zmq_msg_init(&_recv_buffer); - zmq_msg_move(&_recv_buffer, &source._recv_buffer); - - // Clean up source a little, we will handle the deinit, it doesn't need to - source._socket = nullptr; -} - -socket& socket::operator=(socket&& source) NOEXCEPT -{ - std::swap(_socket, source._socket); - - _type = source._type; // just clone? - - // we steal the zmq_msg_t from the valid socket, we only init our own because it's cheap - // and zmq_msg_move does a valid check - zmq_msg_init(&_recv_buffer); - zmq_msg_move(&_recv_buffer, &source._recv_buffer); - - return *this; -} - - -socket::operator bool() const -{ - return nullptr != _socket; -} - - -socket::operator void*() const -{ - return _socket; -} - -void socket::track_message(message const& /* message */, uint32_t const parts, bool& should_delete) -{ - if (parts == 0) - { - should_delete = true; - } -} - -} diff --git a/dep/zmqpp/zmqpp/socket.hpp b/dep/zmqpp/zmqpp/socket.hpp deleted file mode 100644 index 279bf801f77..00000000000 --- a/dep/zmqpp/zmqpp/socket.hpp +++ /dev/null @@ -1,500 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_SOCKET_HPP_ -#define ZMQPP_SOCKET_HPP_ - -#include <cstring> -#include <string> -#include <list> - -#include <zmq.h> - -#include "compatibility.hpp" - -#include "socket_types.hpp" -#include "socket_options.hpp" - -namespace zmqpp -{ - -class context; -class message; - -typedef std::string endpoint_t; -typedef context context_t; -typedef message message_t; - -/*! - * The socket class represents the zmq sockets. - * - * A socket can be bound and/or connected to as many endpoints as required - * with the sole exception of a ::pair socket. - * - * The routing is handled by zmq based on the type set. - * - * The bound side of an inproc connection must occur first and inproc can only - * connect to other inproc sockets of the same context. - * - * This class is c++0x move supporting and cannot be copied. - */ -class socket -{ -public: - static const int normal; /*!< /brief default send type, no flags set */ -#if (ZMQ_VERSION_MAJOR == 2) - static const int dont_wait; /*!< /brief don't block if sending is not currently possible */ -#else - static const int dont_wait; /*!< /brief don't block if sending is not currently possible */ -#endif - static const int send_more; /*!< /brief more parts will follow this one */ -#ifdef ZMQ_EXPERIMENTAL_LABELS - static const int send_label; /*!< /brief this message part is an internal zmq label */ -#endif - - /*! - * Create a socket for a given type. - * - * \param context the zmq context under which the socket will live - * \param type a valid ::socket_type for the socket - */ - socket(context_t const& context, socket_type const type); - - /*! - * This will close any socket still open before returning - */ - ~socket(); - - /*! - * Get the type of the socket, this works on zmqpp types and not the zmq internal types. - * Use the socket::get method if you wish to intergoate the zmq internal ones. - * - * \return the type of the socket - */ - socket_type type() const { return _type; } - - /*! - * Asynchronously binds to an endpoint. - * - * \param endpoint the zmq endpoint to bind to - */ - void bind(endpoint_t const& endpoint); - - /*! - * Unbinds from a previously bound endpoint. - * - * \param endpoint the zmq endpoint to bind to - */ - void unbind(endpoint_t const& endpoint); - - /*! - * Asynchronously connects to an endpoint. - * If the endpoint is not inproc then zmq will happily keep trying - * to connect until there is something there. - * - * Inproc sockets must have a valid target already bound before connection - * will work. - * - * \param endpoint the zmq endpoint to connect to - */ - void connect(endpoint_t const& endpoint); - - /*! - * Asynchronously connects to multiple endpoints. - * If the endpoint is not inproc then zmq will happily keep trying - * to connect until there is something there. - * - * Inproc sockets must have a valid target already bound before connection - * will work. - * - * This is a helper function that wraps the single item connect in a loop - * - * \param connections_begin the starting iterator for zmq endpoints. - * \param connections_end the final iterator for zmq endpoints. - */ - template<typename InputIterator> - void connect(InputIterator const& connections_begin, InputIterator const& connections_end) - { - for(InputIterator it = connections_begin; it != connections_end; ++it) - { - connect(*it); - } - } - - - /*! - * Disconnects a previously connected endpoint. - * - * \param endpoint the zmq endpoint to disconnect from - */ - void disconnect(endpoint_t const& endpoint); - - /*! - * Disconnects from multiple previously connected endpoints. - * - * This is a helper function that wraps the single item disconnect in a loop - * - * \param disconnections_begin the starting iterator for zmq endpoints. - * \param disconnections_end the final iterator for zmq endpoints. - */ - template<typename InputIterator> - void disconnect(InputIterator const& disconnections_begin, InputIterator const& disconnections_end) - { - for(InputIterator it = disconnections_begin; it != disconnections_end; ++it) - { - disconnect(*it); - } - } - - /*! - * Closes the internal zmq socket and marks this instance - * as invalid. - */ - void close(); - - /*! - * Sends the message over the connection, this may be a multipart message. - * - * If dont_block is true and we are unable to add a new message then this - * function will return false. - * - * \param message message to send - * \param dont_block boolean to dictate if we wait while sending. - * \return true if message sent, false if it would have blocked - */ - bool send(message_t& message, bool const dont_block = false); - - /*! - * Gets a message from the connection, this may be a multipart message. - * - * If dont_block is true and we are unable to get a message then this - * function will return false. - * - * \param message reference to fill with received data - * \param dont_block boolean to dictate if we wait for data. - * \return true if message sent, false if it would have blocked - */ - bool receive(message_t& message, bool const dont_block = false); - - /*! - * Sends the byte data held by the string as the next message part. - * - * If the socket::DONT_WAIT flag and we are unable to add a new message to - * socket then this function will return false. - * - * \param string message part to send - * \param flags message send flags - * \return true if message part sent, false if it would have blocked - */ - bool send(std::string const& string, int const flags = normal); - - /*! - * If there is a message ready then get the next part as a string - * - * If the socket::DONT_WAIT flag and there is no message ready to receive - * then this function will return false. - * - * \param string message part to receive into - * \param flags message receive flags - * \return true if message part received, false if it would have blocked - */ - bool receive(std::string& string, int const flags = normal); - - /*! - * Sends the byte data pointed to by buffer as the next part of the message. - * - * If the socket::DONT_WAIT flag and we are unable to add a new message to - * socket then this function will return false. - * - * \param buffer byte buffer pointer to start writing from - * \param length max length of the buffer - * \param flags message send flags - * \return true if message part sent, false if it would have blocked - */ - bool send_raw(char const* buffer, int const length, int const flags = normal); - - /*! - * \warning If the buffer is not large enough for the message part then the - * data will be truncated. The rest of the part is lost forever. - * - * If there is a message ready then get the next part of it as a raw - * byte buffer. - * - * If the socket::DONT_WAIT flag and there is no message ready to receive - * then this function will return false. - * - * \param buffer byte buffer pointer to start writing to - * \param length max length of the buffer - * \param flags message receive flags - * \return true if message part received, false if it would have blocked - */ - bool receive_raw(char* buffer, int& length, int const flags = normal); - - /*! - * - * Subscribe to a topic - * - * Helper function that is equivalent of calling - * \code - * set(zmqpp::socket_option::subscribe, topic); - * \endcode - * - * This method is only useful for subscribe type sockets. - * - * \param topic the topic to subscribe to. - */ - void subscribe(std::string const& topic); - - /*! - * Subscribe to a topic - * - * Helper function that is equivalent of a loop calling - * \code - * set(zmqpp::socket_option::subscribe, topic); - * \endcode - * - * This method is only useful for subscribe type sockets. - * - * Generally this will be used with stl collections using begin() and - * end() functions to get the iterators. - * For this reason the end loop runs until the end iterator, not inclusive - * of it. - * - * \param topics_begin the starting iterator for topics. - * \param topics_end the final iterator for topics. - */ - template<typename InputIterator> - void subscribe(InputIterator const& topics_begin, InputIterator const& topics_end) - { - for(InputIterator it = topics_begin; it != topics_end; ++it) - { - subscribe(*it); - } - } - - /*! - * Unsubscribe from a topic - * - * Helper function that is equivalent of calling - * \code - * set(zmqpp::socket_option::unsubscribe, topic); - * \endcode - * - * This method is only useful for subscribe type sockets. - * - * \param topic the topic to unsubscribe from. - */ - void unsubscribe(std::string const& topic); - - /*! - * Unsubscribe from a topic - * - * Helper function that is equivalent of a loop calling - * \code - * set(zmqpp::socket_option::unsubscribe, topic); - * \endcode - * - * This method is only useful for subscribe type sockets. - * - * Generally this will be used with stl collections using begin() and - * end() functions to get the iterators. - * For this reason the end loop runs until the end iterator, not inclusive - * of it. - * - * \param topics_begin the starting iterator for topics. - * \param topics_end the final iterator for topics. - */ - template<typename InputIterator> - void unsubscribe(InputIterator const& topics_begin, InputIterator const& topics_end) - { - for(InputIterator it = topics_begin; it != topics_end; ++it) - { - unsubscribe(*it); - } - } - - /*! - * If the last receive part call to the socket resulted - * in a label or a non-terminating part of a multipart - * message this will return true. - * - * \return true if there are more parts - */ - bool has_more_parts() const; - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value to set the option to - */ - void set(socket_option const option, int const value); - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \since 2.0.0 (built against 0mq version 3.1.x or later) - * - * \param option a valid ::socket_option - * \param value to set the option to - */ - void set(socket_option const option, bool const value); - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value to set the option to - */ - void set(socket_option const option, uint64_t const value); - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value to set the option to - */ - void set(socket_option const option, int64_t const value); - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param pointer to raw byte value to set the option to - * \param length the size of the raw byte value - */ - void set(socket_option const option, char const* value, size_t const length); - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param pointer to null terminated cstring value to set the option to - */ - inline void set(socket_option const option, char const* value) { set(option, value, strlen(value)); } - - /*! - * Set the value of an option in the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value to set the option to - */ - inline void set(socket_option const option, std::string const value) { set(option, value.c_str(), value.length()); } - - /*! - * Get a socket option from the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value referenced int to return value in - */ - void get(socket_option const option, int& value) const; - - /*! - * Get a socket option from the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value referenced bool to return value in - */ - void get(socket_option const option, bool& value) const; - - /*! - * Get a socket option from the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value referenced uint64_t to return value in - */ - void get(socket_option const option, uint64_t& value) const; - - /*! - * Get a socket option from the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value referenced uint64_t to return value in - */ - void get(socket_option const option, int64_t& value) const; - - /*! - * Get a socket option from the underlaying zmq socket. - * - * \param option a valid ::socket_option - * \param value referenced std::string to return value in - */ - void get(socket_option const option, std::string& value) const; - - /*! - * For those that don't want to get into a referenced value this templated method - * will return the value instead. - * - * \param option a valid ::socket_option - * \return socket option value - */ - template<typename Type> - Type get(socket_option const option) const - { - Type value = Type(); - get(option, value); - return value; - } - - /*! - * Move constructor - * - * Moves the internals of source to this object, there is no guarantee - * that source will be left in a valid state. - * - * This constructor is noexcept and so will not throw exceptions - * - * \param source target socket to steal internals from - */ - socket(socket&& source) NOEXCEPT; - - /*! - * Move operator - * - * Moves the internals of source to this object, there is no guarantee - * that source will be left in a valid state. - * - * This function is noexcept and so will not throw exceptions - * - * \param source target socket to steal internals from - * \return socket reference to this - */ - socket& operator=(socket&& source) NOEXCEPT; - - /*! - * Check the socket is still valid - * - * This tests the internal state of the socket. - * If creation failed for some reason or if the move functions were used - * to move the socket internals to another instance this will return false. - * - * \return true if the socket is valid - */ - operator bool() const; - - /*! - * Access to the raw 0mq context - * - * \return void pointer to the underlying 0mq socket - */ - operator void*() const; - -private: - void* _socket; - socket_type _type; - zmq_msg_t _recv_buffer; - - // No copy - socket(socket const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; - socket& operator=(socket const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED; - - void track_message(message_t const&, uint32_t const, bool&); -}; - -} - -#endif /* ZMQPP_SOCKET_HPP_ */ diff --git a/dep/zmqpp/zmqpp/socket_options.hpp b/dep/zmqpp/zmqpp/socket_options.hpp deleted file mode 100644 index c5c8586cbc7..00000000000 --- a/dep/zmqpp/zmqpp/socket_options.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/** - * \file - * - * \date 23 Sep 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_SOCKET_OPTIONS_HPP_ -#define ZMQPP_SOCKET_OPTIONS_HPP_ - -namespace zmqpp -{ - -/** \todo Expand the information on the options to make it actually useful. */ -/*! - * \brief possible Socket options in zmq - */ - -enum class socket_option { - affinity = ZMQ_AFFINITY, /*!< I/O thread affinity */ - identity = ZMQ_IDENTITY, /*!< Socket identity */ - subscribe = ZMQ_SUBSCRIBE, /*!< Add topic subscription - set only */ - unsubscribe = ZMQ_UNSUBSCRIBE, /*!< Remove topic subscription - set only */ - rate = ZMQ_RATE, /*!< Multicast data rate */ - send_buffer_size = ZMQ_SNDBUF, /*!< Kernel transmission buffer size */ - receive_buffer_size = ZMQ_RCVBUF, /*!< Kernel receive buffer size */ - receive_more = ZMQ_RCVMORE, /*!< Can receive more parts - get only */ - file_descriptor = ZMQ_FD, /*!< Socket file descriptor - get only */ - events = ZMQ_EVENTS, /*!< Socket event flags - get only */ - type = ZMQ_TYPE, /*!< Socket type - get only */ - linger = ZMQ_LINGER, /*!< Socket linger timeout */ - backlog = ZMQ_BACKLOG, /*!< Maximum length of outstanding connections - get only */ -#if (ZMQ_VERSION_MAJOR == 2) - // Note that this is inverse of the zmq names for version 2.x - recovery_interval_seconds = ZMQ_RECOVERY_IVL, /*!< Multicast recovery interval in seconds */ - recovery_interval = ZMQ_RECOVERY_IVL_MSEC, /*!< Multicast recovery interval in milliseconds */ -#else - recovery_interval = ZMQ_RECOVERY_IVL, /*!< Multicast recovery interval in milliseconds */ -#endif - reconnect_interval = ZMQ_RECONNECT_IVL, /*!< Reconnection interval */ - reconnect_interval_max = ZMQ_RECONNECT_IVL_MAX, /*!< Maximum reconnection interval */ - receive_timeout = ZMQ_RCVTIMEO, /*!< Maximum inbound block timeout */ - send_timeout = ZMQ_SNDTIMEO, /*!< Maximum outbound block timeout */ -#if (ZMQ_VERSION_MAJOR == 2) - high_water_mark = ZMQ_HWM, /*!< High-water mark for all messages */ - swap_size = ZMQ_SWAP, /*!< Maximum socket swap size in bytes */ - multicast_loopback = ZMQ_MCAST_LOOP, /*!< Allow multicast packet loopback */ -#else - max_messsage_size = ZMQ_MAXMSGSIZE, /*!< Maximum inbound message size */ - send_high_water_mark = ZMQ_SNDHWM, /*!< High-water mark for outbound messages */ - receive_high_water_mark = ZMQ_RCVHWM, /*!< High-water mark for inbound messages */ - multicast_hops = ZMQ_MULTICAST_HOPS, /*!< Maximum number of multicast hops */ -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1)) - ipv4_only = ZMQ_IPV4ONLY, -#endif -#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2)) -#if (ZMQ_VERSION_MINOR == 2) - delay_attach_on_connect = ZMQ_DELAY_ATTACH_ON_CONNECT, /*!< Delay buffer attachment until connect complete */ -#else - // ZMQ_DELAY_ATTACH_ON_CONNECT is renamed in ZeroMQ starting 3.3.x - immediate = ZMQ_IMMEDIATE, /*!< Block message sending until connect complete */ -#endif - last_endpoint = ZMQ_LAST_ENDPOINT, /*!< Last bound endpoint - get only */ - router_mandatory = ZMQ_ROUTER_MANDATORY, /*!< Require routable messages - set only */ - xpub_verbose = ZMQ_XPUB_VERBOSE, /*!< Pass on existing subscriptions - set only */ - tcp_keepalive = ZMQ_TCP_KEEPALIVE, /*!< Enable TCP keepalives */ - tcp_keepalive_idle = ZMQ_TCP_KEEPALIVE_IDLE, /*!< TCP keepalive idle count (generally retry count) */ - tcp_keepalive_count = ZMQ_TCP_KEEPALIVE_CNT, /*!< TCP keepalive retry count */ - tcp_keepalive_interval = ZMQ_TCP_KEEPALIVE_INTVL, /*!< TCP keepalive interval */ - tcp_accept_filter = ZMQ_TCP_ACCEPT_FILTER, /*!< Filter inbound connections - set only */ -#endif -#ifdef ZMQ_EXPERIMENTAL_LABELS - receive_label = ZMQ_RCVLABEL, /*!< Received label part - get only */ -#endif -}; - -} - -#endif /* ZMQPP_SOCKET_OPTIONS_HPP_ */ diff --git a/dep/zmqpp/zmqpp/socket_types.hpp b/dep/zmqpp/zmqpp/socket_types.hpp deleted file mode 100644 index e59e71ca0e1..00000000000 --- a/dep/zmqpp/zmqpp/socket_types.hpp +++ /dev/null @@ -1,148 +0,0 @@ -/** - * \file - * - * \date 23 Sep 2011 - * \author Ben Gray (\@benjamg) - */ - -#ifndef ZMQPP_SOCKET_TYPES_HPP_ -#define ZMQPP_SOCKET_TYPES_HPP_ - -namespace zmqpp -{ - -/*! - * \brief Socket types allowed by zmq - * - * The socket type choose at creation must be one of these types. - * - * Each is designed for a different use and has different limitations. - */ -enum class socket_type { - /*! - * One to one - two way connection.\n - * Connect to ::pair.\n - * A \c pair socket has to be connected only one other pair socket and allows - * two way communication between them. - */ - pair = ZMQ_PAIR, - - /*! - * One to many - fan out.\n - * Connect to ::subscribe or ::xsubscribe.\n - * Socket is send only.\n - * Socket will drop messages and not block.\n - * \c publish sockets allow sending of the same message to many subscribers - * each subscriber can limit what is sent through the socket_option::subscribe - * settings. - */ - publish = ZMQ_PUB, - - /*! - * \note It seems doxygen can't work out which data is for the socket type and - * which is for the socket option so both get listed for both. - * - * One to many - fair-queued.\n - * Connect to ::publish or ::xpublish.\n - * Socket is receive only.\n - * The \c subscribe socket can connection to any number of publishers and will - * fairly pull messages from each. The socket_option::subscribe settings can - * be use to limit which messages are received and by default none are. - */ - subscribe = ZMQ_SUB, - - /*! - * One to many - fair-queued.\n - * Connect to ::push.\n - * Socket is receive only.\n - * The \c pull socket fairly pulls messages from all pushers it is connected - * to. - */ - pull = ZMQ_PULL, - - /*! - * One to many - load-balanced.\n - * Connect to ::pull.\n - * Socket is send only.\n - * Socket will block if unable to send.\n - * The \c push socket fairly distributes messages between any connected - * puller sockets. - */ - push = ZMQ_PUSH, - - /*! - * One to many - fair-queued outgoing, last peer incoming.\n - * Connect to ::reply or ::xreply.\n - * Socket flips between send and receive only.\n - * Socket will block if unable to send.\n - * The \c request socket will fairly balance requests sent out to a - * replier and then can only be used to receive until that replier - * sends a reply. - */ - request = ZMQ_REQ, - - /*! - * One to many - load-balanced incoming, last peer outgoing.\n - * Connect to ::request or ::xrequest.\n - * Socket flips between send and receive only.\n - * Socket will drop messages and not block.\n - * The \c reply socket can only receive until it pulls a message from a - * requester at which point it can only send until the reply is sent. - */ - reply = ZMQ_REP, - - /*! - * One to many - fan out.\n - * Connect to ::subscribe or ::xsubscribe.\n - * Socket is send only with the exception of special subscription messages.\n - * Socket will drop messages and not block.\n - * \c xpublish act the same as ::publish sockets however also allow special - * subscription messages to be received from subscribers. - */ - xpublish = ZMQ_XPUB, - - /*! - * One to many - fair-queued.\n - * Connect to ::publish or ::xpublish.\n - * Socket is receive only with the exception of special subscription messages\n - * \c xsubscribe act the same as ::subscribe sockets however also allow special - * subscription messages to be send to connected publishers. - */ - xsubscribe = ZMQ_XSUB, - - /*! - * One to many - fair-queued incoming, load-balanced outgoing.\n - * Connect to ::reply or ::xreply.\n - * Socket will block if unable to send.\n - * An \c xrequest socket balances requests between repliers and pulls replies - * back in a fair manner. Each request is expected to have exactly one reply. - */ - xrequest = ZMQ_XREQ, - - /*! - * One to many - fair-queued incoming, targeted outgoing.\n - * Connect to ::request or ::xrequest.\n - * Socket will drop messages and not block.\n - * An \c xreply socket fairly pulls in requests from requesters and will - * label requests so it can return replies back to the correct target. - */ - xreply = ZMQ_XREP, - - // To match for people who prefer the shorter versions - pub = ZMQ_PUB, /*!< version of ::publish to match zmq name convention */ - sub = ZMQ_SUB, /*!< version of ::subscribe to match zmq name convention */ - req = ZMQ_REQ, /*!< version of ::request to match zmq name convention */ - rep = ZMQ_REP, /*!< version of ::reply to match zmq name convention */ - xpub = ZMQ_XPUB, /*!< version of ::xpublish to match zmq name convention */ - xsub = ZMQ_XSUB, /*!< version of ::xsubscribe to match zmq name convention */ - xreq = ZMQ_XREQ, /*!< version of ::xrequest to match zmq name convention */ - xrep = ZMQ_XREP, /*!< version of ::xreply to match zmq name convention */ - - // For completion - router = ZMQ_ROUTER, /*!< \deprecated Matches zmq 2.x xrep functionality. */ - dealer = ZMQ_DEALER /*!< \deprecated Matches zmq 2.x xreq functionality. */ -}; - -} - -#endif /* ZMQPP_SOCKET_TYPES_HPP_ */ diff --git a/dep/zmqpp/zmqpp/zmqpp.cpp b/dep/zmqpp/zmqpp/zmqpp.cpp deleted file mode 100644 index 216948e73e7..00000000000 --- a/dep/zmqpp/zmqpp/zmqpp.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Created on: 18 Aug 2011 - * Author: Ben Gray (@benjamg) - */ - -#include "zmqpp.hpp" - -namespace zmqpp -{ - -std::string version() -{ - return BUILD_VERSION; -} - -void version(uint8_t& major, uint8_t& minor, uint8_t& revision) -{ - major = ZMQPP_VERSION_MAJOR; - minor = ZMQPP_VERSION_MINOR; - revision = ZMQPP_VERSION_REVISION; -} - -void zmq_version(uint8_t& major, uint8_t& minor, uint8_t& patch) -{ - major = ZMQ_VERSION_MAJOR; - minor = ZMQ_VERSION_MINOR; - patch = ZMQ_VERSION_PATCH; -} - -} diff --git a/dep/zmqpp/zmqpp/zmqpp.hpp b/dep/zmqpp/zmqpp/zmqpp.hpp deleted file mode 100644 index 92a47ce38bf..00000000000 --- a/dep/zmqpp/zmqpp/zmqpp.hpp +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file - * - * \date 9 Aug 2011 - * \author Ben Gray (\@benjamg) - * - * License: http://www.opensource.org/licenses/MIT - * - * Copyright (C) 2011 by Ben Gray - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef ZMQPP_ZMQPP_HPP_ -#define ZMQPP_ZMQPP_HPP_ - -/** - * \def ZMQPP_VERSION_MAJOR - * zmqpp major version number, generated at compile time - */ -#define ZMQPP_VERSION_MAJOR BUILD_VERSION_MAJOR - -/** - * \def ZMQPP_VERSION_MINOR - * zmqpp minor version number, generated at compile time - */ -#define ZMQPP_VERSION_MINOR BUILD_VERSION_MINOR - -/** - * \def ZMQPP_VERSION_REVISION - * zmqpp version revision number, generated at compile time - */ -#define ZMQPP_VERSION_REVISION BUILD_VERSION_REVISION - -#include <zmq.h> - -#include "compatibility.hpp" -#include "context.hpp" -#include "exception.hpp" -#include "message.hpp" -#include "poller.hpp" -#include "socket.hpp" - -/*! - * \brief C++ wrapper around zmq - * - * All zmq++ / zmqpp functions, constants and classes live within this namespace, - */ -namespace zmqpp -{ - -/*! - * Returns the current major.minor.revision version number as a string. - * - * \return string version number. - */ -std::string version(); - -/*! - * Retrieve the parts of the zmqpp version number. - * - * Set the three parameters to values representing the zmqpp version number. - * These values are generated at library compile time. - * - * \param major an unsigned 8 bit reference to set to the major version. - * \param minor an unsigned 8 bit reference to set to the minor version. - * \param revision an unsigned 8 bit reference to set the current revision. - */ -void version(uint8_t& major, uint8_t& minor, uint8_t& revision); - -/*! - * Retrieve the parts of the 0mq version this library was built against. - * - * Because sections of the library are optionally compiled in or ignored - * depending on the version of 0mq it was compiled against this method is - * provided to allow sanity checking for usage. - * - * Set the three parameters to values representing the 0mq version number. - * These values are generated at library compile time. - * - * \param major an unsigned 8 bit reference to set to the major version. - * \param minor an unsigned 8 bit reference to set to the minor version. - * \param revision an unsigned 8 bit reference to set the current revision. - */ -void zmq_version(uint8_t& major, uint8_t& minor, uint8_t& patch); - -typedef context context_t; /*!< \brief context type */ -typedef std::string endpoint_t; /*!< \brief endpoint type */ -typedef message message_t; /*!< \brief message type */ -typedef poller poller_t; /*!< \brief poller type */ -typedef socket socket_t; /*!< \brief socket type */ - -} - -#endif /* ZMQPP_ZMQPP_HPP_ */ diff --git a/dep/zmqpp/zmqpp_hotfix1.diff b/dep/zmqpp/zmqpp_hotfix1.diff deleted file mode 100644 index 956902e0dfa..00000000000 --- a/dep/zmqpp/zmqpp_hotfix1.diff +++ /dev/null @@ -1,106 +0,0 @@ -diff --git a/dep/zmqpp/zmqpp/inet.hpp b/dep/zmqpp/zmqpp/inet.hpp -index 5245aa4..e0c3b14 100644 ---- a/dep/zmqpp/zmqpp/inet.hpp -+++ b/dep/zmqpp/zmqpp/inet.hpp -@@ -76,10 +76,12 @@ inline uint64_t swap_if_needed(uint64_t const value_to_check) - * \param hostlonglong unsigned 64 bit host order integer - * \return unsigned 64 bit network order integer - */ -+#ifndef htonll - inline uint64_t htonll(uint64_t const hostlonglong) - { - return zmqpp::swap_if_needed(hostlonglong); - } -+#endif - - /*! - * 64 bit version of the ntohs/ntohl -@@ -89,10 +91,12 @@ inline uint64_t htonll(uint64_t const hostlonglong) - * \param networklonglong unsigned 64 bit network order integer - * \return unsigned 64 bit host order integer - */ -+#ifndef ntohll - inline uint64_t ntohll(uint64_t const networklonglong) - { - return zmqpp::swap_if_needed(networklonglong); - } -+#endif - - /*! - * floating point version of the htons/htonl -@@ -142,7 +146,7 @@ inline double htond(double value) - - uint64_t temp; - memcpy(&temp, &value, sizeof(uint64_t)); -- temp = zmqpp::htonll(temp); -+ temp = htonll(temp); - memcpy(&value, &temp, sizeof(uint64_t)); - - return value; -@@ -160,7 +164,7 @@ inline double ntohd(double value) - - uint64_t temp; - memcpy(&temp, &value, sizeof(uint64_t)); -- temp = zmqpp::ntohll(temp); -+ temp = ntohll(temp); - memcpy(&value, &temp, sizeof(uint64_t)); - - return value; -diff --git a/dep/zmqpp/zmqpp/message.cpp b/dep/zmqpp/zmqpp/message.cpp -index 5858730..4d81d24 100644 ---- a/dep/zmqpp/zmqpp/message.cpp -+++ b/dep/zmqpp/zmqpp/message.cpp -@@ -138,7 +138,7 @@ void message::get(int64_t& integer, size_t const part) const - assert(sizeof(int64_t) == size(part)); - - uint64_t const* network_order = static_cast<uint64_t const*>(raw_data(part)); -- integer = static_cast<int64_t>(zmqpp::htonll(*network_order)); -+ integer = static_cast<int64_t>(htonll(*network_order)); - } - - void message::get(uint8_t& unsigned_integer, size_t const part) const -@@ -170,7 +170,7 @@ void message::get(uint64_t& unsigned_integer, size_t const part) const - assert(sizeof(uint64_t) == size(part)); - - uint64_t const* network_order = static_cast<uint64_t const*>(raw_data(part)); -- unsigned_integer = zmqpp::ntohll(*network_order); -+ unsigned_integer = ntohll(*network_order); - } - - void message::get(float& floating_point, size_t const part) const -@@ -228,7 +228,7 @@ message& message::operator<<(int32_t const integer) - - message& message::operator<<(int64_t const integer) - { -- uint64_t network_order = zmqpp::htonll(static_cast<uint64_t>(integer)); -+ uint64_t network_order = htonll(static_cast<uint64_t>(integer)); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint64_t)); - - return *this; -@@ -259,7 +259,7 @@ message& message::operator<<(uint32_t const unsigned_integer) - - message& message::operator<<(uint64_t const unsigned_integer) - { -- uint64_t network_order = zmqpp::htonll(unsigned_integer); -+ uint64_t network_order = htonll(unsigned_integer); - add(reinterpret_cast<void const*>(&network_order), sizeof(uint64_t)); - - return *this; -@@ -329,7 +329,7 @@ void message::push_front(int32_t const integer) - - void message::push_front(int64_t const integer) - { -- uint64_t network_order = zmqpp::htonll(static_cast<uint64_t>(integer)); -+ uint64_t network_order = htonll(static_cast<uint64_t>(integer)); - push_front(&network_order, sizeof(uint64_t)); - } - -@@ -353,7 +353,7 @@ void message::push_front(uint32_t const unsigned_integer) - - void message::push_front(uint64_t const unsigned_integer) - { -- uint64_t network_order = zmqpp::htonll(unsigned_integer); -+ uint64_t network_order = htonll(unsigned_integer); - push_front(&network_order, sizeof(uint64_t)); - } - diff --git a/revision_data.h.in.cmake b/revision_data.h.in.cmake index efe722b99d5..7d189e54c3b 100644 --- a/revision_data.h.in.cmake +++ b/revision_data.h.in.cmake @@ -3,7 +3,7 @@ #define _HASH "@rev_hash@" #define _DATE "@rev_date@" #define _BRANCH "@rev_branch@" - #define _CMAKE_COMMAND "@CMAKE_COMMAND@" + #define _CMAKE_COMMAND R"(@CMAKE_COMMAND@)" #define _SOURCE_DIRECTORY R"(@CMAKE_SOURCE_DIR@)" #define _BUILD_DIRECTORY R"(@BUILDDIR@)" #define _MYSQL_EXECUTABLE R"(@MYSQL_EXECUTABLE@)" diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index ad2e9280029..24d3d6b99ff 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -599,7 +599,7 @@ CREATE TABLE `rbac_linked_permissions` ( LOCK TABLES `rbac_linked_permissions` WRITE; /*!40000 ALTER TABLE `rbac_linked_permissions` DISABLE KEYS */; -INSERT INTO `rbac_linked_permissions` VALUES (192,21),(192,42),(192,43),(192,193),(192,196),(192,692),(192,776),(192,778),(192,779),(192,780),(192,781),(192,782),(192,783),(192,784),(192,785),(192,786),(192,787),(192,788),(192,789),(192,790),(192,791),(192,792),(192,793),(192,794),(192,835),(193,48),(193,194),(193,197),(194,1),(194,2),(194,11),(194,13),(194,14),(194,15),(194,16),(194,17),(194,18),(194,19),(194,20),(194,22),(194,23),(194,25),(194,26),(194,27),(194,28),(194,29),(194,30),(194,31),(194,32),(194,33),(194,34),(194,35),(194,36),(194,37),(194,38),(194,39),(194,40),(194,41),(194,44),(194,46),(194,47),(194,51),(194,195),(194,198),(194,632),(194,798),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,10),(196,200),(196,201),(196,208),(196,212),(196,213),(196,214),(196,215),(196,216),(196,226),(196,227),(196,230),(196,231),(196,233),(196,234),(196,235),(196,238),(196,239),(196,240),(196,241),(196,242),(196,243),(196,244),(196,245),(196,246),(196,247),(196,248),(196,249),(196,250),(196,251),(196,252),(196,253),(196,254),(196,255),(196,256),(196,257),(196,258),(196,259),(196,260),(196,261),(196,262),(196,264),(196,265),(196,266),(196,267),(196,268),(196,269),(196,270),(196,271),(196,272),(196,279),(196,280),(196,283),(196,287),(196,288),(196,289),(196,290),(196,291),(196,292),(196,293),(196,294),(196,295),(196,296),(196,297),(196,298),(196,299),(196,302),(196,303),(196,304),(196,305),(196,306),(196,307),(196,308),(196,309),(196,310),(196,313),(196,314),(196,319),(196,320),(196,321),(196,322),(196,323),(196,324),(196,325),(196,326),(196,327),(196,328),(196,329),(196,330),(196,331),(196,332),(196,333),(196,334),(196,335),(196,336),(196,337),(196,338),(196,339),(196,340),(196,341),(196,342),(196,343),(196,344),(196,345),(196,346),(196,347),(196,348),(196,349),(196,350),(196,351),(196,352),(196,353),(196,354),(196,355),(196,356),(196,357),(196,358),(196,359),(196,360),(196,361),(196,362),(196,363),(196,364),(196,365),(196,366),(196,373),(196,375),(196,400),(196,401),(196,402),(196,403),(196,404),(196,405),(196,406),(196,407),(196,417),(196,418),(196,419),(196,420),(196,421),(196,422),(196,423),(196,424),(196,425),(196,426),(196,427),(196,428),(196,429),(196,434),(196,435),(196,436),(196,437),(196,438),(196,439),(196,440),(196,441),(196,442),(196,443),(196,444),(196,445),(196,446),(196,447),(196,448),(196,449),(196,450),(196,451),(196,452),(196,453),(196,454),(196,455),(196,456),(196,457),(196,458),(196,459),(196,461),(196,463),(196,464),(196,465),(196,472),(196,473),(196,474),(196,475),(196,476),(196,477),(196,478),(196,488),(196,489),(196,491),(196,492),(196,493),(196,495),(196,497),(196,498),(196,499),(196,500),(196,502),(196,503),(196,505),(196,508),(196,511),(196,513),(196,514),(196,516),(196,519),(196,522),(196,523),(196,526),(196,527),(196,529),(196,530),(196,533),(196,535),(196,536),(196,537),(196,538),(196,539),(196,540),(196,541),(196,556),(196,581),(196,582),(196,592),(196,593),(196,596),(196,602),(196,603),(196,604),(196,605),(196,606),(196,607),(196,608),(196,609),(196,610),(196,611),(196,612),(196,613),(196,615),(196,616),(196,617),(196,618),(196,619),(196,620),(196,621),(196,623),(196,624),(196,625),(196,626),(196,627),(196,628),(196,629),(196,630),(196,631),(196,633),(196,634),(196,635),(196,636),(196,637),(196,638),(196,639),(196,640),(196,641),(196,642),(196,643),(196,644),(196,645),(196,646),(196,647),(196,648),(196,649),(196,650),(196,651),(196,652),(196,653),(196,654),(196,655),(196,656),(196,657),(196,658),(196,659),(196,660),(196,661),(196,662),(196,663),(196,664),(196,665),(196,666),(196,667),(196,668),(196,669),(196,670),(196,671),(196,672),(196,673),(196,674),(196,675),(196,676),(196,677),(196,678),(196,679),(196,680),(196,681),(196,682),(196,683),(196,684),(196,685),(196,686),(196,687),(196,688),(196,689),(196,690),(196,691),(196,693),(196,694),(196,695),(196,696),(196,697),(196,698),(196,699),(196,700),(196,701),(196,702),(196,703),(196,704),(196,705),(196,706),(196,707),(196,708),(196,709),(196,710),(196,711),(196,712),(196,713),(196,714),(196,715),(196,716),(196,717),(196,718),(196,719),(196,721),(196,722),(196,723),(196,724),(196,725),(196,726),(196,727),(196,728),(196,729),(196,730),(196,733),(196,734),(196,735),(196,736),(196,738),(196,739),(196,753),(196,757),(196,773),(196,777),(196,809),(196,817),(196,825),(196,829),(196,831),(196,832),(196,833),(197,232),(197,236),(197,237),(197,273),(197,274),(197,275),(197,276),(197,277),(197,284),(197,285),(197,286),(197,301),(197,311),(197,387),(197,388),(197,389),(197,390),(197,391),(197,392),(197,393),(197,394),(197,395),(197,396),(197,397),(197,398),(197,399),(197,479),(197,480),(197,481),(197,482),(197,485),(197,486),(197,487),(197,494),(197,506),(197,509),(197,510),(197,517),(197,518),(197,521),(197,542),(197,543),(197,550),(197,558),(197,568),(197,571),(197,572),(197,573),(197,574),(197,575),(197,576),(197,577),(197,578),(197,579),(197,580),(197,583),(197,584),(197,585),(197,586),(197,587),(197,588),(197,589),(197,590),(197,591),(197,594),(197,595),(197,601),(197,761),(197,762),(197,763),(197,764),(197,765),(197,766),(197,767),(197,768),(197,769),(197,770),(197,771),(197,772),(197,774),(197,805),(197,811),(197,813),(197,819),(197,821),(197,827),(198,218),(198,300),(198,312),(198,315),(198,316),(198,317),(198,318),(198,367),(198,368),(198,369),(198,370),(198,371),(198,372),(198,374),(198,376),(198,377),(198,378),(198,379),(198,380),(198,381),(198,382),(198,384),(198,385),(198,386),(198,408),(198,409),(198,410),(198,411),(198,412),(198,413),(198,414),(198,415),(198,416),(198,430),(198,431),(198,432),(198,433),(198,462),(198,466),(198,467),(198,468),(198,469),(198,470),(198,471),(198,483),(198,484),(198,490),(198,504),(198,512),(198,515),(198,520),(198,524),(198,528),(198,531),(198,532),(198,544),(198,545),(198,546),(198,547),(198,548),(198,549),(198,551),(198,552),(198,553),(198,554),(198,555),(198,557),(198,559),(198,560),(198,561),(198,562),(198,563),(198,564),(198,565),(198,566),(198,567),(198,569),(198,570),(198,597),(198,598),(198,599),(198,600),(198,737),(198,740),(198,741),(198,742),(198,799),(198,800),(198,801),(198,802),(198,803),(198,804),(198,806),(198,807),(198,808),(198,810),(198,812),(198,814),(198,815),(198,816),(198,818),(198,820),(198,822),(198,823),(198,824),(198,826),(198,828),(198,834),(199,207),(199,209),(199,210),(199,211),(199,217),(199,221),(199,222),(199,223),(199,225),(199,263),(199,496),(199,501),(199,507),(199,525),(199,534),(199,797); +INSERT INTO `rbac_linked_permissions` VALUES (192,21),(192,42),(192,43),(192,193),(192,196),(192,692),(192,776),(192,778),(192,779),(192,780),(192,781),(192,782),(192,783),(192,784),(192,785),(192,786),(192,787),(192,788),(192,789),(192,790),(192,791),(192,792),(192,793),(192,794),(192,835),(193,48),(193,194),(193,197),(194,1),(194,2),(194,11),(194,13),(194,14),(194,15),(194,16),(194,17),(194,18),(194,19),(194,20),(194,22),(194,23),(194,25),(194,26),(194,27),(194,28),(194,29),(194,30),(194,31),(194,32),(194,33),(194,34),(194,35),(194,36),(194,37),(194,38),(194,39),(194,40),(194,41),(194,44),(194,46),(194,47),(194,51),(194,195),(194,198),(194,632),(194,798),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,10),(196,200),(196,201),(196,208),(196,212),(196,213),(196,214),(196,215),(196,216),(196,226),(196,227),(196,230),(196,231),(196,233),(196,234),(196,235),(196,238),(196,239),(196,240),(196,241),(196,242),(196,243),(196,244),(196,245),(196,246),(196,247),(196,248),(196,249),(196,250),(196,251),(196,252),(196,253),(196,254),(196,255),(196,256),(196,257),(196,258),(196,259),(196,260),(196,261),(196,262),(196,264),(196,265),(196,266),(196,267),(196,268),(196,269),(196,270),(196,271),(196,272),(196,279),(196,280),(196,283),(196,287),(196,288),(196,289),(196,290),(196,291),(196,292),(196,293),(196,294),(196,295),(196,296),(196,297),(196,298),(196,299),(196,302),(196,303),(196,304),(196,305),(196,306),(196,307),(196,308),(196,309),(196,310),(196,313),(196,314),(196,319),(196,320),(196,321),(196,322),(196,323),(196,324),(196,325),(196,326),(196,327),(196,328),(196,329),(196,330),(196,331),(196,332),(196,333),(196,334),(196,335),(196,336),(196,337),(196,338),(196,339),(196,340),(196,341),(196,342),(196,343),(196,344),(196,345),(196,346),(196,347),(196,348),(196,349),(196,350),(196,351),(196,352),(196,353),(196,354),(196,355),(196,356),(196,357),(196,358),(196,359),(196,360),(196,361),(196,362),(196,363),(196,364),(196,365),(196,366),(196,373),(196,375),(196,400),(196,401),(196,402),(196,403),(196,404),(196,405),(196,406),(196,407),(196,417),(196,418),(196,419),(196,420),(196,421),(196,422),(196,423),(196,424),(196,425),(196,426),(196,427),(196,428),(196,429),(196,434),(196,435),(196,436),(196,437),(196,438),(196,439),(196,440),(196,441),(196,442),(196,443),(196,444),(196,445),(196,446),(196,447),(196,448),(196,449),(196,450),(196,451),(196,452),(196,453),(196,454),(196,455),(196,456),(196,457),(196,458),(196,459),(196,461),(196,463),(196,464),(196,465),(196,472),(196,473),(196,474),(196,475),(196,476),(196,477),(196,478),(196,488),(196,489),(196,491),(196,492),(196,493),(196,495),(196,497),(196,498),(196,499),(196,500),(196,502),(196,503),(196,505),(196,508),(196,511),(196,513),(196,514),(196,516),(196,519),(196,522),(196,523),(196,526),(196,527),(196,529),(196,530),(196,533),(196,535),(196,536),(196,537),(196,538),(196,539),(196,540),(196,541),(196,556),(196,581),(196,582),(196,592),(196,593),(196,596),(196,602),(196,603),(196,604),(196,605),(196,606),(196,607),(196,608),(196,609),(196,610),(196,611),(196,612),(196,613),(196,615),(196,616),(196,617),(196,618),(196,619),(196,620),(196,621),(196,623),(196,624),(196,625),(196,626),(196,627),(196,628),(196,629),(196,630),(196,631),(196,633),(196,634),(196,635),(196,636),(196,637),(196,638),(196,639),(196,640),(196,641),(196,642),(196,643),(196,644),(196,645),(196,646),(196,647),(196,648),(196,649),(196,650),(196,651),(196,652),(196,653),(196,654),(196,655),(196,656),(196,657),(196,658),(196,659),(196,660),(196,661),(196,662),(196,663),(196,664),(196,665),(196,666),(196,667),(196,668),(196,669),(196,670),(196,671),(196,672),(196,673),(196,674),(196,675),(196,676),(196,677),(196,678),(196,679),(196,680),(196,681),(196,682),(196,683),(196,684),(196,685),(196,686),(196,687),(196,688),(196,689),(196,690),(196,691),(196,693),(196,694),(196,695),(196,696),(196,697),(196,698),(196,699),(196,700),(196,701),(196,702),(196,703),(196,704),(196,705),(196,706),(196,707),(196,708),(196,709),(196,710),(196,711),(196,712),(196,713),(196,714),(196,715),(196,716),(196,717),(196,718),(196,719),(196,721),(196,722),(196,723),(196,724),(196,725),(196,726),(196,727),(196,728),(196,729),(196,730),(196,733),(196,734),(196,735),(196,736),(196,738),(196,739),(196,753),(196,757),(196,773),(196,777),(196,809),(196,817),(196,825),(196,829),(196,831),(196,832),(196,833),(196,836),(197,232),(197,236),(197,237),(197,273),(197,274),(197,275),(197,276),(197,277),(197,284),(197,285),(197,286),(197,301),(197,311),(197,387),(197,388),(197,389),(197,390),(197,391),(197,392),(197,393),(197,394),(197,395),(197,396),(197,397),(197,398),(197,399),(197,479),(197,480),(197,481),(197,482),(197,485),(197,486),(197,487),(197,494),(197,506),(197,509),(197,510),(197,517),(197,518),(197,521),(197,542),(197,543),(197,550),(197,558),(197,568),(197,571),(197,572),(197,573),(197,574),(197,575),(197,576),(197,577),(197,578),(197,579),(197,580),(197,583),(197,584),(197,585),(197,586),(197,587),(197,588),(197,589),(197,590),(197,591),(197,594),(197,595),(197,601),(197,761),(197,762),(197,763),(197,764),(197,765),(197,766),(197,767),(197,768),(197,769),(197,770),(197,771),(197,772),(197,774),(197,805),(197,811),(197,813),(197,819),(197,821),(197,827),(198,218),(198,300),(198,312),(198,315),(198,316),(198,317),(198,318),(198,367),(198,368),(198,369),(198,370),(198,371),(198,372),(198,374),(198,376),(198,377),(198,378),(198,379),(198,380),(198,381),(198,382),(198,384),(198,385),(198,386),(198,408),(198,409),(198,410),(198,411),(198,412),(198,413),(198,414),(198,415),(198,416),(198,430),(198,431),(198,432),(198,433),(198,462),(198,466),(198,467),(198,468),(198,469),(198,470),(198,471),(198,483),(198,484),(198,490),(198,504),(198,512),(198,515),(198,520),(198,524),(198,528),(198,531),(198,532),(198,544),(198,545),(198,546),(198,547),(198,548),(198,549),(198,551),(198,552),(198,553),(198,554),(198,555),(198,557),(198,559),(198,560),(198,561),(198,562),(198,563),(198,564),(198,565),(198,566),(198,567),(198,569),(198,570),(198,597),(198,598),(198,599),(198,600),(198,737),(198,740),(198,741),(198,742),(198,799),(198,800),(198,801),(198,802),(198,803),(198,804),(198,806),(198,807),(198,808),(198,810),(198,812),(198,814),(198,815),(198,816),(198,818),(198,820),(198,822),(198,823),(198,824),(198,826),(198,828),(198,834),(199,207),(199,209),(199,210),(199,211),(199,217),(199,221),(199,222),(199,223),(199,225),(199,263),(199,496),(199,501),(199,507),(199,525),(199,534),(199,797); /*!40000 ALTER TABLE `rbac_linked_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -623,7 +623,7 @@ CREATE TABLE `rbac_permissions` ( LOCK TABLES `rbac_permissions` WRITE; /*!40000 ALTER TABLE `rbac_permissions` DISABLE KEYS */; -INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(10,'Use character templates'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(207,'Command: battlenetaccount'),(208,'Command: battlenetaccount create'),(209,'Command: battlenetaccount lock country'),(210,'Command: battlenetaccount lock ip'),(211,'Command: battlenetaccount password'),(212,'Command: battlenetaccount set'),(213,'Command: battlenetaccount set password'),(214,'Command: bnetaccount link'),(215,'Command: bnetaccount unlink'),(216,'Command: bnetaccount gameaccountcreate'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatriggers'),(303,'Command: debug arena'),(304,'Command: debug bg'),(305,'Command: debug entervehicle'),(306,'Command: debug getitemstate'),(307,'Command: debug getitemvalue'),(308,'Command: debug getvalue'),(309,'Command: debug hostil'),(310,'Command: debug itemexpire'),(311,'Command: debug lootrecipient'),(312,'Command: debug los'),(313,'Command: debug mod32value'),(314,'Command: debug moveflags'),(315,'Command: debug play'),(316,'Command: debug play cinematics'),(317,'Command: debug play movie'),(318,'Command: debug play sound'),(319,'Command: debug send'),(320,'Command: debug send buyerror'),(321,'Command: debug send channelnotify'),(322,'Command: debug send chatmessage'),(323,'Command: debug send equiperror'),(324,'Command: debug send largepacket'),(325,'Command: debug send opcode'),(326,'Command: debug send qinvalidmsg'),(327,'Command: debug send qpartymsg'),(328,'Command: debug send sellerror'),(329,'Command: debug send setphaseshift'),(330,'Command: debug send spellfail'),(331,'Command: debug setaurastate'),(332,'Command: debug setbit'),(333,'Command: debug setitemvalue'),(334,'Command: debug setvalue'),(335,'Command: debug setvid'),(336,'Command: debug spawnvehicle'),(337,'Command: debug threat'),(338,'Command: debug update'),(339,'Command: debug uws'),(340,'Command: wpgps'),(341,'Command: deserter'),(342,'Command: deserter bg'),(343,'Command: deserter bg add'),(344,'Command: deserter bg remove'),(345,'Command: deserter instance'),(346,'Command: deserter instance add'),(347,'Command: deserter instance remove'),(348,'Command: disable'),(349,'Command: disable add'),(350,'Command: disable add achievement_criteria'),(351,'Command: disable add battleground'),(352,'Command: disable add map'),(353,'Command: disable add mmap'),(354,'Command: disable add outdoorpvp'),(355,'Command: disable add quest'),(356,'Command: disable add spell'),(357,'Command: disable add vmap'),(358,'Command: disable remove'),(359,'Command: disable remove achievement_criteria'),(360,'Command: disable remove battleground'),(361,'Command: disable remove map'),(362,'Command: disable remove mmap'),(363,'Command: disable remove outdoorpvp'),(364,'Command: disable remove quest'),(365,'Command: disable remove spell'),(366,'Command: disable remove vmap'),(367,'Command: event'),(368,'Command: event activelist'),(369,'Command: event start'),(370,'Command: event stop'),(371,'Command: gm'),(372,'Command: gm chat'),(373,'Command: gm fly'),(374,'Command: gm ingame'),(375,'Command: gm list'),(376,'Command: gm visible'),(377,'Command: go'),(378,'Command: go creature'),(379,'Command: go graveyard'),(380,'Command: go grid'),(381,'Command: go object'),(382,'Command: go taxinode'),(384,'Command: go trigger'),(385,'Command: go xyz'),(386,'Command: go zonexy'),(387,'Command: gobject'),(388,'Command: gobject activate'),(389,'Command: gobject add'),(390,'Command: gobject add temp'),(391,'Command: gobject delete'),(392,'Command: gobject info'),(393,'Command: gobject move'),(394,'Command: gobject near'),(395,'Command: gobject set'),(396,'Command: gobject set phase'),(397,'Command: gobject set state'),(398,'Command: gobject target'),(399,'Command: gobject turn'),(400,'debug transport'),(401,'Command: guild'),(402,'Command: guild create'),(403,'Command: guild delete'),(404,'Command: guild invite'),(405,'Command: guild uninvite'),(406,'Command: guild rank'),(407,'Command: guild rename'),(408,'Command: honor'),(409,'Command: honor add'),(410,'Command: honor add kill'),(411,'Command: honor update'),(412,'Command: instance'),(413,'Command: instance listbinds'),(414,'Command: instance unbind'),(415,'Command: instance stats'),(416,'Command: instance savedata'),(417,'Command: learn'),(418,'Command: learn all'),(419,'Command: learn all my'),(420,'Command: learn all my class'),(421,'Command: learn all my pettalents'),(422,'Command: learn all my spells'),(423,'Command: learn all my talents'),(424,'Command: learn all gm'),(425,'Command: learn all crafts'),(426,'Command: learn all default'),(427,'Command: learn all lang'),(428,'Command: learn all recipes'),(429,'Command: unlearn'),(430,'Command: lfg'),(431,'Command: lfg player'),(432,'Command: lfg group'),(433,'Command: lfg queue'),(434,'Command: lfg clean'),(435,'Command: lfg options'),(436,'Command: list'),(437,'Command: list creature'),(438,'Command: list item'),(439,'Command: list object'),(440,'Command: list auras'),(441,'Command: list mail'),(442,'Command: lookup'),(443,'Command: lookup area'),(444,'Command: lookup creature'),(445,'Command: lookup event'),(446,'Command: lookup faction'),(447,'Command: lookup item'),(448,'Command: lookup itemset'),(449,'Command: lookup object'),(450,'Command: lookup quest'),(451,'Command: lookup player'),(452,'Command: lookup player ip'),(453,'Command: lookup player account'),(454,'Command: lookup player email'),(455,'Command: lookup skill'),(456,'Command: lookup spell'),(457,'Command: lookup spell id'),(458,'Command: lookup taxinode'),(459,'Command: lookup tele'),(460,'Command: lookup title'),(461,'Command: lookup map'),(462,'Command: announce'),(463,'Command: channel'),(464,'Command: channel set'),(465,'Command: channel set ownership'),(466,'Command: gmannounce'),(467,'Command: gmnameannounce'),(468,'Command: gmnotify'),(469,'Command: nameannounce'),(470,'Command: notify'),(471,'Command: whispers'),(472,'Command: group'),(473,'Command: group leader'),(474,'Command: group disband'),(475,'Command: group remove'),(476,'Command: group join'),(477,'Command: group list'),(478,'Command: group summon'),(479,'Command: pet'),(480,'Command: pet create'),(481,'Command: pet learn'),(482,'Command: pet unlearn'),(483,'Command: send'),(484,'Command: send items'),(485,'Command: send mail'),(486,'Command: send message'),(487,'Command: send money'),(488,'Command: additem'),(489,'Command: additemset'),(490,'Command: appear'),(491,'Command: aura'),(492,'Command: bank'),(493,'Command: bindsight'),(494,'Command: combatstop'),(495,'Command: cometome'),(496,'Command: commands'),(497,'Command: cooldown'),(498,'Command: damage'),(499,'Command: dev'),(500,'Command: die'),(501,'Command: dismount'),(502,'Command: distance'),(503,'Command: flusharenapoints'),(504,'Command: freeze'),(505,'Command: gps'),(506,'Command: guid'),(507,'Command: help'),(508,'Command: hidearea'),(509,'Command: itemmove'),(510,'Command: kick'),(511,'Command: linkgrave'),(512,'Command: listfreeze'),(513,'Command: maxskill'),(514,'Command: movegens'),(515,'Command: mute'),(516,'Command: neargrave'),(517,'Command: pinfo'),(518,'Command: playall'),(519,'Command: possess'),(520,'Command: recall'),(521,'Command: repairitems'),(522,'Command: respawn'),(523,'Command: revive'),(524,'Command: saveall'),(525,'Command: save'),(526,'Command: setskill'),(527,'Command: showarea'),(528,'Command: summon'),(529,'Command: unaura'),(530,'Command: unbindsight'),(531,'Command: unfreeze'),(532,'Command: unmute'),(533,'Command: unpossess'),(534,'Command: unstuck'),(535,'Command: wchange'),(536,'Command: mmap'),(537,'Command: mmap loadedtiles'),(538,'Command: mmap loc'),(539,'Command: mmap path'),(540,'Command: mmap stats'),(541,'Command: mmap testarea'),(542,'Command: morph'),(543,'Command: demorph'),(544,'Command: modify'),(545,'Command: modify arenapoints'),(546,'Command: modify bit'),(547,'Command: modify drunk'),(548,'Command: modify energy'),(549,'Command: modify faction'),(550,'Command: modify gender'),(551,'Command: modify honor'),(552,'Command: modify hp'),(553,'Command: modify mana'),(554,'Command: modify money'),(555,'Command: modify mount'),(556,'Command: modify phase'),(557,'Command: modify rage'),(558,'Command: modify reputation'),(559,'Command: modify runicpower'),(560,'Command: modify scale'),(561,'Command: modify speed'),(562,'Command: modify speed all'),(563,'Command: modify speed backwalk'),(564,'Command: modify speed fly'),(565,'Command: modify speed walk'),(566,'Command: modify speed swim'),(567,'Command: modify spell'),(568,'Command: modify standstate'),(569,'Command: modify talentpoints'),(570,'Command: npc'),(571,'Command: npc add'),(572,'Command: npc add formation'),(573,'Command: npc add item'),(574,'Command: npc add move'),(575,'Command: npc add temp'),(576,'Command: npc add delete'),(577,'Command: npc add delete item'),(578,'Command: npc add follow'),(579,'Command: npc add follow stop'),(580,'Command: npc set'),(581,'Command: npc set allowmove'),(582,'Command: npc set entry'),(583,'Command: npc set factionid'),(584,'Command: npc set flag'),(585,'Command: npc set level'),(586,'Command: npc set link'),(587,'Command: npc set model'),(588,'Command: npc set movetype'),(589,'Command: npc set phase'),(590,'Command: npc set spawndist'),(591,'Command: npc set spawntime'),(592,'Command: npc set data'),(593,'Command: npc info'),(594,'Command: npc near'),(595,'Command: npc move'),(596,'Command: npc playemote'),(597,'Command: npc say'),(598,'Command: npc textemote'),(599,'Command: npc whisper'),(600,'Command: npc yell'),(601,'Command: npc tame'),(602,'Command: quest'),(603,'Command: quest add'),(604,'Command: quest complete'),(605,'Command: quest remove'),(606,'Command: quest reward'),(607,'Command: reload'),(608,'Command: reload access_requirement'),(609,'Command: reload achievement_criteria_data'),(610,'Command: reload achievement_reward'),(611,'Command: reload all'),(612,'Command: reload all achievement'),(613,'Command: reload all area'),(615,'Command: reload all gossips'),(616,'Command: reload all item'),(617,'Command: reload all locales'),(618,'Command: reload all loot'),(619,'Command: reload all npc'),(620,'Command: reload all quest'),(621,'Command: reload all scripts'),(623,'Command: reload areatrigger_involvedrelation'),(624,'Command: reload areatrigger_tavern'),(625,'Command: reload areatrigger_teleport'),(626,'Command: reload auctions'),(627,'Command: reload autobroadcast'),(628,'Command: reload command'),(629,'Command: reload conditions'),(630,'Command: reload config'),(631,'Command: reload battleground_template'),(632,'Command: .mutehistory'),(633,'Command: reload creature_linked_respawn'),(634,'Command: reload creature_loot_template'),(635,'Command: reload creature_onkill_reputation'),(636,'Command: reload creature_questender'),(637,'Command: reload creature_queststarter'),(638,'Command: reload creature_summon_groups'),(639,'Command: reload creature_template'),(640,'Command: reload creature_text'),(641,'Command: reload disables'),(642,'Command: reload disenchant_loot_template'),(643,'Command: reload event_scripts'),(644,'Command: reload fishing_loot_template'),(645,'Command: reload game_graveyard_zone'),(646,'Command: reload game_tele'),(647,'Command: reload gameobject_questender'),(648,'Command: reload gameobject_loot_template'),(649,'Command: reload gameobject_queststarter'),(650,'Command: reload support'),(651,'Command: reload gossip_menu'),(652,'Command: reload gossip_menu_option'),(653,'Command: reload item_enchantment_template'),(654,'Command: reload item_loot_template'),(655,'Command: reload item_set_names'),(656,'Command: reload lfg_dungeon_rewards'),(657,'Command: reload locales_achievement_reward'),(658,'Command: reload locales_creature'),(659,'Command: reload locales_creature_text'),(660,'Command: reload locales_gameobject'),(661,'Command: reload locales_gossip_menu_option'),(662,'Command: reload character_template'),(663,'Command: reload locales_item_set_name'),(664,'Command: reload quest_greeting'),(665,'Command: reload locales_page_text'),(666,'Command: reload locales_points_of_interest'),(667,'Command: reload quest_locale'),(668,'Command: reload mail_level_reward'),(669,'Command: reload mail_loot_template'),(670,'Command: reload milling_loot_template'),(671,'Command: reload npc_spellclick_spells'),(672,'Command: reload npc_trainer'),(673,'Command: reload npc_vendor'),(674,'Command: reload page_text'),(675,'Command: reload pickpocketing_loot_template'),(676,'Command: reload points_of_interest'),(677,'Command: reload prospecting_loot_template'),(678,'Command: reload quest_poi'),(679,'Command: reload quest_template'),(680,'Command: reload rbac'),(681,'Command: reload reference_loot_template'),(682,'Command: reload reserved_name'),(683,'Command: reload reputation_reward_rate'),(684,'Command: reload reputation_spillover_template'),(685,'Command: reload skill_discovery_template'),(686,'Command: reload skill_extra_item_template'),(687,'Command: reload skill_fishing_base_level'),(688,'Command: reload skinning_loot_template'),(689,'Command: reload smart_scripts'),(690,'Command: reload spell_required'),(691,'Command: reload spell_area'),(692,'Command: debug send playscene'),(693,'Command: reload spell_group'),(694,'Command: reload spell_learn_spell'),(695,'Command: reload spell_loot_template'),(696,'Command: reload spell_linked_spell'),(697,'Command: reload spell_pet_auras'),(698,'Command: reload spell_proc_event'),(699,'Command: reload spell_proc'),(700,'Command: reload spell_scripts'),(701,'Command: reload spell_target_position'),(702,'Command: reload spell_threats'),(703,'Command: reload spell_group_stack_rules'),(704,'Command: reload trinity_string'),(705,'Command: reload warden_action'),(706,'Command: reload waypoint_scripts'),(707,'Command: reload waypoint_data'),(708,'Command: reload vehicle_accessory'),(709,'Command: reload vehicle_template_accessory'),(710,'Command: reset'),(711,'Command: reset achievements'),(712,'Command: reset honor'),(713,'Command: reset level'),(714,'Command: reset spells'),(715,'Command: reset stats'),(716,'Command: reset talents'),(717,'Command: reset all'),(718,'Command: server'),(719,'Command: server corpses'),(720,'Command: server exit'),(721,'Command: server idlerestart'),(722,'Command: server idlerestart cancel'),(723,'Command: server idleshutdown'),(724,'Command: server idleshutdown cancel'),(725,'Command: server info'),(726,'Command: server plimit'),(727,'Command: server restart'),(728,'Command: server restart cancel'),(729,'Command: server set'),(730,'Command: server set closed'),(731,'Command: server set difftime'),(732,'Command: server set loglevel'),(733,'Command: server set motd'),(734,'Command: server shutdown'),(735,'Command: server shutdown cancel'),(736,'Command: server motd'),(737,'Command: tele'),(738,'Command: tele add'),(739,'Command: tele del'),(740,'Command: tele name'),(741,'Command: tele group'),(742,'Command: ticket'),(753,'Command: ticket reset'),(757,'Command: ticket togglesystem'),(761,'Command: titles'),(762,'Command: titles add'),(763,'Command: titles current'),(764,'Command: titles remove'),(765,'Command: titles set'),(766,'Command: titles set mask'),(767,'Command: wp'),(768,'Command: wp add'),(769,'Command: wp event'),(770,'Command: wp load'),(771,'Command: wp modify'),(772,'Command: wp unload'),(773,'Command: wp reload'),(774,'Command: wp show'),(776,'Command: debug phase'),(777,'Command: mailbox'),(778,'Command: ahbot'),(779,'Command: ahbot items'),(780,'Command: ahbot items gray'),(781,'Command: ahbot items white'),(782,'Command: ahbot items green'),(783,'Command: ahbot items blue'),(784,'Command: ahbot items purple'),(785,'Command: ahbot items orange'),(786,'Command: ahbot items yellow'),(787,'Command: ahbot ratio'),(788,'Command: ahbot ratio alliance'),(789,'Command: ahbot ratio horde'),(790,'Command: ahbot ratio neutral'),(791,'Command: ahbot rebuild'),(792,'Command: ahbot reload'),(793,'Command: ahbot status'),(794,'Command: .guild info'),(797,'Command: pvpstats'),(798,'Command: .mod xp'),(799,'Command: .go bugticket'),(800,'Command: .go complaintticket'),(801,'Command: .go suggestionticket'),(802,'Command: .ticket bug'),(803,'Command: .ticket complaint'),(804,'Command: .ticket suggestion'),(805,'Command: .ticket bug assign'),(806,'Command: .ticket bug close'),(807,'Command: .ticket bug closedlist'),(808,'Command: .ticket bug comment'),(809,'Command: .ticket bug delete'),(810,'Command: .ticket bug list'),(811,'Command: .ticket bug unassign'),(812,'Command: .ticket bug view'),(813,'Command: .ticket complaint assign'),(814,'Command: .ticket complaint close'),(815,'Command: .ticket complaint closedlist'),(816,'Command: .ticket complaint comment'),(817,'Command: .ticket complaint delete'),(818,'Command: .ticket complaint list'),(819,'Command: .ticket complaint unassign'),(820,'Command: .ticket complaint view'),(821,'Command: .ticket suggestion assign'),(822,'Command: .ticket suggestion close'),(823,'Command: .ticket suggestion closedlist'),(824,'Command: .ticket suggestion comment'),(825,'Command: .ticket suggestion delete'),(826,'Command: .ticket suggestion list'),(827,'Command: .ticket suggestion unassign'),(828,'Command: .ticket suggestion view'),(829,'Command: .ticket reset all'),(831,'Command: .ticket reset bug'),(832,'Command: .ticket reset complaint'),(833,'Command: .ticket reset suggestion'),(834,'Command: go quest'),(835,'Command: debug loadcells'); +INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(10,'Use character templates'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(207,'Command: battlenetaccount'),(208,'Command: battlenetaccount create'),(209,'Command: battlenetaccount lock country'),(210,'Command: battlenetaccount lock ip'),(211,'Command: battlenetaccount password'),(212,'Command: battlenetaccount set'),(213,'Command: battlenetaccount set password'),(214,'Command: bnetaccount link'),(215,'Command: bnetaccount unlink'),(216,'Command: bnetaccount gameaccountcreate'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatriggers'),(303,'Command: debug arena'),(304,'Command: debug bg'),(305,'Command: debug entervehicle'),(306,'Command: debug getitemstate'),(307,'Command: debug getitemvalue'),(308,'Command: debug getvalue'),(309,'Command: debug hostil'),(310,'Command: debug itemexpire'),(311,'Command: debug lootrecipient'),(312,'Command: debug los'),(313,'Command: debug mod32value'),(314,'Command: debug moveflags'),(315,'Command: debug play'),(316,'Command: debug play cinematics'),(317,'Command: debug play movie'),(318,'Command: debug play sound'),(319,'Command: debug send'),(320,'Command: debug send buyerror'),(321,'Command: debug send channelnotify'),(322,'Command: debug send chatmessage'),(323,'Command: debug send equiperror'),(324,'Command: debug send largepacket'),(325,'Command: debug send opcode'),(326,'Command: debug send qinvalidmsg'),(327,'Command: debug send qpartymsg'),(328,'Command: debug send sellerror'),(329,'Command: debug send setphaseshift'),(330,'Command: debug send spellfail'),(331,'Command: debug setaurastate'),(332,'Command: debug setbit'),(333,'Command: debug setitemvalue'),(334,'Command: debug setvalue'),(335,'Command: debug setvid'),(336,'Command: debug spawnvehicle'),(337,'Command: debug threat'),(338,'Command: debug update'),(339,'Command: debug uws'),(340,'Command: wpgps'),(341,'Command: deserter'),(342,'Command: deserter bg'),(343,'Command: deserter bg add'),(344,'Command: deserter bg remove'),(345,'Command: deserter instance'),(346,'Command: deserter instance add'),(347,'Command: deserter instance remove'),(348,'Command: disable'),(349,'Command: disable add'),(350,'Command: disable add achievement_criteria'),(351,'Command: disable add battleground'),(352,'Command: disable add map'),(353,'Command: disable add mmap'),(354,'Command: disable add outdoorpvp'),(355,'Command: disable add quest'),(356,'Command: disable add spell'),(357,'Command: disable add vmap'),(358,'Command: disable remove'),(359,'Command: disable remove achievement_criteria'),(360,'Command: disable remove battleground'),(361,'Command: disable remove map'),(362,'Command: disable remove mmap'),(363,'Command: disable remove outdoorpvp'),(364,'Command: disable remove quest'),(365,'Command: disable remove spell'),(366,'Command: disable remove vmap'),(367,'Command: event'),(368,'Command: event activelist'),(369,'Command: event start'),(370,'Command: event stop'),(371,'Command: gm'),(372,'Command: gm chat'),(373,'Command: gm fly'),(374,'Command: gm ingame'),(375,'Command: gm list'),(376,'Command: gm visible'),(377,'Command: go'),(378,'Command: go creature'),(379,'Command: go graveyard'),(380,'Command: go grid'),(381,'Command: go object'),(382,'Command: go taxinode'),(384,'Command: go trigger'),(385,'Command: go xyz'),(386,'Command: go zonexy'),(387,'Command: gobject'),(388,'Command: gobject activate'),(389,'Command: gobject add'),(390,'Command: gobject add temp'),(391,'Command: gobject delete'),(392,'Command: gobject info'),(393,'Command: gobject move'),(394,'Command: gobject near'),(395,'Command: gobject set'),(396,'Command: gobject set phase'),(397,'Command: gobject set state'),(398,'Command: gobject target'),(399,'Command: gobject turn'),(400,'debug transport'),(401,'Command: guild'),(402,'Command: guild create'),(403,'Command: guild delete'),(404,'Command: guild invite'),(405,'Command: guild uninvite'),(406,'Command: guild rank'),(407,'Command: guild rename'),(408,'Command: honor'),(409,'Command: honor add'),(410,'Command: honor add kill'),(411,'Command: honor update'),(412,'Command: instance'),(413,'Command: instance listbinds'),(414,'Command: instance unbind'),(415,'Command: instance stats'),(416,'Command: instance savedata'),(417,'Command: learn'),(418,'Command: learn all'),(419,'Command: learn all my'),(420,'Command: learn all my class'),(421,'Command: learn all my pettalents'),(422,'Command: learn all my spells'),(423,'Command: learn all my talents'),(424,'Command: learn all gm'),(425,'Command: learn all crafts'),(426,'Command: learn all default'),(427,'Command: learn all lang'),(428,'Command: learn all recipes'),(429,'Command: unlearn'),(430,'Command: lfg'),(431,'Command: lfg player'),(432,'Command: lfg group'),(433,'Command: lfg queue'),(434,'Command: lfg clean'),(435,'Command: lfg options'),(436,'Command: list'),(437,'Command: list creature'),(438,'Command: list item'),(439,'Command: list object'),(440,'Command: list auras'),(441,'Command: list mail'),(442,'Command: lookup'),(443,'Command: lookup area'),(444,'Command: lookup creature'),(445,'Command: lookup event'),(446,'Command: lookup faction'),(447,'Command: lookup item'),(448,'Command: lookup itemset'),(449,'Command: lookup object'),(450,'Command: lookup quest'),(451,'Command: lookup player'),(452,'Command: lookup player ip'),(453,'Command: lookup player account'),(454,'Command: lookup player email'),(455,'Command: lookup skill'),(456,'Command: lookup spell'),(457,'Command: lookup spell id'),(458,'Command: lookup taxinode'),(459,'Command: lookup tele'),(460,'Command: lookup title'),(461,'Command: lookup map'),(462,'Command: announce'),(463,'Command: channel'),(464,'Command: channel set'),(465,'Command: channel set ownership'),(466,'Command: gmannounce'),(467,'Command: gmnameannounce'),(468,'Command: gmnotify'),(469,'Command: nameannounce'),(470,'Command: notify'),(471,'Command: whispers'),(472,'Command: group'),(473,'Command: group leader'),(474,'Command: group disband'),(475,'Command: group remove'),(476,'Command: group join'),(477,'Command: group list'),(478,'Command: group summon'),(479,'Command: pet'),(480,'Command: pet create'),(481,'Command: pet learn'),(482,'Command: pet unlearn'),(483,'Command: send'),(484,'Command: send items'),(485,'Command: send mail'),(486,'Command: send message'),(487,'Command: send money'),(488,'Command: additem'),(489,'Command: additemset'),(490,'Command: appear'),(491,'Command: aura'),(492,'Command: bank'),(493,'Command: bindsight'),(494,'Command: combatstop'),(495,'Command: cometome'),(496,'Command: commands'),(497,'Command: cooldown'),(498,'Command: damage'),(499,'Command: dev'),(500,'Command: die'),(501,'Command: dismount'),(502,'Command: distance'),(503,'Command: flusharenapoints'),(504,'Command: freeze'),(505,'Command: gps'),(506,'Command: guid'),(507,'Command: help'),(508,'Command: hidearea'),(509,'Command: itemmove'),(510,'Command: kick'),(511,'Command: linkgrave'),(512,'Command: listfreeze'),(513,'Command: maxskill'),(514,'Command: movegens'),(515,'Command: mute'),(516,'Command: neargrave'),(517,'Command: pinfo'),(518,'Command: playall'),(519,'Command: possess'),(520,'Command: recall'),(521,'Command: repairitems'),(522,'Command: respawn'),(523,'Command: revive'),(524,'Command: saveall'),(525,'Command: save'),(526,'Command: setskill'),(527,'Command: showarea'),(528,'Command: summon'),(529,'Command: unaura'),(530,'Command: unbindsight'),(531,'Command: unfreeze'),(532,'Command: unmute'),(533,'Command: unpossess'),(534,'Command: unstuck'),(535,'Command: wchange'),(536,'Command: mmap'),(537,'Command: mmap loadedtiles'),(538,'Command: mmap loc'),(539,'Command: mmap path'),(540,'Command: mmap stats'),(541,'Command: mmap testarea'),(542,'Command: morph'),(543,'Command: demorph'),(544,'Command: modify'),(545,'Command: modify arenapoints'),(546,'Command: modify bit'),(547,'Command: modify drunk'),(548,'Command: modify energy'),(549,'Command: modify faction'),(550,'Command: modify gender'),(551,'Command: modify honor'),(552,'Command: modify hp'),(553,'Command: modify mana'),(554,'Command: modify money'),(555,'Command: modify mount'),(556,'Command: modify phase'),(557,'Command: modify rage'),(558,'Command: modify reputation'),(559,'Command: modify runicpower'),(560,'Command: modify scale'),(561,'Command: modify speed'),(562,'Command: modify speed all'),(563,'Command: modify speed backwalk'),(564,'Command: modify speed fly'),(565,'Command: modify speed walk'),(566,'Command: modify speed swim'),(567,'Command: modify spell'),(568,'Command: modify standstate'),(569,'Command: modify talentpoints'),(570,'Command: npc'),(571,'Command: npc add'),(572,'Command: npc add formation'),(573,'Command: npc add item'),(574,'Command: npc add move'),(575,'Command: npc add temp'),(576,'Command: npc add delete'),(577,'Command: npc add delete item'),(578,'Command: npc add follow'),(579,'Command: npc add follow stop'),(580,'Command: npc set'),(581,'Command: npc set allowmove'),(582,'Command: npc set entry'),(583,'Command: npc set factionid'),(584,'Command: npc set flag'),(585,'Command: npc set level'),(586,'Command: npc set link'),(587,'Command: npc set model'),(588,'Command: npc set movetype'),(589,'Command: npc set phase'),(590,'Command: npc set spawndist'),(591,'Command: npc set spawntime'),(592,'Command: npc set data'),(593,'Command: npc info'),(594,'Command: npc near'),(595,'Command: npc move'),(596,'Command: npc playemote'),(597,'Command: npc say'),(598,'Command: npc textemote'),(599,'Command: npc whisper'),(600,'Command: npc yell'),(601,'Command: npc tame'),(602,'Command: quest'),(603,'Command: quest add'),(604,'Command: quest complete'),(605,'Command: quest remove'),(606,'Command: quest reward'),(607,'Command: reload'),(608,'Command: reload access_requirement'),(609,'Command: reload achievement_criteria_data'),(610,'Command: reload achievement_reward'),(611,'Command: reload all'),(612,'Command: reload all achievement'),(613,'Command: reload all area'),(615,'Command: reload all gossips'),(616,'Command: reload all item'),(617,'Command: reload all locales'),(618,'Command: reload all loot'),(619,'Command: reload all npc'),(620,'Command: reload all quest'),(621,'Command: reload all scripts'),(623,'Command: reload areatrigger_involvedrelation'),(624,'Command: reload areatrigger_tavern'),(625,'Command: reload areatrigger_teleport'),(626,'Command: reload auctions'),(627,'Command: reload autobroadcast'),(628,'Command: reload command'),(629,'Command: reload conditions'),(630,'Command: reload config'),(631,'Command: reload battleground_template'),(632,'Command: .mutehistory'),(633,'Command: reload creature_linked_respawn'),(634,'Command: reload creature_loot_template'),(635,'Command: reload creature_onkill_reputation'),(636,'Command: reload creature_questender'),(637,'Command: reload creature_queststarter'),(638,'Command: reload creature_summon_groups'),(639,'Command: reload creature_template'),(640,'Command: reload creature_text'),(641,'Command: reload disables'),(642,'Command: reload disenchant_loot_template'),(643,'Command: reload event_scripts'),(644,'Command: reload fishing_loot_template'),(645,'Command: reload game_graveyard_zone'),(646,'Command: reload game_tele'),(647,'Command: reload gameobject_questender'),(648,'Command: reload gameobject_loot_template'),(649,'Command: reload gameobject_queststarter'),(650,'Command: reload support'),(651,'Command: reload gossip_menu'),(652,'Command: reload gossip_menu_option'),(653,'Command: reload item_enchantment_template'),(654,'Command: reload item_loot_template'),(655,'Command: reload item_set_names'),(656,'Command: reload lfg_dungeon_rewards'),(657,'Command: reload locales_achievement_reward'),(658,'Command: reload locales_creature'),(659,'Command: reload locales_creature_text'),(660,'Command: reload locales_gameobject'),(661,'Command: reload locales_gossip_menu_option'),(662,'Command: reload character_template'),(663,'Command: reload locales_item_set_name'),(664,'Command: reload quest_greeting'),(665,'Command: reload locales_page_text'),(666,'Command: reload locales_points_of_interest'),(667,'Command: reload quest_locale'),(668,'Command: reload mail_level_reward'),(669,'Command: reload mail_loot_template'),(670,'Command: reload milling_loot_template'),(671,'Command: reload npc_spellclick_spells'),(672,'Command: reload npc_trainer'),(673,'Command: reload npc_vendor'),(674,'Command: reload page_text'),(675,'Command: reload pickpocketing_loot_template'),(676,'Command: reload points_of_interest'),(677,'Command: reload prospecting_loot_template'),(678,'Command: reload quest_poi'),(679,'Command: reload quest_template'),(680,'Command: reload rbac'),(681,'Command: reload reference_loot_template'),(682,'Command: reload reserved_name'),(683,'Command: reload reputation_reward_rate'),(684,'Command: reload reputation_spillover_template'),(685,'Command: reload skill_discovery_template'),(686,'Command: reload skill_extra_item_template'),(687,'Command: reload skill_fishing_base_level'),(688,'Command: reload skinning_loot_template'),(689,'Command: reload smart_scripts'),(690,'Command: reload spell_required'),(691,'Command: reload spell_area'),(692,'Command: debug send playscene'),(693,'Command: reload spell_group'),(694,'Command: reload spell_learn_spell'),(695,'Command: reload spell_loot_template'),(696,'Command: reload spell_linked_spell'),(697,'Command: reload spell_pet_auras'),(698,'Command: reload spell_proc_event'),(699,'Command: reload spell_proc'),(700,'Command: reload spell_scripts'),(701,'Command: reload spell_target_position'),(702,'Command: reload spell_threats'),(703,'Command: reload spell_group_stack_rules'),(704,'Command: reload trinity_string'),(705,'Command: reload warden_action'),(706,'Command: reload waypoint_scripts'),(707,'Command: reload waypoint_data'),(708,'Command: reload vehicle_accessory'),(709,'Command: reload vehicle_template_accessory'),(710,'Command: reset'),(711,'Command: reset achievements'),(712,'Command: reset honor'),(713,'Command: reset level'),(714,'Command: reset spells'),(715,'Command: reset stats'),(716,'Command: reset talents'),(717,'Command: reset all'),(718,'Command: server'),(719,'Command: server corpses'),(720,'Command: server exit'),(721,'Command: server idlerestart'),(722,'Command: server idlerestart cancel'),(723,'Command: server idleshutdown'),(724,'Command: server idleshutdown cancel'),(725,'Command: server info'),(726,'Command: server plimit'),(727,'Command: server restart'),(728,'Command: server restart cancel'),(729,'Command: server set'),(730,'Command: server set closed'),(731,'Command: server set difftime'),(732,'Command: server set loglevel'),(733,'Command: server set motd'),(734,'Command: server shutdown'),(735,'Command: server shutdown cancel'),(736,'Command: server motd'),(737,'Command: tele'),(738,'Command: tele add'),(739,'Command: tele del'),(740,'Command: tele name'),(741,'Command: tele group'),(742,'Command: ticket'),(753,'Command: ticket reset'),(757,'Command: ticket togglesystem'),(761,'Command: titles'),(762,'Command: titles add'),(763,'Command: titles current'),(764,'Command: titles remove'),(765,'Command: titles set'),(766,'Command: titles set mask'),(767,'Command: wp'),(768,'Command: wp add'),(769,'Command: wp event'),(770,'Command: wp load'),(771,'Command: wp modify'),(772,'Command: wp unload'),(773,'Command: wp reload'),(774,'Command: wp show'),(776,'Command: debug phase'),(777,'Command: mailbox'),(778,'Command: ahbot'),(779,'Command: ahbot items'),(780,'Command: ahbot items gray'),(781,'Command: ahbot items white'),(782,'Command: ahbot items green'),(783,'Command: ahbot items blue'),(784,'Command: ahbot items purple'),(785,'Command: ahbot items orange'),(786,'Command: ahbot items yellow'),(787,'Command: ahbot ratio'),(788,'Command: ahbot ratio alliance'),(789,'Command: ahbot ratio horde'),(790,'Command: ahbot ratio neutral'),(791,'Command: ahbot rebuild'),(792,'Command: ahbot reload'),(793,'Command: ahbot status'),(794,'Command: .guild info'),(797,'Command: pvpstats'),(798,'Command: .mod xp'),(799,'Command: .go bugticket'),(800,'Command: .go complaintticket'),(801,'Command: .go suggestionticket'),(802,'Command: .ticket bug'),(803,'Command: .ticket complaint'),(804,'Command: .ticket suggestion'),(805,'Command: .ticket bug assign'),(806,'Command: .ticket bug close'),(807,'Command: .ticket bug closedlist'),(808,'Command: .ticket bug comment'),(809,'Command: .ticket bug delete'),(810,'Command: .ticket bug list'),(811,'Command: .ticket bug unassign'),(812,'Command: .ticket bug view'),(813,'Command: .ticket complaint assign'),(814,'Command: .ticket complaint close'),(815,'Command: .ticket complaint closedlist'),(816,'Command: .ticket complaint comment'),(817,'Command: .ticket complaint delete'),(818,'Command: .ticket complaint list'),(819,'Command: .ticket complaint unassign'),(820,'Command: .ticket complaint view'),(821,'Command: .ticket suggestion assign'),(822,'Command: .ticket suggestion close'),(823,'Command: .ticket suggestion closedlist'),(824,'Command: .ticket suggestion comment'),(825,'Command: .ticket suggestion delete'),(826,'Command: .ticket suggestion list'),(827,'Command: .ticket suggestion unassign'),(828,'Command: .ticket suggestion view'),(829,'Command: .ticket reset all'),(831,'Command: .ticket reset bug'),(832,'Command: .ticket reset complaint'),(833,'Command: .ticket reset suggestion'),(834,'Command: go quest'),(835,'Command: debug loadcells'),(836,'Command: .debug boundary'); /*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -712,7 +712,7 @@ CREATE TABLE `updates` ( LOCK TABLES `updates` WRITE; /*!40000 ALTER TABLE `updates` DISABLE KEYS */; -INSERT INTO `updates` VALUES ('2014_10_04_00_auth.sql','C3BC70A6EC381474B7308F442346F1E721176BC6','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_19_00_auth.sql','7472B490A4F86C9D3DA609CDD3197499CB80C87C','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_26_00_auth.sql','75CC67ADE2A3B2E54FD57D6B0DCAA8FE50F4EE35','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_03_00_auth.sql','5948C9F286CF0FEA8E241785C0259FF36B73BDC5','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_04_00_auth.sql','3AFC68B2375C2A417DDEA94583C53AFF83DE50DF','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_09_00_auth.sql','B8DD1A7047C0FDDB80344B239343EC33BF1A0D97','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth.sql','8FBA737A1D3FF4631A1E662A5B500A8BD304EC63','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth_from_335.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_23_00_auth.sql','0BBEB3EB3AED0FEF277A062819B6B2C00084A742','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_25_00_auth.sql','4F45CDB26BDBB3EE83F1988E3D7818C5926ADC02','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_05_00_auth.sql','6A7BBCEF43111C73A2D2C3CCB6911BE50DE7DD94','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_19_00_auth.sql','44D8E12FFF327AD07878FBDF8D9C16B6B7DCB122','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_20_00_auth.sql','4DAA02AE285C02AE6C82EA2C8B97AC71990F1085','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_25_00_auth.sql','61411930F482BC73FC7FD2C370C811E944F5FF92','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_27_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_28_00_auth.sql','0A913217610E76AFF119C27259737BBC523090E6','ARCHIVED','2015-03-21 16:55:52',0),('2015_02_22_00_auth.sql','21CCCF8B01252E16CA3D6C9E3E8DAA4C9B28ED6E','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_01_00_auth.sql','911881E273207FF6182D1FDAC8C85FFAE8F1C852','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_10_00_auth.sql','2CC8502C11412EFEB5C11BE166761A8754A59009','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_00_auth.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_01_auth.sql','5CCEDF20C8189FB1E8DF064A9F0DDC342841FBF0','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_02_auth.sql','85E4ACD9AA099C0C4AC034575F2BB07D348EAC72','ARCHIVED','2015-03-21 16:56:46',0),('2015_03_15_00_auth.sql','1D8E107FBEFE5E7F47E09F45240DFF499B77CDED','ARCHIVED','2015-05-02 13:57:57',0),('2015_03_26_00_auth.sql','34AC8543E6A9C6C832DE58EAB33618EEEF70B9F9','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_04_00_auth.sql','57146B35E54A2EC7869C945034AB078358020311','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_06_00_auth.sql','2A8049DC2923420A002D42FB6F02C2FFCC5CDD22','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_08_00_auth.sql','4D7D8EEF285C982BB676836602266501BEC26764','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_10_00_auth.sql','4AE68FD97A95CEE5143EA20FD33F5D557367AC1F','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_00_auth.sql','80A71C8921CFEBB547D264558B6DE27201685B84','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_01_auth.sql','3E88183E1A85D11BFD74CF9A32A725C44AE02EEC','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_21_00_auth.sql','1B3B48DBA06368B985C548D166C515C9DD598CB9','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_00_auth.sql','96AB595E0D2A088750E3F48B0AF0A8A14F3CFE1E','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_01_auth.sql','FB11FB834E488B0FD3AFDABCC1A3113092E7C2E5','ARCHIVED','2015-05-02 13:57:57',0),('2015_07_02_00_auth.sql','E5EE3842AB9B01851E49B360FBAF6FFEEAB2A8DA','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_06_00_auth.sql','6D1ADBA496DC6E6D7B3BF887DA8D4D17D3FBACE0','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_00_auth.sql','CB54020AFD1E31742FD8BF9CE16879625E289788','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_01_auth.sql','74D281CB82E0DA36D628BDC7AC797AE5498DB461','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_16_00_auth.sql','A057E95B5553B6A57A1642FE3FEC8E2E62EDE3C6','ARCHIVED','2015-10-10 08:30:48',0),('2015_07_29_00_auth.sql','0000FECBC413E96C7C45F303D162E263EFBA7116','ARCHIVED','2015-10-10 08:30:48',0),('2015_08_26_00_auth.sql','3071C02A2EB7DCBF4CEE10279FEFAB7C29A43A3A','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_00_auth.sql','F765D82B37873FA67447347D5B83C99C159FB452','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_01_auth.sql','97A72DBCBF14D27A1863834A22296905FF276086','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_09_00_auth.sql','495A0CF1B1C49205D4A5D3C25A4E1EB95616D6B4','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_15_00_auth.sql','D1FEFDA4C98F30384DF4B64D5A53187303EB5786','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_09_00_auth.sql','B6D643D444C6AE711503F73B96B6252A852913D6','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_16_00_auth.sql','366AFFD1088762866091A81CE1EC64138B8B35F1','ARCHIVED','2015-11-08 00:46:02',62),('2015_10_17_00_auth.sql','AC0D45E905033F42093852D2C4476663BDACCB3D','ARCHIVED','2015-10-17 12:39:12',0),('2015_11_01_00_auth_2015_08_21_00.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-11-01 14:50:26',0),('2015_11_08_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2015-11-08 00:51:45',0),('2015_11_21_00_auth.sql','575A1D697CC6C7C517F7CCB950988267C99CE7FA','RELEASED','2015-11-21 21:25:38',0),('2015_12_07_00_auth.sql','24A07AC1F38E5D26A3599FC06D29E267418F69F3','RELEASED','2015-12-07 20:55:48',0),('2016_01_13_00_auth.sql','114527BCCB0DE286CBE6FDA3029DD0523D1037FA','RELEASED','2016-01-13 21:39:13',0); +INSERT INTO `updates` VALUES ('2014_10_04_00_auth.sql','C3BC70A6EC381474B7308F442346F1E721176BC6','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_19_00_auth.sql','7472B490A4F86C9D3DA609CDD3197499CB80C87C','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_26_00_auth.sql','75CC67ADE2A3B2E54FD57D6B0DCAA8FE50F4EE35','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_03_00_auth.sql','5948C9F286CF0FEA8E241785C0259FF36B73BDC5','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_04_00_auth.sql','3AFC68B2375C2A417DDEA94583C53AFF83DE50DF','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_09_00_auth.sql','B8DD1A7047C0FDDB80344B239343EC33BF1A0D97','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth.sql','8FBA737A1D3FF4631A1E662A5B500A8BD304EC63','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth_from_335.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_23_00_auth.sql','0BBEB3EB3AED0FEF277A062819B6B2C00084A742','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_25_00_auth.sql','4F45CDB26BDBB3EE83F1988E3D7818C5926ADC02','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_05_00_auth.sql','6A7BBCEF43111C73A2D2C3CCB6911BE50DE7DD94','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_19_00_auth.sql','44D8E12FFF327AD07878FBDF8D9C16B6B7DCB122','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_20_00_auth.sql','4DAA02AE285C02AE6C82EA2C8B97AC71990F1085','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_25_00_auth.sql','61411930F482BC73FC7FD2C370C811E944F5FF92','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_27_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_28_00_auth.sql','0A913217610E76AFF119C27259737BBC523090E6','ARCHIVED','2015-03-21 16:55:52',0),('2015_02_22_00_auth.sql','21CCCF8B01252E16CA3D6C9E3E8DAA4C9B28ED6E','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_01_00_auth.sql','911881E273207FF6182D1FDAC8C85FFAE8F1C852','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_10_00_auth.sql','2CC8502C11412EFEB5C11BE166761A8754A59009','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_00_auth.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_01_auth.sql','5CCEDF20C8189FB1E8DF064A9F0DDC342841FBF0','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_02_auth.sql','85E4ACD9AA099C0C4AC034575F2BB07D348EAC72','ARCHIVED','2015-03-21 16:56:46',0),('2015_03_15_00_auth.sql','1D8E107FBEFE5E7F47E09F45240DFF499B77CDED','ARCHIVED','2015-05-02 13:57:57',0),('2015_03_26_00_auth.sql','34AC8543E6A9C6C832DE58EAB33618EEEF70B9F9','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_04_00_auth.sql','57146B35E54A2EC7869C945034AB078358020311','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_06_00_auth.sql','2A8049DC2923420A002D42FB6F02C2FFCC5CDD22','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_08_00_auth.sql','4D7D8EEF285C982BB676836602266501BEC26764','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_10_00_auth.sql','4AE68FD97A95CEE5143EA20FD33F5D557367AC1F','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_00_auth.sql','80A71C8921CFEBB547D264558B6DE27201685B84','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_01_auth.sql','3E88183E1A85D11BFD74CF9A32A725C44AE02EEC','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_21_00_auth.sql','1B3B48DBA06368B985C548D166C515C9DD598CB9','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_00_auth.sql','96AB595E0D2A088750E3F48B0AF0A8A14F3CFE1E','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_01_auth.sql','FB11FB834E488B0FD3AFDABCC1A3113092E7C2E5','ARCHIVED','2015-05-02 13:57:57',0),('2015_07_02_00_auth.sql','E5EE3842AB9B01851E49B360FBAF6FFEEAB2A8DA','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_06_00_auth.sql','6D1ADBA496DC6E6D7B3BF887DA8D4D17D3FBACE0','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_00_auth.sql','CB54020AFD1E31742FD8BF9CE16879625E289788','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_01_auth.sql','74D281CB82E0DA36D628BDC7AC797AE5498DB461','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_16_00_auth.sql','A057E95B5553B6A57A1642FE3FEC8E2E62EDE3C6','ARCHIVED','2015-10-10 08:30:48',0),('2015_07_29_00_auth.sql','0000FECBC413E96C7C45F303D162E263EFBA7116','ARCHIVED','2015-10-10 08:30:48',0),('2015_08_26_00_auth.sql','3071C02A2EB7DCBF4CEE10279FEFAB7C29A43A3A','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_00_auth.sql','F765D82B37873FA67447347D5B83C99C159FB452','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_01_auth.sql','97A72DBCBF14D27A1863834A22296905FF276086','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_09_00_auth.sql','495A0CF1B1C49205D4A5D3C25A4E1EB95616D6B4','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_15_00_auth.sql','D1FEFDA4C98F30384DF4B64D5A53187303EB5786','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_09_00_auth.sql','B6D643D444C6AE711503F73B96B6252A852913D6','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_16_00_auth.sql','366AFFD1088762866091A81CE1EC64138B8B35F1','ARCHIVED','2015-11-08 00:46:02',62),('2015_10_17_00_auth.sql','AC0D45E905033F42093852D2C4476663BDACCB3D','ARCHIVED','2015-10-17 12:39:12',0),('2015_11_01_00_auth_2015_08_21_00.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-11-01 14:50:26',0),('2015_11_08_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2015-11-08 00:51:45',0),('2015_11_21_00_auth.sql','575A1D697CC6C7C517F7CCB950988267C99CE7FA','RELEASED','2015-11-21 21:25:38',0),('2015_12_07_00_auth.sql','24A07AC1F38E5D26A3599FC06D29E267418F69F3','RELEASED','2015-12-07 20:55:48',0),('2016_01_13_00_auth.sql','114527BCCB0DE286CBE6FDA3029DD0523D1037FA','RELEASED','2016-01-13 21:39:13',0),('2016_03_22_01_auth_2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','RELEASED','2016-03-22 22:55:13',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/auth/2016_03_22_01_auth_2016_01_13_00_auth.sql b/sql/updates/auth/2016_03_22_01_auth_2016_01_13_00_auth.sql new file mode 100644 index 00000000000..c70d4c09468 --- /dev/null +++ b/sql/updates/auth/2016_03_22_01_auth_2016_01_13_00_auth.sql @@ -0,0 +1,6 @@ +-- +DELETE FROM `rbac_permissions` WHERE `id`=836; +INSERT INTO `rbac_permissions` (`id`,`name`) VALUES (836,"Command: .debug boundary"); + +DELETE FROM `rbac_linked_permissions` WHERE `linkedId`=836; +INSERT INTO `rbac_linked_permissions` (`id`,`linkedId`) VALUES (196, 836); diff --git a/sql/updates/world/2016_01_02_01_world.sql b/sql/updates/world/2016_01_02_01_world.sql new file mode 100644 index 00000000000..b862cc0e644 --- /dev/null +++ b/sql/updates/world/2016_01_02_01_world.sql @@ -0,0 +1,37 @@ +-- +-- SAI script for Wyrmrest Temple taxi Flight Paths + +SET @Tariolstrasz := 26443; +SET @Torastrasza := 26949; +SET @Afrasastrasz := 27575; + +-- Ground ----> Top: 878 (@Tariolstrasz,9455,0) +-- Ground -> Middle: 883 (@Tariolstrasz,9455,1) +-- Top ----> Ground: 879 (@Torastrasza, 9457,0) +-- Top ----> Middle: 880 (@Torastrasza, 9457,1) +-- Middle ----> Top: 881 (@Afrasastrasz,9563,0) +-- Middle -> Ground: 882 (@Afrasastrasz,9563,1) + +-- Set AIName and remove old ScriptName in creature_template for all 3 NPCs +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName`= '' WHERE `entry` IN (@Tariolstrasz,@Torastrasza,@Afrasastrasz); + +-- Tariolstrasz (Steward of Wyrmrest Temple) +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = @Tariolstrasz); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@Tariolstrasz, 0, 0, 2, 62, 0, 100, 0, 9455, 0, 0, 0, 52, 878, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Tariolstrasz - On Gossip Option 0 Selected - Activate Taxi Path 878'), +(@Tariolstrasz, 0, 1, 2, 62, 0, 100, 0, 9455, 1, 0, 0, 52, 883, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Tariolstrasz - On Gossip Option 1 Selected - Activate Taxi Path 883'), +(@Tariolstrasz, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Tariolstrasz - On Gossip Options Selected - Close Gossip'); + +-- Torastrasza (Majordomo to the Ruling Council) +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = @Torastrasza); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@Torastrasza, 0, 0, 2, 62, 0, 100, 0, 9457, 0, 0, 0, 52, 879, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Torastrasza - On Gossip Option 0 Selected - Activate Taxi Path 879'), +(@Torastrasza, 0, 1, 2, 62, 0, 100, 0, 9457, 1, 0, 0, 52, 880, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Torastrasza - On Gossip Option 1 Selected - Activate Taxi Path 880'), +(@Torastrasza, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Torastrasza - On Gossip Options Selected - Close Gossip'); + +-- Lord Afrasastrasz (Commander of Wyrmrest Temple Defenses) +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = @Afrasastrasz); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@Afrasastrasz, 0, 0, 2, 62, 0, 100, 0, 9563, 0, 0, 0, 52, 881, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Lord Afrasastrasz - On Gossip Option 0 Selected - Activate Taxi Path 881'), +(@Afrasastrasz, 0, 1, 2, 62, 0, 100, 0, 9563, 1, 0, 0, 52, 882, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Lord Afrasastrasz - On Gossip Option 1 Selected - Activate Taxi Path 882'), +(@Afrasastrasz, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Lord Afrasastrasz - On Gossip Options Selected - Close Gossip'); diff --git a/sql/updates/world/2016_03_20_02_world.sql b/sql/updates/world/2016_03_20_02_world.sql new file mode 100644 index 00000000000..9b03a9cdea3 --- /dev/null +++ b/sql/updates/world/2016_03_20_02_world.sql @@ -0,0 +1,40 @@ +-- Charscale Invoker SAI +SET @ENTRY := 40417; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,6000,6000,8000,8000,11,75419,0,0,0,0,0,2,0,0,0,0,0,0,0,"Charscale Invoker - In Combat - Cast 'Scorch'"), +(@ENTRY,0,1,0,0,0,100,0,10000,10000,20000,20000,11,75413,0,0,0,0,0,1,0,0,0,0,0,0,0,"Charscale Invoker - In Combat - Cast 'Flame Wave'"); + +-- Charscale Assaulter SAI +SET @ENTRY := 40419; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,6000,6000,7000,7000,11,15284,0,0,0,0,0,2,0,0,0,0,0,0,0,"Charscale Assaulter - In Combat - Cast 'Cleave'"), +(@ENTRY,0,1,0,0,0,100,0,14000,14000,14000,14000,11,75418,0,0,0,0,0,1,0,0,0,0,0,0,0,"Charscale Assaulter - In Combat - Cast 'Shockwave'"); + +-- Charscale Commander SAI +SET @ENTRY := 40423; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,0,0,100,0,8000,8000,40000,40000,11,75414,0,0,0,0,0,1,0,0,0,0,0,0,0,"Charscale Commander - In Combat - Cast 'Rallying Shout'"), +(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Charscale Commander - In Combat - Say Line 0"), +(@ENTRY,0,2,0,0,0,100,0,15000,15000,14000,14000,11,13737,0,0,0,0,0,2,0,0,0,0,0,0,0,"Charscale Commander - In Combat - Cast 'Mortal Strike'"); + +-- Charscale Commander Text +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `comment`) VALUES +(@ENTRY, 0, 0, '%s rallies the other combatants with a battle roar!', 41, 0, 100, 0, 0, 0, 40420, 'Charscale Commander'); + +-- Charscale Elite SAI +SET @ENTRY := 40421; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,12000,12000,11000,11000,11,15621,0,0,0,0,0,2,0,0,0,0,0,0,0,"Charscale Elite - In Combat - Cast 'Skull Crack'"); + +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_ruby_sanctum_rallying_shout'; +INSERT INTO `spell_script_names` VALUE +(75415, 'spell_ruby_sanctum_rallying_shout'); diff --git a/sql/updates/world/2016_03_21_00_world_2015_11_27_00.sql b/sql/updates/world/2016_03_21_00_world_2015_11_27_00.sql new file mode 100644 index 00000000000..15be2ab73ed --- /dev/null +++ b/sql/updates/world/2016_03_21_00_world_2015_11_27_00.sql @@ -0,0 +1,3 @@ +DELETE FROM `trinity_string` WHERE `entry` = 11010; +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(11010, 'You didn\'t get kicked out of the instance even if Player::CheckInstanceLoginValid() returned false and without .gm on flag'); diff --git a/sql/updates/world/2016_03_21_01_world_2015_12_27_instancerevive.sql b/sql/updates/world/2016_03_21_01_world_2015_12_27_instancerevive.sql new file mode 100644 index 00000000000..3bee62963ef --- /dev/null +++ b/sql/updates/world/2016_03_21_01_world_2015_12_27_instancerevive.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `trinity_string` WHERE `entry`=11014; +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(11014,"You are already locked to %s."); diff --git a/sql/updates/world/2016_03_21_02_world_2016_01_03_01_world.sql b/sql/updates/world/2016_03_21_02_world_2016_01_03_01_world.sql new file mode 100644 index 00000000000..3ddb56a9c72 --- /dev/null +++ b/sql/updates/world/2016_03_21_02_world_2016_01_03_01_world.sql @@ -0,0 +1,26 @@ +-- +-- Sergeant Kan'ren, Wretched Captive and Novice Ranger SAI +SET @Sergeant := 16924; +SET @Captive := 16916; +SET @Ranger := 16923; + +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry` in (@Sergeant, @Captive, @Ranger); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@Sergeant, @Ranger, @Captive) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@Sergeant*100 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@Sergeant,0,0,0,1,0,100,0,60000,100000,100000,120000,80,@Sergeant*100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sergeant Kan'ren - Out of Combat - Action list"), +(@Sergeant*100,9,0,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sergeant Kan'ren - Action list - Say Line 0"), +(@Sergeant*100,9,1,0,0,0,100,0,5000,5000,0,0,5,18,0,0,0,0,0,19,@Captive,10,0,0,0,0,0,"Sergeant Kan'ren - Action list - Captive Play Emote 18"), +(@Sergeant*100,9,2,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,19,@Captive,10,0,0,0,0,0,"Sergeant Kan'ren - Action list - Captive Say Line 0"), +(@Sergeant*100,9,3,0,0,0,100,0,8000,8000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sergeant Kan'ren - Action list - Say Line 1"), +(@Captive,0,0,0,1,0,100,0,14000,14000,14000,14000,5,20,0,0,0,0,0,1,0,0,0,0,0,0,0,"Wretched Captive - Out of Combat - Play Emote 20"), +(@Ranger,0,0,0,1,0,100,0,50000,70000,70000,80000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Ranger - Out of Combat - Say text"); + +UPDATE `creature` SET `movementtype`=0 WHERE `guid`=58691; +UPDATE `creature_addon` SET `path_id`=0 WHERE `guid`=58691; +DELETE FROM `waypoint_data` WHERE `id`=586910; +DELETE FROM `waypoint_scripts` WHERE `id` IN (66, 67, 68, 69, 70); + +DELETE FROM `creature_text` WHERE `entry`=@Ranger; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`,`BroadcastTextID`) VALUES +(@Ranger,0,0, 'I might just have to go hunting for that Wretched beast now that there''s a bounty on his head.',12,1,100,0,0,0, 'Ranger', 12832); diff --git a/sql/updates/world/2016_03_21_03_world_2016_01_03_02_world.sql b/sql/updates/world/2016_03_21_03_world_2016_01_03_02_world.sql new file mode 100644 index 00000000000..79eba012e41 --- /dev/null +++ b/sql/updates/world/2016_03_21_03_world_2016_01_03_02_world.sql @@ -0,0 +1,9 @@ +-- Issue #16168 +-- Orbaz Bloodbane: Fix incorrect creature texts +-- By: dr-j +UPDATE `creature_text` SET `BroadcastTextId`=31961 WHERE `entry`=31283 AND `groupid`=1 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=31962 WHERE `entry`=31283 AND `groupid`=2 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=31963 WHERE `entry`=31283 AND `groupid`=3 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=31966 WHERE `entry`=31283 AND `groupid`=4 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=31967 WHERE `entry`=31283 AND `groupid`=5 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=31964 WHERE `entry`=31283 AND `groupid`=6 AND `id`=0; diff --git a/sql/updates/world/2016_03_21_04_world_2016_01_03_03_world.sql b/sql/updates/world/2016_03_21_04_world_2016_01_03_03_world.sql new file mode 100644 index 00000000000..1b1766ee557 --- /dev/null +++ b/sql/updates/world/2016_03_21_04_world_2016_01_03_03_world.sql @@ -0,0 +1,10 @@ +-- Betrayal (Drakuru) fixes: +-- Fix "Blight Fog" cast behavior +-- Fix "Throw Blight Crystal" cast timing +-- By: dr-j +UPDATE `smart_scripts` SET `event_param2`=7500, `event_param3`=10000, `event_param4`=20000 WHERE `entryorguid`=28998 AND `source_type`=0 AND `id`=5 AND `link`=0; + +DELETE FROM `smart_scripts` WHERE `entryorguid`=28998 AND `source_type`=0 AND `id` in(13,14); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(28998, 0, 13, 0, 0, 0, 100, 0, 0, 0, 60000, 60000, 28, 54104, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Overlord Drakuru - IC - Remove Aura (Blight Fog'), +(28998, 0, 14, 0, 0, 0, 100, 0, 45000, 45000, 60000, 60000, 11, 54104, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Overlord Drakuru - IC - Cast Blight Fog'); diff --git a/sql/updates/world/2016_03_21_05_world_2016_01_03_04_world.sql b/sql/updates/world/2016_03_21_05_world_2016_01_03_04_world.sql new file mode 100644 index 00000000000..ffe8eb07fd5 --- /dev/null +++ b/sql/updates/world/2016_03_21_05_world_2016_01_03_04_world.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `faction`=2109 WHERE `entry`=30012; diff --git a/sql/updates/world/2016_03_21_06_world_2016_01_03_05_world.sql b/sql/updates/world/2016_03_21_06_world_2016_01_03_05_world.sql new file mode 100644 index 00000000000..4c2fe0817f0 --- /dev/null +++ b/sql/updates/world/2016_03_21_06_world_2016_01_03_05_world.sql @@ -0,0 +1,25 @@ +-- Add sniffed gossip texts to menu +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (8095, 8096, 8100); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`) VALUES +(8095, 0, 2, 'Show me where I can fly.',12271,1,1,0,0,0,0,'',0), +(8096, 0, 0, 'Send me to Honor Point!',18200,1,1,0,0,0,0,'',0), +(8096, 1, 0, 'Send me to the Abyssal Shelf!',17936,1,1,0,0,0,0,'',0), +(8100, 0, 0, 'Send me to Shatter Point!',17937,1,1,0,0,0,0,'',0); + +-- Migrate NPC to use SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '', `gossip_menu_id` = 8096 WHERE `entry` = 20235; + +-- Condition: Gossip menu ID 0 needs either quest ID 10163 or quest ID 10346 to be incomplete. +-- Condition: Gossip menu ID 1 needs quest ID 10382 to be complete +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`= 15 AND `SourceGroup` = 8096 AND `SourceEntry`IN (0,1); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,8096,0,0,0,9,0,10163,0,0,0,0,'','Gryphoneer Windbellow - Show gossip option 0 if player has taken quest ID 10163'), +(15,8096,0,0,1,9,0,10346,0,0,0,0,'','Gryphoneer Windbellow - Show gossip option 0 if player has taken quest ID 10346'), +(15,8096,1,0,0,28,0,10382,0,0,0,0,'','Gryphoneer Windbellow - Show gossip option 1 if quest ID 10382 is completed'); + +-- Create SmartAI for Gryphoneer Windbellow +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = 20235); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(20235,0,0,2,62,0,100,0,8096,0,0,0,11,33899,0,0,0,0,0,7,0,0,0,0,0,0,0,'Gryphoneer Windbellow - On Gossip Option 0 Selected - Cast Spell 33899'), +(20235,0,1,2,62,0,100,0,8096,1,0,0,11,35065,0,0,0,0,0,7,0,0,0,0,0,0,0,'Gryphoneer Windbellow - On Gossip Option 1 Selected - Cast Spell 35065'), +(20235,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Gryphoneer Windbellow - On Linked Actions - Close Gossip'); diff --git a/sql/updates/world/2016_03_21_07_world_2016_01_05_01_world.sql b/sql/updates/world/2016_03_21_07_world_2016_01_05_01_world.sql new file mode 100644 index 00000000000..22075b2cf33 --- /dev/null +++ b/sql/updates/world/2016_03_21_07_world_2016_01_05_01_world.sql @@ -0,0 +1,24 @@ +-- Add gossip texts to menu +DELETE FROM `gossip_menu_option` WHERE `menu_id` = 8718; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`) VALUES +(8718, 0, 0, 'Yes, I''d love a ride to Blackwind Landing.',21550,1,1,0,0,0,0,'',0); + +DELETE FROM `npc_text` WHERE `ID` = 10977; +INSERT INTO `npc_text` (`ID`, `Probability0`, `Probability1`, `Probability2`, `Probability3`, `Probability4`, `Probability5`, `Probability6`, `Probability7`, `BroadcastTextID0`, `BroadcastTextID1`, `BroadcastTextID2`, `BroadcastTextID3`, `BroadcastTextID4`, `BroadcastTextID5`, `BroadcastTextID6`, `BroadcastTextID7`, `VerifiedBuild`) VALUES +(10977, 1, 0, 0, 0, 0, 0, 0, 0, 21547, 0, 0, 0, 0, 0, 0, 0, -15354); +-- Other npc_text (10978) is already set in DB + +-- Migrate NPC to use SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 23413; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (14, 15) AND `SourceGroup` = 8718; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,8718,10977,0,0,5,0,1031,224,0,1,0,'','Skyguard Handler Irena - Show gossip menu text below Honored reputation with faction 1031'), +(14,8718,10978,0,0,5,0,1031,224,0,0,0,'','Skyguard Handler Irena - Show gossip menu text above Honored reputation with faction 1031'), +(15,8718,0,0,0,5,0,1031,224,0,0,0,'','Skyguard Handler Irena - Show gossip option 0 if player has reputation Honored or above with faction 1031'); + +-- Create SmartAI for Skyguard Handler Irena +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = 23413); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(23413,0,0,1,62,0,100,0,8718,0,0,0,11,41278,0,0,0,0,0,7,0,0,0,0,0,0,0,'Skyguard Handler Irena - On Gossip Option 0 Selected - Cast Spell 41278'), +(23413,0,1,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Skyguard Handler Irena - On Linked Actions - Close Gossip'); diff --git a/sql/updates/world/2016_03_21_08_world_2016_01_05_02_world.sql b/sql/updates/world/2016_03_21_08_world_2016_01_05_02_world.sql new file mode 100644 index 00000000000..64909129e60 --- /dev/null +++ b/sql/updates/world/2016_03_21_08_world_2016_01_05_02_world.sql @@ -0,0 +1,21 @@ +-- Add gossip texts to menu +DELETE FROM `gossip_menu_option` WHERE `menu_id` = 8719; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`) VALUES +(8719,0,0,'Absolutely! Send me to the Skyguard Outpost.',21553,1,1,0,0,0,0,'',0); +-- This was already here but I think rather enumerate from 0 than 1 in gossip_menu_option + +-- Migrate NPC to use SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 23415; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (14, 15) AND `SourceGroup` = 8719; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,8719,10980,0,0,5,0,1031,224,0,1,0,'','Skyguard Handler Deesak - Show gossip menu text below Honored reputation with faction 1031'), +(14,8719,10979,0,0,5,0,1031,224,0,0,0,'','Skyguard Handler Deesak - Show gossip menu text above Honored reputation with faction 1031'), +(15,8719,0,0,0,5,0,1031,224,0,0,0,'','Skyguard Handler Deesak - Show gossip option 0 if player has reputation Honored or above with faction 1031'); +-- Not sure if the missing condition is necessary, but it makes things a lot clearer when looking at the table. + +-- Create SmartAI for Skyguard Handler Deesak +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = 23415); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(23415,0,0,1,62,0,100,0,8719,0,0,0,11,41279,0,0,0,0,0,7,0,0,0,0,0,0,0,'Skyguard Handler Deesak - On Gossip Option 0 Selected - Cast Spell 41279'), +(23415,0,1,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Skyguard Handler Deesak - On Linked Actions - Close Gossip'); diff --git a/sql/updates/world/2016_03_21_09_world_2016_01_07_00_world.sql b/sql/updates/world/2016_03_21_09_world_2016_01_07_00_world.sql new file mode 100644 index 00000000000..d36dda80e50 --- /dev/null +++ b/sql/updates/world/2016_03_21_09_world_2016_01_07_00_world.sql @@ -0,0 +1,25 @@ +-- Add sniffed gossip texts to menu +DELETE FROM `gossip_menu_option` WHERE `menu_id` = 7970; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`) VALUES +(7970, 0, 0, 'I''m on a bombing mission for Forward Commander Kingston. I need a gryphon destroyer!',18198,1,1,0,0,0,0,'',0), +(7970, 1, 0, 'Send me to Shatter Point!',17935,1,1,0,0,0,0,'',0); + +-- Migrate NPC to use SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '', `gossip_menu_id` = 7970 WHERE `entry` = 19409; + +-- Condition: Gossip menu ID 0 needs either quest ID 10146 to be incomplete. +-- Condition: Gossip menu ID 1 needs quest ID 10340 to not be rewarded +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`= 15 AND `SourceGroup` = 7970 AND `SourceEntry`IN (0,1); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,7970,0,0,0,9,0,10146,0,0,0,0,'','Wing Commander Dabir''ee - Show gossip option 0 if player has taken quest ID 10146'), +(15,7970,1,0,0,8,0,10340,0,0,1,0,'','Wing Commander Dabir''ee - Show gossip option 1 if quest ID 10340 is not rewarded'); + +-- Create SmartAI for Wing Commander Dabir'ee +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = 19409); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(19409,0,0,2,62,0,100,0,7970,0,0,0,11,33768,0,0,0,0,0,7,0,0,0,0,0,0,0,'Wing Commander Dabir''ee - On Gossip Option 0 Selected - Cast Spell 33768'), +(19409,0,1,2,62,0,100,0,7970,1,0,0,11,35069,0,0,0,0,0,7,0,0,0,0,0,0,0,'Wing Commander Dabir''ee - On Gossip Option 1 Selected - Cast Spell 35069'), +(19409,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Wing Commander Dabir''ee - On Linked Actions - Close Gossip'); + +-- Misc creature fixes +UPDATE `creature` SET `MovementType` = 0 WHERE id = 22987 AND guid IN (79007, 79008, 79009); diff --git a/sql/updates/world/2016_03_21_10_world_2016_01_09_00_world.sql b/sql/updates/world/2016_03_21_10_world_2016_01_09_00_world.sql new file mode 100644 index 00000000000..534e17ccb00 --- /dev/null +++ b/sql/updates/world/2016_03_21_10_world_2016_01_09_00_world.sql @@ -0,0 +1,16 @@ +-- +-- Enable Landmine Knockback Achievement by removing it from disables +DELETE FROM `disables` WHERE `sourceType`= 4 AND `entry`= 5258; + +-- Insert missing Landmine Knockback Achievement criteria data +DELETE FROM `achievement_criteria_data` WHERE `criteria_id`= 5258; +INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES +(5258,0,57064,0,''); + +-- Update description for the linked spells 54355 and 54402 +UPDATE `spell_linked_spell` SET `comment`= 'Trigger Detonation with Land Mine Knockback' WHERE `spell_trigger` = 54355; + +-- Insert spell script name for spell 57099 +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_landmine_knockback_achievement'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(57099,'spell_gen_landmine_knockback_achievement'); diff --git a/sql/updates/world/2016_03_22_00_world_2016_01_05_00_world.sql b/sql/updates/world/2016_03_22_00_world_2016_01_05_00_world.sql new file mode 100644 index 00000000000..3f7f01449fc --- /dev/null +++ b/sql/updates/world/2016_03_22_00_world_2016_01_05_00_world.sql @@ -0,0 +1,20 @@ +DELETE FROM `spell_area` WHERE `spell` IN(52214,50735); + +INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +(52214, 3711, 12572, 12572, 0, 0, 2, 1, 74, 11), -- Gods Like Shiny Things +(52214, 3711, 12704, 12704, 0, 0, 2, 1, 74, 11), -- Appeasing the Great Rainstone +(50735, 3711, 12532, 12532, 0, 0, 2, 1, 74, 11), -- Flown the Coop! +(50735, 3711, 12702, 12702, 0, 0, 2, 1, 74, 11); -- Chicken Party! + +DELETE FROM `smart_scripts` WHERE `entryorguid`=28138 AND `source_type`=0 AND `id`=3 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28138 AND `source_type`=0 AND `id`=1 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28138 AND `source_type`=0 AND `id`=2 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28138 AND `source_type`=0 AND `id`=0 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28027 AND `source_type`=0 AND `id`=9 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28027 AND `source_type`=0 AND `id`=10 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28027 AND `source_type`=0 AND `id`=11 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28120 AND `source_type`=0 AND `id`=13 AND `link`=0; + +UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid` IN(28214,28215,28216, 28120, 28121,28122,28362) AND `source_type`=0; +UPDATE `smart_scripts` SET `event_param3`=60000, `event_param4`=60000 WHERE `entryorguid`=28362 AND `source_type`=0 AND `id`=0 AND `link`=0; + diff --git a/sql/updates/world/2016_03_22_01_world_2016_01_07_01_world.sql b/sql/updates/world/2016_03_22_01_world_2016_01_07_01_world.sql new file mode 100644 index 00000000000..4a15aa405ec --- /dev/null +++ b/sql/updates/world/2016_03_22_01_world_2016_01_07_01_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature` WHERE `id`=22972; diff --git a/sql/updates/world/2016_03_22_02_world_2016_01_07_02_world.sql b/sql/updates/world/2016_03_22_02_world_2016_01_07_02_world.sql new file mode 100644 index 00000000000..7724b42ac9d --- /dev/null +++ b/sql/updates/world/2016_03_22_02_world_2016_01_07_02_world.sql @@ -0,0 +1,2 @@ +-- fix a start-up warning +UPDATE `creature` SET `spawndist`=0 WHERE `guid` IN (79007,79008,79009); diff --git a/sql/updates/world/2016_03_22_03_world_2016_01_10_00_world.sql b/sql/updates/world/2016_03_22_03_world_2016_01_10_00_world.sql new file mode 100644 index 00000000000..83ed21c8489 --- /dev/null +++ b/sql/updates/world/2016_03_22_03_world_2016_01_10_00_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `creature_text` SET `text`='Windroc Matriarch lets loose a terrifying shriek.', `BroadcastTextId`=16149 WHERE `entry`=19055; +UPDATE `smart_scripts` SET `action_type`=49, `action_param1`=0 WHERE `entryorguid`=1905500 AND `id`=3; diff --git a/sql/updates/world/2016_03_22_04_world_2016_01_10_01_world.sql b/sql/updates/world/2016_03_22_04_world_2016_01_10_01_world.sql new file mode 100644 index 00000000000..c79c157a1a1 --- /dev/null +++ b/sql/updates/world/2016_03_22_04_world_2016_01_10_01_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `unit_flags`=32832 WHERE `entry`= 18689; diff --git a/sql/updates/world/2016_03_22_05_world_2016_01_10_02_world.sql b/sql/updates/world/2016_03_22_05_world_2016_01_10_02_world.sql new file mode 100644 index 00000000000..eca8ef07849 --- /dev/null +++ b/sql/updates/world/2016_03_22_05_world_2016_01_10_02_world.sql @@ -0,0 +1,6 @@ +-- +UPDATE `creature_template` SET `AIName`='SmartAI', `ScriptName`='' WHERE `entry`=25623; +DELETE FROM `smart_scripts` WHERE `entryorguid`=25623 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(25623, 0, 0, 0, 0, 0, 100, 0, 3000, 5000, 4000, 6000, 11, 54185, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Harvest Collector - IC - Cast Claw Slash'), +(25623, 0, 1, 0, 8, 0, 100, 0, 47166, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Harvest Collector - On spell hit - Despawn'); diff --git a/sql/updates/world/2016_03_22_06_world_2016_01_10_03_world.sql b/sql/updates/world/2016_03_22_06_world_2016_01_10_03_world.sql new file mode 100644 index 00000000000..5ac352ffe10 --- /dev/null +++ b/sql/updates/world/2016_03_22_06_world_2016_01_10_03_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `smart_scripts` SET `action_param6`=2 WHERE `entryorguid`=-96556 AND `id`=0 AND `source_type`=0; diff --git a/sql/updates/world/2016_03_22_07_world_2016_01_10_04_world.sql b/sql/updates/world/2016_03_22_07_world_2016_01_10_04_world.sql new file mode 100644 index 00000000000..da6eed191ad --- /dev/null +++ b/sql/updates/world/2016_03_22_07_world_2016_01_10_04_world.sql @@ -0,0 +1,11 @@ +-- +DELETE FROM `instance_template` WHERE `map` = 169; +INSERT INTO `instance_template` (`map`, `parent`, `script`, `allowMount`) VALUES +(169, 0, '', 0); + +DELETE FROM `game_tele` WHERE `id` IN (1425, 1426, 1427, 1428); +INSERT INTO `game_tele` (`id`, `position_x`, `position_y`, `position_z`, `orientation`, `map`, `name`) VALUES +(1425, -366.091, 3097.86, 92.317, 0.0487625, 169, 'EmeraldDream'), +(1426, 2781.566406, 3006.763184, 23.221882, 0.5, 169, 'EmeraldStatue'), +(1427, -2128.12, -1005.89, 132.213, 0.5, 169, 'VerdantFields'), +(1428, 2732.93, -3319.63, 101.284, 0.5, 169, 'EmeraldForest'); diff --git a/sql/updates/world/2016_03_22_08_world_2016_01_12_03_world.sql b/sql/updates/world/2016_03_22_08_world_2016_01_12_03_world.sql new file mode 100644 index 00000000000..6ff3a769918 --- /dev/null +++ b/sql/updates/world/2016_03_22_08_world_2016_01_12_03_world.sql @@ -0,0 +1,15 @@ +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=32820; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=32820; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(32820,0,0,0,6,0,100,0,0,0,0,0,11,62014,2,0,0,0,0,7,0,0,0,0,0,0,0,"Wild Turkey - On Just Died - Cast 'Turkey Tracker'"); + +DELETE FROM `creature_text` WHERE `entry`=32820; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES +(32820,0,0,'Turkey Hunter!',42,0,100,0,0,0,33163,0,'Wild Turkey'), +(32820,1,0,'Turkey Domination!',42,0,100,0,0,0,33164,0,'Wild Turkey'), +(32820,2,0,'Turkey Slaughter!',42,0,100,0,0,0,33165,0,'Wild Turkey'), +(32820,3,0,'TURKEY TRIUMPH!',42,0,100,0,0,0,33167,0,'Wild Turkey'); + +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_pilgrims_bounty_turkey_tracker'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(62014,'spell_pilgrims_bounty_turkey_tracker'); diff --git a/sql/updates/world/2016_03_22_09_world_2016_01_13_00_world.sql b/sql/updates/world/2016_03_22_09_world_2016_01_13_00_world.sql new file mode 100644 index 00000000000..cba5d3a18a1 --- /dev/null +++ b/sql/updates/world/2016_03_22_09_world_2016_01_13_00_world.sql @@ -0,0 +1,10 @@ +-- +DELETE FROM `command` WHERE `permission`=836; +INSERT INTO `command` (`name`,`permission`,`help`) VALUES ("debug boundary",836,"Syntax: .debug boundary [fill] [duration] +Flood fills the targeted unit's movement boundary and marks the edge of said boundary with debug creatures.\nSpecify 'fill' as first parameter to fill the entire area with debug creatures."); + +DELETE FROM `trinity_string` WHERE `entry` IN (11011,11012,11013); +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(11011,"VisualizeBoundary warning: No interior point of the creature's boundary could be found - check if you have mutually exclusive boundaries!"), +(11012,"VisualizeBoundary error: Creature movement is unbounded"), +(11013,"VisualizeBoundary warning: Reached fail-safe flood boundary - check is your boundary is unbounded!"); diff --git a/sql/updates/world/2016_03_22_10_world_2016_01_16_01_world.sql b/sql/updates/world/2016_03_22_10_world_2016_01_16_01_world.sql new file mode 100644 index 00000000000..235378a7a84 --- /dev/null +++ b/sql/updates/world/2016_03_22_10_world_2016_01_16_01_world.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `npc_text` WHERE `ID` = 10884; +DELETE FROM `gossip_menu` WHERE `entry`=8441 AND `text_id`=10884; diff --git a/sql/updates/world/2016_03_22_11_world_2016_01_16_02_world.sql b/sql/updates/world/2016_03_22_11_world_2016_01_16_02_world.sql new file mode 100644 index 00000000000..b36d7d69ff6 --- /dev/null +++ b/sql/updates/world/2016_03_22_11_world_2016_01_16_02_world.sql @@ -0,0 +1,7 @@ +-- +DELETE FROM `creature_template_addon` WHERE `entry` IN (16525); +INSERT INTO `creature_template_addon` (`entry`, `bytes2`, `auras`) VALUES +(16525, 1, '29920'); + +UPDATE `smart_scripts` SET `event_chance`=100 WHERE `entryorguid`=16525 AND `source_type`=0; +UPDATE `smart_scripts` SET `event_flags`=3, `event_param1`=0, `event_param2`=0, `event_param3`=0, `event_param4`=0, `action_type`=28, `comment`="Spell Shade - In Combat - Remove Aura 'Phasing Invisibility' (Normal Dungeon)" WHERE `entryorguid`=16525 AND `source_type`=0 AND `id`=3; diff --git a/sql/updates/world/2016_03_22_12_world_2016_01_16_03_world.sql b/sql/updates/world/2016_03_22_12_world_2016_01_16_03_world.sql new file mode 100644 index 00000000000..5a06cfaecca --- /dev/null +++ b/sql/updates/world/2016_03_22_12_world_2016_01_16_03_world.sql @@ -0,0 +1,11 @@ +-- +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=29333; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=29333; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid` IN (29329, 29330, 29338) AND `id`=2; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(29329,0,2,0,8,0,100,0,52741,0,0,0,41,1000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Onslaught Paladin - On spell hit "Darkmender''s Tincture" - Despawn'), +(29330,0,2,0,8,0,100,0,52741,0,0,0,41,1000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Onslaught Harbor Guard - On spell hit "Darkmender''s Tincture" - Despawn'), +(29338,0,2,0,8,0,100,0,52741,0,0,0,41,1000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Raven Bishop - On spell hit "Darkmender''s Tincture" - Despawn'), +(29333,0,0,0,8,0,100,0,52741,0,0,0,41,1000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Onslaught Gryphon Rider - On spell hit "Darkmender''s Tincture" - Despawn'); + +UPDATE `spell_scripts` SET `datalong2`=2, `dataint`=0 WHERE `id`=52741 AND `command`=15; diff --git a/sql/updates/world/2016_03_22_13_world_2016_01_17_01_world.sql b/sql/updates/world/2016_03_22_13_world_2016_01_17_01_world.sql new file mode 100644 index 00000000000..8e5bcd22a07 --- /dev/null +++ b/sql/updates/world/2016_03_22_13_world_2016_01_17_01_world.sql @@ -0,0 +1,9 @@ +-- +DELETE FROM `creature_template_addon` WHERE `entry` IN (21694,21914,17796,17797,20629,20630); +INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(21694,0,0x0,0x1,'18950'), -- 21694 - 18950 +(21914,0,0x0,0x1,'18950'), -- 21914 - 18950 +(17796,0,0x0,0x1,'18950'), -- 17796 - 18950 +(17797,0,0x0,0x1,'18950'), -- 17797 - 18950 +(20629,0,0x0,0x1,'18950'), -- 20629 - 18950 +(20630,0,0x0,0x1,'18950'); -- 20630 - 18950 diff --git a/sql/updates/world/2016_03_22_14_world_2016_01_17_02_world.sql b/sql/updates/world/2016_03_22_14_world_2016_01_17_02_world.sql new file mode 100644 index 00000000000..f019b927228 --- /dev/null +++ b/sql/updates/world/2016_03_22_14_world_2016_01_17_02_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `creature_onkill_reputation` WHERE `creature_id`=20477; +INSERT INTO `creature_onkill_reputation` (`creature_id`, `RewOnKillRepFaction1`, `RewOnKillRepFaction2`, `MaxStanding1`, `IsTeamAward1`, `RewOnKillRepValue1`, `MaxStanding2`, `IsTeamAward2`, `RewOnKillRepValue2`, `TeamDependent`) VALUES +(20477, 942, 0, 5, 0, 7, 0, 0, 0, 0); diff --git a/sql/updates/world/2016_03_22_15_world_2016_01_17_06_world.sql b/sql/updates/world/2016_03_22_15_world_2016_01_17_06_world.sql new file mode 100644 index 00000000000..659f146845a --- /dev/null +++ b/sql/updates/world/2016_03_22_15_world_2016_01_17_06_world.sql @@ -0,0 +1,5 @@ +UPDATE `smart_scripts` SET `id`=5 WHERE `source_type` = 9 AND `entryorguid` = 2229300 AND `id`=4 AND `action_type`=51; + +DELETE FROM `smart_scripts` WHERE `source_type` = 9 AND `entryorguid` = 2229300 AND `id`=4; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(2229300, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 85, 38758, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Inactive Fel Reaver - Action list - Invoker Cast [PH] Quest reward: Nether Gas In a Fel Fire Engine'); diff --git a/sql/updates/world/2016_03_22_16_world_2016_01_17_10_world.sql b/sql/updates/world/2016_03_22_16_world_2016_01_17_10_world.sql new file mode 100644 index 00000000000..0fdc04eb60f --- /dev/null +++ b/sql/updates/world/2016_03_22_16_world_2016_01_17_10_world.sql @@ -0,0 +1 @@ +UPDATE `creature` SET `MovementType`=0 WHERE `guid`=131180; diff --git a/sql/updates/world/2016_03_22_17_world_2016_01_17_13_world.sql b/sql/updates/world/2016_03_22_17_world_2016_01_17_13_world.sql new file mode 100644 index 00000000000..163aa3fb659 --- /dev/null +++ b/sql/updates/world/2016_03_22_17_world_2016_01_17_13_world.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `creature` WHERE `guid`=66270; +UPDATE `creature` SET `position_x`=-3047.323, `position_y`=4081.128, `position_z`=2.707369, `orientation`=5.484657, `spawndist`=10, `MovementType`=1 WHERE `guid`=66343; diff --git a/sql/updates/world/2016_03_22_18_world_2016_01_17_15_world.sql b/sql/updates/world/2016_03_22_18_world_2016_01_17_15_world.sql new file mode 100644 index 00000000000..da949d7100d --- /dev/null +++ b/sql/updates/world/2016_03_22_18_world_2016_01_17_15_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_text` SET `TextRange`=3 WHERE `entry`=32871; diff --git a/sql/updates/world/2016_03_22_19_world_2016_01_18_00_world.sql b/sql/updates/world/2016_03_22_19_world_2016_01_18_00_world.sql new file mode 100644 index 00000000000..85f41cfc0c5 --- /dev/null +++ b/sql/updates/world/2016_03_22_19_world_2016_01_18_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `smart_scripts` SET `action_param2`=0 WHERE `entryorguid`=21126 AND `source_type`=0 AND `id` IN (4,5); diff --git a/sql/updates/world/2016_03_22_20_world_2016_01_18_04_world.sql b/sql/updates/world/2016_03_22_20_world_2016_01_18_04_world.sql new file mode 100644 index 00000000000..28ab2d96731 --- /dev/null +++ b/sql/updates/world/2016_03_22_20_world_2016_01_18_04_world.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `creature` WHERE id=27535; +DELETE FROM `vehicle_template_accessory` WHERE `entry` IN (27761); +INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `minion`, `description`, `summontype`) VALUES (27761, 27535,1, "Fordragon Battle Steed", 7); +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=27761; diff --git a/sql/updates/world/2016_03_23_00_world.sql b/sql/updates/world/2016_03_23_00_world.sql new file mode 100644 index 00000000000..b5a31f35526 --- /dev/null +++ b/sql/updates/world/2016_03_23_00_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `npc_vendor` WHERE `item` IN (2512,2515,3030,3464,9399,11285,19316,18042,12654,28053,24417,28056,30611,31949,33803,34581,31737,30319,41165,41586,52021,2516,8067,4960,2519,8068,5568,3033,8069,3465,10512,11284,10513,19317,15997,11630,13377,28060,23772,28061,30612,32883,32882,23773,34582,31735,41164,41584,52020); +DELETE FROM `creature_loot_template` WHERE `Item` IN (2512,2515,3030,3464,9399,11285,19316,18042,12654,28053,24417,28056,30611,31949,33803,34581,31737,30319,41165,41586,52021,2516,8067,4960,2519,8068,5568,3033,8069,3465,10512,11284,10513,19317,15997,11630,13377,28060,23772,28061,30612,32883,32882,23773,34582,31735,41164,41584,52020); +DELETE FROM `gameobject_loot_template` WHERE `Item` IN (2512,2515,3030,3464,9399,11285,19316,18042,12654,28053,24417,28056,30611,31949,33803,34581,31737,30319,41165,41586,52021,2516,8067,4960,2519,8068,5568,3033,8069,3465,10512,11284,10513,19317,15997,11630,13377,28060,23772,28061,30612,32883,32882,23773,34582,31735,41164,41584,52020); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8bf86b57139..4250df6d1f1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -8,40 +8,33 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Common Common.cpp Common.h) -file(GLOB_RECURSE sources_Collision Collision/*.cpp Collision/*.h) -file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h) -file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h) -file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h) -file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) -file(GLOB_RECURSE sources_Cryptography Cryptography/*.cpp Cryptography/*.h) +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging + ${CMAKE_CURRENT_SOURCE_DIR}/Platform + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) # Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in common project # It needs to be included both in authserver and worldserver for the static global variable to be properly initialized # and to handle crash logs on windows -set(sources_Debugging Debugging/Errors.cpp Debugging/Errors.h) -file(GLOB sources_localdir *.cpp *.h) +list(APPEND PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging/Errors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging/Errors.h) if (USE_COREPCH) - set(common_STAT_PCH_HDR PrecompiledHeaders/commonPCH.h) - set(common_STAT_PCH_SRC PrecompiledHeaders/commonPCH.cpp) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/commonPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/commonPCH.cpp) endif (USE_COREPCH) -set(common_STAT_SRCS - ${common_STAT_SRCS} - ${sources_Common} - ${sources_Collision} - ${sources_Threading} - ${sources_Utilities} - ${sources_Debugging} - ${sources_Configuration} - ${sources_Logging} - ${sources_Cryptography} - ${sources_localdir} +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_definitions(-DTRINITY_API_EXPORT_COMMON) + +add_library(common + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) # Do NOT add any extra include directory here, as we don't want the common @@ -53,37 +46,53 @@ set(common_STAT_SRCS # linkage (enums, defines...) it is discouraged to do so unless necessary, as it will pullute # include_directories leading to further unnoticed dependency aditions # Linker Depencency requirements: none -include_directories( - ${CMAKE_BINARY_DIR} +CollectIncludeDirectories( ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Collision - ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Management - ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Maps - ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Models - ${CMAKE_CURRENT_SOURCE_DIR}/Configuration - ${CMAKE_CURRENT_SOURCE_DIR}/Cryptography - ${CMAKE_CURRENT_SOURCE_DIR}/Debugging - ${CMAKE_CURRENT_SOURCE_DIR}/Logging - ${CMAKE_CURRENT_SOURCE_DIR}/Utilities - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/SFMT - ${CMAKE_SOURCE_DIR}/dep/utf8cpp - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(common + PUBLIC + # Provide the binary dir for all child targets + ${CMAKE_BINARY_DIR} + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_library(common STATIC - ${common_STAT_SRCS} - ${common_STAT_PCH_SRC} -) +target_link_libraries(common + PUBLIC + boost + cppformat + g3dlib + Detour + sfmt + utf8cpp + openssl + valgrind + threads + jemalloc) add_dependencies(common revision_data.h) +set_target_properties(common + PROPERTIES + FOLDER + "server") + +if( BUILD_SHARED_LIBS ) + if( UNIX ) + install(TARGETS common + LIBRARY + DESTINATION lib) + elseif( WIN32 ) + install(TARGETS common + RUNTIME + DESTINATION "${CMAKE_INSTALL_PREFIX}") + endif() +endif() + # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(common ${common_STAT_PCH_HDR} ${common_STAT_PCH_SRC}) + add_cxx_pch(common ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif () diff --git a/src/common/Collision/BoundingIntervalHierarchy.h b/src/common/Collision/BoundingIntervalHierarchy.h index 22ea36ec2e6..d84ee3f6bf3 100644 --- a/src/common/Collision/BoundingIntervalHierarchy.h +++ b/src/common/Collision/BoundingIntervalHierarchy.h @@ -67,7 +67,7 @@ struct AABound Copyright (c) 2003-2007 Christopher Kulla */ -class BIH +class TC_COMMON_API BIH { private: void init_empty() diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h index 0f18bb265f8..85707efebd2 100644 --- a/src/common/Collision/DynamicTree.h +++ b/src/common/Collision/DynamicTree.h @@ -31,7 +31,7 @@ namespace G3D class GameObjectModel; struct DynTreeImpl; -class DynamicMapTree +class TC_COMMON_API DynamicMapTree { DynTreeImpl *impl; diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index 1e64551956c..35437b7b816 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -42,7 +42,7 @@ namespace VMAP #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case //=========================================================== - class IVMapManager + class TC_COMMON_API IVMapManager { private: bool iEnableLineOfSightCalc; diff --git a/src/common/Collision/Management/MMapFactory.h b/src/common/Collision/Management/MMapFactory.h index edd074fc93d..6dda7a40a22 100644 --- a/src/common/Collision/Management/MMapFactory.h +++ b/src/common/Collision/Management/MMapFactory.h @@ -38,7 +38,7 @@ namespace MMAP // static class // holds all mmap global data // access point to MMapManager singleton - class MMapFactory + class TC_COMMON_API MMapFactory { public: static MMapManager* createOrGetMMapManager(); diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h index 45a60d88dc7..8aa28ec7ab4 100644 --- a/src/common/Collision/Management/MMapManager.h +++ b/src/common/Collision/Management/MMapManager.h @@ -38,7 +38,7 @@ namespace MMAP typedef std::set<uint32> TerrainSet; - struct NavMeshHolder + struct TC_COMMON_API NavMeshHolder { // Pre-built navMesh dtNavMesh* navMesh; @@ -49,7 +49,7 @@ namespace MMAP MMapTileSet loadedTileRefs; }; - struct PhasedTile + struct TC_COMMON_API PhasedTile { unsigned char* data; MmapTileHeader fileHeader; @@ -62,7 +62,7 @@ namespace MMAP typedef std::unordered_map<uint32, TerrainSet> TerrainSetMap; - class MMapData + class TC_COMMON_API MMapData { public: MMapData(dtNavMesh* mesh, uint32 mapId); @@ -90,7 +90,7 @@ namespace MMAP // singleton class // holds all all access to mmap loading unloading and meshes - class MMapManager + class TC_COMMON_API MMapManager { public: MMapManager() : loadedTiles(0), thread_safe_environment(true) {} diff --git a/src/common/Collision/Management/VMapFactory.h b/src/common/Collision/Management/VMapFactory.h index 1a45bd5094b..a730fa12ef2 100644 --- a/src/common/Collision/Management/VMapFactory.h +++ b/src/common/Collision/Management/VMapFactory.h @@ -29,7 +29,7 @@ namespace VMAP { //=========================================================== - class VMapFactory + class TC_COMMON_API VMapFactory { public: static IVMapManager* createOrGetVMapManager(); diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index 4125970f757..a3b383bdc10 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -51,7 +51,7 @@ namespace VMAP class StaticMapTree; class WorldModel; - class ManagedModel + class TC_COMMON_API ManagedModel { public: ManagedModel() : iModel(nullptr), iRefCount(0) { } @@ -75,7 +75,7 @@ namespace VMAP VMAP_DISABLE_LIQUIDSTATUS = 0x8 }; - class VMapManager2 : public IVMapManager + class TC_COMMON_API VMapManager2 : public IVMapManager { protected: // Tree to check collision diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index 58b58bf3073..0227a982b4c 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -29,7 +29,7 @@ namespace VMAP class GroupModel; class VMapManager2; - struct LocationInfo + struct TC_COMMON_API LocationInfo { LocationInfo(): hitInstance(nullptr), hitModel(nullptr), ground_Z(-G3D::finf()) { } const ModelInstance* hitInstance; @@ -37,7 +37,7 @@ namespace VMAP float ground_Z; }; - class StaticMapTree + class TC_COMMON_API StaticMapTree { typedef std::unordered_map<uint32, bool> loadedTileMap; typedef std::unordered_map<uint32, uint32> loadedSpawnMap; @@ -87,7 +87,7 @@ namespace VMAP StaticMapTree& operator=(StaticMapTree const& right) = delete; }; - struct AreaInfo + struct TC_COMMON_API AreaInfo { AreaInfo(): result(false), ground_Z(-G3D::finf()), flags(0), adtId(0), rootId(0), groupId(0) { } diff --git a/src/common/Collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h index 1e2dc1924f1..74111f69910 100644 --- a/src/common/Collision/Maps/TileAssembler.h +++ b/src/common/Collision/Maps/TileAssembler.h @@ -35,7 +35,7 @@ namespace VMAP */ //=============================================== - class ModelPosition + class TC_COMMON_API ModelPosition { private: G3D::Matrix3 iRotation; @@ -55,7 +55,7 @@ namespace VMAP typedef std::map<uint32, ModelSpawn> UniqueEntryMap; typedef std::multimap<uint32, uint32> TileMap; - struct MapSpawns + struct TC_COMMON_API MapSpawns { UniqueEntryMap UniqueEntries; TileMap TileEntries; @@ -64,7 +64,7 @@ namespace VMAP typedef std::map<uint32, MapSpawns*> MapData; //=============================================== - struct GroupModel_Raw + struct TC_COMMON_API GroupModel_Raw { uint32 mogpflags; uint32 GroupWMOID; @@ -82,7 +82,7 @@ namespace VMAP bool Read(FILE* f); }; - struct WorldModel_Raw + struct TC_COMMON_API WorldModel_Raw { uint32 RootWMOID; std::vector<GroupModel_Raw> groupsArray; @@ -90,7 +90,7 @@ namespace VMAP bool Read(const char * path); }; - class TileAssembler + class TC_COMMON_API TileAssembler { private: std::string iDestDir; diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 9d8687233c1..37f11af20ac 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -35,7 +35,7 @@ namespace VMAP class GameObject; struct GameObjectDisplayInfoEntry; -class GameObjectModelOwnerBase +class TC_COMMON_API GameObjectModelOwnerBase { public: virtual bool IsSpawned() const { return false; } @@ -47,7 +47,7 @@ public: virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const { } }; -class GameObjectModel /*, public Intersectable*/ +class TC_COMMON_API GameObjectModel /*, public Intersectable*/ { GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { } public: @@ -84,4 +84,6 @@ private: std::unique_ptr<GameObjectModelOwnerBase> owner; }; +TC_COMMON_API void LoadGameObjectModelList(std::string const& dataPath); + #endif // _GAMEOBJECT_MODEL_H diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h index d101630d1e9..84a41b15ce6 100644 --- a/src/common/Collision/Models/ModelInstance.h +++ b/src/common/Collision/Models/ModelInstance.h @@ -39,7 +39,7 @@ namespace VMAP MOD_HAS_BOUND = 1<<2 }; - class ModelSpawn + class TC_COMMON_API ModelSpawn { public: //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name @@ -60,7 +60,7 @@ namespace VMAP static bool writeToFile(FILE* rw, const ModelSpawn &spawn); }; - class ModelInstance: public ModelSpawn + class TC_COMMON_API ModelInstance: public ModelSpawn { public: ModelInstance(): iInvScale(0.0f), iModel(nullptr) { } diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h index 39787f6c664..bfc0367627f 100644 --- a/src/common/Collision/Models/WorldModel.h +++ b/src/common/Collision/Models/WorldModel.h @@ -33,7 +33,7 @@ namespace VMAP struct AreaInfo; struct LocationInfo; - class MeshTriangle + class TC_COMMON_API MeshTriangle { public: MeshTriangle() : idx0(0), idx1(0), idx2(0) { } @@ -44,7 +44,7 @@ namespace VMAP uint32 idx2; }; - class WmoLiquid + class TC_COMMON_API WmoLiquid { public: WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type); @@ -70,7 +70,7 @@ namespace VMAP }; /*! holding additional info for WMO group files */ - class GroupModel + class TC_COMMON_API GroupModel { public: GroupModel() : iBound(), iMogpFlags(0), iGroupWMOID(0), iLiquid(NULL) { } @@ -103,7 +103,7 @@ namespace VMAP }; /*! Holds a model (converted M2 or WMO) in its original coordinate space */ - class WorldModel + class TC_COMMON_API WorldModel { public: WorldModel(): RootWMOID(0) { } diff --git a/src/common/Collision/RegularGrid.h b/src/common/Collision/RegularGrid.h index a582f3c081c..2f3819c872c 100644 --- a/src/common/Collision/RegularGrid.h +++ b/src/common/Collision/RegularGrid.h @@ -20,7 +20,7 @@ class NodeCreatorFunc = NodeCreator<Node>, /*class BoundsFunc = BoundsTrait<T>,*/ class PositionFunc = PositionTrait<T> > -class RegularGrid2D +class TC_COMMON_API RegularGrid2D { public: diff --git a/src/common/Collision/VMapTools.h b/src/common/Collision/VMapTools.h index 54b8fcd0032..86ec498f72a 100644 --- a/src/common/Collision/VMapTools.h +++ b/src/common/Collision/VMapTools.h @@ -22,6 +22,8 @@ #include <G3D/CollisionDetection.h> #include <G3D/AABox.h> +#include "Define.h" + #include "NodeValueAccess.h" /** @@ -48,7 +50,7 @@ namespace VMAP //============================================================== //============================================================== - class MyCollisionDetection + class TC_COMMON_API MyCollisionDetection { private: public: diff --git a/src/common/Common.cpp b/src/common/Common.cpp index 4555f00a76c..eb4316edd69 100644 --- a/src/common/Common.cpp +++ b/src/common/Common.cpp @@ -18,7 +18,7 @@ #include "Common.h" -char const* localeNames[TOTAL_LOCALES] = +TC_COMMON_API char const* localeNames[TOTAL_LOCALES] = { "enUS", "koKR", diff --git a/src/common/Common.h b/src/common/Common.h index ad48358ca8d..a6e2a8635cf 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -135,15 +135,15 @@ const uint8 OLD_TOTAL_LOCALES = 9; /// @todo convert in simple system #define MAX_LOCALES 11 -extern char const* localeNames[TOTAL_LOCALES]; +extern "C" TC_COMMON_API char const* localeNames[TOTAL_LOCALES]; -LocaleConstant GetLocaleByName(const std::string& name); +TC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name); typedef std::vector<std::string> StringVector; #pragma pack(push, 1) -struct LocalizedString +struct TC_COMMON_API LocalizedString { char const* Str[TOTAL_LOCALES]; }; diff --git a/src/common/Configuration/BuiltInConfig.h b/src/common/Configuration/BuiltInConfig.h index 4ae4ed40189..0ffa059bc41 100644 --- a/src/common/Configuration/BuiltInConfig.h +++ b/src/common/Configuration/BuiltInConfig.h @@ -19,6 +19,7 @@ #define BUILT_IN_CONFIG_H #include <string> +#include "Define.h" /// Provides helper functions to access built-in values /// which can be overwritten in config @@ -26,16 +27,16 @@ namespace BuiltInConfig { /// Returns the CMake command when any is specified in the config, /// returns the built-in path otherwise - std::string GetCMakeCommand(); + TC_COMMON_API std::string GetCMakeCommand(); /// Returns the build directory path when any is specified in the config, /// returns the built-in one otherwise - std::string GetBuildDirectory(); + TC_COMMON_API std::string GetBuildDirectory(); /// Returns the source directory path when any is specified in the config, /// returns the built-in one otherwise - std::string GetSourceDirectory(); + TC_COMMON_API 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(); + TC_COMMON_API std::string GetMySQLExecutable(); } // namespace BuiltInConfig diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index 196c128532e..bc21bb47b48 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -57,6 +57,12 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::string& error) return true; } +ConfigMgr* ConfigMgr::instance() +{ + static ConfigMgr instance; + return &instance; +} + bool ConfigMgr::Reload(std::string& error) { return LoadInitial(_filename, error); diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 77150e9b436..d8dfeb230a7 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -19,12 +19,14 @@ #ifndef CONFIG_H #define CONFIG_H +#include "Define.h" + #include <string> #include <list> #include <mutex> #include <boost/property_tree/ptree.hpp> -class ConfigMgr +class TC_COMMON_API ConfigMgr { ConfigMgr() { } ~ConfigMgr() { } @@ -33,11 +35,7 @@ public: /// Method used only for loading main configuration files bool LoadInitial(std::string const& file, std::string& error); - static ConfigMgr* instance() - { - static ConfigMgr instance; - return &instance; - } + static ConfigMgr* instance(); bool Reload(std::string& error); diff --git a/src/common/Cryptography/ARC4.h b/src/common/Cryptography/ARC4.h index 5b5fbf4a020..df412944ef6 100644 --- a/src/common/Cryptography/ARC4.h +++ b/src/common/Cryptography/ARC4.h @@ -22,7 +22,7 @@ #include <openssl/evp.h> #include "Define.h" -class ARC4 +class TC_COMMON_API ARC4 { public: ARC4(uint32 len); diff --git a/src/common/Cryptography/Authentication/PacketCrypt.h b/src/common/Cryptography/Authentication/PacketCrypt.h index 9e13cb02529..8af6c7ae926 100644 --- a/src/common/Cryptography/Authentication/PacketCrypt.h +++ b/src/common/Cryptography/Authentication/PacketCrypt.h @@ -22,7 +22,7 @@ class BigNumber; -class PacketCrypt +class TC_COMMON_API PacketCrypt { public: PacketCrypt(uint32 rc4InitSize); diff --git a/src/common/Cryptography/Authentication/WorldPacketCrypt.h b/src/common/Cryptography/Authentication/WorldPacketCrypt.h index 2b19fb54188..d296b049af2 100644 --- a/src/common/Cryptography/Authentication/WorldPacketCrypt.h +++ b/src/common/Cryptography/Authentication/WorldPacketCrypt.h @@ -23,7 +23,7 @@ class BigNumber; -class WorldPacketCrypt : public PacketCrypt +class TC_COMMON_API WorldPacketCrypt : public PacketCrypt { public: WorldPacketCrypt(); diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h index 56fc2196fde..baf338552d0 100644 --- a/src/common/Cryptography/BigNumber.h +++ b/src/common/Cryptography/BigNumber.h @@ -25,7 +25,7 @@ struct bignum_st; -class BigNumber +class TC_COMMON_API BigNumber { public: BigNumber(); diff --git a/src/common/Cryptography/HmacHash.cpp b/src/common/Cryptography/HmacHash.cpp index d9bb28d3e0b..bd50a2fc708 100644 --- a/src/common/Cryptography/HmacHash.cpp +++ b/src/common/Cryptography/HmacHash.cpp @@ -62,5 +62,5 @@ uint8* HmacHash<HashCreator, DigestLength>::ComputeHash(BigNumber* bn) return _digest; } -template class HmacHash<EVP_sha1, SHA_DIGEST_LENGTH>; -template class HmacHash<EVP_sha256, SHA256_DIGEST_LENGTH>; +template class TC_COMMON_API HmacHash<EVP_sha1, SHA_DIGEST_LENGTH>; +template class TC_COMMON_API HmacHash<EVP_sha256, SHA256_DIGEST_LENGTH>; diff --git a/src/common/Cryptography/HmacHash.h b/src/common/Cryptography/HmacHash.h index f61bf251abc..5156d03a18a 100644 --- a/src/common/Cryptography/HmacHash.h +++ b/src/common/Cryptography/HmacHash.h @@ -31,7 +31,7 @@ class BigNumber; typedef EVP_MD const* (*HashCreateFn)(); template<HashCreateFn HashCreator, uint32 DigestLength> -class HmacHash +class TC_COMMON_API HmacHash { public: HmacHash(uint32 len, uint8 const* seed); diff --git a/src/common/Cryptography/OpenSSLCrypto.h b/src/common/Cryptography/OpenSSLCrypto.h index df1b14b5eda..65155df9af8 100644 --- a/src/common/Cryptography/OpenSSLCrypto.h +++ b/src/common/Cryptography/OpenSSLCrypto.h @@ -18,6 +18,8 @@ #ifndef OPENSSL_CRYPTO_H #define OPENSSL_CRYPTO_H +#include "Define.h" + /** * A group of functions which setup openssl crypto module to work properly in multithreaded enviroment * If not setup properly - it will crash @@ -25,9 +27,9 @@ namespace OpenSSLCrypto { /// Needs to be called before threads using openssl are spawned - void threadsSetup(); + TC_COMMON_API void threadsSetup(); /// Needs to be called after threads using openssl are despawned - void threadsCleanup(); + TC_COMMON_API void threadsCleanup(); } -#endif
\ No newline at end of file +#endif diff --git a/src/common/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h index ffa02176a2d..f943e1d2de8 100644 --- a/src/common/Cryptography/SHA1.h +++ b/src/common/Cryptography/SHA1.h @@ -21,13 +21,16 @@ #include "Define.h" #include <string> +#include <type_traits> #include <openssl/sha.h> class BigNumber; -class SHA1Hash +class TC_COMMON_API SHA1Hash { public: + typedef std::integral_constant<uint32, SHA_DIGEST_LENGTH> DigestLength; + SHA1Hash(); ~SHA1Hash(); diff --git a/src/common/Cryptography/SHA256.h b/src/common/Cryptography/SHA256.h index d31c24ed93b..22d8a9870cf 100644 --- a/src/common/Cryptography/SHA256.h +++ b/src/common/Cryptography/SHA256.h @@ -20,13 +20,16 @@ #include "Define.h" #include <string> +#include <type_traits> #include <openssl/sha.h> class BigNumber; -class SHA256Hash +class TC_COMMON_API SHA256Hash { public: + typedef std::integral_constant<uint32, SHA256_DIGEST_LENGTH> DigestLength; + SHA256Hash(); ~SHA256Hash(); diff --git a/src/common/Cryptography/WardenKeyGeneration.h b/src/common/Cryptography/SessionKeyGeneration.h index 18118ece649..0ec4479b765 100644 --- a/src/common/Cryptography/WardenKeyGeneration.h +++ b/src/common/Cryptography/SessionKeyGeneration.h @@ -16,17 +16,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "SHA1.h" +#ifndef SessionKeyGeneration_h__ +#define SessionKeyGeneration_h__ -#include <cstring> +#include "Common.h" -#ifndef _WARDEN_KEY_GENERATION_H -#define _WARDEN_KEY_GENERATION_H - -class SHA1Randx +template<class Hash> +class SessionKeyGenerator { public: - SHA1Randx(uint8* buff, uint32 size) + SessionKeyGenerator(uint8* buff, uint32 size) { uint32 halfSize = size / 2; @@ -34,15 +33,15 @@ public: sh.UpdateData(buff, halfSize); sh.Finalize(); - memcpy(o1, sh.GetDigest(), 20); + memcpy(o1, sh.GetDigest(), Hash::DigestLength::value); sh.Initialize(); sh.UpdateData(buff + halfSize, size - halfSize); sh.Finalize(); - memcpy(o2, sh.GetDigest(), 20); + memcpy(o2, sh.GetDigest(), Hash::DigestLength::value); - memset(o0, 0x00, 20); + memset(o0, 0x00, Hash::DigestLength::value); FillUp(); } @@ -51,7 +50,7 @@ public: { for (uint32 i = 0; i < sz; ++i) { - if (taken == 20) + if (taken == Hash::DigestLength::value) FillUp(); buf[i] = o0[taken]; @@ -63,19 +62,21 @@ private: void FillUp() { sh.Initialize(); - sh.UpdateData(o1, 20); - sh.UpdateData(o0, 20); - sh.UpdateData(o2, 20); + sh.UpdateData(o1, Hash::DigestLength::value); + sh.UpdateData(o0, Hash::DigestLength::value); + sh.UpdateData(o2, Hash::DigestLength::value); sh.Finalize(); - memcpy(o0, sh.GetDigest(), 20); + memcpy(o0, sh.GetDigest(), Hash::DigestLength::value); taken = 0; } - SHA1Hash sh; + Hash sh; uint32 taken; - uint8 o0[20], o1[20], o2[20]; + uint8 o0[Hash::DigestLength::value]; + uint8 o1[Hash::DigestLength::value]; + uint8 o2[Hash::DigestLength::value]; }; -#endif +#endif // SessionKeyGeneration_h__ diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h index 37d247ada82..e4b3563ca96 100644 --- a/src/common/Debugging/Errors.h +++ b/src/common/Debugging/Errors.h @@ -23,18 +23,18 @@ namespace Trinity { - DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; - DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) ATTR_NORETURN ATTR_PRINTF(5, 6); + DECLSPEC_NORETURN TC_COMMON_API void Assert(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; + DECLSPEC_NORETURN TC_COMMON_API void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) ATTR_NORETURN ATTR_PRINTF(5, 6); - DECLSPEC_NORETURN void Fatal(char const* file, int line, char const* function, char const* message, ...) ATTR_NORETURN ATTR_PRINTF(4, 5); + DECLSPEC_NORETURN TC_COMMON_API void Fatal(char const* file, int line, char const* function, char const* message, ...) ATTR_NORETURN ATTR_PRINTF(4, 5); - DECLSPEC_NORETURN void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; + DECLSPEC_NORETURN TC_COMMON_API void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; - DECLSPEC_NORETURN void Abort(char const* file, int line, char const* function) ATTR_NORETURN; + DECLSPEC_NORETURN TC_COMMON_API void Abort(char const* file, int line, char const* function) ATTR_NORETURN; - void Warning(char const* file, int line, char const* function, char const* message); + TC_COMMON_API void Warning(char const* file, int line, char const* function, char const* message); - DECLSPEC_NORETURN void AbortHandler(int sigval) ATTR_NORETURN; + DECLSPEC_NORETURN TC_COMMON_API void AbortHandler(int sigval) ATTR_NORETURN; } // namespace Trinity diff --git a/src/common/Define.h b/src/common/Define.h index 061a6bc2f5e..07b79252074 100644 --- a/src/common/Define.h +++ b/src/common/Define.h @@ -95,6 +95,45 @@ #endif #endif //COMPILER == COMPILER_GNU +#ifdef TRINITY_API_USE_DYNAMIC_LINKING +# if COMPILER == COMPILER_MICROSOFT +# define TC_API_EXPORT __declspec(dllexport) +# define TC_API_IMPORT __declspec(dllimport) +# elif COMPILER == COMPILER_GNU +# define TC_API_EXPORT __attribute__((visibility("default"))) +# define TC_API_IMPORT +# else +# error compiler not supported! +# endif +#else +# define TC_API_EXPORT +# define TC_API_IMPORT +#endif + +#ifdef TRINITY_API_EXPORT_COMMON +# define TC_COMMON_API TC_API_EXPORT +#else +# define TC_COMMON_API TC_API_IMPORT +#endif + +#ifdef TRINITY_API_EXPORT_DATABASE +# define TC_DATABASE_API TC_API_EXPORT +#else +# define TC_DATABASE_API TC_API_IMPORT +#endif + +#ifdef TRINITY_API_EXPORT_SHARED +# define TC_SHARED_API TC_API_EXPORT +#else +# define TC_SHARED_API TC_API_IMPORT +#endif + +#ifdef TRINITY_API_EXPORT_GAME +# define TC_GAME_API TC_API_EXPORT +#else +# define TC_GAME_API TC_API_IMPORT +#endif + #define UI64FMTD "%" PRIu64 #define UI64LIT(N) UINT64_C(N) diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index 3dd6b543013..2b4537db448 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -1,5 +1,4 @@ #include "GitRevision.h" -#include "CompilerDefs.h" #include "revision_data.h" char const* GitRevision::GetHash() diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index c65c8fb6cff..ffe8884eb0a 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -19,23 +19,24 @@ #define __GITREVISION_H__ #include <string> +#include "Define.h" 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(); - char const* GetHotfixesDatabase(); - char const* GetFullVersion(); - char const* GetCompanyNameStr(); - char const* GetLegalCopyrightStr(); - char const* GetFileVersionStr(); - char const* GetProductVersionStr(); + TC_COMMON_API char const* GetHash(); + TC_COMMON_API char const* GetDate(); + TC_COMMON_API char const* GetBranch(); + TC_COMMON_API char const* GetCMakeCommand(); + TC_COMMON_API char const* GetBuildDirectory(); + TC_COMMON_API char const* GetSourceDirectory(); + TC_COMMON_API char const* GetMySQLExecutable(); + TC_COMMON_API char const* GetFullDatabase(); + TC_COMMON_API char const* GetHotfixesDatabase(); + TC_COMMON_API char const* GetFullVersion(); + TC_COMMON_API char const* GetCompanyNameStr(); + TC_COMMON_API char const* GetLegalCopyrightStr(); + TC_COMMON_API char const* GetFileVersionStr(); + TC_COMMON_API char const* GetProductVersionStr(); } #endif diff --git a/src/common/Logging/Appender.h b/src/common/Logging/Appender.h index f0bfe423a66..22fe1112239 100644 --- a/src/common/Logging/Appender.h +++ b/src/common/Logging/Appender.h @@ -59,7 +59,7 @@ enum AppenderFlags APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10 // only used by FileAppender }; -struct LogMessage +struct TC_COMMON_API LogMessage { LogMessage(LogLevel _level, std::string const& _type, std::string&& _text) : level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(NULL)) @@ -85,7 +85,7 @@ struct LogMessage } }; -class Appender +class TC_COMMON_API Appender { public: Appender(uint8 _id, std::string const& name, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE); @@ -123,7 +123,7 @@ Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, Appe return new AppenderImpl(id, name, level, flags, std::forward<ExtraAppenderArgs>(extraArgs)); } -class InvalidAppenderArgsException : public std::length_error +class TC_COMMON_API InvalidAppenderArgsException : public std::length_error { public: explicit InvalidAppenderArgsException(std::string const& message) : std::length_error(message) { } diff --git a/src/common/Logging/AppenderConsole.h b/src/common/Logging/AppenderConsole.h index 5d7eae36b40..96d17207158 100644 --- a/src/common/Logging/AppenderConsole.h +++ b/src/common/Logging/AppenderConsole.h @@ -42,7 +42,7 @@ enum ColorTypes const uint8 MaxColors = uint8(WHITE) + 1; -class AppenderConsole : public Appender +class TC_COMMON_API AppenderConsole : public Appender { public: typedef std::integral_constant<AppenderType, APPENDER_CONSOLE>::type TypeIndex; diff --git a/src/common/Logging/AppenderFile.h b/src/common/Logging/AppenderFile.h index 9ba5d59259c..956b7a70b93 100644 --- a/src/common/Logging/AppenderFile.h +++ b/src/common/Logging/AppenderFile.h @@ -21,7 +21,7 @@ #include <atomic> #include "Appender.h" -class AppenderFile : public Appender +class TC_COMMON_API AppenderFile : public Appender { public: typedef std::integral_constant<AppenderType, APPENDER_FILE>::type TypeIndex; diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index dff0351d52d..b350a41b482 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -321,6 +321,12 @@ void Log::Close() appenders.clear(); } +Log* Log::instance() +{ + static Log instance; + return &instance; +} + void Log::Initialize(boost::asio::io_service* ioService) { if (ioService) diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index eafd7412a94..6460e404c90 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -34,7 +34,7 @@ #define LOGGER_ROOT "root" -class Log +class TC_COMMON_API Log { typedef std::unordered_map<std::string, Logger> LoggerMap; @@ -44,11 +44,7 @@ class Log public: - static Log* instance() - { - static Log instance; - return &instance; - } + static Log* instance(); void Initialize(boost::asio::io_service* ioService); void SetSynchronous(); // Not threadsafe - should only be called from main() after all threads are joined diff --git a/src/common/Logging/LogOperation.h b/src/common/Logging/LogOperation.h index 618629b5423..56e2307d492 100644 --- a/src/common/Logging/LogOperation.h +++ b/src/common/Logging/LogOperation.h @@ -19,11 +19,12 @@ #define LOGOPERATION_H #include <memory> +#include "Define.h" class Logger; struct LogMessage; -class LogOperation +class TC_COMMON_API LogOperation { public: LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) diff --git a/src/common/Logging/Logger.h b/src/common/Logging/Logger.h index 67eab4295a4..4ac2e4494cc 100644 --- a/src/common/Logging/Logger.h +++ b/src/common/Logging/Logger.h @@ -20,7 +20,7 @@ #include "Appender.h" -class Logger +class TC_COMMON_API Logger { public: Logger(); diff --git a/src/server/shared/Service/ServiceWin32.cpp b/src/common/Platform/ServiceWin32.cpp index b6a1682993b..3c34f3e322c 100644 --- a/src/server/shared/Service/ServiceWin32.cpp +++ b/src/common/Platform/ServiceWin32.cpp @@ -261,4 +261,3 @@ bool WinServiceRun() return true; } #endif - diff --git a/src/server/shared/Service/ServiceWin32.h b/src/common/Platform/ServiceWin32.h index 3d67bfe5445..b892ba4e3b6 100644 --- a/src/server/shared/Service/ServiceWin32.h +++ b/src/common/Platform/ServiceWin32.h @@ -26,4 +26,3 @@ bool WinServiceRun(); #endif // _WIN32_SERVICE_ #endif // _WIN32 - diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index 9818712c0cb..e8a40ede4c7 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -20,6 +20,7 @@ #include "Define.h" #include "Random.h" +#include "Util.h" #include <algorithm> #include <functional> #include <list> diff --git a/src/common/Utilities/EventMap.h b/src/common/Utilities/EventMap.h index a1aaa9af269..bb40980181d 100644 --- a/src/common/Utilities/EventMap.h +++ b/src/common/Utilities/EventMap.h @@ -22,7 +22,7 @@ #include "Duration.h" #include "Util.h" -class EventMap +class TC_COMMON_API EventMap { /** * Internal storage type. diff --git a/src/common/Utilities/EventProcessor.h b/src/common/Utilities/EventProcessor.h index e5eafed79b9..e10558e6a21 100644 --- a/src/common/Utilities/EventProcessor.h +++ b/src/common/Utilities/EventProcessor.h @@ -25,7 +25,7 @@ // Note. All times are in milliseconds here. -class BasicEvent +class TC_COMMON_API BasicEvent { public: BasicEvent() @@ -55,7 +55,7 @@ class BasicEvent typedef std::multimap<uint64, BasicEvent*> EventList; -class EventProcessor +class TC_COMMON_API EventProcessor { public: EventProcessor(); diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h index dee0bfbfcf0..da3df620af8 100644 --- a/src/common/Utilities/Random.h +++ b/src/common/Utilities/Random.h @@ -23,25 +23,25 @@ #include <random> /* Return a random number in the range min..max. */ -int32 irand(int32 min, int32 max); +TC_COMMON_API int32 irand(int32 min, int32 max); /* Return a random number in the range min..max (inclusive). */ -uint32 urand(uint32 min, uint32 max); +TC_COMMON_API uint32 urand(uint32 min, uint32 max); /* Return a random millisecond value between min and max seconds. Functionally equivalent to urand(min*IN_MILLISECONDS, max*IN_MILLISECONDS). */ -uint32 urandms(uint32 min, uint32 max); +TC_COMMON_API uint32 urandms(uint32 min, uint32 max); /* Return a random number in the range 0 .. UINT32_MAX. */ -uint32 rand32(); +TC_COMMON_API uint32 rand32(); /* Return a random number in the range min..max */ -float frand(float min, float max); +TC_COMMON_API float frand(float min, float max); /* Return a random double from 0.0 to 1.0 (exclusive). */ -double rand_norm(); +TC_COMMON_API double rand_norm(); /* Return a random double from 0.0 to 100.0 (exclusive). */ -double rand_chance(); +TC_COMMON_API double rand_chance(); /* Return true if a random roll fits in the specified chance (range 0-100). */ inline bool roll_chance_f(float chance) @@ -58,7 +58,7 @@ inline bool roll_chance_i(int chance) /* * SFMT wrapper satisfying UniformRandomNumberGenerator concept for use in <random> algorithms */ -class SFMTEngine +class TC_COMMON_API SFMTEngine { public: typedef uint32 result_type; diff --git a/src/common/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h index d85523bc11f..e21b1024e87 100644 --- a/src/common/Utilities/StringFormat.h +++ b/src/common/Utilities/StringFormat.h @@ -19,7 +19,7 @@ #ifndef TRINITYCORE_STRING_FORMAT_H #define TRINITYCORE_STRING_FORMAT_H -#include "format.h" +#include "cppformat/format.h" namespace Trinity { diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h index 8cf5d914128..c5163ef33d5 100644 --- a/src/common/Utilities/TaskScheduler.h +++ b/src/common/Utilities/TaskScheduler.h @@ -46,7 +46,7 @@ class TaskContext; /// with the same duration or a new one. /// It also provides access to the repeat counter which is useful for task that repeat itself often /// but behave different every time (spoken event dialogs for example). -class TaskScheduler +class TC_COMMON_API TaskScheduler { friend class TaskContext; @@ -131,7 +131,7 @@ class TaskScheduler }; }; - class TaskQueue + class TC_COMMON_API TaskQueue { std::multiset<TaskContainer, Compare> container; @@ -408,7 +408,7 @@ private: void Dispatch(success_t const& callback); }; -class TaskContext +class TC_COMMON_API TaskContext { friend class TaskScheduler; diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 5e36bfeb3b7..25bd935de92 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -219,22 +219,29 @@ bool IsIPAddress(char const* ipaddress) } /// create PID file -uint32 CreatePIDFile(const std::string& filename) +uint32 CreatePIDFile(std::string const& filename) { - FILE* pid_file = fopen (filename.c_str(), "w" ); + FILE* pid_file = fopen(filename.c_str(), "w"); if (pid_file == NULL) return 0; + uint32 pid = GetPID(); + + fprintf(pid_file, "%u", pid); + fclose(pid_file); + + return pid; +} + +uint32 GetPID() +{ #ifdef _WIN32 DWORD pid = GetCurrentProcessId(); #else pid_t pid = getpid(); #endif - fprintf(pid_file, "%u", pid ); - fclose(pid_file); - - return (uint32)pid; + return uint32(pid); } size_t utf8length(std::string& utf8str) diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 486c86f9182..ffc35a6894b 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -41,7 +41,7 @@ template<typename T, class S> struct Finder bool operator()(const std::pair<int, S> &obj) { return obj.second.*idMember_ == val_; } }; -class Tokenizer +class TC_COMMON_API Tokenizer { public: typedef std::vector<char const*> StorageType; @@ -69,15 +69,15 @@ private: StorageType m_storage; }; -void stripLineInvisibleChars(std::string &src); +TC_COMMON_API void stripLineInvisibleChars(std::string &src); -int64 MoneyStringToMoney(const std::string& moneyString); +TC_COMMON_API int64 MoneyStringToMoney(const std::string& moneyString); -struct tm* localtime_r(const time_t* time, struct tm *result); +TC_COMMON_API struct tm* localtime_r(const time_t* time, struct tm *result); -std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false); -uint32 TimeStringToSecs(const std::string& timestring); -std::string TimeToTimestampStr(time_t t); +TC_COMMON_API std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false); +TC_COMMON_API uint32 TimeStringToSecs(const std::string& timestring); +TC_COMMON_API std::string TimeToTimestampStr(time_t t); inline void ApplyPercentModFloatVar(float& var, float val, bool apply) { @@ -112,20 +112,23 @@ inline T RoundToInterval(T& num, T floor, T ceil) } // UTF8 handling -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); +TC_COMMON_API bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); + // in wsize==max size of buffer, out wsize==real string size -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); +TC_COMMON_API bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); + inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) { return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); } -bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str); +TC_COMMON_API bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str); // size==real string size -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); +TC_COMMON_API bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); -size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence -void utf8truncate(std::string& utf8str, size_t len); +// set string to "" if invalid utf8 sequence +TC_COMMON_API size_t utf8length(std::string& utf8str); +TC_COMMON_API void utf8truncate(std::string& utf8str, size_t len); inline bool isBasicLatinCharacter(wchar_t wchar) { @@ -304,23 +307,24 @@ inline void wstrToLower(std::wstring& str) std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); } -std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension); +TC_COMMON_API std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension); -bool utf8ToConsole(const std::string& utf8str, std::string& conStr); -bool consoleToUtf8(const std::string& conStr, std::string& utf8str); -bool Utf8FitTo(const std::string& str, std::wstring const& search); -void utf8printf(FILE* out, const char *str, ...); -void vutf8printf(FILE* out, const char *str, va_list* ap); -bool Utf8ToUpperOnlyLatin(std::string& utf8String); +TC_COMMON_API bool utf8ToConsole(const std::string& utf8str, std::string& conStr); +TC_COMMON_API bool consoleToUtf8(const std::string& conStr, std::string& utf8str); +TC_COMMON_API bool Utf8FitTo(const std::string& str, std::wstring const& search); +TC_COMMON_API void utf8printf(FILE* out, const char *str, ...); +TC_COMMON_API void vutf8printf(FILE* out, const char *str, va_list* ap); +TC_COMMON_API bool Utf8ToUpperOnlyLatin(std::string& utf8String); -bool IsIPAddress(char const* ipaddress); +TC_COMMON_API bool IsIPAddress(char const* ipaddress); -uint32 CreatePIDFile(const std::string& filename); +TC_COMMON_API uint32 CreatePIDFile(std::string const& filename); +TC_COMMON_API uint32 GetPID(); -std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); -void HexStrToByteArray(std::string const& str, uint8* out, bool reverse = false); +TC_COMMON_API std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); +TC_COMMON_API void HexStrToByteArray(std::string const& str, uint8* out, bool reverse = false); -bool StringToBool(std::string const& str); +TC_COMMON_API bool StringToBool(std::string const& str); // simple class for not-modifyable list template <typename T> @@ -354,7 +358,7 @@ class HookList } }; -class flag128 +class TC_COMMON_API flag128 { private: uint32 part[4]; diff --git a/src/genrev/CMakeLists.txt b/src/genrev/CMakeLists.txt index 91a13609037..355e2043b51 100644 --- a/src/genrev/CMakeLists.txt +++ b/src/genrev/CMakeLists.txt @@ -13,3 +13,8 @@ add_custom_target(revision_data.h ALL COMMAND "${CMAKE_COMMAND}" -DBUILDDIR="${CMAKE_BINARY_DIR}" -P "${CMAKE_SOURCE_DIR}/cmake/genrev.cmake" "${CMAKE_BINARY_DIR}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ) + +set_target_properties(revision_data.h + PROPERTIES + FOLDER + "server") diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index d10425db8f6..f4a7246d9b0 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -16,15 +16,18 @@ if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) add_definitions(-fno-delete-null-pointer-checks) endif() +if(WIN32) + set(sources_windows + ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.cpp + ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.h + ${CMAKE_SOURCE_DIR}/src/common/Platform/ServiceWin32.cpp + ${CMAKE_SOURCE_DIR}/src/common/Platform/ServiceWin32.h + ) +endif(WIN32) -set(sources_windows_Debugging - ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.cpp - ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.h -) add_subdirectory(database) add_subdirectory(shared) -add_subdirectory(game) -add_subdirectory(ipc) add_subdirectory(bnetserver) +add_subdirectory(game) add_subdirectory(scripts) add_subdirectory(worldserver) diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt index 6d19b9ca95e..7aa861499d9 100644 --- a/src/server/bnetserver/CMakeLists.txt +++ b/src/server/bnetserver/CMakeLists.txt @@ -10,74 +10,29 @@ ########### bnetserver ############### -file(GLOB_RECURSE sources_authentication Authentication/*.cpp Authentication/*.h) -file(GLOB_RECURSE sources_realms Realms/*.cpp Realms/*.h) -file(GLOB_RECURSE sources_server Server/*.cpp Server/*.h) -file(GLOB_RECURSE sources_packets Packets/*.cpp Packets/*.h) -file(GLOB sources_localdir *.cpp *.h) - -if (USE_COREPCH) - set(bnetserver_PCH_HDR PrecompiledHeaders/bnetPCH.h) - set(bnetserver_PCH_SRC PrecompiledHeaders/bnetPCH.cpp) -endif() - -set(bnetserver_SRCS - ${bnetserver_SRCS} - ${sources_authentication} - ${sources_realms} - ${sources_server} - ${sources_packets} - ${sources_localdir} -) +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) if( WIN32 ) - set(bnetserver_SRCS - ${bnetserver_SRCS} - ${sources_windows_Debugging} - ) + list(APPEND PRIVATE_SOURCES ${sources_windows}) if ( MSVC ) - set(bnetserver_SRCS - ${bnetserver_SRCS} - bnetserver.rc - ) - endif () + list(APPEND PRIVATE_SOURCES bnetserver.rc) + endif() endif() -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Authentication - ${CMAKE_CURRENT_SOURCE_DIR}/Packets - ${CMAKE_CURRENT_SOURCE_DIR}/Realms - ${CMAKE_CURRENT_SOURCE_DIR}/Server - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/common/Configuration - ${CMAKE_SOURCE_DIR}/src/common/Cryptography - ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${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/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/Service - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} - ${ZMQ_INCLUDE_DIR} -) +if (USE_COREPCH) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/bnetPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/bnetPCH.cpp) +endif() GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(bnetserver - ${bnetserver_SRCS} - ${bnetserver_PCH_SRC} + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) if( NOT WIN32 ) @@ -87,18 +42,25 @@ if( NOT WIN32 ) endif() target_link_libraries(bnetserver - shared - database - ipc - common - zmqpp - format - ${MYSQL_LIBRARY} - ${OPENSSL_LIBRARIES} - ${ZMQ_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - ${Boost_LIBRARIES} -) + PUBLIC + shared) + +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) + +target_include_directories(bnetserver + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +set_target_properties(bnetserver + PROPERTIES + FOLDER + "server") if( WIN32 ) if ( MSVC ) @@ -124,5 +86,5 @@ endif() # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(bnetserver ${bnetserver_PCH_HDR} ${bnetserver_PCH_SRC}) + add_cxx_pch(bnetserver ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif() diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index c367a1f7d40..65b8d6e772b 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -36,7 +36,6 @@ #include "RealmList.h" #include "GitRevision.h" #include "Util.h" -#include "ZmqContext.h" #include "DatabaseLoader.h" #include <cstdlib> #include <iostream> @@ -81,7 +80,6 @@ static boost::asio::deadline_timer* _dbPingTimer; static uint32 _dbPingInterval; static boost::asio::deadline_timer* _banExpiryCheckTimer; static uint32 _banExpiryCheckInterval; -LoginDatabaseWorkerPool LoginDatabase; int main(int argc, char** argv) { @@ -137,23 +135,14 @@ int main(int argc, char** argv) } } - int32 worldListenPort = sConfigMgr->GetIntDefault("WorldserverListenPort", 1118); - if (worldListenPort < 0 || worldListenPort > 0xFFFF) - { - TC_LOG_ERROR("server.bnetserver", "Specified worldserver listen port (%d) out of allowed range (1-65535)", worldListenPort); - return 1; - } - // Initialize the database connection if (!StartDB()) return 1; - sIpcContext->Initialize(); - _ioService = new boost::asio::io_service(); // Get the list of realms for the server - sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10), worldListenPort); + sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); // Start the listening port (acceptor) for auth connections int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); @@ -210,8 +199,6 @@ int main(int argc, char** argv) sSessionMgr.StopNetwork(); - sIpcContext->Close(); - sRealmList->Close(); // Close the Database Pool and library diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp index d3f40a8cc97..056ddef39d4 100644 --- a/src/server/bnetserver/Realms/RealmList.cpp +++ b/src/server/bnetserver/Realms/RealmList.cpp @@ -20,23 +20,20 @@ #include "Database/DatabaseEnv.h" #include "SessionManager.h" #include "Util.h" -#include "Commands.h" #include "RealmList.h" #include <boost/asio/ip/tcp.hpp> -RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr), _worldListener(nullptr) +RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) { } RealmList::~RealmList() { delete _updateTimer; - delete _resolver; - delete _worldListener; } // Load the realm list from the database -void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval, uint16 worldListenPort) +void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) { _updateInterval = updateInterval; _updateTimer = new boost::asio::deadline_timer(ioService); @@ -44,14 +41,10 @@ void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInte // Get the content of the realmlist table in the database UpdateRealms(boost::system::error_code()); - - _worldListener = new WorldListener(worldListenPort); - _worldListener->Start(); } void RealmList::Close() { - _worldListener->End(); _updateTimer->cancel(); } diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h index 388d4d5e1aa..fe3c9185ccf 100644 --- a/src/server/bnetserver/Realms/RealmList.h +++ b/src/server/bnetserver/Realms/RealmList.h @@ -21,7 +21,6 @@ #include "Common.h" #include "Realm/Realm.h" -#include "WorldListener.h" #include <boost/asio/ip/address.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/io_service.hpp> @@ -43,7 +42,7 @@ public: ~RealmList(); - void Initialize(boost::asio::io_service& ioService, uint32 updateInterval, uint16 worldListenPort); + void Initialize(boost::asio::io_service& ioService, uint32 updateInterval); void Close(); RealmMap const& GetRealms() const { return _realms; } @@ -60,7 +59,6 @@ private: uint32 _updateInterval; boost::asio::deadline_timer* _updateTimer; boost::asio::ip::tcp::resolver* _resolver; - WorldListener* _worldListener; }; #define sRealmList RealmList::instance() diff --git a/src/server/bnetserver/Realms/WorldListener.cpp b/src/server/bnetserver/Realms/WorldListener.cpp deleted file mode 100644 index 2dd9bcdfa2f..00000000000 --- a/src/server/bnetserver/Realms/WorldListener.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "Log.h" -#include "SessionManager.h" -#include "WoWRealmPackets.h" -#include "ZmqContext.h" -#include "WorldListener.h" - -WorldListener::HandlerTable const WorldListener::_handlers; - -WorldListener::HandlerTable::HandlerTable() -{ -#define DEFINE_HANDLER(opc, func) _handlers[opc] = { func, #opc } - - DEFINE_HANDLER(BNET_CHANGE_TOON_ONLINE_STATE, &WorldListener::HandleToonOnlineStatusChange); - -#undef DEFINE_HANDLER -} - -WorldListener::WorldListener(uint16 worldListenPort) : _worldListenPort(worldListenPort) -{ - _worldSocket = sIpcContext->CreateNewSocket(zmqpp::socket_type::pull); -} - -WorldListener::~WorldListener() -{ - delete _worldSocket; -} - -void WorldListener::Run() -{ - while (!ProcessExit()) - { - _poller->poll(); - if (_poller->events(*_worldSocket) & zmqpp::poller::poll_in) - { - int32 op1; - do - { - zmqpp::message msg; - _worldSocket->receive(msg); - Dispatch(msg); - _worldSocket->get(zmqpp::socket_option::events, op1); - } while (op1 & zmqpp::poller::poll_in); - } - } -} - -void WorldListener::HandleOpen() -{ - try - { - _worldSocket->bind(std::string("tcp://*:") + std::to_string(_worldListenPort)); - } - catch (zmqpp::zmq_internal_exception& ex) - { - TC_LOG_FATAL("server.ipc", "Could not bind to WorldserverListenPort %u. Exception: %s. Shutting down bnetserver.", _worldListenPort, ex.what()); - abort(); - } - - _poller->add(*_worldSocket); - TC_LOG_INFO("server.ipc", "Listening on connections from worldservers on port %u...", _worldListenPort); -} - -void WorldListener::HandleClose() -{ - _worldSocket->close(); - TC_LOG_INFO("server.ipc", "Shutting down connections from worldservers..."); -} - -void WorldListener::Dispatch(zmqpp::message& msg) const -{ - IPC::BattlenetComm::Header ipcHeader; - msg >> ipcHeader; - - if (ipcHeader.Ipc.Channel != IPC_CHANNEL_BNET) - return; - - if (ipcHeader.Ipc.Command < IPC_BNET_MAX_COMMAND) - (this->*_handlers[ipcHeader.Ipc.Command].Handler)(ipcHeader.Realm, msg); -} - -void WorldListener::HandleToonOnlineStatusChange(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const -{ - IPC::BattlenetComm::ToonHandle toonHandle; - bool online; - msg >> toonHandle; - msg >> online; - - if (Battlenet::Session* session = sSessionMgr.GetSession(toonHandle.AccountId, toonHandle.GameAccountId)) - { - if (online) - { - if (!session->IsToonOnline()) - { - Battlenet::WoWRealm::ToonReady* toonReady = new Battlenet::WoWRealm::ToonReady(); - toonReady->Name.Region = realm.Region; - toonReady->Name.ProgramId = "WoW"; - toonReady->Name.Realm = realm.GetAddress(); - toonReady->Name.Name = toonHandle.Name; - - toonReady->Handle.Region = realm.Region; - toonReady->Handle.ProgramId = "WoW"; - toonReady->Handle.Realm = realm.GetAddress(); - toonReady->Handle.Id = toonHandle.Guid; - - session->SetToonOnline(true); - session->AsyncWrite(toonReady); - } - } - else if (session->IsToonOnline()) - { - session->AsyncWrite(new Battlenet::WoWRealm::ToonLoggedOut()); - session->SetToonOnline(false); - } - } -} diff --git a/src/server/bnetserver/Realms/WorldListener.h b/src/server/bnetserver/Realms/WorldListener.h deleted file mode 100644 index e5b1ff41201..00000000000 --- a/src/server/bnetserver/Realms/WorldListener.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef WorldListener_h__ -#define WorldListener_h__ - -#include "ZMQTask.h" -#include "Commands.h" - -class WorldListener : public ZMQTask -{ -public: - explicit WorldListener(uint16 worldListenPort); - ~WorldListener(); - void Run() override; - -protected: - void HandleOpen() override; - void HandleClose() override; - -private: - void Dispatch(zmqpp::message& msg) const; - - typedef void(WorldListener::*PacketHandler)(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const; - class HandlerTable - { - public: - HandlerTable(); - - struct HandlerInfo - { - PacketHandler Handler; - char const* Name; - }; - - HandlerInfo const& operator[](uint8 opcode) const { return _handlers[opcode]; } - - private: - HandlerInfo _handlers[IPC_BNET_MAX_COMMAND]; - }; - - void HandleToonOnlineStatusChange(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const; - - zmqpp::socket* _worldSocket; - uint16 _worldListenPort; - static HandlerTable const _handlers; -}; - -#endif // WorldListener_h__ diff --git a/src/server/bnetserver/bnetserver.conf.dist b/src/server/bnetserver/bnetserver.conf.dist index cf5d27699d8..252a29440b5 100644 --- a/src/server/bnetserver/bnetserver.conf.dist +++ b/src/server/bnetserver/bnetserver.conf.dist @@ -48,13 +48,6 @@ LogsDir = "" MaxPingTime = 30 # -# WorldserverListenPort -# Description: TCP port to listen on for incoming worldserver IPC. -# Default: 1118 - -WorldserverListenPort = 1118 - -# # BattlenetPort # Description: TCP port to reach the auth server for battle.net connections. # Default: 1119 diff --git a/src/server/database/CMakeLists.txt b/src/server/database/CMakeLists.txt index 5a53899f4cb..06772cd5309 100644 --- a/src/server/database/CMakeLists.txt +++ b/src/server/database/CMakeLists.txt @@ -8,34 +8,22 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -if (NOT MYSQL_FOUND) - message(SEND_ERROR "MySQL wasn't found on your system but it's required to build the servers!") -endif() - -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Database Database/*.cpp Database/*.h) -file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) -file(GLOB_RECURSE sources_Updater Updater/*.cpp Updater/*.h) - -file(GLOB sources_localdir *.cpp *.h) - -# -# Build shared sourcelist -# +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) if (USE_COREPCH) - set(database_STAT_PCH_HDR PrecompiledHeaders/databasePCH.h) - set(database_STAT_PCH_SRC PrecompiledHeaders/databasePCH.cpp) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/databasePCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/databasePCH.cpp) endif() -set(database_STAT_SRCS - ${database_STAT_SRCS} - ${sources_Database} - ${sources_Logging} - ${sources_Updater} +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(database + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) # Do NOT add any extra include directory unless it does not create unneeded extra dependencies, @@ -47,31 +35,44 @@ set(database_STAT_SRCS # linkage (enums, defines...) it is discouraged to do so unless necessary, as it will pullute # include_directories leading to further unnoticed dependency aditions # Linker Depencency requirements: common -include_directories( +CollectIncludeDirectories( ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Database - ${CMAKE_CURRENT_SOURCE_DIR}/Updater - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/process - ${CMAKE_SOURCE_DIR}/src/common/ - ${CMAKE_SOURCE_DIR}/src/common/Configuration - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(database + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_library(database STATIC - ${database_STAT_SRCS} - ${database_STAT_PCH_SRC} -) +add_definitions(-DTRINITY_API_EXPORT_DATABASE) + +target_link_libraries(database + PUBLIC + common + process + mysql) + +set_target_properties(database + PROPERTIES + FOLDER + "server") + +if( BUILD_SHARED_LIBS ) + if( UNIX ) + install(TARGETS database + LIBRARY + DESTINATION lib) + elseif( WIN32 ) + install(TARGETS database + RUNTIME + DESTINATION "${CMAKE_INSTALL_PREFIX}") + endif() +endif() # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(database ${database_STAT_PCH_HDR} ${database_STAT_PCH_SRC}) + add_cxx_pch(database ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif () diff --git a/src/server/database/Database/AdhocStatement.h b/src/server/database/Database/AdhocStatement.h index ab85493a14e..9315038bce1 100644 --- a/src/server/database/Database/AdhocStatement.h +++ b/src/server/database/Database/AdhocStatement.h @@ -25,7 +25,7 @@ typedef std::future<QueryResult> QueryResultFuture; typedef std::promise<QueryResult> QueryResultPromise; /*! Raw, ad-hoc query. */ -class BasicStatementTask : public SQLOperation +class TC_DATABASE_API BasicStatementTask : public SQLOperation { public: BasicStatementTask(const char* sql, bool async = false); diff --git a/src/server/ipc/ZmqWorker.h b/src/server/database/Database/DatabaseEnv.cpp index 21d2d95ac18..693158b7c9e 100644 --- a/src/server/ipc/ZmqWorker.h +++ b/src/server/database/Database/DatabaseEnv.cpp @@ -15,30 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __ZMQWORKER_H -#define __ZMQWORKER_H +#include "DatabaseEnv.h" -#include "ZMQTask.h" -#include <zmqpp/zmqpp.hpp> - -class ZmqWorker : public ZMQTask -{ -public: - ZmqWorker(std::string const& taskUri, std::string const& resUri); - ~ZmqWorker(); - void Run() override; - -protected: - void HandleOpen() override; - void HandleClose() override; - zmqpp::socket* _results = nullptr; - -private: - void PerformWork(); - virtual void Dispatch(zmqpp::message const&) = 0; - zmqpp::socket* _taskQueue = nullptr; - std::string _taskUri; - std::string _resultsUri; -}; - -#endif +WorldDatabaseWorkerPool WorldDatabase; +CharacterDatabaseWorkerPool CharacterDatabase; +LoginDatabaseWorkerPool LoginDatabase; +HotfixDatabaseWorkerPool HotfixDatabase; diff --git a/src/server/database/Database/DatabaseEnv.h b/src/server/database/Database/DatabaseEnv.h index 27b2bce744b..3d1700bfeba 100644 --- a/src/server/database/Database/DatabaseEnv.h +++ b/src/server/database/Database/DatabaseEnv.h @@ -39,10 +39,13 @@ #include "Implementation/WorldDatabase.h" #include "Implementation/HotfixDatabase.h" -extern WorldDatabaseWorkerPool WorldDatabase; -extern CharacterDatabaseWorkerPool CharacterDatabase; -extern LoginDatabaseWorkerPool LoginDatabase; -extern HotfixDatabaseWorkerPool HotfixDatabase; +/// Accessor to the world database +TC_DATABASE_API extern WorldDatabaseWorkerPool WorldDatabase; +/// Accessor to the character database +TC_DATABASE_API extern CharacterDatabaseWorkerPool CharacterDatabase; +/// Accessor to the realm/login database +TC_DATABASE_API extern LoginDatabaseWorkerPool LoginDatabase; +/// Accessor to the hotfix database +TC_DATABASE_API extern HotfixDatabaseWorkerPool HotfixDatabase; #endif - diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp index 2cbf31dbef8..89428561524 100644 --- a/src/server/database/Database/DatabaseLoader.cpp +++ b/src/server/database/Database/DatabaseLoader.cpp @@ -177,11 +177,11 @@ bool DatabaseLoader::Process(std::queue<Predicate>& queue) return true; } -template -DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(DatabaseWorkerPool<LoginDatabaseConnection>& pool, std::string const& name); -template -DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>& pool, std::string const& name); -template -DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>& pool, std::string const& name); -template -DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(DatabaseWorkerPool<HotfixDatabaseConnection>& pool, std::string const& name); +template TC_DATABASE_API +DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(LoginDatabaseWorkerPool&, std::string const&); +template TC_DATABASE_API +DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(CharacterDatabaseWorkerPool&, std::string const&); +template TC_DATABASE_API +DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(HotfixDatabaseWorkerPool&, std::string const&); +template TC_DATABASE_API +DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(WorldDatabaseWorkerPool&, std::string const&); diff --git a/src/server/database/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h index 1b31d3691c4..4b0c670c3b7 100644 --- a/src/server/database/Database/DatabaseLoader.h +++ b/src/server/database/Database/DatabaseLoader.h @@ -19,7 +19,7 @@ #define DatabaseLoader_h__ #include "DatabaseWorkerPool.h" -#include "DatabaseEnv.h" +#include "DBUpdater.h" #include <functional> #include <stack> @@ -27,7 +27,7 @@ // A helper class to initiate all database worker pools, // handles updating, delays preparing of statements and cleans up on failure. -class DatabaseLoader +class TC_DATABASE_API DatabaseLoader { public: DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask); diff --git a/src/server/database/Database/DatabaseWorker.h b/src/server/database/Database/DatabaseWorker.h index c21a3d2a343..d6b43943f7d 100644 --- a/src/server/database/Database/DatabaseWorker.h +++ b/src/server/database/Database/DatabaseWorker.h @@ -24,7 +24,7 @@ class MySQLConnection; class SQLOperation; -class DatabaseWorker +class TC_DATABASE_API DatabaseWorker { public: DatabaseWorker(ProducerConsumerQueue<SQLOperation*>* newQueue, MySQLConnection* connection); diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp index 6c352bb11b8..daf54d271b2 100644 --- a/src/server/database/Database/DatabaseWorkerPool.cpp +++ b/src/server/database/Database/DatabaseWorkerPool.cpp @@ -317,7 +317,7 @@ T* DatabaseWorkerPool<T>::GetFreeConnection() return connection; } -template class DatabaseWorkerPool<LoginDatabaseConnection>; -template class DatabaseWorkerPool<WorldDatabaseConnection>; -template class DatabaseWorkerPool<CharacterDatabaseConnection>; -template class DatabaseWorkerPool<HotfixDatabaseConnection>; +template class TC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>; +template class TC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>; +template class TC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>; +template class TC_DATABASE_API DatabaseWorkerPool<HotfixDatabaseConnection>; diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h index abbe9253c2f..cd05023f417 100644 --- a/src/server/database/Database/Field.h +++ b/src/server/database/Database/Field.h @@ -53,7 +53,7 @@ | SUM, AVG | DECIMAL | | COUNT | BIGINT | */ -class Field +class TC_DATABASE_API Field { friend class ResultSet; friend class PreparedResultSet; diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index babf39ec3e5..8b7baf385ce 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -45,21 +45,21 @@ void CharacterDatabaseConnection::DoPrepareStatements() "subject, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? ", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, " - "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot " + "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, c.logout_time " "FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid " "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, " "c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, " - "cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? " + "cb.guid, c.slot, c.logout_time, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? " "LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid " "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_UNDELETE_ENUM, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, " - "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot " + "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, c.logout_time " "FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid " "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, " "c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, " - "cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? " + "cb.guid, c.slot, c.logout_time, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? " "LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid " "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT name, at_login FROM characters WHERE guid = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index ebc63f1cb6e..192a7e5f8dd 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -595,7 +595,7 @@ enum CharacterDatabaseStatements MAX_CHARACTERDATABASE_STATEMENTS }; -class CharacterDatabaseConnection : public MySQLConnection +class TC_DATABASE_API CharacterDatabaseConnection : public MySQLConnection { public: typedef CharacterDatabaseStatements Statements; diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index 35f08d98c77..438485156d5 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -281,7 +281,7 @@ enum HotfixDatabaseStatements MAX_HOTFIXDATABASE_STATEMENTS }; -class HotfixDatabaseConnection : public MySQLConnection +class TC_DATABASE_API HotfixDatabaseConnection : public MySQLConnection { public: typedef HotfixDatabaseStatements Statements; diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 964748a2682..2ca59c05ecc 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -39,7 +39,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, ba.os, ba.id, aa.gmLevel, " + PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.gmLevel, " "bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id " "FROM account a LEFT JOIN account r ON a.id = r.recruiter LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id " "LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 " diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index 749e7c2c9bb..94111d66388 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -147,7 +147,7 @@ enum LoginDatabaseStatements MAX_LOGINDATABASE_STATEMENTS }; -class LoginDatabaseConnection : public MySQLConnection +class TC_DATABASE_API LoginDatabaseConnection : public MySQLConnection { public: typedef LoginDatabaseStatements Statements; diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h index 0cc876c4a6d..60ac17b5f4a 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.h +++ b/src/server/database/Database/Implementation/WorldDatabase.h @@ -103,7 +103,7 @@ enum WorldDatabaseStatements MAX_WORLDDATABASE_STATEMENTS }; -class WorldDatabaseConnection : public MySQLConnection +class TC_DATABASE_API WorldDatabaseConnection : public MySQLConnection { public: typedef WorldDatabaseStatements Statements; diff --git a/src/server/database/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h index a0b908593df..566995988c0 100644 --- a/src/server/database/Database/MySQLConnection.h +++ b/src/server/database/Database/MySQLConnection.h @@ -35,7 +35,7 @@ enum ConnectionFlags CONNECTION_BOTH = CONNECTION_ASYNC | CONNECTION_SYNCH }; -struct MySQLConnectionInfo +struct TC_DATABASE_API MySQLConnectionInfo { explicit MySQLConnectionInfo(std::string const& infoString) { @@ -62,7 +62,7 @@ struct MySQLConnectionInfo typedef std::map<uint32 /*index*/, std::pair<std::string /*query*/, ConnectionFlags /*sync/async*/> > PreparedStatementMap; -class MySQLConnection +class TC_DATABASE_API MySQLConnection { template <class T> friend class DatabaseWorkerPool; friend class PingOperation; diff --git a/src/server/database/Database/MySQLThreading.h b/src/server/database/Database/MySQLThreading.h index 1cfa11d7e5b..b6083500989 100644 --- a/src/server/database/Database/MySQLThreading.h +++ b/src/server/database/Database/MySQLThreading.h @@ -20,7 +20,7 @@ #include "Log.h" -class MySQL +class TC_DATABASE_API MySQL { public: static void Library_Init() diff --git a/src/server/database/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h index 2079a5b78b8..d7508dbae1f 100644 --- a/src/server/database/Database/PreparedStatement.h +++ b/src/server/database/Database/PreparedStatement.h @@ -71,7 +71,7 @@ struct PreparedStatementData class MySQLPreparedStatement; //- Upper-level class that is used in code -class PreparedStatement +class TC_DATABASE_API PreparedStatement { friend class PreparedStatementTask; friend class MySQLPreparedStatement; @@ -111,7 +111,7 @@ class PreparedStatement //- Class of which the instances are unique per MySQLConnection //- access to these class objects is only done when a prepared statement task //- is executed. -class MySQLPreparedStatement +class TC_DATABASE_API MySQLPreparedStatement { friend class MySQLConnection; friend class PreparedStatement; @@ -159,7 +159,7 @@ typedef std::future<PreparedQueryResult> PreparedQueryResultFuture; typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise; //- Lower-level class, enqueuable operation -class PreparedStatementTask : public SQLOperation +class TC_DATABASE_API PreparedStatementTask : public SQLOperation { public: PreparedStatementTask(PreparedStatement* stmt, bool async = false); diff --git a/src/server/database/Database/QueryHolder.h b/src/server/database/Database/QueryHolder.h index f78f88f4c1e..34887767dea 100644 --- a/src/server/database/Database/QueryHolder.h +++ b/src/server/database/Database/QueryHolder.h @@ -20,7 +20,7 @@ #include <future> -class SQLQueryHolder +class TC_DATABASE_API SQLQueryHolder { friend class SQLQueryHolderTask; private: @@ -46,7 +46,7 @@ class SQLQueryHolder typedef std::future<SQLQueryHolder*> QueryResultHolderFuture; typedef std::promise<SQLQueryHolder*> QueryResultHolderPromise; -class SQLQueryHolderTask : public SQLOperation +class TC_DATABASE_API SQLQueryHolderTask : public SQLOperation { private: SQLQueryHolder* m_holder; diff --git a/src/server/database/Database/QueryResult.h b/src/server/database/Database/QueryResult.h index d4d63b5ec85..3b1691db1a6 100644 --- a/src/server/database/Database/QueryResult.h +++ b/src/server/database/Database/QueryResult.h @@ -27,7 +27,7 @@ #endif #include <mysql.h> -class ResultSet +class TC_DATABASE_API ResultSet { public: ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount); @@ -60,7 +60,7 @@ class ResultSet typedef std::shared_ptr<ResultSet> QueryResult; -class PreparedResultSet +class TC_DATABASE_API PreparedResultSet { public: PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount); diff --git a/src/server/database/Database/SQLOperation.h b/src/server/database/Database/SQLOperation.h index f0500d1f232..5b3032eab87 100644 --- a/src/server/database/Database/SQLOperation.h +++ b/src/server/database/Database/SQLOperation.h @@ -53,7 +53,7 @@ union SQLResultSetUnion class MySQLConnection; -class SQLOperation +class TC_DATABASE_API SQLOperation { public: SQLOperation(): m_conn(NULL) { } diff --git a/src/server/database/Database/Transaction.h b/src/server/database/Database/Transaction.h index 5780c0363d9..7b5b6addfe4 100644 --- a/src/server/database/Database/Transaction.h +++ b/src/server/database/Database/Transaction.h @@ -25,7 +25,7 @@ class PreparedStatement; /*! Transactions, high level class. */ -class Transaction +class TC_DATABASE_API Transaction { friend class TransactionTask; friend class MySQLConnection; @@ -58,7 +58,7 @@ class Transaction typedef std::shared_ptr<Transaction> SQLTransaction; /*! Low level class*/ -class TransactionTask : public SQLOperation +class TC_DATABASE_API TransactionTask : public SQLOperation { template <class T> friend class DatabaseWorkerPool; friend class DatabaseWorker; diff --git a/src/server/database/Logging/AppenderDB.h b/src/server/database/Logging/AppenderDB.h index a6acc66b48c..225ae969802 100644 --- a/src/server/database/Logging/AppenderDB.h +++ b/src/server/database/Logging/AppenderDB.h @@ -20,7 +20,7 @@ #include "Appender.h" -class AppenderDB: public Appender +class TC_DATABASE_API AppenderDB: public Appender { public: typedef std::integral_constant<AppenderType, APPENDER_DB>::type TypeIndex; diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index ab4b767b104..ef4a0d407cb 100644 --- a/src/server/database/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -468,7 +468,7 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos } } -template class DBUpdater<LoginDatabaseConnection>; -template class DBUpdater<WorldDatabaseConnection>; -template class DBUpdater<CharacterDatabaseConnection>; -template class DBUpdater<HotfixDatabaseConnection>; +template class TC_DATABASE_API DBUpdater<LoginDatabaseConnection>; +template class TC_DATABASE_API DBUpdater<WorldDatabaseConnection>; +template class TC_DATABASE_API DBUpdater<CharacterDatabaseConnection>; +template class TC_DATABASE_API DBUpdater<HotfixDatabaseConnection>; diff --git a/src/server/database/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h index dbb897d2527..cc5d3aad68b 100644 --- a/src/server/database/Updater/DBUpdater.h +++ b/src/server/database/Updater/DBUpdater.h @@ -23,7 +23,7 @@ #include <string> #include <boost/filesystem.hpp> -class UpdateException : public std::exception +class TC_DATABASE_API UpdateException : public std::exception { public: UpdateException(std::string const& msg) : _msg(msg) { } @@ -41,7 +41,7 @@ enum BaseLocation LOCATION_DOWNLOAD }; -struct UpdateResult +struct TC_DATABASE_API UpdateResult { UpdateResult() : updated(0), recent(0), archived(0) { } @@ -66,7 +66,7 @@ private: }; template <class T> -class DBUpdater +class TC_DATABASE_API DBUpdater { public: using Path = boost::filesystem::path; diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index c87efea2b02..a17658818ce 100644 --- a/src/server/database/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h @@ -25,7 +25,7 @@ #include <memory> #include <vector> -class UpdateFetcher +class TC_DATABASE_API UpdateFetcher { typedef boost::filesystem::path Path; diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h index 55b91b6969e..f1718fbdb6a 100644 --- a/src/server/game/AI/CoreAI/CombatAI.h +++ b/src/server/game/AI/CoreAI/CombatAI.h @@ -25,7 +25,7 @@ class Creature; -class AggressorAI : public CreatureAI +class TC_GAME_API AggressorAI : public CreatureAI { public: explicit AggressorAI(Creature* c) : CreatureAI(c) { } @@ -36,7 +36,7 @@ class AggressorAI : public CreatureAI typedef std::vector<uint32> SpellVct; -class CombatAI : public CreatureAI +class TC_GAME_API CombatAI : public CreatureAI { public: explicit CombatAI(Creature* c) : CreatureAI(c) { } @@ -55,7 +55,7 @@ class CombatAI : public CreatureAI SpellVct spells; }; -class CasterAI : public CombatAI +class TC_GAME_API CasterAI : public CombatAI { public: explicit CasterAI(Creature* c) : CombatAI(c) { m_attackDist = MELEE_RANGE; } @@ -67,7 +67,7 @@ class CasterAI : public CombatAI float m_attackDist; }; -struct ArcherAI : public CreatureAI +struct TC_GAME_API ArcherAI : public CreatureAI { public: explicit ArcherAI(Creature* c); @@ -80,7 +80,7 @@ struct ArcherAI : public CreatureAI float m_minRange; }; -struct TurretAI : public CreatureAI +struct TC_GAME_API TurretAI : public CreatureAI { public: explicit TurretAI(Creature* c); @@ -97,7 +97,7 @@ struct TurretAI : public CreatureAI #define VEHICLE_CONDITION_CHECK_TIME 1000 #define VEHICLE_DISMISS_TIME 5000 -struct VehicleAI : public CreatureAI +struct TC_GAME_API VehicleAI : public CreatureAI { public: explicit VehicleAI(Creature* creature); diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h index 4f256a5de31..7a2f23ac804 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -26,7 +26,7 @@ #include "GameObject.h" #include "CreatureAI.h" -class GameObjectAI +class TC_GAME_API GameObjectAI { protected: GameObject* const go; @@ -63,7 +63,7 @@ class GameObjectAI virtual void EventInform(uint32 /*eventId*/) { } }; -class NullGameObjectAI : public GameObjectAI +class TC_GAME_API NullGameObjectAI : public GameObjectAI { public: explicit NullGameObjectAI(GameObject* g); diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp index 176dd41fdae..c7d618a9918 100644 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -43,7 +43,7 @@ bool GuardAI::CanSeeAlways(WorldObject const* obj) return false; } -void GuardAI::EnterEvadeMode() +void GuardAI::EnterEvadeMode(EvadeReason /*why*/) { if (!me->IsAlive()) { diff --git a/src/server/game/AI/CoreAI/GuardAI.h b/src/server/game/AI/CoreAI/GuardAI.h index 01d54e47b9a..a6aa4b6624a 100644 --- a/src/server/game/AI/CoreAI/GuardAI.h +++ b/src/server/game/AI/CoreAI/GuardAI.h @@ -23,7 +23,7 @@ class Creature; -class GuardAI : public ScriptedAI +class TC_GAME_API GuardAI : public ScriptedAI { public: explicit GuardAI(Creature* creature); @@ -31,7 +31,7 @@ class GuardAI : public ScriptedAI static int Permissible(Creature const* creature); bool CanSeeAlways(WorldObject const* obj) override; - void EnterEvadeMode() override; + void EnterEvadeMode(EvadeReason /*why*/) override; void JustDied(Unit* killer) override; }; #endif diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index 1a6af99b11d..f283afe77a8 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -26,7 +26,7 @@ NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState( void PassiveAI::UpdateAI(uint32) { if (me->IsInCombat() && me->getAttackers().empty()) - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); } void PossessedAI::AttackStart(Unit* target) @@ -64,11 +64,11 @@ void CritterAI::DamageTaken(Unit* /*done_by*/, uint32&) me->SetControlled(true, UNIT_STATE_FLEEING); } -void CritterAI::EnterEvadeMode() +void CritterAI::EnterEvadeMode(EvadeReason why) { if (me->HasUnitState(UNIT_STATE_FLEEING)) me->SetControlled(false, UNIT_STATE_FLEEING); - CreatureAI::EnterEvadeMode(); + CreatureAI::EnterEvadeMode(why); } void TriggerAI::IsSummonedBy(Unit* summoner) diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h index 28a73cff5de..5a6dba7046d 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.h +++ b/src/server/game/AI/CoreAI/PassiveAI.h @@ -21,7 +21,7 @@ #include "CreatureAI.h" -class PassiveAI : public CreatureAI +class TC_GAME_API PassiveAI : public CreatureAI { public: explicit PassiveAI(Creature* c); @@ -33,7 +33,7 @@ class PassiveAI : public CreatureAI static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } }; -class PossessedAI : public CreatureAI +class TC_GAME_API PossessedAI : public CreatureAI { public: explicit PossessedAI(Creature* c); @@ -41,7 +41,7 @@ class PossessedAI : public CreatureAI void MoveInLineOfSight(Unit*) override { } void AttackStart(Unit* target) override; void UpdateAI(uint32) override; - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } void JustDied(Unit*) override; void KilledUnit(Unit* victim) override; @@ -49,7 +49,7 @@ class PossessedAI : public CreatureAI static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } }; -class NullCreatureAI : public CreatureAI +class TC_GAME_API NullCreatureAI : public CreatureAI { public: explicit NullCreatureAI(Creature* c); @@ -57,22 +57,22 @@ class NullCreatureAI : public CreatureAI void MoveInLineOfSight(Unit*) override { } void AttackStart(Unit*) override { } void UpdateAI(uint32) override { } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } void OnCharmed(bool /*apply*/) override { } static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } }; -class CritterAI : public PassiveAI +class TC_GAME_API CritterAI : public PassiveAI { public: explicit CritterAI(Creature* c) : PassiveAI(c) { } void DamageTaken(Unit* done_by, uint32& /*damage*/) override; - void EnterEvadeMode() override; + void EnterEvadeMode(EvadeReason why) override; }; -class TriggerAI : public NullCreatureAI +class TC_GAME_API TriggerAI : public NullCreatureAI { public: explicit TriggerAI(Creature* c) : NullCreatureAI(c) { } diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 2bf31a8be06..46a0342fea5 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -148,15 +148,15 @@ void PetAI::UpdateAI(uint32 diff) if (me->GetCharmInfo() && me->GetSpellHistory()->HasGlobalCooldown(spellInfo)) continue; + + // check spell cooldown + if (!me->GetSpellHistory()->IsReady(spellInfo)) + continue; if (spellInfo->IsPositive()) { if (spellInfo->CanBeUsedInCombat()) { - // check spell cooldown - if (!me->GetSpellHistory()->IsReady(spellInfo)) - continue; - // Check if we're in combat or commanded to attack if (!me->IsInCombat() && !me->GetCharmInfo()->IsCommandAttack()) continue; diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index 9f220e64bfb..3ad34047b01 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -25,7 +25,7 @@ class Creature; class Spell; -class PetAI : public CreatureAI +class TC_GAME_API PetAI : public CreatureAI { public: @@ -47,7 +47,7 @@ class PetAI : public CreatureAI // void MoveInLineOfSight(Unit* /*who*/) override { } // CreatureAI interferes with returning pets void MoveInLineOfSight_Safe(Unit* /*who*/) { } // CreatureAI interferes with returning pets - void EnterEvadeMode() override { } // For fleeing, pets don't use this type of Evade mechanic + void EnterEvadeMode(EvadeReason /*why*/) override { } // For fleeing, pets don't use this type of Evade mechanic private: bool _isVisible(Unit*) const; diff --git a/src/server/game/AI/CoreAI/ReactorAI.h b/src/server/game/AI/CoreAI/ReactorAI.h index e5abaac2f00..d281ca11fdf 100644 --- a/src/server/game/AI/CoreAI/ReactorAI.h +++ b/src/server/game/AI/CoreAI/ReactorAI.h @@ -23,7 +23,7 @@ class Unit; -class ReactorAI : public CreatureAI +class TC_GAME_API ReactorAI : public CreatureAI { public: diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp index 3c34ea88e39..48459ce0cd1 100644 --- a/src/server/game/AI/CoreAI/TotemAI.cpp +++ b/src/server/game/AI/CoreAI/TotemAI.cpp @@ -40,7 +40,7 @@ TotemAI::TotemAI(Creature* c) : CreatureAI(c), i_victimGuid() void TotemAI::MoveInLineOfSight(Unit* /*who*/) { } -void TotemAI::EnterEvadeMode() +void TotemAI::EnterEvadeMode(EvadeReason /*why*/) { me->CombatStop(true); } diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h index fdde303c7b2..a0e796ed7e0 100644 --- a/src/server/game/AI/CoreAI/TotemAI.h +++ b/src/server/game/AI/CoreAI/TotemAI.h @@ -25,7 +25,7 @@ class Creature; class Totem; -class TotemAI : public CreatureAI +class TC_GAME_API TotemAI : public CreatureAI { public: @@ -33,7 +33,7 @@ class TotemAI : public CreatureAI void MoveInLineOfSight(Unit* who) override; void AttackStart(Unit* victim) override; - void EnterEvadeMode() override; + void EnterEvadeMode(EvadeReason /*why*/) override; void UpdateAI(uint32 diff) override; static int Permissible(Creature const* creature); diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index b43e61b6c6e..ea001ceda32 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -40,7 +40,7 @@ enum SelectAggroTarget }; // default predicate function to select target based on distance, player and/or aura criteria -struct DefaultTargetSelector : public std::unary_function<Unit*, bool> +struct TC_GAME_API DefaultTargetSelector : public std::unary_function<Unit*, bool> { const Unit* me; float m_dist; @@ -90,7 +90,7 @@ struct DefaultTargetSelector : public std::unary_function<Unit*, bool> // Target selector for spell casts checking range, auras and attributes /// @todo Add more checks from Spell::CheckCast -struct SpellTargetSelector : public std::unary_function<Unit*, bool> +struct TC_GAME_API SpellTargetSelector : public std::unary_function<Unit*, bool> { public: SpellTargetSelector(Unit* caster, uint32 spellId); @@ -104,7 +104,7 @@ struct SpellTargetSelector : public std::unary_function<Unit*, bool> // Very simple target selector, will just skip main target // NOTE: When passing to UnitAI::SelectTarget remember to use 0 as position for random selection // because tank will not be in the temporary list -struct NonTankTargetSelector : public std::unary_function<Unit*, bool> +struct TC_GAME_API NonTankTargetSelector : public std::unary_function<Unit*, bool> { public: NonTankTargetSelector(Creature* source, bool playerOnly = true) : _source(source), _playerOnly(playerOnly) { } @@ -115,7 +115,7 @@ struct NonTankTargetSelector : public std::unary_function<Unit*, bool> bool _playerOnly; }; -class UnitAI +class TC_GAME_API UnitAI { protected: Unit* const me; @@ -264,7 +264,7 @@ class UnitAI UnitAI& operator=(UnitAI const& right) = delete; }; -class PlayerAI : public UnitAI +class TC_GAME_API PlayerAI : public UnitAI { protected: Player* const me; @@ -274,7 +274,7 @@ class PlayerAI : public UnitAI void OnCharmed(bool apply) override; }; -class SimpleCharmedAI : public PlayerAI +class TC_GAME_API SimpleCharmedAI : public PlayerAI { public: void UpdateAI(uint32 diff) override; diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index e94f5a037a3..8ef8940e89f 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -26,6 +26,7 @@ #include "MapReference.h" #include "Player.h" #include "CreatureTextMgr.h" +#include "Language.h" //Disable CreatureAI when charmed void CreatureAI::OnCharmed(bool /*apply*/) @@ -164,9 +165,9 @@ void CreatureAI::TriggerAlert(Unit const* who) const me->GetMotionMaster()->MoveDistract(5 * IN_MILLISECONDS); } -void CreatureAI::EnterEvadeMode() +void CreatureAI::EnterEvadeMode(EvadeReason why) { - if (!_EnterEvadeMode()) + if (!_EnterEvadeMode(why)) return; TC_LOG_DEBUG("entities.unit", "Creature %u enters evade mode.", me->GetEntry()); @@ -241,14 +242,14 @@ bool CreatureAI::UpdateVictim() } else if (me->getThreatManager().isThreatListEmpty()) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return false; } return true; } -bool CreatureAI::_EnterEvadeMode() +bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) { if (!me->IsAlive()) return false; @@ -271,6 +272,105 @@ bool CreatureAI::_EnterEvadeMode() return true; } +#define BOUNDARY_VISUALIZE_CREATURE 15425 +#define BOUNDARY_VISUALIZE_CREATURE_SCALE 0.25f +#define BOUNDARY_VISUALIZE_STEP_SIZE 1 +#define BOUNDARY_VISUALIZE_FAILSAFE_LIMIT 750 +#define BOUNDARY_VISUALIZE_SPAWN_HEIGHT 5 +int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) const +{ + typedef std::pair<int32, int32> coordinate; + + if (!owner) + return -1; + + if (!_boundary || _boundary->empty()) + return LANG_CREATURE_MOVEMENT_NOT_BOUNDED; + + std::queue<coordinate> Q; + std::unordered_set<coordinate> alreadyChecked; + std::unordered_set<coordinate> outOfBounds; + + Position startPosition = owner->GetPosition(); + if (!CheckBoundary(&startPosition)) // fall back to creature position + { + startPosition = me->GetPosition(); + if (!CheckBoundary(&startPosition)) + { + startPosition = me->GetHomePosition(); + if (!CheckBoundary(&startPosition)) // fall back to creature home position + return LANG_CREATURE_NO_INTERIOR_POINT_FOUND; + } + } + float spawnZ = startPosition.GetPositionZ() + BOUNDARY_VISUALIZE_SPAWN_HEIGHT; + + bool boundsWarning = false; + Q.push({ 0,0 }); + while (!Q.empty()) + { + coordinate front = Q.front(); + bool hasOutOfBoundsNeighbor = false; + for (coordinate off : std::initializer_list<coordinate>{{1,0}, {0,1}, {-1,0}, {0,-1}}) + { + coordinate next(front.first + off.first, front.second + off.second); + if (next.first > BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.first < -BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.second > BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.second < -BOUNDARY_VISUALIZE_FAILSAFE_LIMIT) + { + boundsWarning = true; + continue; + } + if (alreadyChecked.find(next) == alreadyChecked.end()) // never check a coordinate twice + { + Position nextPos(startPosition.GetPositionX() + next.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + next.second*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionZ()); + if (CheckBoundary(&nextPos)) + Q.push(next); + else + { + outOfBounds.insert(next); + hasOutOfBoundsNeighbor = true; + } + alreadyChecked.insert(next); + } + else + if (outOfBounds.find(next) != outOfBounds.end()) + hasOutOfBoundsNeighbor = true; + } + if (fill || hasOutOfBoundsNeighbor) + if (TempSummon* point = owner->SummonCreature(BOUNDARY_VISUALIZE_CREATURE, Position(startPosition.GetPositionX() + front.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + front.second*BOUNDARY_VISUALIZE_STEP_SIZE, spawnZ), TEMPSUMMON_TIMED_DESPAWN, duration * IN_MILLISECONDS)) + { + point->SetObjectScale(BOUNDARY_VISUALIZE_CREATURE_SCALE); + point->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_STUNNED | UNIT_FLAG_IMMUNE_TO_NPC); + if (!hasOutOfBoundsNeighbor) + point->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + Q.pop(); + } + return boundsWarning ? LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED : 0; +} + +bool CreatureAI::CheckBoundary(Position* who) const +{ + if (!who) + who = me; + + if (_boundary) + for (CreatureBoundary::const_iterator it = _boundary->begin(); it != _boundary->end(); ++it) + if (!(*it)->IsWithinBoundary(who)) + return false; + + return true; +} + +bool CreatureAI::CheckInRoom() +{ + if (CheckBoundary()) + return true; + else + { + EnterEvadeMode(EVADE_REASON_BOUNDARY); + return false; + } +} + Creature* CreatureAI::DoSummon(uint32 entry, const Position& pos, uint32 despawnTime, TempSummonType summonType) { return me->SummonCreature(entry, pos, summonType, despawnTime); diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index 0a2cce723dc..f2108ef2b3f 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -21,6 +21,7 @@ #include "Creature.h" #include "UnitAI.h" +#include "AreaBoundary.h" #include "Common.h" class WorldObject; @@ -63,7 +64,8 @@ enum SCEquip EQUIP_UNEQUIP = 0 }; -class CreatureAI : public UnitAI +typedef std::set<AreaBoundary const*> CreatureBoundary; +class TC_GAME_API CreatureAI : public UnitAI { protected: Creature* const me; @@ -77,10 +79,20 @@ class CreatureAI : public UnitAI Creature* DoSummon(uint32 entry, WorldObject* obj, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN); Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN); + bool CheckBoundary(Position* who = nullptr) const; + void SetBoundary(CreatureBoundary const* boundary) { _boundary = boundary; me->DoImmediateBoundaryCheck(); } public: + enum EvadeReason + { + EVADE_REASON_NO_HOSTILES, // the creature's threat list is empty + EVADE_REASON_BOUNDARY, // the creature has moved outside its evade boundary + EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet + EVADE_REASON_OTHER + }; + void Talk(uint8 id, WorldObject const* whisperTarget = nullptr); - explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), m_MoveInLineOfSight_locked(false) { } + explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), _boundary(nullptr), m_MoveInLineOfSight_locked(false) { } virtual ~CreatureAI() { } @@ -96,7 +108,7 @@ class CreatureAI : public UnitAI virtual bool CanRespawn() { return true; } // Called for reaction at stopping attack at no attackers or targets - virtual void EnterEvadeMode(); + virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER); // Called for reaction at enter to combat if not in combat yet (enemy can be NULL) virtual void EnterCombat(Unit* /*victim*/) { } @@ -124,8 +136,8 @@ class CreatureAI : public UnitAI virtual void AttackedBy(Unit* /*attacker*/) { } virtual bool IsEscorted() const { return false; } - // Called when creature is spawned or respawned (for reseting variables) - virtual void JustRespawned() { Reset(); } + // Called when creature is spawned or respawned + virtual void JustRespawned() { } // Called at waypoint reached or point movement finished virtual void MovementInform(uint32 /*type*/, uint32 /*id*/) { } @@ -174,10 +186,17 @@ class CreatureAI : public UnitAI virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; } + // 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(); + CreatureBoundary const* GetBoundary() const { return _boundary; } + protected: virtual void MoveInLineOfSight(Unit* /*who*/); - bool _EnterEvadeMode(); + bool _EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER); + + CreatureBoundary const* _boundary; private: bool m_MoveInLineOfSight_locked; diff --git a/src/server/game/AI/CreatureAISelector.h b/src/server/game/AI/CreatureAISelector.h index 7c7bc705ade..0e3be1a8604 100644 --- a/src/server/game/AI/CreatureAISelector.h +++ b/src/server/game/AI/CreatureAISelector.h @@ -27,9 +27,9 @@ class GameObject; namespace FactorySelector { - CreatureAI* selectAI(Creature*); - MovementGenerator* selectMovementGenerator(Creature*); - GameObjectAI* SelectGameObjectAI(GameObject*); + TC_GAME_API CreatureAI* selectAI(Creature*); + TC_GAME_API MovementGenerator* selectMovementGenerator(Creature*); + TC_GAME_API GameObjectAI* SelectGameObjectAI(GameObject*); } #endif diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index c2ddd1e9e8e..87c7f2083af 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -23,6 +23,7 @@ #include "Cell.h" #include "CellImpl.h" #include "ObjectMgr.h" +#include "AreaBoundary.h" // Spell summary for ScriptedAI::SelectSpell struct TSpellSummary @@ -98,7 +99,6 @@ bool SummonList::HasEntry(uint32 entry) const ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature), IsFleeing(false), - _evadeCheckCooldown(2500), _isCombatMovementAllowed(true) { _isHeroic = me->GetMap()->IsHeroic(); @@ -394,7 +394,7 @@ enum NPCs // Hacklike storage used for misc creatures that are expected to evade of outside of a certain area. // It is assumed the information is found elswehere and can be handled by the core. So far no luck finding such information/way to extract it. -bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff) +/*bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff) { if (_evadeCheckCooldown <= diff) _evadeCheckCooldown = 2500; @@ -438,15 +438,16 @@ bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff) EnterEvadeMode(); return true; -} +}*/ // BossAI - for instanced bosses BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature), instance(creature->GetInstanceScript()), summons(creature), - _boundary(instance ? instance->GetBossBoundary(bossId) : NULL), _bossId(bossId) { + if (instance) + SetBoundary(instance->GetBossBoundary(bossId)); scheduler.SetValidator([this] { return !me->HasUnitState(UNIT_STATE_CASTING); @@ -483,7 +484,7 @@ void BossAI::_EnterCombat() // bosses do not respawn, check only on enter combat if (!instance->CheckRequiredBosses(_bossId)) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); return; } instance->SetBossState(_bossId, IN_PROGRESS); @@ -507,55 +508,6 @@ void BossAI::TeleportCheaters() target->NearTeleportTo(x, y, z, 0); } -bool BossAI::CheckBoundary(Unit* who) -{ - if (!GetBoundary() || !who) - return true; - - for (BossBoundaryMap::const_iterator itr = GetBoundary()->begin(); itr != GetBoundary()->end(); ++itr) - { - switch (itr->first) - { - case BOUNDARY_N: - if (who->GetPositionX() > itr->second) - return false; - break; - case BOUNDARY_S: - if (who->GetPositionX() < itr->second) - return false; - break; - case BOUNDARY_E: - if (who->GetPositionY() < itr->second) - return false; - break; - case BOUNDARY_W: - if (who->GetPositionY() > itr->second) - return false; - break; - case BOUNDARY_NW: - if (who->GetPositionX() + who->GetPositionY() > itr->second) - return false; - break; - case BOUNDARY_SE: - if (who->GetPositionX() + who->GetPositionY() < itr->second) - return false; - break; - case BOUNDARY_NE: - if (who->GetPositionX() - who->GetPositionY() > itr->second) - return false; - break; - case BOUNDARY_SW: - if (who->GetPositionX() - who->GetPositionY() < itr->second) - return false; - break; - default: - break; - } - } - - return true; -} - void BossAI::JustSummoned(Creature* summon) { summons.Summon(summon); @@ -656,27 +608,27 @@ void WorldBossAI::UpdateAI(uint32 diff) } // SD2 grid searchers. -Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/) +TC_GAME_API Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/) { return source->FindNearestCreature(entry, maxSearchRange, alive); } -GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange) +TC_GAME_API GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange) { return source->FindNearestGameObject(entry, maxSearchRange); } -void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange) +TC_GAME_API void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange) { source->GetCreatureListWithEntryInGrid(list, entry, maxSearchRange); } -void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange) +TC_GAME_API void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange) { source->GetGameObjectListWithEntryInGrid(list, entry, maxSearchRange); } -void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange) +TC_GAME_API void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange) { source->GetPlayerListInGrid(list, maxSearchRange); } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 87c1a63d4e4..56e4b8bf780 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -38,7 +38,7 @@ T* EnsureAI(U* ai) class InstanceScript; -class SummonList +class TC_GAME_API SummonList { public: typedef GuidList StorageType; @@ -123,7 +123,7 @@ private: StorageType storage_; }; -class EntryCheckPredicate +class TC_GAME_API EntryCheckPredicate { public: EntryCheckPredicate(uint32 entry) : _entry(entry) { } @@ -133,13 +133,13 @@ class EntryCheckPredicate uint32 _entry; }; -class DummyEntryCheckPredicate +class TC_GAME_API DummyEntryCheckPredicate { public: bool operator()(ObjectGuid) { return true; } }; -struct ScriptedAI : public CreatureAI +struct TC_GAME_API ScriptedAI : public CreatureAI { explicit ScriptedAI(Creature* creature); virtual ~ScriptedAI() { } @@ -260,8 +260,6 @@ struct ScriptedAI : public CreatureAI void SetCombatMovement(bool allowMovement); bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; } - bool EnterEvadeIfOutOfCombatArea(uint32 const diff); - // return true for heroic mode. i.e. // - for dungeon in mode 10-heroic, // - for raid in mode 10-Heroic @@ -329,19 +327,17 @@ struct ScriptedAI : public CreatureAI private: Difficulty _difficulty; - uint32 _evadeCheckCooldown; bool _isCombatMovementAllowed; bool _isHeroic; }; -class BossAI : public ScriptedAI +class TC_GAME_API BossAI : public ScriptedAI { public: BossAI(Creature* creature, uint32 bossId); virtual ~BossAI() { } InstanceScript* const instance; - BossBoundaryMap const* GetBoundary() const { return _boundary; } void JustSummoned(Creature* summon) override; void SummonedCreatureDespawn(Creature* summon) override; @@ -368,16 +364,6 @@ class BossAI : public ScriptedAI void _JustReachedHome() { me->setActive(false); } void _DespawnAtEvade(); - virtual bool CheckInRoom() - { - if (CheckBoundary(me)) - return true; - - EnterEvadeMode(); - return false; - } - - bool CheckBoundary(Unit* who); void TeleportCheaters(); EventMap events; @@ -385,11 +371,10 @@ class BossAI : public ScriptedAI TaskScheduler scheduler; private: - BossBoundaryMap const* const _boundary; uint32 const _bossId; }; -class WorldBossAI : public ScriptedAI +class TC_GAME_API WorldBossAI : public ScriptedAI { public: WorldBossAI(Creature* creature); @@ -420,10 +405,10 @@ class WorldBossAI : public ScriptedAI }; // SD2 grid searchers. -Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive = true); -GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange); -void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange); -void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange); -void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange); +TC_GAME_API Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive = true); +TC_GAME_API GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange); +TC_GAME_API void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange); +TC_GAME_API void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange); +TC_GAME_API void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange); #endif // SCRIPTEDCREATURE_H_ diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index cd2288364c1..6e8a2def3e3 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -184,7 +184,7 @@ void npc_escortAI::ReturnToLastPoint() me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z); } -void npc_escortAI::EnterEvadeMode() +void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/) { me->RemoveAllAuras(); me->DeleteThreatList(); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h index 3b7428e2b9e..37a1464d812 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h @@ -49,7 +49,7 @@ enum eEscortState STATE_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed }; -struct npc_escortAI : public ScriptedAI +struct TC_GAME_API npc_escortAI : public ScriptedAI { public: explicit npc_escortAI(Creature* creature); @@ -66,7 +66,7 @@ struct npc_escortAI : public ScriptedAI void ReturnToLastPoint(); - void EnterEvadeMode() override; + void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override; void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI() virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc) diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 3fbd6b9a834..583e99b9d10 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -176,7 +176,7 @@ void FollowerAI::JustRespawned() Reset(); } -void FollowerAI::EnterEvadeMode() +void FollowerAI::EnterEvadeMode(EvadeReason /*why*/) { me->RemoveAllAuras(); me->DeleteThreatList(); diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h index f3919ea63bc..e17fb7c8507 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h @@ -32,7 +32,7 @@ enum eFollowState STATE_FOLLOW_POSTEVENT = 0x020 //can be set at complete and allow post event to run }; -class FollowerAI : public ScriptedAI +class TC_GAME_API FollowerAI : public ScriptedAI { public: explicit FollowerAI(Creature* creature); @@ -46,7 +46,7 @@ class FollowerAI : public ScriptedAI void MoveInLineOfSight(Unit*) override; - void EnterEvadeMode() override; + void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override; void JustDied(Unit*) override; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 001fd259996..2dec1d0fc4c 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -408,7 +408,7 @@ void SmartAI::MovementInform(uint32 MovementType, uint32 Data) MovepointReached(Data); } -void SmartAI::EnterEvadeMode() +void SmartAI::EnterEvadeMode(EvadeReason /*why*/) { if (!me->IsAlive() || me->IsInEvadeMode()) return; diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index cfc8fbe785d..aa7c9ace0b3 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -42,7 +42,7 @@ enum SmartEscortVars SMART_MAX_AID_DIST = SMART_ESCORT_MAX_PLAYER_DIST / 2 }; -class SmartAI : public CreatureAI +class TC_GAME_API SmartAI : public CreatureAI { public: ~SmartAI(){ } @@ -79,7 +79,7 @@ class SmartAI : public CreatureAI void EnterCombat(Unit* enemy) override; // Called for reaction at stopping attack at no attackers or targets - void EnterEvadeMode() override; + void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override; // Called when the creature is killed void JustDied(Unit* killer) override; @@ -230,7 +230,7 @@ class SmartAI : public CreatureAI bool mJustReset; }; -class SmartGameObjectAI : public GameObjectAI +class TC_GAME_API SmartGameObjectAI : public GameObjectAI { public: SmartGameObjectAI(GameObject* g) : GameObjectAI(g) { } @@ -257,4 +257,8 @@ class SmartGameObjectAI : public GameObjectAI private: SmartScript mScript; }; + +/// Registers scripts required by the SAI scripting system +void AddSC_SmartScripts(); + #endif diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 95792fead3c..0ea3afa08f9 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -28,7 +28,7 @@ #include "SmartScriptMgr.h" //#include "SmartAI.h" -class SmartScript +class TC_GAME_API SmartScript { public: SmartScript(); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index b02906a7164..d249bf8c42c 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -28,6 +28,12 @@ #include "SmartScriptMgr.h" +SmartWaypointMgr* SmartWaypointMgr::instance() +{ + static SmartWaypointMgr instance; + return &instance; +} + void SmartWaypointMgr::LoadFromDB() { uint32 oldMSTime = getMSTime(); @@ -99,6 +105,12 @@ SmartWaypointMgr::~SmartWaypointMgr() } } +SmartAIMgr* SmartAIMgr::instance() +{ + static SmartAIMgr instance; + return &instance; +} + void SmartAIMgr::LoadSmartAIFromDB() { LoadHelperStores(); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 00d3e97e19f..87d23b077b1 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1435,18 +1435,14 @@ public: }; typedef std::unordered_map<uint32, ObjectGuidList*> ObjectListMap; -class SmartWaypointMgr +class TC_GAME_API SmartWaypointMgr { private: SmartWaypointMgr() { } ~SmartWaypointMgr(); public: - static SmartWaypointMgr* instance() - { - static SmartWaypointMgr instance; - return &instance; - } + static SmartWaypointMgr* instance(); void LoadFromDB(); @@ -1471,18 +1467,14 @@ typedef std::unordered_map<int64, SmartAIEventList> SmartAIEventMap; typedef std::map<uint32 /*entry*/, std::pair<uint32 /*spellId*/, SpellEffIndex /*effIndex*/> > CacheSpellContainer; typedef std::pair<CacheSpellContainer::const_iterator, CacheSpellContainer::const_iterator> CacheSpellContainerBounds; -class SmartAIMgr +class TC_GAME_API SmartAIMgr { private: SmartAIMgr() { } ~SmartAIMgr() { } public: - static SmartAIMgr* instance() - { - static SmartAIMgr instance; - return &instance; - } + static SmartAIMgr* instance(); void LoadSmartAIFromDB(); diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index d5d62908e53..81d071881fe 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -33,6 +33,12 @@ AccountMgr::~AccountMgr() ClearRBAC(); } +AccountMgr* AccountMgr::instance() +{ + static AccountMgr instance; + return &instance; +} + AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/, uint32 bnetAccountId /*= 0*/, uint8 bnetIndex /*= 0*/) { if (utf8length(username) > MAX_ACCOUNT_STR) diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h index 1addf82e986..d0a80f983db 100644 --- a/src/server/game/Accounts/AccountMgr.h +++ b/src/server/game/Accounts/AccountMgr.h @@ -50,18 +50,14 @@ typedef std::map<uint32, rbac::RBACPermission*> RBACPermissionsContainer; typedef std::map<uint8, rbac::RBACPermissionContainer> RBACDefaultPermissionsContainer; } -class AccountMgr +class TC_GAME_API AccountMgr { private: AccountMgr(); ~AccountMgr(); public: - static AccountMgr* instance() - { - static AccountMgr instance; - return &instance; - } + static AccountMgr* instance(); AccountOpResult CreateAccount(std::string username, std::string password, std::string email = "", uint32 bnetAccountId = 0, uint8 bnetIndex = 0); static AccountOpResult DeleteAccount(uint32 accountId); diff --git a/src/server/game/Accounts/BattlenetAccountMgr.h b/src/server/game/Accounts/BattlenetAccountMgr.h index ef47a3e5c93..1888e782616 100644 --- a/src/server/game/Accounts/BattlenetAccountMgr.h +++ b/src/server/game/Accounts/BattlenetAccountMgr.h @@ -29,18 +29,18 @@ namespace Battlenet { namespace AccountMgr { - AccountOpResult CreateBattlenetAccount(std::string email, std::string password, bool withGameAccount = true); - AccountOpResult ChangePassword(uint32 accountId, std::string newPassword); - bool CheckPassword(uint32 accountId, std::string password); - AccountOpResult LinkWithGameAccount(std::string const& email, std::string const& gameAccountName); - AccountOpResult UnlinkGameAccount(std::string const& gameAccountName); - - uint32 GetId(std::string const& username); - bool GetName(uint32 accountId, std::string& name); - uint32 GetIdByGameAccount(uint32 gameAccountId); - uint8 GetMaxIndex(uint32 accountId); - - std::string CalculateShaPassHash(std::string const& name, std::string const& password); + TC_GAME_API AccountOpResult CreateBattlenetAccount(std::string email, std::string password, bool withGameAccount = true); + TC_GAME_API AccountOpResult ChangePassword(uint32 accountId, std::string newPassword); + TC_GAME_API bool CheckPassword(uint32 accountId, std::string password); + TC_GAME_API AccountOpResult LinkWithGameAccount(std::string const& email, std::string const& gameAccountName); + TC_GAME_API AccountOpResult UnlinkGameAccount(std::string const& gameAccountName); + + TC_GAME_API uint32 GetId(std::string const& username); + TC_GAME_API bool GetName(uint32 accountId, std::string& name); + TC_GAME_API uint32 GetIdByGameAccount(uint32 gameAccountId); + TC_GAME_API uint8 GetMaxIndex(uint32 accountId); + + TC_GAME_API std::string CalculateShaPassHash(std::string const& name, std::string const& password); } } diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index d355d4fdfd3..07ad2a2fd4b 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -727,6 +727,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_TICKET_RESET_SUGGESTION = 833, RBAC_PERM_COMMAND_GO_QUEST = 834, RBAC_PERM_COMMAND_DEBUG_LOADCELLS = 835, + RBAC_PERM_COMMAND_DEBUG_BOUNDARY = 836, // custom permissions 1000+ RBAC_PERM_MAX @@ -744,7 +745,7 @@ enum RBACCommandResult typedef std::set<uint32> RBACPermissionContainer; -class RBACPermission +class TC_GAME_API RBACPermission { public: RBACPermission(uint32 id = 0, std::string const& name = ""): @@ -779,7 +780,7 @@ class RBACPermission * - Granted permissions: through linked permissions and directly assigned * - Denied permissions: through linked permissions and directly assigned */ -class RBACData +class TC_GAME_API RBACData { public: RBACData(uint32 id, std::string const& name, int32 realmId, uint8 secLevel = 255): diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 6462c89a694..219745e0444 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -488,13 +488,7 @@ void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /* // Not needed } -template<class T> -void AchievementMgr<T>::DeleteFromDB(ObjectGuid /*guid*/) -{ -} - -template<> -void AchievementMgr<Player>::DeleteFromDB(ObjectGuid guid) +void DeletePlayerAchievementsFromDB(ObjectGuid guid) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -509,8 +503,7 @@ void AchievementMgr<Player>::DeleteFromDB(ObjectGuid guid) CharacterDatabase.CommitTransaction(trans); } -template<> -void AchievementMgr<Guild>::DeleteFromDB(ObjectGuid guid) +void DeleteGuildAchievementsFromDB(ObjectGuid guid) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -529,6 +522,7 @@ template<class T> void AchievementMgr<T>::SaveToDB(SQLTransaction& /*trans*/) { } + template<> void AchievementMgr<Player>::SaveToDB(SQLTransaction& trans) { @@ -2584,6 +2578,9 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(ModifierTreeNode const* return true; } +template class TC_GAME_API AchievementMgr<Player>; +template class TC_GAME_API AchievementMgr<Guild>; + char const* AchievementGlobalMgr::GetCriteriaTypeString(uint32 type) { return GetCriteriaTypeString(AchievementCriteriaTypes(type)); @@ -2887,8 +2884,11 @@ char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes return "MISSING_TYPE"; } -template class AchievementMgr<Guild>; -template class AchievementMgr<Player>; +AchievementGlobalMgr* AchievementGlobalMgr::instance() +{ + static AchievementGlobalMgr instance; + return &instance; +} //========================================================== AchievementGlobalMgr::~AchievementGlobalMgr() diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index 60c563683fb..16f4d20614a 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -30,6 +30,7 @@ class Unit; class Player; +class Guild; class WorldPacket; struct ModifierTreeNode @@ -233,7 +234,7 @@ struct AchievementCriteriaData bool Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 = 0) const; }; -struct AchievementCriteriaDataSet +struct TC_GAME_API AchievementCriteriaDataSet { AchievementCriteriaDataSet() : criteria_id(0) { } typedef std::vector<AchievementCriteriaData> Storage; @@ -284,15 +285,41 @@ enum ProgressType PROGRESS_HIGHEST }; +// Hackfix to solve an unresolved issue in clang that the visibility +// flag is ignored in some explicit template specializations, +// which prevents clang from exporting the `DeleteFromDB` symbol. +// https://llvm.org/bugs/show_bug.cgi?id=24815 +// https://llvm.org/bugs/show_bug.cgi?id=23667 +TC_GAME_API void DeletePlayerAchievementsFromDB(ObjectGuid guid); +TC_GAME_API void DeleteGuildAchievementsFromDB(ObjectGuid guid); + +template<typename T> +struct AchievementMgrDeleterBase; + +template<> +struct AchievementMgrDeleterBase<Player> +{ + static void DeleteFromDB(ObjectGuid lowguid) { DeletePlayerAchievementsFromDB(lowguid); } +}; + +template<> +struct AchievementMgrDeleterBase<Guild> +{ + static void DeleteFromDB(ObjectGuid lowguid) { DeleteGuildAchievementsFromDB(lowguid); } +}; + template<class T> -class AchievementMgr +class TC_GAME_API AchievementMgr + : public AchievementMgrDeleterBase<T> { public: AchievementMgr(T* owner); ~AchievementMgr(); void Reset(); - static void DeleteFromDB(ObjectGuid lowguid); + + using AchievementMgrDeleterBase<T>::DeleteFromDB; + void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult); void SaveToDB(SQLTransaction& trans); void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false); @@ -335,7 +362,7 @@ class AchievementMgr uint32 _achievementPoints; }; -class AchievementGlobalMgr +class TC_GAME_API AchievementGlobalMgr { AchievementGlobalMgr() { } ~AchievementGlobalMgr(); @@ -344,11 +371,7 @@ class AchievementGlobalMgr static char const* GetCriteriaTypeString(AchievementCriteriaTypes type); static char const* GetCriteriaTypeString(uint32 type); - static AchievementGlobalMgr* instance() - { - static AchievementGlobalMgr instance; - return &instance; - } + static AchievementGlobalMgr* instance(); AchievementCriteriaTreeList const* GetAchievementCriteriaTreesByCriteria(uint32 criteriaId) const { diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index b86f00e3295..ce8815dee07 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -45,6 +45,12 @@ AuctionHouseMgr::~AuctionHouseMgr() delete itr->second; } +AuctionHouseMgr* AuctionHouseMgr::instance() +{ + static AuctionHouseMgr instance; + return &instance; +} + AuctionHouseObject* AuctionHouseMgr::GetAuctionsMap(uint32 factionTemplateId) { if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) @@ -71,12 +77,23 @@ uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 float multiplier = CalculatePct(float(entry->DepositRate), 3); uint32 timeHr = (((time / 60) / 60) / 12); - uint32 deposit = uint32(((multiplier * MSV * count / 3) * timeHr * 3) * sWorld->getRate(RATE_AUCTION_DEPOSIT)); + uint32 deposit = uint32(MSV * multiplier * sWorld->getRate(RATE_AUCTION_DEPOSIT)); + float remainderbase = float(MSV * multiplier * sWorld->getRate(RATE_AUCTION_DEPOSIT)) - deposit; + + deposit *= timeHr * count; + + int i = count; + while (i > 0 && (remainderbase * i) != uint32(remainderbase * i)) + i--; + + if (i) + deposit += remainderbase * i * timeHr; TC_LOG_DEBUG("auctionHouse", "MSV: %u", MSV); TC_LOG_DEBUG("auctionHouse", "Items: %u", count); TC_LOG_DEBUG("auctionHouse", "Multiplier: %f", multiplier); TC_LOG_DEBUG("auctionHouse", "Deposit: %u", deposit); + TC_LOG_DEBUG("auctionHouse", "Deposit rm: %f", remainderbase * count); if (deposit < AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT)) return AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT); @@ -379,6 +396,116 @@ bool AuctionHouseMgr::RemoveAItem(ObjectGuid::LowType id, bool deleteItem) return true; } +void AuctionHouseMgr::PendingAuctionAdd(Player* player, AuctionEntry* aEntry) +{ + PlayerAuctions* thisAH; + auto itr = pendingAuctionMap.find(player->GetGUID()); + if (itr != pendingAuctionMap.end()) + thisAH = itr->second.first; + else + { + thisAH = new PlayerAuctions; + pendingAuctionMap[player->GetGUID()] = AuctionPair(thisAH, 0); + } + thisAH->push_back(aEntry); +} + +uint32 AuctionHouseMgr::PendingAuctionCount(const Player* player) const +{ + auto const itr = pendingAuctionMap.find(player->GetGUID()); + if (itr != pendingAuctionMap.end()) + return itr->second.first->size(); + + return 0; +} + +void AuctionHouseMgr::PendingAuctionProcess(Player* player) +{ + auto iterMap = pendingAuctionMap.find(player->GetGUID()); + if (iterMap == pendingAuctionMap.end()) + return; + + PlayerAuctions* thisAH = iterMap->second.first; + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + uint32 totalItems = 0; + for (auto itrAH = thisAH->begin(); itrAH != thisAH->end(); ++itrAH) + { + AuctionEntry* AH = (*itrAH); + totalItems += AH->itemCount; + } + + uint32 totaldeposit = 0; + auto itr = (*thisAH->begin()); + + if (Item* item = GetAItem(itr->itemGUIDLow)) + totaldeposit = GetAuctionDeposit(itr->auctionHouseEntry, itr->etime, item, totalItems); + + uint32 depositremain = totaldeposit; + for (auto itr = thisAH->begin(); itr != thisAH->end(); ++itr) + { + AuctionEntry* AH = (*itr); + + if (next(itr) == thisAH->end()) + AH->deposit = depositremain; + else + { + AH->deposit = totaldeposit / thisAH->size(); + depositremain -= AH->deposit; + } + + AH->DeleteFromDB(trans); + AH->SaveToDB(trans); + } + + CharacterDatabase.CommitTransaction(trans); + pendingAuctionMap.erase(player->GetGUID()); + delete thisAH; + player->ModifyMoney(-int32(totaldeposit)); +} + +void AuctionHouseMgr::UpdatePendingAuctions() +{ + for (auto itr = pendingAuctionMap.begin(); itr != pendingAuctionMap.end();) + { + ObjectGuid playerGUID = itr->first; + if (Player* player = ObjectAccessor::FindConnectedPlayer(playerGUID)) + { + // Check if there were auctions since last update process if not + if (PendingAuctionCount(player) == itr->second.second) + { + ++itr; + PendingAuctionProcess(player); + } + else + { + ++itr; + pendingAuctionMap[playerGUID].second = PendingAuctionCount(player); + } + } + else + { + // Expire any auctions that we couldn't get a deposit for + TC_LOG_WARN("auctionHouse", "Player %s was offline, unable to retrieve deposit!", playerGUID.ToString().c_str()); + PlayerAuctions* thisAH = itr->second.first; + ++itr; + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + for (auto AHitr = thisAH->begin(); AHitr != thisAH->end();) + { + AuctionEntry* AH = (*AHitr); + ++AHitr; + AH->expire_time = time(NULL); + AH->DeleteFromDB(trans); + AH->SaveToDB(trans); + } + CharacterDatabase.CommitTransaction(trans); + pendingAuctionMap.erase(playerGUID); + delete thisAH; + } + } +} + void AuctionHouseMgr::Update() { mHordeAuctions.Update(); diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index 3f747608d9e..ae9a6c1e894 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -24,6 +24,7 @@ #include "DBCStructure.h" #include "ObjectGuid.h" #include "AuctionHousePackets.h" +#include <set> class Item; class Player; @@ -63,7 +64,7 @@ enum MailAuctionAnswers AUCTION_SALE_PENDING = 6 }; -struct AuctionEntry +struct TC_GAME_API AuctionEntry { uint32 Id; ObjectGuid::LowType auctioneer; // creature low guid @@ -77,6 +78,7 @@ struct AuctionEntry time_t expire_time; ObjectGuid::LowType bidder; uint32 deposit; //deposit can be calculated only when creating auction + uint32 etime; AuctionHouseEntry const* auctionHouseEntry; // in AuctionHouse.dbc uint32 factionTemplateId; @@ -95,7 +97,7 @@ struct AuctionEntry }; //this class is used as auctionhouse instance -class AuctionHouseObject +class TC_GAME_API AuctionHouseObject { public: ~AuctionHouseObject() @@ -133,20 +135,18 @@ class AuctionHouseObject AuctionEntryMap AuctionsMap; }; -class AuctionHouseMgr +class TC_GAME_API AuctionHouseMgr { private: AuctionHouseMgr(); ~AuctionHouseMgr(); public: - static AuctionHouseMgr* instance() - { - static AuctionHouseMgr instance; - return &instance; - } + static AuctionHouseMgr* instance(); typedef std::unordered_map<ObjectGuid::LowType, Item*> ItemMap; + typedef std::vector<AuctionEntry*> PlayerAuctions; + typedef std::pair<PlayerAuctions*, uint32> AuctionPair; AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId); AuctionHouseObject* GetBidsMap(uint32 factionTemplateId); @@ -179,7 +179,10 @@ class AuctionHouseMgr void AddAItem(Item* it); bool RemoveAItem(ObjectGuid::LowType id, bool deleteItem = false); - + void PendingAuctionAdd(Player* player, AuctionEntry* aEntry); + uint32 PendingAuctionCount(const Player* player) const; + void PendingAuctionProcess(Player* player); + void UpdatePendingAuctions(); void Update(); private: @@ -188,6 +191,8 @@ class AuctionHouseMgr AuctionHouseObject mAllianceAuctions; AuctionHouseObject mNeutralAuctions; + std::map<ObjectGuid, AuctionPair> pendingAuctionMap; + ItemMap mAitems; }; diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp index eb00798ed54..1f0274572d7 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp @@ -24,6 +24,12 @@ #include "AuctionHouseBotBuyer.h" #include "AuctionHouseBotSeller.h" +AuctionBotConfig* AuctionBotConfig::instance() +{ + static AuctionBotConfig instance; + return &instance; +} + bool AuctionBotConfig::Initialize() { GetConfigFromFile(); @@ -242,6 +248,22 @@ void AuctionBotConfig::GetConfigFromFile() SetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.TradeGood.ItemLevel.Max", 0); SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL, "AuctionHouseBot.Class.Container.ItemLevel.Min", 0); SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.Container.ItemLevel.Max", 0); + + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE, "AuctionHouseBot.Class.RandomStackRatio.Consumable", 20); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER, "AuctionHouseBot.Class.RandomStackRatio.Container", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON, "AuctionHouseBot.Class.RandomStackRatio.Weapon", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM, "AuctionHouseBot.Class.RandomStackRatio.Gem", 20); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR, "AuctionHouseBot.Class.RandomStackRatio.Armor", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT, "AuctionHouseBot.Class.RandomStackRatio.Reagent", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE, "AuctionHouseBot.Class.RandomStackRatio.Projectile", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD, "AuctionHouseBot.Class.RandomStackRatio.TradeGood", 50); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC, "AuctionHouseBot.Class.RandomStackRatio.Generic", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE, "AuctionHouseBot.Class.RandomStackRatio.Recipe", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER, "AuctionHouseBot.Class.RandomStackRatio.Quiver", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST, "AuctionHouseBot.Class.RandomStackRatio.Quest", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY, "AuctionHouseBot.Class.RandomStackRatio.Key", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC, "AuctionHouseBot.Class.RandomStackRatio.Misc", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH, "AuctionHouseBot.Class.RandomStackRatio.Glyph", 0); } char const* AuctionBotConfig::GetHouseTypeName(AuctionHouseType houseType) @@ -410,6 +432,12 @@ void AuctionHouseBot::Rebuild(bool all) } } +AuctionHouseBot* AuctionHouseBot::instance() +{ + static AuctionHouseBot instance; + return &instance; +} + void AuctionHouseBot::Update() { // nothing do... diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouseBot/AuctionHouseBot.h index 63641fc7da2..1a438e01cdb 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBot.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.h @@ -137,6 +137,21 @@ enum AuctionBotConfigUInt32Values CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL, CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL, CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH, CONFIG_UINT32_AHBOT_UINT32_COUNT }; @@ -181,7 +196,7 @@ enum AuctionBotConfigFloatValues }; // All basic config data used by other AHBot classes for self-configure. -class AuctionBotConfig +class TC_GAME_API AuctionBotConfig { private: AuctionBotConfig(): _itemsPerCycleBoost(1000), _itemsPerCycleNormal(20) {} @@ -190,11 +205,7 @@ private: AuctionBotConfig& operator=(const AuctionBotConfig&); public: - static AuctionBotConfig* instance() - { - static AuctionBotConfig instance; - return &instance; - } + static AuctionBotConfig* instance(); bool Initialize(); const std::string& GetAHBotIncludes() const { return _AHBotIncludes; } @@ -259,7 +270,7 @@ typedef AuctionHouseBotStatusInfoPerType AuctionHouseBotStatusInfo[MAX_AUCTION_H // This class handle both Selling and Buying method // (holder of AuctionBotBuyer and AuctionBotSeller objects) -class AuctionHouseBot +class TC_GAME_API AuctionHouseBot { private: AuctionHouseBot(); @@ -268,11 +279,7 @@ private: AuctionHouseBot& operator=(const AuctionHouseBot&); public: - static AuctionHouseBot* instance() - { - static AuctionHouseBot instance; - return &instance; - } + static AuctionHouseBot* instance(); void Update(); void Initialize(); diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h index e1b6b425c48..979f73c0099 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h @@ -67,7 +67,7 @@ private: // This class handle all Buyer method // (holder of AuctionBotConfig for each auction house type) -class AuctionBotBuyer : public AuctionBotAgent +class TC_GAME_API AuctionBotBuyer : public AuctionBotAgent { public: AuctionBotBuyer(); diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index d3215f10db5..2800167add7 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -533,6 +533,23 @@ void AuctionBotSeller::LoadItemsQuantity(SellerConfiguration& config) config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_GLYPH, 0); // ============================================================================================ + // Set Stack Quantities + config.SetRandomStackRatioPerClass(ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_REAGENT, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_GENERIC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_QUIVER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_KEY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_MISCELLANEOUS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_GLYPH, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH)); + // Set the best value to get nearest amount of items wanted for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j) { @@ -719,6 +736,15 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf bidp = urand(basePrice - range, basePrice + range) + 1; } +// Determines the stack size to use for the item +uint32 AuctionBotSeller::GetStackSizeForItem(ItemTemplate const* itemProto, SellerConfiguration& config) const +{ + if (config.GetRandomStackRatioPerClass(ItemClass(itemProto->GetClass())) > urand(0, 99)) + return urand(1, itemProto->GetMaxStackSize()); + else + return 1; +} + // Determine the multiplier for the sell price of any weapon without a buy price. uint32 AuctionBotSeller::GetSellModifier(ItemTemplate const* prototype) { @@ -950,7 +976,7 @@ void AuctionBotSeller::AddNewAuctions(SellerConfiguration& config) continue; } - uint32 stackCount = urand(1, prototype->GetMaxStackSize()); + uint32 stackCount = GetStackSizeForItem(prototype, config); Item* item = Item::CreateItem(itemId, stackCount); if (!item) diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h index 7168915ec75..3e6f263707f 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h @@ -33,12 +33,13 @@ typedef std::vector<std::vector<uint32>> AllItemsArray; struct SellerItemClassInfo { - SellerItemClassInfo(): AmountOfItems(0), MissItems(0), Quantity(0), PriceRatio(0) {} + SellerItemClassInfo(): AmountOfItems(0), MissItems(0), Quantity(0), PriceRatio(0), RandomStackRatio(100) {} uint32 AmountOfItems; uint32 MissItems; uint32 Quantity; uint32 PriceRatio; + uint32 RandomStackRatio; }; struct SellerItemInfo @@ -102,6 +103,8 @@ public: uint32 GetPriceRatioPerQuality(AuctionQuality quality) const { return _ItemInfo[quality].PriceRatio; } void SetPriceRatioPerClass(ItemClass item, uint32 value) { _ItemInfo[0].ItemClassInfos[item].PriceRatio = value; } uint32 GetPriceRatioPerClass(ItemClass item) const { return _ItemInfo[0].ItemClassInfos[item].PriceRatio; } + void SetRandomStackRatioPerClass(ItemClass item, uint32 value) { _ItemInfo[0].ItemClassInfos[item].RandomStackRatio = value; } + uint32 GetRandomStackRatioPerClass(ItemClass item) const { return _ItemInfo[0].ItemClassInfos[item].RandomStackRatio; } private: AuctionHouseType _houseType; @@ -112,7 +115,7 @@ private: // This class handle all Selling method // (holder of AHB_Seller_Config data for each auction house type) -class AuctionBotSeller : public AuctionBotAgent +class TC_GAME_API AuctionBotSeller : public AuctionBotAgent { public: typedef std::vector<uint32> ItemPool; @@ -139,6 +142,7 @@ private: uint32 SetStat(SellerConfiguration& config); bool GetItemsToSell(SellerConfiguration& config, ItemsToSellArray& itemsToSellArray, AllItemsArray const& addedItem); void SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyp, uint32& bidp, uint32 stackcnt); + uint32 GetStackSizeForItem(ItemTemplate const* itemProto, SellerConfiguration& config) const; void LoadItemsQuantity(SellerConfiguration& config); static uint32 GetBuyModifier(ItemTemplate const* prototype); static uint32 GetSellModifier(ItemTemplate const* itemProto); diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index 0159ba95eeb..ad5770e2ad0 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -78,7 +78,7 @@ class BfGraveyard; typedef std::vector<BfGraveyard*> GraveyardVect; typedef std::map<ObjectGuid, time_t> PlayerTimerMap; -class BfCapturePoint +class TC_GAME_API BfCapturePoint { public: BfCapturePoint(Battlefield* bf); @@ -146,7 +146,7 @@ class BfCapturePoint ObjectGuid m_capturePointGUID; }; -class BfGraveyard +class TC_GAME_API BfGraveyard { public: BfGraveyard(Battlefield* Bf); @@ -193,7 +193,7 @@ class BfGraveyard Battlefield* m_Bf; }; -class Battlefield : public ZoneScript +class TC_GAME_API Battlefield : public ZoneScript { friend class BattlefieldMgr; diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp index 8e105f95604..b92b2e64318 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.cpp +++ b/src/server/game/Battlefield/BattlefieldMgr.cpp @@ -32,6 +32,12 @@ BattlefieldMgr::~BattlefieldMgr() _battlefieldMap.clear(); } +BattlefieldMgr* BattlefieldMgr::instance() +{ + static BattlefieldMgr instance; + return &instance; +} + void BattlefieldMgr::InitBattlefield() { Battlefield* wg = new BattlefieldWG(); diff --git a/src/server/game/Battlefield/BattlefieldMgr.h b/src/server/game/Battlefield/BattlefieldMgr.h index b68e4df46f7..623f1dadb91 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.h +++ b/src/server/game/Battlefield/BattlefieldMgr.h @@ -24,14 +24,10 @@ class Player; class ZoneScript; // class to handle player enter / leave / areatrigger / GO use events -class BattlefieldMgr +class TC_GAME_API BattlefieldMgr { public: - static BattlefieldMgr* instance() - { - static BattlefieldMgr instance; - return &instance; - } + static BattlefieldMgr* instance(); // create battlefield events void InitBattlefield(); diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 087f20e9224..e849c2f33d1 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -266,7 +266,7 @@ class WintergraspCapturePoint : public BfCapturePoint * WinterGrasp Battlefield * * ######################### */ -class BattlefieldWG : public Battlefield +class TC_GAME_API BattlefieldWG : public Battlefield { public: ~BattlefieldWG(); @@ -1098,7 +1098,7 @@ StaticWintergraspWorkshopInfo const WorkshopData[WG_MAX_WORKSHOP] = // ******************************************************************** // Structure for different buildings that can be destroyed during battle -struct BfWGGameObjectBuilding +struct TC_GAME_API BfWGGameObjectBuilding { private: // WG object @@ -1150,7 +1150,7 @@ public: }; // Structure for the 6 workshop -struct WintergraspWorkshop +struct TC_GAME_API WintergraspWorkshop { private: BattlefieldWG* _wg; // Pointer to wintergrasp diff --git a/src/server/game/Battlegrounds/Arena.h b/src/server/game/Battlegrounds/Arena.h index d0ed3a86af7..80745d2658c 100644 --- a/src/server/game/Battlegrounds/Arena.h +++ b/src/server/game/Battlegrounds/Arena.h @@ -36,7 +36,7 @@ enum ArenaWorldStates ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD = 3601 }; -class Arena : public Battleground +class TC_GAME_API Arena : public Battleground { protected: Arena(); diff --git a/src/server/game/Battlegrounds/ArenaScore.h b/src/server/game/Battlegrounds/ArenaScore.h index 683b216dd42..c9a9419dc2c 100644 --- a/src/server/game/Battlegrounds/ArenaScore.h +++ b/src/server/game/Battlegrounds/ArenaScore.h @@ -23,7 +23,7 @@ #include "Player.h" #include "ObjectAccessor.h" -struct ArenaScore : public BattlegroundScore +struct TC_GAME_API ArenaScore : public BattlegroundScore { friend class Arena; @@ -43,7 +43,7 @@ struct ArenaScore : public BattlegroundScore uint8 TeamId; // BattlegroundTeamId }; -struct ArenaTeamScore +struct TC_GAME_API ArenaTeamScore { friend class Arena; friend class Battleground; diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h index db5d63a8915..df966a632cb 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.h +++ b/src/server/game/Battlegrounds/ArenaTeam.h @@ -81,7 +81,7 @@ enum ArenaTeamTypes ARENA_TEAM_5v5 = 5 }; -struct ArenaTeamMember +struct TC_GAME_API ArenaTeamMember { ObjectGuid Guid; std::string Name; @@ -109,7 +109,7 @@ struct ArenaTeamStats #define MAX_ARENA_SLOT 3 // 0..2 slots -class ArenaTeam +class TC_GAME_API ArenaTeam { public: ArenaTeam(); diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp index 3f3502b9aa6..ecf0ae6c6d1 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp @@ -33,6 +33,12 @@ ArenaTeamMgr::~ArenaTeamMgr() delete itr->second; } +ArenaTeamMgr* ArenaTeamMgr::instance() +{ + static ArenaTeamMgr instance; + return &instance; +} + // Arena teams collection ArenaTeam* ArenaTeamMgr::GetArenaTeamById(uint32 arenaTeamId) const { diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h index 8a36dfa7324..131a2cc8899 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.h +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h @@ -20,18 +20,14 @@ #include "ArenaTeam.h" -class ArenaTeamMgr +class TC_GAME_API ArenaTeamMgr { private: ArenaTeamMgr(); ~ArenaTeamMgr(); public: - static ArenaTeamMgr* instance() - { - static ArenaTeamMgr instance; - return &instance; - } + static ArenaTeamMgr* instance(); typedef std::unordered_map<uint32, ArenaTeam*> ArenaTeamContainer; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 1f33b0d5d7c..cb2fb68d9dd 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -232,7 +232,7 @@ This class is used to: 3. some certain cases, same for all battlegrounds 4. It has properties same for all battlegrounds */ -class Battleground +class TC_GAME_API Battleground { public: Battleground(); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 57f61c0e195..514242011b3 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -75,6 +75,12 @@ void BattlegroundMgr::DeleteAllBattlegrounds() bgDataStore.clear(); } +BattlegroundMgr* BattlegroundMgr::instance() +{ + static BattlegroundMgr instance; + return &instance; +} + // used to update running battlegrounds, and delete finished ones void BattlegroundMgr::Update(uint32 diff) { diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index 354f37b8cd8..d35b239a725 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -67,18 +67,14 @@ namespace WorldPackets } } -class BattlegroundMgr +class TC_GAME_API BattlegroundMgr { private: BattlegroundMgr(); ~BattlegroundMgr(); public: - static BattlegroundMgr* instance() - { - static BattlegroundMgr instance; - return &instance; - } + static BattlegroundMgr* instance(); void Update(uint32 diff); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h index 9291adf9e8d..5eac6a8f51a 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.h +++ b/src/server/game/Battlegrounds/BattlegroundQueue.h @@ -72,7 +72,7 @@ enum BattlegroundQueueInvitationType }; class Battleground; -class BattlegroundQueue +class TC_GAME_API BattlegroundQueue { public: BattlegroundQueue(); @@ -142,7 +142,7 @@ class BattlegroundQueue This class is used to invite player to BG again, when minute lasts from his first invitation it is capable to solve all possibilities */ -class BGQueueInviteEvent : public BasicEvent +class TC_GAME_API BGQueueInviteEvent : public BasicEvent { public: BGQueueInviteEvent(ObjectGuid pl_guid, uint32 BgInstanceGUID, BattlegroundTypeId BgTypeId, uint8 arenaType, uint32 removeTime) : @@ -165,7 +165,7 @@ class BGQueueInviteEvent : public BasicEvent We must store removeInvite time in case player left queue and joined and is invited again We must store bgQueueTypeId, because battleground can be deleted already, when player entered it */ -class BGQueueRemoveEvent : public BasicEvent +class TC_GAME_API BGQueueRemoveEvent : public BasicEvent { public: BGQueueRemoveEvent(ObjectGuid pl_guid, uint32 bgInstanceGUID, BattlegroundTypeId BgTypeId, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime) diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index f439e0efc9a..df0d2b7cc2a 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -8,219 +8,63 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources_Accounts Accounts/*.cpp Accounts/*.h) -file(GLOB_RECURSE sources_Achievements Achievements/*.cpp Achievements/*.h) -file(GLOB_RECURSE sources_Addons Addons/*.cpp Addons/*.h) -file(GLOB_RECURSE sources_AI AI/*.cpp AI/*.h) -file(GLOB_RECURSE sources_AuctionHouse AuctionHouse/*.cpp AuctionHouse/*.h) -file(GLOB_RECURSE sources_AuctionHouseBot AuctionHouseBot/*.cpp AuctionHouseBot/*.h) -file(GLOB_RECURSE sources_Battlefield Battlefield/*.cpp Battlefield/*.h) -file(GLOB_RECURSE sources_Battlegrounds Battlegrounds/*.cpp Battlegrounds/*.h) -file(GLOB_RECURSE sources_BattlePets BattlePets/*.cpp BattlePets/*.h) -file(GLOB_RECURSE sources_Calendar Calendar/*.cpp Calendar/*.h) -file(GLOB_RECURSE sources_Chat Chat/*.cpp Chat/*.h) -file(GLOB_RECURSE sources_Combat Combat/*.cpp Combat/*.h) -file(GLOB_RECURSE sources_Conditions Conditions/*.cpp Conditions/*.h) -file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h) -file(GLOB_RECURSE sources_DungeonFinding DungeonFinding/*.cpp DungeonFinding/*.h) -file(GLOB_RECURSE sources_Entities Entities/*.cpp Entities/*.h) -file(GLOB_RECURSE sources_Events Events/*.cpp Events/*.h) -file(GLOB_RECURSE sources_Garrison Garrison/*.cpp Garrison/*.h) -file(GLOB_RECURSE sources_Globals Globals/*.cpp Globals/*.h) -file(GLOB_RECURSE sources_Grids Grids/*.cpp Grids/*.h) -file(GLOB_RECURSE sources_Groups Groups/*.cpp Groups/*.h) -file(GLOB_RECURSE sources_Guilds Guilds/*.cpp Guilds/*.h) -file(GLOB_RECURSE sources_Handlers Handlers/*.cpp Handlers/*.h) -file(GLOB_RECURSE sources_Instances Instances/*.cpp Instances/*.h) -file(GLOB_RECURSE sources_Loot Loot/*.cpp Loot/*.h) -file(GLOB_RECURSE sources_Mails Mails/*.cpp Mails/*.h) -file(GLOB_RECURSE sources_Maps Maps/*.cpp Maps/*.h) -file(GLOB_RECURSE sources_Miscellaneous Miscellaneous/*.cpp Miscellaneous/*.h) -file(GLOB_RECURSE sources_Movement Movement/*.cpp Movement/*.h) -file(GLOB_RECURSE sources_OutdoorPvP OutdoorPvP/*.cpp OutdoorPvP/*.h) -file(GLOB_RECURSE sources_Pools Pools/*.cpp Pools/*.h) -file(GLOB_RECURSE sources_Quests Quests/*.cpp Quests/*.h) -file(GLOB_RECURSE sources_Reputation Reputation/*.cpp Reputation/*.h) -file(GLOB_RECURSE sources_Scripting Scripting/*.cpp Scripting/*.h) -file(GLOB_RECURSE sources_Server Server/*.cpp Server/*.h) -file(GLOB_RECURSE sources_Skills Skills/*.cpp Skills/*.h) -file(GLOB_RECURSE sources_Spells Spells/*.cpp Spells/*.h) -file(GLOB_RECURSE sources_Support Support/*.cpp Support/*.h) -file(GLOB_RECURSE sources_Texts Texts/*.cpp Texts/*.h) -file(GLOB_RECURSE sources_Tools Tools/*.cpp Tools/*.h) -file(GLOB_RECURSE sources_Warden Warden/*.cpp Warden/*.h) -file(GLOB_RECURSE sources_Weather Weather/*.cpp Weather/*.h) -file(GLOB_RECURSE sources_World World/*.cpp World/*.h) - -# Create game-libary +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) if (USE_COREPCH) - set(game_STAT_PCH_HDR PrecompiledHeaders/gamePCH.h) - set(game_STAT_PCH_SRC PrecompiledHeaders/gamePCH.cpp) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/gamePCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/gamePCH.cpp) endif () -set(game_STAT_SRCS - ${game_STAT_SRCS} - ${sources_Accounts} - ${sources_Achievements} - ${sources_Addons} - ${sources_AI} - ${sources_AuctionHouse} - ${sources_AuctionHouseBot} - ${sources_Battlefield} - ${sources_Battlegrounds} - ${sources_BattlePets} - ${sources_Calendar} - ${sources_Chat} - ${sources_Combat} - ${sources_Conditions} - ${sources_DataStores} - ${sources_DungeonFinding} - ${sources_Entities} - ${sources_Events} - ${sources_Garrison} - ${sources_Globals} - ${sources_Grids} - ${sources_Groups} - ${sources_Guilds} - ${sources_Handlers} - ${sources_Instances} - ${sources_Loot} - ${sources_Mails} - ${sources_Maps} - ${sources_Miscellaneous} - ${sources_Movement} - ${sources_OutdoorPvP} - ${sources_Pools} - ${sources_Quests} - ${sources_Reputation} - ${sources_Scripting} - ${sources_Server} - ${sources_Skills} - ${sources_Spells} - ${sources_Support} - ${sources_Texts} - ${sources_Tools} - ${sources_Warden} - ${sources_Weather} - ${sources_World} -) +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/Accounts - ${CMAKE_CURRENT_SOURCE_DIR}/Achievements - ${CMAKE_CURRENT_SOURCE_DIR}/Addons - ${CMAKE_CURRENT_SOURCE_DIR}/AI - ${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI - ${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI - ${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts - ${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse - ${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouseBot - ${CMAKE_CURRENT_SOURCE_DIR}/Battlefield - ${CMAKE_CURRENT_SOURCE_DIR}/Battlefield/Zones - ${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds - ${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds/Zones - ${CMAKE_CURRENT_SOURCE_DIR}/BattlePets - ${CMAKE_CURRENT_SOURCE_DIR}/Calendar - ${CMAKE_CURRENT_SOURCE_DIR}/Chat - ${CMAKE_CURRENT_SOURCE_DIR}/Chat/Channels - ${CMAKE_CURRENT_SOURCE_DIR}/Combat - ${CMAKE_CURRENT_SOURCE_DIR}/Conditions - ${CMAKE_CURRENT_SOURCE_DIR}/DataStores - ${CMAKE_CURRENT_SOURCE_DIR}/DungeonFinding - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/AreaTrigger - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Corpse - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/DynamicObject - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/GameObject - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Item - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Item/Container - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Object - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Object/Updates - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Pet - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Player - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Taxi - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Totem - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Unit - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Vehicle - ${CMAKE_CURRENT_SOURCE_DIR}/Events - ${CMAKE_CURRENT_SOURCE_DIR}/Garrison - ${CMAKE_CURRENT_SOURCE_DIR}/Globals - ${CMAKE_CURRENT_SOURCE_DIR}/Grids - ${CMAKE_CURRENT_SOURCE_DIR}/Grids/Cells - ${CMAKE_CURRENT_SOURCE_DIR}/Grids/Notifiers - ${CMAKE_CURRENT_SOURCE_DIR}/Groups - ${CMAKE_CURRENT_SOURCE_DIR}/Guilds - ${CMAKE_CURRENT_SOURCE_DIR}/Handlers - ${CMAKE_CURRENT_SOURCE_DIR}/Instances - ${CMAKE_CURRENT_SOURCE_DIR}/Loot - ${CMAKE_CURRENT_SOURCE_DIR}/Mails - ${CMAKE_CURRENT_SOURCE_DIR}/Maps - ${CMAKE_CURRENT_SOURCE_DIR}/Miscellaneous - ${CMAKE_CURRENT_SOURCE_DIR}/Movement - ${CMAKE_CURRENT_SOURCE_DIR}/Movement/MovementGenerators - ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Spline - ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Waypoints - ${CMAKE_CURRENT_SOURCE_DIR}/OutdoorPvP - ${CMAKE_CURRENT_SOURCE_DIR}/Pools - ${CMAKE_CURRENT_SOURCE_DIR}/Quests - ${CMAKE_CURRENT_SOURCE_DIR}/Reputation - ${CMAKE_CURRENT_SOURCE_DIR}/Scripting - ${CMAKE_CURRENT_SOURCE_DIR}/Server - ${CMAKE_CURRENT_SOURCE_DIR}/Server/Packets - ${CMAKE_CURRENT_SOURCE_DIR}/Server/Protocol - ${CMAKE_CURRENT_SOURCE_DIR}/Skills - ${CMAKE_CURRENT_SOURCE_DIR}/Spells - ${CMAKE_CURRENT_SOURCE_DIR}/Spells/Auras - ${CMAKE_CURRENT_SOURCE_DIR}/Support - ${CMAKE_CURRENT_SOURCE_DIR}/Texts - ${CMAKE_CURRENT_SOURCE_DIR}/Tickets - ${CMAKE_CURRENT_SOURCE_DIR}/Tools - ${CMAKE_CURRENT_SOURCE_DIR}/Warden - ${CMAKE_CURRENT_SOURCE_DIR}/Warden/Modules - ${CMAKE_CURRENT_SOURCE_DIR}/Weather - ${CMAKE_CURRENT_SOURCE_DIR}/World - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/common/Collision - ${CMAKE_SOURCE_DIR}/src/common/Collision/Management - ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps - ${CMAKE_SOURCE_DIR}/src/common/Collision/Models - ${CMAKE_SOURCE_DIR}/src/common/Configuration - ${CMAKE_SOURCE_DIR}/src/common/Cryptography - ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/server/database - ${CMAKE_SOURCE_DIR}/src/server/database/Database - ${CMAKE_SOURCE_DIR}/src/server/ipc - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Networking - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} - ${ZMQ_INCLUDE_DIR} +add_definitions(-DTRINITY_API_EXPORT_GAME) + +add_library(game + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -add_library(game STATIC - ${game_STAT_PCH_SRC} - ${game_STAT_SRCS} -) +target_include_directories(game + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +target_link_libraries(game + PUBLIC + shared + Detour + PRIVATE + efsw) + +set_target_properties(game + PROPERTIES + FOLDER + "server") + +if( BUILD_SHARED_LIBS ) + if( UNIX ) + install(TARGETS game + LIBRARY + DESTINATION lib) + elseif( WIN32 ) + install(TARGETS game + RUNTIME + DESTINATION "${CMAKE_INSTALL_PREFIX}") + endif() +endif() # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(game ${game_STAT_PCH_HDR} ${game_STAT_PCH_SRC}) + add_cxx_pch(game ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif () diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index 83bcdf733e2..92df0ea6ea2 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -46,6 +46,12 @@ CalendarMgr::~CalendarMgr() delete *itr2; } +CalendarMgr* CalendarMgr::instance() +{ + static CalendarMgr instance; + return &instance; +} + void CalendarMgr::LoadFromDB() { uint32 count = 0; diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h index e22482323c7..e7594823d51 100644 --- a/src/server/game/Calendar/CalendarMgr.h +++ b/src/server/game/Calendar/CalendarMgr.h @@ -128,7 +128,7 @@ enum CalendarError #define CALENDAR_MAX_INVITES 100 #define CALENDAR_DEFAULT_RESPONSE_TIME 946684800 // 01/01/2000 00:00:00 -struct CalendarInvite +struct TC_GAME_API CalendarInvite { public: CalendarInvite(CalendarInvite const& calendarInvite, uint64 inviteId, uint64 eventId) @@ -188,7 +188,7 @@ struct CalendarInvite std::string _note; }; -struct CalendarEvent +struct TC_GAME_API CalendarEvent { public: CalendarEvent(CalendarEvent const& calendarEvent, uint64 eventId) @@ -268,7 +268,7 @@ typedef std::vector<CalendarInvite*> CalendarInviteStore; typedef std::set<CalendarEvent*> CalendarEventStore; typedef std::map<uint64 /* eventID */, CalendarInviteStore > CalendarEventInviteStore; -class CalendarMgr +class TC_GAME_API CalendarMgr { private: CalendarMgr(); @@ -283,11 +283,7 @@ class CalendarMgr uint64 _maxInviteId; public: - static CalendarMgr* instance() - { - static CalendarMgr instance; - return &instance; - } + static CalendarMgr* instance(); void LoadFromDB(); diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 5683a876f6d..f309f3c7936 100644 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -123,7 +123,7 @@ enum ChannelMemberFlags // 0x80 }; -class Channel +class TC_GAME_API Channel { struct PlayerInfo { diff --git a/src/server/game/Chat/Channels/ChannelMgr.h b/src/server/game/Chat/Channels/ChannelMgr.h index 835a4cdcaaa..cdaf6b8565c 100644 --- a/src/server/game/Chat/Channels/ChannelMgr.h +++ b/src/server/game/Chat/Channels/ChannelMgr.h @@ -24,7 +24,7 @@ #define MAX_CHANNEL_NAME_STR 0x31 #define MAX_CHANNEL_PASS_STR 31 -class ChannelMgr +class TC_GAME_API ChannelMgr { typedef std::map<std::wstring, Channel*> ChannelMap; diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 63166b6ae91..226ec1fe6ad 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -37,7 +37,7 @@ class WorldObject; struct GameTele; -class ChatCommand +class TC_GAME_API ChatCommand { typedef bool(*pHandler)(ChatHandler*, char const*); @@ -53,7 +53,7 @@ class ChatCommand std::vector<ChatCommand> ChildCommands; }; -class ChatHandler +class TC_GAME_API ChatHandler { public: WorldSession* GetSession() { return m_session; } @@ -154,7 +154,7 @@ class ChatHandler bool sentErrorMessage; }; -class CliHandler : public ChatHandler +class TC_GAME_API CliHandler : public ChatHandler { public: typedef void Print(void*, char const*); diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h index 1a0310118d2..ae6932b5d27 100644 --- a/src/server/game/Chat/ChatLink.h +++ b/src/server/game/Chat/ChatLink.h @@ -35,7 +35,7 @@ class Quest; /////////////////////////////////////////////////////////////////////////////////////////////////// // ChatLink - abstract base class for various links -class ChatLink +class TC_GAME_API ChatLink { public: ChatLink() : _color(0), _startPos(0), _endPos(0) { } @@ -55,7 +55,7 @@ protected: }; // ItemChatLink - link to item -class ItemChatLink : public ChatLink +class TC_GAME_API ItemChatLink : public ChatLink { public: ItemChatLink() : ChatLink(), _item(NULL), _suffix(NULL), _property(NULL) @@ -76,7 +76,7 @@ protected: }; // QuestChatLink - link to quest -class QuestChatLink : public ChatLink +class TC_GAME_API QuestChatLink : public ChatLink { public: QuestChatLink() : ChatLink(), _quest(nullptr), _questLevel(0) { } @@ -89,7 +89,7 @@ protected: }; // SpellChatLink - link to quest -class SpellChatLink : public ChatLink +class TC_GAME_API SpellChatLink : public ChatLink { public: SpellChatLink() : ChatLink(), _spell(nullptr) { } @@ -101,7 +101,7 @@ protected: }; // AchievementChatLink - link to quest -class AchievementChatLink : public ChatLink +class TC_GAME_API AchievementChatLink : public ChatLink { public: AchievementChatLink() : ChatLink(), _guid(0), _achievement(NULL) @@ -118,7 +118,7 @@ protected: }; // TradeChatLink - link to trade info -class TradeChatLink : public SpellChatLink +class TC_GAME_API TradeChatLink : public SpellChatLink { public: TradeChatLink() : SpellChatLink(), _minSkillLevel(0), _maxSkillLevel(0), _guid(0) { } @@ -131,7 +131,7 @@ private: }; // TalentChatLink - link to talent -class TalentChatLink : public SpellChatLink +class TC_GAME_API TalentChatLink : public SpellChatLink { public: TalentChatLink() : SpellChatLink(), _talentId(0), _rankId(0) { } @@ -143,7 +143,7 @@ private: }; // EnchantmentChatLink - link to enchantment -class EnchantmentChatLink : public SpellChatLink +class TC_GAME_API EnchantmentChatLink : public SpellChatLink { public: EnchantmentChatLink() : SpellChatLink() { } @@ -151,7 +151,7 @@ public: }; // GlyphChatLink - link to glyph -class GlyphChatLink : public SpellChatLink +class TC_GAME_API GlyphChatLink : public SpellChatLink { public: GlyphChatLink() : SpellChatLink(), _slotId(0), _glyph(NULL) { } @@ -161,7 +161,7 @@ private: GlyphPropertiesEntry const* _glyph; }; -class LinkExtractor +class TC_GAME_API LinkExtractor { public: explicit LinkExtractor(const char* msg); diff --git a/src/server/game/Combat/HostileRefManager.h b/src/server/game/Combat/HostileRefManager.h index 96152ed46f7..855f9e3d272 100644 --- a/src/server/game/Combat/HostileRefManager.h +++ b/src/server/game/Combat/HostileRefManager.h @@ -29,7 +29,7 @@ class SpellInfo; //================================================= -class HostileRefManager : public RefManager<Unit, ThreatManager> +class TC_GAME_API HostileRefManager : public RefManager<Unit, ThreatManager> { private: Unit* iOwner; diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h index 7d20e99c128..8b28779569a 100644 --- a/src/server/game/Combat/ThreatManager.h +++ b/src/server/game/Combat/ThreatManager.h @@ -39,14 +39,14 @@ class SpellInfo; //============================================================== // Class to calculate the real threat based -struct ThreatCalcHelper +struct TC_GAME_API ThreatCalcHelper { static float calcThreat(Unit* hatedUnit, Unit* hatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = NULL); static bool isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* threatSpell = NULL); }; //============================================================== -class HostileReference : public Reference<Unit, ThreatManager> +class TC_GAME_API HostileReference : public Reference<Unit, ThreatManager> { public: HostileReference(Unit* refUnit, ThreatManager* threatManager, float threat); @@ -141,7 +141,7 @@ class HostileReference : public Reference<Unit, ThreatManager> //============================================================== class ThreatManager; -class ThreatContainer +class TC_GAME_API ThreatContainer { friend class ThreatManager; @@ -198,7 +198,7 @@ class ThreatContainer //================================================= -class ThreatManager +class TC_GAME_API ThreatManager { public: friend class HostileReference; diff --git a/src/server/game/Combat/UnitEvents.h b/src/server/game/Combat/UnitEvents.h index e501cdaa4a2..f50edcf3c7d 100644 --- a/src/server/game/Combat/UnitEvents.h +++ b/src/server/game/Combat/UnitEvents.h @@ -81,7 +81,7 @@ class UnitBaseEvent //============================================================== -class ThreatRefStatusChangeEvent : public UnitBaseEvent +class TC_GAME_API ThreatRefStatusChangeEvent : public UnitBaseEvent { private: HostileReference* iHostileReference; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 3dfbb2a12e1..c0c4c7c485c 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -926,6 +926,12 @@ bool ConditionMgr::IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 return true; } +ConditionMgr* ConditionMgr::instance() +{ + static ConditionMgr instance; + return &instance; +} + void ConditionMgr::LoadConditions(bool isReload) { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 601dc8dbda9..db5b78215b3 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -178,7 +178,7 @@ enum MaxConditionTargets MAX_CONDITION_TARGETS = 3 }; -struct ConditionSourceInfo +struct TC_GAME_API ConditionSourceInfo { WorldObject* mConditionTargets[MAX_CONDITION_TARGETS]; // an array of targets available for conditions Condition const* mLastFailedCondition; @@ -191,7 +191,7 @@ struct ConditionSourceInfo } }; -struct Condition +struct TC_GAME_API Condition { ConditionSourceType SourceType; //SourceTypeOrReferenceId uint32 SourceGroup; @@ -243,18 +243,14 @@ typedef std::unordered_map<uint32, ConditionsByEntryMap> ConditionEntriesByCreat typedef std::unordered_map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionsByEntryMap> SmartEventConditionContainer; typedef std::unordered_map<uint32, ConditionContainer> ConditionReferenceContainer;//only used for references -class ConditionMgr +class TC_GAME_API ConditionMgr { private: ConditionMgr(); ~ConditionMgr(); public: - static ConditionMgr* instance() - { - static ConditionMgr instance; - return &instance; - } + static ConditionMgr* instance(); void LoadConditions(bool isReload = false); bool isConditionTypeValid(Condition* cond) const; diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h index e74b7a9c319..cae1e0329e8 100644 --- a/src/server/game/Conditions/DisableMgr.h +++ b/src/server/game/Conditions/DisableMgr.h @@ -57,11 +57,11 @@ enum MMapDisableTypes namespace DisableMgr { - void LoadDisables(); - bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0); - void CheckQuestDisables(); - bool IsVMAPDisabledFor(uint32 entry, uint8 flags); - bool IsPathfindingEnabled(uint32 mapId); + TC_GAME_API void LoadDisables(); + TC_GAME_API bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0); + TC_GAME_API void CheckQuestDisables(); + TC_GAME_API bool IsVMAPDisabledFor(uint32 entry, uint8 flags); + TC_GAME_API bool IsPathfindingEnabled(uint32 mapId); } #endif //TRINITY_DISABLEMGR_H diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 91f770d3c13..09799921258 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -187,6 +187,12 @@ inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, D stores[storage->GetHash()] = storage; } +DB2Manager& DB2Manager::Instance() +{ + static DB2Manager instance; + return instance; +} + void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 5c7c4128137..5088b750de4 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -24,96 +24,96 @@ #include <boost/regex.hpp> #include <array> -extern DB2Storage<AchievementEntry> sAchievementStore; -extern DB2Storage<AuctionHouseEntry> sAuctionHouseStore; -extern DB2Storage<BarberShopStyleEntry> sBarberShopStyleStore; -extern DB2Storage<BattlePetBreedQualityEntry> sBattlePetBreedQualityStore; -extern DB2Storage<BattlePetBreedStateEntry> sBattlePetBreedStateStore; -extern DB2Storage<BattlePetSpeciesEntry> sBattlePetSpeciesStore; -extern DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore; -extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore; -extern DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore; -extern DB2Storage<CinematicSequencesEntry> sCinematicSequencesStore; -extern DB2Storage<CreatureDisplayInfoEntry> sCreatureDisplayInfoStore; -extern DB2Storage<CreatureTypeEntry> sCreatureTypeStore; -extern DB2Storage<CriteriaEntry> sCriteriaStore; -extern DB2Storage<CriteriaTreeEntry> sCriteriaTreeStore; -extern DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore; -extern DB2Storage<DestructibleModelDataEntry> sDestructibleModelDataStore; -extern DB2Storage<DurabilityQualityEntry> sDurabilityQualityStore; -extern DB2Storage<GameObjectsEntry> sGameObjectsStore; -extern DB2Storage<GameTablesEntry> sGameTablesStore; -extern DB2Storage<GarrAbilityEntry> sGarrAbilityStore; -extern DB2Storage<GarrBuildingEntry> sGarrBuildingStore; -extern DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore; -extern DB2Storage<GarrClassSpecEntry> sGarrClassSpecStore; -extern DB2Storage<GarrFollowerEntry> sGarrFollowerStore; -extern DB2Storage<GarrFollowerXAbilityEntry> sGarrFollowerXAbilityStore; -extern DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore; -extern DB2Storage<GarrPlotEntry> sGarrPlotStore; -extern DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore; -extern DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore; -extern DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore; -extern DB2Storage<GlyphSlotEntry> sGlyphSlotStore; -extern DB2Storage<GuildPerkSpellsEntry> sGuildPerkSpellsStore; -extern DB2Storage<HeirloomEntry> sHeirloomStore; -extern DB2Storage<HolidaysEntry> sHolidaysStore; -extern DB2Storage<ImportPriceArmorEntry> sImportPriceArmorStore; -extern DB2Storage<ImportPriceQualityEntry> sImportPriceQualityStore; -extern DB2Storage<ImportPriceShieldEntry> sImportPriceShieldStore; -extern DB2Storage<ImportPriceWeaponEntry> sImportPriceWeaponStore; -extern DB2Storage<ItemClassEntry> sItemClassStore; -extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore; -extern DB2Storage<ItemDisenchantLootEntry> sItemDisenchantLootStore; -extern DB2Storage<ItemEffectEntry> sItemEffectStore; -extern DB2Storage<ItemEntry> sItemStore; -extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore; -extern DB2Storage<ItemLimitCategoryEntry> sItemLimitCategoryStore; -extern DB2Storage<ItemPriceBaseEntry> sItemPriceBaseStore; -extern DB2Storage<ItemRandomPropertiesEntry> sItemRandomPropertiesStore; -extern DB2Storage<ItemRandomSuffixEntry> sItemRandomSuffixStore; -extern DB2Storage<ItemSparseEntry> sItemSparseStore; -extern DB2Storage<ItemSpecEntry> sItemSpecStore; -extern DB2Storage<ItemSpecOverrideEntry> sItemSpecOverrideStore; -extern DB2Storage<ItemToBattlePetSpeciesEntry> sItemToBattlePetSpeciesStore; -extern DB2Storage<MailTemplateEntry> sMailTemplateStore; -extern DB2Storage<ModifierTreeEntry> sModifierTreeStore; -extern DB2Storage<MountCapabilityEntry> sMountCapabilityStore; -extern DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore; -extern DB2Storage<PlayerConditionEntry> sPlayerConditionStore; -extern DB2Storage<QuestMoneyRewardEntry> sQuestMoneyRewardStore; -extern DB2Storage<QuestSortEntry> sQuestSortStore; -extern DB2Storage<QuestXPEntry> sQuestXPStore; -extern DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore; -extern DB2Storage<SoundEntriesEntry> sSoundEntriesStore; -extern DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore; -extern DB2Storage<SpellCastTimesEntry> sSpellCastTimesStore; -extern DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore; -extern DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore; -extern DB2Storage<SpellDurationEntry> sSpellDurationStore; -extern DB2Storage<SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore; -extern DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore; -extern DB2Storage<SpellMiscEntry> sSpellMiscStore; -extern DB2Storage<SpellPowerEntry> sSpellPowerStore; -extern DB2Storage<SpellRadiusEntry> sSpellRadiusStore; -extern DB2Storage<SpellRangeEntry> sSpellRangeStore; -extern DB2Storage<SpellReagentsEntry> sSpellReagentsStore; -extern DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore; -extern DB2Storage<SpellTotemsEntry> sSpellTotemsStore; -extern DB2Storage<SpellXSpellVisualEntry> sSpellXSpellVisualStore; -extern DB2Storage<TaxiNodesEntry> sTaxiNodesStore; -extern DB2Storage<TaxiPathEntry> sTaxiPathStore; -extern DB2Storage<TotemCategoryEntry> sTotemCategoryStore; -extern DB2Storage<ToyEntry> sToyStore; -extern DB2Storage<UnitPowerBarEntry> sUnitPowerBarStore; -extern DB2Storage<WorldMapOverlayEntry> sWorldMapOverlayStore; - -extern TaxiMask sTaxiNodesMask; -extern TaxiMask sOldContinentsNodesMask; -extern TaxiMask sHordeTaxiNodesMask; -extern TaxiMask sAllianceTaxiNodesMask; -extern TaxiPathSetBySource sTaxiPathSetBySource; -extern TaxiPathNodesByPath sTaxiPathNodesByPath; +TC_GAME_API extern DB2Storage<AchievementEntry> sAchievementStore; +TC_GAME_API extern DB2Storage<AuctionHouseEntry> sAuctionHouseStore; +TC_GAME_API extern DB2Storage<BarberShopStyleEntry> sBarberShopStyleStore; +TC_GAME_API extern DB2Storage<BattlePetBreedQualityEntry> sBattlePetBreedQualityStore; +TC_GAME_API extern DB2Storage<BattlePetBreedStateEntry> sBattlePetBreedStateStore; +TC_GAME_API extern DB2Storage<BattlePetSpeciesEntry> sBattlePetSpeciesStore; +TC_GAME_API extern DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore; +TC_GAME_API extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore; +TC_GAME_API extern DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore; +TC_GAME_API extern DB2Storage<CinematicSequencesEntry> sCinematicSequencesStore; +TC_GAME_API extern DB2Storage<CreatureDisplayInfoEntry> sCreatureDisplayInfoStore; +TC_GAME_API extern DB2Storage<CreatureTypeEntry> sCreatureTypeStore; +TC_GAME_API extern DB2Storage<CriteriaEntry> sCriteriaStore; +TC_GAME_API extern DB2Storage<CriteriaTreeEntry> sCriteriaTreeStore; +TC_GAME_API extern DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore; +TC_GAME_API extern DB2Storage<DestructibleModelDataEntry> sDestructibleModelDataStore; +TC_GAME_API extern DB2Storage<DurabilityQualityEntry> sDurabilityQualityStore; +TC_GAME_API extern DB2Storage<GameObjectsEntry> sGameObjectsStore; +TC_GAME_API extern DB2Storage<GameTablesEntry> sGameTablesStore; +TC_GAME_API extern DB2Storage<GarrAbilityEntry> sGarrAbilityStore; +TC_GAME_API extern DB2Storage<GarrBuildingEntry> sGarrBuildingStore; +TC_GAME_API extern DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore; +TC_GAME_API extern DB2Storage<GarrClassSpecEntry> sGarrClassSpecStore; +TC_GAME_API extern DB2Storage<GarrFollowerEntry> sGarrFollowerStore; +TC_GAME_API extern DB2Storage<GarrFollowerXAbilityEntry> sGarrFollowerXAbilityStore; +TC_GAME_API extern DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore; +TC_GAME_API extern DB2Storage<GarrPlotEntry> sGarrPlotStore; +TC_GAME_API extern DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore; +TC_GAME_API extern DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore; +TC_GAME_API extern DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore; +TC_GAME_API extern DB2Storage<GlyphSlotEntry> sGlyphSlotStore; +TC_GAME_API extern DB2Storage<GuildPerkSpellsEntry> sGuildPerkSpellsStore; +TC_GAME_API extern DB2Storage<HeirloomEntry> sHeirloomStore; +TC_GAME_API extern DB2Storage<HolidaysEntry> sHolidaysStore; +TC_GAME_API extern DB2Storage<ImportPriceArmorEntry> sImportPriceArmorStore; +TC_GAME_API extern DB2Storage<ImportPriceQualityEntry> sImportPriceQualityStore; +TC_GAME_API extern DB2Storage<ImportPriceShieldEntry> sImportPriceShieldStore; +TC_GAME_API extern DB2Storage<ImportPriceWeaponEntry> sImportPriceWeaponStore; +TC_GAME_API extern DB2Storage<ItemClassEntry> sItemClassStore; +TC_GAME_API extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore; +TC_GAME_API extern DB2Storage<ItemDisenchantLootEntry> sItemDisenchantLootStore; +TC_GAME_API extern DB2Storage<ItemEffectEntry> sItemEffectStore; +TC_GAME_API extern DB2Storage<ItemEntry> sItemStore; +TC_GAME_API extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore; +TC_GAME_API extern DB2Storage<ItemLimitCategoryEntry> sItemLimitCategoryStore; +TC_GAME_API extern DB2Storage<ItemPriceBaseEntry> sItemPriceBaseStore; +TC_GAME_API extern DB2Storage<ItemRandomPropertiesEntry> sItemRandomPropertiesStore; +TC_GAME_API extern DB2Storage<ItemRandomSuffixEntry> sItemRandomSuffixStore; +TC_GAME_API extern DB2Storage<ItemSparseEntry> sItemSparseStore; +TC_GAME_API extern DB2Storage<ItemSpecEntry> sItemSpecStore; +TC_GAME_API extern DB2Storage<ItemSpecOverrideEntry> sItemSpecOverrideStore; +TC_GAME_API extern DB2Storage<ItemToBattlePetSpeciesEntry> sItemToBattlePetSpeciesStore; +TC_GAME_API extern DB2Storage<MailTemplateEntry> sMailTemplateStore; +TC_GAME_API extern DB2Storage<ModifierTreeEntry> sModifierTreeStore; +TC_GAME_API extern DB2Storage<MountCapabilityEntry> sMountCapabilityStore; +TC_GAME_API extern DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore; +TC_GAME_API extern DB2Storage<PlayerConditionEntry> sPlayerConditionStore; +TC_GAME_API extern DB2Storage<QuestMoneyRewardEntry> sQuestMoneyRewardStore; +TC_GAME_API extern DB2Storage<QuestSortEntry> sQuestSortStore; +TC_GAME_API extern DB2Storage<QuestXPEntry> sQuestXPStore; +TC_GAME_API extern DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore; +TC_GAME_API extern DB2Storage<SoundEntriesEntry> sSoundEntriesStore; +TC_GAME_API extern DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore; +TC_GAME_API extern DB2Storage<SpellCastTimesEntry> sSpellCastTimesStore; +TC_GAME_API extern DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore; +TC_GAME_API extern DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore; +TC_GAME_API extern DB2Storage<SpellDurationEntry> sSpellDurationStore; +TC_GAME_API extern DB2Storage<SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore; +TC_GAME_API extern DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore; +TC_GAME_API extern DB2Storage<SpellMiscEntry> sSpellMiscStore; +TC_GAME_API extern DB2Storage<SpellPowerEntry> sSpellPowerStore; +TC_GAME_API extern DB2Storage<SpellRadiusEntry> sSpellRadiusStore; +TC_GAME_API extern DB2Storage<SpellRangeEntry> sSpellRangeStore; +TC_GAME_API extern DB2Storage<SpellReagentsEntry> sSpellReagentsStore; +TC_GAME_API extern DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore; +TC_GAME_API extern DB2Storage<SpellTotemsEntry> sSpellTotemsStore; +TC_GAME_API extern DB2Storage<SpellXSpellVisualEntry> sSpellXSpellVisualStore; +TC_GAME_API extern DB2Storage<TaxiNodesEntry> sTaxiNodesStore; +TC_GAME_API extern DB2Storage<TaxiPathEntry> sTaxiPathStore; +TC_GAME_API extern DB2Storage<TotemCategoryEntry> sTotemCategoryStore; +TC_GAME_API extern DB2Storage<ToyEntry> sToyStore; +TC_GAME_API extern DB2Storage<UnitPowerBarEntry> sUnitPowerBarStore; +TC_GAME_API extern DB2Storage<WorldMapOverlayEntry> sWorldMapOverlayStore; + +TC_GAME_API extern TaxiMask sTaxiNodesMask; +TC_GAME_API extern TaxiMask sOldContinentsNodesMask; +TC_GAME_API extern TaxiMask sHordeTaxiNodesMask; +TC_GAME_API extern TaxiMask sAllianceTaxiNodesMask; +TC_GAME_API extern TaxiPathSetBySource sTaxiPathSetBySource; +TC_GAME_API extern TaxiPathNodesByPath sTaxiPathNodesByPath; struct HotfixNotify { @@ -131,7 +131,7 @@ typedef std::vector<HotfixNotify> HotfixData; static bool Compare(structure const* left, structure const* right); \ }; -class DB2Manager +class TC_GAME_API DB2Manager { public: DEFINE_DB2_SET_COMPARATOR(ChrClassesXPowerTypesEntry); @@ -162,11 +162,7 @@ public: typedef std::unordered_map<uint32, std::unordered_map<uint32, std::vector<SpellPowerEntry const*>>> SpellPowerDifficultyContainer; typedef std::unordered_set<uint32> ToyItemIdsContainer; - static DB2Manager& Instance() - { - static DB2Manager instance; - return instance; - } + static DB2Manager& Instance(); void LoadStores(std::string const& dataPath, uint32 defaultLocale); DB2StorageBase const* GetStorage(uint32 type) const; diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index d8af7418be4..2f30a00d3c0 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -25,50 +25,50 @@ #include "SharedDefines.h" // CharSections -CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color); +TC_GAME_API CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color); // ChrClasses -char const* GetClassName(uint8 class_, uint8 locale); +TC_GAME_API char const* GetClassName(uint8 class_, uint8 locale); // ChrRaces -char const* GetRaceName(uint8 race, uint8 locale); +TC_GAME_API char const* GetRaceName(uint8 race, uint8 locale); // ChrSpecialization typedef ChrSpecializationEntry const* ChrSpecializationByIndexArray[MAX_CLASSES][MAX_SPECIALIZATIONS]; // CreatureFamilty -char const* GetCreatureFamilyPetName(uint32 petfamily, uint32 locale); +TC_GAME_API char const* GetCreatureFamilyPetName(uint32 petfamily, uint32 locale); // Faction -std::vector<uint32> const* GetFactionTeamList(uint32 faction); +TC_GAME_API std::vector<uint32> const* GetFactionTeamList(uint32 faction); // ItemSetSpells typedef std::vector<ItemSetSpellEntry const*> ItemSetSpells; typedef std::unordered_map<uint32, ItemSetSpells> ItemSetSpellsStore; // LfgDungeons -LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty); +TC_GAME_API LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty); // Light -uint32 GetDefaultMapLight(uint32 mapId); +TC_GAME_API uint32 GetDefaultMapLight(uint32 mapId); // LiquidType -uint32 GetLiquidFlags(uint32 liquidType); +TC_GAME_API uint32 GetLiquidFlags(uint32 liquidType); // MapDifficulty typedef std::unordered_map<uint32, std::unordered_map<uint32, MapDifficultyEntry const*>> MapDifficultyMap; -MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty = nullptr); -MapDifficultyEntry const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); -MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty); +TC_GAME_API MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty = nullptr); +TC_GAME_API MapDifficultyEntry const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); +TC_GAME_API MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty); // PvpDifficulty -PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level); -PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id); +TC_GAME_API PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level); +TC_GAME_API PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id); // SkillRaceClassInfo typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoMap; typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds; -SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); +TC_GAME_API SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); // SpellEffectScaling typedef std::unordered_map<uint32, uint32> SpellEffectScallingByEffectId; @@ -77,21 +77,21 @@ typedef std::unordered_map<uint32, uint32> SpellEffectScallingByEffectId; typedef std::vector<TalentEntry const*> TalentsByPosition[MAX_CLASSES][MAX_TALENT_TIERS][MAX_TALENT_COLUMNS]; // TotemCategory -bool IsTotemCategoryCompatibleWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId); +TC_GAME_API bool IsTotemCategoryCompatibleWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId); // WMOAreaTable -WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid); +TC_GAME_API WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid); // WorldMapArea -uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId); -void Zone2MapCoordinates(float &x, float &y, uint32 worldMapAreaId); -void Map2ZoneCoordinates(float &x, float &y, uint32 worldMapAreaId); +TC_GAME_API uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId); +TC_GAME_API void Zone2MapCoordinates(float &x, float &y, uint32 worldMapAreaId); +TC_GAME_API void Map2ZoneCoordinates(float &x, float &y, uint32 worldMapAreaId); // WorldMapTransforms -void DeterminaAlternateMapPosition(uint32 mapId, float x, float y, float z, uint32* newMapId = nullptr, DBCPosition2D* newPos = nullptr); +TC_GAME_API void DeterminaAlternateMapPosition(uint32 mapId, float x, float y, float z, uint32* newMapId = nullptr, DBCPosition2D* newPos = nullptr); -uint32 GetMaxLevelForExpansion(uint32 expansion); -uint32 GetExpansionForLevel(uint32 level); +TC_GAME_API uint32 GetMaxLevelForExpansion(uint32 expansion); +TC_GAME_API uint32 GetExpansionForLevel(uint32 level); template<class T> class GameTable @@ -121,111 +121,111 @@ private: GameTablesEntry const* _gtEntry; }; -extern DBCStorage<AnimKitEntry> sAnimKitStore; -extern DBCStorage<AreaTableEntry> sAreaTableStore; -extern DBCStorage<AreaTriggerEntry> sAreaTriggerStore; -extern DBCStorage<ArmorLocationEntry> sArmorLocationStore; -extern DBCStorage<BankBagSlotPricesEntry> sBankBagSlotPricesStore; -extern DBCStorage<BannedAddOnsEntry> sBannedAddOnsStore; -extern DBCStorage<BattlemasterListEntry> sBattlemasterListStore; -extern DBCStorage<CharSectionsEntry> sCharSectionsStore; -extern DBCStorage<CharTitlesEntry> sCharTitlesStore; -extern DBCStorage<ChatChannelsEntry> sChatChannelsStore; -extern DBCStorage<ChrClassesEntry> sChrClassesStore; -extern DBCStorage<ChrRacesEntry> sChrRacesStore; -extern DBCStorage<ChrSpecializationEntry> sChrSpecializationStore; -extern ChrSpecializationByIndexArray sChrSpecializationByIndexStore; -extern DBCStorage<CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore; -extern DBCStorage<CreatureFamilyEntry> sCreatureFamilyStore; -extern DBCStorage<CreatureModelDataEntry> sCreatureModelDataStore; -extern DBCStorage<DifficultyEntry> sDifficultyStore; -extern DBCStorage<DungeonEncounterEntry> sDungeonEncounterStore; -extern DBCStorage<DurabilityCostsEntry> sDurabilityCostsStore; -extern DBCStorage<EmotesEntry> sEmotesStore; -extern DBCStorage<EmotesTextEntry> sEmotesTextStore; -extern DBCStorage<FactionEntry> sFactionStore; -extern DBCStorage<FactionTemplateEntry> sFactionTemplateStore; -extern DBCStorage<GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore; -extern DBCStorage<GemPropertiesEntry> sGemPropertiesStore; -extern DBCStorage<GlyphPropertiesEntry> sGlyphPropertiesStore; -extern DBCStorage<GuildColorBackgroundEntry> sGuildColorBackgroundStore; -extern DBCStorage<GuildColorBorderEntry> sGuildColorBorderStore; -extern DBCStorage<GuildColorEmblemEntry> sGuildColorEmblemStore; -extern DBCStorage<ItemArmorQualityEntry> sItemArmorQualityStore; -extern DBCStorage<ItemArmorShieldEntry> sItemArmorShieldStore; -extern DBCStorage<ItemArmorTotalEntry> sItemArmorTotalStore; -extern DBCStorage<ItemBagFamilyEntry> sItemBagFamilyStore; -extern DBCStorage<ItemDamageEntry> sItemDamageAmmoStore; -extern DBCStorage<ItemDamageEntry> sItemDamageOneHandCasterStore; -extern DBCStorage<ItemDamageEntry> sItemDamageOneHandStore; -extern DBCStorage<ItemDamageEntry> sItemDamageRangedStore; -extern DBCStorage<ItemDamageEntry> sItemDamageThrownStore; -extern DBCStorage<ItemDamageEntry> sItemDamageTwoHandCasterStore; -extern DBCStorage<ItemDamageEntry> sItemDamageTwoHandStore; -extern DBCStorage<ItemDamageEntry> sItemDamageWandStore; -extern DBCStorage<ItemSetEntry> sItemSetStore; -extern DBCStorage<ItemSetSpellEntry> sItemSetSpellStore; -extern ItemSetSpellsStore sItemSetSpellsStore; -extern DBCStorage<LFGDungeonEntry> sLFGDungeonStore; -extern DBCStorage<LiquidTypeEntry> sLiquidTypeStore; -extern DBCStorage<LockEntry> sLockStore; -extern DBCStorage<MapEntry> sMapStore; -extern MapDifficultyMap sMapDifficultyMap; -extern DBCStorage<MovieEntry> sMovieStore; -extern DBCStorage<PhaseEntry> sPhaseStore; -extern DBCStorage<PowerDisplayEntry> sPowerDisplayStore; -extern DBCStorage<QuestFactionRewEntry> sQuestFactionRewardStore; -extern DBCStorage<RandomPropertiesPointsEntry> sRandomPropertiesPointsStore; -extern DBCStorage<SkillLineAbilityEntry> sSkillLineAbilityStore; -extern DBCStorage<SkillLineEntry> sSkillLineStore; -extern DBCStorage<SkillRaceClassInfoEntry> sSkillRaceClassInfoStore; -extern DBCStorage<SpellAuraOptionsEntry> sSpellAuraOptionsStore; -extern DBCStorage<SpellCategoriesEntry> sSpellCategoriesStore; -extern DBCStorage<SpellCategoryEntry> sSpellCategoryStore; -extern DBCStorage<SpellCooldownsEntry> sSpellCooldownsStore; -extern DBCStorage<SpellEffectEntry> sSpellEffectStore; -extern DBCStorage<SpellEffectScalingEntry> sSpellEffectScalingStore; -extern SpellEffectScallingByEffectId sSpellEffectScallingByEffectId; -extern DBCStorage<SpellEntry> sSpellStore; -extern DBCStorage<SpellEquippedItemsEntry> sSpellEquippedItemsStore; -extern DBCStorage<SpellFocusObjectEntry> sSpellFocusObjectStore; -extern DBCStorage<SpellInterruptsEntry> sSpellInterruptsStore; -extern DBCStorage<SpellItemEnchantmentEntry> sSpellItemEnchantmentStore; -extern DBCStorage<SpellLevelsEntry> sSpellLevelsStore; -extern DBCStorage<SpellScalingEntry> sSpellScalingStore; -extern DBCStorage<SpellShapeshiftEntry> sSpellShapeshiftStore; -extern DBCStorage<SpellShapeshiftFormEntry> sSpellShapeshiftFormStore; -extern DBCStorage<SpellTargetRestrictionsEntry> sSpellTargetRestrictionsStore; -extern DBCStorage<SummonPropertiesEntry> sSummonPropertiesStore; -extern DBCStorage<TalentEntry> sTalentStore; -extern TalentsByPosition sTalentByPos; -extern DBCStorage<VehicleEntry> sVehicleStore; -extern DBCStorage<VehicleSeatEntry> sVehicleSeatStore; -extern DBCStorage<WMOAreaTableEntry> sWMOAreaTableStore; -extern DBCStorage<WorldSafeLocsEntry> sWorldSafeLocsStore; - -extern GameTable<GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore; -extern GameTable<GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore; -extern GameTable<GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore; -extern GameTable<GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore; -extern GameTable<GtChanceToSpellCritEntry> sGtChanceToSpellCritStore; -extern GameTable<GtCombatRatingsEntry> sGtCombatRatingsStore; -extern GameTable<GtItemSocketCostPerLevelEntry> sGtItemSocketCostPerLevelStore; -extern GameTable<GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore; -extern GameTable<GtNpcTotalHpEntry> sGtNpcTotalHpStore; -extern GameTable<GtNpcTotalHpExp1Entry> sGtNpcTotalHpExp1Store; -extern GameTable<GtNpcTotalHpExp2Entry> sGtNpcTotalHpExp2Store; -extern GameTable<GtNpcTotalHpExp3Entry> sGtNpcTotalHpExp3Store; -extern GameTable<GtNpcTotalHpExp4Entry> sGtNpcTotalHpExp4Store; -extern GameTable<GtNpcTotalHpExp5Entry> sGtNpcTotalHpExp5Store; -extern GameTable<GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore; -extern GameTable<GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore; -extern GameTable<GtOCTLevelExperienceEntry> sGtOCTLevelExperienceStore; -extern GameTable<GtRegenMPPerSptEntry> sGtRegenMPPerSptStore; -extern GameTable<GtSpellScalingEntry> sGtSpellScalingStore; -extern GameTable<GtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore; - -void LoadDBCStores(const std::string& dataPath, uint32 defaultLocale); -void LoadGameTables(const std::string& dataPath, uint32 defaultLocale); +TC_GAME_API extern DBCStorage<AnimKitEntry> sAnimKitStore; +TC_GAME_API extern DBCStorage<AreaTableEntry> sAreaTableStore; +TC_GAME_API extern DBCStorage<AreaTriggerEntry> sAreaTriggerStore; +TC_GAME_API extern DBCStorage<ArmorLocationEntry> sArmorLocationStore; +TC_GAME_API extern DBCStorage<BankBagSlotPricesEntry> sBankBagSlotPricesStore; +TC_GAME_API extern DBCStorage<BannedAddOnsEntry> sBannedAddOnsStore; +TC_GAME_API extern DBCStorage<BattlemasterListEntry> sBattlemasterListStore; +TC_GAME_API extern DBCStorage<CharSectionsEntry> sCharSectionsStore; +TC_GAME_API extern DBCStorage<CharTitlesEntry> sCharTitlesStore; +TC_GAME_API extern DBCStorage<ChatChannelsEntry> sChatChannelsStore; +TC_GAME_API extern DBCStorage<ChrClassesEntry> sChrClassesStore; +TC_GAME_API extern DBCStorage<ChrRacesEntry> sChrRacesStore; +TC_GAME_API extern DBCStorage<ChrSpecializationEntry> sChrSpecializationStore; +TC_GAME_API extern ChrSpecializationByIndexArray sChrSpecializationByIndexStore; +TC_GAME_API extern DBCStorage<CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore; +TC_GAME_API extern DBCStorage<CreatureFamilyEntry> sCreatureFamilyStore; +TC_GAME_API extern DBCStorage<CreatureModelDataEntry> sCreatureModelDataStore; +TC_GAME_API extern DBCStorage<DifficultyEntry> sDifficultyStore; +TC_GAME_API extern DBCStorage<DungeonEncounterEntry> sDungeonEncounterStore; +TC_GAME_API extern DBCStorage<DurabilityCostsEntry> sDurabilityCostsStore; +TC_GAME_API extern DBCStorage<EmotesEntry> sEmotesStore; +TC_GAME_API extern DBCStorage<EmotesTextEntry> sEmotesTextStore; +TC_GAME_API extern DBCStorage<FactionEntry> sFactionStore; +TC_GAME_API extern DBCStorage<FactionTemplateEntry> sFactionTemplateStore; +TC_GAME_API extern DBCStorage<GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore; +TC_GAME_API extern DBCStorage<GemPropertiesEntry> sGemPropertiesStore; +TC_GAME_API extern DBCStorage<GlyphPropertiesEntry> sGlyphPropertiesStore; +TC_GAME_API extern DBCStorage<GuildColorBackgroundEntry> sGuildColorBackgroundStore; +TC_GAME_API extern DBCStorage<GuildColorBorderEntry> sGuildColorBorderStore; +TC_GAME_API extern DBCStorage<GuildColorEmblemEntry> sGuildColorEmblemStore; +TC_GAME_API extern DBCStorage<ItemArmorQualityEntry> sItemArmorQualityStore; +TC_GAME_API extern DBCStorage<ItemArmorShieldEntry> sItemArmorShieldStore; +TC_GAME_API extern DBCStorage<ItemArmorTotalEntry> sItemArmorTotalStore; +TC_GAME_API extern DBCStorage<ItemBagFamilyEntry> sItemBagFamilyStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageAmmoStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageOneHandCasterStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageOneHandStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageRangedStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageThrownStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageTwoHandCasterStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageTwoHandStore; +TC_GAME_API extern DBCStorage<ItemDamageEntry> sItemDamageWandStore; +TC_GAME_API extern DBCStorage<ItemSetEntry> sItemSetStore; +TC_GAME_API extern DBCStorage<ItemSetSpellEntry> sItemSetSpellStore; +TC_GAME_API extern ItemSetSpellsStore sItemSetSpellsStore; +TC_GAME_API extern DBCStorage<LFGDungeonEntry> sLFGDungeonStore; +TC_GAME_API extern DBCStorage<LiquidTypeEntry> sLiquidTypeStore; +TC_GAME_API extern DBCStorage<LockEntry> sLockStore; +TC_GAME_API extern DBCStorage<MapEntry> sMapStore; +TC_GAME_API extern MapDifficultyMap sMapDifficultyMap; +TC_GAME_API extern DBCStorage<MovieEntry> sMovieStore; +TC_GAME_API extern DBCStorage<PhaseEntry> sPhaseStore; +TC_GAME_API extern DBCStorage<PowerDisplayEntry> sPowerDisplayStore; +TC_GAME_API extern DBCStorage<QuestFactionRewEntry> sQuestFactionRewardStore; +TC_GAME_API extern DBCStorage<RandomPropertiesPointsEntry> sRandomPropertiesPointsStore; +TC_GAME_API extern DBCStorage<SkillLineAbilityEntry> sSkillLineAbilityStore; +TC_GAME_API extern DBCStorage<SkillLineEntry> sSkillLineStore; +TC_GAME_API extern DBCStorage<SkillRaceClassInfoEntry> sSkillRaceClassInfoStore; +TC_GAME_API extern DBCStorage<SpellAuraOptionsEntry> sSpellAuraOptionsStore; +TC_GAME_API extern DBCStorage<SpellCategoriesEntry> sSpellCategoriesStore; +TC_GAME_API extern DBCStorage<SpellCategoryEntry> sSpellCategoryStore; +TC_GAME_API extern DBCStorage<SpellCooldownsEntry> sSpellCooldownsStore; +TC_GAME_API extern DBCStorage<SpellEffectEntry> sSpellEffectStore; +TC_GAME_API extern DBCStorage<SpellEffectScalingEntry> sSpellEffectScalingStore; +TC_GAME_API extern SpellEffectScallingByEffectId sSpellEffectScallingByEffectId; +TC_GAME_API extern DBCStorage<SpellEntry> sSpellStore; +TC_GAME_API extern DBCStorage<SpellEquippedItemsEntry> sSpellEquippedItemsStore; +TC_GAME_API extern DBCStorage<SpellFocusObjectEntry> sSpellFocusObjectStore; +TC_GAME_API extern DBCStorage<SpellInterruptsEntry> sSpellInterruptsStore; +TC_GAME_API extern DBCStorage<SpellItemEnchantmentEntry> sSpellItemEnchantmentStore; +TC_GAME_API extern DBCStorage<SpellLevelsEntry> sSpellLevelsStore; +TC_GAME_API extern DBCStorage<SpellScalingEntry> sSpellScalingStore; +TC_GAME_API extern DBCStorage<SpellShapeshiftEntry> sSpellShapeshiftStore; +TC_GAME_API extern DBCStorage<SpellShapeshiftFormEntry> sSpellShapeshiftFormStore; +TC_GAME_API extern DBCStorage<SpellTargetRestrictionsEntry> sSpellTargetRestrictionsStore; +TC_GAME_API extern DBCStorage<SummonPropertiesEntry> sSummonPropertiesStore; +TC_GAME_API extern DBCStorage<TalentEntry> sTalentStore; +TC_GAME_API extern TalentsByPosition sTalentByPos; +TC_GAME_API extern DBCStorage<VehicleEntry> sVehicleStore; +TC_GAME_API extern DBCStorage<VehicleSeatEntry> sVehicleSeatStore; +TC_GAME_API extern DBCStorage<WMOAreaTableEntry> sWMOAreaTableStore; +TC_GAME_API extern DBCStorage<WorldSafeLocsEntry> sWorldSafeLocsStore; + +TC_GAME_API extern GameTable<GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore; +TC_GAME_API extern GameTable<GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore; +TC_GAME_API extern GameTable<GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore; +TC_GAME_API extern GameTable<GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore; +TC_GAME_API extern GameTable<GtChanceToSpellCritEntry> sGtChanceToSpellCritStore; +TC_GAME_API extern GameTable<GtCombatRatingsEntry> sGtCombatRatingsStore; +TC_GAME_API extern GameTable<GtItemSocketCostPerLevelEntry> sGtItemSocketCostPerLevelStore; +TC_GAME_API extern GameTable<GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore; +TC_GAME_API extern GameTable<GtNpcTotalHpEntry> sGtNpcTotalHpStore; +TC_GAME_API extern GameTable<GtNpcTotalHpExp1Entry> sGtNpcTotalHpExp1Store; +TC_GAME_API extern GameTable<GtNpcTotalHpExp2Entry> sGtNpcTotalHpExp2Store; +TC_GAME_API extern GameTable<GtNpcTotalHpExp3Entry> sGtNpcTotalHpExp3Store; +TC_GAME_API extern GameTable<GtNpcTotalHpExp4Entry> sGtNpcTotalHpExp4Store; +TC_GAME_API extern GameTable<GtNpcTotalHpExp5Entry> sGtNpcTotalHpExp5Store; +TC_GAME_API extern GameTable<GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore; +TC_GAME_API extern GameTable<GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore; +TC_GAME_API extern GameTable<GtOCTLevelExperienceEntry> sGtOCTLevelExperienceStore; +TC_GAME_API extern GameTable<GtRegenMPPerSptEntry> sGtRegenMPPerSptStore; +TC_GAME_API extern GameTable<GtSpellScalingEntry> sGtSpellScalingStore; +TC_GAME_API extern GameTable<GtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore; + +TC_GAME_API void LoadDBCStores(const std::string& dataPath, uint32 defaultLocale); +TC_GAME_API void LoadGameTables(const std::string& dataPath, uint32 defaultLocale); #endif diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h index 9aae994f168..b76c5e08d32 100644 --- a/src/server/game/DungeonFinding/LFG.h +++ b/src/server/game/DungeonFinding/LFG.h @@ -99,7 +99,7 @@ enum LfgAnswer LFG_ANSWER_AGREE = 1 }; -struct LfgLockInfoData +struct TC_GAME_API LfgLockInfoData { LfgLockInfoData(uint32 _lockStatus = 0, uint16 _requiredItemLevel = 0, float _currentItemLevel = 0) : lockStatus(_lockStatus), requiredItemLevel(_requiredItemLevel), currentItemLevel(_currentItemLevel) { } @@ -115,9 +115,9 @@ typedef std::map<ObjectGuid, LfgLockMap> LfgLockPartyMap; typedef std::map<ObjectGuid, uint8> LfgRolesMap; typedef std::map<ObjectGuid, ObjectGuid> LfgGroupsMap; -std::string ConcatenateDungeons(LfgDungeonSet const& dungeons); -std::string GetRolesString(uint8 roles); -std::string GetStateString(LfgState state); +TC_GAME_API std::string ConcatenateDungeons(LfgDungeonSet const& dungeons); +TC_GAME_API std::string GetRolesString(uint8 roles); +TC_GAME_API std::string GetStateString(LfgState state); } // namespace lfg diff --git a/src/server/game/DungeonFinding/LFGGroupData.h b/src/server/game/DungeonFinding/LFGGroupData.h index 7ae4777cd4d..62a41b6b350 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.h +++ b/src/server/game/DungeonFinding/LFGGroupData.h @@ -31,7 +31,7 @@ enum LfgGroupEnum /** Stores all lfg data needed about a group. */ -class LfgGroupData +class TC_GAME_API LfgGroupData { public: LfgGroupData(); diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 0bf31636697..e328732c0c5 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -258,6 +258,12 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) CachedDungeonMapStore.clear(); } +LFGMgr* LFGMgr::instance() +{ + static LFGMgr instance; + return &instance; +} + void LFGMgr::Update(uint32 diff) { if (!isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER)) diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index e092cbdee02..f38812549a6 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -295,18 +295,14 @@ struct LFGDungeonData uint32 Entry() const { return id + (type << 24); } }; -class LFGMgr +class TC_GAME_API LFGMgr { private: LFGMgr(); ~LFGMgr(); public: - static LFGMgr* instance() - { - static LFGMgr instance; - return &instance; - } + static LFGMgr* instance(); // Functions used outside lfg namespace void Update(uint32 diff); diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h index 859317ca956..91e4153a6d5 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.h +++ b/src/server/game/DungeonFinding/LFGPlayerData.h @@ -26,7 +26,7 @@ namespace lfg /** Stores all lfg data needed about the player. */ -class LfgPlayerData +class TC_GAME_API LfgPlayerData { public: LfgPlayerData(); diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h index c9e2af7f480..c69b3cecb64 100644 --- a/src/server/game/DungeonFinding/LFGQueue.h +++ b/src/server/game/DungeonFinding/LFGQueue.h @@ -83,7 +83,7 @@ typedef std::map<ObjectGuid, LfgQueueData> LfgQueueDataContainer; /** Stores all data related to queue */ -class LFGQueue +class TC_GAME_API LFGQueue { public: diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h index 377614bc55d..ec64604a282 100644 --- a/src/server/game/DungeonFinding/LFGScripts.h +++ b/src/server/game/DungeonFinding/LFGScripts.h @@ -29,7 +29,7 @@ class Group; namespace lfg { -class LFGPlayerScript : public PlayerScript +class TC_GAME_API LFGPlayerScript : public PlayerScript { public: LFGPlayerScript(); @@ -40,7 +40,7 @@ class LFGPlayerScript : public PlayerScript void OnMapChanged(Player* player) override; }; -class LFGGroupScript : public GroupScript +class TC_GAME_API LFGGroupScript : public GroupScript { public: LFGGroupScript(); diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h index 7a6581e13c4..e3caa6d2e95 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h @@ -23,7 +23,7 @@ class Unit; class SpellInfo; -class AreaTrigger : public WorldObject, public GridObject<AreaTrigger> +class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigger> { public: AreaTrigger(); diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h index 4d2775789eb..f961a966796 100644 --- a/src/server/game/Entities/Corpse/Corpse.h +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -46,7 +46,7 @@ enum CorpseFlags CORPSE_FLAG_LOOTABLE = 0x20 }; -class Corpse : public WorldObject, public GridObject<Corpse> +class TC_GAME_API Corpse : public WorldObject, public GridObject<Corpse> { public: explicit Corpse(CorpseType type = CORPSE_BONES); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 594d2e81afe..47ef22b2df0 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -182,7 +182,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_groupLootTimer(0), m_PlayerDamageReq(0), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0), -m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), +m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(NULL), m_creatureData(NULL), m_waypointID(0), m_path_id(0), m_formation(NULL) @@ -586,6 +586,17 @@ void Creature::Update(uint32 diff) LastCharmerGUID.Clear(); } + // periodic check to see if the creature has passed an evade boundary + if (IsAIEnabled && !IsInEvadeMode() && IsInCombat()) + { + if (diff >= m_boundaryCheckTime) + { + AI()->CheckInRoom(); + m_boundaryCheckTime = 2500; + } else + m_boundaryCheckTime -= diff; + } + // if periodic combat pulse is enabled and we are both in combat and in a dungeon, do this now if (m_combatPulseDelay > 0 && IsInCombat() && GetMap()->IsDungeon()) { diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 8ae94e51451..96b04b32f84 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -74,7 +74,7 @@ enum CreatureFlagsExtra #define MAX_CREATURE_DIFFICULTIES 3 // from `creature_template` table -struct CreatureTemplate +struct TC_GAME_API CreatureTemplate { uint32 Entry; uint32 DifficultyEntry[MAX_CREATURE_DIFFICULTIES]; @@ -213,7 +213,7 @@ typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer; #pragma pack(push, 1) // Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage). -struct CreatureBaseStats +struct TC_GAME_API CreatureBaseStats { uint32 BaseHealth[MAX_EXPANSIONS]; uint32 BaseMana; @@ -440,7 +440,7 @@ struct TrainerSpell typedef std::unordered_map<uint32 /*spellid*/, TrainerSpell> TrainerSpellMap; -struct TrainerSpellData +struct TC_GAME_API TrainerSpellData { TrainerSpellData() : trainerType(0) { } ~TrainerSpellData() { spellList.clear(); } @@ -462,7 +462,7 @@ typedef std::map<uint32, time_t> CreatureSpellCooldowns; typedef std::vector<uint8> CreatureTextRepeatIds; typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup; -class Creature : public Unit, public GridObject<Creature>, public MapObject +class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public MapObject { public: @@ -638,6 +638,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject float GetRespawnRadius() const { return m_respawnradius; } void SetRespawnRadius(float dist) { m_respawnradius = dist; } + void DoImmediateBoundaryCheck() { m_boundaryCheckTime = 0; } uint32 GetCombatPulseDelay() const { return m_combatPulseDelay; } void SetCombatPulseDelay(uint32 delay) // (secs) interval at which the creature pulses the entire zone into combat (only works in dungeons) { @@ -731,6 +732,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance float m_respawnradius; + uint32 m_boundaryCheckTime; // (msecs) remaining time for next evade boundary check uint32 m_combatPulseTime; // (msecs) remaining time for next zone-in-combat pulse uint32 m_combatPulseDelay; // (secs) how often the creature puts the entire zone in combat (only works in dungeons) @@ -781,7 +783,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject CreatureTextRepeatGroup m_textRepeat; }; -class AssistDelayEvent : public BasicEvent +class TC_GAME_API AssistDelayEvent : public BasicEvent { public: AssistDelayEvent(ObjectGuid victim, Unit& owner) : BasicEvent(), m_victim(victim), m_owner(owner) { } @@ -796,7 +798,7 @@ class AssistDelayEvent : public BasicEvent Unit& m_owner; }; -class ForcedDespawnDelayEvent : public BasicEvent +class TC_GAME_API ForcedDespawnDelayEvent : public BasicEvent { public: ForcedDespawnDelayEvent(Creature& owner) : BasicEvent(), m_owner(owner) { } diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 666ee0a82d0..b33777eb1fa 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -30,6 +30,12 @@ FormationMgr::~FormationMgr() delete itr->second; } +FormationMgr* FormationMgr::instance() +{ + static FormationMgr instance; + return &instance; +} + void FormationMgr::AddCreatureToGroup(ObjectGuid::LowType leaderGuid, Creature* creature) { Map* map = creature->FindMap(); diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index ca0aea431d8..36e72b66753 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -38,18 +38,14 @@ struct FormationInfo typedef std::unordered_map<ObjectGuid::LowType/*memberDBGUID*/, FormationInfo*> CreatureGroupInfoType; -class FormationMgr +class TC_GAME_API FormationMgr { private: FormationMgr() { } ~FormationMgr(); public: - static FormationMgr* instance() - { - static FormationMgr instance; - return &instance; - } + static FormationMgr* instance(); void AddCreatureToGroup(ObjectGuid::LowType leaderGuid, Creature* creature); void RemoveCreatureFromGroup(CreatureGroup* group, Creature* creature); @@ -57,7 +53,7 @@ class FormationMgr CreatureGroupInfoType CreatureGroupMap; }; -class CreatureGroup +class TC_GAME_API CreatureGroup { private: Creature* m_leader; //Important do not forget sometimes to work with pointers instead synonims :D:D diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h index ba5a2e1f6ba..ebd3045be67 100644 --- a/src/server/game/Entities/Creature/GossipDef.h +++ b/src/server/game/Entities/Creature/GossipDef.h @@ -158,7 +158,7 @@ struct QuestMenuItem typedef std::vector<QuestMenuItem> QuestMenuItemList; -class GossipMenu +class TC_GAME_API GossipMenu { public: GossipMenu(); @@ -216,7 +216,7 @@ class GossipMenu LocaleConstant _locale; }; -class QuestMenu +class TC_GAME_API QuestMenu { public: QuestMenu(); @@ -233,7 +233,7 @@ class QuestMenu QuestMenuItemList _questMenuItems; }; -class PlayerMenu +class TC_GAME_API PlayerMenu { public: explicit PlayerMenu(WorldSession* session); diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index f3c7b0eda2e..d43e7fcf626 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -37,7 +37,7 @@ struct TempSummonData uint32 time; ///< Despawn time, usable only with certain temp summon types }; -class TempSummon : public Creature +class TC_GAME_API TempSummon : public Creature { public: explicit TempSummon(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject); @@ -63,7 +63,7 @@ class TempSummon : public Creature ObjectGuid m_summonerGUID; }; -class Minion : public TempSummon +class TC_GAME_API Minion : public TempSummon { public: Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject); @@ -80,7 +80,7 @@ class Minion : public TempSummon float m_followAngle; }; -class Guardian : public Minion +class TC_GAME_API Guardian : public Minion { public: Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject); @@ -104,7 +104,7 @@ class Guardian : public Minion float m_statFromOwner[MAX_STATS]; }; -class Puppet : public Minion +class TC_GAME_API Puppet : public Minion { public: Puppet(SummonPropertiesEntry const* properties, Unit* owner); @@ -114,7 +114,7 @@ class Puppet : public Minion void RemoveFromWorld() override; }; -class ForcedUnsummonDelayEvent : public BasicEvent +class TC_GAME_API ForcedUnsummonDelayEvent : public BasicEvent { public: ForcedUnsummonDelayEvent(TempSummon& owner) : BasicEvent(), m_owner(owner) { } diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h index 78ef5ca935f..09426a3c044 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.h +++ b/src/server/game/Entities/DynamicObject/DynamicObject.h @@ -32,7 +32,7 @@ enum DynamicObjectType DYNAMIC_OBJECT_FARSIGHT_FOCUS = 0x2 }; -class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MapObject +class TC_GAME_API DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MapObject { public: DynamicObject(bool isWorldObject); diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 010ea09347f..47d06e1492b 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -877,7 +877,7 @@ class GameObjectModel; // 5 sec for bobber catch #define FISHING_BOBBER_READY_TIME 5 -class GameObject : public WorldObject, public GridObject<GameObject>, public MapObject +class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>, public MapObject { public: explicit GameObject(); diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h index 449301ee5ce..128213af4b4 100644 --- a/src/server/game/Entities/Item/Container/Bag.h +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -25,7 +25,7 @@ #include "Item.h" #include "ItemTemplate.h" -class Bag : public Item +class TC_GAME_API Bag : public Item { public: diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 7d1c3761430..4836c7b7246 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -256,7 +256,7 @@ struct BonusData void AddBonus(uint32 type, int32 const (&values)[2]); }; -class Item : public Object +class TC_GAME_API Item : public Object { public: static Item* CreateItem(uint32 itemEntry, uint32 count, Player const* player = NULL); diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp index 99fe78bea2f..daf3473c5a8 100644 --- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp +++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp @@ -44,7 +44,7 @@ typedef std::unordered_map<uint32, EnchStoreList> EnchantmentStore; static EnchantmentStore RandomItemEnch; -void LoadRandomEnchantmentsTable() +TC_GAME_API void LoadRandomEnchantmentsTable() { uint32 oldMSTime = getMSTime(); @@ -77,7 +77,7 @@ void LoadRandomEnchantmentsTable() TC_LOG_ERROR("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty."); } -uint32 GetItemEnchantMod(int32 entry) +TC_GAME_API uint32 GetItemEnchantMod(int32 entry) { if (!entry) return 0; @@ -118,7 +118,7 @@ uint32 GetItemEnchantMod(int32 entry) return 0; } -uint32 GenerateEnchSuffixFactor(uint32 item_id) +TC_GAME_API uint32 GenerateEnchSuffixFactor(uint32 item_id) { ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id); @@ -130,7 +130,7 @@ uint32 GenerateEnchSuffixFactor(uint32 item_id) return GetRandomPropertyPoints(itemProto->GetBaseItemLevel(), itemProto->GetQuality(), itemProto->GetInventoryType(), itemProto->GetSubClass()); } -uint32 GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subClass) +TC_GAME_API uint32 GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subClass) { uint32 propIndex; diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.h b/src/server/game/Entities/Item/ItemEnchantmentMgr.h index 25278caa512..ec84b13dec5 100644 --- a/src/server/game/Entities/Item/ItemEnchantmentMgr.h +++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.h @@ -21,9 +21,9 @@ #include "Common.h" -void LoadRandomEnchantmentsTable(); -uint32 GetItemEnchantMod(int32 entry); -uint32 GenerateEnchSuffixFactor(uint32 item_id); -uint32 GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subclass); +TC_GAME_API void LoadRandomEnchantmentsTable(); +TC_GAME_API uint32 GetItemEnchantMod(int32 entry); +TC_GAME_API uint32 GenerateEnchSuffixFactor(uint32 item_id); +TC_GAME_API uint32 GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subclass); #endif diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index 46584e1b5d3..aa65fdd3d6e 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -644,7 +644,7 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] = class Player; -struct ItemTemplate +struct TC_GAME_API ItemTemplate { ItemEntry const* BasicData; ItemSparseEntry const* ExtendedData; diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 4d54de20277..e3f22a41275 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -92,7 +92,7 @@ class ZoneScript; typedef std::unordered_map<Player*, UpdateData> UpdateDataMapType; -class Object +class TC_GAME_API Object { public: virtual ~Object(); @@ -395,7 +395,7 @@ enum MapObjectCellMoveState MAP_OBJECT_CELL_MOVE_INACTIVE, //in move list but should not move }; -class MapObject +class TC_GAME_API MapObject { friend class Map; //map for moving creatures friend class ObjectGridLoader; //grid loader for loading creatures @@ -420,7 +420,7 @@ class MapObject } }; -class WorldObject : public Object, public WorldLocation +class TC_GAME_API WorldObject : public Object, public WorldLocation { protected: explicit WorldObject(bool isWorldObject); //note: here it means if it is in grid object list or world object list diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index 5d7c19d48e7..6d063a901bd 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -177,3 +177,29 @@ void ObjectGuidGeneratorBase::HandleCounterOverflow(HighGuid high) TC_LOG_ERROR("misc", "%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high)); World::StopNow(ERROR_EXIT_CODE); } + +#define GUID_TRAIT_INSTANTIATE_GUID( HIGH_GUID ) \ + template class TC_GAME_API ObjectGuidGenerator< HIGH_GUID >; + +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Player) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Item) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Transport) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Guild) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Conversation) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Creature) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Vehicle) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Pet) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::GameObject) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::DynamicObject) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::AreaTrigger) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Corpse) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::LootObject) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::SceneObject) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Scenario) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::AIGroup) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::DynamicDoor) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Vignette) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::CallForHelp) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::AIResource) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::AILock) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::AILockTicket) diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index def19abca78..8bc2ee4df28 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -180,11 +180,11 @@ class PackedGuid; #pragma pack(push, 1) -class ObjectGuid +class TC_GAME_API ObjectGuid { - friend std::ostream& operator<<(std::ostream& stream, ObjectGuid const& guid); - friend ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid); - friend ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid); + friend TC_GAME_API std::ostream& operator<<(std::ostream& stream, ObjectGuid const& guid); + friend TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid); + friend TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid); public: static ObjectGuid const Empty; @@ -332,9 +332,9 @@ typedef std::unordered_set<ObjectGuid> GuidUnorderedSet; // maximum buffer size for packed guid is 18 bytes #define PACKED_GUID_MIN_BUFFER_SIZE 18 -class PackedGuid +class TC_GAME_API PackedGuid { - friend ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid); + friend TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid); public: explicit PackedGuid() : _packedGuid(PACKED_GUID_MIN_BUFFER_SIZE) { _packedGuid << uint16(0); } @@ -348,7 +348,7 @@ class PackedGuid ByteBuffer _packedGuid; }; -class ObjectGuidGeneratorBase +class TC_GAME_API ObjectGuidGeneratorBase { public: ObjectGuidGeneratorBase(ObjectGuid::LowType start = UI64LIT(1)) : _nextGuid(start) { } @@ -363,7 +363,7 @@ protected: }; template<HighGuid high> -class ObjectGuidGenerator : public ObjectGuidGeneratorBase +class TC_GAME_API ObjectGuidGenerator : public ObjectGuidGeneratorBase { public: explicit ObjectGuidGenerator(ObjectGuid::LowType start = UI64LIT(1)) : ObjectGuidGeneratorBase(start) { } @@ -376,12 +376,12 @@ public: } }; -ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid); -ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid); +TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid); +TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid); -ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid); +TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid); -std::ostream& operator<<(std::ostream& stream, ObjectGuid const& guid); +TC_GAME_API std::ostream& operator<<(std::ostream& stream, ObjectGuid const& guid); namespace std { diff --git a/src/server/game/Entities/Object/ObjectPosSelector.h b/src/server/game/Entities/Object/ObjectPosSelector.h index 26a23678009..84c694abf08 100644 --- a/src/server/game/Entities/Object/ObjectPosSelector.h +++ b/src/server/game/Entities/Object/ObjectPosSelector.h @@ -30,7 +30,7 @@ inline UsedPosType operator ~(UsedPosType uptype) return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS; } -struct ObjectPosSelector +struct TC_GAME_API ObjectPosSelector { struct UsedPos { diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index cc528b973f8..a941a2141f1 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -24,7 +24,7 @@ class ByteBuffer; -struct Position +struct TC_GAME_API Position { Position(float x = 0, float y = 0, float z = 0, float o = 0) : m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { } @@ -225,7 +225,7 @@ public: #define MAPID_INVALID 0xFFFFFFFF -class WorldLocation : public Position +class TC_GAME_API WorldLocation : public Position { public: explicit WorldLocation(uint32 mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f) @@ -256,11 +256,11 @@ public: uint32 m_mapId; }; -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); +TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); +TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); +TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); +TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); +TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); +TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); #endif // Trinity_game_Position_h__ diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h index 6d0d2fecca5..046916ea9d1 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h +++ b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h @@ -37,17 +37,17 @@ enum UpdatefieldFlags UF_FLAG_URGENT_SELF_ONLY = 0x400 }; -extern uint32 ItemUpdateFieldFlags[CONTAINER_END]; -extern uint32 ItemDynamicUpdateFieldFlags[CONTAINER_DYNAMIC_END]; -extern uint32 UnitUpdateFieldFlags[PLAYER_END]; -extern uint32 UnitDynamicUpdateFieldFlags[PLAYER_DYNAMIC_END]; -extern uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END]; -extern uint32 GameObjectDynamicUpdateFieldFlags[GAMEOBJECT_DYNAMIC_END]; -extern uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END]; -extern uint32 CorpseUpdateFieldFlags[CORPSE_END]; -extern uint32 AreaTriggerUpdateFieldFlags[AREATRIGGER_END]; -extern uint32 SceneObjectUpdateFieldFlags[SCENEOBJECT_END]; -extern uint32 ConversationUpdateFieldFlags[CONVERSATION_END]; -extern uint32 ConversationDynamicUpdateFieldFlags[CONVERSATION_DYNAMIC_END]; +TC_GAME_API extern uint32 ItemUpdateFieldFlags[CONTAINER_END]; +TC_GAME_API extern uint32 ItemDynamicUpdateFieldFlags[CONTAINER_DYNAMIC_END]; +TC_GAME_API extern uint32 UnitUpdateFieldFlags[PLAYER_END]; +TC_GAME_API extern uint32 UnitDynamicUpdateFieldFlags[PLAYER_DYNAMIC_END]; +TC_GAME_API extern uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END]; +TC_GAME_API extern uint32 GameObjectDynamicUpdateFieldFlags[GAMEOBJECT_DYNAMIC_END]; +TC_GAME_API extern uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END]; +TC_GAME_API extern uint32 CorpseUpdateFieldFlags[CORPSE_END]; +TC_GAME_API extern uint32 AreaTriggerUpdateFieldFlags[AREATRIGGER_END]; +TC_GAME_API extern uint32 SceneObjectUpdateFieldFlags[SCENEOBJECT_END]; +TC_GAME_API extern uint32 ConversationUpdateFieldFlags[CONVERSATION_END]; +TC_GAME_API extern uint32 ConversationDynamicUpdateFieldFlags[CONVERSATION_DYNAMIC_END]; #endif // _UPDATEFIELDFLAGS_H diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index bc989b515eb..170b881fa50 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -43,7 +43,7 @@ typedef std::vector<uint32> AutoSpellList; class Player; -class Pet : public Guardian +class TC_GAME_API Pet : public Guardian { public: explicit Pet(Player* owner, PetType type = MAX_PET_TYPE); diff --git a/src/server/game/Entities/Player/CollectionMgr.h b/src/server/game/Entities/Player/CollectionMgr.h index 6870cd5732d..aa2f70d4df9 100644 --- a/src/server/game/Entities/Player/CollectionMgr.h +++ b/src/server/game/Entities/Player/CollectionMgr.h @@ -45,7 +45,7 @@ struct HeirloomData typedef std::map<uint32, bool> ToyBoxContainer; typedef std::map<uint32, HeirloomData> HeirloomContainer; -class CollectionMgr +class TC_GAME_API CollectionMgr { public: explicit CollectionMgr(WorldSession* owner) : _owner(owner) { } diff --git a/src/server/game/Entities/Player/KillRewarder.h b/src/server/game/Entities/Player/KillRewarder.h index 08530de900c..210e5ff0246 100644 --- a/src/server/game/Entities/Player/KillRewarder.h +++ b/src/server/game/Entities/Player/KillRewarder.h @@ -24,7 +24,7 @@ class Player; class Unit; class Group; -class KillRewarder +class TC_GAME_API KillRewarder { public: KillRewarder(Player* killer, Unit* victim, bool isBattleGround); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 60ae8d6b075..950a1ff0841 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -167,8 +167,6 @@ Player::Player(WorldSession* session) : Unit(true) m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE); - _resurrectionData = nullptr; - memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); m_social = nullptr; @@ -403,8 +401,6 @@ Player::~Player() for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) delete _voidStorageItems[i]; - ClearResurrectRequestData(); - sWorld->DecreasePlayerCount(); } @@ -1366,6 +1362,7 @@ void Player::Update(uint32 p_time) //because we don't want player's ghost teleported from graveyard if (IsHasDelayedTeleport() && IsAlive()) TeleportTo(m_teleport_dest, m_teleport_options); + } void Player::setDeathState(DeathState s) @@ -1562,7 +1559,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // Check enter rights before map getting to avoid creating instance copy for player // this check not dependent from map instance copy and same for all instance copies of selected map - if (!sMapMgr->CanPlayerEnter(mapid, this, false)) + if (sMapMgr->PlayerCannotEnter(mapid, this, false)) return false; // Seamless teleport can happen only if cosmetic maps match @@ -1706,28 +1703,7 @@ void Player::ProcessDelayedOperations() return; if (m_DelayedOperations & DELAYED_RESURRECT_PLAYER) - { - ResurrectPlayer(0.0f, false); - - if (GetMaxHealth() > _resurrectionData->Health) - SetHealth(_resurrectionData->Health); - else - SetFullHealth(); - - if (uint32(GetMaxPower(POWER_MANA)) > _resurrectionData->Mana) - SetPower(POWER_MANA, _resurrectionData->Mana); - else - SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); - - SetPower(POWER_RAGE, 0); - SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY)); - SetPower(POWER_ECLIPSE, 0); - - if (uint32 aura = _resurrectionData->Aura) - CastSpell(this, aura, true, nullptr, nullptr, _resurrectionData->GUID); - - SpawnCorpseBones(); - } + ResurrectUsingRequestDataImpl(); if (m_DelayedOperations & DELAYED_SAVE_PLAYER) SaveToDB(); @@ -2298,7 +2274,7 @@ void Player::SetGameMaster(bool on) bool Player::CanBeGameMaster() const { - return m_session && m_session->HasPermission(rbac::RBAC_PERM_COMMAND_GM); + return GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_GM); } void Player::SetGMVisible(bool on) @@ -6894,6 +6870,7 @@ void Player::UpdateArea(uint32 newArea) UpdatePvPState(true); UpdateAreaDependentAuras(newArea); + UpdateAreaPhase(); // previously this was in UpdateZone (but after UpdateArea) so nothing will break pvpInfo.IsInNoPvPArea = false; @@ -15069,13 +15046,7 @@ QuestStatus Player::GetQuestStatus(uint32 quest_id) const bool Player::CanShareQuest(uint32 quest_id) const { Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id); - if (qInfo && qInfo->HasFlag(QUEST_FLAGS_SHARABLE)) - { - QuestStatusMap::const_iterator itr = m_QuestStatus.find(quest_id); - if (itr != m_QuestStatus.end()) - return itr->second.Status == QUEST_STATUS_INCOMPLETE; - } - return false; + return qInfo && qInfo->HasFlag(QUEST_FLAGS_SHARABLE) && IsActiveQuest(quest_id); } void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*= true*/) @@ -16658,7 +16629,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) // NOW player must have valid map // load the player's map here if it's not already loaded - Map* map = sMapMgr->CreateMap(mapId, this); + Map* map = sMapMgr->CreateMap(mapId, this, instanceId); AreaTriggerStruct const* areaTrigger = nullptr; bool check = false; @@ -16669,8 +16640,28 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) } else if (map->IsDungeon()) // if map is dungeon... { - if (!((InstanceMap*)map)->CanEnter(this) || !CheckInstanceLoginValid(map)) // ... and can't enter map, then look for entry point. + if (Map::EnterState denyReason = ((InstanceMap*)map)->CannotEnter(this)) // ... and can't enter map, then look for entry point. { + switch (denyReason) + { + case Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_DIFFICULTY, map->GetDifficultyID()); + break; + case Map::CANNOT_ENTER_INSTANCE_BIND_MISMATCH: + ChatHandler(GetSession()).PSendSysMessage(GetSession()->GetTrinityString(LANG_INSTANCE_BIND_MISMATCH), map->GetMapName()); + break; + case Map::CANNOT_ENTER_TOO_MANY_INSTANCES: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_TOO_MANY_INSTANCES); + break; + case Map::CANNOT_ENTER_MAX_PLAYERS: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_MAX_PLAYERS); + break; + case Map::CANNOT_ENTER_ZONE_IN_COMBAT: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); + break; + default: + break; + } areaTrigger = sObjectMgr->GetGoBackTrigger(mapId); check = true; } @@ -16716,6 +16707,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) SetMap(map); + // now that map position is determined, check instance validity + if (!CheckInstanceValidity(true) && !IsInstanceLoginGameMasterException()) + m_InstanceValid = false; + // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] // this must help in case next save after mass player load after server startup m_nextSave = urand(m_nextSave / 2, m_nextSave * 3 / 2); @@ -18314,31 +18309,6 @@ void Player::SendRaidInfo() GetSession()->SendPacket(instanceInfo.Write()); } -/// convert the player's binds to the group -void Player::ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader) -{ - // copy all binds to the group, when changing leader it's assumed the character - // will not have any solo binds - - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) - { - if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficultyID(), itr->first)) - group->BindToInstance(itr->second.save, itr->second.perm, false); - - // permanent binds are not removed - if (switchLeader && !itr->second.perm) - { - // increments itr in call - player->UnbindInstance(itr, Difficulty(i), false); - } - else - ++itr; - } - } -} - bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report) { if (!IsGameMaster() && ar) @@ -18411,37 +18381,68 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report return true; } -bool Player::CheckInstanceLoginValid(Map* map) +bool Player::IsInstanceLoginGameMasterException() const { - if (!map->IsDungeon() || IsGameMaster()) - return true; - - if (map->IsRaid()) + if (CanBeGameMaster()) { - // cannot be in raid instance without a group - if (!GetGroup()) - return IsInstanceLoginGameMasterException(); + ChatHandler(GetSession()).SendSysMessage(LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION); + return true; } else - { - // cannot be in normal instance without a group and more players than 1 in instance - if (!GetGroup() && map->GetPlayersCountExceptGMs() > 1) - return IsInstanceLoginGameMasterException(); - } - - // do checks for satisfy accessreqs, instance full, encounter in progress (raid), perm bind group != perm bind player - return sMapMgr->CanPlayerEnter(map->GetId(), this, true) || IsInstanceLoginGameMasterException(); + return false; } -bool Player::IsInstanceLoginGameMasterException() const +bool Player::CheckInstanceValidity(bool /*isLogin*/) { - if (CanBeGameMaster()) - { - ChatHandler(GetSession()).PSendSysMessage("You didn't get kicked out of the instance even if Player::CheckInstanceLoginValid() returned false and without .gm on flag"); + // game masters' instances are always valid + if (IsGameMaster()) + return true; + + // non-instances are always valid + Map* map = GetMap(); + if (!map || !map->IsDungeon()) return true; + + // raid instances require the player to be in a raid group to be valid + if (map->IsRaid() && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) + if (!GetGroup() || !GetGroup()->isRaidGroup()) + return false; + + if (Group* group = GetGroup()) + { + // check if player's group is bound to this instance + InstanceGroupBind* bind = group->GetBoundInstance(map->GetDifficultyID(), map->GetId()); + if (!bind || !bind->save || bind->save->GetInstanceId() != map->GetInstanceId()) + return false; + + Map::PlayerList const& players = map->GetPlayers(); + if (!players.isEmpty()) + for (Map::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it) + { + if (Player* otherPlayer = it->GetSource()) + { + if (otherPlayer->IsGameMaster()) + continue; + if (!otherPlayer->m_InstanceValid) // ignore players that currently have a homebind timer active + continue; + if (group != otherPlayer->GetGroup()) + return false; + } + } } else - return false; + { + // instance is invalid if we are not grouped and there are other players + if (map->GetPlayersCountExceptGMs() > 1) + return false; + + // check if the player is bound to this instance + InstancePlayerBind* bind = GetBoundInstance(map->GetId(), map->GetDifficultyID()); + if (!bind || !bind->save || bind->save->GetInstanceId() != map->GetInstanceId()) + return false; + } + + return true; } bool Player::CheckInstanceCount(uint32 instanceId) const @@ -21511,13 +21512,14 @@ void Player::UpdatePotionCooldown(Spell* spell) void Player::SetResurrectRequestData(Unit* caster, uint32 health, uint32 mana, uint32 appliedAura) { ASSERT(!IsResurrectRequested()); - _resurrectionData = new ResurrectionData(); + _resurrectionData.reset(new ResurrectionData()); _resurrectionData->GUID = caster->GetGUID(); _resurrectionData->Location.WorldRelocate(*caster); _resurrectionData->Health = health; _resurrectionData->Mana = mana; _resurrectionData->Aura = appliedAura; } + //slot to be excluded while counting bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) const { @@ -23429,9 +23431,7 @@ bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const void Player::ResurrectUsingRequestData() { /// Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse - float x, y, z, o; - _resurrectionData->Location.GetPosition(x, y, z, o); - TeleportTo(_resurrectionData->Location.GetMapId(), x, y, z, o); + TeleportTo(_resurrectionData->Location); if (IsBeingTeleported()) { @@ -23439,6 +23439,11 @@ void Player::ResurrectUsingRequestData() return; } + ResurrectUsingRequestDataImpl(); +} + +void Player::ResurrectUsingRequestDataImpl() +{ ResurrectPlayer(0.0f, false); if (GetMaxHealth() > _resurrectionData->Health) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 07d7c80a5e2..3fc5a7d76fd 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -115,7 +115,7 @@ struct PlayerSpell bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; -extern uint32 const MasterySpells[MAX_CLASSES]; +TC_GAME_API extern uint32 const MasterySpells[MAX_CLASSES]; enum TalentSpecialization // talent tabs { @@ -1012,7 +1012,7 @@ enum PlayerDelayedOperations // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) // Maximum money amount : 2^31 - 1 -extern uint64 const MAX_MONEY_AMOUNT; +TC_GAME_API extern uint64 const MAX_MONEY_AMOUNT; struct InstancePlayerBind { @@ -1146,7 +1146,7 @@ struct ResurrectionData static uint32 const DefaultTalentRowLevels[MAX_TALENT_TIERS] = { 15, 30, 45, 60, 75, 90, 100 }; static uint32 const DKTalentRowLevels[MAX_TALENT_TIERS] = { 57, 58, 59, 60, 75, 90, 100 }; -struct PlayerTalentInfo +struct TC_GAME_API PlayerTalentInfo { PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), @@ -1182,7 +1182,7 @@ private: PlayerTalentInfo(PlayerTalentInfo const&); }; -class Player : public Unit, public GridObject<Player> +class TC_GAME_API Player : public Unit, public GridObject<Player> { friend class WorldSession; friend void Item::AddToUpdateQueueOf(Player* player); @@ -1813,11 +1813,10 @@ class Player : public Unit, public GridObject<Player> void SetResurrectRequestData(Unit* caster, uint32 health, uint32 mana, uint32 appliedAura); void ClearResurrectRequestData() { - delete _resurrectionData; - _resurrectionData = nullptr; + _resurrectionData.reset(); } - bool IsResurrectRequestedBy(ObjectGuid guid) const + bool IsResurrectRequestedBy(ObjectGuid const& guid) const { if (!IsResurrectRequested()) return false; @@ -1825,8 +1824,9 @@ class Player : public Unit, public GridObject<Player> return !_resurrectionData->GUID.IsEmpty() && _resurrectionData->GUID == guid; } - bool IsResurrectRequested() const { return _resurrectionData != nullptr; } + bool IsResurrectRequested() const { return _resurrectionData.get() != nullptr; } void ResurrectUsingRequestData(); + void ResurrectUsingRequestDataImpl(); uint8 getCinematic() const { return m_cinematic; } void setCinematic(uint8 cine) { m_cinematic = cine; } @@ -2353,9 +2353,8 @@ class Player : public Unit, public GridObject<Player> void SetPendingBind(uint32 instanceId, uint32 bindTimer); bool HasPendingBind() const { return _pendingBindId > 0; } void SendRaidInfo(); - static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader); bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false); - bool CheckInstanceLoginValid(Map* map); + bool CheckInstanceValidity(bool /*isLogin*/); bool CheckInstanceCount(uint32 instanceId) const; void AddInstanceEnterTime(uint32 instanceId, time_t enterTime); @@ -2685,7 +2684,7 @@ class Player : public Unit, public GridObject<Player> void ResetTimeSync(); void SendTimeSync(); - ResurrectionData* _resurrectionData; + std::unique_ptr<ResurrectionData> _resurrectionData; WorldSession* m_session; @@ -2838,8 +2837,8 @@ class Player : public Unit, public GridObject<Player> WorldLocation _corpseLocation; }; -void AddItemsSetItem(Player* player, Item* item); -void RemoveItemsSetItem(Player* player, ItemTemplate const* proto); +TC_GAME_API void AddItemsSetItem(Player* player, Item* item); +TC_GAME_API void RemoveItemsSetItem(Player* player, ItemTemplate const* proto); // "the bodies of template functions must be made available in a header file" template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell) diff --git a/src/server/game/Entities/Player/PlayerTaxi.h b/src/server/game/Entities/Player/PlayerTaxi.h index fb73042cb84..13aeed19ef8 100644 --- a/src/server/game/Entities/Player/PlayerTaxi.h +++ b/src/server/game/Entities/Player/PlayerTaxi.h @@ -6,7 +6,7 @@ #include "WorldSession.h" #include <map> -class PlayerTaxi +class TC_GAME_API PlayerTaxi { public: PlayerTaxi() { m_taximask.fill(0); } diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp index 6244475c458..7870c754ffc 100644 --- a/src/server/game/Entities/Player/SocialMgr.cpp +++ b/src/server/game/Entities/Player/SocialMgr.cpp @@ -161,6 +161,12 @@ bool PlayerSocial::HasIgnore(ObjectGuid const& ignoreGuid) return _HasContact(ignoreGuid, SOCIAL_FLAG_IGNORED); } +SocialMgr* SocialMgr::instance() +{ + static SocialMgr instance; + return &instance; +} + void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo) { if (!player) diff --git a/src/server/game/Entities/Player/SocialMgr.h b/src/server/game/Entities/Player/SocialMgr.h index d2237e328a7..df409106bdc 100644 --- a/src/server/game/Entities/Player/SocialMgr.h +++ b/src/server/game/Entities/Player/SocialMgr.h @@ -100,7 +100,7 @@ enum FriendsResult : uint8 #define SOCIALMGR_FRIEND_LIMIT 50u #define SOCIALMGR_IGNORE_LIMIT 50u -class PlayerSocial +class TC_GAME_API PlayerSocial { friend class SocialMgr; @@ -138,11 +138,7 @@ class SocialMgr ~SocialMgr() { } public: - static SocialMgr* instance() - { - static SocialMgr instance; - return &instance; - } + static SocialMgr* instance(); // Misc void RemovePlayerSocial(ObjectGuid const& guid) { _socialMap.erase(guid); } diff --git a/src/server/game/Entities/Player/TradeData.h b/src/server/game/Entities/Player/TradeData.h index 0dfded6c4aa..365f7a9fa82 100644 --- a/src/server/game/Entities/Player/TradeData.h +++ b/src/server/game/Entities/Player/TradeData.h @@ -31,7 +31,7 @@ enum TradeSlots class Item; class Player; -class TradeData +class TC_GAME_API TradeData { public: TradeData(Player* player, Player* trader) : diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp index 5fe2db46fa5..6617267be6a 100644 --- a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp +++ b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp @@ -25,6 +25,12 @@ #include <boost/graph/dijkstra_shortest_paths.hpp> #include <boost/property_map/transform_value_property_map.hpp> +TaxiPathGraph& TaxiPathGraph::Instance() +{ + static TaxiPathGraph instance; + return instance; +} + void TaxiPathGraph::Initialize() { if (GetVertexCount() > 0) diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.h b/src/server/game/Entities/Taxi/TaxiPathGraph.h index 0da1090ef8f..24ec3ce9a7e 100644 --- a/src/server/game/Entities/Taxi/TaxiPathGraph.h +++ b/src/server/game/Entities/Taxi/TaxiPathGraph.h @@ -25,14 +25,10 @@ class Player; struct TaxiNodesEntry; -class TaxiPathGraph +class TC_GAME_API TaxiPathGraph { public: - static TaxiPathGraph& Instance() - { - static TaxiPathGraph instance; - return instance; - } + static TaxiPathGraph& Instance(); void Initialize(); std::size_t GetCompleteNodeRoute(TaxiNodesEntry const* from, TaxiNodesEntry const* to, Player const* player, std::vector<uint32>& shortestPath); diff --git a/src/server/game/Entities/Totem/Totem.h b/src/server/game/Entities/Totem/Totem.h index f0a4af3a3d7..14bb60f916f 100644 --- a/src/server/game/Entities/Totem/Totem.h +++ b/src/server/game/Entities/Totem/Totem.h @@ -35,7 +35,7 @@ enum TotemSpells SPELL_TOTEMIC_WRATH = 77747 }; -class Totem : public Minion +class TC_GAME_API Totem : public Minion { public: Totem(SummonPropertiesEntry const* properties, Unit* owner); diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 9385d262ad8..f4d2866fbb3 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -25,7 +25,7 @@ struct CreatureData; -class Transport : public GameObject, public TransportBase +class TC_GAME_API Transport : public GameObject, public TransportBase { friend Transport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*, uint32, uint32); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0e61c3d0df9..9a2a955d74d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -10746,7 +10746,7 @@ void Unit::TauntFadeOut(Unit* taunter) if (m_ThreatManager.isThreatListEmpty()) { if (creature->IsAIEnabled) - creature->AI()->EnterEvadeMode(); + creature->AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES); return; } @@ -10887,7 +10887,7 @@ Unit* Creature::SelectVictim() } // enter in evade mode in other case - AI()->EnterEvadeMode(); + AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES); return NULL; } @@ -11048,9 +11048,6 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* if (!spellInfo || castTime < 0) return; - if (spellInfo->IsChanneled() && !spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) - return; - // called from caster if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell); @@ -11064,6 +11061,25 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* castTime = 500; } +void Unit::ModSpellDurationTime(SpellInfo const* spellInfo, int32 & duration, Spell* spell) +{ + if (!spellInfo || duration < 0) + return; + + if (spellInfo->IsChanneled() && !spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) + return; + + // called from caster + if (Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, duration, spell); + + if (!(spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) && + ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT)) + duration = int32(float(duration) * GetFloatValue(UNIT_MOD_CAST_SPEED)); + else if (spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && !spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG)) + duration = int32(float(duration) * m_modAttackSpeedPct[RANGED_ATTACK]); +} + DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) { for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9902b2a2af9..d6e3d01b09a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -609,8 +609,8 @@ enum UnitMoveType #define MAX_MOVE_TYPE 9 -extern float baseMoveSpeed[MAX_MOVE_TYPE]; -extern float playerBaseMoveSpeed[MAX_MOVE_TYPE]; +TC_GAME_API extern float baseMoveSpeed[MAX_MOVE_TYPE]; +TC_GAME_API extern float playerBaseMoveSpeed[MAX_MOVE_TYPE]; enum WeaponAttackType : uint16 { @@ -918,7 +918,7 @@ struct CleanDamage struct CalcDamageInfo; -class DamageInfo +class TC_GAME_API DamageInfo { private: Unit* const m_attacker; @@ -981,7 +981,7 @@ public: SpellSchoolMask GetSchoolMask() const { return _schoolMask; }; }; -class ProcEventInfo +class TC_GAME_API ProcEventInfo { public: ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask, @@ -1039,7 +1039,7 @@ struct CalcDamageInfo }; // Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode -struct SpellNonMeleeDamage +struct TC_GAME_API SpellNonMeleeDamage { SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _schoolMask); @@ -1198,7 +1198,7 @@ enum ActionBarIndex #define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START) -struct CharmInfo +struct TC_GAME_API CharmInfo { public: explicit CharmInfo(Unit* unit); @@ -1302,7 +1302,7 @@ enum PlayerTotemType struct SpellProcEventEntry; // used only privately -class Unit : public WorldObject +class TC_GAME_API Unit : public WorldObject { public: typedef std::set<Unit*> AttackerSet; @@ -2091,6 +2091,7 @@ class Unit : public WorldObject int32 CalcSpellDuration(SpellInfo const* spellProto); int32 ModSpellDuration(SpellInfo const* spellProto, Unit const* target, int32 duration, bool positive, uint32 effectMask); void ModSpellCastTime(SpellInfo const* spellProto, int32& castTime, Spell* spell = NULL); + void ModSpellDurationTime(SpellInfo const* spellProto, int32& castTime, Spell* spell = NULL); float CalculateLevelPenalty(SpellInfo const* spellProto) const; void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 10341a7c029..dbaaa3b7b9f 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -29,7 +29,7 @@ struct VehicleEntry; class Unit; class VehicleJoinEvent; -class Vehicle : public TransportBase +class TC_GAME_API Vehicle : public TransportBase { protected: friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry, bool); @@ -118,7 +118,7 @@ class Vehicle : public TransportBase PendingJoinEventContainer _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers }; -class VehicleJoinEvent : public BasicEvent +class TC_GAME_API VehicleJoinEvent : public BasicEvent { friend class Vehicle; protected: diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 89d2a53c071..879e5032b73 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -29,6 +29,12 @@ #include "GameObjectAI.h" #include "WorldStatePackets.h" +GameEventMgr* GameEventMgr::instance() +{ + static GameEventMgr instance; + return &instance; +} + bool GameEventMgr::CheckOneGameEvent(uint16 entry) const { switch (mGameEvent[entry].state) diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index aaff9c3700f..312f4de4b80 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -94,18 +94,14 @@ class Player; class Creature; class Quest; -class GameEventMgr +class TC_GAME_API GameEventMgr { private: GameEventMgr(); ~GameEventMgr() { } public: - static GameEventMgr* instance() - { - static GameEventMgr instance; - return &instance; - } + static GameEventMgr* instance(); typedef std::set<uint16> ActiveEvents; typedef std::vector<GameEventData> GameEventDataMap; @@ -187,8 +183,8 @@ class GameEventMgr #define sGameEventMgr GameEventMgr::instance() -bool IsHolidayActive(HolidayIds id); -bool IsEventActive(uint16 event_id); +TC_GAME_API bool IsHolidayActive(HolidayIds id); +TC_GAME_API bool IsEventActive(uint16 event_id); #endif diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h index e35df29997b..2aa38ee6ad3 100644 --- a/src/server/game/Garrison/Garrison.h +++ b/src/server/game/Garrison/Garrison.h @@ -80,7 +80,7 @@ enum GarrisonFollowerStatus class GameObject; class Map; -class Garrison +class TC_GAME_API Garrison { public: struct Building diff --git a/src/server/game/Garrison/GarrisonMap.h b/src/server/game/Garrison/GarrisonMap.h index 57bc114970c..c04cf9d9a24 100644 --- a/src/server/game/Garrison/GarrisonMap.h +++ b/src/server/game/Garrison/GarrisonMap.h @@ -23,7 +23,7 @@ class Garrison; class Player; -class GarrisonMap : public Map +class TC_GAME_API GarrisonMap : public Map { public: GarrisonMap(uint32 id, time_t, uint32 instanceId, Map* parent, ObjectGuid const& owner); diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp index 9be49fec2ad..5c9bef62fc3 100644 --- a/src/server/game/Garrison/GarrisonMgr.cpp +++ b/src/server/game/Garrison/GarrisonMgr.cpp @@ -24,6 +24,12 @@ #include "GameObject.h" #include "ObjectMgr.h" +GarrisonMgr& GarrisonMgr::Instance() +{ + static GarrisonMgr instance; + return instance; +} + void GarrisonMgr::Initialize() { for (GarrSiteLevelPlotInstEntry const* plotInstance : sGarrSiteLevelPlotInstStore) diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h index 91c133af0cd..6130fd67b25 100644 --- a/src/server/game/Garrison/GarrisonMgr.h +++ b/src/server/game/Garrison/GarrisonMgr.h @@ -38,14 +38,10 @@ struct GarrAbilities std::unordered_set<GarrAbilityEntry const*> Traits; }; -class GarrisonMgr +class TC_GAME_API GarrisonMgr { public: - static GarrisonMgr& Instance() - { - static GarrisonMgr instance; - return instance; - } + static GarrisonMgr& Instance(); void Initialize(); diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 695591fb1c7..7cb21321f04 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -34,6 +34,48 @@ #include <boost/thread/shared_mutex.hpp> #include <boost/thread/locks.hpp> +template<class T> +void HashMapHolder<T>::Insert(T* o) +{ + boost::unique_lock<boost::shared_mutex> lock(*GetLock()); + + GetContainer()[o->GetGUID()] = o; +} + +template<class T> +void HashMapHolder<T>::Remove(T* o) +{ + boost::unique_lock<boost::shared_mutex> lock(*GetLock()); + + GetContainer().erase(o->GetGUID()); +} + +template<class T> +T* HashMapHolder<T>::Find(ObjectGuid guid) +{ + boost::shared_lock<boost::shared_mutex> lock(*GetLock()); + + typename MapType::iterator itr = GetContainer().find(guid); + return (itr != GetContainer().end()) ? itr->second : NULL; +} + +template<class T> +auto HashMapHolder<T>::GetContainer() -> MapType& +{ + static MapType _objectMap; + return _objectMap; +} + +template<class T> +boost::shared_mutex* HashMapHolder<T>::GetLock() +{ + static boost::shared_mutex _lock; + return &_lock; +} + +template class TC_GAME_API HashMapHolder<Player>; +template class TC_GAME_API HashMapHolder<Transport>; + WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid const& guid) { switch (guid.GetHigh()) @@ -226,12 +268,3 @@ void ObjectAccessor::SaveAllPlayers() for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) itr->second->SaveToDB(); } - -/// Define the static members of HashMapHolder - -template <class T> typename HashMapHolder<T>::MapType HashMapHolder<T>::_objectMap; -template <class T> boost::shared_mutex HashMapHolder<T>::_lock; - -/// Global definitions for the hashmap storage -template class HashMapHolder<Player>; -template class HashMapHolder<Transport>; diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index 1c1ec6b3451..83bbdf42239 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -42,77 +42,57 @@ class WorldRunnable; class Transport; template <class T> -class HashMapHolder +class TC_GAME_API HashMapHolder { - public: - static_assert(std::is_same<Player, T>::value - || std::is_same<Transport, T>::value, - "Only Player and Transport can be registered in global HashMapHolder"); + //Non instanceable only static + HashMapHolder() { } - typedef std::unordered_map<ObjectGuid, T*> MapType; +public: + static_assert(std::is_same<Player, T>::value + || std::is_same<Transport, T>::value, + "Only Player and Transport can be registered in global HashMapHolder"); - static void Insert(T* o) - { - boost::unique_lock<boost::shared_mutex> lock(_lock); + typedef std::unordered_map<ObjectGuid, T*> MapType; - _objectMap[o->GetGUID()] = o; - } + static void Insert(T* o); - static void Remove(T* o) - { - boost::unique_lock<boost::shared_mutex> lock(_lock); + static void Remove(T* o); - _objectMap.erase(o->GetGUID()); - } + static T* Find(ObjectGuid guid); - static T* Find(ObjectGuid guid) - { - boost::shared_lock<boost::shared_mutex> lock(_lock); + static MapType& GetContainer(); - typename MapType::iterator itr = _objectMap.find(guid); - return (itr != _objectMap.end()) ? itr->second : NULL; - } - - static MapType& GetContainer() { return _objectMap; } - - static boost::shared_mutex* GetLock() { return &_lock; } - - private: - //Non instanceable only static - HashMapHolder() { } - - static boost::shared_mutex _lock; - static MapType _objectMap; + static boost::shared_mutex* GetLock(); }; namespace ObjectAccessor { // these functions return objects only if in map of specified object - WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const&); - Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask); - Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid); - GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid); - Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid); - DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid); - AreaTrigger* GetAreaTrigger(WorldObject const& u, ObjectGuid const& guid); - Unit* GetUnit(WorldObject const&, ObjectGuid const& guid); - Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid); - Pet* GetPet(WorldObject const&, ObjectGuid const& guid); - Player* GetPlayer(Map const*, ObjectGuid const& guid); - Player* GetPlayer(WorldObject const&, ObjectGuid const& guid); - Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&); + TC_GAME_API WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const&); + TC_GAME_API Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask); + TC_GAME_API Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API AreaTrigger* GetAreaTrigger(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API Unit* GetUnit(WorldObject const&, ObjectGuid const& guid); + TC_GAME_API Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API Pet* GetPet(WorldObject const&, ObjectGuid const& guid); + TC_GAME_API Player* GetPlayer(Map const*, ObjectGuid const& guid); + TC_GAME_API Player* GetPlayer(WorldObject const&, ObjectGuid const& guid); + TC_GAME_API Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&); // these functions return objects if found in whole world // ACCESS LIKE THAT IS NOT THREAD SAFE - Player* FindPlayer(ObjectGuid const&); - Player* FindPlayerByName(std::string const& name); + TC_GAME_API Player* FindPlayer(ObjectGuid const&); + TC_GAME_API Player* FindPlayerByName(std::string const& name); // this returns Player even if he is not in world, for example teleporting - Player* FindConnectedPlayer(ObjectGuid const&); - Player* FindConnectedPlayerByName(std::string const& name); + TC_GAME_API Player* FindConnectedPlayer(ObjectGuid const&); + TC_GAME_API Player* FindConnectedPlayerByName(std::string const& name); // when using this, you must use the hashmapholder's lock - HashMapHolder<Player>::MapType const& GetPlayers(); + TC_GAME_API HashMapHolder<Player>::MapType const& GetPlayers(); template<class T> void AddObject(T* object) @@ -126,7 +106,8 @@ namespace ObjectAccessor HashMapHolder<T>::Remove(object); } - void SaveAllPlayers(); + TC_GAME_API void SaveAllPlayers(); }; #endif + diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 2efcc71ae75..85adc2764ab 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -251,6 +251,12 @@ ObjectMgr::ObjectMgr(): _playerInfo[j][i] = NULL; } +ObjectMgr* ObjectMgr::instance() +{ + static ObjectMgr instance; + return &instance; +} + ObjectMgr::~ObjectMgr() { for (QuestMap::iterator i = _questTemplates.begin(); i != _questTemplates.end(); ++i) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 7fb35c15504..f67d753cf7c 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -376,15 +376,15 @@ typedef std::multimap<uint32, ScriptInfo> ScriptMap; typedef std::map<uint32, ScriptMap > ScriptMapMap; typedef std::multimap<uint32, uint32> SpellScriptsContainer; typedef std::pair<SpellScriptsContainer::iterator, SpellScriptsContainer::iterator> SpellScriptsBounds; -extern ScriptMapMap sSpellScripts; -extern ScriptMapMap sEventScripts; -extern ScriptMapMap sWaypointScripts; +TC_GAME_API extern ScriptMapMap sSpellScripts; +TC_GAME_API extern ScriptMapMap sEventScripts; +TC_GAME_API extern ScriptMapMap sWaypointScripts; std::string GetScriptsTableNameByType(ScriptsType type); ScriptMapMap* GetScriptsMapByType(ScriptsType type); std::string GetScriptCommandName(ScriptCommands command); -struct SpellClickInfo +struct TC_GAME_API SpellClickInfo { uint32 spellId; uint8 castFlags; @@ -646,7 +646,7 @@ SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry); #define MAX_PET_NAME 12 // max allowed by client name length #define MAX_CHARTER_NAME 24 // max allowed by client name length -bool normalizePlayerName(std::string& name); +TC_GAME_API bool normalizePlayerName(std::string& name); struct ExtendedPlayerName { @@ -664,7 +664,7 @@ struct LanguageDesc uint32 skill_id; }; -extern LanguageDesc lang_description[LANGUAGES_COUNT]; +TC_GAME_API extern LanguageDesc lang_description[LANGUAGES_COUNT]; LanguageDesc const* GetLanguageDescByID(uint32 lang); enum EncounterCreditType @@ -699,7 +699,7 @@ typedef std::unordered_map<uint32, std::vector<PhaseInfoStruct>> PhaseInfo; // p class PlayerDumpReader; -class ObjectMgr +class TC_GAME_API ObjectMgr { friend class PlayerDumpReader; @@ -708,11 +708,13 @@ class ObjectMgr ~ObjectMgr(); public: - static ObjectMgr* instance() - { - static ObjectMgr instance; - return &instance; - } + ObjectMgr(ObjectMgr const&) = delete; + ObjectMgr(ObjectMgr&&) = delete; + + ObjectMgr& operator= (ObjectMgr const&) = delete; + ObjectMgr& operator= (ObjectMgr&&) = delete; + + static ObjectMgr* instance(); typedef std::unordered_map<uint32, Item*> ItemMap; diff --git a/src/server/game/Grids/GridStates.h b/src/server/game/Grids/GridStates.h index 9420bef4b9d..b567da43b69 100644 --- a/src/server/game/Grids/GridStates.h +++ b/src/server/game/Grids/GridStates.h @@ -24,32 +24,32 @@ class Map; -class GridState +class TC_GAME_API GridState { public: virtual ~GridState() { }; virtual void Update(Map &, NGridType&, GridInfo &, uint32 t_diff) const = 0; }; -class InvalidState : public GridState +class TC_GAME_API InvalidState : public GridState { public: void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override; }; -class ActiveState : public GridState +class TC_GAME_API ActiveState : public GridState { public: void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override; }; -class IdleState : public GridState +class TC_GAME_API IdleState : public GridState { public: void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override; }; -class RemovalState : public GridState +class TC_GAME_API RemovalState : public GridState { public: void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override; diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 553de2f1a1f..66540add24b 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -40,7 +40,7 @@ class Player; namespace Trinity { - struct VisibleNotifier + struct TC_GAME_API VisibleNotifier { Player &i_player; UpdateData i_data; @@ -63,7 +63,7 @@ namespace Trinity void Visit(DynamicObjectMapType &); }; - struct PlayerRelocationNotifier : public VisibleNotifier + struct TC_GAME_API PlayerRelocationNotifier : public VisibleNotifier { PlayerRelocationNotifier(Player &player) : VisibleNotifier(player) { } @@ -72,7 +72,7 @@ namespace Trinity void Visit(PlayerMapType &); }; - struct CreatureRelocationNotifier + struct TC_GAME_API CreatureRelocationNotifier { Creature &i_creature; CreatureRelocationNotifier(Creature &c) : i_creature(c) { } @@ -81,7 +81,7 @@ namespace Trinity void Visit(PlayerMapType &); }; - struct DelayedUnitRelocation + struct TC_GAME_API DelayedUnitRelocation { Map &i_map; Cell &cell; @@ -94,7 +94,7 @@ namespace Trinity void Visit(PlayerMapType &); }; - struct AIRelocationNotifier + struct TC_GAME_API AIRelocationNotifier { Unit &i_unit; bool isCreature; @@ -123,7 +123,7 @@ namespace Trinity void Visit(AreaTriggerMapType &m) { updateObjects<AreaTrigger>(m); } }; - struct MessageDistDeliverer + struct TC_GAME_API MessageDistDeliverer { WorldObject* i_source; WorldPacket const* i_message; @@ -580,7 +580,7 @@ namespace Trinity // WorldObject check classes - class AnyDeadUnitObjectInRangeCheck + class TC_GAME_API AnyDeadUnitObjectInRangeCheck { public: AnyDeadUnitObjectInRangeCheck(Unit* searchObj, float range) : i_searchObj(searchObj), i_range(range) { } @@ -593,7 +593,7 @@ namespace Trinity float i_range; }; - class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck + class TC_GAME_API AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck { public: AnyDeadUnitSpellTargetInRangeCheck(Unit* searchObj, float range, SpellInfo const* spellInfo, SpellTargetCheckTypes check) diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h index 11a54a3e7b0..d70f830ea68 100644 --- a/src/server/game/Grids/ObjectGridLoader.h +++ b/src/server/game/Grids/ObjectGridLoader.h @@ -27,7 +27,7 @@ class ObjectWorldLoader; -class ObjectGridLoader +class TC_GAME_API ObjectGridLoader { friend class ObjectWorldLoader; @@ -56,7 +56,7 @@ class ObjectGridLoader }; //Stop the creatures before unloading the NGrid -class ObjectGridStoper +class TC_GAME_API ObjectGridStoper { public: void Visit(CreatureMapType &m); @@ -64,7 +64,7 @@ class ObjectGridStoper }; //Move the foreign creatures back to respawn positions before unloading the NGrid -class ObjectGridEvacuator +class TC_GAME_API ObjectGridEvacuator { public: void Visit(CreatureMapType &m); diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 5f8813c2071..e3528d053f5 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -157,10 +157,9 @@ bool Group::Create(Player* leader) CharacterDatabase.Execute(stmt); + Group::ConvertLeaderInstancesToGroup(leader, this, false); ASSERT(AddMember(leader)); // If the leader can't be added to a new group because it appears full, something is clearly wrong. - - Player::ConvertInstancesToGroup(leader, this, false); } else if (!AddMember(leader)) return false; @@ -410,9 +409,7 @@ bool Group::AddMember(Player* player) player->SetGroup(this, subGroup); // if the same group invites the player back, cancel the homebind timer - InstanceGroupBind* bind = GetBoundInstance(player); - if (bind && bind->save->GetInstanceId() == player->GetInstanceId()) - player->m_InstanceValid = true; + player->m_InstanceValid = player->CheckInstanceValidity(false); if (!isRaidGroup()) // reset targetIcons for non-raid-groups { @@ -693,7 +690,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex) } // Copy the permanent binds from the new leader to the group - Player::ConvertInstancesToGroup(newLeader, this, true); + Group::ConvertLeaderInstancesToGroup(newLeader, this, true); // Update the group leader PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER); @@ -720,6 +717,42 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex) BroadcastPacket(groupNewLeader.Write(), true); } +/// convert the player's binds to the group +void Group::ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader) +{ + // copy all binds to the group, when changing leader it's assumed the character + // will not have any solo binds + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + for (Player::BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) + { + if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficultyID(), itr->first)) + group->BindToInstance(itr->second.save, itr->second.perm, false); + + // permanent binds are not removed + if (switchLeader && !itr->second.perm) + { + // increments itr in call + player->UnbindInstance(itr, Difficulty(i), false); + } + else + ++itr; + } + } + + /* if group leader is in a non-raid dungeon map and nobody is actually bound to this map then the group can "take over" the instance * + * (example: two-player group disbanded by disconnect where the player reconnects within 60 seconds and the group is reformed) */ + if (Map* playerMap = player->GetMap()) + if (!switchLeader && playerMap->IsNonRaidDungeon()) + if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(playerMap->GetInstanceId())) + if (save->GetGroupCount() == 0 && save->GetPlayerCount() == 0) + { + TC_LOG_DEBUG("maps", "Group::ConvertLeaderInstancesToGroup: Group for player %s is taking over unbound instance map %d with Id %d", player->GetName().c_str(), playerMap->GetId(), playerMap->GetInstanceId()); + // if nobody is saved to this, then the save wasn't permanent + group->BindToInstance(save, false, false); + } +} + void Group::Disband(bool hideDestroy /* = false */) { sScriptMgr->OnGroupDisband(this); diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index fab6edd5603..3c75bf6739f 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -188,7 +188,7 @@ struct RaidMarker /** request member stats checken **/ /// @todo uninvite people that not accepted invite -class Group +class TC_GAME_API Group { public: struct MemberSlot @@ -226,6 +226,7 @@ class Group bool AddMember(Player* player); bool RemoveMember(ObjectGuid guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker = ObjectGuid::Empty, const char* reason = NULL); void ChangeLeader(ObjectGuid guid, int8 partyIndex = 0); + static void ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader); void SetLootMethod(LootMethod method); void SetLooterGuid(ObjectGuid guid); void SetMasterLooterGuid(ObjectGuid guid); diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp index 24d4983a1e0..c6046c3a9aa 100644 --- a/src/server/game/Groups/GroupMgr.cpp +++ b/src/server/game/Groups/GroupMgr.cpp @@ -92,6 +92,12 @@ ObjectGuid::LowType GroupMgr::GenerateGroupId() return NextGroupId++; } +GroupMgr* GroupMgr::instance() +{ + static GroupMgr instance; + return &instance; +} + Group* GroupMgr::GetGroupByGUID(ObjectGuid const& groupId) const { GroupContainer::const_iterator itr = GroupStore.find(groupId.GetCounter()); diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h index 25dd1275908..f3031493782 100644 --- a/src/server/game/Groups/GroupMgr.h +++ b/src/server/game/Groups/GroupMgr.h @@ -20,18 +20,14 @@ #include "Group.h" -class GroupMgr +class TC_GAME_API GroupMgr { private: GroupMgr(); ~GroupMgr(); public: - static GroupMgr* instance() - { - static GroupMgr instance; - return &instance; - } + static GroupMgr* instance(); typedef std::map<ObjectGuid::LowType, Group*> GroupContainer; typedef std::vector<Group*> GroupDbContainer; diff --git a/src/server/game/Groups/GroupReference.h b/src/server/game/Groups/GroupReference.h index 4718dda1832..6e7373de7d7 100644 --- a/src/server/game/Groups/GroupReference.h +++ b/src/server/game/Groups/GroupReference.h @@ -24,7 +24,7 @@ class Group; class Player; -class GroupReference : public Reference<Group, Player> +class TC_GAME_API GroupReference : public Reference<Group, Player> { protected: uint8 iSubGroup; diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index e5ecef91649..d41a4f7c726 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -261,7 +261,7 @@ const uint32 GuildChallengeMaxLevelGoldReward[GUILD_CHALLENGES_TYPES] = { 0, 125 const uint32 GuildChallengesMaxCount[GUILD_CHALLENGES_TYPES] = { 0, 7, 1, 3, 0, 3 }; // Emblem info -class EmblemInfo +class TC_GAME_API EmblemInfo { public: EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { } @@ -317,7 +317,7 @@ typedef std::vector <GuildBankRightsAndSlots> GuildBankRightsAndSlotsVec; typedef std::set <uint8> SlotIds; -class Guild +class TC_GAME_API Guild { private: // Class representing guild member diff --git a/src/server/game/Guilds/GuildFinderMgr.cpp b/src/server/game/Guilds/GuildFinderMgr.cpp index de355712be4..961827c9d3b 100644 --- a/src/server/game/Guilds/GuildFinderMgr.cpp +++ b/src/server/game/Guilds/GuildFinderMgr.cpp @@ -339,3 +339,9 @@ void GuildFinderMgr::SendMembershipRequestListUpdate(Player* player) { player->SendDirectMessage(WorldPackets::GuildFinder::LFGuildApplicationsListChanged().Write()); } + +GuildFinderMgr* GuildFinderMgr::instance() +{ + static GuildFinderMgr instance; + return &instance; +} diff --git a/src/server/game/Guilds/GuildFinderMgr.h b/src/server/game/Guilds/GuildFinderMgr.h index 6a705a5b4ef..d0cd29b0bee 100644 --- a/src/server/game/Guilds/GuildFinderMgr.h +++ b/src/server/game/Guilds/GuildFinderMgr.h @@ -265,11 +265,7 @@ class GuildFinderMgr static void SendApplicantListUpdate(Guild* guild); static void SendMembershipRequestListUpdate(Player* player); - static GuildFinderMgr* instance() - { - static GuildFinderMgr instance; - return &instance; - } + static GuildFinderMgr* instance(); }; #define sGuildFinderMgr GuildFinderMgr::instance() diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp index d8969d73e72..8cafc8cdd2f 100644 --- a/src/server/game/Guilds/GuildMgr.cpp +++ b/src/server/game/Guilds/GuildMgr.cpp @@ -96,6 +96,12 @@ std::string GuildMgr::GetGuildNameById(ObjectGuid::LowType guildId) const return ""; } +GuildMgr* GuildMgr::instance() +{ + static GuildMgr instance; + return &instance; +} + Guild* GuildMgr::GetGuildByLeader(ObjectGuid guid) const { for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr) diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h index 069f4e165eb..66aed6ad1a7 100644 --- a/src/server/game/Guilds/GuildMgr.h +++ b/src/server/game/Guilds/GuildMgr.h @@ -20,18 +20,14 @@ #include "Guild.h" -class GuildMgr +class TC_GAME_API GuildMgr { private: GuildMgr(); ~GuildMgr(); public: - static GuildMgr* instance() - { - static GuildMgr instance; - return &instance; - } + static GuildMgr* instance(); Guild* GetGuildByLeader(ObjectGuid guid) const; Guild* GetGuildById(ObjectGuid::LowType guildId) const; diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index a92298981ec..347ae3d0b03 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -258,18 +258,21 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell AH->buyout = packet.BuyoutPrice; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; + AH->etime = packet.RunTime; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: %s %s is selling item %s %s to auctioneer " UI64FMTD " with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetTemplate()->GetDefaultLocaleName(), AH->auctioneer, item->GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(item); auctionHouse->AddAuction(AH); + sAuctionMgr->PendingAuctionAdd(_player, AH); _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(trans); item->SaveToDB(trans); + AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); @@ -306,12 +309,14 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell AH->buyout = packet.BuyoutPrice; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; + AH->etime = packet.RunTime; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: %s %s is selling %s %s to auctioneer " UI64FMTD " with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), newItem->GetGUID().ToString().c_str(), newItem->GetTemplate()->GetDefaultLocaleName(), AH->auctioneer, newItem->GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(newItem); auctionHouse->AddAuction(AH); + sAuctionMgr->PendingAuctionAdd(_player, AH); for (auto const& packetItem : packet.Items) { @@ -351,8 +356,6 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); } - - _player->ModifyMoney(-int32(deposit)); } // this function is called when client bids or buys out auction diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index ef197cbe541..dff529891b6 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -21,7 +21,6 @@ #include "ArenaTeamMgr.h" #include "AuthenticationPackets.h" #include "Battleground.h" -#include "BattlenetServerManager.h" #include "BattlePetPackets.h" #include "CalendarMgr.h" #include "CharacterPackets.h" @@ -1138,8 +1137,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin); - sBattlenetServer.SendChangeToonOnlineState(GetBattlenetAccountId(), GetAccountId(), _player->GetGUID(), _player->GetName(), true); - delete holder; } diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index b94b4ce838e..a9db9d52572 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -534,8 +534,69 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack bool teleported = false; if (player->GetMapId() != at->target_mapId) { - if (!sMapMgr->CanPlayerEnter(at->target_mapId, player, false)) + if (Map::EnterState denyReason = sMapMgr->PlayerCannotEnter(at->target_mapId, player, false)) + { + bool reviveAtTrigger = false; // should we revive the player if he is trying to enter the correct instance? + switch (denyReason) + { + case Map::CANNOT_ENTER_NO_ENTRY: + TC_LOG_DEBUG("maps", "MAP: Player '%s' attempted to enter map with id %d which has no entry", player->GetName().c_str(), at->target_mapId); + break; + case Map::CANNOT_ENTER_UNINSTANCED_DUNGEON: + TC_LOG_DEBUG("maps", "MAP: Player '%s' attempted to enter dungeon map %d but no instance template was found", player->GetName().c_str(), at->target_mapId); + break; + case Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE: + TC_LOG_DEBUG("maps", "MAP: Player '%s' attempted to enter instance map %d but the requested difficulty was not found", player->GetName().c_str(), at->target_mapId); + if (MapEntry const* entry = sMapStore.LookupEntry(at->target_mapId)) + player->SendTransferAborted(entry->ID, TRANSFER_ABORT_DIFFICULTY, player->GetDifficultyID(entry)); + break; + case Map::CANNOT_ENTER_NOT_IN_RAID: + TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter map %d", player->GetName().c_str(), at->target_mapId); + player->SendRaidGroupOnlyMessage(RAID_GROUP_ERR_ONLY, 0); + reviveAtTrigger = true; + break; + case Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE: + player->GetSession()->SendPacket(WorldPackets::Misc::AreaTriggerNoCorpse().Write()); + TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance map %d and cannot enter", player->GetName().c_str(), at->target_mapId); + break; + case Map::CANNOT_ENTER_INSTANCE_BIND_MISMATCH: + if (MapEntry const* entry = sMapStore.LookupEntry(at->target_mapId)) + { + char const* mapName = entry->MapName_lang; + TC_LOG_DEBUG("maps", "MAP: Player '%s' cannot enter instance map '%s' because their permanent bind is incompatible with their group's", player->GetName().c_str(), mapName); + // is there a special opcode for this? + // @todo figure out how to get player localized difficulty string (e.g. "10 player", "Heroic" etc) + ChatHandler(player->GetSession()).PSendSysMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_BIND_MISMATCH), mapName); + } + reviveAtTrigger = true; + break; + case Map::CANNOT_ENTER_TOO_MANY_INSTANCES: + player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_TOO_MANY_INSTANCES); + TC_LOG_DEBUG("maps", "MAP: Player '%s' cannot enter instance map %d because he has exceeded the maximum number of instances per hour.", player->GetName().c_str(), at->target_mapId); + reviveAtTrigger = true; + break; + case Map::CANNOT_ENTER_MAX_PLAYERS: + player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAX_PLAYERS); + reviveAtTrigger = true; + break; + case Map::CANNOT_ENTER_ZONE_IN_COMBAT: + player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ZONE_IN_COMBAT); + reviveAtTrigger = true; + break; + default: + break; + } + + if (reviveAtTrigger) // check if the player is touching the areatrigger leading to the map his corpse is on + if (!player->IsAlive() && player->HasCorpse()) + if (player->GetCorpseLocation().GetMapId() == at->target_mapId) + { + player->ResurrectPlayer(0.5f); + player->SpawnCorpseBones(); + } + return; + } if (Group* group = player->GetGroup()) if (group->isLFGGroup() && player->GetMap()->IsDungeon()) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 3ab9f683dea..697060078bc 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -77,9 +77,9 @@ void WorldSession::HandleMoveWorldportAckOpcode() } // relocate the player to the teleport destination - // the CanEnter checks are done in TeleporTo but conditions may change + // the CannotEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full - if (!newMap || !newMap->CanEnter(GetPlayer())) + if (!newMap || newMap->CannotEnter(GetPlayer())) { TC_LOG_ERROR("network", "Map %d (%s) could not be created for %s (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", GetPlayer()->GetGUID().ToString().c_str(), GetPlayer()->GetName().c_str()); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); @@ -157,19 +157,18 @@ void WorldSession::HandleMoveWorldportAckOpcode() } // resurrect character at enter into instance where his corpse exist after add to map - Corpse* corpse = GetPlayer()->GetMap()->GetCorpseByPlayer(GetPlayer()->GetGUID()); - if (corpse && corpse->GetType() != CORPSE_BONES) - { - if (mEntry->IsDungeon()) + + if (mEntry->IsDungeon() && !GetPlayer()->IsAlive()) + if (GetPlayer()->GetCorpseLocation().GetMapId() == mEntry->ID) { GetPlayer()->ResurrectPlayer(0.5f, false); GetPlayer()->SpawnCorpseBones(); } - } bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); if (mInstance) { + // check if this instance has a reset time and send it to player if so Difficulty diff = GetPlayer()->GetDifficultyID(mEntry); if (MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mEntry->ID, diff)) { @@ -182,6 +181,12 @@ void WorldSession::HandleMoveWorldportAckOpcode() } } } + + // check if instance is valid + if (!GetPlayer()->CheckInstanceValidity(false)) + GetPlayer()->m_InstanceValid = false; + + // instance mounting is handled in InstanceTemplate allowMount = mInstance->AllowMount; } diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 0b496100346..cb56a81e5d9 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -98,7 +98,11 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST %s, quest = %u, startcheat = %u", packet.QuestGiverGUID.ToString().c_str(), packet.QuestID, packet.StartCheat); - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, packet.QuestGiverGUID, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM | TYPEMASK_PLAYER); + Object* object; + if (!packet.QuestGiverGUID.IsPlayer()) + object = ObjectAccessor::GetObjectByTypeMask(*_player, packet.QuestGiverGUID, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); + else + object = ObjectAccessor::FindPlayer(packet.QuestGiverGUID); #define CLOSE_GOSSIP_CLEAR_DIVIDER() \ do { \ @@ -120,6 +124,11 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } + if (!_player->IsInSameRaidWith(playerQuestObject)) + { + CLOSE_GOSSIP_CLEAR_DIVIDER(); + return; + } } else { @@ -132,7 +141,10 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) + { + CLOSE_GOSSIP_CLEAR_DIVIDER(); return; + } if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID)) { @@ -190,7 +202,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG } } - _player->PlayerTalkClass->SendCloseGossip(); + CLOSE_GOSSIP_CLEAR_DIVIDER(); #undef CLOSE_GOSSIP_CLEAR_DIVIDER } @@ -462,17 +474,22 @@ void WorldSession::HandleQuestConfirmAccept(WorldPackets::Quest::QuestConfirmAcc if (!_player->IsInSameRaidWith(originalPlayer)) return; - if (!originalPlayer->CanShareQuest(packet.QuestID)) + if (!originalPlayer->IsActiveQuest(packet.QuestID)) return; if (!_player->CanTakeQuest(quest, true)) return; if (_player->CanAddQuest(quest, true)) + { _player->AddQuestAndCheckCompletion(quest, NULL); // NULL, this prevent DB script from duplicate running - _player->SetDivider(ObjectGuid::Empty); + if (quest->GetSrcSpell() > 0) + _player->CastSpell(_player, quest->GetSrcSpell(), true); + } } + + _player->SetDivider(ObjectGuid::Empty); } void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiverCompleteQuest& packet) @@ -605,20 +622,20 @@ void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty& else { receiver->SetDivider(sender->GetGUID()); - receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, sender->GetGUID(), true); + receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, receiver->GetGUID(), true); } } } void WorldSession::HandleQuestPushResult(WorldPackets::Quest::QuestPushResult& packet) { - if (!_player->GetDivider().IsEmpty() && _player->GetDivider() == packet.SenderGUID) + if (!_player->GetDivider().IsEmpty()) { - if (Player* player = ObjectAccessor::FindPlayer(_player->GetDivider())) - { - player->SendPushToPartyResponse(_player, static_cast<QuestPushReason>(packet.Result)); - _player->SetDivider(ObjectGuid::Empty); - } + if (_player->GetDivider() == packet.SenderGUID) + if (Player* player = ObjectAccessor::FindPlayer(_player->GetDivider())) + player->SendPushToPartyResponse(_player, static_cast<QuestPushReason>(packet.Result)); + + _player->SetDivider(ObjectGuid::Empty); } } diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 7d0c9241a51..fc65a1da82f 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -38,6 +38,12 @@ InstanceSaveManager::~InstanceSaveManager() { } +InstanceSaveManager* InstanceSaveManager::instance() +{ + static InstanceSaveManager instance; + return &instance; +} + void InstanceSaveManager::Unload() { lock_instLists = true; diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index a09325e9ce7..21b5c3ca5c3 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -41,7 +41,7 @@ class Group; - player-instance binds for permanent heroic/raid saves - group-instance binds (both solo and permanent) cache the player binds for the group leader */ -class InstanceSave +class TC_GAME_API InstanceSave { friend class InstanceSaveManager; public: @@ -147,7 +147,7 @@ class InstanceSave typedef std::unordered_map<uint64 /*PAIR64(map, difficulty)*/, time_t /*resetTime*/> ResetTimeByMapDifficultyMap; -class InstanceSaveManager +class TC_GAME_API InstanceSaveManager { friend class InstanceSave; @@ -158,11 +158,7 @@ class InstanceSaveManager public: typedef std::unordered_map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap; - static InstanceSaveManager* instance() - { - static InstanceSaveManager instance; - return &instance; - } + static InstanceSaveManager* instance(); void Unload(); diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 6700ca07646..8892be38d37 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -30,6 +30,12 @@ #include "WorldSession.h" #include "Opcodes.h" +BossBoundaryData::~BossBoundaryData() +{ + for (const_iterator it = begin(); it != end(); ++it) + delete it->Boundary; +} + void InstanceScript::SaveToDB() { std::string data = GetSaveData(); @@ -96,6 +102,13 @@ void InstanceScript::SetHeaders(std::string const& dataHeaders) headers.push_back(header); } +void InstanceScript::LoadBossBoundaries(const BossBoundaryData& data) +{ + for (BossBoundaryEntry const& entry : data) + if (entry.BossId < bosses.size()) + bosses[entry.BossId].boundary.insert(entry.Boundary); +} + void InstanceScript::LoadMinionData(const MinionData* data) { while (data->entry) @@ -113,7 +126,7 @@ void InstanceScript::LoadDoorData(const DoorData* data) while (data->entry) { if (data->bossId < bosses.size()) - doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary)))); + doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type))); ++data; } @@ -236,28 +249,6 @@ void InstanceScript::AddDoor(GameObject* door, bool add) if (add) { data.bossInfo->door[data.type].insert(door->GetGUID()); - switch (data.boundary) - { - default: - case BOUNDARY_NONE: - break; - case BOUNDARY_N: - case BOUNDARY_S: - data.bossInfo->boundary[data.boundary] = door->GetPositionX(); - break; - case BOUNDARY_E: - case BOUNDARY_W: - data.bossInfo->boundary[data.boundary] = door->GetPositionY(); - break; - case BOUNDARY_NW: - case BOUNDARY_SE: - data.bossInfo->boundary[data.boundary] = door->GetPositionX() + door->GetPositionY(); - break; - case BOUNDARY_NE: - case BOUNDARY_SW: - data.bossInfo->boundary[data.boundary] = door->GetPositionX() - door->GetPositionY(); - break; - } } else data.bossInfo->door[data.type].erase(door->GetGUID()); diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 56e97217e2a..2bb2f14ca12 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -19,9 +19,11 @@ #ifndef TRINITY_INSTANCE_DATA_H #define TRINITY_INSTANCE_DATA_H +#include <set> #include "ZoneScript.h" #include "World.h" #include "ObjectMgr.h" +#include "CreatureAI.h" #include "Packets/WorldStatePackets.h" #define OUT_SAVE_INST_DATA TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) @@ -69,30 +71,30 @@ enum DoorType MAX_DOOR_TYPES }; -enum BoundaryType +struct DoorData { - BOUNDARY_NONE = 0, - BOUNDARY_N, - BOUNDARY_S, - BOUNDARY_E, - BOUNDARY_W, - BOUNDARY_NE, - BOUNDARY_NW, - BOUNDARY_SE, - BOUNDARY_SW, - BOUNDARY_MAX_X = BOUNDARY_N, - BOUNDARY_MIN_X = BOUNDARY_S, - BOUNDARY_MAX_Y = BOUNDARY_W, - BOUNDARY_MIN_Y = BOUNDARY_E + uint32 entry, bossId; + DoorType type; }; -typedef std::map<BoundaryType, float> BossBoundaryMap; +struct BossBoundaryEntry +{ + uint32 BossId; + AreaBoundary const* Boundary; +}; -struct DoorData +struct TC_GAME_API BossBoundaryData { - uint32 entry, bossId; - DoorType type; - uint32 boundary; + typedef std::vector<BossBoundaryEntry> StorageType; + typedef StorageType::const_iterator const_iterator; + + BossBoundaryData(std::initializer_list<BossBoundaryEntry> data) : _data(data) { } + ~BossBoundaryData(); + const_iterator begin() const { return _data.begin(); } + const_iterator end() const { return _data.end(); } + + private: + StorageType _data; }; struct MinionData @@ -112,16 +114,15 @@ struct BossInfo EncounterState state; GuidSet door[MAX_DOOR_TYPES]; GuidSet minion; - BossBoundaryMap boundary; + CreatureBoundary boundary; }; struct DoorInfo { - explicit DoorInfo(BossInfo* _bossInfo, DoorType _type, BoundaryType _boundary) - : bossInfo(_bossInfo), type(_type), boundary(_boundary) { } + explicit DoorInfo(BossInfo* _bossInfo, DoorType _type) + : bossInfo(_bossInfo), type(_type) { } BossInfo* bossInfo; DoorType type; - BoundaryType boundary; }; struct MinionInfo @@ -137,7 +138,7 @@ typedef std::map<uint32 /*entry*/, MinionInfo> MinionInfoMap; typedef std::map<uint32 /*type*/, ObjectGuid /*guid*/> ObjectGuidMap; typedef std::map<uint32 /*entry*/, uint32 /*type*/> ObjectInfoMap; -class InstanceScript : public ZoneScript +class TC_GAME_API InstanceScript : public ZoneScript { public: explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) { } @@ -161,7 +162,7 @@ class InstanceScript : public ZoneScript virtual void Update(uint32 /*diff*/) { } - // Used by the map's CanEnter function. + // Used by the map's CannotEnter function. // This is to prevent players from entering during boss encounters. virtual bool IsEncounterInProgress() const; @@ -225,7 +226,7 @@ class InstanceScript : public ZoneScript virtual bool SetBossState(uint32 id, EncounterState state); EncounterState GetBossState(uint32 id) const { return id < bosses.size() ? bosses[id].state : TO_BE_DECIDED; } static std::string GetBossStateName(uint8 state); - BossBoundaryMap const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : NULL; } + CreatureBoundary const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : NULL; } // Achievement criteria additional requirements check // NOTE: not use this if same can be checked existed requirement types from AchievementCriteriaRequirementType @@ -255,6 +256,7 @@ class InstanceScript : public ZoneScript protected: void SetHeaders(std::string const& dataHeaders); void SetBossNumber(uint32 number) { bosses.resize(number); } + void LoadBossBoundaries(BossBoundaryData const& data); void LoadDoorData(DoorData const* data); void LoadMinionData(MinionData const* data); void LoadObjectData(ObjectData const* creatureData, ObjectData const* gameObjectData); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index e57bf681b8a..a7e11e81970 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -1877,3 +1877,20 @@ void LoadLootTemplates_Reference() TC_LOG_INFO("server.loading", ">> Loaded refence loot templates in %u ms", GetMSTimeDiffToNow(oldMSTime)); } + +void LoadLootTables() +{ + LoadLootTemplates_Creature(); + LoadLootTemplates_Fishing(); + LoadLootTemplates_Gameobject(); + LoadLootTemplates_Item(); + LoadLootTemplates_Mail(); + LoadLootTemplates_Milling(); + LoadLootTemplates_Pickpocketing(); + LoadLootTemplates_Skinning(); + LoadLootTemplates_Disenchant(); + LoadLootTemplates_Prospecting(); + LoadLootTemplates_Spell(); + + LoadLootTemplates_Reference(); +} diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index 05e045f4a2f..db12250f443 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -131,7 +131,7 @@ enum LootSlotType class Player; class LootStore; -struct LootStoreItem +struct TC_GAME_API LootStoreItem { uint32 itemid; // id of the item uint32 reference; // referenced TemplateleId @@ -154,7 +154,7 @@ struct LootStoreItem bool IsValid(LootStore const& store, uint32 entry) const; // Checks correctness of values }; -struct LootItem +struct TC_GAME_API LootItem { uint32 itemid; uint32 randomSuffix; @@ -210,7 +210,7 @@ typedef std::unordered_map<uint32, LootTemplate*> LootTemplateMap; typedef std::set<uint32> LootIdSet; -class LootStore +class TC_GAME_API LootStore { public: explicit LootStore(char const* name, char const* entryName, bool ratesAllowed) @@ -247,7 +247,7 @@ class LootStore bool m_ratesAllowed; }; -class LootTemplate +class TC_GAME_API LootTemplate { class LootGroup; // A set of loot definitions for items (refs are not allowed inside) typedef std::vector<LootGroup*> LootGroups; @@ -311,7 +311,7 @@ class LootValidatorRefManager : public RefManager<Loot, LootValidatorRef> //===================================================== -struct Loot +struct TC_GAME_API Loot { QuestItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; } QuestItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; } @@ -414,48 +414,33 @@ private: uint32 _difficultyBonusTreeMod; }; -extern LootStore LootTemplates_Creature; -extern LootStore LootTemplates_Fishing; -extern LootStore LootTemplates_Gameobject; -extern LootStore LootTemplates_Item; -extern LootStore LootTemplates_Mail; -extern LootStore LootTemplates_Milling; -extern LootStore LootTemplates_Pickpocketing; -extern LootStore LootTemplates_Reference; -extern LootStore LootTemplates_Skinning; -extern LootStore LootTemplates_Disenchant; -extern LootStore LootTemplates_Prospecting; -extern LootStore LootTemplates_Spell; - -void LoadLootTemplates_Creature(); -void LoadLootTemplates_Fishing(); -void LoadLootTemplates_Gameobject(); -void LoadLootTemplates_Item(); -void LoadLootTemplates_Mail(); -void LoadLootTemplates_Milling(); -void LoadLootTemplates_Pickpocketing(); -void LoadLootTemplates_Skinning(); -void LoadLootTemplates_Disenchant(); -void LoadLootTemplates_Prospecting(); - -void LoadLootTemplates_Spell(); -void LoadLootTemplates_Reference(); - -inline void LoadLootTables() -{ - LoadLootTemplates_Creature(); - LoadLootTemplates_Fishing(); - LoadLootTemplates_Gameobject(); - LoadLootTemplates_Item(); - LoadLootTemplates_Mail(); - LoadLootTemplates_Milling(); - LoadLootTemplates_Pickpocketing(); - LoadLootTemplates_Skinning(); - LoadLootTemplates_Disenchant(); - LoadLootTemplates_Prospecting(); - LoadLootTemplates_Spell(); - - LoadLootTemplates_Reference(); -} +TC_GAME_API extern LootStore LootTemplates_Creature; +TC_GAME_API extern LootStore LootTemplates_Fishing; +TC_GAME_API extern LootStore LootTemplates_Gameobject; +TC_GAME_API extern LootStore LootTemplates_Item; +TC_GAME_API extern LootStore LootTemplates_Mail; +TC_GAME_API extern LootStore LootTemplates_Milling; +TC_GAME_API extern LootStore LootTemplates_Pickpocketing; +TC_GAME_API extern LootStore LootTemplates_Reference; +TC_GAME_API extern LootStore LootTemplates_Skinning; +TC_GAME_API extern LootStore LootTemplates_Disenchant; +TC_GAME_API extern LootStore LootTemplates_Prospecting; +TC_GAME_API extern LootStore LootTemplates_Spell; + +TC_GAME_API void LoadLootTemplates_Creature(); +TC_GAME_API void LoadLootTemplates_Fishing(); +TC_GAME_API void LoadLootTemplates_Gameobject(); +TC_GAME_API void LoadLootTemplates_Item(); +TC_GAME_API void LoadLootTemplates_Mail(); +TC_GAME_API void LoadLootTemplates_Milling(); +TC_GAME_API void LoadLootTemplates_Pickpocketing(); +TC_GAME_API void LoadLootTemplates_Skinning(); +TC_GAME_API void LoadLootTemplates_Disenchant(); +TC_GAME_API void LoadLootTemplates_Prospecting(); + +TC_GAME_API void LoadLootTemplates_Spell(); +TC_GAME_API void LoadLootTemplates_Reference(); + +TC_GAME_API void LoadLootTables(); #endif diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h index 8bbd378f5d7..0031d3f7c3e 100644 --- a/src/server/game/Mails/Mail.h +++ b/src/server/game/Mails/Mail.h @@ -80,7 +80,7 @@ enum MailShowFlags MAIL_SHOW_RETURN = 0x0010 }; -class MailSender +class TC_GAME_API MailSender { public: // Constructors MailSender(MailMessageType messageType, ObjectGuid::LowType sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_DEFAULT) @@ -101,7 +101,7 @@ class MailSender MailStationery m_stationery; }; -class MailReceiver +class TC_GAME_API MailReceiver { public: // Constructors explicit MailReceiver(ObjectGuid::LowType receiver_lowguid) : m_receiver(NULL), m_receiver_lowguid(receiver_lowguid) { } @@ -115,7 +115,7 @@ class MailReceiver ObjectGuid::LowType m_receiver_lowguid; }; -class MailDraft +class TC_GAME_API MailDraft { typedef std::map<ObjectGuid::LowType, Item*> MailItemMap; @@ -163,7 +163,7 @@ struct MailItemInfo }; typedef std::vector<MailItemInfo> MailItemInfoVec; -struct Mail +struct TC_GAME_API Mail { uint32 messageID; uint8 messageType; diff --git a/src/server/game/Maps/AreaBoundary.cpp b/src/server/game/Maps/AreaBoundary.cpp new file mode 100644 index 00000000000..e09b252179e --- /dev/null +++ b/src/server/game/Maps/AreaBoundary.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "AreaBoundary.h" +#include "Unit.h" +#include "TemporarySummon.h" + +// ---== RECTANGLE ==--- +RectangleBoundary::RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_RECTANGLE, isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { } +bool RectangleBoundary::IsWithinBoundaryArea(const Position* pos) const +{ + if (!pos) + return false; + + return !( + pos->GetPositionX() < _minX || + pos->GetPositionX() > _maxX || + pos->GetPositionY() < _minY || + pos->GetPositionY() > _maxY + ); +} + + +// ---== CIRCLE ==--- +CircleBoundary::CircleBoundary(Position const& center, double radius, bool isInverted) : + CircleBoundary(DoublePosition(center), radius, isInverted) { } +CircleBoundary::CircleBoundary(DoublePosition const& center, double radius, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(radius*radius) { } +CircleBoundary::CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted) : + CircleBoundary(DoublePosition(center), DoublePosition(pointOnCircle), isInverted) { } +CircleBoundary::CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(center.GetDoubleExactDist2dSq(pointOnCircle)) { } +bool CircleBoundary::IsWithinBoundaryArea(const Position* pos) const +{ + if (!pos) + return false; + + double offX = _center.GetDoublePositionX() - pos->GetPositionX(); + double offY = _center.GetDoublePositionY() - pos->GetPositionY(); + return offX*offX+offY*offY <= _radiusSq; +} + + +// ---== ELLIPSE ==--- +EllipseBoundary::EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted) : + EllipseBoundary(DoublePosition(center), radiusX, radiusY, isInverted) { } +EllipseBoundary::EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_ELLIPSE, isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { } +bool EllipseBoundary::IsWithinBoundaryArea(const Position* pos) const +{ + if (!pos) + return false; + + double offX = _center.GetDoublePositionX()-pos->GetPositionX(), offY = _center.GetDoublePositionY()-pos->GetPositionY(); + return (offX*offX)*_scaleXSq + (offY*offY) <= _radiusYSq; +} + + +// ---== TRIANGLE ==--- +TriangleBoundary::TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted) : + TriangleBoundary(DoublePosition(pointA), DoublePosition(pointB), DoublePosition(pointC), isInverted) { } +TriangleBoundary::TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_TRIANGLE, isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { } +bool TriangleBoundary::IsWithinBoundaryArea(const Position* pos) const +{ + if (!pos) + return false; + + // half-plane signs + bool sign1 = ((-_b.GetDoublePositionX() + pos->GetPositionX()) * _aby - (-_b.GetDoublePositionY() + pos->GetPositionY()) * _abx) < 0; + bool sign2 = ((-_c.GetDoublePositionX() + pos->GetPositionX()) * _bcy - (-_c.GetDoublePositionY() + pos->GetPositionY()) * _bcx) < 0; + bool sign3 = ((-_a.GetDoublePositionX() + pos->GetPositionX()) * _cay - (-_a.GetDoublePositionY() + pos->GetPositionY()) * _cax) < 0; + + // if all signs are the same, the point is inside the triangle + return ((sign1 == sign2) && (sign2 == sign3)); +} + + +// ---== PARALLELOGRAM ==--- +ParallelogramBoundary::ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted) : + ParallelogramBoundary(DoublePosition(cornerA), DoublePosition(cornerB), DoublePosition(cornerD), isInverted) { } +ParallelogramBoundary::ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_PARALLELOGRAM, isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { } +bool ParallelogramBoundary::IsWithinBoundaryArea(const Position* pos) const +{ + if (!pos) + return false; + + // half-plane signs + bool sign1 = ((-_b.GetDoublePositionX() + pos->GetPositionX()) * _aby - (-_b.GetDoublePositionY() + pos->GetPositionY()) * _abx) < 0; + bool sign2 = ((-_a.GetDoublePositionX() + pos->GetPositionX()) * _day - (-_a.GetDoublePositionY() + pos->GetPositionY()) * _dax) < 0; + bool sign3 = ((-_d.GetDoublePositionY() + pos->GetPositionY()) * _abx - (-_d.GetDoublePositionX() + pos->GetPositionX()) * _aby) < 0; // AB = -CD + bool sign4 = ((-_c.GetDoublePositionY() + pos->GetPositionY()) * _dax - (-_c.GetDoublePositionX() + pos->GetPositionX()) * _day) < 0; // DA = -BC + + // if all signs are equal, the point is inside + return ((sign1 == sign2) && (sign2 == sign3) && (sign3 == sign4)); +} + + +// ---== Z RANGE ==--- +ZRangeBoundary::ZRangeBoundary(float minZ, float maxZ, bool isInverted) : + AreaBoundary(BoundaryType::BOUNDARY_Z_RANGE, isInverted), _minZ(minZ), _maxZ(maxZ) { } +bool ZRangeBoundary::IsWithinBoundaryArea(const Position* pos) const +{ + if (!pos) + return false; + + return !(pos->GetPositionZ() < _minZ || pos->GetPositionZ() > _maxZ); +} diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h new file mode 100644 index 00000000000..a8780ddb60f --- /dev/null +++ b/src/server/game/Maps/AreaBoundary.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_AREA_BOUNDARY_H +#define TRINITY_AREA_BOUNDARY_H + +#include "Position.h" + +class TC_GAME_API AreaBoundary +{ + public: + enum BoundaryType + { + BOUNDARY_RECTANGLE, // Rectangle aligned with the coordinate axis + BOUNDARY_CIRCLE, + BOUNDARY_ELLIPSE, + BOUNDARY_TRIANGLE, + BOUNDARY_PARALLELOGRAM, + BOUNDARY_Z_RANGE, + }; + virtual ~AreaBoundary() { } + BoundaryType GetBoundaryType() const { return m_boundaryType; } + bool IsWithinBoundary(const Position* pos) const { return (IsWithinBoundaryArea(pos) != m_isInvertedBoundary); } + + struct DoublePosition : Position + { + double d_positionX, d_positionY, d_positionZ; + DoublePosition(double x = 0.0, double y = 0.0, double z = 0.0, float o = 0.0f) + : Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { } + DoublePosition(float x, float y = 0.0f, float z = 0.0f, float o = 0.0f) + : Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { } + DoublePosition(const Position& pos) + : DoublePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()) { } + + double GetDoublePositionX() const { return d_positionX; } + double GetDoublePositionY() const { return d_positionY; } + double GetDoublePositionZ() const { return d_positionZ; } + + double GetDoubleExactDist2dSq(DoublePosition const& pos) const { + double offX = GetDoublePositionX() - pos.GetDoublePositionX(); + double offY = GetDoublePositionY() - pos.GetDoublePositionY(); + return (offX*offX) + (offY*offY); + } + + Position* sync() { m_positionX = (float)d_positionX; m_positionY = (float)d_positionY; m_positionZ = (float)d_positionZ; return this; } + }; + + protected: + AreaBoundary(BoundaryType bType, bool isInverted) : m_boundaryType(bType), m_isInvertedBoundary(isInverted) { } + virtual bool IsWithinBoundaryArea(const Position* pos) const = 0; + const BoundaryType m_boundaryType; + bool m_isInvertedBoundary; +}; + +class TC_GAME_API RectangleBoundary : public AreaBoundary +{ + public: + // X axis is north/south, Y axis is east/west, larger values are northwest + RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted = false); + + protected: + bool IsWithinBoundaryArea(const Position* pos) const override; + + private: + const float _minX, _maxX, _minY, _maxY; +}; + +class TC_GAME_API CircleBoundary : public AreaBoundary +{ + public: + CircleBoundary(Position const& center, double radius, bool isInverted = false); + CircleBoundary(DoublePosition const& center, double radius, bool isInverted = false); + CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted = false); + CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted = false); + + protected: + bool IsWithinBoundaryArea(const Position* pos) const override; + + private: + const DoublePosition _center; + const double _radiusSq; +}; + +class TC_GAME_API EllipseBoundary : public AreaBoundary +{ + public: + EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted = false); + EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted = false); + + protected: + bool IsWithinBoundaryArea(const Position* pos) const override; + + private: + const DoublePosition _center; + const double _radiusYSq, _scaleXSq; +}; + +class TC_GAME_API TriangleBoundary : public AreaBoundary +{ + public: + TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted = false); + TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted = false); + + protected: + bool IsWithinBoundaryArea(const Position* pos) const override; + + private: + const DoublePosition _a, _b, _c; + const double _abx, _bcx, _cax, _aby, _bcy, _cay; +}; + +class TC_GAME_API ParallelogramBoundary : public AreaBoundary +{ + public: + // Note: AB must be orthogonal to AD + ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted = false); + ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted = false); + + protected: + bool IsWithinBoundaryArea(const Position* pos) const override; + + private: + const DoublePosition _a, _b, _d, _c; + const double _abx, _dax, _aby, _day; +}; + +class TC_GAME_API ZRangeBoundary : public AreaBoundary +{ + public: + ZRangeBoundary(float minZ, float maxZ, bool isInverted = false); + + protected: + bool IsWithinBoundaryArea(const Position* pos) const override; + + private: + const float _minZ, _maxZ; +}; + +#endif //TRINITY_AREA_BOUNDARY_H diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 90c02b10477..d1d13e428f9 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3019,17 +3019,17 @@ void Map::RemoveFromActive(DynamicObject* obj) RemoveFromActiveHelper(obj); } -template bool Map::AddToMap(Corpse*); -template bool Map::AddToMap(Creature*); -template bool Map::AddToMap(GameObject*); -template bool Map::AddToMap(DynamicObject*); -template bool Map::AddToMap(AreaTrigger*); - -template void Map::RemoveFromMap(Corpse*, bool); -template void Map::RemoveFromMap(Creature*, bool); -template void Map::RemoveFromMap(GameObject*, bool); -template void Map::RemoveFromMap(DynamicObject*, bool); -template void Map::RemoveFromMap(AreaTrigger*, bool); +template TC_GAME_API bool Map::AddToMap(Corpse*); +template TC_GAME_API bool Map::AddToMap(Creature*); +template TC_GAME_API bool Map::AddToMap(GameObject*); +template TC_GAME_API bool Map::AddToMap(DynamicObject*); +template TC_GAME_API bool Map::AddToMap(AreaTrigger*); + +template TC_GAME_API void Map::RemoveFromMap(Corpse*, bool); +template TC_GAME_API void Map::RemoveFromMap(Creature*, bool); +template TC_GAME_API void Map::RemoveFromMap(GameObject*, bool); +template TC_GAME_API void Map::RemoveFromMap(DynamicObject*, bool); +template TC_GAME_API void Map::RemoveFromMap(AreaTrigger*, bool); /* ******* Dungeon Instance Maps ******* */ @@ -3062,62 +3062,38 @@ void InstanceMap::InitVisibilityDistance() /* Do map specific checks to see if the player can enter */ -bool InstanceMap::CanEnter(Player* player) +Map::EnterState InstanceMap::CannotEnter(Player* player) { if (player->GetMapRef().getTarget() == this) { - TC_LOG_ERROR("maps", "InstanceMap::CanEnter - player %s(%s) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetId(), GetInstanceId(), GetSpawnMode()); + TC_LOG_ERROR("maps", "InstanceMap::CannotEnter - player %s(%s) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetId(), GetInstanceId(), GetSpawnMode()); ABORT(); - return false; + return CANNOT_ENTER_ALREADY_IN_MAP; } // allow GM's to enter if (player->IsGameMaster()) - return Map::CanEnter(player); + return Map::CannotEnter(player); // cannot enter if the instance is full (player cap), GMs don't count uint32 maxPlayers = GetMaxPlayers(); if (GetPlayersCountExceptGMs() >= maxPlayers) { TC_LOG_WARN("maps", "MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName().c_str()); - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; + return CANNOT_ENTER_MAX_PLAYERS; } - // cannot enter while an encounter is in progress - // allow if just loading + // cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted) if (!player->IsLoading() && IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress()) - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); - return false; - } + return CANNOT_ENTER_ZONE_IN_COMBAT; - // cannot enter if instance is in use by another party/soloer that have a - // permanent save in the same instance id + // cannot enter if player is permanent saved to a different instance id + if (InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficultyID())) + if (playerBind->perm && playerBind->save) + if (playerBind->save->GetInstanceId() != GetInstanceId()) + return CANNOT_ENTER_INSTANCE_BIND_MISMATCH; - PlayerList const &playerList = GetPlayers(); - - if (!playerList.isEmpty()) - for (PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i) - if (Player* iPlayer = i->GetSource()) - { - if (iPlayer->IsGameMaster()) // bypass GMs - continue; - if (!player->GetGroup()) // player has not group and there is someone inside, deny entry - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; - } - // player inside instance has no group or his groups is different to entering player's one, deny entry - if (!iPlayer->GetGroup() || iPlayer->GetGroup() != player->GetGroup()) - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; - } - break; - } - - return Map::CanEnter(player); + return Map::CannotEnter(player); } /* @@ -3169,7 +3145,7 @@ bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { if (group) { - // solo saves should be reset when entering a group + // solo saves should have been reset when the map was loaded InstanceGroupBind* groupBind = group->GetBoundInstance(this); if (playerBind && playerBind->save != mapSave) { @@ -3474,21 +3450,21 @@ void BattlegroundMap::InitVisibilityDistance() m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas(); } -bool BattlegroundMap::CanEnter(Player* player) +Map::EnterState BattlegroundMap::CannotEnter(Player* player) { if (player->GetMapRef().getTarget() == this) { - TC_LOG_ERROR("maps", "BGMap::CanEnter - %s is already in map!", player->GetGUID().ToString().c_str()); + TC_LOG_ERROR("maps", "BGMap::CannotEnter - player %s is already in map!", player->GetGUID().ToString().c_str()); ABORT(); - return false; + return CANNOT_ENTER_ALREADY_IN_MAP; } if (player->GetBattlegroundId() != GetInstanceId()) - return false; + return CANNOT_ENTER_INSTANCE_BIND_MISMATCH; // player number limit is checked in bgmgr, no need to do it here - return Map::CanEnter(player); + return Map::CannotEnter(player); } bool BattlegroundMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 34aa00e4bf9..75d184b19a6 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -156,7 +156,7 @@ struct LiquidData float depth_level; }; -class GridMap +class TC_GAME_API GridMap { uint32 _flags; union{ @@ -256,7 +256,7 @@ typedef std::unordered_map<uint32 /*zoneId*/, ZoneDynamicInfo> ZoneDynamicInfoMa typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer; -class Map : public GridRefManager<NGridType> +class TC_GAME_API Map : public GridRefManager<NGridType> { friend class MapReference; public: @@ -280,6 +280,7 @@ class Map : public GridRefManager<NGridType> virtual bool AddPlayerToMap(Player* player, bool initPlayer = true); virtual void RemovePlayerFromMap(Player*, bool); + template<class T> bool AddToMap(T *); template<class T> void RemoveFromMap(T *, bool); @@ -295,7 +296,8 @@ class Map : public GridRefManager<NGridType> void GameObjectRelocation(GameObject* go, float x, float y, float z, float orientation, bool respawnRelocationOnFail = true); void DynamicObjectRelocation(DynamicObject* go, float x, float y, float z, float orientation); - template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor); + template<class T, class CONTAINER> + void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor); bool IsRemovalGrid(float x, float y) const { @@ -365,7 +367,23 @@ class Map : public GridRefManager<NGridType> uint32 GetInstanceId() const { return i_InstanceId; } uint8 GetSpawnMode() const { return (i_spawnMode); } - virtual bool CanEnter(Player* /*player*/) { return true; } + + enum EnterState + { + CAN_ENTER = 0, + CANNOT_ENTER_ALREADY_IN_MAP = 1, // Player is already in the map + CANNOT_ENTER_NO_ENTRY, // No map entry was found for the target map ID + CANNOT_ENTER_UNINSTANCED_DUNGEON, // No instance template was found for dungeon map + CANNOT_ENTER_DIFFICULTY_UNAVAILABLE, // Requested instance difficulty is not available for target map + CANNOT_ENTER_NOT_IN_RAID, // Target instance is a raid instance and the player is not in a raid group + CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE, // Player is dead and their corpse is not in target instance + CANNOT_ENTER_INSTANCE_BIND_MISMATCH, // Player's permanent instance save is not compatible with their group's current instance bind + CANNOT_ENTER_TOO_MANY_INSTANCES, // Player has entered too many instances recently + CANNOT_ENTER_MAX_PLAYERS, // Target map already has the maximum number of players allowed + CANNOT_ENTER_ZONE_IN_COMBAT, // A boss encounter is currently in progress on the target map + CANNOT_ENTER_UNSPECIFIED_REASON + }; + virtual EnterState CannotEnter(Player* /*player*/) { return CAN_ENTER; } const char* GetMapName() const; // have meaning only for instanced map (that have set real difficulty) @@ -737,7 +755,7 @@ enum InstanceResetMethod INSTANCE_RESET_RESPAWN_DELAY }; -class InstanceMap : public Map +class TC_GAME_API InstanceMap : public Map { public: InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent); @@ -751,7 +769,7 @@ class InstanceMap : public Map InstanceScript* GetInstanceScript() { return i_data; } void PermBindAllPlayers(Player* source); void UnloadAll() override; - bool CanEnter(Player* player) override; + EnterState CannotEnter(Player* player) override; void SendResetWarnings(uint32 timeLeft) const; void SetResetSchedule(bool on); @@ -766,7 +784,7 @@ class InstanceMap : public Map uint32 i_script_id; }; -class BattlegroundMap : public Map +class TC_GAME_API BattlegroundMap : public Map { public: BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode); @@ -774,7 +792,7 @@ class BattlegroundMap : public Map bool AddPlayerToMap(Player* player, bool initPlayer = true) override; void RemovePlayerFromMap(Player*, bool) override; - bool CanEnter(Player* player) override; + EnterState CannotEnter(Player* player) override; void SetUnload(); //void UnloadAll(bool pForce); void RemoveAllPlayers() override; diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 70623e1d7ab..e277746290a 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -111,12 +111,12 @@ void MapInstanced::UnloadAll() - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ -Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) +Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, uint32 loginInstanceId) { if (GetId() != mapId || !player) - return NULL; + return nullptr; - Map* map = NULL; + Map* map = nullptr; uint32 newInstanceId = 0; // instanceId of the resulting map if (IsBattlegroundOrArena()) @@ -125,7 +125,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) // the instance id is set in battlegroundid newInstanceId = player->GetBattlegroundId(); if (!newInstanceId) - return NULL; + return nullptr; map = sMapMgr->FindMap(mapId, newInstanceId); if (!map) @@ -135,27 +135,40 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) else { player->TeleportToBGEntryPoint(); - return NULL; + return nullptr; } } } else if (!IsGarrison()) { InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficultyID(GetEntry())); - InstanceSave* pSave = pBind ? pBind->save : NULL; + InstanceSave* pSave = pBind ? pBind->save : nullptr; - // the player's permanent player bind is taken into consideration first - // then the player's group bind and finally the solo bind. + // priority: + // 1. player's permanent bind + // 2. player's current instance id if this is at login + // 3. group's current bind + // 4. player's current bind if (!pBind || !pBind->perm) { - InstanceGroupBind* groupBind = NULL; + if (loginInstanceId) // if the player has a saved instance id on login, we either use this instance or relocate him out (return null) + { + map = FindInstanceMap(loginInstanceId); + return (map && map->GetId() == GetId()) ? map : nullptr; // is this check necessary? or does MapInstanced only find instances of itself? + } + + InstanceGroupBind* groupBind = nullptr; Group* group = player->GetGroup(); // use the player's difficulty setting (it may not be the same as the group's) if (group) { groupBind = group->GetBoundInstance(this); if (groupBind) + { + // solo saves should be reset when entering a group's instance + player->UnbindInstance(GetId(), player->GetDifficultyID(GetEntry())); pSave = groupBind->save; + } } } if (pSave) @@ -288,8 +301,8 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) return true; } -bool MapInstanced::CanEnter(Player* /*player*/) +Map::EnterState MapInstanced::CannotEnter(Player* /*player*/) { //ABORT(); - return true; + return CAN_ENTER; } diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h index f0d185bd796..7d89d446846 100644 --- a/src/server/game/Maps/MapInstanced.h +++ b/src/server/game/Maps/MapInstanced.h @@ -25,7 +25,7 @@ class GarrisonMap; -class MapInstanced : public Map +class TC_GAME_API MapInstanced : public Map { friend class MapManager; public: @@ -39,13 +39,13 @@ class MapInstanced : public Map void DelayedUpdate(const uint32 diff) override; //void RelocationNotify(); void UnloadAll() override; - bool CanEnter(Player* player) override; + EnterState CannotEnter(Player* /*player*/) override; - Map* CreateInstanceForPlayer(const uint32 mapId, Player* player); + Map* CreateInstanceForPlayer(const uint32 mapId, Player* player, uint32 loginInstanceId=0); Map* FindInstanceMap(uint32 instanceId) const { InstancedMaps::const_iterator i = m_InstancedMaps.find(instanceId); - return(i == m_InstancedMaps.end() ? NULL : i->second); + return(i == m_InstancedMaps.end() ? nullptr : i->second); } bool DestroyInstance(InstancedMaps::iterator &itr); diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index bed31834842..184af8fc360 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -62,6 +62,12 @@ void MapManager::InitializeVisibilityDistanceInfo() (*iter).second->InitVisibilityDistance(); } +MapManager* MapManager::instance() +{ + static MapManager instance; + return &instance; +} + Map* MapManager::CreateBaseMap(uint32 id) { Map* map = FindBaseMap(id); @@ -97,12 +103,12 @@ Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const return map; } -Map* MapManager::CreateMap(uint32 id, Player* player) +Map* MapManager::CreateMap(uint32 id, Player* player, uint32 loginInstanceId) { Map* m = CreateBaseMap(id); if (m && m->Instanceable()) - m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, player); + m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, player, loginInstanceId); return m; } @@ -119,47 +125,36 @@ Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const return ((MapInstanced*)map)->FindInstanceMap(instanceId); } -bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) +Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck) { MapEntry const* entry = sMapStore.LookupEntry(mapid); if (!entry) - return false; + return Map::CANNOT_ENTER_NO_ENTRY; if (!entry->IsDungeon()) - return true; + return Map::CAN_ENTER; InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapid); if (!instance) - return false; + return Map::CANNOT_ENTER_UNINSTANCED_DUNGEON; Difficulty targetDifficulty, requestedDifficulty; targetDifficulty = requestedDifficulty = player->GetDifficultyID(entry); // Get the highest available difficulty if current setting is higher than the instance allows MapDifficultyEntry const* mapDiff = GetDownscaledMapDifficultyData(entry->ID, targetDifficulty); if (!mapDiff) - { - player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, requestedDifficulty); - return false; - } + return Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE; //Bypass checks for GMs if (player->IsGameMaster()) - return true; + return Map::CAN_ENTER; char const* mapName = entry->MapName_lang; Group* group = player->GetGroup(); - if (entry->IsRaid()) - { - // can only enter in a raid group + if (entry->IsRaid()) // can only enter in a raid group if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) - { - /// @todo this is not a good place to send the message - player->SendRaidGroupOnlyMessage(RAID_GROUP_ERR_ONLY, 0); - TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName); - return false; - } - } + return Map::CANNOT_ENTER_NOT_IN_RAID; if (!player->IsAlive()) { @@ -177,12 +172,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) } while (corpseMap); if (!corpseMap) - { - WorldPackets::Misc::AreaTriggerNoCorpse packet; - player->GetSession()->SendPacket(packet.Write()); - TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName); - return false; - } + return Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE; TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName); } @@ -191,23 +181,13 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) } //Get instance where player's group is bound & its map - if (group) + if (!loginCheck && group) { InstanceGroupBind* boundInstance = group->GetBoundInstance(entry); if (boundInstance && boundInstance->save) if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId())) - if (!loginCheck && !boundMap->CanEnter(player)) - return false; - /* - This check has to be moved to InstanceMap::CanEnter() - // Player permanently bounded to different instance than groups one - InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficultyID(entry)); - if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && - boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) - { - /// @todo send some kind of error message to the player - return false; - }*/ + if (Map::EnterState denyReason = boundMap->CannotEnter(player)) + return denyReason; } // players are only allowed to enter 5 instances per hour @@ -219,14 +199,14 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) // instanceId can never be 0 - will not be found if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead()) - { - player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES); - return false; - } + return Map::CANNOT_ENTER_TOO_MANY_INSTANCES; } //Other requirements - return player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true); + if (player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true)) + return Map::CAN_ENTER; + else + return Map::CANNOT_ENTER_UNSPECIFIED_REASON; } void MapManager::Update(uint32 diff) diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index c0811e7fecc..a4075f73563 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -28,18 +28,14 @@ class Transport; struct TransportCreatureProto; -class MapManager +class TC_GAME_API MapManager { public: - static MapManager* instance() - { - static MapManager instance; - return &instance; - } + static MapManager* instance(); Map* CreateBaseMap(uint32 mapId); Map* FindBaseNonInstanceMap(uint32 mapId) const; - Map* CreateMap(uint32 mapId, Player* player); + Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId=0); Map* FindMap(uint32 mapId, uint32 instanceId) const; uint32 GetAreaId(uint32 mapid, float x, float y, float z) const @@ -106,7 +102,7 @@ class MapManager void DoDelayedMovesAndRemoves(); - bool CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck = false); + Map::EnterState PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck = false); void InitializeVisibilityDistanceInfo(); /* statistics */ diff --git a/src/server/game/Maps/MapUpdater.h b/src/server/game/Maps/MapUpdater.h index fce4a26c36a..7fdcc24d530 100644 --- a/src/server/game/Maps/MapUpdater.h +++ b/src/server/game/Maps/MapUpdater.h @@ -28,7 +28,7 @@ class MapUpdateRequest; class Map; -class MapUpdater +class TC_GAME_API MapUpdater { public: diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index 028a58f53c0..5de0133c342 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -35,6 +35,12 @@ TransportMgr::TransportMgr() { } TransportMgr::~TransportMgr() { } +TransportMgr* TransportMgr::instance() +{ + static TransportMgr instance; + return &instance; +} + void TransportMgr::Unload() { _transportTemplates.clear(); diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index d73f284138a..d058c0bb111 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -83,7 +83,7 @@ struct TransportTemplate typedef std::map<uint32, TransportAnimationEntry const*> TransportPathContainer; typedef std::map<uint32, TransportRotationEntry const*> TransportPathRotationContainer; -struct TransportAnimation +struct TC_GAME_API TransportAnimation { TransportAnimation() : TotalTime(0) { } @@ -97,16 +97,12 @@ struct TransportAnimation typedef std::map<uint32, TransportAnimation> TransportAnimationContainer; -class TransportMgr +class TC_GAME_API TransportMgr { friend void DB2Manager::LoadStores(std::string const&, uint32); public: - static TransportMgr* instance() - { - static TransportMgr instance; - return &instance; - } + static TransportMgr* instance(); void Unload(); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index de0e4b77791..4c3ce70fbef 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1211,7 +1211,12 @@ enum TrinityStrings LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD = 11007, LANG_NPCINFO_INHABIT_TYPE = 11008, - LANG_NPCINFO_FLAGS_EXTRA = 11009 + LANG_NPCINFO_FLAGS_EXTRA = 11009, + LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION = 11010, + LANG_CREATURE_NO_INTERIOR_POINT_FOUND = 11011, + LANG_CREATURE_MOVEMENT_NOT_BOUNDED = 11012, + LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED = 11013, + LANG_INSTANCE_BIND_MISMATCH = 11014 }; #endif diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 3cb56e7d9d9..da1f9ef90f3 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -79,7 +79,7 @@ enum RotateDirection // assume it is 25 yard per 0.6 second #define SPEED_CHARGE 42.0f -class MotionMaster //: private std::stack<MovementGenerator *> +class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *> { private: //typedef std::stack<MovementGenerator *> Impl; diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index 56e5dc7058a..d9dd17fabc2 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -27,7 +27,7 @@ class Unit; -class MovementGenerator +class TC_GAME_API MovementGenerator { public: virtual ~MovementGenerator(); diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index 9aa778c5651..161f9e3e970 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -32,7 +32,7 @@ class IdleMovementGenerator : public MovementGenerator MovementGeneratorType GetMovementGeneratorType() const override { return IDLE_MOTION_TYPE; } }; -extern IdleMovementGenerator si_idleMovement; +TC_GAME_API extern IdleMovementGenerator si_idleMovement; class RotateMovementGenerator : public MovementGenerator { diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index 71e0e88f0b2..3cad62abf25 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -49,7 +49,7 @@ enum PathType PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length }; -class PathGenerator +class TC_GAME_API PathGenerator { public: explicit PathGenerator(Unit const* owner); diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index 439cd9a14a4..24a6d85fcbc 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -46,7 +46,7 @@ namespace Movement // MoveSpline represents smooth catmullrom or linear curve and point that moves belong it // curve can be cyclic - in this case movement will be cyclic // point can have vertical acceleration motion component (used in fall, parabolic movement) - class MoveSpline + class TC_GAME_API MoveSpline { friend class WorldPackets::Movement::CommonMovement; friend class WorldPackets::Movement::MonsterMove; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index c968f660f58..421a8d6b06c 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -35,7 +35,7 @@ namespace Movement }; // Transforms coordinates from global to transport offsets - class TransportPathTransform + class TC_GAME_API TransportPathTransform { public: TransportPathTransform(Unit* owner, bool transformForTransport) @@ -49,7 +49,7 @@ namespace Movement /* Initializes and launches spline movement */ - class MoveSplineInit + class TC_GAME_API MoveSplineInit { public: diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h index 927707bfd56..56d8842e700 100644 --- a/src/server/game/Movement/Spline/MovementTypedefs.h +++ b/src/server/game/Movement/Spline/MovementTypedefs.h @@ -77,10 +77,10 @@ namespace Movement typedef counter<uint32, 0xFFFFFFFF> UInt32Counter; - extern float gravity; - extern UInt32Counter splineIdGen; - extern std::string MovementFlags_ToString(uint32 flags); - extern std::string MovementFlagsExtra_ToString(uint32 flags); + TC_GAME_API extern float gravity; + TC_GAME_API extern UInt32Counter splineIdGen; + TC_GAME_API extern std::string MovementFlags_ToString(uint32 flags); + TC_GAME_API extern std::string MovementFlagsExtra_ToString(uint32 flags); } #endif // TRINITYSERVER_TYPEDEFS_H diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp index e0639e38e77..dc935263927 100644 --- a/src/server/game/Movement/Waypoints/WaypointManager.cpp +++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp @@ -94,6 +94,12 @@ void WaypointMgr::Load() TC_LOG_INFO("server.loading", ">> Loaded %u waypoints in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +WaypointMgr* WaypointMgr::instance() +{ + static WaypointMgr instance; + return &instance; +} + void WaypointMgr::ReloadPath(uint32 id) { WaypointPathContainer::iterator itr = _waypointStore.find(id); diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h index d519eee4793..63dc4184308 100644 --- a/src/server/game/Movement/Waypoints/WaypointManager.h +++ b/src/server/game/Movement/Waypoints/WaypointManager.h @@ -44,14 +44,10 @@ struct WaypointData typedef std::vector<WaypointData*> WaypointPath; typedef std::unordered_map<uint32, WaypointPath> WaypointPathContainer; -class WaypointMgr +class TC_GAME_API WaypointMgr { public: - static WaypointMgr* instance() - { - static WaypointMgr instance; - return &instance; - } + static WaypointMgr* instance(); // Attempts to reload a single path from database void ReloadPath(uint32 id); diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h index 2be74279ae7..5996b4126e4 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.h +++ b/src/server/game/OutdoorPvP/OutdoorPvP.h @@ -84,7 +84,7 @@ class Unit; struct GossipMenuItems; class OutdoorPvP; -class OPvPCapturePoint +class TC_GAME_API OPvPCapturePoint { public: @@ -185,7 +185,7 @@ class OPvPCapturePoint }; // base class for specific outdoor pvp handlers -class OutdoorPvP : public ZoneScript +class TC_GAME_API OutdoorPvP : public ZoneScript { friend class OutdoorPvPMgr; diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp index 55fc8602c99..4081652cac7 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -37,6 +37,12 @@ void OutdoorPvPMgr::Die() delete itr->second; } +OutdoorPvPMgr* OutdoorPvPMgr::instance() +{ + static OutdoorPvPMgr instance; + return &instance; +} + void OutdoorPvPMgr::InitOutdoorPvP() { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h index 8a113987882..e53a78ac271 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h @@ -35,18 +35,14 @@ struct OutdoorPvPData }; // class to handle player enter / leave / areatrigger / GO use events -class OutdoorPvPMgr +class TC_GAME_API OutdoorPvPMgr { private: OutdoorPvPMgr(); ~OutdoorPvPMgr() { }; public: - static OutdoorPvPMgr* instance() - { - static OutdoorPvPMgr instance; - return &instance; - } + static OutdoorPvPMgr* instance(); // create outdoor pvp events void InitOutdoorPvP(); diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index 006ce9c52f7..4e51641c502 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -60,6 +60,11 @@ bool ActivePoolData::IsActiveObject<Quest>(uint64 quest_id) const return mActiveQuests.find(quest_id) != mActiveQuests.end(); } +template TC_GAME_API bool ActivePoolData::IsActiveObject<Creature>(uint64) const; +template TC_GAME_API bool ActivePoolData::IsActiveObject<GameObject>(uint64) const; +template TC_GAME_API bool ActivePoolData::IsActiveObject<Pool>(uint64) const; +template TC_GAME_API bool ActivePoolData::IsActiveObject<Quest>(uint64) const; + template<> void ActivePoolData::ActivateObject<Creature>(uint64 db_guid, uint32 pool_id) { @@ -570,6 +575,12 @@ void PoolMgr::Initialize() mCreatureSearchMap.clear(); } +PoolMgr* PoolMgr::instance() +{ + static PoolMgr instance; + return &instance; +} + void PoolMgr::LoadFromDB() { // Pool templates diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h index 59cbee83094..b38d27f9c94 100644 --- a/src/server/game/Pools/PoolMgr.h +++ b/src/server/game/Pools/PoolMgr.h @@ -43,7 +43,7 @@ class Pool // for Pool of Pool typedef std::set<uint64> ActivePoolObjects; typedef std::map<uint64, uint32> ActivePoolPools; -class ActivePoolData +class TC_GAME_API ActivePoolData { public: template<typename T> @@ -66,7 +66,7 @@ class ActivePoolData }; template <class T> -class PoolGroup +class TC_GAME_API PoolGroup { typedef std::vector<PoolObject> PoolObjectList; public: @@ -101,18 +101,14 @@ typedef std::multimap<uint32, uint32> PooledQuestRelation; typedef std::pair<PooledQuestRelation::const_iterator, PooledQuestRelation::const_iterator> PooledQuestRelationBounds; typedef std::pair<PooledQuestRelation::iterator, PooledQuestRelation::iterator> PooledQuestRelationBoundsNC; -class PoolMgr +class TC_GAME_API PoolMgr { private: PoolMgr(); ~PoolMgr() { }; public: - static PoolMgr* instance() - { - static PoolMgr instance; - return &instance; - } + static PoolMgr* instance(); void LoadFromDB(); void LoadQuestPools(); diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 8b27be40c20..b0df26f1ca5 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -276,7 +276,7 @@ typedef std::vector<QuestObjective> QuestObjectives; // This Quest class provides a convenient way to access a few pretotaled (cached) quest details, // all base quest information, and any utility functions such as generating the amount of // xp to give -class Quest +class TC_GAME_API Quest { friend class ObjectMgr; friend class Player; diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h index 224a928bbac..f2a5f3ba1f3 100644 --- a/src/server/game/Reputation/ReputationMgr.h +++ b/src/server/game/Reputation/ReputationMgr.h @@ -61,7 +61,7 @@ typedef std::map<uint32, ReputationRank> ForcedReactions; class Player; -class ReputationMgr +class TC_GAME_API ReputationMgr { public: // constructors and global modifiers explicit ReputationMgr(Player* owner) : _player(owner), diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 38ca4911a21..9b403e608c1 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -22,10 +22,10 @@ #include "DBCStores.h" #include "ObjectMgr.h" #include "OutdoorPvPMgr.h" -#include "ScriptLoader.h" #include "ScriptSystem.h" #include "Transport.h" #include "Vehicle.h" +#include "SmartAI.h" #include "SpellInfo.h" #include "SpellScript.h" #include "GossipDef.h" @@ -240,12 +240,19 @@ struct TSpellSummary uint8 Effects; // set of enum SelectEffect } *SpellSummary; -ScriptMgr::ScriptMgr() : _scriptCount(0), _scheduledScripts(0) +ScriptMgr::ScriptMgr() + : _scriptCount(0), _scheduledScripts(0), _script_loader_callback(nullptr) { } ScriptMgr::~ScriptMgr() { } +ScriptMgr* ScriptMgr::instance() +{ + static ScriptMgr instance; + return &instance; +} + void ScriptMgr::Initialize() { uint32 oldMSTime = getMSTime(); @@ -255,7 +262,13 @@ void ScriptMgr::Initialize() TC_LOG_INFO("server.loading", "Loading C++ scripts"); FillSpellSummary(); - AddScripts(); + + AddSC_SmartScripts(); + + ASSERT(_script_loader_callback, + "Script loader callback wasn't registered!"); + + _script_loader_callback(); #ifdef SCRIPTS for (std::string const& scriptName : UnusedScriptNames) @@ -504,17 +517,6 @@ void ScriptMgr::OnPacketSend(WorldSession* session, WorldPacket const& packet) FOREACH_SCRIPT(ServerScript)->OnPacketSend(session, copy); } -void ScriptMgr::OnUnknownPacketReceive(WorldSession* session, WorldPacket const& packet) -{ - ASSERT(session); - - if (SCR_REG_LST(ServerScript).empty()) - return; - - WorldPacket copy(packet); - FOREACH_SCRIPT(ServerScript)->OnUnknownPacketReceive(session, copy); -} - void ScriptMgr::OnOpenStateChange(bool open) { FOREACH_SCRIPT(WorldScript)->OnOpenStateChange(open); @@ -1689,32 +1691,32 @@ template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::Scripts; template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0; // Specialize for each script type class like so: -template class ScriptRegistry<SpellScriptLoader>; -template class ScriptRegistry<ServerScript>; -template class ScriptRegistry<WorldScript>; -template class ScriptRegistry<FormulaScript>; -template class ScriptRegistry<WorldMapScript>; -template class ScriptRegistry<InstanceMapScript>; -template class ScriptRegistry<BattlegroundMapScript>; -template class ScriptRegistry<ItemScript>; -template class ScriptRegistry<CreatureScript>; -template class ScriptRegistry<GameObjectScript>; -template class ScriptRegistry<AreaTriggerScript>; -template class ScriptRegistry<BattlegroundScript>; -template class ScriptRegistry<OutdoorPvPScript>; -template class ScriptRegistry<CommandScript>; -template class ScriptRegistry<WeatherScript>; -template class ScriptRegistry<AuctionHouseScript>; -template class ScriptRegistry<ConditionScript>; -template class ScriptRegistry<VehicleScript>; -template class ScriptRegistry<DynamicObjectScript>; -template class ScriptRegistry<TransportScript>; -template class ScriptRegistry<AchievementCriteriaScript>; -template class ScriptRegistry<PlayerScript>; -template class ScriptRegistry<GuildScript>; -template class ScriptRegistry<GroupScript>; -template class ScriptRegistry<UnitScript>; -template class ScriptRegistry<AccountScript>; +template class TC_GAME_API ScriptRegistry<SpellScriptLoader>; +template class TC_GAME_API ScriptRegistry<ServerScript>; +template class TC_GAME_API ScriptRegistry<WorldScript>; +template class TC_GAME_API ScriptRegistry<FormulaScript>; +template class TC_GAME_API ScriptRegistry<WorldMapScript>; +template class TC_GAME_API ScriptRegistry<InstanceMapScript>; +template class TC_GAME_API ScriptRegistry<BattlegroundMapScript>; +template class TC_GAME_API ScriptRegistry<ItemScript>; +template class TC_GAME_API ScriptRegistry<CreatureScript>; +template class TC_GAME_API ScriptRegistry<GameObjectScript>; +template class TC_GAME_API ScriptRegistry<AreaTriggerScript>; +template class TC_GAME_API ScriptRegistry<BattlegroundScript>; +template class TC_GAME_API ScriptRegistry<OutdoorPvPScript>; +template class TC_GAME_API ScriptRegistry<CommandScript>; +template class TC_GAME_API ScriptRegistry<WeatherScript>; +template class TC_GAME_API ScriptRegistry<AuctionHouseScript>; +template class TC_GAME_API ScriptRegistry<ConditionScript>; +template class TC_GAME_API ScriptRegistry<VehicleScript>; +template class TC_GAME_API ScriptRegistry<DynamicObjectScript>; +template class TC_GAME_API ScriptRegistry<TransportScript>; +template class TC_GAME_API ScriptRegistry<AchievementCriteriaScript>; +template class TC_GAME_API ScriptRegistry<PlayerScript>; +template class TC_GAME_API ScriptRegistry<GuildScript>; +template class TC_GAME_API ScriptRegistry<GroupScript>; +template class TC_GAME_API ScriptRegistry<UnitScript>; +template class TC_GAME_API ScriptRegistry<AccountScript>; // Undefine utility macros. #undef GET_SCRIPT_RET diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index aac2cdeabfa..f75446048ff 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -146,7 +146,7 @@ struct OutdoorPvPData; event on all registered scripts of that type. */ -class ScriptObject +class TC_GAME_API ScriptObject { friend class ScriptMgr; @@ -185,7 +185,7 @@ template<class TObject> class UpdatableScript virtual void OnUpdate(TObject* /*obj*/, uint32 /*diff*/) { } }; -class SpellScriptLoader : public ScriptObject +class TC_GAME_API SpellScriptLoader : public ScriptObject { protected: @@ -200,7 +200,7 @@ class SpellScriptLoader : public ScriptObject virtual AuraScript* GetAuraScript() const { return NULL; } }; -class ServerScript : public ScriptObject +class TC_GAME_API ServerScript : public ScriptObject { protected: @@ -228,10 +228,6 @@ class ServerScript : public ScriptObject // Called when a (valid) packet is received by a client. The packet object is a copy of the original packet, so // reading and modifying it is safe. Make sure to check WorldSession pointer before usage, it might be null in case of auth packets virtual void OnPacketReceive(WorldSession* /*session*/, WorldPacket& /*packet*/) { } - - // Called when an invalid (unknown opcode) packet is received by a client. The packet is a reference to the orignal - // packet; not a copy. This allows you to actually handle unknown packets (for whatever purpose). - virtual void OnUnknownPacketReceive(WorldSession* /*session*/, WorldPacket& /*packet*/) { } }; class WorldScript : public ScriptObject @@ -334,14 +330,14 @@ template<class TMap> class MapScript : public UpdatableScript<TMap> virtual void OnPlayerLeave(TMap* /*map*/, Player* /*player*/) { } }; -class WorldMapScript : public ScriptObject, public MapScript<Map> +class TC_GAME_API WorldMapScript : public ScriptObject, public MapScript<Map> { protected: WorldMapScript(const char* name, uint32 mapId); }; -class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> +class TC_GAME_API InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> { protected: @@ -353,14 +349,14 @@ class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; } }; -class BattlegroundMapScript : public ScriptObject, public MapScript<BattlegroundMap> +class TC_GAME_API BattlegroundMapScript : public ScriptObject, public MapScript<BattlegroundMap> { protected: BattlegroundMapScript(const char* name, uint32 mapId); }; -class ItemScript : public ScriptObject +class TC_GAME_API ItemScript : public ScriptObject { protected: @@ -384,7 +380,7 @@ class ItemScript : public ScriptObject virtual bool OnRemove(Player* /*player*/, Item* /*item*/) { return false; } }; -class UnitScript : public ScriptObject +class TC_GAME_API UnitScript : public ScriptObject { protected: @@ -407,7 +403,7 @@ class UnitScript : public ScriptObject virtual void ModifySpellDamageTaken(Unit* /*target*/, Unit* /*attacker*/, int32& /*damage*/) { } }; -class CreatureScript : public UnitScript, public UpdatableScript<Creature> +class TC_GAME_API CreatureScript : public UnitScript, public UpdatableScript<Creature> { protected: @@ -443,7 +439,7 @@ class CreatureScript : public UnitScript, public UpdatableScript<Creature> virtual CreatureAI* GetAI(Creature* /*creature*/) const { return NULL; } }; -class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject> +class TC_GAME_API GameObjectScript : public ScriptObject, public UpdatableScript<GameObject> { protected: @@ -488,7 +484,7 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject> virtual GameObjectAI* GetAI(GameObject* /*go*/) const { return NULL; } }; -class AreaTriggerScript : public ScriptObject +class TC_GAME_API AreaTriggerScript : public ScriptObject { protected: @@ -500,7 +496,7 @@ class AreaTriggerScript : public ScriptObject virtual bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/, bool /*entered*/) { return false; } }; -class BattlegroundScript : public ScriptObject +class TC_GAME_API BattlegroundScript : public ScriptObject { protected: @@ -512,7 +508,7 @@ class BattlegroundScript : public ScriptObject virtual Battleground* GetBattleground() const = 0; }; -class OutdoorPvPScript : public ScriptObject +class TC_GAME_API OutdoorPvPScript : public ScriptObject { protected: @@ -524,7 +520,7 @@ class OutdoorPvPScript : public ScriptObject virtual OutdoorPvP* GetOutdoorPvP() const = 0; }; -class CommandScript : public ScriptObject +class TC_GAME_API CommandScript : public ScriptObject { protected: @@ -536,7 +532,7 @@ class CommandScript : public ScriptObject virtual std::vector<ChatCommand> GetCommands() const = 0; }; -class WeatherScript : public ScriptObject, public UpdatableScript<Weather> +class TC_GAME_API WeatherScript : public ScriptObject, public UpdatableScript<Weather> { protected: @@ -548,7 +544,7 @@ class WeatherScript : public ScriptObject, public UpdatableScript<Weather> virtual void OnChange(Weather* /*weather*/, WeatherState /*state*/, float /*grade*/) { } }; -class AuctionHouseScript : public ScriptObject +class TC_GAME_API AuctionHouseScript : public ScriptObject { protected: @@ -569,7 +565,7 @@ class AuctionHouseScript : public ScriptObject virtual void OnAuctionExpire(AuctionHouseObject* /*ah*/, AuctionEntry* /*entry*/) { } }; -class ConditionScript : public ScriptObject +class TC_GAME_API ConditionScript : public ScriptObject { protected: @@ -581,7 +577,7 @@ class ConditionScript : public ScriptObject virtual bool OnConditionCheck(Condition const* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; } }; -class VehicleScript : public ScriptObject +class TC_GAME_API VehicleScript : public ScriptObject { protected: @@ -608,14 +604,14 @@ class VehicleScript : public ScriptObject virtual void OnRemovePassenger(Vehicle* /*veh*/, Unit* /*passenger*/) { } }; -class DynamicObjectScript : public ScriptObject, public UpdatableScript<DynamicObject> +class TC_GAME_API DynamicObjectScript : public ScriptObject, public UpdatableScript<DynamicObject> { protected: DynamicObjectScript(const char* name); }; -class TransportScript : public ScriptObject, public UpdatableScript<Transport> +class TC_GAME_API TransportScript : public ScriptObject, public UpdatableScript<Transport> { protected: @@ -636,7 +632,7 @@ class TransportScript : public ScriptObject, public UpdatableScript<Transport> virtual void OnRelocate(Transport* /*transport*/, uint32 /*waypointId*/, uint32 /*mapId*/, float /*x*/, float /*y*/, float /*z*/) { } }; -class AchievementCriteriaScript : public ScriptObject +class TC_GAME_API AchievementCriteriaScript : public ScriptObject { protected: @@ -648,7 +644,7 @@ class AchievementCriteriaScript : public ScriptObject virtual bool OnCheck(Player* source, Unit* target) = 0; }; -class PlayerScript : public UnitScript +class TC_GAME_API PlayerScript : public UnitScript { protected: @@ -745,7 +741,7 @@ class PlayerScript : public UnitScript virtual void OnQuestStatusChange(Player* /*player*/, uint32 /*questId*/, QuestStatus /*status*/) { } }; -class AccountScript : public ScriptObject +class TC_GAME_API AccountScript : public ScriptObject { protected: @@ -772,7 +768,7 @@ class AccountScript : public ScriptObject virtual void OnFailedPasswordChange(uint32 /*accountId*/) {} }; -class GuildScript : public ScriptObject +class TC_GAME_API GuildScript : public ScriptObject { protected: @@ -813,7 +809,7 @@ class GuildScript : public ScriptObject virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, ObjectGuid::LowType /*playerGuid*/, uint64 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { } }; -class GroupScript : public ScriptObject +class TC_GAME_API GroupScript : public ScriptObject { protected: @@ -843,11 +839,11 @@ class GroupScript : public ScriptObject // namespace // { typedef std::list<std::string> UnusedScriptNamesContainer; - extern UnusedScriptNamesContainer UnusedScriptNames; + TC_GAME_API extern UnusedScriptNamesContainer UnusedScriptNames; // } // Manages registration, loading, and execution of scripts. -class ScriptMgr +class TC_GAME_API ScriptMgr { friend class ScriptObject; @@ -856,11 +852,7 @@ class ScriptMgr virtual ~ScriptMgr(); public: /* Initialization */ - static ScriptMgr* instance() - { - static ScriptMgr instance; - return &instance; - } + static ScriptMgr* instance(); void Initialize(); void LoadDatabase(); @@ -871,6 +863,15 @@ class ScriptMgr void IncrementScriptCount() { ++_scriptCount; } uint32 GetScriptCount() const { return _scriptCount; } + typedef void(*ScriptLoaderCallbackType)(); + + /// Sets the script loader callback which is invoked to load scripts + /// (Workaround for circular dependency game <-> scripts) + void SetScriptLoader(ScriptLoaderCallbackType script_loader_callback) + { + _script_loader_callback = script_loader_callback; + } + public: /* Unloading */ void Unload(); @@ -889,7 +890,6 @@ class ScriptMgr void OnSocketClose(std::shared_ptr<WorldSocket> socket); void OnPacketReceive(WorldSession* session, WorldPacket const& packet); void OnPacketSend(WorldSession* session, WorldPacket const& packet); - void OnUnknownPacketReceive(WorldSession* session, WorldPacket const& packet); public: /* WorldScript */ @@ -1106,6 +1106,8 @@ class ScriptMgr //atomic op counter for active scripts amount std::atomic<uint64> _scheduledScripts; + + ScriptLoaderCallbackType _script_loader_callback; }; #endif diff --git a/src/server/game/Scripting/ScriptSystem.cpp b/src/server/game/Scripting/ScriptSystem.cpp index e828830ec0f..52c5c1640af 100644 --- a/src/server/game/Scripting/ScriptSystem.cpp +++ b/src/server/game/Scripting/ScriptSystem.cpp @@ -21,7 +21,13 @@ #include "DatabaseEnv.h" #include "ScriptMgr.h" -ScriptPointVector const SystemMgr::_empty; +TC_GAME_API ScriptPointVector const SystemMgr::_empty; + +SystemMgr* SystemMgr::instance() +{ + static SystemMgr instance; + return &instance; +} void SystemMgr::LoadScriptWaypoints() { diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h index aebfbf85502..1b79c29d643 100644 --- a/src/server/game/Scripting/ScriptSystem.h +++ b/src/server/game/Scripting/ScriptSystem.h @@ -59,18 +59,14 @@ struct ScriptPointMove typedef std::vector<ScriptPointMove> ScriptPointVector; -class SystemMgr +class TC_GAME_API SystemMgr { private: SystemMgr() { } ~SystemMgr() { } public: - static SystemMgr* instance() - { - static SystemMgr instance; - return &instance; - } + static SystemMgr* instance(); typedef std::unordered_map<uint32, ScriptPointVector> PointMoveMap; diff --git a/src/server/game/Server/BattlenetServerManager.cpp b/src/server/game/Server/BattlenetServerManager.cpp deleted file mode 100644 index 5da0d81161a..00000000000 --- a/src/server/game/Server/BattlenetServerManager.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "Config.h" -#include "World.h" -#include "ZmqContext.h" -#include "BattlenetServerManager.h" - -void IPC::BattlenetComm::ServerManager::InitializeConnection() -{ - std::string bnetserverAddress = sConfigMgr->GetStringDefault("BnetServer.Address", "127.0.0.1"); - int32 bnetserverPort = sConfigMgr->GetIntDefault("BnetServer.Port", 1118); - _socket = new ZmqMux("inproc://bnetmgr", "tcp://" + bnetserverAddress + ":" + std::to_string(bnetserverPort)); - _socket->Start(); -} - -void IPC::BattlenetComm::ServerManager::CloseConnection() -{ - _socket->End(); - delete _socket; - _socket = nullptr; -} - -IPC::BattlenetComm::Header IPC::BattlenetComm::ServerManager::CreateHeader(BnetCommands command) -{ - Header header; - header.Ipc.Channel = IPC_CHANNEL_BNET; - header.Ipc.Command = command; - header.Realm = realm.Id; - return header; -} - -void IPC::BattlenetComm::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online) -{ - // Do nothing for Grunt login - if (!battlenetAccountId) - return; - - Header header = CreateHeader(BNET_CHANGE_TOON_ONLINE_STATE); - ToonHandle toon; - toon.AccountId = battlenetAccountId; - toon.GameAccountId = gameAccountId; - toon.Guid = guid.GetCounter(); - toon.Name = name; - - zmqpp::message msg; - msg << header; - msg << toon; - msg << online; - - 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 deleted file mode 100644 index 4d426c96eb1..00000000000 --- a/src/server/game/Server/BattlenetServerManager.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef BattlenetMgr_h__ -#define BattlenetMgr_h__ - -#include "ZmqMux.h" -#include "Commands.h" - -namespace zmqpp -{ - class socket; - class message; -} - -namespace IPC -{ - namespace BattlenetComm - { - class ServerManager - { - ServerManager() : _socket(nullptr) { } - - public: - void InitializeConnection(); - void CloseConnection(); - - static ServerManager& Instance() - { - static ServerManager instance; - return 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 IPC::BattlenetComm::ServerManager::Instance() - -#endif // BattlenetMgr_h__ diff --git a/src/server/game/Server/Packet.h b/src/server/game/Server/Packet.h index ed9c1cc0afd..4bf9f2be688 100644 --- a/src/server/game/Server/Packet.h +++ b/src/server/game/Server/Packet.h @@ -22,7 +22,7 @@ namespace WorldPackets { - class Packet + class TC_GAME_API Packet { public: Packet(WorldPacket&& worldPacket) : _worldPacket(std::move(worldPacket)) { } diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index 6a76f8ee3b8..648d03ec4ef 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -20,34 +20,39 @@ WorldPacket const* WorldPackets::Auth::AuthChallenge::Write() { - _worldPacket << uint32(Challenge); _worldPacket.append(DosChallenge, 8); + _worldPacket.append(Challenge.data(), Challenge.size()); _worldPacket << uint8(DosZeroBits); return &_worldPacket; } void WorldPackets::Auth::AuthSession::Read() { - uint32 addonDataSize; + uint32 addonDataSize, realmJoinTicketSize; - _worldPacket >> LoginServerID; _worldPacket >> Build; + _worldPacket >> BuildType; _worldPacket >> RegionID; _worldPacket >> BattlegroupID; _worldPacket >> RealmID; - _worldPacket >> LoginServerType; - _worldPacket >> BuildType; - _worldPacket >> LocalChallenge; + _worldPacket.read(LocalChallenge.data(), LocalChallenge.size()); + _worldPacket.read(Digest.data(), Digest.size()); _worldPacket >> DosResponse; - _worldPacket.read(Digest, SHA_DIGEST_LENGTH); - Account = _worldPacket.ReadString(_worldPacket.ReadBits(11)); - UseIPv6 = _worldPacket.ReadBit(); // UseIPv6 _worldPacket >> addonDataSize; if (addonDataSize) { - AddonInfo.resize(addonDataSize); - _worldPacket.read(AddonInfo.contents(), addonDataSize); + AddonInfo.resize(std::min(addonDataSize, uint32(_worldPacket.size() - _worldPacket.rpos()))); + _worldPacket.read(AddonInfo.contents(), AddonInfo.size()); + } + + _worldPacket >> realmJoinTicketSize; + if (realmJoinTicketSize) + { + RealmJoinTicket.resize(std::min(realmJoinTicketSize, uint32(_worldPacket.size() - _worldPacket.rpos()))); + _worldPacket.read(reinterpret_cast<uint8*>(&RealmJoinTicket[0]), RealmJoinTicket.size()); } + + UseIPv6 = _worldPacket.ReadBit(); // UseIPv6 } WorldPackets::Auth::AuthResponse::AuthResponse() @@ -57,7 +62,7 @@ WorldPackets::Auth::AuthResponse::AuthResponse() WorldPacket const* WorldPackets::Auth::AuthResponse::Write() { - _worldPacket << uint8(Result); + _worldPacket << uint32(Result); _worldPacket.WriteBit(SuccessInfo.is_initialized()); _worldPacket.WriteBit(WaitInfo.is_initialized()); _worldPacket.FlushBits(); @@ -294,7 +299,7 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write() ByteBuffer payload; uint16 port = Payload.Where.port(); uint8 address[16] = { 0 }; - uint32 addressType = 3; + uint8 addressType = 3; if (Payload.Where.address().is_v4()) { memcpy(address, Payload.Where.address().to_v4().to_bytes().data(), 4); @@ -308,7 +313,7 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write() HmacSha1 hmacHash(64, WherePacketHmac); hmacHash.UpdateData(address, 16); - hmacHash.UpdateData((uint8* const)&addressType, 4); + hmacHash.UpdateData(&addressType, 1); hmacHash.UpdateData((uint8* const)&port, 2); hmacHash.UpdateData((uint8* const)Haiku.c_str(), 71); hmacHash.UpdateData(Payload.PanamaKey, 32); @@ -316,260 +321,15 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write() hmacHash.UpdateData(&Payload.XorMagic, 1); hmacHash.Finalize(); - uint8* hmac = hmacHash.GetDigest(); - - payload << uint8(Haiku[53]); - payload << uint8(PiDigits[12]); - payload << uint8(Haiku[27]); - payload << uint8(PiDigits[65]); - payload << uint8(PiDigits[96]); - payload << uint8(Haiku[29]); - payload << uint8(Payload.PanamaKey[12]); - payload << uint8(hmac[3]); - payload << uint8(PiDigits[10]); - payload << uint8(Payload.PanamaKey[20]); - payload << uint8(PiDigits[14]); - payload << uint8(hmac[17]); - payload << uint8(Haiku[3]); - payload << uint8(PiDigits[26]); - payload << uint8(PiDigits[94]); - payload << uint8(PiDigits[7]); - payload << uint8(PiDigits[93]); - payload << uint8(Payload.PanamaKey[8]); - payload << uint8(PiDigits[40]); - payload << uint8(PiDigits[52]); - payload << uint8(Haiku[44]); - payload << uint8(address[13]); - payload << uint8(Haiku[57]); - payload << uint8(PiDigits[59]); - payload << uint8(PiDigits[97]); - payload << uint8(PiDigits[42]); - payload << uint8(Haiku[70]); - payload << uint8(Haiku[42]); - payload << uint8(PiDigits[50]); - payload << uint8(address[3]); - payload << uint8(PiDigits[60]); - payload << uint8(address[12]); - payload << uint8(PiDigits[86]); - payload << uint8(Haiku[56]); - payload << uint8(PiDigits[70]); - payload << uint8(Haiku[26]); - payload << uint8(PiDigits[74]); - payload << uint8(PiDigits[49]); - payload << uint8(Payload.PanamaKey[28]); - payload << uint8(Haiku[69]); - payload << uint8(hmac[9]); - payload << uint8(Haiku[15]); - payload << uint8(Payload.PanamaKey[0]); - payload << uint8(Payload.PanamaKey[6]); - payload << uint8(Haiku[17]); - payload << uint8((port >> 8) & 0xFF); - payload << uint8(PiDigits[20]); - payload << uint8(PiDigits[99]); - payload << uint8(PiDigits[95]); - payload << uint8(PiDigits[100]); - payload << uint8(PiDigits[105]); - payload << uint8(hmac[13]); - payload << uint8(Payload.PanamaKey[9]); - payload << uint8(PiDigits[41]); - payload << uint8(PiDigits[35]); - payload << uint8(Haiku[10]); - payload << uint8(Haiku[20]); - payload << uint8(Haiku[14]); - payload << uint8(Haiku[47]); - payload << uint8(Payload.PanamaKey[10]); - payload << uint8(PiDigits[54]); - payload << uint8(PiDigits[67]); - payload << uint8(PiDigits[79]); - payload << uint8(Payload.PanamaKey[3]); - payload << uint8(PiDigits[84]); - payload << uint8(Haiku[33]); - payload << uint8(Haiku[23]); - payload << uint8(Haiku[48]); - payload << uint8(PiDigits[64]); - payload << uint8(PiDigits[85]); - payload << uint8(Payload.PanamaKey[24]); - payload << uint8(hmac[8]); - payload << uint8(PiDigits[101]); - payload << uint8(addressType); - payload << uint8(PiDigits[53]); - payload << uint8(Haiku[39]); - payload << uint8(hmac[19]); - payload << uint8(Payload.PanamaKey[31]); - payload << uint8(Payload.PanamaKey[18]); - payload << uint8(hmac[4]); - payload << uint8(Haiku[54]); - payload << uint8(PiDigits[76]); - payload << uint8(address[9]); - payload << uint8(hmac[7]); - payload << uint8(PiDigits[80]); - payload << uint8(hmac[2]); - payload << uint8(Haiku[13]); - payload << uint8(Haiku[11]); - payload << uint8(Payload.PanamaKey[7]); - payload << uint8(Haiku[64]); - payload << uint8(Haiku[62]); - payload << uint8(Haiku[9]); - payload << uint8(Payload.PanamaKey[26]); - payload << uint8(hmac[1]); - payload << uint8(hmac[15]); - payload << uint8(PiDigits[25]); - payload << uint8(hmac[14]); - payload << uint8(Haiku[35]); - payload << uint8(Haiku[43]); - payload << uint8(PiDigits[58]); - payload << uint8(Payload.PanamaKey[1]); - payload << uint8(PiDigits[45]); - payload << uint8(Payload.PanamaKey[25]); - payload << uint8(PiDigits[69]); - payload << uint8(PiDigits[27]); - payload << uint8(address[4]); - payload << uint8(PiDigits[11]); - payload << uint8(Payload.PanamaKey[16]); - payload << uint8(PiDigits[38]); - payload << uint8(PiDigits[82]); - payload << uint8(PiDigits[1]); - payload << uint8(PiDigits[103]); - payload << uint8(address[10]); - payload << uint8(Haiku[18]); - payload << uint8(PiDigits[91]); - payload << uint8(PiDigits[75]); - payload << uint8(PiDigits[34]); - payload << uint8(Payload.PanamaKey[27]); - payload << uint8(PiDigits[106]); - payload << uint8(PiDigits[28]); - payload << uint8(Haiku[8]); - payload << uint8(PiDigits[5]); - payload << uint8(Haiku[68]); - payload << uint8(Payload.PanamaKey[15]); - payload << uint8(address[2]); - payload << uint8(PiDigits[48]); - payload << uint8(PiDigits[107]); - payload << uint8(Payload.PanamaKey[17]); - payload << uint8(PiDigits[15]); payload << uint32(Payload.Adler32); - payload << uint8(PiDigits[36]); - payload << uint8(address[5]); - payload << uint8(PiDigits[71]); - payload << uint8(address[15]); - payload << uint8(address[0]); - payload << uint8(hmac[5]); - payload << uint8(PiDigits[83]); - payload << uint8(Payload.PanamaKey[14]); - payload << uint8(PiDigits[55]); - payload << uint8(PiDigits[31]); - payload << uint8(Haiku[52]); - payload << uint8(PiDigits[22]); - payload << uint8(PiDigits[8]); - payload << uint8(PiDigits[6]); - payload << uint8(Payload.PanamaKey[21]); - payload << uint8(port & 0xFF); - payload << uint8(PiDigits[51]); - payload << uint8(Haiku[31]); - payload << uint8(Haiku[59]); - payload << uint8(PiDigits[17]); - payload << uint8(PiDigits[88]); - payload << uint8(PiDigits[32]); - payload << uint8(address[6]); - payload << uint8(Haiku[49]); - payload << uint8(PiDigits[21]); - payload << uint8(Payload.PanamaKey[13]); - payload << uint8(address[1]); - payload << uint8(Haiku[19]); - payload << uint8(Haiku[63]); - payload << uint8(PiDigits[4]); - payload << uint8(Haiku[65]); - payload << uint8(PiDigits[39]); - payload << uint8(Haiku[21]); - payload << uint8(Haiku[32]); - payload << uint8(Haiku[25]); - payload << uint8(Haiku[1]); - payload << uint8(PiDigits[9]); - payload << uint8(Haiku[2]); - payload << uint8(Payload.PanamaKey[22]); - payload << uint8(PiDigits[78]); - payload << uint8(Haiku[4]); - payload << uint8(Haiku[50]); - payload << uint8(Payload.PanamaKey[29]); - payload << uint8(hmac[12]); - payload << uint8(PiDigits[56]); - payload << uint8(address[11]); - payload << uint8(PiDigits[102]); - payload << uint8(Payload.PanamaKey[19]); - payload << uint8(PiDigits[33]); - payload << uint8(Haiku[30]); - payload << uint8(Payload.PanamaKey[5]); - payload << uint8(PiDigits[46]); - payload << uint8(PiDigits[30]); - payload << uint8(PiDigits[98]); - payload << uint8(Haiku[66]); - payload << uint8(PiDigits[77]); - payload << uint8(PiDigits[63]); - payload << uint8(Payload.PanamaKey[11]); - payload << uint8(PiDigits[2]); - payload << uint8(Haiku[61]); - payload << uint8(address[7]); - payload << uint8(PiDigits[3]); - payload << uint8(Haiku[12]); - payload << uint8(Haiku[40]); - payload << uint8(PiDigits[57]); - payload << uint8(Haiku[28]); - payload << uint8(PiDigits[29]); - payload << uint8(Haiku[46]); - payload << uint8(PiDigits[44]); - payload << uint8(address[14]); - payload << uint8(PiDigits[16]); - payload << uint8(PiDigits[87]); - payload << uint8(PiDigits[81]); - payload << uint8(hmac[18]); - payload << uint8(address[8]); - payload << uint8(Haiku[6]); - payload << uint8(hmac[16]); - payload << uint8(PiDigits[62]); - payload << uint8(PiDigits[72]); - payload << uint8(PiDigits[18]); - payload << uint8(PiDigits[43]); - payload << uint8(Haiku[7]); - payload << uint8(Haiku[37]); + payload << uint8(addressType); + payload.append(address, 16); + payload << uint16(port); + payload.append(Haiku.data(), 71); + payload.append(Payload.PanamaKey, 32); + payload.append(PiDigits, 108); payload << uint8(Payload.XorMagic); - payload << uint8(Payload.PanamaKey[2]); - payload << uint8(PiDigits[92]); - payload << uint8(PiDigits[47]); - payload << uint8(PiDigits[13]); - payload << uint8(PiDigits[66]); - payload << uint8(Haiku[55]); - payload << uint8(PiDigits[73]); - payload << uint8(Haiku[5]); - payload << uint8(PiDigits[0]); - payload << uint8(Haiku[16]); - payload << uint8(Haiku[34]); - payload << uint8(hmac[10]); - payload << uint8(PiDigits[89]); - payload << uint8(Haiku[38]); - payload << uint8(Haiku[22]); - payload << uint8(hmac[11]); - payload << uint8(PiDigits[61]); - payload << uint8(Haiku[0]); - payload << uint8(hmac[0]); - payload << uint8(Haiku[24]); - payload << uint8(PiDigits[37]); - payload << uint8(hmac[6]); - payload << uint8(Haiku[41]); - payload << uint8(Haiku[60]); - payload << uint8(PiDigits[90]); - payload << uint8(Haiku[67]); - payload << uint8(Haiku[51]); - payload << uint8(PiDigits[24]); - payload << uint8(PiDigits[23]); - payload << uint8(Haiku[58]); - payload << uint8(Haiku[45]); - payload << uint8(PiDigits[104]); - payload << uint8(PiDigits[68]); - payload << uint8(Payload.PanamaKey[30]); - payload << uint8(Payload.PanamaKey[23]); - payload << uint8(Payload.PanamaKey[4]); - payload << uint8(Haiku[36]); - payload << uint8(PiDigits[19]); + payload.append(hmacHash.GetDigest(), hmacHash.GetLength()); BigNumber bnData; bnData.SetBinary(payload.contents(), payload.size()); @@ -594,7 +354,8 @@ void WorldPackets::Auth::AuthContinuedSession::Read() { _worldPacket >> DosResponse; _worldPacket >> Key; - _worldPacket.read(Digest, SHA_DIGEST_LENGTH); + _worldPacket.read(LocalChallenge.data(), LocalChallenge.size()); + _worldPacket.read(Digest.data(), Digest.size()); } void WorldPackets::Auth::ConnectToFailed::Read() diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index 123d4a24f10..5bd433ebb57 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -38,7 +38,7 @@ namespace WorldPackets WorldPacket const* Write() override; - uint32 Challenge = 0; + std::array<uint8, 16> Challenge; uint32 DosChallenge[8]; ///< Encryption seeds uint8 DosZeroBits = 0; }; @@ -46,26 +46,27 @@ namespace WorldPackets class AuthSession final : public ClientPacket { public: + static uint32 const DigestLength = 24; + AuthSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_SESSION, std::move(packet)) { - memset(Digest, 0, SHA_DIGEST_LENGTH); + LocalChallenge.fill(0); + Digest.fill(0); } void Read() override; - uint32 BattlegroupID = 0; - int8 LoginServerType = 0; ///< Auth type used - 0 GRUNT, 1 battle.net - int8 BuildType = 0; - uint32 RealmID = 0; uint16 Build = 0; - uint32 LocalChallenge = 0; - int32 LoginServerID = 0; + int8 BuildType = 0; uint32 RegionID = 0; + uint32 BattlegroupID = 0; + uint32 RealmID = 0; + std::array<uint8, 16> LocalChallenge; + std::array<uint8, DigestLength> Digest; uint64 DosResponse = 0; - uint8 Digest[SHA_DIGEST_LENGTH]; - std::string Account; - bool UseIPv6 = false; ByteBuffer AddonInfo; + std::string RealmJoinTicket; + bool UseIPv6 = false; }; class AuthResponse final : public ServerPacket @@ -121,7 +122,7 @@ namespace WorldPackets Optional<AuthSuccessInfo> SuccessInfo; ///< contains the packet data in case that it has account information (It is never set when WaitInfo is set), otherwise its contents are undefined. Optional<AuthWaitInfo> WaitInfo; ///< contains the queue wait information in case the account is in the login queue. - uint8 Result = 0; ///< the result of the authentication process, it is AUTH_OK if it succeeded and the account is ready to log in. It can also be AUTH_WAIT_QUEUE if the account entered the login queue (Queued, QueuePos), possible values are @ref ResponseCodes + uint32 Result = 0; ///< the result of the authentication process, it is AUTH_OK if it succeeded and the account is ready to log in. It can also be AUTH_WAIT_QUEUE if the account entered the login queue (Queued, QueuePos), possible values are @ref ResponseCodes }; enum class ConnectToSerial : uint32 @@ -169,16 +170,20 @@ namespace WorldPackets class AuthContinuedSession final : public ClientPacket { public: + static uint32 const DigestLength = 24; + AuthContinuedSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet)) { - memset(Digest, 0, SHA_DIGEST_LENGTH); + LocalChallenge.fill(0); + Digest.fill(0); } void Read() override; uint64 DosResponse = 0; uint64 Key = 0; - uint8 Digest[SHA_DIGEST_LENGTH]; + std::array<uint8, 16> LocalChallenge; + std::array<uint8, DigestLength> Digest; }; class ResumeComms final : public ServerPacket diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index d54402d40c7..d30779d49c2 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -28,8 +28,8 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel // "characters.hairColor, characters.facialStyle, characters.level, characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, " // 16 17 18 19 20 21 22 // "guild_member.guildid, characters.playerFlags, characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, " - // 23 24 25 - // "character_banned.guid, characters.slot, character_declinedname.genitive" + // 23 24 25 26 + // "character_banned.guid, characters.slot, characters.logout_time, character_declinedname.genitive" Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); Name = fields[1].GetString(); @@ -72,7 +72,7 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel if (fields[23].GetUInt64()) Flags |= CHARACTER_FLAG_LOCKED_BY_BILLING; - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[25].GetString().empty()) + if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[26].GetString().empty()) Flags |= CHARACTER_FLAG_DECLINED; if (atLoginFlags & AT_LOGIN_CUSTOMIZE) @@ -102,6 +102,7 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel Tokenizer equipment(fields[22].GetString(), ' '); ListPosition = fields[24].GetUInt8(); + LastPlayedTime = fields[25].GetUInt32(); for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot) { @@ -155,6 +156,7 @@ WorldPacket const* WorldPackets::Character::EnumCharactersResult::Write() _worldPacket << uint8(charInfo.VisualItems[slot].InventoryType); } + _worldPacket << uint32(charInfo.LastPlayedTime); _worldPacket.WriteBits(charInfo.Name.length(), 6); _worldPacket.WriteBit(charInfo.FirstLogin); _worldPacket.WriteBit(charInfo.BoostInProgress); diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h index bb163b075cc..017dddd1d06 100644 --- a/src/server/game/Server/Packets/CharacterPackets.h +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -133,6 +133,7 @@ namespace WorldPackets uint32 Flags3 = 0; ///< Character flags 3 @todo research bool FirstLogin = false; uint8 unkWod61x = 0; + uint32 LastPlayedTime = 0; struct PetInfo { @@ -721,7 +722,7 @@ namespace WorldPackets { public: SetPlayerDeclinedNames(WorldPacket&& packet) : ClientPacket(CMSG_SET_PLAYER_DECLINED_NAMES, std::move(packet)) { } - + void Read() override; ObjectGuid Player; diff --git a/src/server/game/Server/Packets/ChatPackets.h b/src/server/game/Server/Packets/ChatPackets.h index faa060b3c0f..590fa930845 100644 --- a/src/server/game/Server/Packets/ChatPackets.h +++ b/src/server/game/Server/Packets/ChatPackets.h @@ -147,7 +147,7 @@ namespace WorldPackets }; // SMSG_CHAT - class Chat final : public ServerPacket + class TC_GAME_API Chat final : public ServerPacket { public: Chat() : ServerPacket(SMSG_CHAT, 100) { } @@ -217,7 +217,7 @@ namespace WorldPackets int32 EmoteID = 0; }; - class PrintNotification final : public ServerPacket + class TC_GAME_API PrintNotification final : public ServerPacket { public: PrintNotification(std::string const& notifyText) : ServerPacket(SMSG_PRINT_NOTIFICATION, 2 + notifyText.size()), NotifyText(notifyText) { } diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h index ebf920e2787..cef9a810213 100644 --- a/src/server/game/Server/Packets/MiscPackets.h +++ b/src/server/game/Server/Packets/MiscPackets.h @@ -397,7 +397,7 @@ namespace WorldPackets WorldPacket const* Write() override { return &_worldPacket; } }; - class Weather final : public ServerPacket + class TC_GAME_API Weather final : public ServerPacket { public: Weather(); @@ -598,7 +598,7 @@ namespace WorldPackets ObjectGuid ObjectGUID; }; - class PlaySound final : public ServerPacket + class TC_GAME_API PlaySound final : public ServerPacket { public: PlaySound() : ServerPacket(SMSG_PLAY_SOUND, 20) { } diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index e8fc4586ac4..018e0d5fe1a 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -42,7 +42,7 @@ namespace WorldPackets MovementInfo movementInfo; }; - class MoveUpdate final : public ServerPacket + class TC_GAME_API MoveUpdate final : public ServerPacket { public: MoveUpdate() : ServerPacket(SMSG_MOVE_UPDATE) { } @@ -427,7 +427,7 @@ namespace WorldPackets ObjectGuid SummonerGUID; }; - class ControlUpdate final : public ServerPacket + class TC_GAME_API ControlUpdate final : public ServerPacket { public: ControlUpdate() : ServerPacket(SMSG_CONTROL_UPDATE, 16 + 1) { } diff --git a/src/server/game/Server/Packets/NPCPackets.h b/src/server/game/Server/Packets/NPCPackets.h index 28444e87e75..d5c1b9da118 100644 --- a/src/server/game/Server/Packets/NPCPackets.h +++ b/src/server/game/Server/Packets/NPCPackets.h @@ -207,7 +207,7 @@ namespace WorldPackets ObjectGuid Healer; }; - class SpiritHealerConfirm final : public ServerPacket + class TC_GAME_API SpiritHealerConfirm final : public ServerPacket { public: SpiritHealerConfirm() : ServerPacket(SMSG_SPIRIT_HEALER_CONFIRM, 16) { } diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp index bd4a171d0bc..803da693c95 100644 --- a/src/server/game/Server/Packets/QuestPackets.cpp +++ b/src/server/game/Server/Packets/QuestPackets.cpp @@ -25,7 +25,7 @@ void WorldPackets::Quest::QuestGiverStatusQuery::Read() WorldPacket const* WorldPackets::Quest::QuestGiverStatus::Write() { _worldPacket << QuestGiver.Guid; - _worldPacket << QuestGiver.Status; + _worldPacket << uint32(QuestGiver.Status); return &_worldPacket; } @@ -36,7 +36,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverStatusMultiple::Write() for (QuestGiverInfo const& questGiver : QuestGiver) { _worldPacket << questGiver.Guid; - _worldPacket << questGiver.Status; + _worldPacket << uint32(questGiver.Status); } return &_worldPacket; @@ -55,102 +55,102 @@ void WorldPackets::Quest::QueryQuestInfo::Read() WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write() { - _worldPacket << QuestID; + _worldPacket << uint32(QuestID); _worldPacket.WriteBit(Allow); _worldPacket.FlushBits(); if (Allow) { - _worldPacket << Info.QuestID; - _worldPacket << Info.QuestType; - _worldPacket << Info.QuestLevel; - _worldPacket << Info.QuestPackageID; - _worldPacket << Info.QuestMinLevel; - _worldPacket << Info.QuestSortID; - _worldPacket << Info.QuestInfoID; - _worldPacket << Info.SuggestedGroupNum; - _worldPacket << Info.RewardNextQuest; - _worldPacket << Info.RewardXPDifficulty; - _worldPacket << Info.RewardXPMultiplier; - _worldPacket << Info.RewardMoney; - _worldPacket << Info.RewardMoneyDifficulty; - _worldPacket << Info.RewardMoneyMultiplier; - _worldPacket << Info.RewardBonusMoney; - _worldPacket << Info.RewardDisplaySpell; - _worldPacket << Info.RewardSpell; - _worldPacket << Info.RewardHonor; - _worldPacket << Info.RewardKillHonor; - _worldPacket << Info.StartItem; - _worldPacket << Info.Flags; - _worldPacket << Info.FlagsEx; + _worldPacket << int32(Info.QuestID); + _worldPacket << int32(Info.QuestType); + _worldPacket << int32(Info.QuestLevel); + _worldPacket << int32(Info.QuestPackageID); + _worldPacket << int32(Info.QuestMinLevel); + _worldPacket << int32(Info.QuestSortID); + _worldPacket << int32(Info.QuestInfoID); + _worldPacket << int32(Info.SuggestedGroupNum); + _worldPacket << int32(Info.RewardNextQuest); + _worldPacket << int32(Info.RewardXPDifficulty); + _worldPacket << float(Info.RewardXPMultiplier); + _worldPacket << int32(Info.RewardMoney); + _worldPacket << int32(Info.RewardMoneyDifficulty); + _worldPacket << float(Info.RewardMoneyMultiplier); + _worldPacket << int32(Info.RewardBonusMoney); + _worldPacket << int32(Info.RewardDisplaySpell); + _worldPacket << int32(Info.RewardSpell); + _worldPacket << int32(Info.RewardHonor); + _worldPacket << float(Info.RewardKillHonor); + _worldPacket << int32(Info.StartItem); + _worldPacket << uint32(Info.Flags); + _worldPacket << uint32(Info.FlagsEx); for (uint32 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) { - _worldPacket << Info.RewardItems[i]; - _worldPacket << Info.RewardAmount[i]; - _worldPacket << Info.ItemDrop[i]; - _worldPacket << Info.ItemDropQuantity[i]; + _worldPacket << int32(Info.RewardItems[i]); + _worldPacket << int32(Info.RewardAmount[i]); + _worldPacket << int32(Info.ItemDrop[i]); + _worldPacket << int32(Info.ItemDropQuantity[i]); } for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) { - _worldPacket << Info.UnfilteredChoiceItems[i].ItemID; - _worldPacket << Info.UnfilteredChoiceItems[i].Quantity; - _worldPacket << Info.UnfilteredChoiceItems[i].DisplayID; + _worldPacket << int32(Info.UnfilteredChoiceItems[i].ItemID); + _worldPacket << int32(Info.UnfilteredChoiceItems[i].Quantity); + _worldPacket << int32(Info.UnfilteredChoiceItems[i].DisplayID); } - _worldPacket << Info.POIContinent; - _worldPacket << Info.POIx; - _worldPacket << Info.POIy; - _worldPacket << Info.POIPriority; + _worldPacket << int32(Info.POIContinent); + _worldPacket << float(Info.POIx); + _worldPacket << float(Info.POIy); + _worldPacket << int32(Info.POIPriority); - _worldPacket << Info.RewardTitle; - _worldPacket << Info.RewardTalents; - _worldPacket << Info.RewardArenaPoints; - _worldPacket << Info.RewardSkillLineID; - _worldPacket << Info.RewardNumSkillUps; + _worldPacket << int32(Info.RewardTitle); + _worldPacket << int32(Info.RewardTalents); + _worldPacket << int32(Info.RewardArenaPoints); + _worldPacket << int32(Info.RewardSkillLineID); + _worldPacket << int32(Info.RewardNumSkillUps); - _worldPacket << Info.PortraitGiver; - _worldPacket << Info.PortraitTurnIn; + _worldPacket << int32(Info.PortraitGiver); + _worldPacket << int32(Info.PortraitTurnIn); for (uint32 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i) { - _worldPacket << Info.RewardFactionID[i]; - _worldPacket << Info.RewardFactionValue[i]; - _worldPacket << Info.RewardFactionOverride[i]; + _worldPacket << int32(Info.RewardFactionID[i]); + _worldPacket << int32(Info.RewardFactionValue[i]); + _worldPacket << int32(Info.RewardFactionOverride[i]); } - _worldPacket << Info.RewardFactionFlags; + _worldPacket << int32(Info.RewardFactionFlags); for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) { - _worldPacket << Info.RewardCurrencyID[i]; - _worldPacket << Info.RewardCurrencyQty[i]; + _worldPacket << int32(Info.RewardCurrencyID[i]); + _worldPacket << int32(Info.RewardCurrencyQty[i]); } - _worldPacket << Info.AcceptedSoundKitID; - _worldPacket << Info.CompleteSoundKitID; + _worldPacket << int32(Info.AcceptedSoundKitID); + _worldPacket << int32(Info.CompleteSoundKitID); - _worldPacket << Info.AreaGroupID; - _worldPacket << Info.TimeAllowed; + _worldPacket << int32(Info.AreaGroupID); + _worldPacket << int32(Info.TimeAllowed); _worldPacket << int32(Info.Objectives.size()); _worldPacket << int32(Info.AllowableRaces); for (QuestObjective const& questObjective : Info.Objectives) { - _worldPacket << questObjective.ID; - _worldPacket << questObjective.Type; - _worldPacket << questObjective.StorageIndex; - _worldPacket << questObjective.ObjectID; - _worldPacket << questObjective.Amount; - _worldPacket << questObjective.Flags; - _worldPacket << questObjective.UnkFloat; + _worldPacket << uint32(questObjective.ID); + _worldPacket << uint8(questObjective.Type); + _worldPacket << int8(questObjective.StorageIndex); + _worldPacket << int32(questObjective.ObjectID); + _worldPacket << int32(questObjective.Amount); + _worldPacket << uint32(questObjective.Flags); + _worldPacket << float(questObjective.UnkFloat); _worldPacket << int32(questObjective.VisualEffects.size()); for (int32 visualEffect : questObjective.VisualEffects) - _worldPacket << visualEffect; + _worldPacket << int32(visualEffect); _worldPacket.WriteBits(questObjective.Description.size(), 8); _worldPacket.FlushBits(); @@ -186,15 +186,23 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write() WorldPacket const* WorldPackets::Quest::QuestUpdateAddCredit::Write() { _worldPacket << VictimGUID; - _worldPacket << QuestID; - _worldPacket << ObjectID; - _worldPacket << Count; - _worldPacket << Required; - _worldPacket << ObjectiveType; + _worldPacket << int32(QuestID); + _worldPacket << int32(ObjectID); + _worldPacket << uint16(Count); + _worldPacket << uint16(Required); + _worldPacket << uint8(ObjectiveType); return &_worldPacket; }; +WorldPacket const* WorldPackets::Quest::QuestUpdateAddPvPCredit::Write() +{ + _worldPacket << int32(QuestID); + _worldPacket << uint16(Count); + + return &_worldPacket; +} + ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Quest::QuestRewards const& questRewards) { data << questRewards.ChoiceItemCount; @@ -247,18 +255,18 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Quest::QuestRewards const ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Quest::QuestGiverOfferReward const& offer) { data << offer.QuestGiverGUID; - data << offer.QuestGiverCreatureID; - data << offer.QuestID; - data << offer.QuestFlags[0]; // Flags - data << offer.QuestFlags[1]; // FlagsEx - data << offer.SuggestedPartyMembers; + data << int32(offer.QuestGiverCreatureID); + data << int32(offer.QuestID); + data << int32(offer.QuestFlags[0]); // Flags + data << int32(offer.QuestFlags[1]); // FlagsEx + data << int32(offer.SuggestedPartyMembers); data << offer.Rewards; // WorldPackets::Quest::QuestRewards data << int32(offer.Emotes.size()); for (WorldPackets::Quest::QuestDescEmote const& emote : offer.Emotes) { - data << emote.Type; - data << emote.Delay; + data << int32(emote.Type); + data << uint32(emote.Delay); } data.WriteBit(offer.AutoLaunched); @@ -270,9 +278,9 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Quest::QuestGiverOfferRew WorldPacket const* WorldPackets::Quest::QuestGiverOfferRewardMessage::Write() { _worldPacket << QuestData; // WorldPackets::Quest::QuestGiverOfferReward - _worldPacket << PortraitTurnIn; - _worldPacket << PortraitGiver; - _worldPacket << QuestPackageID; + _worldPacket << int32(PortraitTurnIn); + _worldPacket << int32(PortraitGiver); + _worldPacket << int32(QuestPackageID); _worldPacket.WriteBits(QuestTitle.size(), 9); _worldPacket.WriteBits(RewardText.size(), 12); @@ -301,13 +309,13 @@ void WorldPackets::Quest::QuestGiverChooseReward::Read() WorldPacket const* WorldPackets::Quest::QuestGiverQuestComplete::Write() { - _worldPacket << QuestID; - _worldPacket << SkillLineIDReward; - _worldPacket << MoneyReward; - _worldPacket << NumSkillUpsReward; - _worldPacket << XPReward; - _worldPacket << TalentReward; - _worldPacket << ItemReward; // WorldPackets::Item::ItemInstance + _worldPacket << int32(QuestID); + _worldPacket << int32(SkillLineIDReward); + _worldPacket << int32(MoneyReward); + _worldPacket << int32(NumSkillUpsReward); + _worldPacket << int32(XPReward); + _worldPacket << int32(TalentReward); + _worldPacket << ItemReward; _worldPacket.WriteBit(UseQuestReward); _worldPacket.WriteBit(LaunchGossip); @@ -327,33 +335,33 @@ WorldPacket const* WorldPackets::Quest::QuestGiverQuestDetails::Write() { _worldPacket << QuestGiverGUID; _worldPacket << InformUnit; - _worldPacket << QuestID; - _worldPacket << QuestPackageID; - _worldPacket << PortraitGiver; - _worldPacket << SuggestedPartyMembers; - _worldPacket << QuestFlags[0]; // Flags - _worldPacket << QuestFlags[1]; // FlagsEx - _worldPacket << PortraitTurnIn; + _worldPacket << int32(QuestID); + _worldPacket << int32(QuestPackageID); + _worldPacket << int32(PortraitGiver); + _worldPacket << int32(SuggestedPartyMembers); + _worldPacket << uint32(QuestFlags[0]); // Flags + _worldPacket << uint32(QuestFlags[1]); // FlagsEx + _worldPacket << int32(PortraitTurnIn); _worldPacket << int32(LearnSpells.size()); _worldPacket << Rewards; // WorldPackets::Quest::QuestRewards _worldPacket << int32(DescEmotes.size()); _worldPacket << int32(Objectives.size()); for (int32 spell : LearnSpells) - _worldPacket << spell; + _worldPacket << int32(spell); for (WorldPackets::Quest::QuestDescEmote const& emote : DescEmotes) { - _worldPacket << emote.Type; - _worldPacket << emote.Delay; + _worldPacket << int32(emote.Type); + _worldPacket << uint32(emote.Delay); } for (WorldPackets::Quest::QuestObjectiveSimple const& obj : Objectives) { - _worldPacket << obj.ID; - _worldPacket << obj.ObjectID; - _worldPacket << obj.Amount; - _worldPacket << obj.Type; + _worldPacket << int32(obj.ID); + _worldPacket << int32(obj.ObjectID); + _worldPacket << int32(obj.Amount); + _worldPacket << uint8(obj.Type); } _worldPacket.WriteBits(QuestTitle.size(), 9); @@ -382,28 +390,28 @@ WorldPacket const* WorldPackets::Quest::QuestGiverQuestDetails::Write() WorldPacket const* WorldPackets::Quest::QuestGiverRequestItems::Write() { _worldPacket << QuestGiverGUID; - _worldPacket << QuestGiverCreatureID; - _worldPacket << QuestID; - _worldPacket << CompEmoteDelay; - _worldPacket << CompEmoteType; - _worldPacket << QuestFlags[0]; - _worldPacket << QuestFlags[1]; - _worldPacket << SuggestPartyMembers; - _worldPacket << MoneyToGet; + _worldPacket << int32(QuestGiverCreatureID); + _worldPacket << int32(QuestID); + _worldPacket << int32(CompEmoteDelay); + _worldPacket << int32(CompEmoteType); + _worldPacket << uint32(QuestFlags[0]); + _worldPacket << uint32(QuestFlags[1]); + _worldPacket << int32(SuggestPartyMembers); + _worldPacket << int32(MoneyToGet); _worldPacket << int32(Collect.size()); _worldPacket << int32(Currency.size()); - _worldPacket << StatusFlags; + _worldPacket << int32(StatusFlags); for (QuestObjectiveCollect const& obj : Collect) { - _worldPacket << obj.ObjectID; - _worldPacket << obj.Amount; + _worldPacket << int32(obj.ObjectID); + _worldPacket << int32(obj.Amount); } for (QuestCurrency const& cur : Currency) { - _worldPacket << cur.CurrencyID; - _worldPacket << cur.Amount; + _worldPacket << int32(cur.CurrencyID); + _worldPacket << int32(cur.Amount); } _worldPacket.WriteBit(AutoLaunched); @@ -447,16 +455,16 @@ void WorldPackets::Quest::QuestLogRemoveQuest::Read() WorldPacket const* WorldPackets::Quest::QuestGiverQuestList::Write() { _worldPacket << QuestGiverGUID; - _worldPacket << GreetEmoteDelay; - _worldPacket << GreetEmoteType; + _worldPacket << uint32(GreetEmoteDelay); + _worldPacket << uint32(GreetEmoteType); _worldPacket << uint32(GossipTexts.size()); for (GossipTextData const& gossip : GossipTexts) { - _worldPacket << gossip.QuestID; - _worldPacket << gossip.QuestType; - _worldPacket << gossip.QuestLevel; - _worldPacket << gossip.QuestFlags; - _worldPacket << gossip.QuestFlagsEx; + _worldPacket << uint32(gossip.QuestID); + _worldPacket << uint32(gossip.QuestType); + _worldPacket << uint32(gossip.QuestLevel); + _worldPacket << uint32(gossip.QuestFlags); + _worldPacket << uint32(gossip.QuestFlagsEx); _worldPacket.WriteBit(gossip.Repeatable); _worldPacket.WriteBits(gossip.QuestTitle.size(), 9); _worldPacket.FlushBits(); @@ -512,7 +520,7 @@ void WorldPackets::Quest::QuestPushResult::Read() WorldPacket const* WorldPackets::Quest::QuestGiverInvalidQuest::Write() { - _worldPacket << Reason; + _worldPacket << uint32(Reason); _worldPacket.WriteBit(SendErrorMessage); _worldPacket.WriteBits(ReasonText.length(), 9); @@ -526,15 +534,15 @@ WorldPacket const* WorldPackets::Quest::QuestGiverInvalidQuest::Write() WorldPacket const* WorldPackets::Quest::QuestUpdateFailedTimer::Write() { - _worldPacket << QuestID; + _worldPacket << uint32(QuestID); return &_worldPacket; } WorldPacket const* WorldPackets::Quest::QuestGiverQuestFailed::Write() { - _worldPacket << QuestID; - _worldPacket << Reason; + _worldPacket << uint32(QuestID); + _worldPacket << uint32(Reason); return &_worldPacket; } diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h index c2a54bb8ddc..b321b4076a5 100644 --- a/src/server/game/Server/Packets/QuestPackets.h +++ b/src/server/game/Server/Packets/QuestPackets.h @@ -194,6 +194,17 @@ namespace WorldPackets uint8 ObjectiveType = 0; }; + class QuestUpdateAddPvPCredit final : public ServerPacket + { + public: + QuestUpdateAddPvPCredit() : ServerPacket(SMSG_QUEST_UPDATE_ADD_PVP_CREDIT, 4 + 2) { } + + WorldPacket const* Write() override; + + int32 QuestID = 0; + uint16 Count = 0; + }; + struct QuestChoiceItem { int32 ItemID = 0; @@ -288,8 +299,6 @@ namespace WorldPackets int32 QuestID = 0; int32 TalentReward = 0; bool LaunchGossip = 0; - - // Not in JAM struct WorldPackets::Item::ItemInstance ItemReward; }; diff --git a/src/server/game/Server/Packets/ScenePackets.h b/src/server/game/Server/Packets/ScenePackets.h index 02fca2d5fe9..df6a1f0957e 100644 --- a/src/server/game/Server/Packets/ScenePackets.h +++ b/src/server/game/Server/Packets/ScenePackets.h @@ -25,7 +25,7 @@ namespace WorldPackets { namespace Scenes { - class PlayScene final : public ServerPacket + class TC_GAME_API PlayScene final : public ServerPacket { public: PlayScene() : ServerPacket(SMSG_PLAY_SCENE, 34) { } diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index 5c800497039..aa78cae6deb 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -813,7 +813,7 @@ WorldPacket const* WorldPackets::Spells::NotifyMissileTrajectoryCollision::Write _worldPacket << Caster; _worldPacket << uint8(CastID); _worldPacket << CollisionPos; - + return &_worldPacket; } @@ -844,3 +844,15 @@ WorldPacket const* WorldPackets::Spells::SpellDelayed::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Spells::DispelFailed::Write() +{ + _worldPacket << CasterGUID; + _worldPacket << VictimGUID; + _worldPacket << uint32(SpellID); + _worldPacket << uint32(FailedSpells.size()); + if (!FailedSpells.empty()) + _worldPacket.append(FailedSpells.data(), FailedSpells.size()); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index 18194255316..b1cb39251de 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -419,7 +419,7 @@ namespace WorldPackets uint8 CastID = 0; }; - class CastFailed final : public ServerPacket + class TC_GAME_API CastFailed final : public ServerPacket { public: CastFailed(OpcodeServer opcode) : ServerPacket(opcode, 4+4+4+4+1) { } @@ -445,7 +445,7 @@ namespace WorldPackets std::vector<SpellModifierData> ModifierData; }; - class SetSpellModifier final : public ServerPacket + class TC_GAME_API SetSpellModifier final : public ServerPacket { public: SetSpellModifier(OpcodeServer opcode) : ServerPacket(opcode, 20) { } @@ -830,7 +830,7 @@ namespace WorldPackets { public: MissileTrajectoryCollision(WorldPacket&& packet) : ClientPacket(CMSG_MISSILE_TRAJECTORY_COLLISION, std::move(packet)) { } - + void Read() override; ObjectGuid Target; @@ -839,7 +839,7 @@ namespace WorldPackets G3D::Vector3 CollisionPos; }; - class NotifyMissileTrajectoryCollision : public ServerPacket + class NotifyMissileTrajectoryCollision final : public ServerPacket { public: NotifyMissileTrajectoryCollision() : ServerPacket(SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION, 8 + 1 + 12) { } @@ -855,7 +855,7 @@ namespace WorldPackets { public: UpdateMissileTrajectory(WorldPacket&& packet) : ClientPacket(CMSG_UPDATE_MISSILE_TRAJECTORY, std::move(packet)) { } - + void Read() override; ObjectGuid Guid; @@ -868,7 +868,7 @@ namespace WorldPackets Optional<MovementInfo> Status; }; - class SpellDelayed : public ServerPacket + class SpellDelayed final : public ServerPacket { public: SpellDelayed() : ServerPacket(SMSG_SPELL_DELAYED, sizeof(ObjectGuid) + 4) { } @@ -878,6 +878,19 @@ namespace WorldPackets ObjectGuid Caster; int32 ActualDelay = 0; }; + + class DispelFailed final : public ServerPacket + { + public: + DispelFailed() : ServerPacket(SMSG_DISPEL_FAILED, 16 + 16 + 4 + 4 + 4 /* predict a single failure on average */) { } + + WorldPacket const* Write() override; + + ObjectGuid CasterGUID; + ObjectGuid VictimGUID; + uint32 SpellID = 0; + std::vector<int32> FailedSpells; + }; } } diff --git a/src/server/game/Server/Packets/TicketPackets.cpp b/src/server/game/Server/Packets/TicketPackets.cpp index 1e9eb14e3ea..8048fecb597 100644 --- a/src/server/game/Server/Packets/TicketPackets.cpp +++ b/src/server/game/Server/Packets/TicketPackets.cpp @@ -53,6 +53,9 @@ WorldPacket const* WorldPackets::Ticket::GMTicketCaseStatus::Write() _worldPacket.WriteBits(c.Url.size(), 11); _worldPacket.WriteBits(c.WaitTimeOverrideMessage.size(), 10); + + _worldPacket.WriteString(c.Url); + _worldPacket.WriteString(c.WaitTimeOverrideMessage); } _worldPacket.FlushBits(); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index e8f924ced63..19aff2468a9 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -159,6 +159,8 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Battleground::BattlemasterJoinArena, &WorldSession::HandleBattlemasterJoinArena); DEFINE_HANDLER(CMSG_BATTLEMASTER_JOIN_SKIRMISH, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLENET_CHALLENGE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_BATTLENET_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_BATTLENET_REQUEST_REALM_LIST_TICKET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLE_PAY_ACK_FAILED_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLE_PAY_CONFIRM_PURCHASE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLE_PAY_DISTRIBUTION_ASSIGN_TO_TARGET, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -365,8 +367,8 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_GET_TROPHY_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GET_UNDELETE_CHARACTER_COOLDOWN_STATUS, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::GetUndeleteCharacterCooldownStatus, &WorldSession::HandleGetUndeleteCooldownStatus); DEFINE_HANDLER(CMSG_GM_TICKET_ACKNOWLEDGE_SURVEY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GM_TICKET_GET_CASE_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Ticket::GMTicketGetCaseStatus, &WorldSession::HandleGMTicketGetCaseStatusOpcode); - DEFINE_HANDLER(CMSG_GM_TICKET_GET_SYSTEM_STATUS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Ticket::GMTicketGetSystemStatus, &WorldSession::HandleGMTicketSystemStatusOpcode); + DEFINE_HANDLER(CMSG_GM_TICKET_GET_CASE_STATUS, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Ticket::GMTicketGetCaseStatus, &WorldSession::HandleGMTicketGetCaseStatusOpcode); + DEFINE_HANDLER(CMSG_GM_TICKET_GET_SYSTEM_STATUS, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Ticket::GMTicketGetSystemStatus, &WorldSession::HandleGMTicketSystemStatusOpcode); DEFINE_HANDLER(CMSG_GOSSIP_SELECT_OPTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::GossipSelectOption, &WorldSession::HandleGossipSelectOptionOpcode); DEFINE_HANDLER(CMSG_GRANT_LEVEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::RaF::GrantLevel, &WorldSession::HandleGrantLevel); DEFINE_HANDLER(CMSG_GUILD_ADD_BATTLENET_FRIEND, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -430,7 +432,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_KEYBOUND_OVERRIDE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_LEARN_PET_SPECIALIZATION_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_LEARN_TALENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Talent::LearnTalents, &WorldSession::HandleLearnTalentsOpcode); - DEFINE_HANDLER(CMSG_LEAVE_GROUP, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::LeaveGroup, &WorldSession::HandleLeaveGroupOpcode); + DEFINE_HANDLER(CMSG_LEAVE_GROUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::LeaveGroup, &WorldSession::HandleLeaveGroupOpcode); DEFINE_HANDLER(CMSG_LEAVE_PET_BATTLE_QUEUE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_LFG_LIST_APPLY_TO_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_LFG_LIST_CANCEL_APPLICATION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -667,7 +669,6 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SEND_CONTACT_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Social::SendContactList, &WorldSession::HandleContactListOpcode); DEFINE_HANDLER(CMSG_SEND_MAIL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::SendMail, &WorldSession::HandleSendMail); DEFINE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_ADDRESS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SEND_TEXT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::CTextEmote, &WorldSession::HandleTextEmoteOpcode); DEFINE_HANDLER(CMSG_SET_ACHIEVEMENTS_HIDDEN, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SET_ACTION_BAR_TOGGLES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetActionBarToggles, &WorldSession::HandleSetActionBarToggles); @@ -848,6 +849,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AVAILABLE_VOICE_CHANNEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BAN_REASON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BARBER_SHOP_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEFIELD_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEFIELD_PORT_DENIED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -865,6 +867,10 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_POINTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_CHALLENGE_ABORT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_CHALLENGE_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_REALM_LIST_TICKET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_SET_SESSION_STATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_ACK_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_CONFIRM_PURCHASE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_DELIVERY_ENDED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -977,7 +983,6 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_SERVER_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHEAT_IGNORE_DIMISHING_RETURNS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHECK_WARGAME_ENTRY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHUNKED_PACKET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_ALL_SPELL_CHARGES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_BOSS_EMOTES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1023,7 +1028,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISENCHANT_CREDIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPEL_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPEL_FAILED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPLAY_GAME_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPLAY_PLAYER_CHOICE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPLAY_PROMOTION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1053,7 +1058,6 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEIGN_DEATH_RESISTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_FINAL_CHUNK, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FISH_ESCAPED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FISH_NOT_HOOKED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FLIGHT_SPLINE_SYNC, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1123,7 +1127,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_REQUEST_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_TICKET_CASE_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_TICKET_CASE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_TICKET_SYSTEM_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GOD_MODE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GOSSIP_COMPLETE, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1491,8 +1495,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_POI_QUERY_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_PUSH_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_CREDIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_PVP_CREDIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_PVP_CREDIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_COMPLETE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_FAILED_TIMER, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1509,7 +1513,6 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_RESULT_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_RESULT_OK, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_QUERY_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_SPLIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RECRUIT_A_FRIEND_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_EXPIRED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_NEVER, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 138cb7c1dd5..6dd830fd310 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -37,7 +37,7 @@ enum ConnectionType enum OpcodeMisc : uint32 { - MAX_OPCODE = 0x1FFF, + MAX_OPCODE = 0x3FFF, NUM_OPCODE_HANDLERS = (MAX_OPCODE + 1), UNKNOWN_OPCODE = (0xFFFF + 1), NULL_OPCODE = 0xBADD @@ -45,1604 +45,1607 @@ enum OpcodeMisc : uint32 enum OpcodeClient : uint32 { - CMSG_ACCEPT_GUILD_INVITE = 0x00BF, - CMSG_ACCEPT_LEVEL_GRANT = 0x0731, - CMSG_ACCEPT_TRADE = 0x00FD, - CMSG_ACCEPT_WARGAME_INVITE = 0x117F, - CMSG_ACTIVATE_TAXI = 0x037A, - CMSG_ADDON_LIST = 0x0540, - CMSG_ADD_BATTLENET_FRIEND = 0x0140, - CMSG_ADD_FRIEND = 0x046B, - CMSG_ADD_IGNORE = 0x04A7, - CMSG_ADD_TOY = 0x05E1, - CMSG_ALTER_APPEARANCE = 0x152D, - CMSG_AREA_SPIRIT_HEALER_QUERY = 0x1DAA, - CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x0675, - CMSG_AREA_TRIGGER = 0x043D, - CMSG_ATTACK_STOP = 0x0DA6, - CMSG_ATTACK_SWING = 0x0C2A, - CMSG_AUCTION_HELLO_REQUEST = 0x1D0E, - CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x150D, - CMSG_AUCTION_LIST_ITEMS = 0x118D, - CMSG_AUCTION_LIST_OWNER_ITEMS = 0x15AE, - CMSG_AUCTION_LIST_PENDING_SALES = 0x0256, - CMSG_AUCTION_PLACE_BID = 0x0811, - CMSG_AUCTION_REMOVE_ITEM = 0x0659, - CMSG_AUCTION_REPLICATE_ITEMS = 0x15AA, - CMSG_AUCTION_SELL_ITEM = 0x005D, - CMSG_AUTH_CONTINUED_SESSION = 0x0C33, - CMSG_AUTH_SESSION = 0x0977, - CMSG_AUTOBANK_ITEM = 0x121E, - CMSG_AUTOBANK_REAGENT = 0x127E, - CMSG_AUTOSTORE_BANK_ITEM = 0x1312, - CMSG_AUTOSTORE_BANK_REAGENT = 0x1635, - CMSG_AUTO_EQUIP_ITEM = 0x1375, - CMSG_AUTO_EQUIP_ITEM_SLOT = 0x1239, - CMSG_AUTO_STORE_BAG_ITEM = 0x161E, - CMSG_BANKER_ACTIVATE = 0x1526, - CMSG_BATTLEFIELD_LEAVE = 0x0429, - CMSG_BATTLEFIELD_LIST = 0x08F9, - CMSG_BATTLEFIELD_PORT = 0x0619, - CMSG_BATTLEMASTER_HELLO = 0x01E1, - CMSG_BATTLEMASTER_JOIN = 0x0A71, - CMSG_BATTLEMASTER_JOIN_ARENA = 0x0A16, - CMSG_BATTLEMASTER_JOIN_SKIRMISH = 0x1DA9, - CMSG_BATTLENET_CHALLENGE_RESPONSE = 0x113C, - CMSG_BATTLE_PAY_ACK_FAILED_RESPONSE = 0x00B4, - CMSG_BATTLE_PAY_CONFIRM_PURCHASE_RESPONSE = 0x1424, - CMSG_BATTLE_PAY_DISTRIBUTION_ASSIGN_TO_TARGET = 0x1168, - CMSG_BATTLE_PAY_GET_PRODUCT_LIST = 0x00F0, - CMSG_BATTLE_PAY_GET_PURCHASE_LIST = 0x05E8, - CMSG_BATTLE_PAY_START_PURCHASE = 0x0430, - CMSG_BATTLE_PAY_START_VAS_PURCHASE = 0x046C, - CMSG_BATTLE_PET_DELETE_PET = 0x0168, - CMSG_BATTLE_PET_DELETE_PET_CHEAT = 0x0600, - CMSG_BATTLE_PET_MODIFY_NAME = 0x00E3, - CMSG_BATTLE_PET_REQUEST_JOURNAL = 0x0123, - CMSG_BATTLE_PET_REQUEST_JOURNAL_LOCK = 0x116C, - CMSG_BATTLE_PET_SET_BATTLE_SLOT = 0x106C, - CMSG_BATTLE_PET_SET_FLAGS = 0x0538, - CMSG_BATTLE_PET_SUMMON = 0x007B, - CMSG_BATTLE_PET_UPDATE_NOTIFY = 0x1085, - CMSG_BEGIN_TRADE = 0x1022, - CMSG_BF_MGR_ENTRY_INVITE_RESPONSE = 0x04B4, - CMSG_BF_MGR_QUEUE_EXIT_REQUEST = 0x10BF, - CMSG_BF_MGR_QUEUE_INVITE_RESPONSE = 0x00E8, - CMSG_BF_MGR_QUEUE_REQUEST = 0x0846, - CMSG_BINDER_ACTIVATE = 0x073D, - CMSG_BLACK_MARKET_BID_ON_ITEM = 0x031A, - CMSG_BLACK_MARKET_OPEN = 0x021E, - CMSG_BLACK_MARKET_REQUEST_ITEMS = 0x0C59, - CMSG_BUG_REPORT = 0x04EF, - CMSG_BUSY_TRADE = 0x0590, - CMSG_BUY_BACK_ITEM = 0x1906, - CMSG_BUY_BANK_SLOT = 0x0016, - CMSG_BUY_ITEM = 0x158A, - CMSG_BUY_REAGENT_BANK = 0x0636, - CMSG_BUY_WOW_TOKEN_CONFIRM = 0x102C, - CMSG_BUY_WOW_TOKEN_START = 0x003F, - CMSG_CAGE_BATTLE_PET = 0x10A2, - CMSG_CALENDAR_ADD_EVENT = 0x00F8, - CMSG_CALENDAR_COMPLAIN = 0x0180, - CMSG_CALENDAR_COPY_EVENT = 0x01B7, - CMSG_CALENDAR_EVENT_INVITE = 0x0438, - CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x0130, - CMSG_CALENDAR_EVENT_RSVP = 0x1040, - CMSG_CALENDAR_EVENT_SIGN_UP = 0x01A8, - CMSG_CALENDAR_EVENT_STATUS = 0x013C, - CMSG_CALENDAR_GET = 0x0477, - CMSG_CALENDAR_GET_EVENT = 0x01BB, - CMSG_CALENDAR_GET_NUM_PENDING = 0x00A7, - CMSG_CALENDAR_GUILD_FILTER = 0x04A3, - CMSG_CALENDAR_REMOVE_EVENT = 0x00E7, - CMSG_CALENDAR_REMOVE_INVITE = 0x1067, - CMSG_CALENDAR_UPDATE_EVENT = 0x056F, - CMSG_CANCEL_AURA = 0x0CB6, - CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x1185, - CMSG_CANCEL_CAST = 0x0525, - CMSG_CANCEL_CHANNELLING = 0x01F1, - CMSG_CANCEL_GROWTH_AURA = 0x002E, - CMSG_CANCEL_MASTER_LOOT_ROLL = 0x09FD, - CMSG_CANCEL_MOD_SPEED_NO_CONTROL_AURAS = 0x09BE, - CMSG_CANCEL_MOUNT_AURA = 0x0425, - CMSG_CANCEL_QUEUED_SPELL = 0x0935, - CMSG_CANCEL_TEMP_ENCHANTMENT = 0x075D, - CMSG_CANCEL_TRADE = 0x18AE, - CMSG_CAN_DUEL = 0x10EB, - CMSG_CAST_SPELL = 0x00F5, - CMSG_CHALLENGE_MODE_REQUEST_LEADERS = 0x089E, - CMSG_CHALLENGE_MODE_REQUEST_MAP_STATS = 0x00DA, - CMSG_CHANGE_BAG_SLOT_FLAG = 0x0CA2, - CMSG_CHANGE_MONUMENT_APPEARANCE = 0x1086, - CMSG_CHANGE_SUB_GROUP = 0x11B8, - CMSG_CHARACTER_RENAME_REQUEST = 0x05F0, - CMSG_CHAR_CUSTOMIZE = 0x0433, - CMSG_CHAR_DELETE = 0x0428, - CMSG_CHAR_RACE_OR_FACTION_CHANGE = 0x0528, - CMSG_CHAT_ADDON_MESSAGE_CHANNEL = 0x03D6, - CMSG_CHAT_ADDON_MESSAGE_GUILD = 0x03FE, - CMSG_CHAT_ADDON_MESSAGE_INSTANCE_CHAT = 0x17FA, - CMSG_CHAT_ADDON_MESSAGE_OFFICER = 0x16FD, - CMSG_CHAT_ADDON_MESSAGE_PARTY = 0x02BE, - CMSG_CHAT_ADDON_MESSAGE_RAID = 0x07B1, - CMSG_CHAT_ADDON_MESSAGE_WHISPER = 0x16D9, - CMSG_CHAT_CHANNEL_ANNOUNCEMENTS = 0x0BBE, - CMSG_CHAT_CHANNEL_BAN = 0x0FFA, - CMSG_CHAT_CHANNEL_DECLINE_INVITE = 0x0BF5, - CMSG_CHAT_CHANNEL_DISPLAY_LIST = 0x039E, - CMSG_CHAT_CHANNEL_INVITE = 0x07DE, - CMSG_CHAT_CHANNEL_KICK = 0x12B6, - CMSG_CHAT_CHANNEL_LIST = 0x139D, - CMSG_CHAT_CHANNEL_MODERATE = 0x16D1, - CMSG_CHAT_CHANNEL_MODERATOR = 0x13B1, - CMSG_CHAT_CHANNEL_MUTE = 0x1295, - CMSG_CHAT_CHANNEL_OWNER = 0x0EFE, - CMSG_CHAT_CHANNEL_PASSWORD = 0x16B2, - CMSG_CHAT_CHANNEL_SET_OWNER = 0x13D2, - CMSG_CHAT_CHANNEL_SILENCE_ALL = 0x13DE, - CMSG_CHAT_CHANNEL_SILENCE_VOICE = 0x02F1, - CMSG_CHAT_CHANNEL_UNBAN = 0x0FB1, - CMSG_CHAT_CHANNEL_UNMODERATOR = 0x13F1, - CMSG_CHAT_CHANNEL_UNMUTE = 0x03DD, - CMSG_CHAT_CHANNEL_UNSILENCE_ALL = 0x02D2, - CMSG_CHAT_CHANNEL_UNSILENCE_VOICE = 0x0AF9, - CMSG_CHAT_CHANNEL_VOICE_OFF = 0x0EDE, - CMSG_CHAT_CHANNEL_VOICE_ON = 0x1A96, - CMSG_CHAT_JOIN_CHANNEL = 0x0BF6, - CMSG_CHAT_LEAVE_CHANNEL = 0x0BF1, - CMSG_CHAT_MESSAGE_AFK = 0x07BE, - CMSG_CHAT_MESSAGE_CHANNEL = 0x0BB2, - CMSG_CHAT_MESSAGE_DND = 0x13DA, - CMSG_CHAT_MESSAGE_EMOTE = 0x1799, - CMSG_CHAT_MESSAGE_GUILD = 0x13FA, - CMSG_CHAT_MESSAGE_INSTANCE_CHAT = 0x16DD, - CMSG_CHAT_MESSAGE_OFFICER = 0x13B5, - CMSG_CHAT_MESSAGE_PARTY = 0x12F5, - CMSG_CHAT_MESSAGE_RAID = 0x07D2, - CMSG_CHAT_MESSAGE_RAID_WARNING = 0x0EF9, - CMSG_CHAT_MESSAGE_SAY = 0x03BE, - CMSG_CHAT_MESSAGE_WHISPER = 0x13BD, - CMSG_CHAT_MESSAGE_YELL = 0x03BD, - CMSG_CHAT_REGISTER_ADDON_PREFIXES = 0x0692, - CMSG_CHAT_REPORT_FILTERED = 0x07BD, - CMSG_CHAT_REPORT_IGNORED = 0x0EBE, - CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES = 0x03F9, - CMSG_CHECK_RAF_EMAIL_ENABLED = 0x1033, - CMSG_CHECK_WOW_TOKEN_VETERAN_ELIGIBILITY = 0x01BC, - CMSG_CHOICE_RESPONSE = 0x1001, - CMSG_CLEAR_RAID_MARKER = 0x09EE, - CMSG_CLEAR_TRADE_ITEM = 0x087A, - CMSG_CLIENT_PORT_GRAVEYARD = 0x1509, - CMSG_CLOSE_INTERACTION = 0x001D, - CMSG_COMMENTATOR_ENABLE = 0x1167, - CMSG_COMMENTATOR_ENTER_INSTANCE = 0x047B, - CMSG_COMMENTATOR_EXIT_INSTANCE = 0x10F0, - CMSG_COMMENTATOR_GET_MAP_INFO = 0x04C0, - CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x0073, - CMSG_COMMENTATOR_START_WARGAME = 0x05FC, - CMSG_COMPLAINT = 0x0133, - CMSG_COMPLETE_CINEMATIC = 0x023A, - CMSG_COMPLETE_MOVIE = 0x0612, - CMSG_CONFIRM_RESPEC_WIPE = 0x04A2, - CMSG_CONNECT_TO_FAILED = 0x04F8, - CMSG_CONVERT_RAID = 0x11FF, - CMSG_CREATE_CHARACTER = 0x143B, - CMSG_CREATE_SHIPMENT = 0x0575, - CMSG_DB_QUERY_BULK = 0x10E4, - CMSG_DECLINE_GUILD_INVITES = 0x1D0A, - CMSG_DECLINE_PETITION = 0x1D86, - CMSG_DELETE_EQUIPMENT_SET = 0x027A, - CMSG_DEL_FRIEND = 0x117C, - CMSG_DEL_IGNORE = 0x11EB, - CMSG_DEPOSIT_REAGENT_BANK = 0x0C69, - CMSG_DESTROY_ITEM = 0x00F2, - CMSG_DF_BOOT_PLAYER_VOTE = 0x05AC, - CMSG_DF_GET_JOIN_STATUS = 0x11A7, - CMSG_DF_GET_SYSTEM_INFO = 0x1138, - CMSG_DF_JOIN = 0x11F8, - CMSG_DF_LEAVE = 0x0424, - CMSG_DF_PROPOSAL_RESPONSE = 0x11B0, - CMSG_DF_READY_CHECK_RESPONSE = 0x1028, - CMSG_DF_SEARCH_JOIN = 0x11EC, - CMSG_DF_SEARCH_LEAVE = 0x00F4, - CMSG_DF_SET_COMMENT = 0x10B4, - CMSG_DF_SET_ROLES = 0x003B, - CMSG_DF_TELEPORT = 0x00A8, - CMSG_DISCARDED_TIME_SYNC_ACKS = 0x111A, - CMSG_DISMISS_CRITTER = 0x0A1D, - CMSG_DO_MASTER_LOOT_ROLL = 0x0036, - CMSG_DO_READY_CHECK = 0x012B, - CMSG_DUEL_RESPONSE = 0x19A6, - CMSG_EJECT_PASSENGER = 0x0D65, - CMSG_EMOTE = 0x077E, - CMSG_ENABLE_NAGLE = 0x0827, - CMSG_ENABLE_TAXI_NODE = 0x190D, - CMSG_ENGINE_SURVEY = 0x0534, - CMSG_ENUM_CHARACTERS = 0x1163, - CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT = 0x043B, - CMSG_FAR_SIGHT = 0x025A, - CMSG_GAME_OBJ_REPORT_USE = 0x1101, - CMSG_GAME_OBJ_USE = 0x0359, - CMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING = 0x0583, - CMSG_GARRISON_CANCEL_CONSTRUCTION = 0x01AE, - CMSG_GARRISON_CHECK_UPGRADEABLE = 0x08ED, - CMSG_GARRISON_COMPLETE_MISSION = 0x0D4D, - CMSG_GARRISON_GENERATE_RECRUITS = 0x016E, - CMSG_GARRISON_GET_BUILDING_LANDMARKS = 0x0175, - CMSG_GARRISON_MISSION_BONUS_ROLL = 0x0125, - CMSG_GARRISON_PURCHASE_BUILDING = 0x047E, - CMSG_GARRISON_RECRUIT_FOLLOWER = 0x0588, - CMSG_GARRISON_REMOVE_FOLLOWER = 0x0136, - CMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING = 0x100A, - CMSG_GARRISON_RENAME_FOLLOWER = 0x0472, - CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA = 0x1CA6, - CMSG_GARRISON_REQUEST_LANDING_PAGE_SHIPMENT_INFO = 0x18AA, - CMSG_GARRISON_REQUEST_SHIPMENT_INFO = 0x00EA, - CMSG_GARRISON_SET_BUILDING_ACTIVE = 0x0417, - CMSG_GARRISON_SET_FOLLOWER_FAVORITE = 0x0822, - CMSG_GARRISON_SET_FOLLOWER_INACTIVE = 0x08B0, - CMSG_GARRISON_SET_RECRUITMENT_PREFERENCES = 0x013E, - CMSG_GARRISON_START_MISSION = 0x087E, - CMSG_GARRISON_SWAP_BUILDINGS = 0x1CAE, - CMSG_GENERATE_RANDOM_CHARACTER_NAME = 0x0580, - CMSG_GET_CHALLENGE_MODE_REWARDS = 0x04D6, - CMSG_GET_GARRISON_INFO = 0x0414, - CMSG_GET_ITEM_PURCHASE_DATA = 0x1DA1, - CMSG_GET_MIRROR_IMAGE_DATA = 0x0461, - CMSG_GET_PVP_OPTIONS_ENABLED = 0x1038, - CMSG_GET_REMAINING_GAME_TIME = 0x04A8, - CMSG_GET_TROPHY_LIST = 0x093A, - CMSG_GET_UNDELETE_CHARACTER_COOLDOWN_STATUS = 0x017C, - CMSG_GM_TICKET_ACKNOWLEDGE_SURVEY = 0x10E8, - CMSG_GM_TICKET_GET_CASE_STATUS = 0x01F4, - CMSG_GM_TICKET_GET_SYSTEM_STATUS = 0x0200, - CMSG_GOSSIP_SELECT_OPTION = 0x0A59, - CMSG_GRANT_LEVEL = 0x0459, - CMSG_GUILD_ADD_BATTLENET_FRIEND = 0x08D2, - CMSG_GUILD_ADD_RANK = 0x048D, - CMSG_GUILD_ASSIGN_MEMBER_RANK = 0x09C2, - CMSG_GUILD_AUTO_DECLINE_INVITATION = 0x00C5, - CMSG_GUILD_BANK_ACTIVATE = 0x0311, - CMSG_GUILD_BANK_BUY_TAB = 0x0C11, - CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x0051, - CMSG_GUILD_BANK_LOG_QUERY = 0x0C82, - CMSG_GUILD_BANK_QUERY_TAB = 0x0252, - CMSG_GUILD_BANK_REMAINING_WITHDRAW_MONEY_QUERY = 0x05CE, - CMSG_GUILD_BANK_SET_TAB_TEXT = 0x01C5, - CMSG_GUILD_BANK_SWAP_ITEMS = 0x1522, - CMSG_GUILD_BANK_TEXT_QUERY = 0x048E, - CMSG_GUILD_BANK_UPDATE_TAB = 0x112E, - CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x0855, - CMSG_GUILD_CHALLENGE_UPDATE_REQUEST = 0x0592, - CMSG_GUILD_CHANGE_NAME_REQUEST = 0x0991, - CMSG_GUILD_DECLINE_INVITATION = 0x019D, - CMSG_GUILD_DELETE = 0x0589, - CMSG_GUILD_DELETE_RANK = 0x04C1, - CMSG_GUILD_DEMOTE_MEMBER = 0x0C86, - CMSG_GUILD_EVENT_LOG_QUERY = 0x0896, - CMSG_GUILD_GET_ACHIEVEMENT_MEMBERS = 0x04D5, - CMSG_GUILD_GET_RANKS = 0x0195, - CMSG_GUILD_GET_ROSTER = 0x04D2, - CMSG_GUILD_INVITE_BY_NAME = 0x1440, - CMSG_GUILD_LEAVE = 0x09CE, - CMSG_GUILD_MEMBER_SEND_SOR_REQUEST = 0x01DE, - CMSG_GUILD_NEWS_UPDATE_STICKY = 0x0C8A, - CMSG_GUILD_OFFICER_REMOVE_MEMBER = 0x0889, - CMSG_GUILD_PERMISSIONS_QUERY = 0x018D, - CMSG_GUILD_PROMOTE_MEMBER = 0x01C1, - CMSG_GUILD_QUERY_MEMBERS_FOR_RECIPE = 0x08D5, - CMSG_GUILD_QUERY_MEMBER_RECIPES = 0x088E, - CMSG_GUILD_QUERY_NEWS = 0x09C6, - CMSG_GUILD_QUERY_RECIPES = 0x019A, - CMSG_GUILD_REPLACE_GUILD_MASTER = 0x05CA, - CMSG_GUILD_SET_ACHIEVEMENT_TRACKING = 0x04CD, - CMSG_GUILD_SET_FOCUSED_ACHIEVEMENT = 0x08CE, - CMSG_GUILD_SET_GUILD_MASTER = 0x0034, - CMSG_GUILD_SET_MEMBER_NOTE = 0x0586, - CMSG_GUILD_SET_RANK_PERMISSIONS = 0x058A, - CMSG_GUILD_SHIFT_RANK = 0x0881, - CMSG_GUILD_UPDATE_INFO_TEXT = 0x0882, - CMSG_GUILD_UPDATE_MOTD_TEXT = 0x01CE, - CMSG_HEARTH_AND_RESURRECT = 0x065E, - CMSG_IGNORE_TRADE = 0x083C, - CMSG_INCREASE_CAST_TIME_FOR_SPELL = 0x0D39, - CMSG_INITIATE_ROLE_POLL = 0x0124, - CMSG_INITIATE_TRADE = 0x041F, - CMSG_INSPECT = 0x0371, - CMSG_INSPECT_PVP = 0x1024, - CMSG_INSTANCE_LOCK_RESPONSE = 0x1909, - CMSG_ITEM_PURCHASE_REFUND = 0x0C1A, - CMSG_ITEM_TEXT_QUERY = 0x08BA, - CMSG_JOIN_PET_BATTLE_QUEUE = 0x140D, - CMSG_JOIN_RATED_BATTLEGROUND = 0x053A, - CMSG_KEEP_ALIVE = 0x1434, - CMSG_KEYBOUND_OVERRIDE = 0x0431, - CMSG_LEARN_PET_SPECIALIZATION_GROUP = 0x04B1, - CMSG_LEARN_TALENTS = 0x0497, - CMSG_LEAVE_GROUP = 0x01A7, - CMSG_LEAVE_PET_BATTLE_QUEUE = 0x04F6, - CMSG_LFG_LIST_APPLY_TO_GROUP = 0x04F4, - CMSG_LFG_LIST_CANCEL_APPLICATION = 0x05A7, - CMSG_LFG_LIST_DECLINE_APPLICANT = 0x0470, - CMSG_LFG_LIST_GET_STATUS = 0x10E3, - CMSG_LFG_LIST_INVITE_APPLICANT = 0x046F, - CMSG_LFG_LIST_INVITE_RESPONSE = 0x053F, - CMSG_LFG_LIST_JOIN = 0x10A3, - CMSG_LFG_LIST_LEAVE = 0x00F3, - CMSG_LFG_LIST_SEARCH = 0x0473, - CMSG_LFG_LIST_UPDATE_REQUEST = 0x0167, - CMSG_LF_GUILD_ADD_RECRUIT = 0x11F7, - CMSG_LF_GUILD_BROWSE = 0x11EF, - CMSG_LF_GUILD_DECLINE_RECRUIT = 0x05C9, - CMSG_LF_GUILD_GET_APPLICATIONS = 0x0181, - CMSG_LF_GUILD_GET_GUILD_POST = 0x049D, - CMSG_LF_GUILD_GET_RECRUITS = 0x08DE, - CMSG_LF_GUILD_REMOVE_RECRUIT = 0x0189, - CMSG_LF_GUILD_SET_GUILD_POST = 0x11B4, - CMSG_LIST_INVENTORY = 0x0A55, - CMSG_LOADING_SCREEN_NOTIFY = 0x1428, - CMSG_LOAD_SELECTED_TROPHY = 0x0D2E, - CMSG_LOGOUT_CANCEL = 0x0632, - CMSG_LOGOUT_INSTANT = 0x0411, - CMSG_LOGOUT_REQUEST = 0x1126, - CMSG_LOG_DISCONNECT = 0x0C67, - CMSG_LOG_STREAMING_ERROR = 0x0838, - CMSG_LOOT_ITEM = 0x0936, - CMSG_LOOT_MONEY = 0x0025, - CMSG_LOOT_RELEASE = 0x0922, - CMSG_LOOT_ROLL = 0x08AD, - CMSG_LOOT_UNIT = 0x096E, - CMSG_LOW_LEVEL_RAID1 = 0x1170, - CMSG_LOW_LEVEL_RAID2 = 0x0351, - CMSG_MAIL_CREATE_TEXT_ITEM = 0x19A9, - CMSG_MAIL_DELETE = 0x0876, - CMSG_MAIL_GET_LIST = 0x0859, - CMSG_MAIL_MARK_AS_READ = 0x0A1A, - CMSG_MAIL_RETURN_TO_SENDER = 0x10C0, - CMSG_MAIL_TAKE_ITEM = 0x0715, - CMSG_MAIL_TAKE_MONEY = 0x0379, - CMSG_MASTER_LOOT_ITEM = 0x04FA, - CMSG_MINIMAP_PING = 0x1173, - CMSG_MISSILE_TRAJECTORY_COLLISION = 0x0C0D, - CMSG_MOUNT_SET_FAVORITE = 0x142C, - CMSG_MOUNT_SPECIAL_ANIM = 0x04F5, - CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK = 0x1195, - CMSG_MOVE_CHANGE_TRANSPORT = 0x1412, - CMSG_MOVE_CHANGE_VEHICLE_SEATS = 0x1032, - CMSG_MOVE_CHARM_TELEPORT_CHEAT = 0x1996, - CMSG_MOVE_DISMISS_VEHICLE = 0x111E, - CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK = 0x1C11, - CMSG_MOVE_FALL_LAND = 0x149D, - CMSG_MOVE_FALL_RESET = 0x10B6, - CMSG_MOVE_FEATHER_FALL_ACK = 0x11BE, - CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x103D, - CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x1431, - CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK = 0x10B2, - CMSG_MOVE_FORCE_ROOT_ACK = 0x1036, - CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x1832, - CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK = 0x1436, - CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x14B6, - CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK = 0x1931, - CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK = 0x1112, - CMSG_MOVE_FORCE_UNROOT_ACK = 0x1939, - CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK = 0x15BE, - CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x143E, - CMSG_MOVE_GRAVITY_ENABLE_ACK = 0x1511, - CMSG_MOVE_HEARTBEAT = 0x1512, - CMSG_MOVE_HOVER_ACK = 0x111D, - CMSG_MOVE_JUMP = 0x199E, - CMSG_MOVE_KNOCK_BACK_ACK = 0x159E, - CMSG_MOVE_REMOVE_MOVEMENT_FORCES = 0x159A, - CMSG_MOVE_REMOVE_MOVEMENT_FORCE_ACK = 0x141E, - CMSG_MOVE_SET_CAN_FLY_ACK = 0x1411, - CMSG_MOVE_SET_CAN_TURN_WHILE_FALLING_ACK = 0x181D, - CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0x11B2, - CMSG_MOVE_SET_FACING = 0x1119, - CMSG_MOVE_SET_FLY = 0x1531, - CMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES_ACK = 0x11B6, - CMSG_MOVE_SET_PITCH = 0x1532, - CMSG_MOVE_SET_RELATIVE_POSITION = 0x1135, - CMSG_MOVE_SET_RUN_MODE = 0x181E, - CMSG_MOVE_SET_VEHICLE_REC_ID_ACK = 0x1836, - CMSG_MOVE_SET_WALK_MODE = 0x113A, - CMSG_MOVE_SPLINE_DONE = 0x1991, - CMSG_MOVE_START_ASCEND = 0x1515, - CMSG_MOVE_START_BACKWARD = 0x1191, - CMSG_MOVE_START_DESCEND = 0x1419, - CMSG_MOVE_START_FORWARD = 0x1196, - CMSG_MOVE_START_PITCH_DOWN = 0x151A, - CMSG_MOVE_START_PITCH_UP = 0x1811, - CMSG_MOVE_START_STRAFE_LEFT = 0x1992, - CMSG_MOVE_START_STRAFE_RIGHT = 0x113D, - CMSG_MOVE_START_SWIM = 0x189E, - CMSG_MOVE_START_TURN_LEFT = 0x1819, - CMSG_MOVE_START_TURN_RIGHT = 0x141D, - CMSG_MOVE_STOP = 0x1C16, - CMSG_MOVE_STOP_ASCEND = 0x1912, - CMSG_MOVE_STOP_PITCH = 0x1519, - CMSG_MOVE_STOP_STRAFE = 0x1095, - CMSG_MOVE_STOP_SWIM = 0x14B5, - CMSG_MOVE_STOP_TURN = 0x1491, - CMSG_MOVE_TELEPORT_ACK = 0x1C1A, - CMSG_MOVE_TELEPORT_CHEAT = 0x18B5, - CMSG_MOVE_TIME_SKIPPED = 0x18B9, - CMSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x1111, - CMSG_MOVE_WATER_WALK_ACK = 0x18B2, - CMSG_NEUTRAL_PLAYER_SELECT_FACTION = 0x092E, - CMSG_NEXT_CINEMATIC_CAMERA = 0x0C51, - CMSG_OBJECT_UPDATE_FAILED = 0x01A9, - CMSG_OBJECT_UPDATE_RESCUED = 0x059F, - CMSG_OFFER_PETITION = 0x053B, - CMSG_OPENING_CINEMATIC = 0x0655, - CMSG_OPEN_ITEM = 0x042D, - CMSG_OPEN_MISSION_NPC = 0x08B1, - CMSG_OPEN_SHIPMENT_NPC = 0x09B1, - CMSG_OPEN_TRADESKILL_NPC = 0x092D, - CMSG_OPT_OUT_OF_LOOT = 0x065A, - CMSG_PARTY_INVITE = 0x11FC, - CMSG_PARTY_INVITE_RESPONSE = 0x057B, - CMSG_PARTY_UNINVITE = 0x05FF, - CMSG_PETITION_BUY = 0x150E, - CMSG_PETITION_RENAME_GUILD = 0x1133, - CMSG_PETITION_SHOW_LIST = 0x0779, - CMSG_PETITION_SHOW_SIGNATURES = 0x1521, - CMSG_PET_ABANDON = 0x1129, - CMSG_PET_ACTION = 0x0312, - CMSG_PET_BATTLE_FINAL_NOTIFY = 0x1025, - CMSG_PET_BATTLE_INPUT = 0x01FC, - CMSG_PET_BATTLE_QUEUE_PROPOSE_MATCH_RESULT = 0x1C02, - CMSG_PET_BATTLE_QUIT_NOTIFY = 0x1029, - CMSG_PET_BATTLE_REPLACE_FRONT_PET = 0x1137, - CMSG_PET_BATTLE_REQUEST_PVP = 0x1422, - CMSG_PET_BATTLE_REQUEST_UPDATE = 0x0CBE, - CMSG_PET_BATTLE_REQUEST_WILD = 0x05AE, - CMSG_PET_BATTLE_SCRIPT_ERROR_NOTIFY = 0x0488, - CMSG_PET_CANCEL_AURA = 0x0019, - CMSG_PET_CAST_SPELL = 0x1089, - CMSG_PET_RENAME = 0x05F7, - CMSG_PET_SET_ACTION = 0x0355, - CMSG_PET_SPELL_AUTOCAST = 0x045D, - CMSG_PET_STOP_ATTACK = 0x0271, - CMSG_PING = 0x0828, - CMSG_PLAYER_LOGIN = 0x10F3, - CMSG_PROTOCOL_MISMATCH = 0x0CE7, - CMSG_PUSH_QUEST_TO_PARTY = 0x110A, - CMSG_PVP_LOG_DATA = 0x0075, - CMSG_QUERY_BATTLE_PET_NAME = 0x0CE1, - CMSG_QUERY_CORPSE_LOCATION_FROM_CLIENT = 0x0074, - CMSG_QUERY_CORPSE_TRANSPORT = 0x1124, - CMSG_QUERY_COUNTDOWN_TIMER = 0x08F2, - CMSG_QUERY_CREATURE = 0x1002, - CMSG_QUERY_GAME_OBJECT = 0x182D, - CMSG_QUERY_GARRISON_CREATURE_NAME = 0x090E, - CMSG_QUERY_GUILD_INFO = 0x00BC, - CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x1921, - CMSG_QUERY_NEXT_MAIL_TIME = 0x1189, - CMSG_QUERY_NPC_TEXT = 0x04E2, - CMSG_QUERY_PAGE_TEXT = 0x0C21, - CMSG_QUERY_PETITION = 0x050A, - CMSG_QUERY_PET_NAME = 0x0569, - CMSG_QUERY_PLAYER_NAME = 0x01A4, - CMSG_QUERY_QUEST_COMPLETION_NPCS = 0x04E9, - CMSG_QUERY_QUEST_INFO = 0x08BD, - CMSG_QUERY_REALM_NAME = 0x016C, - CMSG_QUERY_SCENARIO_POI = 0x01E7, - CMSG_QUERY_TIME = 0x0A32, - CMSG_QUERY_VOID_STORAGE = 0x08E5, - CMSG_QUEST_CONFIRM_ACCEPT = 0x0C16, - CMSG_QUEST_GIVER_ACCEPT_QUEST = 0x005E, - CMSG_QUEST_GIVER_CHOOSE_REWARD = 0x037E, - CMSG_QUEST_GIVER_COMPLETE_QUEST = 0x0775, - CMSG_QUEST_GIVER_HELLO = 0x035A, - CMSG_QUEST_GIVER_QUERY_QUEST = 0x198A, - CMSG_QUEST_GIVER_REQUEST_REWARD = 0x118A, - CMSG_QUEST_GIVER_STATUS_MULTIPLE_QUERY = 0x061E, - CMSG_QUEST_GIVER_STATUS_QUERY = 0x001A, - CMSG_QUEST_LOG_REMOVE_QUEST = 0x033E, - CMSG_QUEST_POI_QUERY = 0x04AF, - CMSG_QUEST_PUSH_RESULT = 0x0415, - CMSG_QUEUED_MESSAGES_END = 0x0878, - CMSG_RANDOM_ROLL = 0x10BC, - CMSG_READY_CHECK_RESPONSE = 0x1078, - CMSG_READ_ITEM = 0x0071, - CMSG_RECLAIM_CORPSE = 0x0275, - CMSG_RECRUIT_A_FRIEND = 0x04EC, - CMSG_REDEEM_WOW_TOKEN_CONFIRM = 0x04AC, - CMSG_REDEEM_WOW_TOKEN_START = 0x05BC, - CMSG_REORDER_CHARACTERS = 0x10B3, - CMSG_REPAIR_ITEM = 0x0736, - CMSG_REPLACE_TROPHY = 0x0DE9, - CMSG_REPOP_REQUEST = 0x15A9, - CMSG_REPORT_PVP_PLAYER_AFK = 0x1D09, - CMSG_REQUEST_ACCOUNT_DATA = 0x01B4, - CMSG_REQUEST_BATTLEFIELD_STATUS = 0x116B, - CMSG_REQUEST_CATEGORY_COOLDOWNS = 0x09A9, - CMSG_REQUEST_CEMETERY_LIST = 0x0DBA, - CMSG_REQUEST_CONQUEST_FORMULA_CONSTANTS = 0x0875, - CMSG_REQUEST_FORCED_REACTIONS = 0x086A, - CMSG_REQUEST_GUILD_PARTY_STATE = 0x08A6, - CMSG_REQUEST_GUILD_REWARDS_LIST = 0x00B1, - CMSG_REQUEST_HONOR_STATS = 0x1C86, - CMSG_REQUEST_LFG_LIST_BLACKLIST = 0x0D7A, - CMSG_REQUEST_PARTY_JOIN_UPDATES = 0x0570, - CMSG_REQUEST_PARTY_MEMBER_STATS = 0x01FF, - CMSG_REQUEST_PET_INFO = 0x0A11, - CMSG_REQUEST_PLAYED_TIME = 0x003D, - CMSG_REQUEST_PVP_REWARDS = 0x0435, - CMSG_REQUEST_RAID_INFO = 0x0533, - CMSG_REQUEST_RATED_BATTLEFIELD_INFO = 0x00B0, - CMSG_REQUEST_RESEARCH_HISTORY = 0x017A, - CMSG_REQUEST_STABLED_PETS = 0x0456, - CMSG_REQUEST_VEHICLE_EXIT = 0x0DF5, - CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x08BB, - CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x10A6, - CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x0C6A, - CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE = 0x0024, - CMSG_RESET_CHALLENGE_MODE = 0x0065, - CMSG_RESET_INSTANCES = 0x04FF, - CMSG_RESURRECT_RESPONSE = 0x003C, - CMSG_REVERT_MONUMENT_APPEARANCE = 0x0171, - CMSG_RIDE_VEHICLE_INTERACT = 0x1CA9, - CMSG_SAVE_CUF_PROFILES = 0x000A, - CMSG_SAVE_EQUIPMENT_SET = 0x041E, - CMSG_SAVE_GUILD_EMBLEM = 0x1402, - CMSG_SCENE_PLAYBACK_CANCELED = 0x0C65, - CMSG_SCENE_PLAYBACK_COMPLETE = 0x04A0, - CMSG_SCENE_TRIGGER_EVENT = 0x084D, - CMSG_SELF_RES = 0x1989, - CMSG_SELL_ITEM = 0x1922, - CMSG_SELL_WOW_TOKEN_CONFIRM = 0x11A3, - CMSG_SELL_WOW_TOKEN_START = 0x1140, - CMSG_SEND_CONTACT_LIST = 0x0077, - CMSG_SEND_MAIL = 0x00C0, - CMSG_SEND_SOR_REQUEST_VIA_ADDRESS = 0x00AC, - CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID = 0x0530, - CMSG_SEND_TEXT_EMOTE = 0x0412, - CMSG_SET_ACHIEVEMENTS_HIDDEN = 0x1C05, - CMSG_SET_ACTION_BAR_TOGGLES = 0x1D29, - CMSG_SET_ACTION_BUTTON = 0x1037, - CMSG_SET_ACTIVE_MOVER = 0x1936, - CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x00FF, - CMSG_SET_ADVANCED_COMBAT_LOGGING = 0x18A2, - CMSG_SET_ASSISTANT_LEADER = 0x04BB, - CMSG_SET_BACKPACK_AUTOSORT_DISABLED = 0x142D, - CMSG_SET_BANK_AUTOSORT_DISABLED = 0x0906, - CMSG_SET_BANK_BAG_SLOT_FLAG = 0x0035, - CMSG_SET_CONTACT_NOTES = 0x1030, - CMSG_SET_CURRENCY_FLAGS = 0x1421, - CMSG_SET_DIFFICULTY_ID = 0x08B9, - CMSG_SET_DUNGEON_DIFFICULTY = 0x00AF, - CMSG_SET_EVERYONE_IS_ASSISTANT = 0x0437, - CMSG_SET_FACTION_AT_WAR = 0x1582, - CMSG_SET_FACTION_INACTIVE = 0x1DAE, - CMSG_SET_FACTION_NOT_AT_WAR = 0x077D, - CMSG_SET_INSERT_ITEMS_LEFT_TO_RIGHT = 0x0505, - CMSG_SET_LFG_BONUS_FACTION_ID = 0x0402, - CMSG_SET_LOOT_METHOD = 0x016B, - CMSG_SET_LOOT_SPECIALIZATION = 0x0A51, - CMSG_SET_PARTY_ASSIGNMENT = 0x1074, - CMSG_SET_PARTY_LEADER = 0x11E7, - CMSG_SET_PET_SLOT = 0x0C45, - CMSG_SET_PLAYER_DECLINED_NAMES = 0x04B3, - CMSG_SET_PREFERRED_CEMETERY = 0x0D69, - CMSG_SET_PVP = 0x08AC, - CMSG_SET_RAID_DIFFICULTY = 0x103F, - CMSG_SET_ROLE = 0x01BF, - CMSG_SET_SAVED_INSTANCE_EXTEND = 0x10AB, - CMSG_SET_SELECTION = 0x1986, - CMSG_SET_SHEATHED = 0x0C5A, - CMSG_SET_SORT_BAGS_RIGHT_TO_LEFT = 0x00F1, - CMSG_SET_SPECIALIZATION = 0x1C82, - CMSG_SET_TAXI_BENCHMARK_MODE = 0x0455, - CMSG_SET_TITLE = 0x0C72, - CMSG_SET_TRADE_CURRENCY = 0x140A, - CMSG_SET_TRADE_GOLD = 0x0CE5, - CMSG_SET_TRADE_ITEM = 0x0105, - CMSG_SET_USING_PARTY_GARRISON = 0x10A9, - CMSG_SET_WATCHED_FACTION = 0x1905, - CMSG_SHOWING_CLOAK = 0x118E, - CMSG_SHOWING_HELM = 0x073E, - CMSG_SHOW_TRADE_SKILL = 0x11C0, - CMSG_SIGN_PETITION = 0x0679, - CMSG_SILENCE_PARTY_TALKER = 0x10F8, - CMSG_SOCKET_GEMS = 0x021A, - CMSG_SORT_BAGS = 0x01ED, - CMSG_SORT_BANK_BAGS = 0x09F2, - CMSG_SORT_REAGENT_BANK_BAGS = 0x05AA, - CMSG_SPELL_CLICK = 0x150A, - CMSG_SPIRIT_HEALER_ACTIVATE = 0x0A36, - CMSG_SPLIT_ITEM = 0x1219, - CMSG_STAND_STATE_CHANGE = 0x05EE, - CMSG_START_SPECTATOR_WAR_GAME = 0x10B7, - CMSG_START_WAR_GAME = 0x0100, - CMSG_SUMMON_RESPONSE = 0x0577, - CMSG_SUPPORT_TICKET_SUBMIT_BUG = 0x11BC, - CMSG_SUPPORT_TICKET_SUBMIT_COMPLAINT = 0x00EC, - CMSG_SUPPORT_TICKET_SUBMIT_SUGGESTION = 0x05A4, - CMSG_SUSPEND_COMMS_ACK = 0x0CB7, - CMSG_SUSPEND_TOKEN_RESPONSE = 0x08E8, - CMSG_SWAP_INV_ITEM = 0x1379, - CMSG_SWAP_ITEM = 0x1619, - CMSG_SWAP_SUB_GROUPS = 0x05EC, - CMSG_SWAP_VOID_ITEM = 0x096A, - CMSG_TABARD_VENDOR_ACTIVATE = 0x0905, - CMSG_TALK_TO_GOSSIP = 0x0A19, - CMSG_TAXI_NODE_STATUS_QUERY = 0x1DAD, - CMSG_TAXI_QUERY_AVAILABLE_NODES = 0x0336, - CMSG_TAXI_REQUEST_EARLY_LANDING = 0x0755, - CMSG_TELEPORT_TO_UNIT = 0x112F, - CMSG_TIME_ADJUSTMENT_RESPONSE = 0x119A, - CMSG_TIME_SYNC_RESPONSE = 0x119D, - CMSG_TIME_SYNC_RESPONSE_DROPPED = 0x18BA, - CMSG_TIME_SYNC_RESPONSE_FAILED = 0x15B5, - CMSG_TOGGLE_DIFFICULTY = 0x107F, - CMSG_TOGGLE_PVP = 0x1C21, - CMSG_TOTEM_DESTROYED = 0x0056, - CMSG_TOY_SET_FAVORITE = 0x1068, - CMSG_TRAINER_BUY_SPELL = 0x1D26, - CMSG_TRAINER_LIST = 0x0735, - CMSG_TRANSMOGRIFY_ITEMS = 0x09A1, - CMSG_TURN_IN_PETITION = 0x0A3A, - CMSG_TUTORIAL = 0x05EF, - CMSG_TWITTER_CHECK_STATUS = 0x0916, - CMSG_TWITTER_CONNECT = 0x095E, - CMSG_TWITTER_DISCONNECT = 0x011E, - CMSG_TWITTER_POST = 0x1482, - CMSG_UI_TIME_REQUEST = 0x0567, - CMSG_UNACCEPT_TRADE = 0x1081, - CMSG_UNDELETE_CHARACTER = 0x11F4, - CMSG_UNLEARN_SKILL = 0x0816, - CMSG_UNLEARN_SPECIALIZATION = 0x0880, - CMSG_UNLOCK_VOID_STORAGE = 0x0436, - CMSG_UPDATE_ACCOUNT_DATA = 0x102F, - CMSG_UPDATE_CLIENT_SETTINGS = 0x052B, - CMSG_UPDATE_MISSILE_TRAJECTORY = 0x0945, - CMSG_UPDATE_RAID_TARGET = 0x01B8, - CMSG_UPDATE_VAS_PURCHASE_STATES = 0x006C, - CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST = 0x0174, - CMSG_UPDATE_WOW_TOKEN_COUNT = 0x0164, - CMSG_UPGRADE_GARRISON = 0x0466, - CMSG_UPGRADE_ITEM = 0x182E, - CMSG_USED_FOLLOW = 0x0962, - CMSG_USE_CRITTER_ITEM = 0x0408, - CMSG_USE_EQUIPMENT_SET = 0x1236, - CMSG_USE_ITEM = 0x0562, - CMSG_USE_TOY = 0x057D, - CMSG_VIOLENCE_LEVEL = 0x0CBA, - CMSG_VOICE_ADD_IGNORE = 0x113B, - CMSG_VOICE_DEL_IGNORE = 0x01EB, - CMSG_VOICE_SESSION_ENABLE = 0x0434, - CMSG_VOID_STORAGE_TRANSFER = 0x14A2, - CMSG_WARDEN_DATA = 0x00EF, - CMSG_WHO = 0x00A4, - CMSG_WHO_IS = 0x042C, - CMSG_WORLD_PORT_RESPONSE = 0x04F7, - CMSG_WORLD_TELEPORT = 0x10EC, - CMSG_WRAP_ITEM = 0x1352, + CMSG_ACCEPT_GUILD_INVITE = 0x357B, + CMSG_ACCEPT_LEVEL_GRANT = 0x3463, + CMSG_ACCEPT_TRADE = 0x30D8, + CMSG_ACCEPT_WARGAME_INVITE = 0x3560, + CMSG_ACTIVATE_TAXI = 0x341F, + CMSG_ADDON_LIST = 0x3555, + CMSG_ADD_BATTLENET_FRIEND = 0x35E5, + CMSG_ADD_FRIEND = 0x365E, + CMSG_ADD_IGNORE = 0x3662, + CMSG_ADD_TOY = 0x31E6, + CMSG_ALTER_APPEARANCE = 0x345F, + CMSG_AREA_SPIRIT_HEALER_QUERY = 0x3424, + CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x3425, + CMSG_AREA_TRIGGER = 0x313C, + CMSG_ATTACK_STOP = 0x31B4, + CMSG_ATTACK_SWING = 0x31B3, + CMSG_AUCTION_HELLO_REQUEST = 0x3434, + CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x343A, + CMSG_AUCTION_LIST_ITEMS = 0x3437, + CMSG_AUCTION_LIST_OWNER_ITEMS = 0x3439, + CMSG_AUCTION_LIST_PENDING_SALES = 0x343C, + CMSG_AUCTION_PLACE_BID = 0x343B, + CMSG_AUCTION_REMOVE_ITEM = 0x3436, + CMSG_AUCTION_REPLICATE_ITEMS = 0x3438, + CMSG_AUCTION_SELL_ITEM = 0x3435, + CMSG_AUTH_CONTINUED_SESSION = 0x36E4, + CMSG_AUTH_SESSION = 0x36E3, + CMSG_AUTOBANK_ITEM = 0x3917, + CMSG_AUTOBANK_REAGENT = 0x3914, + CMSG_AUTOSTORE_BANK_ITEM = 0x3916, + CMSG_AUTOSTORE_BANK_REAGENT = 0x3915, + CMSG_AUTO_EQUIP_ITEM = 0x3918, + CMSG_AUTO_EQUIP_ITEM_SLOT = 0x391D, + CMSG_AUTO_STORE_BAG_ITEM = 0x3919, + CMSG_BANKER_ACTIVATE = 0x3427, + CMSG_BATTLEFIELD_LEAVE = 0x30F0, + CMSG_BATTLEFIELD_LIST = 0x30FB, + CMSG_BATTLEFIELD_PORT = 0x348C, + CMSG_BATTLEMASTER_HELLO = 0x31FC, + CMSG_BATTLEMASTER_JOIN = 0x3489, + CMSG_BATTLEMASTER_JOIN_ARENA = 0x348A, + CMSG_BATTLEMASTER_JOIN_SKIRMISH = 0x348B, + CMSG_BATTLENET_CHALLENGE_RESPONSE = 0x3661, + CMSG_BATTLENET_REQUEST = 0x3683, + CMSG_BATTLENET_REQUEST_REALM_LIST_TICKET = 0x3684, + CMSG_BATTLE_PAY_ACK_FAILED_RESPONSE = 0x3658, + CMSG_BATTLE_PAY_CONFIRM_PURCHASE_RESPONSE = 0x3657, + CMSG_BATTLE_PAY_DISTRIBUTION_ASSIGN_TO_TARGET = 0x3651, + CMSG_BATTLE_PAY_GET_PRODUCT_LIST = 0x364C, + CMSG_BATTLE_PAY_GET_PURCHASE_LIST = 0x364D, + CMSG_BATTLE_PAY_START_PURCHASE = 0x3680, + CMSG_BATTLE_PAY_START_VAS_PURCHASE = 0x3681, + CMSG_BATTLE_PET_DELETE_PET = 0x35AD, + CMSG_BATTLE_PET_DELETE_PET_CHEAT = 0x35AC, + CMSG_BATTLE_PET_MODIFY_NAME = 0x35AF, + CMSG_BATTLE_PET_REQUEST_JOURNAL = 0x35AB, + CMSG_BATTLE_PET_REQUEST_JOURNAL_LOCK = 0x35AA, + CMSG_BATTLE_PET_SET_BATTLE_SLOT = 0x35B3, + CMSG_BATTLE_PET_SET_FLAGS = 0x35B6, + CMSG_BATTLE_PET_SUMMON = 0x35B0, + CMSG_BATTLE_PET_UPDATE_NOTIFY = 0x3145, + CMSG_BEGIN_TRADE = 0x30D5, + CMSG_BF_MGR_ENTRY_INVITE_RESPONSE = 0x3559, + CMSG_BF_MGR_QUEUE_EXIT_REQUEST = 0x355B, + CMSG_BF_MGR_QUEUE_INVITE_RESPONSE = 0x355A, + CMSG_BF_MGR_QUEUE_REQUEST = 0x30EF, + CMSG_BINDER_ACTIVATE = 0x3426, + CMSG_BLACK_MARKET_BID_ON_ITEM = 0x3493, + CMSG_BLACK_MARKET_OPEN = 0x3491, + CMSG_BLACK_MARKET_REQUEST_ITEMS = 0x3492, + CMSG_BUG_REPORT = 0x3616, + CMSG_BUSY_TRADE = 0x30D6, + CMSG_BUY_BACK_ITEM = 0x3418, + CMSG_BUY_BANK_SLOT = 0x3428, + CMSG_BUY_ITEM = 0x3417, + CMSG_BUY_REAGENT_BANK = 0x3429, + CMSG_BUY_WOW_TOKEN_CONFIRM = 0x367A, + CMSG_BUY_WOW_TOKEN_START = 0x3679, + CMSG_CAGE_BATTLE_PET = 0x3154, + CMSG_CALENDAR_ADD_EVENT = 0x360D, + CMSG_CALENDAR_COMPLAIN = 0x3609, + CMSG_CALENDAR_COPY_EVENT = 0x3608, + CMSG_CALENDAR_EVENT_INVITE = 0x3602, + CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x3606, + CMSG_CALENDAR_EVENT_RSVP = 0x3604, + CMSG_CALENDAR_EVENT_SIGN_UP = 0x360B, + CMSG_CALENDAR_EVENT_STATUS = 0x3605, + CMSG_CALENDAR_GET = 0x35FF, + CMSG_CALENDAR_GET_EVENT = 0x3600, + CMSG_CALENDAR_GET_NUM_PENDING = 0x360A, + CMSG_CALENDAR_GUILD_FILTER = 0x3601, + CMSG_CALENDAR_REMOVE_EVENT = 0x3607, + CMSG_CALENDAR_REMOVE_INVITE = 0x3603, + CMSG_CALENDAR_UPDATE_EVENT = 0x360E, + CMSG_CANCEL_AURA = 0x3126, + CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x344F, + CMSG_CANCEL_CAST = 0x31EB, + CMSG_CANCEL_CHANNELLING = 0x31BF, + CMSG_CANCEL_GROWTH_AURA = 0x31C4, + CMSG_CANCEL_MASTER_LOOT_ROLL = 0x3172, + CMSG_CANCEL_MOD_SPEED_NO_CONTROL_AURAS = 0x3125, + CMSG_CANCEL_MOUNT_AURA = 0x31D5, + CMSG_CANCEL_QUEUED_SPELL = 0x30FC, + CMSG_CANCEL_TEMP_ENCHANTMENT = 0x345C, + CMSG_CANCEL_TRADE = 0x30DA, + CMSG_CAN_DUEL = 0x35EE, + CMSG_CAST_SPELL = 0x31E9, + CMSG_CHALLENGE_MODE_REQUEST_LEADERS = 0x300D, + CMSG_CHALLENGE_MODE_REQUEST_MAP_STATS = 0x300C, + CMSG_CHANGE_BAG_SLOT_FLAG = 0x3265, + CMSG_CHANGE_MONUMENT_APPEARANCE = 0x3247, + CMSG_CHANGE_SUB_GROUP = 0x35D3, + CMSG_CHARACTER_RENAME_REQUEST = 0x364F, + CMSG_CHAR_CUSTOMIZE = 0x361E, + CMSG_CHAR_DELETE = 0x362B, + CMSG_CHAR_RACE_OR_FACTION_CHANGE = 0x3624, + CMSG_CHAT_ADDON_MESSAGE_CHANNEL = 0x374E, + CMSG_CHAT_ADDON_MESSAGE_GUILD = 0x3752, + CMSG_CHAT_ADDON_MESSAGE_INSTANCE_CHAT = 0x3775, + CMSG_CHAT_ADDON_MESSAGE_OFFICER = 0x3754, + CMSG_CHAT_ADDON_MESSAGE_PARTY = 0x3771, + CMSG_CHAT_ADDON_MESSAGE_RAID = 0x3773, + CMSG_CHAT_ADDON_MESSAGE_WHISPER = 0x3750, + CMSG_CHAT_CHANNEL_ANNOUNCEMENTS = 0x3765, + CMSG_CHAT_CHANNEL_BAN = 0x3763, + CMSG_CHAT_CHANNEL_DECLINE_INVITE = 0x376C, + CMSG_CHAT_CHANNEL_DISPLAY_LIST = 0x3758, + CMSG_CHAT_CHANNEL_INVITE = 0x3761, + CMSG_CHAT_CHANNEL_KICK = 0x3762, + CMSG_CHAT_CHANNEL_LIST = 0x3757, + CMSG_CHAT_CHANNEL_MODERATE = 0x375C, + CMSG_CHAT_CHANNEL_MODERATOR = 0x375D, + CMSG_CHAT_CHANNEL_MUTE = 0x375F, + CMSG_CHAT_CHANNEL_OWNER = 0x375B, + CMSG_CHAT_CHANNEL_PASSWORD = 0x3759, + CMSG_CHAT_CHANNEL_SET_OWNER = 0x375A, + CMSG_CHAT_CHANNEL_SILENCE_ALL = 0x3768, + CMSG_CHAT_CHANNEL_SILENCE_VOICE = 0x3766, + CMSG_CHAT_CHANNEL_UNBAN = 0x3764, + CMSG_CHAT_CHANNEL_UNMODERATOR = 0x375E, + CMSG_CHAT_CHANNEL_UNMUTE = 0x3760, + CMSG_CHAT_CHANNEL_UNSILENCE_ALL = 0x3769, + CMSG_CHAT_CHANNEL_UNSILENCE_VOICE = 0x3767, + CMSG_CHAT_CHANNEL_VOICE_OFF = 0x376B, + CMSG_CHAT_CHANNEL_VOICE_ON = 0x376A, + CMSG_CHAT_JOIN_CHANNEL = 0x3746, + CMSG_CHAT_LEAVE_CHANNEL = 0x3747, + CMSG_CHAT_MESSAGE_AFK = 0x3755, + CMSG_CHAT_MESSAGE_CHANNEL = 0x374D, + CMSG_CHAT_MESSAGE_DND = 0x3756, + CMSG_CHAT_MESSAGE_EMOTE = 0x376E, + CMSG_CHAT_MESSAGE_GUILD = 0x3751, + CMSG_CHAT_MESSAGE_INSTANCE_CHAT = 0x3774, + CMSG_CHAT_MESSAGE_OFFICER = 0x3753, + CMSG_CHAT_MESSAGE_PARTY = 0x3770, + CMSG_CHAT_MESSAGE_RAID = 0x3772, + CMSG_CHAT_MESSAGE_RAID_WARNING = 0x3776, + CMSG_CHAT_MESSAGE_SAY = 0x376D, + CMSG_CHAT_MESSAGE_WHISPER = 0x374F, + CMSG_CHAT_MESSAGE_YELL = 0x376F, + CMSG_CHAT_REGISTER_ADDON_PREFIXES = 0x374B, + CMSG_CHAT_REPORT_FILTERED = 0x374A, + CMSG_CHAT_REPORT_IGNORED = 0x3749, + CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES = 0x374C, + CMSG_CHECK_RAF_EMAIL_ENABLED = 0x3659, + CMSG_CHECK_WOW_TOKEN_VETERAN_ELIGIBILITY = 0x3678, + CMSG_CHOICE_RESPONSE = 0x31ED, + CMSG_CLEAR_RAID_MARKER = 0x311E, + CMSG_CLEAR_TRADE_ITEM = 0x30DC, + CMSG_CLIENT_PORT_GRAVEYARD = 0x348E, + CMSG_CLOSE_INTERACTION = 0x3405, + CMSG_COMMENTATOR_ENABLE = 0x3673, + CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3573, + CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3574, + CMSG_COMMENTATOR_GET_MAP_INFO = 0x3571, + CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3572, + CMSG_COMMENTATOR_START_WARGAME = 0x356F, + CMSG_COMPLAINT = 0x35FC, + CMSG_COMPLETE_CINEMATIC = 0x34AB, + CMSG_COMPLETE_MOVIE = 0x3446, + CMSG_CONFIRM_RESPEC_WIPE = 0x316C, + CMSG_CONNECT_TO_FAILED = 0x3552, + CMSG_CONVERT_RAID = 0x35D5, + CMSG_CREATE_CHARACTER = 0x35CA, + CMSG_CREATE_SHIPMENT = 0x3236, + CMSG_DB_QUERY_BULK = 0x3566, + CMSG_DECLINE_GUILD_INVITES = 0x3487, + CMSG_DECLINE_PETITION = 0x349A, + CMSG_DELETE_EQUIPMENT_SET = 0x3478, + CMSG_DEL_FRIEND = 0x365F, + CMSG_DEL_IGNORE = 0x3663, + CMSG_DEPOSIT_REAGENT_BANK = 0x326E, + CMSG_DESTROY_ITEM = 0x31E0, + CMSG_DF_BOOT_PLAYER_VOTE = 0x359B, + CMSG_DF_GET_JOIN_STATUS = 0x3597, + CMSG_DF_GET_SYSTEM_INFO = 0x3596, + CMSG_DF_JOIN = 0x3588, + CMSG_DF_LEAVE = 0x3593, + CMSG_DF_PROPOSAL_RESPONSE = 0x3587, + CMSG_DF_READY_CHECK_RESPONSE = 0x359E, + CMSG_DF_SEARCH_JOIN = 0x3594, + CMSG_DF_SEARCH_LEAVE = 0x3595, + CMSG_DF_SET_COMMENT = 0x3598, + CMSG_DF_SET_ROLES = 0x3599, + CMSG_DF_TELEPORT = 0x359C, + CMSG_DISCARDED_TIME_SYNC_ACKS = 0x39B4, + CMSG_DISMISS_CRITTER = 0x3465, + CMSG_DO_MASTER_LOOT_ROLL = 0x3171, + CMSG_DO_READY_CHECK = 0x35BA, + CMSG_DUEL_RESPONSE = 0x344B, + CMSG_EJECT_PASSENGER = 0x3198, + CMSG_EMOTE = 0x34A7, + CMSG_ENABLE_NAGLE = 0x36E8, + CMSG_ENABLE_TAXI_NODE = 0x341D, + CMSG_ENGINE_SURVEY = 0x3672, + CMSG_ENUM_CHARACTERS = 0x3568, + CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT = 0x366C, + CMSG_FAR_SIGHT = 0x3450, + CMSG_GAME_OBJ_REPORT_USE = 0x3459, + CMSG_GAME_OBJ_USE = 0x3458, + CMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING = 0x3227, + CMSG_GARRISON_CANCEL_CONSTRUCTION = 0x3219, + CMSG_GARRISON_CHECK_UPGRADEABLE = 0x3261, + CMSG_GARRISON_COMPLETE_MISSION = 0x3254, + CMSG_GARRISON_GENERATE_RECRUITS = 0x322A, + CMSG_GARRISON_GET_BUILDING_LANDMARKS = 0x3232, + CMSG_GARRISON_MISSION_BONUS_ROLL = 0x3256, + CMSG_GARRISON_PURCHASE_BUILDING = 0x3215, + CMSG_GARRISON_RECRUIT_FOLLOWER = 0x322C, + CMSG_GARRISON_REMOVE_FOLLOWER = 0x324B, + CMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING = 0x3228, + CMSG_GARRISON_RENAME_FOLLOWER = 0x3229, + CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA = 0x3214, + CMSG_GARRISON_REQUEST_LANDING_PAGE_SHIPMENT_INFO = 0x3235, + CMSG_GARRISON_REQUEST_SHIPMENT_INFO = 0x3234, + CMSG_GARRISON_SET_BUILDING_ACTIVE = 0x3216, + CMSG_GARRISON_SET_FOLLOWER_FAVORITE = 0x3226, + CMSG_GARRISON_SET_FOLLOWER_INACTIVE = 0x3222, + CMSG_GARRISON_SET_RECRUITMENT_PREFERENCES = 0x322B, + CMSG_GARRISON_START_MISSION = 0x3253, + CMSG_GARRISON_SWAP_BUILDINGS = 0x321A, + CMSG_GENERATE_RANDOM_CHARACTER_NAME = 0x3567, + CMSG_GET_CHALLENGE_MODE_REWARDS = 0x300F, + CMSG_GET_GARRISON_INFO = 0x320F, + CMSG_GET_ITEM_PURCHASE_DATA = 0x3495, + CMSG_GET_MIRROR_IMAGE_DATA = 0x31E4, + CMSG_GET_PVP_OPTIONS_ENABLED = 0x356E, + CMSG_GET_REMAINING_GAME_TIME = 0x367B, + CMSG_GET_TROPHY_LIST = 0x3244, + CMSG_GET_UNDELETE_CHARACTER_COOLDOWN_STATUS = 0x366E, + CMSG_GM_TICKET_ACKNOWLEDGE_SURVEY = 0x3622, + CMSG_GM_TICKET_GET_CASE_STATUS = 0x3621, + CMSG_GM_TICKET_GET_SYSTEM_STATUS = 0x3620, + CMSG_GOSSIP_SELECT_OPTION = 0x3406, + CMSG_GRANT_LEVEL = 0x3461, + CMSG_GUILD_ADD_BATTLENET_FRIEND = 0x300B, + CMSG_GUILD_ADD_RANK = 0x2FE2, + CMSG_GUILD_ASSIGN_MEMBER_RANK = 0x2FDD, + CMSG_GUILD_AUTO_DECLINE_INVITATION = 0x2FDF, + CMSG_GUILD_BANK_ACTIVATE = 0x342A, + CMSG_GUILD_BANK_BUY_TAB = 0x342D, + CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x342F, + CMSG_GUILD_BANK_LOG_QUERY = 0x3000, + CMSG_GUILD_BANK_QUERY_TAB = 0x342C, + CMSG_GUILD_BANK_REMAINING_WITHDRAW_MONEY_QUERY = 0x3001, + CMSG_GUILD_BANK_SET_TAB_TEXT = 0x3004, + CMSG_GUILD_BANK_SWAP_ITEMS = 0x342B, + CMSG_GUILD_BANK_TEXT_QUERY = 0x3005, + CMSG_GUILD_BANK_UPDATE_TAB = 0x342E, + CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3430, + CMSG_GUILD_CHALLENGE_UPDATE_REQUEST = 0x2FF9, + CMSG_GUILD_CHANGE_NAME_REQUEST = 0x2FFC, + CMSG_GUILD_DECLINE_INVITATION = 0x2FDE, + CMSG_GUILD_DELETE = 0x2FE6, + CMSG_GUILD_DELETE_RANK = 0x2FE3, + CMSG_GUILD_DEMOTE_MEMBER = 0x2FDC, + CMSG_GUILD_EVENT_LOG_QUERY = 0x3003, + CMSG_GUILD_GET_ACHIEVEMENT_MEMBERS = 0x2FEF, + CMSG_GUILD_GET_RANKS = 0x2FEB, + CMSG_GUILD_GET_ROSTER = 0x2FF1, + CMSG_GUILD_INVITE_BY_NAME = 0x3586, + CMSG_GUILD_LEAVE = 0x2FE0, + CMSG_GUILD_MEMBER_SEND_SOR_REQUEST = 0x300A, + CMSG_GUILD_NEWS_UPDATE_STICKY = 0x2FEC, + CMSG_GUILD_OFFICER_REMOVE_MEMBER = 0x2FE1, + CMSG_GUILD_PERMISSIONS_QUERY = 0x3002, + CMSG_GUILD_PROMOTE_MEMBER = 0x2FDB, + CMSG_GUILD_QUERY_MEMBERS_FOR_RECIPE = 0x2FE9, + CMSG_GUILD_QUERY_MEMBER_RECIPES = 0x2FE7, + CMSG_GUILD_QUERY_NEWS = 0x2FEA, + CMSG_GUILD_QUERY_RECIPES = 0x2FE8, + CMSG_GUILD_REPLACE_GUILD_MASTER = 0x3006, + CMSG_GUILD_SET_ACHIEVEMENT_TRACKING = 0x2FED, + CMSG_GUILD_SET_FOCUSED_ACHIEVEMENT = 0x2FEE, + CMSG_GUILD_SET_GUILD_MASTER = 0x3653, + CMSG_GUILD_SET_MEMBER_NOTE = 0x2FF0, + CMSG_GUILD_SET_RANK_PERMISSIONS = 0x2FE5, + CMSG_GUILD_SHIFT_RANK = 0x2FE4, + CMSG_GUILD_UPDATE_INFO_TEXT = 0x2FF3, + CMSG_GUILD_UPDATE_MOTD_TEXT = 0x2FF2, + CMSG_HEARTH_AND_RESURRECT = 0x3474, + CMSG_IGNORE_TRADE = 0x30D7, + CMSG_INCREASE_CAST_TIME_FOR_SPELL = 0x3169, + CMSG_INITIATE_ROLE_POLL = 0x3557, + CMSG_INITIATE_TRADE = 0x30D4, + CMSG_INSPECT = 0x3490, + CMSG_INSPECT_PVP = 0x3631, + CMSG_INSTANCE_LOCK_RESPONSE = 0x3479, + CMSG_ITEM_PURCHASE_REFUND = 0x3496, + CMSG_ITEM_TEXT_QUERY = 0x3262, + CMSG_JOIN_PET_BATTLE_QUEUE = 0x3143, + CMSG_JOIN_RATED_BATTLEGROUND = 0x30F4, + CMSG_KEEP_ALIVE = 0x360F, + CMSG_KEYBOUND_OVERRIDE = 0x3183, + CMSG_LEARN_PET_SPECIALIZATION_GROUP = 0x3124, + CMSG_LEARN_TALENTS = 0x3123, + CMSG_LEAVE_GROUP = 0x35D0, + CMSG_LEAVE_PET_BATTLE_QUEUE = 0x3144, + CMSG_LFG_LIST_APPLY_TO_GROUP = 0x358E, + CMSG_LFG_LIST_CANCEL_APPLICATION = 0x358F, + CMSG_LFG_LIST_DECLINE_APPLICANT = 0x3590, + CMSG_LFG_LIST_GET_STATUS = 0x358C, + CMSG_LFG_LIST_INVITE_APPLICANT = 0x3591, + CMSG_LFG_LIST_INVITE_RESPONSE = 0x3592, + CMSG_LFG_LIST_JOIN = 0x3589, + CMSG_LFG_LIST_LEAVE = 0x358B, + CMSG_LFG_LIST_SEARCH = 0x358D, + CMSG_LFG_LIST_UPDATE_REQUEST = 0x358A, + CMSG_LF_GUILD_ADD_RECRUIT = 0x35A3, + CMSG_LF_GUILD_BROWSE = 0x35A5, + CMSG_LF_GUILD_DECLINE_RECRUIT = 0x2FF6, + CMSG_LF_GUILD_GET_APPLICATIONS = 0x2FF7, + CMSG_LF_GUILD_GET_GUILD_POST = 0x2FF4, + CMSG_LF_GUILD_GET_RECRUITS = 0x2FF5, + CMSG_LF_GUILD_REMOVE_RECRUIT = 0x2FF8, + CMSG_LF_GUILD_SET_GUILD_POST = 0x35A4, + CMSG_LIST_INVENTORY = 0x3415, + CMSG_LOADING_SCREEN_NOTIFY = 0x3577, + CMSG_LOAD_SELECTED_TROPHY = 0x3245, + CMSG_LOGOUT_CANCEL = 0x3441, + CMSG_LOGOUT_INSTANT = 0x3442, + CMSG_LOGOUT_REQUEST = 0x3440, + CMSG_LOG_DISCONNECT = 0x36E6, + CMSG_LOG_STREAMING_ERROR = 0x36EA, + CMSG_LOOT_ITEM = 0x316F, + CMSG_LOOT_MONEY = 0x316E, + CMSG_LOOT_RELEASE = 0x3173, + CMSG_LOOT_ROLL = 0x3174, + CMSG_LOOT_UNIT = 0x316D, + CMSG_LOW_LEVEL_RAID1 = 0x362F, + CMSG_LOW_LEVEL_RAID2 = 0x347F, + CMSG_MAIL_CREATE_TEXT_ITEM = 0x34A1, + CMSG_MAIL_DELETE = 0x3185, + CMSG_MAIL_GET_LIST = 0x349C, + CMSG_MAIL_MARK_AS_READ = 0x34A0, + CMSG_MAIL_RETURN_TO_SENDER = 0x35DF, + CMSG_MAIL_TAKE_ITEM = 0x349E, + CMSG_MAIL_TAKE_MONEY = 0x349D, + CMSG_MASTER_LOOT_ITEM = 0x3170, + CMSG_MINIMAP_PING = 0x35D2, + CMSG_MISSILE_TRAJECTORY_COLLISION = 0x3107, + CMSG_MOUNT_SET_FAVORITE = 0x35B8, + CMSG_MOUNT_SPECIAL_ANIM = 0x31D6, + CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK = 0x398C, + CMSG_MOVE_CHANGE_TRANSPORT = 0x39A4, + CMSG_MOVE_CHANGE_VEHICLE_SEATS = 0x39A9, + CMSG_MOVE_CHARM_TELEPORT_CHEAT = 0x3972, + CMSG_MOVE_DISMISS_VEHICLE = 0x39A8, + CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK = 0x3993, + CMSG_MOVE_FALL_LAND = 0x3975, + CMSG_MOVE_FALL_RESET = 0x3990, + CMSG_MOVE_FEATHER_FALL_ACK = 0x3985, + CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x398A, + CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x3983, + CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK = 0x39B5, + CMSG_MOVE_FORCE_ROOT_ACK = 0x3986, + CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x39AA, + CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK = 0x3982, + CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x3992, + CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK = 0x39A3, + CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK = 0x3996, + CMSG_MOVE_FORCE_UNROOT_ACK = 0x399A, + CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK = 0x3997, + CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x3998, + CMSG_MOVE_GRAVITY_ENABLE_ACK = 0x399C, + CMSG_MOVE_HEARTBEAT = 0x3987, + CMSG_MOVE_HOVER_ACK = 0x399B, + CMSG_MOVE_JUMP = 0x3968, + CMSG_MOVE_KNOCK_BACK_ACK = 0x39AB, + CMSG_MOVE_REMOVE_MOVEMENT_FORCES = 0x398E, + CMSG_MOVE_REMOVE_MOVEMENT_FORCE_ACK = 0x398D, + CMSG_MOVE_SET_CAN_FLY_ACK = 0x3984, + CMSG_MOVE_SET_CAN_TURN_WHILE_FALLING_ACK = 0x3999, + CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0x39AE, + CMSG_MOVE_SET_FACING = 0x3980, + CMSG_MOVE_SET_FLY = 0x399D, + CMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES_ACK = 0x39A7, + CMSG_MOVE_SET_PITCH = 0x3981, + CMSG_MOVE_SET_RELATIVE_POSITION = 0x3973, + CMSG_MOVE_SET_RUN_MODE = 0x396F, + CMSG_MOVE_SET_VEHICLE_REC_ID_ACK = 0x398B, + CMSG_MOVE_SET_WALK_MODE = 0x3970, + CMSG_MOVE_SPLINE_DONE = 0x398F, + CMSG_MOVE_START_ASCEND = 0x399E, + CMSG_MOVE_START_BACKWARD = 0x3963, + CMSG_MOVE_START_DESCEND = 0x39A5, + CMSG_MOVE_START_FORWARD = 0x3962, + CMSG_MOVE_START_PITCH_DOWN = 0x396D, + CMSG_MOVE_START_PITCH_UP = 0x396C, + CMSG_MOVE_START_STRAFE_LEFT = 0x3965, + CMSG_MOVE_START_STRAFE_RIGHT = 0x3966, + CMSG_MOVE_START_SWIM = 0x3976, + CMSG_MOVE_START_TURN_LEFT = 0x3969, + CMSG_MOVE_START_TURN_RIGHT = 0x396A, + CMSG_MOVE_STOP = 0x3964, + CMSG_MOVE_STOP_ASCEND = 0x399F, + CMSG_MOVE_STOP_PITCH = 0x396E, + CMSG_MOVE_STOP_STRAFE = 0x3967, + CMSG_MOVE_STOP_SWIM = 0x3977, + CMSG_MOVE_STOP_TURN = 0x396B, + CMSG_MOVE_TELEPORT_ACK = 0x3974, + CMSG_MOVE_TELEPORT_CHEAT = 0x3971, + CMSG_MOVE_TIME_SKIPPED = 0x3991, + CMSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x397F, + CMSG_MOVE_WATER_WALK_ACK = 0x3989, + CMSG_NEUTRAL_PLAYER_SELECT_FACTION = 0x3139, + CMSG_NEXT_CINEMATIC_CAMERA = 0x34AA, + CMSG_OBJECT_UPDATE_FAILED = 0x30FD, + CMSG_OBJECT_UPDATE_RESCUED = 0x30FE, + CMSG_OFFER_PETITION = 0x3640, + CMSG_OPENING_CINEMATIC = 0x34A9, + CMSG_OPEN_ITEM = 0x3263, + CMSG_OPEN_MISSION_NPC = 0x322E, + CMSG_OPEN_SHIPMENT_NPC = 0x3233, + CMSG_OPEN_TRADESKILL_NPC = 0x323B, + CMSG_OPT_OUT_OF_LOOT = 0x3460, + CMSG_PARTY_INVITE = 0x3581, + CMSG_PARTY_INVITE_RESPONSE = 0x3582, + CMSG_PARTY_UNINVITE = 0x35CE, + CMSG_PETITION_BUY = 0x3432, + CMSG_PETITION_RENAME_GUILD = 0x3654, + CMSG_PETITION_SHOW_LIST = 0x3431, + CMSG_PETITION_SHOW_SIGNATURES = 0x3433, + CMSG_PET_ABANDON = 0x33FF, + CMSG_PET_ACTION = 0x33FD, + CMSG_PET_BATTLE_FINAL_NOTIFY = 0x3147, + CMSG_PET_BATTLE_INPUT = 0x35C7, + CMSG_PET_BATTLE_QUEUE_PROPOSE_MATCH_RESULT = 0x3184, + CMSG_PET_BATTLE_QUIT_NOTIFY = 0x3146, + CMSG_PET_BATTLE_REPLACE_FRONT_PET = 0x35C8, + CMSG_PET_BATTLE_REQUEST_PVP = 0x3141, + CMSG_PET_BATTLE_REQUEST_UPDATE = 0x3142, + CMSG_PET_BATTLE_REQUEST_WILD = 0x313F, + CMSG_PET_BATTLE_SCRIPT_ERROR_NOTIFY = 0x3148, + CMSG_PET_CANCEL_AURA = 0x3400, + CMSG_PET_CAST_SPELL = 0x31E8, + CMSG_PET_RENAME = 0x3615, + CMSG_PET_SET_ACTION = 0x33FC, + CMSG_PET_SPELL_AUTOCAST = 0x3401, + CMSG_PET_STOP_ATTACK = 0x33FE, + CMSG_PING = 0x36E5, + CMSG_PLAYER_LOGIN = 0x356A, + CMSG_PROTOCOL_MISMATCH = 0x36EB, + CMSG_PUSH_QUEST_TO_PARTY = 0x3413, + CMSG_PVP_LOG_DATA = 0x30F8, + CMSG_QUERY_BATTLE_PET_NAME = 0x31CB, + CMSG_QUERY_CORPSE_LOCATION_FROM_CLIENT = 0x35EC, + CMSG_QUERY_CORPSE_TRANSPORT = 0x35ED, + CMSG_QUERY_COUNTDOWN_TIMER = 0x3121, + CMSG_QUERY_CREATURE = 0x31C5, + CMSG_QUERY_GAME_OBJECT = 0x31C6, + CMSG_QUERY_GARRISON_CREATURE_NAME = 0x31CC, + CMSG_QUERY_GUILD_INFO = 0x361D, + CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x346F, + CMSG_QUERY_NEXT_MAIL_TIME = 0x349F, + CMSG_QUERY_NPC_TEXT = 0x31C7, + CMSG_QUERY_PAGE_TEXT = 0x31C9, + CMSG_QUERY_PETITION = 0x31CD, + CMSG_QUERY_PET_NAME = 0x31CA, + CMSG_QUERY_PLAYER_NAME = 0x361B, + CMSG_QUERY_QUEST_COMPLETION_NPCS = 0x30F1, + CMSG_QUERY_QUEST_INFO = 0x31C8, + CMSG_QUERY_REALM_NAME = 0x361C, + CMSG_QUERY_SCENARIO_POI = 0x35E0, + CMSG_QUERY_TIME = 0x343F, + CMSG_QUERY_VOID_STORAGE = 0x311A, + CMSG_QUEST_CONFIRM_ACCEPT = 0x3412, + CMSG_QUEST_GIVER_ACCEPT_QUEST = 0x340B, + CMSG_QUEST_GIVER_CHOOSE_REWARD = 0x340E, + CMSG_QUEST_GIVER_COMPLETE_QUEST = 0x340C, + CMSG_QUEST_GIVER_HELLO = 0x3408, + CMSG_QUEST_GIVER_QUERY_QUEST = 0x3409, + CMSG_QUEST_GIVER_REQUEST_REWARD = 0x340F, + CMSG_QUEST_GIVER_STATUS_MULTIPLE_QUERY = 0x3411, + CMSG_QUEST_GIVER_STATUS_QUERY = 0x3410, + CMSG_QUEST_LOG_REMOVE_QUEST = 0x3494, + CMSG_QUEST_POI_QUERY = 0x3641, + CMSG_QUEST_PUSH_RESULT = 0x3414, + CMSG_QUEUED_MESSAGES_END = 0x36E9, + CMSG_RANDOM_ROLL = 0x35DB, + CMSG_READY_CHECK_RESPONSE = 0x35BB, + CMSG_READ_ITEM = 0x3264, + CMSG_RECLAIM_CORPSE = 0x3444, + CMSG_RECRUIT_A_FRIEND = 0x365A, + CMSG_REDEEM_WOW_TOKEN_CONFIRM = 0x367D, + CMSG_REDEEM_WOW_TOKEN_START = 0x367C, + CMSG_REORDER_CHARACTERS = 0x3569, + CMSG_REPAIR_ITEM = 0x3454, + CMSG_REPLACE_TROPHY = 0x3246, + CMSG_REPOP_REQUEST = 0x348D, + CMSG_REPORT_PVP_PLAYER_AFK = 0x345E, + CMSG_REQUEST_ACCOUNT_DATA = 0x3625, + CMSG_REQUEST_BATTLEFIELD_STATUS = 0x355C, + CMSG_REQUEST_CATEGORY_COOLDOWNS = 0x30FA, + CMSG_REQUEST_CEMETERY_LIST = 0x30F2, + CMSG_REQUEST_CONQUEST_FORMULA_CONSTANTS = 0x31FF, + CMSG_REQUEST_FORCED_REACTIONS = 0x3168, + CMSG_REQUEST_GUILD_PARTY_STATE = 0x3120, + CMSG_REQUEST_GUILD_REWARDS_LIST = 0x311F, + CMSG_REQUEST_HONOR_STATS = 0x30F7, + CMSG_REQUEST_LFG_LIST_BLACKLIST = 0x31EF, + CMSG_REQUEST_PARTY_JOIN_UPDATES = 0x3576, + CMSG_REQUEST_PARTY_MEMBER_STATS = 0x35DA, + CMSG_REQUEST_PET_INFO = 0x3402, + CMSG_REQUEST_PLAYED_TIME = 0x31D1, + CMSG_REQUEST_PVP_REWARDS = 0x310E, + CMSG_REQUEST_RAID_INFO = 0x3655, + CMSG_REQUEST_RATED_BATTLEFIELD_INFO = 0x3564, + CMSG_REQUEST_RESEARCH_HISTORY = 0x30E5, + CMSG_REQUEST_STABLED_PETS = 0x3403, + CMSG_REQUEST_VEHICLE_EXIT = 0x3193, + CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x3194, + CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x3195, + CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x3196, + CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE = 0x3675, + CMSG_RESET_CHALLENGE_MODE = 0x3166, + CMSG_RESET_INSTANCES = 0x35F8, + CMSG_RESURRECT_RESPONSE = 0x3614, + CMSG_REVERT_MONUMENT_APPEARANCE = 0x3248, + CMSG_RIDE_VEHICLE_INTERACT = 0x3197, + CMSG_SAVE_CUF_PROFILES = 0x3108, + CMSG_SAVE_EQUIPMENT_SET = 0x3477, + CMSG_SAVE_GUILD_EMBLEM = 0x31F4, + CMSG_SCENE_PLAYBACK_CANCELED = 0x3180, + CMSG_SCENE_PLAYBACK_COMPLETE = 0x317F, + CMSG_SCENE_TRIGGER_EVENT = 0x3181, + CMSG_SELF_RES = 0x3497, + CMSG_SELL_ITEM = 0x3416, + CMSG_SELL_WOW_TOKEN_CONFIRM = 0x3677, + CMSG_SELL_WOW_TOKEN_START = 0x3676, + CMSG_SEND_CONTACT_LIST = 0x365D, + CMSG_SEND_MAIL = 0x3579, + CMSG_SEND_SOR_REQUEST_VIA_ADDRESS = 0x35A8, + CMSG_SEND_TEXT_EMOTE = 0x33F9, + CMSG_SET_ACHIEVEMENTS_HIDDEN = 0x3186, + CMSG_SET_ACTION_BAR_TOGGLES = 0x3498, + CMSG_SET_ACTION_BUTTON = 0x35BC, + CMSG_SET_ACTIVE_MOVER = 0x39AF, + CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x35DC, + CMSG_SET_ADVANCED_COMBAT_LOGGING = 0x3200, + CMSG_SET_ASSISTANT_LEADER = 0x35D6, + CMSG_SET_BACKPACK_AUTOSORT_DISABLED = 0x3267, + CMSG_SET_BANK_AUTOSORT_DISABLED = 0x3268, + CMSG_SET_BANK_BAG_SLOT_FLAG = 0x3266, + CMSG_SET_CONTACT_NOTES = 0x3660, + CMSG_SET_CURRENCY_FLAGS = 0x30E7, + CMSG_SET_DIFFICULTY_ID = 0x3182, + CMSG_SET_DUNGEON_DIFFICULTY = 0x3612, + CMSG_SET_EVERYONE_IS_ASSISTANT = 0x359D, + CMSG_SET_FACTION_AT_WAR = 0x3447, + CMSG_SET_FACTION_INACTIVE = 0x3449, + CMSG_SET_FACTION_NOT_AT_WAR = 0x3448, + CMSG_SET_INSERT_ITEMS_LEFT_TO_RIGHT = 0x326A, + CMSG_SET_LFG_BONUS_FACTION_ID = 0x31EE, + CMSG_SET_LOOT_METHOD = 0x35CF, + CMSG_SET_LOOT_SPECIALIZATION = 0x34A5, + CMSG_SET_PARTY_ASSIGNMENT = 0x35D8, + CMSG_SET_PARTY_LEADER = 0x35D1, + CMSG_SET_PET_SLOT = 0x30E6, + CMSG_SET_PLAYER_DECLINED_NAMES = 0x361A, + CMSG_SET_PREFERRED_CEMETERY = 0x30F3, + CMSG_SET_PVP = 0x31F8, + CMSG_SET_RAID_DIFFICULTY = 0x366A, + CMSG_SET_ROLE = 0x3556, + CMSG_SET_SAVED_INSTANCE_EXTEND = 0x3618, + CMSG_SET_SELECTION = 0x348F, + CMSG_SET_SHEATHED = 0x33FA, + CMSG_SET_SORT_BAGS_RIGHT_TO_LEFT = 0x3269, + CMSG_SET_SPECIALIZATION = 0x3122, + CMSG_SET_TAXI_BENCHMARK_MODE = 0x345D, + CMSG_SET_TITLE = 0x31D4, + CMSG_SET_TRADE_CURRENCY = 0x30DE, + CMSG_SET_TRADE_GOLD = 0x30DD, + CMSG_SET_TRADE_ITEM = 0x30DB, + CMSG_SET_USING_PARTY_GARRISON = 0x322F, + CMSG_SET_WATCHED_FACTION = 0x344A, + CMSG_SHOWING_CLOAK = 0x3456, + CMSG_SHOWING_HELM = 0x3455, + CMSG_SHOW_TRADE_SKILL = 0x3650, + CMSG_SIGN_PETITION = 0x3499, + CMSG_SILENCE_PARTY_TALKER = 0x35D9, + CMSG_SOCKET_GEMS = 0x3453, + CMSG_SORT_BAGS = 0x326B, + CMSG_SORT_BANK_BAGS = 0x326C, + CMSG_SORT_REAGENT_BANK_BAGS = 0x326D, + CMSG_SPELL_CLICK = 0x3407, + CMSG_SPIRIT_HEALER_ACTIVATE = 0x3423, + CMSG_SPLIT_ITEM = 0x391C, + CMSG_STAND_STATE_CHANGE = 0x3106, + CMSG_START_SPECTATOR_WAR_GAME = 0x355F, + CMSG_START_WAR_GAME = 0x355E, + CMSG_SUMMON_RESPONSE = 0x35FA, + CMSG_SUPPORT_TICKET_SUBMIT_BUG = 0x35CC, + CMSG_SUPPORT_TICKET_SUBMIT_COMPLAINT = 0x35CB, + CMSG_SUPPORT_TICKET_SUBMIT_SUGGESTION = 0x35CD, + CMSG_SUSPEND_COMMS_ACK = 0x36E2, + CMSG_SUSPEND_TOKEN_RESPONSE = 0x36E7, + CMSG_SWAP_INV_ITEM = 0x391B, + CMSG_SWAP_ITEM = 0x391A, + CMSG_SWAP_SUB_GROUPS = 0x35D4, + CMSG_SWAP_VOID_ITEM = 0x311C, + CMSG_TABARD_VENDOR_ACTIVATE = 0x31F5, + CMSG_TALK_TO_GOSSIP = 0x3404, + CMSG_TAXI_NODE_STATUS_QUERY = 0x341C, + CMSG_TAXI_QUERY_AVAILABLE_NODES = 0x341E, + CMSG_TAXI_REQUEST_EARLY_LANDING = 0x3420, + CMSG_TELEPORT_TO_UNIT = 0x35F1, + CMSG_TIME_ADJUSTMENT_RESPONSE = 0x39B3, + CMSG_TIME_SYNC_RESPONSE = 0x39B0, + CMSG_TIME_SYNC_RESPONSE_DROPPED = 0x39B2, + CMSG_TIME_SYNC_RESPONSE_FAILED = 0x39B1, + CMSG_TOGGLE_DIFFICULTY = 0x35E1, + CMSG_TOGGLE_PVP = 0x31F7, + CMSG_TOTEM_DESTROYED = 0x3464, + CMSG_TOY_SET_FAVORITE = 0x35B9, + CMSG_TRAINER_BUY_SPELL = 0x3422, + CMSG_TRAINER_LIST = 0x3421, + CMSG_TRANSMOGRIFY_ITEMS = 0x310F, + CMSG_TURN_IN_PETITION = 0x349B, + CMSG_TUTORIAL = 0x366B, + CMSG_TWITTER_CHECK_STATUS = 0x30A8, + CMSG_TWITTER_CONNECT = 0x30A5, + CMSG_TWITTER_DISCONNECT = 0x30A9, + CMSG_TWITTER_POST = 0x326F, + CMSG_UI_TIME_REQUEST = 0x362A, + CMSG_UNACCEPT_TRADE = 0x30D9, + CMSG_UNDELETE_CHARACTER = 0x366D, + CMSG_UNLEARN_SKILL = 0x344D, + CMSG_UNLEARN_SPECIALIZATION = 0x311D, + CMSG_UNLOCK_VOID_STORAGE = 0x3119, + CMSG_UPDATE_ACCOUNT_DATA = 0x3626, + CMSG_UPDATE_CLIENT_SETTINGS = 0x35F4, + CMSG_UPDATE_MISSILE_TRAJECTORY = 0x39B6, + CMSG_UPDATE_RAID_TARGET = 0x35D7, + CMSG_UPDATE_VAS_PURCHASE_STATES = 0x3682, + CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST = 0x367E, + CMSG_UPDATE_WOW_TOKEN_COUNT = 0x3674, + CMSG_UPGRADE_GARRISON = 0x3208, + CMSG_UPGRADE_ITEM = 0x3187, + CMSG_USED_FOLLOW = 0x3103, + CMSG_USE_CRITTER_ITEM = 0x319E, + CMSG_USE_EQUIPMENT_SET = 0x3913, + CMSG_USE_ITEM = 0x31E5, + CMSG_USE_TOY = 0x31E7, + CMSG_VIOLENCE_LEVEL = 0x3101, + CMSG_VOICE_ADD_IGNORE = 0x35DD, + CMSG_VOICE_DEL_IGNORE = 0x35DE, + CMSG_VOICE_SESSION_ENABLE = 0x3613, + CMSG_VOID_STORAGE_TRANSFER = 0x311B, + CMSG_WARDEN_DATA = 0x356C, + CMSG_WHO = 0x3611, + CMSG_WHO_IS = 0x3610, + CMSG_WORLD_PORT_RESPONSE = 0x3578, + CMSG_WORLD_TELEPORT = 0x3562, + CMSG_WRAP_ITEM = 0x3912, }; enum OpcodeServer : uint32 { - SMSG_ABORT_NEW_WORLD = 0x0E7C, - SMSG_ACCOUNT_CRITERIA_UPDATE = 0x1A7F, - SMSG_ACCOUNT_DATA_TIMES = 0x1773, - SMSG_ACCOUNT_MOUNT_UPDATE = 0x1350, - SMSG_ACCOUNT_TOYS_UPDATE = 0x1B44, - SMSG_ACHIEVEMENT_DELETED = 0x1B63, - SMSG_ACHIEVEMENT_EARNED = 0x0BE4, - SMSG_ACTIVATE_TAXI_REPLY = 0x1A54, - SMSG_ADDON_INFO = 0x026F, - SMSG_ADD_BATTLENET_FRIEND_RESPONSE = 0x1353, - SMSG_ADD_ITEM_PASSIVE = 0x1358, - SMSG_ADD_LOSS_OF_CONTROL = 0x1754, - SMSG_ADD_RUNE_POWER = 0x0367, - SMSG_ADJUST_SPLINE_DURATION = 0x0F57, - SMSG_AE_LOOT_TARGETS = 0x0BF0, - SMSG_AE_LOOT_TARGET_ACK = 0x06DC, - SMSG_AI_REACTION = 0x135C, - SMSG_ALL_ACCOUNT_CRITERIA = 0x0A60, - SMSG_ALL_ACHIEVEMENT_DATA = 0x1B50, - SMSG_ALL_GUILD_ACHIEVEMENTS = 0x154F, - SMSG_ARCHAEOLOGY_SURVERY_CAST = 0x1BC4, - SMSG_AREA_SPIRIT_HEALER_TIME = 0x024C, - SMSG_AREA_TRIGGER_DENIED = 0x03DF, - SMSG_AREA_TRIGGER_NO_CORPSE = 0x1B43, - SMSG_AREA_TRIGGER_RE_PATH = 0x065C, - SMSG_AREA_TRIGGER_RE_SHAPE = 0x127B, - SMSG_ARENA_ERROR = 0x02F3, - SMSG_ARENA_PREP_OPPONENT_SPECIALIZATIONS = 0x0F78, - SMSG_ATTACKER_STATE_UPDATE = 0x0ACF, - SMSG_ATTACK_START = 0x12CC, - SMSG_ATTACK_STOP = 0x0F6B, - SMSG_ATTACK_SWING_ERROR = 0x1A78, - SMSG_ATTACK_SWING_LANDED_LOG = 0x16DB, - SMSG_AUCTION_CLOSED_NOTIFICATION = 0x1BE0, - SMSG_AUCTION_COMMAND_RESULT = 0x12F7, - SMSG_AUCTION_HELLO_RESPONSE = 0x0E57, - SMSG_AUCTION_LIST_BIDDER_ITEMS_RESULT = 0x027C, - SMSG_AUCTION_LIST_ITEMS_RESULT = 0x1243, - SMSG_AUCTION_LIST_OWNER_ITEMS_RESULT = 0x0BCC, - SMSG_AUCTION_LIST_PENDING_SALES_RESULT = 0x1BEF, - SMSG_AUCTION_OUTBID_NOTIFICATION = 0x1ACB, - SMSG_AUCTION_OWNER_BID_NOTIFICATION = 0x02D7, - SMSG_AUCTION_REPLICATE_RESPONSE = 0x0BD4, - SMSG_AUCTION_WON_NOTIFICATION = 0x0A5C, - SMSG_AURA_POINTS_DEPLETED = 0x00B0, - SMSG_AURA_UPDATE = 0x10AF, - SMSG_AUTH_CHALLENGE = 0x0307, - SMSG_AUTH_RESPONSE = 0x1357, - SMSG_AVAILABLE_VOICE_CHANNEL = 0x0205, - SMSG_BARBER_SHOP_RESULT = 0x1348, - SMSG_BATTLEFIELD_LIST = 0x0FEF, - SMSG_BATTLEFIELD_PORT_DENIED = 0x0B70, - SMSG_BATTLEFIELD_STATUS_ACTIVE = 0x1AE4, - SMSG_BATTLEFIELD_STATUS_FAILED = 0x0643, - SMSG_BATTLEFIELD_STATUS_NEED_CONFIRMATION = 0x0370, - SMSG_BATTLEFIELD_STATUS_NONE = 0x165C, - SMSG_BATTLEFIELD_STATUS_QUEUED = 0x0ADB, - SMSG_BATTLEFIELD_STATUS_WAIT_FOR_GROUPS = 0x175C, - SMSG_BATTLEGROUND_INFO_THROTTLED = 0x1273, - SMSG_BATTLEGROUND_INIT = 0x0AEC, - SMSG_BATTLEGROUND_PLAYER_JOINED = 0x0E50, - SMSG_BATTLEGROUND_PLAYER_LEFT = 0x1377, - SMSG_BATTLEGROUND_PLAYER_POSITIONS = 0x16D8, - SMSG_BATTLEGROUND_POINTS = 0x07F7, - SMSG_BATTLENET_CHALLENGE_ABORT = 0x0648, - SMSG_BATTLENET_CHALLENGE_START = 0x0657, - SMSG_BATTLE_PAY_ACK_FAILED = 0x17DF, - SMSG_BATTLE_PAY_CONFIRM_PURCHASE = 0x16DC, - SMSG_BATTLE_PAY_DELIVERY_ENDED = 0x0263, - SMSG_BATTLE_PAY_DELIVERY_STARTED = 0x0E78, - SMSG_BATTLE_PAY_DISTRIBUTION_UPDATE = 0x0BEF, - SMSG_BATTLE_PAY_GET_DISTRIBUTION_LIST_RESPONSE = 0x17F0, - SMSG_BATTLE_PAY_GET_PRODUCT_LIST_RESPONSE = 0x1674, - SMSG_BATTLE_PAY_GET_PURCHASE_LIST_RESPONSE = 0x0A6B, - SMSG_BATTLE_PAY_PURCHASE_UPDATE = 0x0A5B, - SMSG_BATTLE_PAY_START_DISTRIBUTION_ASSIGN_TO_TARGET_RESPONSE = 0x1B70, - SMSG_BATTLE_PAY_START_PURCHASE_RESPONSE = 0x0BC3, - SMSG_BATTLE_PETS_HEALED = 0x1B5F, - SMSG_BATTLE_PET_CAGE_DATE_ERROR = 0x1A74, - SMSG_BATTLE_PET_DELETED = 0x17EC, - SMSG_BATTLE_PET_ERROR = 0x1A7C, - SMSG_BATTLE_PET_JOURNAL = 0x13E7, - SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED = 0x1BCB, - SMSG_BATTLE_PET_JOURNAL_LOCK_DENIED = 0x13D7, - SMSG_BATTLE_PET_LICENSE_CHANGED = 0x0247, - SMSG_BATTLE_PET_RESTORED = 0x12DF, - SMSG_BATTLE_PET_REVOKED = 0x0E47, - SMSG_BATTLE_PET_TRAP_LEVEL = 0x13FB, - SMSG_BATTLE_PET_UPDATES = 0x02FF, - SMSG_BF_MGR_DROP_TIMER_CANCELLED = 0x0EC7, - SMSG_BF_MGR_DROP_TIMER_STARTED = 0x025F, - SMSG_BF_MGR_EJECTED = 0x1E43, - SMSG_BF_MGR_EJECT_PENDING = 0x0747, - SMSG_BF_MGR_ENTERING = 0x1AD0, - SMSG_BF_MGR_ENTRY_INVITE = 0x02FB, - SMSG_BF_MGR_QUEUE_INVITE = 0x1A48, - SMSG_BF_MGR_QUEUE_REQUEST_RESPONSE = 0x0B4F, - SMSG_BF_MGR_QUEUE_STATUS_UPDATE = 0x07FF, - SMSG_BF_MGR_STATE_CHANGED = 0x0EE8, - SMSG_BINDER_CONFIRM = 0x0A58, - SMSG_BIND_POINT_UPDATE = 0x075B, - SMSG_BLACK_MARKET_BID_ON_ITEM_RESULT = 0x07E0, - SMSG_BLACK_MARKET_OPEN_RESULT = 0x1760, - SMSG_BLACK_MARKET_OUTBID = 0x164F, - SMSG_BLACK_MARKET_REQUEST_ITEMS_RESULT = 0x0B68, - SMSG_BLACK_MARKET_WON = 0x1780, - SMSG_BONUS_ROLL_EMPTY = 0x1E44, - SMSG_BOSS_KILL_CREDIT = 0x1743, - SMSG_BREAK_TARGET = 0x1B00, - SMSG_BUY_FAILED = 0x1258, - SMSG_BUY_SUCCEEDED = 0x0357, - SMSG_CACHE_VERSION = 0x1747, - SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x02DC, - SMSG_CALENDAR_COMMAND_RESULT = 0x0258, - SMSG_CALENDAR_EVENT_INITIAL_INVITES = 0x0777, - SMSG_CALENDAR_EVENT_INVITE = 0x02D0, - SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x16C4, - SMSG_CALENDAR_EVENT_INVITE_MODERATOR_STATUS = 0x0244, - SMSG_CALENDAR_EVENT_INVITE_NOTES = 0x0E70, - SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT = 0x1748, - SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x0AFB, - SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x06E3, - SMSG_CALENDAR_EVENT_INVITE_STATUS = 0x1B68, - SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x0280, - SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x0BD7, - SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x02D8, - SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x0AD0, - SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x0AC4, - SMSG_CALENDAR_RAID_LOCKOUT_UPDATED = 0x1AC3, - SMSG_CALENDAR_SEND_CALENDAR = 0x0F00, - SMSG_CALENDAR_SEND_EVENT = 0x12F8, - SMSG_CALENDAR_SEND_NUM_PENDING = 0x03C8, - SMSG_CAMERA_SHAKE = 0x07CC, - SMSG_CANCEL_AUTO_REPEAT = 0x1800, - SMSG_CANCEL_COMBAT = 0x02DB, - SMSG_CANCEL_ORPHAN_SPELL_VISUAL = 0x11F8, - SMSG_CANCEL_SCENE = 0x0BE3, - SMSG_CANCEL_SPELL_VISUAL = 0x1440, - SMSG_CANCEL_SPELL_VISUAL_KIT = 0x0167, - SMSG_CAN_DUEL_RESULT = 0x16FB, - SMSG_CAST_FAILED = 0x1138, - SMSG_CATEGORY_COOLDOWN = 0x00FB, - SMSG_CHALLEGE_MODE_REWARDS = 0x1A67, - SMSG_CHALLENGE_MODE_ALL_MAP_STATS = 0x1A58, - SMSG_CHALLENGE_MODE_COMPLETE = 0x0773, - SMSG_CHALLENGE_MODE_MAP_STATS_UPDATE = 0x1B80, - SMSG_CHALLENGE_MODE_NEW_PLAYER_RECORD = 0x067C, - SMSG_CHALLENGE_MODE_REQUEST_LEADERS_RESULT = 0x0FE7, - SMSG_CHALLENGE_MODE_RESET = 0x07DC, - SMSG_CHALLENGE_MODE_START = 0x07CF, - SMSG_CHANGE_PLAYER_DIFFICULTY_RESULT = 0x066C, - SMSG_CHANNEL_LIST = 0x0E05, - SMSG_CHANNEL_NOTIFY = 0x038E, - SMSG_CHANNEL_NOTIFY_JOINED = 0x020D, - SMSG_CHANNEL_NOTIFY_LEFT = 0x0685, - SMSG_CHARACTER_LOGIN_FAILED = 0x02C7, - SMSG_CHARACTER_OBJECT_TEST_RESPONSE = 0x1AF0, - SMSG_CHARACTER_RENAME_RESULT = 0x0264, - SMSG_CHARACTER_UPGRADE_CHARACTER_CHOSEN = 0x07C4, - SMSG_CHARACTER_UPGRADE_COMPLETE = 0x1764, - SMSG_CHARACTER_UPGRADE_SPELL_TIER_SET = 0x07EC, - SMSG_CHARACTER_UPGRADE_STARTED = 0x02C8, - SMSG_CHAR_CUSTOMIZE = 0x1263, - SMSG_CHAR_CUSTOMIZE_FAILED = 0x1B6B, - SMSG_CHAR_FACTION_CHANGE_RESULT = 0x0EF8, - SMSG_CHAT = 0x068D, - SMSG_CHAT_AUTO_RESPONDED = 0x0282, - SMSG_CHAT_DOWN = 0x0B0A, - SMSG_CHAT_IGNORED_ACCOUNT_MUTED = 0x0B0D, - SMSG_CHAT_IS_DOWN = 0x0381, - SMSG_CHAT_NOT_IN_PARTY = 0x038D, - SMSG_CHAT_PLAYER_AMBIGUOUS = 0x0A85, - SMSG_CHAT_PLAYER_NOTFOUND = 0x0A0D, - SMSG_CHAT_RECONNECT = 0x0609, - SMSG_CHAT_RESTRICTED = 0x0B01, - SMSG_CHAT_SERVER_MESSAGE = 0x0A01, - SMSG_CHEAT_IGNORE_DIMISHING_RETURNS = 0x0563, - SMSG_CHECK_WARGAME_ENTRY = 0x16F4, - SMSG_CLEAR_ALL_SPELL_CHARGES = 0x10B3, - SMSG_CLEAR_BOSS_EMOTES = 0x0FE8, - SMSG_CLEAR_COOLDOWN = 0x0AC3, - SMSG_CLEAR_COOLDOWNS = 0x0580, - SMSG_CLEAR_LOSS_OF_CONTROL = 0x07EB, - SMSG_CLEAR_SPELL_CHARGES = 0x10F3, - SMSG_CLEAR_TARGET = 0x0E44, - SMSG_COIN_REMOVED = 0x02E4, - SMSG_COMBAT_EVENT_FAILED = 0x06C3, - SMSG_COMMENTATOR_MAP_INFO = 0x0B44, - SMSG_COMMENTATOR_PLAYER_INFO = 0x0B64, - SMSG_COMMENTATOR_STATE_CHANGED = 0x07DF, - SMSG_COMPLAINT_RESULT = 0x0F80, - SMSG_COMPLETE_SHIPMENT_RESPONSE = 0x0E6C, - SMSG_CONNECT_TO = 0x0284, - SMSG_CONQUEST_FORMULA_CONSTANTS = 0x026C, - SMSG_CONSOLE_WRITE = 0x067F, - SMSG_CONTACT_LIST = 0x1A6F, - SMSG_CONTROL_UPDATE = 0x07D0, - SMSG_CONVERT_RUNE = 0x0368, - SMSG_COOLDOWN_CHEAT = 0x1658, - SMSG_COOLDOWN_EVENT = 0x0BDB, - SMSG_CORPSE_LOCATION = 0x12C3, - SMSG_CORPSE_RECLAIM_DELAY = 0x1BC7, - SMSG_CORPSE_TRANSPORT_QUERY = 0x03EC, - SMSG_CREATE_CHAR = 0x0B5B, - SMSG_CREATE_SHIPMENT_RESPONSE = 0x0EFF, - SMSG_CRITERIA_DELETED = 0x0E53, - SMSG_CRITERIA_UPDATE = 0x0667, - SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x12EF, - SMSG_CUSTOM_LOAD_SCREEN = 0x177C, - SMSG_DAILY_QUESTS_RESET = 0x112D, - SMSG_DAMAGE_CALC_LOG = 0x03F8, - SMSG_DANCE_STUDIO_CREATE_RESULT = 0x1280, - SMSG_DB_REPLY = 0x0E7B, - SMSG_DEATH_RELEASE_LOC = 0x12FF, - SMSG_DEFENSE_MESSAGE = 0x0686, - SMSG_DELETE_CHAR = 0x13DF, - SMSG_DESTROY_ARENA_UNIT = 0x037B, - SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x03CC, - SMSG_DIFFERENT_INSTANCE_FROM_PARTY = 0x0BE7, - SMSG_DISENCHANT_CREDIT = 0x0BD8, - SMSG_DISMOUNT = 0x0AE0, - SMSG_DISMOUNT_RESULT = 0x0680, - SMSG_DISPEL_FAILED = 0x0073, - SMSG_DISPLAY_GAME_ERROR = 0x13EF, - SMSG_DISPLAY_PLAYER_CHOICE = 0x1BEB, - SMSG_DISPLAY_PROMOTION = 0x164C, - SMSG_DISPLAY_QUEST_POPUP = 0x0631, - SMSG_DISPLAY_TOAST = 0x13C4, - SMSG_DONT_AUTO_PUSH_SPELLS_TO_ACTION_BAR = 0x1274, - SMSG_DROP_NEW_CONNECTION = 0x0228, - SMSG_DUEL_COMPLETE = 0x0B6F, - SMSG_DUEL_COUNTDOWN = 0x03E8, - SMSG_DUEL_IN_BOUNDS = 0x0AF4, - SMSG_DUEL_OUT_OF_BOUNDS = 0x1254, - SMSG_DUEL_REQUESTED = 0x07FB, - SMSG_DUEL_WINNER = 0x0B78, - SMSG_DURABILITY_DAMAGE_DEATH = 0x1AD8, - SMSG_EMOTE = 0x06C4, - SMSG_ENABLE_BARBER_SHOP = 0x1774, - SMSG_ENCHANTMENT_LOG = 0x16CF, - SMSG_ENCOUNTER_END = 0x1AE8, - SMSG_ENCOUNTER_START = 0x0F5B, - SMSG_ENUM_CHARACTERS_RESULT = 0x17D8, - SMSG_ENVIRONMENTAL_DAMAGE_LOG = 0x10EC, - SMSG_EQUIPMENT_SET_ID = 0x1AC7, - SMSG_EXPECTED_SPAM_RECORDS = 0x0386, - SMSG_EXPLORATION_EXPERIENCE = 0x0780, - SMSG_FACTION_BONUS_INFO = 0x1248, - SMSG_FAILED_PLAYER_CONDITION = 0x035C, - SMSG_FEATURE_SYSTEM_STATUS = 0x1AC4, - SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN = 0x0753, - SMSG_FEIGN_DEATH_RESISTED = 0x174B, - SMSG_FISH_ESCAPED = 0x0AF0, - SMSG_FISH_NOT_HOOKED = 0x13FF, - SMSG_FLIGHT_SPLINE_SYNC = 0x09E1, - SMSG_FORCED_DEATH_UPDATE = 0x074C, - SMSG_FORCE_ANIM = 0x0E4B, - SMSG_FORCE_OBJECT_RELINK = 0x0A4B, - SMSG_FRIEND_STATUS = 0x17EB, - SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT = 0x0EDC, - SMSG_GAME_OBJECT_CUSTOM_ANIM = 0x1ACC, - SMSG_GAME_OBJECT_DESPAWN = 0x137F, - SMSG_GAME_OBJECT_PLAY_SPELL_VISUAL = 0x0473, - SMSG_GAME_OBJECT_PLAY_SPELL_VISUAL_KIT = 0x10E3, - SMSG_GAME_OBJECT_RESET_STATE = 0x02EB, - SMSG_GAME_OBJECT_UI_ACTION = 0x17CB, - SMSG_GAME_SPEED_SET = 0x0678, - SMSG_GAME_TIME_SET = 0x1768, - SMSG_GAME_TIME_UPDATE = 0x16F0, - SMSG_GARRISON_ADD_FOLLOWER_RESULT = 0x113A, - SMSG_GARRISON_ADD_MISSION_RESULT = 0x1135, - SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT = 0x1931, - SMSG_GARRISON_BUILDING_ACTIVATED = 0x151A, - SMSG_GARRISON_BUILDING_LANDMARKS = 0x14B6, - SMSG_GARRISON_BUILDING_REMOVED = 0x113D, - SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT = 0x199E, - SMSG_GARRISON_CLEAR_ALL_FOLLOWERS_EXHAUSTION = 0x1436, - SMSG_GARRISON_COMPLETE_MISSION_RESULT = 0x189E, - SMSG_GARRISON_CREATE_RESULT = 0x1519, - SMSG_GARRISON_DELETE_RESULT = 0x1836, - SMSG_GARRISON_FOLLOWER_CHANGED_ABILITIES = 0x1119, - SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL = 0x1111, - SMSG_GARRISON_FOLLOWER_CHANGED_STATUS = 0x1532, - SMSG_GARRISON_FOLLOWER_CHANGED_XP = 0x1599, - SMSG_GARRISON_IS_UPGRADEABLE_RESULT = 0x10BA, - SMSG_GARRISON_LANDING_PAGE_SHIPMENT_INFO = 0x1AF7, - SMSG_GARRISON_LEARN_BLUEPRINT_RESULT = 0x1819, - SMSG_GARRISON_LEARN_SPECIALIZATION_RESULT = 0x1095, - SMSG_GARRISON_LIST_FOLLOWERS_CHEAT_RESULT = 0x1996, - SMSG_GARRISON_LIST_MISSIONS_CHEAT_RESULT = 0x183E, - SMSG_GARRISON_MISSION_AREA_BONUS_ADDED = 0x143D, - SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT = 0x14B2, - SMSG_GARRISON_MISSION_UPDATE_CAN_START = 0x18BE, - SMSG_GARRISON_NUM_FOLLOWER_ACTIVATIONS_REMAINING = 0x1832, - SMSG_GARRISON_OPEN_ARCHITECT = 0x1195, - SMSG_GARRISON_OPEN_MISSION_NPC = 0x159A, - SMSG_GARRISON_OPEN_RECRUITMENT_NPC = 0x1C12, - SMSG_GARRISON_OPEN_TRADESKILL_NPC = 0x141E, - SMSG_GARRISON_PLACE_BUILDING_RESULT = 0x1992, - SMSG_GARRISON_PLOT_PLACED = 0x1191, - SMSG_GARRISON_PLOT_REMOVED = 0x1C16, - SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME = 0x14B5, - SMSG_GARRISON_RECALL_PORTAL_USED = 0x1516, - SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED = 0x159E, - SMSG_GARRISON_RECRUIT_FOLLOWER_RESULT = 0x111D, - SMSG_GARRISON_REMOTE_INFO = 0x1811, - SMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING_RESULT = 0x1036, - SMSG_GARRISON_REMOVE_FOLLOWER_RESULT = 0x18B5, - SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT = 0x1491, - SMSG_GARRISON_START_MISSION_RESULT = 0x1C1A, - SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT = 0x141D, - SMSG_GARRISON_UPGRADE_RESULT = 0x181E, - SMSG_GENERATE_RANDOM_CHARACTER_NAME_RESULT = 0x13F7, - SMSG_GET_ACCOUNT_CHARACTER_LIST_RESULT = 0x03CB, - SMSG_GET_DISPLAYED_TROPHY_LIST_RESPONSE = 0x18B2, - SMSG_GET_GARRISON_INFO_RESULT = 0x1196, - SMSG_GET_SHIPMENTS_OF_TYPE_RESPONSE = 0x17FB, - SMSG_GET_SHIPMENT_INFO_RESPONSE = 0x0BF7, - SMSG_GET_TROPHY_LIST_RESPONSE = 0x1648, - SMSG_GM_PLAYER_INFO = 0x1400, - SMSG_GM_REQUEST_PLAYER_INFO = 0x074F, - SMSG_GM_TICKET_CASE_STATUS = 0x17C7, - SMSG_GM_TICKET_SYSTEM_STATUS = 0x1680, - SMSG_GOD_MODE = 0x074B, - SMSG_GOSSIP_COMPLETE = 0x15A2, - SMSG_GOSSIP_MESSAGE = 0x0351, - SMSG_GOSSIP_POI = 0x174C, - SMSG_GROUP_ACTION_THROTTLED = 0x0AFC, - SMSG_GROUP_DECLINE = 0x1667, - SMSG_GROUP_DESTROYED = 0x02EC, - SMSG_GROUP_NEW_LEADER = 0x1AF3, - SMSG_GROUP_UNINVITE = 0x176C, - SMSG_GUILD_ACHIEVEMENT_DELETED = 0x1448, - SMSG_GUILD_ACHIEVEMENT_EARNED = 0x1543, - SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0x1498, - SMSG_GUILD_BANK_LOG_QUERY_RESULTS = 0x1413, - SMSG_GUILD_BANK_QUERY_RESULTS = 0x140B, - SMSG_GUILD_BANK_REMAINING_WITHDRAW_MONEY = 0x1483, - SMSG_GUILD_BANK_TEXT_QUERY_RESULT = 0x155C, - SMSG_GUILD_CHALLENGE_COMPLETED = 0x1497, - SMSG_GUILD_CHALLENGE_UPDATE = 0x140F, - SMSG_GUILD_CHANGE_NAME_RESULT = 0x14CB, - SMSG_GUILD_COMMAND_RESULT = 0x150B, - SMSG_GUILD_CRITERIA_DELETED = 0x1508, - SMSG_GUILD_CRITERIA_UPDATE = 0x145F, - SMSG_GUILD_EVENT_BANK_CONTENTS_CHANGED = 0x1554, - SMSG_GUILD_EVENT_BANK_MONEY_CHANGED = 0x1418, - SMSG_GUILD_EVENT_DISBANDED = 0x1490, - SMSG_GUILD_EVENT_LOG_QUERY_RESULTS = 0x1457, - SMSG_GUILD_EVENT_MOTD = 0x14CF, - SMSG_GUILD_EVENT_NEW_LEADER = 0x1417, - SMSG_GUILD_EVENT_PLAYER_JOINED = 0x1514, - SMSG_GUILD_EVENT_PLAYER_LEFT = 0x14D3, - SMSG_GUILD_EVENT_PRESENCE_CHANGE = 0x151F, - SMSG_GUILD_EVENT_RANKS_UPDATED = 0x1560, - SMSG_GUILD_EVENT_RANK_CHANGED = 0x14C4, - SMSG_GUILD_EVENT_TAB_ADDED = 0x1513, - SMSG_GUILD_EVENT_TAB_DELETED = 0x14E0, - SMSG_GUILD_EVENT_TAB_MODIFIED = 0x149C, - SMSG_GUILD_EVENT_TAB_TEXT_CHANGED = 0x1558, - SMSG_GUILD_FLAGGED_FOR_RENAME = 0x145B, - SMSG_GUILD_INVITE = 0x155F, - SMSG_GUILD_INVITE_DECLINED = 0x1454, - SMSG_GUILD_INVITE_EXPIRED = 0x1520, - SMSG_GUILD_KNOWN_RECIPES = 0x1407, - SMSG_GUILD_MEMBERS_WITH_RECIPE = 0x1420, - SMSG_GUILD_MEMBER_DAILY_RESET = 0x150C, - SMSG_GUILD_MEMBER_RECIPES = 0x1458, - SMSG_GUILD_MEMBER_UPDATE_NOTE = 0x1414, - SMSG_GUILD_MOVED = 0x1553, - SMSG_GUILD_MOVE_STARTING = 0x1488, - SMSG_GUILD_NAME_CHANGED = 0x14D4, - SMSG_GUILD_NEWS = 0x1557, - SMSG_GUILD_NEWS_DELETED = 0x1487, - SMSG_GUILD_PARTY_STATE = 0x151C, - SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0x1544, - SMSG_GUILD_RANKS = 0x150F, - SMSG_GUILD_REPUTATION_REACTION_CHANGED = 0x141B, - SMSG_GUILD_RESET = 0x155B, - SMSG_GUILD_REWARD_LIST = 0x1410, - SMSG_GUILD_ROSTER = 0x1408, - SMSG_GUILD_ROSTER_UPDATE = 0x1517, - SMSG_GUILD_SEND_RANK_CHANGE = 0x149F, - SMSG_HEALTH_UPDATE = 0x0B58, - SMSG_HIGHEST_THREAT_UPDATE = 0x0F53, - SMSG_HOTFIX_NOTIFY = 0x0BEC, - SMSG_HOTFIX_NOTIFY_BLOB = 0x0748, - SMSG_INCREASE_CAST_TIME_FOR_SPELL = 0x1163, - SMSG_INITIALIZE_FACTIONS = 0x0EC4, - SMSG_INITIAL_SETUP = 0x07F0, - SMSG_INIT_WORLD_STATES = 0x0770, - SMSG_INSPECT_HONOR_STATS = 0x1B77, - SMSG_INSPECT_PVP = 0x065F, - SMSG_INSPECT_RESULT = 0x0F7B, - SMSG_INSTANCE_ENCOUNTER_CHANGE_PRIORITY = 0x06E7, - SMSG_INSTANCE_ENCOUNTER_DISENGAGE_UNIT = 0x12D4, - SMSG_INSTANCE_ENCOUNTER_END = 0x02C4, - SMSG_INSTANCE_ENCOUNTER_ENGAGE_UNIT = 0x06D4, - SMSG_INSTANCE_ENCOUNTER_GAIN_COMBAT_RESURRECTION_CHARGE = 0x0B54, - SMSG_INSTANCE_ENCOUNTER_IN_COMBAT_RESURRECTION = 0x0253, - SMSG_INSTANCE_ENCOUNTER_OBJECTIVE_COMPLETE = 0x06F8, - SMSG_INSTANCE_ENCOUNTER_OBJECTIVE_START = 0x0400, - SMSG_INSTANCE_ENCOUNTER_OBJECTIVE_UPDATE = 0x0EEB, - SMSG_INSTANCE_ENCOUNTER_PHASE_SHIFT_CHANGED = 0x1374, - SMSG_INSTANCE_ENCOUNTER_START = 0x0B53, - SMSG_INSTANCE_ENCOUNTER_TIMER_START = 0x0350, - SMSG_INSTANCE_GROUP_SIZE_CHANGED = 0x0E77, - SMSG_INSTANCE_INFO = 0x0AE8, - SMSG_INSTANCE_RESET = 0x07E3, - SMSG_INSTANCE_RESET_FAILED = 0x17D4, - SMSG_INSTANCE_SAVE_CREATED = 0x0ED4, - SMSG_INVALIDATE_PLAYER = 0x166B, - SMSG_INVALID_PROMOTION_CODE = 0x0AF8, - SMSG_INVENTORY_CHANGE_FAILURE = 0x1268, - SMSG_IS_QUEST_COMPLETE_RESPONSE = 0x1D26, - SMSG_ITEM_CHANGED = 0x1744, - SMSG_ITEM_COOLDOWN = 0x0E5C, - SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x1A50, - SMSG_ITEM_EXPIRE_PURCHASE_REFUND = 0x1A7B, - SMSG_ITEM_PURCHASE_REFUND_RESULT = 0x126C, - SMSG_ITEM_PUSH_RESULT = 0x1370, - SMSG_ITEM_TIME_UPDATE = 0x13EC, - SMSG_KICK_REASON = 0x0EFB, - SMSG_LEARNED_SPELLS = 0x05A7, - SMSG_LEARN_TALENT_FAILED = 0x0E43, - SMSG_LEVEL_UP_INFO = 0x1643, - SMSG_LFG_BOOT_PLAYER = 0x100F, - SMSG_LFG_DISABLED = 0x108B, - SMSG_LFG_JOIN_RESULT = 0x114F, - SMSG_LFG_LIST_JOIN_RESULT = 0x109F, - SMSG_LFG_LIST_SEARCH_RESULTS = 0x110B, - SMSG_LFG_LIST_SEARCH_STATUS = 0x1008, - SMSG_LFG_LIST_UPDATE_BLACKLIST = 0x1048, - SMSG_LFG_LIST_UPDATE_STATUS = 0x1157, - SMSG_LFG_OFFER_CONTINUE = 0x1060, - SMSG_LFG_PARTY_INFO = 0x1097, - SMSG_LFG_PLAYER_INFO = 0x1187, - SMSG_LFG_PLAYER_REWARD = 0x1103, - SMSG_LFG_PROPOSAL_UPDATE = 0x110F, - SMSG_LFG_QUEUE_STATUS = 0x1117, - SMSG_LFG_READY_CHECK_RESULT = 0x115B, - SMSG_LFG_READY_CHECK_UPDATE = 0x1007, - SMSG_LFG_ROLE_CHECK_UPDATE = 0x1058, - SMSG_LFG_SEARCH_RESULTS = 0x1014, - SMSG_LFG_SLOT_INVALID = 0x101B, - SMSG_LFG_TELEPORT_DENIED = 0x1053, - SMSG_LFG_UPDATE_STATUS = 0x1010, - SMSG_LF_GUILD_APPLICANT_LIST_CHANGED = 0x1587, - SMSG_LF_GUILD_APPLICATIONS = 0x1460, - SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED = 0x1503, - SMSG_LF_GUILD_BROWSE = 0x154C, - SMSG_LF_GUILD_COMMAND_RESULT = 0x148B, - SMSG_LF_GUILD_POST = 0x1450, - SMSG_LF_GUILD_RECRUITS = 0x1453, - SMSG_LIVE_REGION_ACCOUNT_RESTORE_RESULT = 0x0AC7, - SMSG_LIVE_REGION_CHARACTER_COPY_RESULT = 0x1E48, - SMSG_LIVE_REGION_GET_ACCOUNT_CHARACTER_LIST_RESULT = 0x0AEF, - SMSG_LOAD_CUF_PROFILES = 0x17C4, - SMSG_LOAD_EQUIPMENT_SET = 0x0360, - SMSG_LOAD_SELECTED_TROPHY_RESULT = 0x0BDC, - SMSG_LOGIN_SET_TIME_SPEED = 0x1BEC, - SMSG_LOGIN_VERIFY_WORLD = 0x12C8, - SMSG_LOGOUT_CANCEL_ACK = 0x17E4, - SMSG_LOGOUT_COMPLETE = 0x16EF, - SMSG_LOGOUT_RESPONSE = 0x0664, - SMSG_LOG_XP_GAIN = 0x12F4, - SMSG_LOOT_ALL_PASSED = 0x076B, - SMSG_LOOT_CONTENTS = 0x1B5C, - SMSG_LOOT_ITEM_LIST = 0x1AE7, - SMSG_LOOT_LIST = 0x16E4, - SMSG_LOOT_MONEY_NOTIFY = 0x167F, - SMSG_LOOT_RELEASE = 0x12E7, - SMSG_LOOT_RELEASE_ALL = 0x0FC4, - SMSG_LOOT_REMOVED = 0x03F4, - SMSG_LOOT_RESPONSE = 0x167B, - SMSG_LOOT_ROLL = 0x16C7, - SMSG_LOOT_ROLLS_COMPLETE = 0x034F, - SMSG_LOOT_ROLL_WON = 0x06EC, - SMSG_LOSS_OF_CONTROL_AURA_UPDATE = 0x0254, - SMSG_MAIL_COMMAND_RESULT = 0x06D0, - SMSG_MAIL_LIST_RESULT = 0x16EC, - SMSG_MAIL_QUERY_NEXT_TIME_RESULT = 0x136C, - SMSG_MAP_OBJECTIVES_INIT = 0x0BD3, - SMSG_MAP_OBJ_EVENTS = 0x16D0, - SMSG_MASTER_LOOT_CANDIDATE_LIST = 0x1A5C, - SMSG_MESSAGE_BOX = 0x1347, - SMSG_MINIMAP_PING = 0x1BFC, - SMSG_MIRROR_IMAGE_COMPONENTED_DATA = 0x01BF, - SMSG_MIRROR_IMAGE_CREATURE_DATA = 0x0540, - SMSG_MISSILE_CANCEL = 0x174F, - SMSG_MODIFY_COOLDOWN = 0x13C7, - SMSG_MOTD = 0x0206, - SMSG_MOUNT_RESULT = 0x16FC, - SMSG_MOVE_APPLY_MOVEMENT_FORCE = 0x0C62, - SMSG_MOVE_DISABLE_COLLISION = 0x0102, - SMSG_MOVE_DISABLE_GRAVITY = 0x0D02, - SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x0D3A, - SMSG_MOVE_ENABLE_COLLISION = 0x0576, - SMSG_MOVE_ENABLE_GRAVITY = 0x08ED, - SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x0906, - SMSG_MOVE_KNOCK_BACK = 0x0026, - SMSG_MOVE_REMOVE_MOVEMENT_FORCE = 0x01E2, - SMSG_MOVE_ROOT = 0x0471, - SMSG_MOVE_SET_ACTIVE_MOVER = 0x0175, - SMSG_MOVE_SET_CAN_FLY = 0x05E9, - SMSG_MOVE_SET_CAN_TURN_WHILE_FALLING = 0x00FA, - SMSG_MOVE_SET_COLLISION_HEIGHT = 0x086E, - SMSG_MOVE_SET_COMPOUND_STATE = 0x002D, - SMSG_MOVE_SET_FEATHER_FALL = 0x0425, - SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x0D0D, - SMSG_MOVE_SET_FLIGHT_SPEED = 0x08BD, - SMSG_MOVE_SET_HOVERING = 0x04EA, - SMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES = 0x05B5, - SMSG_MOVE_SET_LAND_WALK = 0x09A1, - SMSG_MOVE_SET_NORMAL_FALL = 0x00F6, - SMSG_MOVE_SET_PITCH_RATE = 0x042D, - SMSG_MOVE_SET_RUN_BACK_SPEED = 0x0875, - SMSG_MOVE_SET_RUN_SPEED = 0x04FD, - SMSG_MOVE_SET_SWIM_BACK_SPEED = 0x0D72, - SMSG_MOVE_SET_SWIM_SPEED = 0x0961, - SMSG_MOVE_SET_TURN_RATE = 0x0DB6, - SMSG_MOVE_SET_VEHICLE_REC_ID = 0x08E6, - SMSG_MOVE_SET_WALK_SPEED = 0x0872, - SMSG_MOVE_SET_WATER_WALK = 0x00F1, - SMSG_MOVE_SKIP_TIME = 0x0829, - SMSG_MOVE_SPLINE_DISABLE_COLLISION = 0x0C71, - SMSG_MOVE_SPLINE_DISABLE_GRAVITY = 0x0465, - SMSG_MOVE_SPLINE_ENABLE_COLLISION = 0x0062, - SMSG_MOVE_SPLINE_ENABLE_GRAVITY = 0x0171, - SMSG_MOVE_SPLINE_ROOT = 0x05E2, - SMSG_MOVE_SPLINE_SET_FEATHER_FALL = 0x08A6, - SMSG_MOVE_SPLINE_SET_FLIGHT_BACK_SPEED = 0x05F1, - SMSG_MOVE_SPLINE_SET_FLIGHT_SPEED = 0x0D01, - SMSG_MOVE_SPLINE_SET_FLYING = 0x0475, - SMSG_MOVE_SPLINE_SET_HOVER = 0x00ED, - SMSG_MOVE_SPLINE_SET_LAND_WALK = 0x04A6, - SMSG_MOVE_SPLINE_SET_NORMAL_FALL = 0x0C79, - SMSG_MOVE_SPLINE_SET_PITCH_RATE = 0x0D79, - SMSG_MOVE_SPLINE_SET_RUN_BACK_SPEED = 0x053A, - SMSG_MOVE_SPLINE_SET_RUN_MODE = 0x040E, - SMSG_MOVE_SPLINE_SET_RUN_SPEED = 0x0DE1, - SMSG_MOVE_SPLINE_SET_SWIM_BACK_SPEED = 0x0031, - SMSG_MOVE_SPLINE_SET_SWIM_SPEED = 0x05F2, - SMSG_MOVE_SPLINE_SET_TURN_RATE = 0x002A, - SMSG_MOVE_SPLINE_SET_WALK_MODE = 0x09AE, - SMSG_MOVE_SPLINE_SET_WALK_SPEED = 0x0401, - SMSG_MOVE_SPLINE_SET_WATER_WALK = 0x0865, - SMSG_MOVE_SPLINE_START_SWIM = 0x00BD, - SMSG_MOVE_SPLINE_STOP_SWIM = 0x01E9, - SMSG_MOVE_SPLINE_UNROOT = 0x0032, - SMSG_MOVE_SPLINE_UNSET_FLYING = 0x057E, - SMSG_MOVE_SPLINE_UNSET_HOVER = 0x0D4D, - SMSG_MOVE_TELEPORT = 0x0D2D, - SMSG_MOVE_UNROOT = 0x0876, - SMSG_MOVE_UNSET_CAN_FLY = 0x1006, - SMSG_MOVE_UNSET_CAN_TURN_WHILE_FALLING = 0x0DF9, - SMSG_MOVE_UNSET_HOVERING = 0x0535, - SMSG_MOVE_UNSET_IGNORE_MOVEMENT_FORCES = 0x0435, - SMSG_MOVE_UPDATE = 0x0439, - SMSG_MOVE_UPDATE_APPLY_MOVEMENT_FORCE = 0x007E, - SMSG_MOVE_UPDATE_COLLISION_HEIGHT = 0x0C0E, - SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED = 0x097D, - SMSG_MOVE_UPDATE_FLIGHT_SPEED = 0x0CA9, - SMSG_MOVE_UPDATE_KNOCK_BACK = 0x0CE2, - SMSG_MOVE_UPDATE_PITCH_RATE = 0x04FE, - SMSG_MOVE_UPDATE_REMOVE_MOVEMENT_FORCE = 0x0DF6, - SMSG_MOVE_UPDATE_RUN_BACK_SPEED = 0x100A, - SMSG_MOVE_UPDATE_RUN_SPEED = 0x0CEA, - SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0x0902, - SMSG_MOVE_UPDATE_SWIM_SPEED = 0x0D75, - SMSG_MOVE_UPDATE_TELEPORT = 0x0D09, - SMSG_MOVE_UPDATE_TURN_RATE = 0x05A2, - SMSG_MOVE_UPDATE_WALK_SPEED = 0x0DA5, - SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT = 0x1A73, - SMSG_NEW_TAXI_PATH = 0x0BFF, - SMSG_NEW_WORLD = 0x0AEB, - SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x05F3, - SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION = 0x0A74, - SMSG_NOTIFY_MONEY = 0x1BCC, - SMSG_NOTIFY_RECEIVED_MAIL = 0x0A73, - SMSG_OFFER_PETITION_ERROR = 0x13F4, - SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x1B54, - SMSG_ON_MONSTER_MOVE = 0x043A, - SMSG_OPEN_CONTAINER = 0x07D8, - SMSG_OPEN_LFG_DUNGEON_FINDER = 0x114C, - SMSG_OPEN_SHIPMENT_NPC_FROM_GOSSIP = 0x1657, - SMSG_OPEN_SHIPMENT_NPC_RESULT = 0x16E8, - SMSG_OVERRIDE_LIGHT = 0x13CC, - SMSG_PAGE_TEXT = 0x03FB, - SMSG_PARTY_COMMAND_RESULT = 0x0744, - SMSG_PARTY_INVITE = 0x07E8, - SMSG_PARTY_KILL_LOG = 0x03EF, - SMSG_PARTY_MEMBER_STATE = 0x0EF3, - SMSG_PARTY_UPDATE = 0x027B, - SMSG_PAUSE_MIRROR_TIMER = 0x036F, - SMSG_PENDING_RAID_LOCK = 0x0E64, - SMSG_PETITION_ALREADY_SIGNED = 0x13D8, - SMSG_PETITION_RENAME_GUILD_RESPONSE = 0x141F, - SMSG_PETITION_SHOW_LIST = 0x136B, - SMSG_PETITION_SHOW_SIGNATURES = 0x0663, - SMSG_PETITION_SIGN_RESULTS = 0x0FE3, - SMSG_PET_ACTION_FEEDBACK = 0x07F4, - SMSG_PET_ACTION_SOUND = 0x0267, - SMSG_PET_ADDED = 0x12CF, - SMSG_PET_BATTLE_CHAT_RESTRICTED = 0x1B48, - SMSG_PET_BATTLE_DEBUG_QUEUE_DUMP_RESPONSE = 0x0377, - SMSG_PET_BATTLE_FINALIZE_LOCATION = 0x165F, - SMSG_PET_BATTLE_FINAL_ROUND = 0x02CF, - SMSG_PET_BATTLE_FINISHED = 0x02F8, - SMSG_PET_BATTLE_FIRST_ROUND = 0x03E3, - SMSG_PET_BATTLE_INITIAL_UPDATE = 0x0B80, - SMSG_PET_BATTLE_MAX_GAME_LENGTH_WARNING = 0x1AC8, - SMSG_PET_BATTLE_PVP_CHALLENGE = 0x0A63, - SMSG_PET_BATTLE_QUEUE_PROPOSE_MATCH = 0x03D3, - SMSG_PET_BATTLE_QUEUE_STATUS = 0x1BD3, - SMSG_PET_BATTLE_REPLACEMENTS_MADE = 0x1360, - SMSG_PET_BATTLE_REQUEST_FAILED = 0x12F0, - SMSG_PET_BATTLE_ROUND_RESULT = 0x0EC8, - SMSG_PET_BATTLE_SLOT_UPDATES = 0x0FCB, - SMSG_PET_CAST_FAILED = 0x11A7, - SMSG_PET_CLEAR_SPELLS = 0x1134, - SMSG_PET_DISMISS_SOUND = 0x07F3, - SMSG_PET_GOD_MODE = 0x1A68, - SMSG_PET_GUIDS = 0x1BF7, - SMSG_PET_LEARNED_SPELLS = 0x046F, - SMSG_PET_MODE = 0x1277, - SMSG_PET_NAME_INVALID = 0x03F0, - SMSG_PET_SLOT_UPDATED = 0x13F8, - SMSG_PET_SPELLS_MESSAGE = 0x10E4, - SMSG_PET_STABLE_LIST = 0x13D0, - SMSG_PET_STABLE_RESULT = 0x03C3, - SMSG_PET_TAME_FAILURE = 0x16E7, - SMSG_PET_UNLEARNED_SPELLS = 0x053F, - SMSG_PHASE_SHIFT_CHANGE = 0x137C, - SMSG_PLAYED_TIME = 0x0EDF, - SMSG_PLAYER_BOUND = 0x12CB, - SMSG_PLAYER_SAVE_GUILD_EMBLEM = 0x14C8, - SMSG_PLAYER_SKINNED = 0x0A48, - SMSG_PLAYER_TABARD_VENDOR_ACTIVATE = 0x16C3, - SMSG_PLAY_MUSIC = 0x1B57, - SMSG_PLAY_OBJECT_SOUND = 0x0A4C, - SMSG_PLAY_ONE_SHOT_ANIM_KIT = 0x0344, - SMSG_PLAY_ORPHAN_SPELL_VISUAL = 0x10A3, - SMSG_PLAY_SCENE = 0x1778, - SMSG_PLAY_SOUND = 0x0F6F, - SMSG_PLAY_SPEAKERBOT_SOUND = 0x0AE4, - SMSG_PLAY_SPELL_VISUAL = 0x11B0, - SMSG_PLAY_SPELL_VISUAL_KIT = 0x00F3, - SMSG_PLAY_TIME_WARNING = 0x1ADF, - SMSG_PONG = 0x0288, - SMSG_POWER_UPDATE = 0x1BDB, - SMSG_PRE_RESSURECT = 0x0C00, - SMSG_PRINT_NOTIFICATION = 0x03FC, - SMSG_PROC_RESIST = 0x1677, - SMSG_PROPOSE_LEVEL_GRANT = 0x0A77, - SMSG_PVP_CREDIT = 0x1673, - SMSG_PVP_LOG_DATA = 0x0EEF, - SMSG_PVP_OPTIONS_ENABLED = 0x1BFB, - SMSG_PVP_SEASON = 0x1BF0, - SMSG_QUERY_BATTLE_PET_NAME_RESPONSE = 0x0800, - SMSG_QUERY_CREATURE_RESPONSE = 0x134F, - SMSG_QUERY_GAME_OBJECT_RESPONSE = 0x03EB, - SMSG_QUERY_GARRISON_CREATURE_NAME_RESPONSE = 0x15BE, - SMSG_QUERY_GUILD_INFO_RESPONSE = 0x1507, - SMSG_QUERY_ITEM_TEXT_RESPONSE = 0x037F, - SMSG_QUERY_NPC_TEXT_RESPONSE = 0x02F7, - SMSG_QUERY_PAGE_TEXT_RESPONSE = 0x1B58, - SMSG_QUERY_PETITION_RESPONSE = 0x1668, - SMSG_QUERY_PET_NAME_RESPONSE = 0x0E5F, - SMSG_QUERY_PLAYER_NAME_RESPONSE = 0x17D0, - SMSG_QUERY_QUEST_INFO_RESPONSE = 0x15AD, - SMSG_QUERY_TIME_RESPONSE = 0x1B7C, - SMSG_QUEST_COMPLETION_NPC_RESPONSE = 0x0442, - SMSG_QUEST_CONFIRM_ACCEPT = 0x0756, - SMSG_QUEST_FORCE_REMOVED = 0x1525, - SMSG_QUEST_GIVER_INVALID_QUEST = 0x11A1, - SMSG_QUEST_GIVER_OFFER_REWARD_MESSAGE = 0x1125, - SMSG_QUEST_GIVER_QUEST_COMPLETE = 0x1D05, - SMSG_QUEST_GIVER_QUEST_DETAILS = 0x1921, - SMSG_QUEST_GIVER_QUEST_FAILED = 0x152D, - SMSG_QUEST_GIVER_QUEST_LIST_MESSAGE = 0x0259, - SMSG_QUEST_GIVER_REQUEST_ITEMS = 0x1DAA, - SMSG_QUEST_GIVER_STATUS = 0x1D02, - SMSG_QUEST_GIVER_STATUS_MULTIPLE = 0x0735, - SMSG_QUEST_LOG_FULL = 0x031D, - SMSG_QUEST_POI_QUERY_RESPONSE = 0x1D82, - SMSG_QUEST_PUSH_RESULT = 0x1D21, - SMSG_QUEST_UPDATE_ADD_CREDIT = 0x1D8A, - SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE = 0x0616, - SMSG_QUEST_UPDATE_ADD_PVP_CREDIT = 0x1501, - SMSG_QUEST_UPDATE_COMPLETE = 0x1981, - SMSG_QUEST_UPDATE_FAILED = 0x023E, - SMSG_QUEST_UPDATE_FAILED_TIMER = 0x1989, - SMSG_RAF_EMAIL_ENABLED_RESPONSE = 0x0767, - SMSG_RAID_DIFFICULTY_SET = 0x1368, - SMSG_RAID_GROUP_ONLY = 0x1B6C, - SMSG_RAID_INSTANCE_MESSAGE = 0x0306, - SMSG_RAID_MARKERS_CHANGED = 0x17E7, - SMSG_RANDOM_ROLL = 0x07DB, - SMSG_RATED_BATTLEFIELD_INFO = 0x1BD8, - SMSG_READY_CHECK_COMPLETED = 0x0BD0, - SMSG_READY_CHECK_RESPONSE = 0x1BDF, - SMSG_READY_CHECK_STARTED = 0x02C3, - SMSG_READ_ITEM_RESULT_FAILED = 0x0ED3, - SMSG_READ_ITEM_RESULT_OK = 0x0AF7, - SMSG_REALM_QUERY_RESPONSE = 0x0ED8, - SMSG_REALM_SPLIT = 0x03E7, - SMSG_RECRUIT_A_FRIEND_RESPONSE = 0x0750, - SMSG_REFER_A_FRIEND_EXPIRED = 0x17DC, - SMSG_REFER_A_FRIEND_FAILURE = 0x13E8, - SMSG_REFRESH_COMPONENT = 0x066B, - SMSG_REFRESH_SPELL_HISTORY = 0x1038, - SMSG_REMOVE_ITEM_PASSIVE = 0x0EDB, - SMSG_REMOVE_LOSS_OF_CONTROL = 0x0364, - SMSG_REPLACE_TROPHY_RESPONSE = 0x03C7, - SMSG_REPORT_PVP_PLAYER_AFK_RESULT = 0x135F, - SMSG_REQUEST_ADDON_LIST = 0x1B47, - SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x1344, - SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0x1AEB, - SMSG_RESEARCH_COMPLETE = 0x1AEC, - SMSG_RESET_COMPRESSION_CONTEXT = 0x0287, - SMSG_RESET_FAILED_NOTIFY = 0x0270, - SMSG_RESET_RANGED_COMBAT_TIMER = 0x16E3, - SMSG_RESET_WEEKLY_CURRENCY = 0x0EF0, - SMSG_RESPEC_WIPE_CONFIRM = 0x1BE8, - SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x0F4C, - SMSG_RESUME_CAST_BAR = 0x01B3, - SMSG_RESUME_COMMS = 0x02A3, - SMSG_RESUME_TOKEN = 0x1373, - SMSG_RESURRECT_REQUEST = 0x06FC, - SMSG_RESYNC_RUNES = 0x13FC, - SMSG_ROLE_CHANGED_INFORM = 0x16D7, - SMSG_ROLE_CHOSEN = 0x111B, - SMSG_ROLE_POLL_INFORM = 0x1663, - SMSG_RUNE_REGEN_DEBUG = 0x0FD3, - SMSG_SCENARIO_BOOT = 0x1244, - SMSG_SCENARIO_COMPLETED = 0x13CB, - SMSG_SCENARIO_OUT_OF_BOUNDS = 0x12D0, - SMSG_SCENARIO_POIS = 0x1BE3, - SMSG_SCENARIO_PROGRESS_UPDATE = 0x0ED7, - SMSG_SCENARIO_STATE = 0x1364, - SMSG_SCENE_OBJECT_EVENT = 0x13F0, - SMSG_SCENE_OBJECT_PET_BATTLE_FINAL_ROUND = 0x0F44, - SMSG_SCENE_OBJECT_PET_BATTLE_FINISHED = 0x1758, - SMSG_SCENE_OBJECT_PET_BATTLE_FIRST_ROUND = 0x16EB, - SMSG_SCENE_OBJECT_PET_BATTLE_INITIAL_UPDATE = 0x02E0, - SMSG_SCENE_OBJECT_PET_BATTLE_REPLACEMENTS_MADE = 0x0F7C, - SMSG_SCENE_OBJECT_PET_BATTLE_ROUND_RESULT = 0x0B43, - SMSG_SCRIPT_CAST = 0x00F4, - SMSG_SELL_RESPONSE = 0x0EE0, - SMSG_SEND_ITEM_PASSIVES = 0x1654, - SMSG_SEND_KNOWN_SPELLS = 0x00EF, - SMSG_SEND_RAID_TARGET_UPDATE_ALL = 0x1BF4, - SMSG_SEND_RAID_TARGET_UPDATE_SINGLE = 0x0FCF, - SMSG_SEND_SPELL_CHARGES = 0x05FC, - SMSG_SEND_SPELL_HISTORY = 0x01F0, - SMSG_SEND_UNLEARN_SPELLS = 0x05B3, - SMSG_SERVER_FIRST_ACHIEVEMENT = 0x030E, - SMSG_SERVER_FIRST_ACHIEVEMENTS = 0x064F, - SMSG_SERVER_TIME = 0x0F60, - SMSG_SETUP_CURRENCY = 0x0F48, - SMSG_SETUP_RESEARCH_HISTORY = 0x126F, - SMSG_SET_AI_ANIM_KIT = 0x13C3, - SMSG_SET_ALL_TASK_PROGRESS = 0x0ADF, - SMSG_SET_ANIM_TIER = 0x03E4, - SMSG_SET_CURRENCY = 0x0BFC, - SMSG_SET_DF_FAST_LAUNCH_RESULT = 0x115F, - SMSG_SET_DUNGEON_DIFFICULTY = 0x0647, - SMSG_SET_FACTION_AT_WAR = 0x02F4, - SMSG_SET_FACTION_NOT_VISIBLE = 0x0A80, - SMSG_SET_FACTION_STANDING = 0x13C8, - SMSG_SET_FACTION_VISIBLE = 0x0AD4, - SMSG_SET_FLAT_SPELL_MODIFIER = 0x00C0, - SMSG_SET_FORCED_REACTIONS = 0x0A6C, - SMSG_SET_ITEM_PURCHASE_DATA = 0x165B, - SMSG_SET_LOOT_METHOD_FAILED = 0x0F47, - SMSG_SET_MAX_WEEKLY_QUANTITY = 0x0F63, - SMSG_SET_MELEE_ANIM_KIT = 0x17CF, - SMSG_SET_MOVEMENT_ANIM_KIT = 0x1A5B, - SMSG_SET_PCT_SPELL_MODIFIER = 0x11AB, - SMSG_SET_PET_SPECIALIZATION = 0x1B7F, - SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x1650, - SMSG_SET_PLAY_HOVER_ANIM = 0x12E4, - SMSG_SET_PROFICIENCY = 0x0668, - SMSG_SET_SPELL_CHARGES = 0x1027, - SMSG_SET_TASK_COMPLETE = 0x13E0, - SMSG_SET_TIME_ZONE_INFORMATION = 0x17E0, - SMSG_SET_VEHICLE_REC_ID = 0x0B4B, - SMSG_SHOW_BANK = 0x0B48, - SMSG_SHOW_MAILBOX = 0x0A7C, - SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI = 0x12FB, - SMSG_SHOW_TAXI_NODES = 0x066F, - SMSG_SHOW_TRADE_SKILL_RESPONSE = 0x0B77, - SMSG_SOCKET_GEMS = 0x025C, - SMSG_SOR_START_EXPERIENCE_INCOMPLETE = 0x17D3, - SMSG_SPECIAL_MOUNT_ANIM = 0x0274, - SMSG_SPELL_ABSORB_LOG = 0x117F, - SMSG_SPELL_CHANNEL_START = 0x1428, - SMSG_SPELL_CHANNEL_UPDATE = 0x04F7, - SMSG_SPELL_COOLDOWN = 0x0124, - SMSG_SPELL_DAMAGE_SHIELD = 0x047B, - SMSG_SPELL_DELAYED = 0x116F, - SMSG_SPELL_DISPELL_LOG = 0x116B, - SMSG_SPELL_ENERGIZE_LOG = 0x0100, - SMSG_SPELL_EXECUTE_LOG = 0x11FC, - SMSG_SPELL_FAILED_OTHER = 0x11EC, - SMSG_SPELL_FAILURE = 0x0424, - SMSG_SPELL_GO = 0x00BF, - SMSG_SPELL_HEAL_LOG = 0x10B7, - SMSG_SPELL_INSTAKILL_LOG = 0x0064, - SMSG_SPELL_INTERRUPT_LOG = 0x01C0, - SMSG_SPELL_MISS_LOG = 0x057B, - SMSG_SPELL_MULTISTRIKE_EFFECT = 0x00AB, - SMSG_SPELL_NON_MELEE_DAMAGE_LOG = 0x10F0, - SMSG_SPELL_OR_DAMAGE_IMMUNE = 0x04C0, - SMSG_SPELL_PERIODIC_AURA_LOG = 0x10FC, - SMSG_SPELL_START = 0x1077, - SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x0570, - SMSG_SPIRIT_HEALER_CONFIRM = 0x164B, - SMSG_STAND_STATE_UPDATE = 0x12E0, - SMSG_START_ELAPSED_TIMER = 0x166F, - SMSG_START_ELAPSED_TIMERS = 0x02CC, - SMSG_START_LOOT_ROLL = 0x02CB, - SMSG_START_MIRROR_TIMER = 0x166C, - SMSG_START_TIMER = 0x1A4B, - SMSG_STOP_ELAPSED_TIMER = 0x0ED0, - SMSG_STOP_MIRROR_TIMER = 0x13EB, - SMSG_STOP_SPEAKERBOT_SOUND = 0x1A64, - SMSG_STREAMING_MOVIES = 0x0644, - SMSG_SUMMON_CANCEL = 0x1B73, - SMSG_SUMMON_RAID_MEMBER_VALIDATE_FAILED = 0x1AE3, - SMSG_SUMMON_REQUEST = 0x065B, - SMSG_SUPERCEDED_SPELLS = 0x04F4, - SMSG_SUPPRESS_NPC_GREETINGS = 0x0758, - SMSG_SUSPEND_COMMS = 0x0208, - SMSG_SUSPEND_TOKEN = 0x0353, - SMSG_TALENTS_INVOLUNTARILY_RESET = 0x035F, - SMSG_TAXI_NODE_STATUS = 0x12F3, - SMSG_TEXT_EMOTE = 0x13E4, - SMSG_THREAT_CLEAR = 0x07C3, - SMSG_THREAT_REMOVE = 0x0BDF, - SMSG_THREAT_UPDATE = 0x035B, - SMSG_TIME_ADJUSTMENT = 0x00BE, - SMSG_TIME_SYNC_REQUEST = 0x0101, - SMSG_TITLE_EARNED = 0x125C, - SMSG_TITLE_LOST = 0x06D8, - SMSG_TOTEM_CREATED = 0x0BC7, - SMSG_TOTEM_MOVED = 0x16CC, - SMSG_TRADE_STATUS = 0x1253, - SMSG_TRADE_UPDATED = 0x0AF3, - SMSG_TRAINER_BUY_FAILED = 0x025B, - SMSG_TRAINER_LIST = 0x12DC, - SMSG_TRANSFER_ABORTED = 0x12DB, - SMSG_TRANSFER_PENDING = 0x0348, - SMSG_TRIGGER_CINEMATIC = 0x16FF, - SMSG_TRIGGER_MOVIE = 0x16F3, - SMSG_TURN_IN_PETITION_RESULT = 0x16C8, - SMSG_TUTORIAL_FLAGS = 0x1B7B, - SMSG_TWITTER_STATUS = 0x0060, - SMSG_UI_TIME = 0x1B4C, - SMSG_UNDELETE_CHARACTER_RESPONSE = 0x0FD0, - SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE = 0x1ADB, - SMSG_UNLEARNED_SPELLS = 0x0470, - SMSG_UPDATE_ACCOUNT_DATA = 0x0B47, - SMSG_UPDATE_ACTION_BUTTONS = 0x17F8, - SMSG_UPDATE_CHARACTER_FLAGS = 0x12D7, - SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT = 0x1050, - SMSG_UPDATE_EXPANSION_LEVEL = 0x125F, - SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x175B, - SMSG_UPDATE_LAST_INSTANCE = 0x0B7C, - SMSG_UPDATE_OBJECT = 0x026B, - SMSG_UPDATE_TALENT_DATA = 0x0277, - SMSG_UPDATE_TASK_PROGRESS = 0x1BE4, - SMSG_UPDATE_WEEKLY_SPELL_USAGE = 0x10BF, - SMSG_UPDATE_WORLD_STATE = 0x0A67, - SMSG_USERLIST_ADD = 0x0B8D, - SMSG_USERLIST_REMOVE = 0x0A8A, - SMSG_USERLIST_UPDATE = 0x0289, - SMSG_USE_EQUIPMENT_SET_RESULT = 0x0B57, - SMSG_VENDOR_INVENTORY = 0x0E5B, - SMSG_VIGNETTE_UPDATE = 0x0EF7, - SMSG_VOICE_CHAT_STATUS = 0x028E, - SMSG_VOICE_PARENTAL_CONTROLS = 0x020E, - SMSG_VOICE_SESSION_LEAVE = 0x0605, - SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x0B85, - SMSG_VOID_ITEM_SWAP_RESPONSE = 0x0F64, - SMSG_VOID_STORAGE_CONTENTS = 0x1ADC, - SMSG_VOID_STORAGE_FAILED = 0x03CF, - SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0x1A6B, - SMSG_VOID_TRANSFER_RESULT = 0x0E68, - SMSG_WAIT_QUEUE_FINISH = 0x1A53, - SMSG_WAIT_QUEUE_UPDATE = 0x1257, - SMSG_WARDEN_DATA = 0x0A68, - SMSG_WARGAME_REQUEST_SUCCESSFULLY_SENT_TO_OPPONENT = 0x1BF8, - SMSG_WEATHER = 0x12FC, - SMSG_WEEKLY_SPELL_USAGE = 0x00E8, - SMSG_WHO = 0x0A09, - SMSG_WHO_IS = 0x0FD4, - SMSG_WORLD_SERVER_INFO = 0x1B78, - SMSG_WORLD_TEXT = 0x17F3, - SMSG_WOW_TOKEN_AUCTION_SOLD = 0x12E3, - SMSG_WOW_TOKEN_BUY_REQUEST_CONFIRMATION = 0x17C8, - SMSG_WOW_TOKEN_BUY_RESULT_CONFIRMATION = 0x0F68, - SMSG_WOW_TOKEN_MARKET_PRICE_RESPONSE = 0x034C, - SMSG_WOW_TOKEN_REDEEM_GAME_TIME_UPDATED = 0x1A80, - SMSG_WOW_TOKEN_REDEEM_REQUEST_CONFIRMATION = 0x1AD4, - SMSG_WOW_TOKEN_REDEEM_RESULT = 0x0BF4, - SMSG_WOW_TOKEN_SELL_REQUEST_CONFIRMATION = 0x0757, - SMSG_WOW_TOKEN_SELL_RESULT_CONFIRMATION = 0x0673, - SMSG_WOW_TOKEN_UPDATE_AUCTIONABLE_LIST_RESPONSE = 0x0A50, - SMSG_XP_GAIN_ABORTED = 0x1300, - SMSG_XP_GAIN_ENABLED = 0x0670, - SMSG_ZONE_UNDER_ATTACK = 0x0A06, + SMSG_ABORT_NEW_WORLD = 0x2533, + SMSG_ACCOUNT_CRITERIA_UPDATE = 0x25D2, + SMSG_ACCOUNT_DATA_TIMES = 0x26CA, + SMSG_ACCOUNT_MOUNT_UPDATE = 0x2549, + SMSG_ACCOUNT_TOYS_UPDATE = 0x254A, + SMSG_ACHIEVEMENT_DELETED = 0x26A0, + SMSG_ACHIEVEMENT_EARNED = 0x25E0, + SMSG_ACTIVATE_TAXI_REPLY = 0x2627, + SMSG_ADDON_INFO = 0x26FC, + SMSG_ADD_BATTLENET_FRIEND_RESPONSE = 0x25DA, + SMSG_ADD_ITEM_PASSIVE = 0x2545, + SMSG_ADD_LOSS_OF_CONTROL = 0x2617, + SMSG_ADD_RUNE_POWER = 0x2665, + SMSG_ADJUST_SPLINE_DURATION = 0x256C, + SMSG_AE_LOOT_TARGETS = 0x25AE, + SMSG_AE_LOOT_TARGET_ACK = 0x25AF, + SMSG_AI_REACTION = 0x2661, + SMSG_ALL_ACCOUNT_CRITERIA = 0x24EE, + SMSG_ALL_ACHIEVEMENT_DATA = 0x24ED, + SMSG_ALL_GUILD_ACHIEVEMENTS = 0x2936, + SMSG_ARCHAEOLOGY_SURVERY_CAST = 0x2504, + SMSG_AREA_SPIRIT_HEALER_TIME = 0x2701, + SMSG_AREA_TRIGGER_DENIED = 0x261E, + SMSG_AREA_TRIGGER_NO_CORPSE = 0x26D6, + SMSG_AREA_TRIGGER_RE_PATH = 0x25BF, + SMSG_AREA_TRIGGER_RE_SHAPE = 0x25C1, + SMSG_ARENA_ERROR = 0x2693, + SMSG_ARENA_PREP_OPPONENT_SPECIALIZATIONS = 0x25E6, + SMSG_ATTACKER_STATE_UPDATE = 0x2749, + SMSG_ATTACK_START = 0x25EE, + SMSG_ATTACK_STOP = 0x25EF, + SMSG_ATTACK_SWING_ERROR = 0x26B5, + SMSG_ATTACK_SWING_LANDED_LOG = 0x26B6, + SMSG_AUCTION_CLOSED_NOTIFICATION = 0x26AA, + SMSG_AUCTION_COMMAND_RESULT = 0x26A7, + SMSG_AUCTION_HELLO_RESPONSE = 0x26A5, + SMSG_AUCTION_LIST_BIDDER_ITEMS_RESULT = 0x26AE, + SMSG_AUCTION_LIST_ITEMS_RESULT = 0x26AC, + SMSG_AUCTION_LIST_OWNER_ITEMS_RESULT = 0x26AD, + SMSG_AUCTION_LIST_PENDING_SALES_RESULT = 0x26AF, + SMSG_AUCTION_OUTBID_NOTIFICATION = 0x26A9, + SMSG_AUCTION_OWNER_BID_NOTIFICATION = 0x26AB, + SMSG_AUCTION_REPLICATE_RESPONSE = 0x26A6, + SMSG_AUCTION_WON_NOTIFICATION = 0x26A8, + SMSG_AURA_POINTS_DEPLETED = 0x2BA0, + SMSG_AURA_UPDATE = 0x2B9F, + SMSG_AUTH_CHALLENGE = 0x2FC6, + SMSG_AUTH_RESPONSE = 0x24EA, + SMSG_AVAILABLE_VOICE_CHANNEL = 0x2B30, + SMSG_BAN_REASON = 0x2633, + SMSG_BARBER_SHOP_RESULT = 0x266B, + SMSG_BATTLEFIELD_LIST = 0x2511, + SMSG_BATTLEFIELD_PORT_DENIED = 0x2517, + SMSG_BATTLEFIELD_STATUS_ACTIVE = 0x250D, + SMSG_BATTLEFIELD_STATUS_FAILED = 0x2510, + SMSG_BATTLEFIELD_STATUS_NEED_CONFIRMATION = 0x250C, + SMSG_BATTLEFIELD_STATUS_NONE = 0x250F, + SMSG_BATTLEFIELD_STATUS_QUEUED = 0x250E, + SMSG_BATTLEFIELD_STATUS_WAIT_FOR_GROUPS = 0x252B, + SMSG_BATTLEGROUND_INFO_THROTTLED = 0x2523, + SMSG_BATTLEGROUND_INIT = 0x271E, + SMSG_BATTLEGROUND_PLAYER_JOINED = 0x2515, + SMSG_BATTLEGROUND_PLAYER_LEFT = 0x2516, + SMSG_BATTLEGROUND_PLAYER_POSITIONS = 0x2512, + SMSG_BATTLEGROUND_POINTS = 0x271D, + SMSG_BATTLENET_CHALLENGE_ABORT = 0x2748, + SMSG_BATTLENET_CHALLENGE_START = 0x2747, + SMSG_BATTLENET_NOTIFICATION = 0x279E, + SMSG_BATTLENET_REALM_LIST_TICKET = 0x27A0, + SMSG_BATTLENET_RESPONSE = 0x279D, + SMSG_BATTLENET_SET_SESSION_STATE = 0x279F, + SMSG_BATTLE_PAY_ACK_FAILED = 0x2740, + SMSG_BATTLE_PAY_CONFIRM_PURCHASE = 0x273F, + SMSG_BATTLE_PAY_DELIVERY_ENDED = 0x2736, + SMSG_BATTLE_PAY_DELIVERY_STARTED = 0x2735, + SMSG_BATTLE_PAY_DISTRIBUTION_UPDATE = 0x2734, + SMSG_BATTLE_PAY_GET_DISTRIBUTION_LIST_RESPONSE = 0x2732, + SMSG_BATTLE_PAY_GET_PRODUCT_LIST_RESPONSE = 0x2730, + SMSG_BATTLE_PAY_GET_PURCHASE_LIST_RESPONSE = 0x2731, + SMSG_BATTLE_PAY_PURCHASE_UPDATE = 0x273E, + SMSG_BATTLE_PAY_START_DISTRIBUTION_ASSIGN_TO_TARGET_RESPONSE = 0x273C, + SMSG_BATTLE_PAY_START_PURCHASE_RESPONSE = 0x273B, + SMSG_BATTLE_PETS_HEALED = 0x258C, + SMSG_BATTLE_PET_CAGE_DATE_ERROR = 0x2621, + SMSG_BATTLE_PET_DELETED = 0x2589, + SMSG_BATTLE_PET_ERROR = 0x25D5, + SMSG_BATTLE_PET_JOURNAL = 0x2588, + SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED = 0x2586, + SMSG_BATTLE_PET_JOURNAL_LOCK_DENIED = 0x2587, + SMSG_BATTLE_PET_LICENSE_CHANGED = 0x258D, + SMSG_BATTLE_PET_RESTORED = 0x258B, + SMSG_BATTLE_PET_REVOKED = 0x258A, + SMSG_BATTLE_PET_TRAP_LEVEL = 0x2584, + SMSG_BATTLE_PET_UPDATES = 0x2583, + SMSG_BF_MGR_DROP_TIMER_CANCELLED = 0x251F, + SMSG_BF_MGR_DROP_TIMER_STARTED = 0x251E, + SMSG_BF_MGR_EJECTED = 0x251D, + SMSG_BF_MGR_EJECT_PENDING = 0x251C, + SMSG_BF_MGR_ENTERING = 0x2519, + SMSG_BF_MGR_ENTRY_INVITE = 0x2518, + SMSG_BF_MGR_QUEUE_INVITE = 0x2520, + SMSG_BF_MGR_QUEUE_REQUEST_RESPONSE = 0x251A, + SMSG_BF_MGR_QUEUE_STATUS_UPDATE = 0x251B, + SMSG_BF_MGR_STATE_CHANGED = 0x2522, + SMSG_BINDER_CONFIRM = 0x26BB, + SMSG_BIND_POINT_UPDATE = 0x24FA, + SMSG_BLACK_MARKET_BID_ON_ITEM_RESULT = 0x25C5, + SMSG_BLACK_MARKET_OPEN_RESULT = 0x25C3, + SMSG_BLACK_MARKET_OUTBID = 0x25C6, + SMSG_BLACK_MARKET_REQUEST_ITEMS_RESULT = 0x25C4, + SMSG_BLACK_MARKET_WON = 0x25C7, + SMSG_BONUS_ROLL_EMPTY = 0x25E3, + SMSG_BOSS_KILL_CREDIT = 0x273A, + SMSG_BREAK_TARGET = 0x25ED, + SMSG_BUY_FAILED = 0x2674, + SMSG_BUY_SUCCEEDED = 0x2673, + SMSG_CACHE_VERSION = 0x26C4, + SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x2647, + SMSG_CALENDAR_COMMAND_RESULT = 0x2648, + SMSG_CALENDAR_EVENT_INITIAL_INVITES = 0x2637, + SMSG_CALENDAR_EVENT_INVITE = 0x2638, + SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x2639, + SMSG_CALENDAR_EVENT_INVITE_MODERATOR_STATUS = 0x263C, + SMSG_CALENDAR_EVENT_INVITE_NOTES = 0x2641, + SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT = 0x2642, + SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x263D, + SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x263E, + SMSG_CALENDAR_EVENT_INVITE_STATUS = 0x263A, + SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x263B, + SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x263F, + SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x2640, + SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x2643, + SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x2644, + SMSG_CALENDAR_RAID_LOCKOUT_UPDATED = 0x2645, + SMSG_CALENDAR_SEND_CALENDAR = 0x2635, + SMSG_CALENDAR_SEND_EVENT = 0x2636, + SMSG_CALENDAR_SEND_NUM_PENDING = 0x2646, + SMSG_CAMERA_SHAKE = 0x26E6, + SMSG_CANCEL_AUTO_REPEAT = 0x2694, + SMSG_CANCEL_COMBAT = 0x26B3, + SMSG_CANCEL_ORPHAN_SPELL_VISUAL = 0x2BC4, + SMSG_CANCEL_SCENE = 0x25D4, + SMSG_CANCEL_SPELL_VISUAL = 0x2BC2, + SMSG_CANCEL_SPELL_VISUAL_KIT = 0x2BC6, + SMSG_CAN_DUEL_RESULT = 0x25F7, + SMSG_CAST_FAILED = 0x2BD2, + SMSG_CATEGORY_COOLDOWN = 0x2B94, + SMSG_CHALLEGE_MODE_REWARDS = 0x25A3, + SMSG_CHALLENGE_MODE_ALL_MAP_STATS = 0x25A4, + SMSG_CHALLENGE_MODE_COMPLETE = 0x25A2, + SMSG_CHALLENGE_MODE_MAP_STATS_UPDATE = 0x25A5, + SMSG_CHALLENGE_MODE_NEW_PLAYER_RECORD = 0x25A7, + SMSG_CHALLENGE_MODE_REQUEST_LEADERS_RESULT = 0x25A6, + SMSG_CHALLENGE_MODE_RESET = 0x25A1, + SMSG_CHALLENGE_MODE_START = 0x25A0, + SMSG_CHANGE_PLAYER_DIFFICULTY_RESULT = 0x26B7, + SMSG_CHANNEL_LIST = 0x2B46, + SMSG_CHANNEL_NOTIFY = 0x2B43, + SMSG_CHANNEL_NOTIFY_JOINED = 0x2B44, + SMSG_CHANNEL_NOTIFY_LEFT = 0x2B45, + SMSG_CHARACTER_LOGIN_FAILED = 0x26C5, + SMSG_CHARACTER_OBJECT_TEST_RESPONSE = 0x2746, + SMSG_CHARACTER_RENAME_RESULT = 0x2724, + SMSG_CHARACTER_UPGRADE_CHARACTER_CHOSEN = 0x2772, + SMSG_CHARACTER_UPGRADE_COMPLETE = 0x2773, + SMSG_CHARACTER_UPGRADE_SPELL_TIER_SET = 0x2578, + SMSG_CHARACTER_UPGRADE_STARTED = 0x2771, + SMSG_CHAR_CUSTOMIZE = 0x269B, + SMSG_CHAR_CUSTOMIZE_FAILED = 0x269A, + SMSG_CHAR_FACTION_CHANGE_RESULT = 0x2760, + SMSG_CHAT = 0x2B2B, + SMSG_CHAT_AUTO_RESPONDED = 0x2B3B, + SMSG_CHAT_DOWN = 0x2B40, + SMSG_CHAT_IGNORED_ACCOUNT_MUTED = 0x2B2A, + SMSG_CHAT_IS_DOWN = 0x2B41, + SMSG_CHAT_NOT_IN_PARTY = 0x2B35, + SMSG_CHAT_PLAYER_AMBIGUOUS = 0x2B2E, + SMSG_CHAT_PLAYER_NOTFOUND = 0x2B3A, + SMSG_CHAT_RECONNECT = 0x2B42, + SMSG_CHAT_RESTRICTED = 0x2B36, + SMSG_CHAT_SERVER_MESSAGE = 0x2B47, + SMSG_CHEAT_IGNORE_DIMISHING_RETURNS = 0x2B90, + SMSG_CHECK_WARGAME_ENTRY = 0x2526, + SMSG_CLEAR_ALL_SPELL_CHARGES = 0x2BA5, + SMSG_CLEAR_BOSS_EMOTES = 0x2552, + SMSG_CLEAR_COOLDOWN = 0x2667, + SMSG_CLEAR_COOLDOWNS = 0x2BA3, + SMSG_CLEAR_LOSS_OF_CONTROL = 0x2619, + SMSG_CLEAR_SPELL_CHARGES = 0x2BA6, + SMSG_CLEAR_TARGET = 0x265D, + SMSG_COIN_REMOVED = 0x25AD, + SMSG_COMBAT_EVENT_FAILED = 0x25F0, + SMSG_COMMENTATOR_MAP_INFO = 0x26C7, + SMSG_COMMENTATOR_PLAYER_INFO = 0x26C8, + SMSG_COMMENTATOR_STATE_CHANGED = 0x26C6, + SMSG_COMPLAINT_RESULT = 0x2655, + SMSG_COMPLETE_SHIPMENT_RESPONSE = 0x2758, + SMSG_CONNECT_TO = 0x2FCA, + SMSG_CONQUEST_FORMULA_CONSTANTS = 0x2741, + SMSG_CONSOLE_WRITE = 0x25D1, + SMSG_CONTACT_LIST = 0x2744, + SMSG_CONTROL_UPDATE = 0x25E5, + SMSG_CONVERT_RUNE = 0x2664, + SMSG_COOLDOWN_CHEAT = 0x26F9, + SMSG_COOLDOWN_EVENT = 0x2666, + SMSG_CORPSE_LOCATION = 0x25EC, + SMSG_CORPSE_RECLAIM_DELAY = 0x270C, + SMSG_CORPSE_TRANSPORT_QUERY = 0x26D2, + SMSG_CREATE_CHAR = 0x26C0, + SMSG_CREATE_SHIPMENT_RESPONSE = 0x2757, + SMSG_CRITERIA_DELETED = 0x269F, + SMSG_CRITERIA_UPDATE = 0x2699, + SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x266F, + SMSG_CUSTOM_LOAD_SCREEN = 0x2568, + SMSG_DAILY_QUESTS_RESET = 0x29FE, + SMSG_DAMAGE_CALC_LOG = 0x277A, + SMSG_DANCE_STUDIO_CREATE_RESULT = 0x2721, + SMSG_DB_REPLY = 0x2528, + SMSG_DEATH_RELEASE_LOC = 0x2687, + SMSG_DEFENSE_MESSAGE = 0x2B39, + SMSG_DELETE_CHAR = 0x26C1, + SMSG_DESTROY_ARENA_UNIT = 0x2703, + SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x26B4, + SMSG_DIFFERENT_INSTANCE_FROM_PARTY = 0x2507, + SMSG_DISENCHANT_CREDIT = 0x2542, + SMSG_DISMOUNT = 0x265C, + SMSG_DISMOUNT_RESULT = 0x24F9, + SMSG_DISPEL_FAILED = 0x2BAE, + SMSG_DISPLAY_GAME_ERROR = 0x253B, + SMSG_DISPLAY_PLAYER_CHOICE = 0x2622, + SMSG_DISPLAY_PROMOTION = 0x25E9, + SMSG_DISPLAY_QUEST_POPUP = 0x2A19, + SMSG_DISPLAY_TOAST = 0x25BB, + SMSG_DONT_AUTO_PUSH_SPELLS_TO_ACTION_BAR = 0x257A, + SMSG_DROP_NEW_CONNECTION = 0x2FC9, + SMSG_DUEL_COMPLETE = 0x25F5, + SMSG_DUEL_COUNTDOWN = 0x25F4, + SMSG_DUEL_IN_BOUNDS = 0x25F3, + SMSG_DUEL_OUT_OF_BOUNDS = 0x25F2, + SMSG_DUEL_REQUESTED = 0x25F1, + SMSG_DUEL_WINNER = 0x25F6, + SMSG_DURABILITY_DAMAGE_DEATH = 0x2708, + SMSG_EMOTE = 0x277B, + SMSG_ENABLE_BARBER_SHOP = 0x266A, + SMSG_ENCHANTMENT_LOG = 0x26D3, + SMSG_ENCOUNTER_END = 0x2739, + SMSG_ENCOUNTER_START = 0x2738, + SMSG_ENUM_CHARACTERS_RESULT = 0x2500, + SMSG_ENVIRONMENTAL_DAMAGE_LOG = 0x2B9E, + SMSG_EQUIPMENT_SET_ID = 0x265E, + SMSG_EXPECTED_SPAM_RECORDS = 0x2B2F, + SMSG_EXPLORATION_EXPERIENCE = 0x2720, + SMSG_FACTION_BONUS_INFO = 0x26E5, + SMSG_FAILED_PLAYER_CONDITION = 0x2567, + SMSG_FEATURE_SYSTEM_STATUS = 0x2557, + SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN = 0x2558, + SMSG_FEIGN_DEATH_RESISTED = 0x2705, + SMSG_FISH_ESCAPED = 0x267C, + SMSG_FISH_NOT_HOOKED = 0x267B, + SMSG_FLIGHT_SPLINE_SYNC = 0x2D73, + SMSG_FORCED_DEATH_UPDATE = 0x2688, + SMSG_FORCE_ANIM = 0x2712, + SMSG_FORCE_OBJECT_RELINK = 0x25E8, + SMSG_FRIEND_STATUS = 0x2745, + SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT = 0x255B, + SMSG_GAME_OBJECT_CUSTOM_ANIM = 0x255C, + SMSG_GAME_OBJECT_DESPAWN = 0x255D, + SMSG_GAME_OBJECT_PLAY_SPELL_VISUAL = 0x2BC9, + SMSG_GAME_OBJECT_PLAY_SPELL_VISUAL_KIT = 0x2BC8, + SMSG_GAME_OBJECT_RESET_STATE = 0x26DC, + SMSG_GAME_OBJECT_UI_ACTION = 0x26D9, + SMSG_GAME_SPEED_SET = 0x262B, + SMSG_GAME_TIME_SET = 0x26CC, + SMSG_GAME_TIME_UPDATE = 0x26CB, + SMSG_GARRISON_ADD_FOLLOWER_RESULT = 0x287C, + SMSG_GARRISON_ADD_MISSION_RESULT = 0x287F, + SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT = 0x2890, + SMSG_GARRISON_BUILDING_ACTIVATED = 0x2879, + SMSG_GARRISON_BUILDING_LANDMARKS = 0x28A3, + SMSG_GARRISON_BUILDING_REMOVED = 0x2872, + SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT = 0x2874, + SMSG_GARRISON_CLEAR_ALL_FOLLOWERS_EXHAUSTION = 0x288E, + SMSG_GARRISON_COMPLETE_MISSION_RESULT = 0x2882, + SMSG_GARRISON_CREATE_RESULT = 0x287A, + SMSG_GARRISON_DELETE_RESULT = 0x2897, + SMSG_GARRISON_FOLLOWER_CHANGED_ABILITIES = 0x288C, + SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL = 0x288B, + SMSG_GARRISON_FOLLOWER_CHANGED_STATUS = 0x288D, + SMSG_GARRISON_FOLLOWER_CHANGED_XP = 0x288A, + SMSG_GARRISON_IS_UPGRADEABLE_RESULT = 0x28A0, + SMSG_GARRISON_LANDING_PAGE_SHIPMENT_INFO = 0x275A, + SMSG_GARRISON_LEARN_BLUEPRINT_RESULT = 0x2875, + SMSG_GARRISON_LEARN_SPECIALIZATION_RESULT = 0x2873, + SMSG_GARRISON_LIST_FOLLOWERS_CHEAT_RESULT = 0x287E, + SMSG_GARRISON_LIST_MISSIONS_CHEAT_RESULT = 0x28A1, + SMSG_GARRISON_MISSION_AREA_BONUS_ADDED = 0x2888, + SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT = 0x2885, + SMSG_GARRISON_MISSION_UPDATE_CAN_START = 0x2889, + SMSG_GARRISON_NUM_FOLLOWER_ACTIVATIONS_REMAINING = 0x288F, + SMSG_GARRISON_OPEN_ARCHITECT = 0x2898, + SMSG_GARRISON_OPEN_MISSION_NPC = 0x289A, + SMSG_GARRISON_OPEN_RECRUITMENT_NPC = 0x2894, + SMSG_GARRISON_OPEN_TRADESKILL_NPC = 0x2899, + SMSG_GARRISON_PLACE_BUILDING_RESULT = 0x2871, + SMSG_GARRISON_PLOT_PLACED = 0x286F, + SMSG_GARRISON_PLOT_REMOVED = 0x2870, + SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME = 0x2883, + SMSG_GARRISON_RECALL_PORTAL_USED = 0x2884, + SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED = 0x2895, + SMSG_GARRISON_RECRUIT_FOLLOWER_RESULT = 0x2896, + SMSG_GARRISON_REMOTE_INFO = 0x2878, + SMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING_RESULT = 0x2891, + SMSG_GARRISON_REMOVE_FOLLOWER_RESULT = 0x287D, + SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT = 0x2877, + SMSG_GARRISON_START_MISSION_RESULT = 0x2880, + SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT = 0x2876, + SMSG_GARRISON_UPGRADE_RESULT = 0x287B, + SMSG_GENERATE_RANDOM_CHARACTER_NAME_RESULT = 0x2501, + SMSG_GET_ACCOUNT_CHARACTER_LIST_RESULT = 0x2722, + SMSG_GET_DISPLAYED_TROPHY_LIST_RESPONSE = 0x289F, + SMSG_GET_GARRISON_INFO_RESULT = 0x286E, + SMSG_GET_SHIPMENTS_OF_TYPE_RESPONSE = 0x2759, + SMSG_GET_SHIPMENT_INFO_RESPONSE = 0x2755, + SMSG_GET_TROPHY_LIST_RESPONSE = 0x2776, + SMSG_GM_PLAYER_INFO = 0x26F8, + SMSG_GM_REQUEST_PLAYER_INFO = 0x256F, + SMSG_GM_TICKET_CASE_STATUS = 0x264E, + SMSG_GM_TICKET_SYSTEM_STATUS = 0x264D, + SMSG_GOD_MODE = 0x26BA, + SMSG_GOSSIP_COMPLETE = 0x2A13, + SMSG_GOSSIP_MESSAGE = 0x2A14, + SMSG_GOSSIP_POI = 0x2752, + SMSG_GROUP_ACTION_THROTTLED = 0x2524, + SMSG_GROUP_DECLINE = 0x274D, + SMSG_GROUP_DESTROYED = 0x274F, + SMSG_GROUP_NEW_LEADER = 0x25CA, + SMSG_GROUP_UNINVITE = 0x274E, + SMSG_GUILD_ACHIEVEMENT_DELETED = 0x2943, + SMSG_GUILD_ACHIEVEMENT_EARNED = 0x2942, + SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0x2945, + SMSG_GUILD_BANK_LOG_QUERY_RESULTS = 0x295C, + SMSG_GUILD_BANK_QUERY_RESULTS = 0x295B, + SMSG_GUILD_BANK_REMAINING_WITHDRAW_MONEY = 0x295D, + SMSG_GUILD_BANK_TEXT_QUERY_RESULT = 0x2960, + SMSG_GUILD_CHALLENGE_COMPLETED = 0x2951, + SMSG_GUILD_CHALLENGE_UPDATE = 0x2950, + SMSG_GUILD_CHANGE_NAME_RESULT = 0x295A, + SMSG_GUILD_COMMAND_RESULT = 0x2938, + SMSG_GUILD_CRITERIA_DELETED = 0x2944, + SMSG_GUILD_CRITERIA_UPDATE = 0x2941, + SMSG_GUILD_EVENT_BANK_CONTENTS_CHANGED = 0x2972, + SMSG_GUILD_EVENT_BANK_MONEY_CHANGED = 0x2971, + SMSG_GUILD_EVENT_DISBANDED = 0x2968, + SMSG_GUILD_EVENT_LOG_QUERY_RESULTS = 0x295F, + SMSG_GUILD_EVENT_MOTD = 0x2969, + SMSG_GUILD_EVENT_NEW_LEADER = 0x2967, + SMSG_GUILD_EVENT_PLAYER_JOINED = 0x2965, + SMSG_GUILD_EVENT_PLAYER_LEFT = 0x2966, + SMSG_GUILD_EVENT_PRESENCE_CHANGE = 0x296A, + SMSG_GUILD_EVENT_RANKS_UPDATED = 0x296B, + SMSG_GUILD_EVENT_RANK_CHANGED = 0x296C, + SMSG_GUILD_EVENT_TAB_ADDED = 0x296D, + SMSG_GUILD_EVENT_TAB_DELETED = 0x296E, + SMSG_GUILD_EVENT_TAB_MODIFIED = 0x296F, + SMSG_GUILD_EVENT_TAB_TEXT_CHANGED = 0x2970, + SMSG_GUILD_FLAGGED_FOR_RENAME = 0x2959, + SMSG_GUILD_INVITE = 0x2948, + SMSG_GUILD_INVITE_DECLINED = 0x2963, + SMSG_GUILD_INVITE_EXPIRED = 0x2964, + SMSG_GUILD_KNOWN_RECIPES = 0x293C, + SMSG_GUILD_MEMBERS_WITH_RECIPE = 0x293D, + SMSG_GUILD_MEMBER_DAILY_RESET = 0x2961, + SMSG_GUILD_MEMBER_RECIPES = 0x293B, + SMSG_GUILD_MEMBER_UPDATE_NOTE = 0x2947, + SMSG_GUILD_MOVED = 0x2957, + SMSG_GUILD_MOVE_STARTING = 0x2956, + SMSG_GUILD_NAME_CHANGED = 0x2958, + SMSG_GUILD_NEWS = 0x293F, + SMSG_GUILD_NEWS_DELETED = 0x2940, + SMSG_GUILD_PARTY_STATE = 0x2949, + SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0x295E, + SMSG_GUILD_RANKS = 0x2946, + SMSG_GUILD_REPUTATION_REACTION_CHANGED = 0x294A, + SMSG_GUILD_RESET = 0x2955, + SMSG_GUILD_REWARD_LIST = 0x293E, + SMSG_GUILD_ROSTER = 0x2939, + SMSG_GUILD_ROSTER_UPDATE = 0x293A, + SMSG_GUILD_SEND_RANK_CHANGE = 0x2937, + SMSG_HEALTH_UPDATE = 0x267F, + SMSG_HIGHEST_THREAT_UPDATE = 0x268E, + SMSG_HOTFIX_NOTIFY = 0x2529, + SMSG_HOTFIX_NOTIFY_BLOB = 0x252A, + SMSG_INCREASE_CAST_TIME_FOR_SPELL = 0x2BA4, + SMSG_INITIALIZE_FACTIONS = 0x26E4, + SMSG_INITIAL_SETUP = 0x24FD, + SMSG_INIT_WORLD_STATES = 0x2709, + SMSG_INSPECT_HONOR_STATS = 0x2538, + SMSG_INSPECT_PVP = 0x26E0, + SMSG_INSPECT_RESULT = 0x25CE, + SMSG_INSTANCE_ENCOUNTER_CHANGE_PRIORITY = 0x2766, + SMSG_INSTANCE_ENCOUNTER_DISENGAGE_UNIT = 0x2765, + SMSG_INSTANCE_ENCOUNTER_END = 0x276C, + SMSG_INSTANCE_ENCOUNTER_ENGAGE_UNIT = 0x2764, + SMSG_INSTANCE_ENCOUNTER_GAIN_COMBAT_RESURRECTION_CHARGE = 0x276E, + SMSG_INSTANCE_ENCOUNTER_IN_COMBAT_RESURRECTION = 0x276D, + SMSG_INSTANCE_ENCOUNTER_OBJECTIVE_COMPLETE = 0x2769, + SMSG_INSTANCE_ENCOUNTER_OBJECTIVE_START = 0x2768, + SMSG_INSTANCE_ENCOUNTER_OBJECTIVE_UPDATE = 0x276B, + SMSG_INSTANCE_ENCOUNTER_PHASE_SHIFT_CHANGED = 0x276F, + SMSG_INSTANCE_ENCOUNTER_START = 0x276A, + SMSG_INSTANCE_ENCOUNTER_TIMER_START = 0x2767, + SMSG_INSTANCE_GROUP_SIZE_CHANGED = 0x26B8, + SMSG_INSTANCE_INFO = 0x25D0, + SMSG_INSTANCE_RESET = 0x2630, + SMSG_INSTANCE_RESET_FAILED = 0x2631, + SMSG_INSTANCE_SAVE_CREATED = 0x2737, + SMSG_INVALIDATE_PLAYER = 0x2654, + SMSG_INVALID_PROMOTION_CODE = 0x2713, + SMSG_INVENTORY_CHANGE_FAILURE = 0x26E2, + SMSG_IS_QUEST_COMPLETE_RESPONSE = 0x2A01, + SMSG_ITEM_CHANGED = 0x26A2, + SMSG_ITEM_COOLDOWN = 0x2779, + SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x2715, + SMSG_ITEM_EXPIRE_PURCHASE_REFUND = 0x2537, + SMSG_ITEM_PURCHASE_REFUND_RESULT = 0x2535, + SMSG_ITEM_PUSH_RESULT = 0x25BA, + SMSG_ITEM_TIME_UPDATE = 0x2714, + SMSG_KICK_REASON = 0x2798, + SMSG_LEARNED_SPELLS = 0x2BCB, + SMSG_LEARN_TALENT_FAILED = 0x256D, + SMSG_LEVEL_UP_INFO = 0x26A1, + SMSG_LFG_BOOT_PLAYER = 0x29B4, + SMSG_LFG_DISABLED = 0x29B2, + SMSG_LFG_JOIN_RESULT = 0x299A, + SMSG_LFG_LIST_JOIN_RESULT = 0x299B, + SMSG_LFG_LIST_SEARCH_RESULTS = 0x299C, + SMSG_LFG_LIST_SEARCH_STATUS = 0x299D, + SMSG_LFG_LIST_UPDATE_BLACKLIST = 0x29A7, + SMSG_LFG_LIST_UPDATE_STATUS = 0x29A3, + SMSG_LFG_OFFER_CONTINUE = 0x29B3, + SMSG_LFG_PARTY_INFO = 0x29B5, + SMSG_LFG_PLAYER_INFO = 0x29B6, + SMSG_LFG_PLAYER_REWARD = 0x29B7, + SMSG_LFG_PROPOSAL_UPDATE = 0x29AA, + SMSG_LFG_QUEUE_STATUS = 0x299E, + SMSG_LFG_READY_CHECK_RESULT = 0x29B9, + SMSG_LFG_READY_CHECK_UPDATE = 0x29A0, + SMSG_LFG_ROLE_CHECK_UPDATE = 0x299F, + SMSG_LFG_SEARCH_RESULTS = 0x29AB, + SMSG_LFG_SLOT_INVALID = 0x29AE, + SMSG_LFG_TELEPORT_DENIED = 0x29B1, + SMSG_LFG_UPDATE_STATUS = 0x29A2, + SMSG_LF_GUILD_APPLICANT_LIST_CHANGED = 0x2952, + SMSG_LF_GUILD_APPLICATIONS = 0x294F, + SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED = 0x2953, + SMSG_LF_GUILD_BROWSE = 0x294C, + SMSG_LF_GUILD_COMMAND_RESULT = 0x294E, + SMSG_LF_GUILD_POST = 0x294B, + SMSG_LF_GUILD_RECRUITS = 0x294D, + SMSG_LIVE_REGION_ACCOUNT_RESTORE_RESULT = 0x272E, + SMSG_LIVE_REGION_CHARACTER_COPY_RESULT = 0x272C, + SMSG_LIVE_REGION_GET_ACCOUNT_CHARACTER_LIST_RESULT = 0x2723, + SMSG_LOAD_CUF_PROFILES = 0x2553, + SMSG_LOAD_EQUIPMENT_SET = 0x26CE, + SMSG_LOAD_SELECTED_TROPHY_RESULT = 0x2777, + SMSG_LOGIN_SET_TIME_SPEED = 0x26CD, + SMSG_LOGIN_VERIFY_WORLD = 0x2532, + SMSG_LOGOUT_CANCEL_ACK = 0x262F, + SMSG_LOGOUT_COMPLETE = 0x262E, + SMSG_LOGOUT_RESPONSE = 0x262D, + SMSG_LOG_XP_GAIN = 0x269D, + SMSG_LOOT_ALL_PASSED = 0x25B8, + SMSG_LOOT_CONTENTS = 0x2573, + SMSG_LOOT_ITEM_LIST = 0x25B6, + SMSG_LOOT_LIST = 0x2702, + SMSG_LOOT_MONEY_NOTIFY = 0x25B2, + SMSG_LOOT_RELEASE = 0x25B1, + SMSG_LOOT_RELEASE_ALL = 0x25B0, + SMSG_LOOT_REMOVED = 0x25AB, + SMSG_LOOT_RESPONSE = 0x25AA, + SMSG_LOOT_ROLL = 0x25B4, + SMSG_LOOT_ROLLS_COMPLETE = 0x25B7, + SMSG_LOOT_ROLL_WON = 0x25B9, + SMSG_LOSS_OF_CONTROL_AURA_UPDATE = 0x2616, + SMSG_MAIL_COMMAND_RESULT = 0x25D8, + SMSG_MAIL_LIST_RESULT = 0x2716, + SMSG_MAIL_QUERY_NEXT_TIME_RESULT = 0x2717, + SMSG_MAP_OBJECTIVES_INIT = 0x271F, + SMSG_MAP_OBJ_EVENTS = 0x255E, + SMSG_MASTER_LOOT_CANDIDATE_LIST = 0x25B5, + SMSG_MESSAGE_BOX = 0x24F3, + SMSG_MINIMAP_PING = 0x267A, + SMSG_MIRROR_IMAGE_COMPONENTED_DATA = 0x2B92, + SMSG_MIRROR_IMAGE_CREATURE_DATA = 0x2B91, + SMSG_MISSILE_CANCEL = 0x255F, + SMSG_MODIFY_COOLDOWN = 0x2725, + SMSG_MOTD = 0x2B2D, + SMSG_MOUNT_RESULT = 0x24F8, + SMSG_MOVE_APPLY_MOVEMENT_FORCE = 0x2D5D, + SMSG_MOVE_DISABLE_COLLISION = 0x2D59, + SMSG_MOVE_DISABLE_GRAVITY = 0x2D57, + SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x2D56, + SMSG_MOVE_ENABLE_COLLISION = 0x2D5A, + SMSG_MOVE_ENABLE_GRAVITY = 0x2D58, + SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x2D55, + SMSG_MOVE_KNOCK_BACK = 0x2D4D, + SMSG_MOVE_REMOVE_MOVEMENT_FORCE = 0x2D5E, + SMSG_MOVE_ROOT = 0x2D45, + SMSG_MOVE_SET_ACTIVE_MOVER = 0x2D21, + SMSG_MOVE_SET_CAN_FLY = 0x2D4F, + SMSG_MOVE_SET_CAN_TURN_WHILE_FALLING = 0x2D51, + SMSG_MOVE_SET_COLLISION_HEIGHT = 0x2D5B, + SMSG_MOVE_SET_COMPOUND_STATE = 0x2D5F, + SMSG_MOVE_SET_FEATHER_FALL = 0x2D49, + SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x2D41, + SMSG_MOVE_SET_FLIGHT_SPEED = 0x2D40, + SMSG_MOVE_SET_HOVERING = 0x2D4B, + SMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES = 0x2D53, + SMSG_MOVE_SET_LAND_WALK = 0x2D48, + SMSG_MOVE_SET_NORMAL_FALL = 0x2D4A, + SMSG_MOVE_SET_PITCH_RATE = 0x2D44, + SMSG_MOVE_SET_RUN_BACK_SPEED = 0x2D3D, + SMSG_MOVE_SET_RUN_SPEED = 0x2D3C, + SMSG_MOVE_SET_SWIM_BACK_SPEED = 0x2D3F, + SMSG_MOVE_SET_SWIM_SPEED = 0x2D3E, + SMSG_MOVE_SET_TURN_RATE = 0x2D43, + SMSG_MOVE_SET_VEHICLE_REC_ID = 0x2D5C, + SMSG_MOVE_SET_WALK_SPEED = 0x2D42, + SMSG_MOVE_SET_WATER_WALK = 0x2D47, + SMSG_MOVE_SKIP_TIME = 0x2D60, + SMSG_MOVE_SPLINE_DISABLE_COLLISION = 0x2D65, + SMSG_MOVE_SPLINE_DISABLE_GRAVITY = 0x2D63, + SMSG_MOVE_SPLINE_ENABLE_COLLISION = 0x2D66, + SMSG_MOVE_SPLINE_ENABLE_GRAVITY = 0x2D64, + SMSG_MOVE_SPLINE_ROOT = 0x2D61, + SMSG_MOVE_SPLINE_SET_FEATHER_FALL = 0x2D67, + SMSG_MOVE_SPLINE_SET_FLIGHT_BACK_SPEED = 0x2D38, + SMSG_MOVE_SPLINE_SET_FLIGHT_SPEED = 0x2D37, + SMSG_MOVE_SPLINE_SET_FLYING = 0x2D71, + SMSG_MOVE_SPLINE_SET_HOVER = 0x2D69, + SMSG_MOVE_SPLINE_SET_LAND_WALK = 0x2D6C, + SMSG_MOVE_SPLINE_SET_NORMAL_FALL = 0x2D68, + SMSG_MOVE_SPLINE_SET_PITCH_RATE = 0x2D3B, + SMSG_MOVE_SPLINE_SET_RUN_BACK_SPEED = 0x2D34, + SMSG_MOVE_SPLINE_SET_RUN_MODE = 0x2D6F, + SMSG_MOVE_SPLINE_SET_RUN_SPEED = 0x2D33, + SMSG_MOVE_SPLINE_SET_SWIM_BACK_SPEED = 0x2D36, + SMSG_MOVE_SPLINE_SET_SWIM_SPEED = 0x2D35, + SMSG_MOVE_SPLINE_SET_TURN_RATE = 0x2D3A, + SMSG_MOVE_SPLINE_SET_WALK_MODE = 0x2D70, + SMSG_MOVE_SPLINE_SET_WALK_SPEED = 0x2D39, + SMSG_MOVE_SPLINE_SET_WATER_WALK = 0x2D6B, + SMSG_MOVE_SPLINE_START_SWIM = 0x2D6D, + SMSG_MOVE_SPLINE_STOP_SWIM = 0x2D6E, + SMSG_MOVE_SPLINE_UNROOT = 0x2D62, + SMSG_MOVE_SPLINE_UNSET_FLYING = 0x2D72, + SMSG_MOVE_SPLINE_UNSET_HOVER = 0x2D6A, + SMSG_MOVE_TELEPORT = 0x2D4E, + SMSG_MOVE_UNROOT = 0x2D46, + SMSG_MOVE_UNSET_CAN_FLY = 0x2D50, + SMSG_MOVE_UNSET_CAN_TURN_WHILE_FALLING = 0x2D52, + SMSG_MOVE_UNSET_HOVERING = 0x2D4C, + SMSG_MOVE_UNSET_IGNORE_MOVEMENT_FORCES = 0x2D54, + SMSG_MOVE_UPDATE = 0x2D2C, + SMSG_MOVE_UPDATE_APPLY_MOVEMENT_FORCE = 0x2D30, + SMSG_MOVE_UPDATE_COLLISION_HEIGHT = 0x2D2B, + SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED = 0x2D28, + SMSG_MOVE_UPDATE_FLIGHT_SPEED = 0x2D27, + SMSG_MOVE_UPDATE_KNOCK_BACK = 0x2D2E, + SMSG_MOVE_UPDATE_PITCH_RATE = 0x2D2A, + SMSG_MOVE_UPDATE_REMOVE_MOVEMENT_FORCE = 0x2D31, + SMSG_MOVE_UPDATE_RUN_BACK_SPEED = 0x2D23, + SMSG_MOVE_UPDATE_RUN_SPEED = 0x2D22, + SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0x2D26, + SMSG_MOVE_UPDATE_SWIM_SPEED = 0x2D25, + SMSG_MOVE_UPDATE_TELEPORT = 0x2D2D, + SMSG_MOVE_UPDATE_TURN_RATE = 0x2D29, + SMSG_MOVE_UPDATE_WALK_SPEED = 0x2D24, + SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT = 0x2575, + SMSG_NEW_TAXI_PATH = 0x2628, + SMSG_NEW_WORLD = 0x2531, + SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x2BC1, + SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION = 0x2653, + SMSG_NOTIFY_MONEY = 0x2534, + SMSG_NOTIFY_RECEIVED_MAIL = 0x25D9, + SMSG_OFFER_PETITION_ERROR = 0x2662, + SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x269E, + SMSG_ON_MONSTER_MOVE = 0x2D20, + SMSG_OPEN_CONTAINER = 0x26E3, + SMSG_OPEN_LFG_DUNGEON_FINDER = 0x29B0, + SMSG_OPEN_SHIPMENT_NPC_FROM_GOSSIP = 0x2754, + SMSG_OPEN_SHIPMENT_NPC_RESULT = 0x2756, + SMSG_OVERRIDE_LIGHT = 0x2669, + SMSG_PAGE_TEXT = 0x26D8, + SMSG_PARTY_COMMAND_RESULT = 0x2751, + SMSG_PARTY_INVITE = 0x2555, + SMSG_PARTY_KILL_LOG = 0x271B, + SMSG_PARTY_MEMBER_STATE = 0x2719, + SMSG_PARTY_UPDATE = 0x258E, + SMSG_PAUSE_MIRROR_TIMER = 0x26D0, + SMSG_PENDING_RAID_LOCK = 0x26B2, + SMSG_PETITION_ALREADY_SIGNED = 0x253E, + SMSG_PETITION_RENAME_GUILD_RESPONSE = 0x2974, + SMSG_PETITION_SHOW_LIST = 0x266C, + SMSG_PETITION_SHOW_SIGNATURES = 0x266D, + SMSG_PETITION_SIGN_RESULTS = 0x270D, + SMSG_PET_ACTION_FEEDBACK = 0x270B, + SMSG_PET_ACTION_SOUND = 0x264A, + SMSG_PET_ADDED = 0x252E, + SMSG_PET_BATTLE_CHAT_RESTRICTED = 0x259B, + SMSG_PET_BATTLE_DEBUG_QUEUE_DUMP_RESPONSE = 0x261D, + SMSG_PET_BATTLE_FINALIZE_LOCATION = 0x2594, + SMSG_PET_BATTLE_FINAL_ROUND = 0x2599, + SMSG_PET_BATTLE_FINISHED = 0x259A, + SMSG_PET_BATTLE_FIRST_ROUND = 0x2596, + SMSG_PET_BATTLE_INITIAL_UPDATE = 0x2595, + SMSG_PET_BATTLE_MAX_GAME_LENGTH_WARNING = 0x259C, + SMSG_PET_BATTLE_PVP_CHALLENGE = 0x2593, + SMSG_PET_BATTLE_QUEUE_PROPOSE_MATCH = 0x25D6, + SMSG_PET_BATTLE_QUEUE_STATUS = 0x25D7, + SMSG_PET_BATTLE_REPLACEMENTS_MADE = 0x2598, + SMSG_PET_BATTLE_REQUEST_FAILED = 0x2592, + SMSG_PET_BATTLE_ROUND_RESULT = 0x2597, + SMSG_PET_BATTLE_SLOT_UPDATES = 0x2585, + SMSG_PET_CAST_FAILED = 0x2BD3, + SMSG_PET_CLEAR_SPELLS = 0x2BA1, + SMSG_PET_DISMISS_SOUND = 0x264B, + SMSG_PET_GOD_MODE = 0x2625, + SMSG_PET_GUIDS = 0x26C3, + SMSG_PET_LEARNED_SPELLS = 0x2BCD, + SMSG_PET_MODE = 0x2506, + SMSG_PET_NAME_INVALID = 0x2671, + SMSG_PET_SLOT_UPDATED = 0x2505, + SMSG_PET_SPELLS_MESSAGE = 0x2BA2, + SMSG_PET_STABLE_LIST = 0x252F, + SMSG_PET_STABLE_RESULT = 0x2530, + SMSG_PET_TAME_FAILURE = 0x265F, + SMSG_PET_UNLEARNED_SPELLS = 0x2BCE, + SMSG_PHASE_SHIFT_CHANGE = 0x24F5, + SMSG_PLAYED_TIME = 0x268A, + SMSG_PLAYER_BOUND = 0x24FB, + SMSG_PLAYER_SAVE_GUILD_EMBLEM = 0x2973, + SMSG_PLAYER_SKINNED = 0x2706, + SMSG_PLAYER_TABARD_VENDOR_ACTIVATE = 0x271A, + SMSG_PLAY_MUSIC = 0x2728, + SMSG_PLAY_OBJECT_SOUND = 0x2729, + SMSG_PLAY_ONE_SHOT_ANIM_KIT = 0x26F0, + SMSG_PLAY_ORPHAN_SPELL_VISUAL = 0x2BC5, + SMSG_PLAY_SCENE = 0x25D3, + SMSG_PLAY_SOUND = 0x2727, + SMSG_PLAY_SPEAKERBOT_SOUND = 0x272A, + SMSG_PLAY_SPELL_VISUAL = 0x2BC3, + SMSG_PLAY_SPELL_VISUAL_KIT = 0x2BC7, + SMSG_PLAY_TIME_WARNING = 0x26BC, + SMSG_PONG = 0x2FCB, + SMSG_POWER_UPDATE = 0x2680, + SMSG_PRE_RESSURECT = 0x2726, + SMSG_PRINT_NOTIFICATION = 0x2566, + SMSG_PROC_RESIST = 0x271C, + SMSG_PROPOSE_LEVEL_GRANT = 0x2692, + SMSG_PVP_CREDIT = 0x2698, + SMSG_PVP_LOG_DATA = 0x2539, + SMSG_PVP_OPTIONS_ENABLED = 0x253C, + SMSG_PVP_SEASON = 0x2559, + SMSG_QUERY_BATTLE_PET_NAME_RESPONSE = 0x2685, + SMSG_QUERY_CREATURE_RESPONSE = 0x267D, + SMSG_QUERY_GAME_OBJECT_RESPONSE = 0x267E, + SMSG_QUERY_GARRISON_CREATURE_NAME_RESPONSE = 0x28A2, + SMSG_QUERY_GUILD_INFO_RESPONSE = 0x2962, + SMSG_QUERY_ITEM_TEXT_RESPONSE = 0x2778, + SMSG_QUERY_NPC_TEXT_RESPONSE = 0x2681, + SMSG_QUERY_PAGE_TEXT_RESPONSE = 0x2683, + SMSG_QUERY_PETITION_RESPONSE = 0x2686, + SMSG_QUERY_PET_NAME_RESPONSE = 0x2684, + SMSG_QUERY_PLAYER_NAME_RESPONSE = 0x2682, + SMSG_QUERY_QUEST_INFO_RESPONSE = 0x2A12, + SMSG_QUERY_TIME_RESPONSE = 0x269C, + SMSG_QUEST_COMPLETION_NPC_RESPONSE = 0x29FF, + SMSG_QUEST_CONFIRM_ACCEPT = 0x2A0B, + SMSG_QUEST_FORCE_REMOVED = 0x2A17, + SMSG_QUEST_GIVER_INVALID_QUEST = 0x2A02, + SMSG_QUEST_GIVER_OFFER_REWARD_MESSAGE = 0x2A10, + SMSG_QUEST_GIVER_QUEST_COMPLETE = 0x2A00, + SMSG_QUEST_GIVER_QUEST_DETAILS = 0x2A0E, + SMSG_QUEST_GIVER_QUEST_FAILED = 0x2A03, + SMSG_QUEST_GIVER_QUEST_LIST_MESSAGE = 0x2A15, + SMSG_QUEST_GIVER_REQUEST_ITEMS = 0x2A0F, + SMSG_QUEST_GIVER_STATUS = 0x2A16, + SMSG_QUEST_GIVER_STATUS_MULTIPLE = 0x2A0D, + SMSG_QUEST_LOG_FULL = 0x2A04, + SMSG_QUEST_POI_QUERY_RESPONSE = 0x2A18, + SMSG_QUEST_PUSH_RESULT = 0x2A0C, + SMSG_QUEST_UPDATE_ADD_CREDIT = 0x2A08, + SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE = 0x2A09, + SMSG_QUEST_UPDATE_ADD_PVP_CREDIT = 0x2A0A, + SMSG_QUEST_UPDATE_COMPLETE = 0x2A05, + SMSG_QUEST_UPDATE_FAILED = 0x2A06, + SMSG_QUEST_UPDATE_FAILED_TIMER = 0x2A07, + SMSG_RAF_EMAIL_ENABLED_RESPONSE = 0x2742, + SMSG_RAID_DIFFICULTY_SET = 0x2761, + SMSG_RAID_GROUP_ONLY = 0x2763, + SMSG_RAID_INSTANCE_MESSAGE = 0x2B37, + SMSG_RAID_MARKERS_CHANGED = 0x253F, + SMSG_RANDOM_ROLL = 0x25CD, + SMSG_RATED_BATTLEFIELD_INFO = 0x252C, + SMSG_READY_CHECK_COMPLETED = 0x2591, + SMSG_READY_CHECK_RESPONSE = 0x2590, + SMSG_READY_CHECK_STARTED = 0x258F, + SMSG_READ_ITEM_RESULT_FAILED = 0x275C, + SMSG_READ_ITEM_RESULT_OK = 0x275B, + SMSG_REALM_QUERY_RESPONSE = 0x2668, + SMSG_RECRUIT_A_FRIEND_RESPONSE = 0x2743, + SMSG_REFER_A_FRIEND_EXPIRED = 0x26E1, + SMSG_REFER_A_FRIEND_FAILURE = 0x266E, + SMSG_REFRESH_COMPONENT = 0x25F9, + SMSG_REFRESH_SPELL_HISTORY = 0x2BAA, + SMSG_REMOVE_ITEM_PASSIVE = 0x2546, + SMSG_REMOVE_LOSS_OF_CONTROL = 0x2618, + SMSG_REPLACE_TROPHY_RESPONSE = 0x2775, + SMSG_REPORT_PVP_PLAYER_AFK_RESULT = 0x265B, + SMSG_REQUEST_ADDON_LIST = 0x25DF, + SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x2525, + SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0x255A, + SMSG_RESEARCH_COMPLETE = 0x2503, + SMSG_RESET_COMPRESSION_CONTEXT = 0x2FCC, + SMSG_RESET_FAILED_NOTIFY = 0x2663, + SMSG_RESET_RANGED_COMBAT_TIMER = 0x2695, + SMSG_RESET_WEEKLY_CURRENCY = 0x24F2, + SMSG_RESPEC_WIPE_CONFIRM = 0x25A8, + SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x24EF, + SMSG_RESUME_CAST_BAR = 0x2BBB, + SMSG_RESUME_COMMS = 0x2FC8, + SMSG_RESUME_TOKEN = 0x2544, + SMSG_RESURRECT_REQUEST = 0x24FC, + SMSG_RESYNC_RUNES = 0x26BF, + SMSG_ROLE_CHANGED_INFORM = 0x2509, + SMSG_ROLE_CHOSEN = 0x29B8, + SMSG_ROLE_POLL_INFORM = 0x250A, + SMSG_RUNE_REGEN_DEBUG = 0x254D, + SMSG_SCENARIO_BOOT = 0x275D, + SMSG_SCENARIO_COMPLETED = 0x2788, + SMSG_SCENARIO_OUT_OF_BOUNDS = 0x275E, + SMSG_SCENARIO_POIS = 0x25CF, + SMSG_SCENARIO_PROGRESS_UPDATE = 0x25C9, + SMSG_SCENARIO_STATE = 0x25C8, + SMSG_SCENE_OBJECT_EVENT = 0x257B, + SMSG_SCENE_OBJECT_PET_BATTLE_FINAL_ROUND = 0x2580, + SMSG_SCENE_OBJECT_PET_BATTLE_FINISHED = 0x2581, + SMSG_SCENE_OBJECT_PET_BATTLE_FIRST_ROUND = 0x257D, + SMSG_SCENE_OBJECT_PET_BATTLE_INITIAL_UPDATE = 0x257C, + SMSG_SCENE_OBJECT_PET_BATTLE_REPLACEMENTS_MADE = 0x257F, + SMSG_SCENE_OBJECT_PET_BATTLE_ROUND_RESULT = 0x257E, + SMSG_SCRIPT_CAST = 0x2BD1, + SMSG_SELL_RESPONSE = 0x2672, + SMSG_SEND_ITEM_PASSIVES = 0x2547, + SMSG_SEND_KNOWN_SPELLS = 0x2BA8, + SMSG_SEND_RAID_TARGET_UPDATE_ALL = 0x25CB, + SMSG_SEND_RAID_TARGET_UPDATE_SINGLE = 0x25CC, + SMSG_SEND_SPELL_CHARGES = 0x2BAB, + SMSG_SEND_SPELL_HISTORY = 0x2BA9, + SMSG_SEND_UNLEARN_SPELLS = 0x2BAC, + SMSG_SERVER_FIRST_ACHIEVEMENT = 0x2B3F, + SMSG_SERVER_FIRST_ACHIEVEMENTS = 0x25EB, + SMSG_SERVER_TIME = 0x262C, + SMSG_SETUP_CURRENCY = 0x24F0, + SMSG_SETUP_RESEARCH_HISTORY = 0x2502, + SMSG_SET_AI_ANIM_KIT = 0x26EF, + SMSG_SET_ALL_TASK_PROGRESS = 0x274B, + SMSG_SET_ANIM_TIER = 0x26F3, + SMSG_SET_CURRENCY = 0x24F1, + SMSG_SET_DF_FAST_LAUNCH_RESULT = 0x29AC, + SMSG_SET_DUNGEON_DIFFICULTY = 0x264F, + SMSG_SET_FACTION_AT_WAR = 0x26BE, + SMSG_SET_FACTION_NOT_VISIBLE = 0x26EA, + SMSG_SET_FACTION_STANDING = 0x26EB, + SMSG_SET_FACTION_VISIBLE = 0x26E9, + SMSG_SET_FLAT_SPELL_MODIFIER = 0x2BB5, + SMSG_SET_FORCED_REACTIONS = 0x26DB, + SMSG_SET_ITEM_PURCHASE_DATA = 0x2536, + SMSG_SET_LOOT_METHOD_FAILED = 0x2784, + SMSG_SET_MAX_WEEKLY_QUANTITY = 0x253D, + SMSG_SET_MELEE_ANIM_KIT = 0x26F2, + SMSG_SET_MOVEMENT_ANIM_KIT = 0x26F1, + SMSG_SET_PCT_SPELL_MODIFIER = 0x2BB6, + SMSG_SET_PET_SPECIALIZATION = 0x25C2, + SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x2689, + SMSG_SET_PLAY_HOVER_ANIM = 0x2551, + SMSG_SET_PROFICIENCY = 0x26F4, + SMSG_SET_SPELL_CHARGES = 0x2BA7, + SMSG_SET_TASK_COMPLETE = 0x274C, + SMSG_SET_TIME_ZONE_INFORMATION = 0x2620, + SMSG_SET_VEHICLE_REC_ID = 0x26B1, + SMSG_SHOW_BANK = 0x2629, + SMSG_SHOW_MAILBOX = 0x275F, + SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI = 0x2574, + SMSG_SHOW_TAXI_NODES = 0x2679, + SMSG_SHOW_TRADE_SKILL_RESPONSE = 0x272F, + SMSG_SOCKET_GEMS = 0x26E7, + SMSG_SOR_START_EXPERIENCE_INCOMPLETE = 0x2576, + SMSG_SPECIAL_MOUNT_ANIM = 0x2649, + SMSG_SPELL_ABSORB_LOG = 0x2B9C, + SMSG_SPELL_CHANNEL_START = 0x2BB3, + SMSG_SPELL_CHANNEL_UPDATE = 0x2BB4, + SMSG_SPELL_COOLDOWN = 0x2B93, + SMSG_SPELL_DAMAGE_SHIELD = 0x2BAF, + SMSG_SPELL_DELAYED = 0x2BBC, + SMSG_SPELL_DISPELL_LOG = 0x2B98, + SMSG_SPELL_ENERGIZE_LOG = 0x2B9A, + SMSG_SPELL_EXECUTE_LOG = 0x2BBD, + SMSG_SPELL_FAILED_OTHER = 0x2BD0, + SMSG_SPELL_FAILURE = 0x2BCF, + SMSG_SPELL_GO = 0x2BB7, + SMSG_SPELL_HEAL_LOG = 0x2B9B, + SMSG_SPELL_INSTAKILL_LOG = 0x2BB1, + SMSG_SPELL_INTERRUPT_LOG = 0x2B9D, + SMSG_SPELL_MISS_LOG = 0x2BBE, + SMSG_SPELL_MULTISTRIKE_EFFECT = 0x2BC0, + SMSG_SPELL_NON_MELEE_DAMAGE_LOG = 0x2BB0, + SMSG_SPELL_OR_DAMAGE_IMMUNE = 0x2BAD, + SMSG_SPELL_PERIODIC_AURA_LOG = 0x2B99, + SMSG_SPELL_START = 0x2BB8, + SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x2BB2, + SMSG_SPIRIT_HEALER_CONFIRM = 0x26D5, + SMSG_STAND_STATE_UPDATE = 0x26DA, + SMSG_START_ELAPSED_TIMER = 0x259D, + SMSG_START_ELAPSED_TIMERS = 0x259F, + SMSG_START_LOOT_ROLL = 0x25B3, + SMSG_START_MIRROR_TIMER = 0x26CF, + SMSG_START_TIMER = 0x2541, + SMSG_STOP_ELAPSED_TIMER = 0x259E, + SMSG_STOP_MIRROR_TIMER = 0x26D1, + SMSG_STOP_SPEAKERBOT_SOUND = 0x272B, + SMSG_STREAMING_MOVIES = 0x2540, + SMSG_SUMMON_CANCEL = 0x265A, + SMSG_SUMMON_RAID_MEMBER_VALIDATE_FAILED = 0x250B, + SMSG_SUMMON_REQUEST = 0x26DF, + SMSG_SUPERCEDED_SPELLS = 0x2BCA, + SMSG_SUPPRESS_NPC_GREETINGS = 0x2554, + SMSG_SUSPEND_COMMS = 0x2FC7, + SMSG_SUSPEND_TOKEN = 0x2543, + SMSG_TALENTS_INVOLUNTARILY_RESET = 0x26D7, + SMSG_TAXI_NODE_STATUS = 0x2626, + SMSG_TEXT_EMOTE = 0x2624, + SMSG_THREAT_CLEAR = 0x2691, + SMSG_THREAT_REMOVE = 0x2690, + SMSG_THREAT_UPDATE = 0x268F, + SMSG_TIME_ADJUSTMENT = 0x2D1F, + SMSG_TIME_SYNC_REQUEST = 0x2D1E, + SMSG_TITLE_EARNED = 0x268C, + SMSG_TITLE_LOST = 0x268D, + SMSG_TOTEM_CREATED = 0x2675, + SMSG_TOTEM_MOVED = 0x2676, + SMSG_TRADE_STATUS = 0x24FF, + SMSG_TRADE_UPDATED = 0x24FE, + SMSG_TRAINER_BUY_FAILED = 0x2697, + SMSG_TRAINER_LIST = 0x2696, + SMSG_TRANSFER_ABORTED = 0x26C2, + SMSG_TRANSFER_PENDING = 0x2569, + SMSG_TRIGGER_CINEMATIC = 0x277C, + SMSG_TRIGGER_MOVIE = 0x2677, + SMSG_TURN_IN_PETITION_RESULT = 0x270F, + SMSG_TUTORIAL_FLAGS = 0x2770, + SMSG_TWITTER_STATUS = 0x2F7B, + SMSG_UI_TIME = 0x26D4, + SMSG_UNDELETE_CHARACTER_RESPONSE = 0x277F, + SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE = 0x2780, + SMSG_UNLEARNED_SPELLS = 0x2BCC, + SMSG_UPDATE_ACCOUNT_DATA = 0x26C9, + SMSG_UPDATE_ACTION_BUTTONS = 0x2579, + SMSG_UPDATE_CHARACTER_FLAGS = 0x2774, + SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT = 0x29AF, + SMSG_UPDATE_EXPANSION_LEVEL = 0x25E4, + SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x2652, + SMSG_UPDATE_LAST_INSTANCE = 0x2632, + SMSG_UPDATE_OBJECT = 0x277D, + SMSG_UPDATE_TALENT_DATA = 0x256E, + SMSG_UPDATE_TASK_PROGRESS = 0x274A, + SMSG_UPDATE_WEEKLY_SPELL_USAGE = 0x2B97, + SMSG_UPDATE_WORLD_STATE = 0x270A, + SMSG_USERLIST_ADD = 0x2B3C, + SMSG_USERLIST_REMOVE = 0x2B3D, + SMSG_USERLIST_UPDATE = 0x2B3E, + SMSG_USE_EQUIPMENT_SET_RESULT = 0x2710, + SMSG_VENDOR_INVENTORY = 0x254F, + SMSG_VIGNETTE_UPDATE = 0x272D, + SMSG_VOICE_CHAT_STATUS = 0x2B31, + SMSG_VOICE_PARENTAL_CONTROLS = 0x2B32, + SMSG_VOICE_SESSION_LEAVE = 0x2B34, + SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x2B33, + SMSG_VOID_ITEM_SWAP_RESPONSE = 0x2564, + SMSG_VOID_STORAGE_CONTENTS = 0x2561, + SMSG_VOID_STORAGE_FAILED = 0x2560, + SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0x2562, + SMSG_VOID_TRANSFER_RESULT = 0x2563, + SMSG_WAIT_QUEUE_FINISH = 0x24EC, + SMSG_WAIT_QUEUE_UPDATE = 0x24EB, + SMSG_WARDEN_DATA = 0x24F4, + SMSG_WARGAME_REQUEST_SUCCESSFULLY_SENT_TO_OPPONENT = 0x253A, + SMSG_WEATHER = 0x2651, + SMSG_WEEKLY_SPELL_USAGE = 0x2B96, + SMSG_WHO = 0x2B2C, + SMSG_WHO_IS = 0x2650, + SMSG_WORLD_SERVER_INFO = 0x2548, + SMSG_WORLD_TEXT = 0x2789, + SMSG_WOW_TOKEN_AUCTION_SOLD = 0x2790, + SMSG_WOW_TOKEN_BUY_REQUEST_CONFIRMATION = 0x2792, + SMSG_WOW_TOKEN_BUY_RESULT_CONFIRMATION = 0x2793, + SMSG_WOW_TOKEN_MARKET_PRICE_RESPONSE = 0x278D, + SMSG_WOW_TOKEN_REDEEM_GAME_TIME_UPDATED = 0x2794, + SMSG_WOW_TOKEN_REDEEM_REQUEST_CONFIRMATION = 0x2795, + SMSG_WOW_TOKEN_REDEEM_RESULT = 0x2796, + SMSG_WOW_TOKEN_SELL_REQUEST_CONFIRMATION = 0x278E, + SMSG_WOW_TOKEN_SELL_RESULT_CONFIRMATION = 0x278F, + SMSG_WOW_TOKEN_UPDATE_AUCTIONABLE_LIST_RESPONSE = 0x2797, + SMSG_XP_GAIN_ABORTED = 0x2565, + SMSG_XP_GAIN_ENABLED = 0x2762, + SMSG_ZONE_UNDER_ATTACK = 0x2B38, // Opcodes that are not generated automatically SMSG_ACCOUNT_HEIRLOOM_UPDATE = 0xBADD, // no client handler - SMSG_CHUNKED_PACKET = 0x0227, - SMSG_COMPRESSED_PACKET = 0x0224, - SMSG_FINAL_CHUNK = 0x02A4, - SMSG_MULTIPLE_PACKETS = 0x0303, + SMSG_COMPRESSED_PACKET = 0x2FCF, + SMSG_MULTIPLE_PACKETS = 0x2FCE, // Deleted opcodes, here only to allow compile SMSG_ARENA_TEAM_STATS = 0xBADD, diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp index c780c27ccf0..2d088606023 100644 --- a/src/server/game/Server/Protocol/PacketLog.cpp +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -70,6 +70,12 @@ PacketLog::~PacketLog() _file = NULL; } +PacketLog* PacketLog::instance() +{ + static PacketLog instance; + return &instance; +} + void PacketLog::Initialize() { std::string logsDir = sConfigMgr->GetStringDefault("LogsDir", ""); diff --git a/src/server/game/Server/Protocol/PacketLog.h b/src/server/game/Server/Protocol/PacketLog.h index f7c8652bd66..329658f0789 100644 --- a/src/server/game/Server/Protocol/PacketLog.h +++ b/src/server/game/Server/Protocol/PacketLog.h @@ -32,7 +32,7 @@ enum Direction class WorldPacket; -class PacketLog +class TC_GAME_API PacketLog { private: PacketLog(); @@ -41,11 +41,7 @@ class PacketLog std::once_flag _initializeFlag; public: - static PacketLog* instance() - { - static PacketLog instance; - return &instance; - } + static PacketLog* instance(); void Initialize(); bool CanLogPacket() const { return (_file != NULL); } diff --git a/src/server/game/Server/Protocol/ServerPktHeader.h b/src/server/game/Server/Protocol/ServerPktHeader.h index 6ca65c9e5fb..d3fe37de94a 100644 --- a/src/server/game/Server/Protocol/ServerPktHeader.h +++ b/src/server/game/Server/Protocol/ServerPktHeader.h @@ -26,13 +26,13 @@ union ServerPktHeader struct { uint16 Size; - uint32 Command; + uint16 Command; } Setup; struct { - uint32 Command : 13; - uint32 Size : 19; + uint32 Size; + uint16 Command; } Normal; }; diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 78e7bbfc180..ebb3ea02896 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -42,7 +42,6 @@ #include "SocialMgr.h" #include "ScriptMgr.h" #include "WardenWin.h" -#include "BattlenetServerManager.h" #include "AuthenticationPackets.h" #include "CharacterPackets.h" #include "ClientConfigPackets.h" @@ -419,12 +418,12 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) } break; case STATUS_NEVER: - TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str() - , GetPlayerInfo().c_str()); + TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str() + , GetPlayerInfo().c_str()); break; case STATUS_UNHANDLED: - TC_LOG_ERROR("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str() - , GetPlayerInfo().c_str()); + TC_LOG_ERROR("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str() + , GetPlayerInfo().c_str()); break; } } @@ -612,8 +611,6 @@ void WorldSession::LogoutPlayer(bool save) TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Logout Character:[%s] (%s) Level: %d", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), _player->getLevel()); - sBattlenetServer.SendChangeToonOnlineState(GetBattlenetAccountId(), GetAccountId(), _player->GetGUID(), _player->GetName(), false); - if (Map* _map = _player->FindMap()) _map->RemovePlayerFromMap(_player, true); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 9655968dcb3..1bcc9d0b373 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -863,7 +863,7 @@ struct PacketCounter }; /// Player session in the World -class WorldSession +class TC_GAME_API WorldSession { public: WorldSession(uint32 id, std::string&& name, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index acec25a7363..84561dbd37e 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -20,10 +20,12 @@ #include "AuthenticationPackets.h" #include "BigNumber.h" #include "CharacterPackets.h" +#include "HmacHash.h" #include "Opcodes.h" -#include "ScriptMgr.h" -#include "SHA1.h" #include "PacketLog.h" +#include "ScriptMgr.h" +#include "SessionKeyGeneration.h" +#include "SHA256.h" #include "World.h" #include <zlib.h> @@ -53,22 +55,24 @@ private: using boost::asio::ip::tcp; +uint32 const WorldSocket::ConnectionInitializeMagic = 0xF5EB1CE; std::string const WorldSocket::ServerConnectionInitialize("WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT"); std::string const WorldSocket::ClientConnectionInitialize("WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER"); uint32 const WorldSocket::MinSizeForCompression = 0x400; -uint32 const SizeOfClientHeader[2][2] = -{ - { 2, 0 }, - { 6, 4 } -}; +uint32 const SizeOfClientHeader[2] = { sizeof(uint16) + sizeof(uint16), sizeof(uint32) + sizeof(uint16) }; +uint32 const SizeOfServerHeader[2] = { sizeof(uint16) + sizeof(uint16), sizeof(uint32) + sizeof(uint16) }; + +uint8 const WorldSocket::AuthCheckSeed[16] = { 0xC5, 0xC6, 0x98, 0x95, 0x76, 0x3F, 0x1D, 0xCD, 0xB6, 0xA1, 0x37, 0x28, 0xB3, 0x12, 0xFF, 0x8A }; +uint8 const WorldSocket::SessionKeySeed[16] = { 0x58, 0xCB, 0xCF, 0x40, 0xFE, 0x2E, 0xCE, 0xA6, 0x5A, 0x90, 0xB8, 0x01, 0x68, 0x6C, 0x28, 0x0B }; +uint8 const WorldSocket::ContinuedSessionSeed[16] = { 0x16, 0xAD, 0x0C, 0xD4, 0x46, 0xF9, 0x4F, 0xB2, 0xEF, 0x7D, 0xEA, 0x2A, 0x17, 0x66, 0x4D, 0x2F }; -uint32 const SizeOfServerHeader[2] = { sizeof(uint16) + sizeof(uint32), sizeof(uint32) }; WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)), - _type(CONNECTION_TYPE_REALM), _authSeed(rand32()), _OverSpeedPings(0), - _worldSession(nullptr), _authed(false), _compressionStream(nullptr), _initialized(false) + _type(CONNECTION_TYPE_REALM), _OverSpeedPings(0), + _worldSession(nullptr), _authed(false), _compressionStream(nullptr) { - _headerBuffer.Resize(SizeOfClientHeader[0][0]); + _serverChallenge.SetRand(8 * 16); + _headerBuffer.Resize(SizeOfClientHeader[0]); } WorldSocket::~WorldSocket() @@ -116,11 +120,14 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result) } } - AsyncRead(); + _packetBuffer.Resize(4 + 2 + ClientConnectionInitialize.length() + 1); + + AsyncReadWithCallback(&WorldSocket::InitializeHandler); MessageBuffer initializer; ServerPktHeader header; header.Setup.Size = ServerConnectionInitialize.size(); + initializer.Write(&ConnectionInitializeMagic, sizeof(ConnectionInitializeMagic)); initializer.Write(&header, sizeof(header.Setup.Size)); initializer.Write(ServerConnectionInitialize.c_str(), ServerConnectionInitialize.length()); @@ -128,6 +135,71 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result) QueuePacket(std::move(initializer)); } +void WorldSocket::InitializeHandler(boost::system::error_code error, std::size_t transferedBytes) +{ + if (error) + { + CloseSocket(); + return; + } + + GetReadBuffer().WriteCompleted(transferedBytes); + + MessageBuffer& packet = GetReadBuffer(); + if (packet.GetActiveSize() > 0) + { + if (_packetBuffer.GetRemainingSpace() > 0) + { + // need to receive the header + std::size_t readHeaderSize = std::min(packet.GetActiveSize(), _packetBuffer.GetRemainingSpace()); + _packetBuffer.Write(packet.GetReadPointer(), readHeaderSize); + packet.ReadCompleted(readHeaderSize); + + if (_packetBuffer.GetRemainingSpace() > 0) + { + // Couldn't receive the whole header this time. + ASSERT(packet.GetActiveSize() == 0); + AsyncReadWithCallback(&WorldSocket::InitializeHandler); + return; + } + + uint32 magic; + uint16 length; + ByteBuffer buffer(std::move(_packetBuffer)); + + buffer >> magic; + buffer >> length; + std::string initializer = buffer.ReadString(length); + if (magic != ConnectionInitializeMagic || initializer != ClientConnectionInitialize) + { + CloseSocket(); + return; + } + + _compressionStream = new z_stream(); + _compressionStream->zalloc = (alloc_func)NULL; + _compressionStream->zfree = (free_func)NULL; + _compressionStream->opaque = (voidpf)NULL; + _compressionStream->avail_in = 0; + _compressionStream->next_in = NULL; + int32 z_res = deflateInit2(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION), Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + if (z_res != Z_OK) + { + CloseSocket(); + TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res)); + return; + } + + _packetBuffer.Reset(); + HandleSendAuthSession(); + AsyncRead(); + return; + } + } + + AsyncReadWithCallback(&WorldSocket::InitializeHandler); +} + bool WorldSocket::Update() { EncryptablePacket* queued; @@ -179,7 +251,7 @@ void WorldSocket::HandleSendAuthSession() _decryptSeed.SetRand(16 * 8); WorldPackets::Auth::AuthChallenge challenge; - challenge.Challenge = _authSeed; + memcpy(challenge.Challenge.data(), _serverChallenge.AsByteArray(16).get(), 16); memcpy(&challenge.DosChallenge[0], _encryptSeed.AsByteArray(16).get(), 16); memcpy(&challenge.DosChallenge[4], _decryptSeed.AsByteArray(16).get(), 16); challenge.DosZeroBits = 1; @@ -261,14 +333,12 @@ void WorldSocket::ExtractOpcodeAndSize(ClientPktHeader const* header, uint32& op if (_authCrypt.IsInitialized()) { opcode = header->Normal.Command; - size = header->Normal.Size; + size = header->Normal.Size - 2; } else { opcode = header->Setup.Command; - size = header->Setup.Size; - if (_initialized) - size -= 4; + size = header->Setup.Size - 2; } } @@ -281,9 +351,9 @@ void WorldSocket::SetWorldSession(WorldSession* session) bool WorldSocket::ReadHeaderHandler() { - ASSERT(_headerBuffer.GetActiveSize() == SizeOfClientHeader[_initialized][_authCrypt.IsInitialized()], "Header size " SZFMTD " different than expected %u", _headerBuffer.GetActiveSize(), SizeOfClientHeader[_initialized][_authCrypt.IsInitialized()]); + ASSERT(_headerBuffer.GetActiveSize() == SizeOfClientHeader[_authCrypt.IsInitialized()], "Header size " SZFMTD " different than expected %u", _headerBuffer.GetActiveSize(), SizeOfClientHeader[_authCrypt.IsInitialized()]); - _authCrypt.DecryptRecv(_headerBuffer.GetReadPointer(), _headerBuffer.GetActiveSize()); + _authCrypt.DecryptRecv(_headerBuffer.GetReadPointer(), 4); ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); uint32 opcode; @@ -291,7 +361,7 @@ bool WorldSocket::ReadHeaderHandler() ExtractOpcodeAndSize(header, opcode, size); - if (!ClientPktHeader::IsValidSize(size) || (_initialized && !ClientPktHeader::IsValidOpcode(opcode))) + if (!ClientPktHeader::IsValidSize(size) || !ClientPktHeader::IsValidOpcode(opcode)) { TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %u, cmd: %u)", GetRemoteIpAddress().to_string().c_str(), size, opcode); @@ -304,133 +374,106 @@ bool WorldSocket::ReadHeaderHandler() WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler() { - if (_initialized) - { - ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); - uint32 cmd; - uint32 size; + ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); + uint32 cmd; + uint32 size; - ExtractOpcodeAndSize(header, cmd, size); + ExtractOpcodeAndSize(header, cmd, size); - OpcodeClient opcode = static_cast<OpcodeClient>(cmd); + OpcodeClient opcode = static_cast<OpcodeClient>(cmd); - WorldPacket packet(opcode, std::move(_packetBuffer), GetConnectionType()); + WorldPacket packet(opcode, std::move(_packetBuffer), GetConnectionType()); - if (sPacketLog->CanLogPacket()) - sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort(), GetConnectionType()); + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort(), GetConnectionType()); - std::unique_lock<std::mutex> sessionGuard(_worldSessionLock, std::defer_lock); + std::unique_lock<std::mutex> sessionGuard(_worldSessionLock, std::defer_lock); - switch (opcode) + switch (opcode) + { + case CMSG_PING: + LogOpcodeText(opcode, sessionGuard); + return HandlePing(packet) ? ReadDataHandlerResult::Ok : ReadDataHandlerResult::Error; + case CMSG_AUTH_SESSION: { - case CMSG_PING: - LogOpcodeText(opcode, sessionGuard); - return HandlePing(packet) ? ReadDataHandlerResult::Ok : ReadDataHandlerResult::Error; - case CMSG_AUTH_SESSION: + LogOpcodeText(opcode, sessionGuard); + if (_authed) { - LogOpcodeText(opcode, sessionGuard); - if (_authed) - { - // locking just to safely log offending user is probably overkill but we are disconnecting him anyway - if (sessionGuard.try_lock()) - TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); - return ReadDataHandlerResult::Error; - } - - std::shared_ptr<WorldPackets::Auth::AuthSession> authSession = std::make_shared<WorldPackets::Auth::AuthSession>(std::move(packet)); - authSession->Read(); - HandleAuthSession(authSession); - return ReadDataHandlerResult::WaitingForQuery; + // locking just to safely log offending user is probably overkill but we are disconnecting him anyway + if (sessionGuard.try_lock()) + TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); + return ReadDataHandlerResult::Error; } - case CMSG_AUTH_CONTINUED_SESSION: - { - LogOpcodeText(opcode, sessionGuard); - if (_authed) - { - // locking just to safely log offending user is probably overkill but we are disconnecting him anyway - if (sessionGuard.try_lock()) - TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_CONTINUED_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); - return ReadDataHandlerResult::Error; - } - std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession = std::make_shared<WorldPackets::Auth::AuthContinuedSession>(std::move(packet)); - authSession->Read(); - HandleAuthContinuedSession(authSession); - return ReadDataHandlerResult::WaitingForQuery; - } - case CMSG_KEEP_ALIVE: - LogOpcodeText(opcode, sessionGuard); - break; - case CMSG_LOG_DISCONNECT: - LogOpcodeText(opcode, sessionGuard); - packet.rfinish(); // contains uint32 disconnectReason; - break; - case CMSG_ENABLE_NAGLE: - LogOpcodeText(opcode, sessionGuard); - SetNoDelay(false); - break; - case CMSG_CONNECT_TO_FAILED: + std::shared_ptr<WorldPackets::Auth::AuthSession> authSession = std::make_shared<WorldPackets::Auth::AuthSession>(std::move(packet)); + authSession->Read(); + HandleAuthSession(authSession); + return ReadDataHandlerResult::WaitingForQuery; + } + case CMSG_AUTH_CONTINUED_SESSION: + { + LogOpcodeText(opcode, sessionGuard); + if (_authed) { - sessionGuard.lock(); - - LogOpcodeText(opcode, sessionGuard); - WorldPackets::Auth::ConnectToFailed connectToFailed(std::move(packet)); - connectToFailed.Read(); - HandleConnectToFailed(connectToFailed); - break; + // locking just to safely log offending user is probably overkill but we are disconnecting him anyway + if (sessionGuard.try_lock()) + TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_CONTINUED_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); + return ReadDataHandlerResult::Error; } - default: - { - sessionGuard.lock(); - LogOpcodeText(opcode, sessionGuard); + std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession = std::make_shared<WorldPackets::Auth::AuthContinuedSession>(std::move(packet)); + authSession->Read(); + HandleAuthContinuedSession(authSession); + return ReadDataHandlerResult::WaitingForQuery; + } + case CMSG_KEEP_ALIVE: + LogOpcodeText(opcode, sessionGuard); + break; + case CMSG_LOG_DISCONNECT: + LogOpcodeText(opcode, sessionGuard); + packet.rfinish(); // contains uint32 disconnectReason; + break; + case CMSG_ENABLE_NAGLE: + LogOpcodeText(opcode, sessionGuard); + SetNoDelay(false); + break; + case CMSG_CONNECT_TO_FAILED: + { + sessionGuard.lock(); - if (!_worldSession) - { - TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); - return ReadDataHandlerResult::Error; - } + LogOpcodeText(opcode, sessionGuard); + WorldPackets::Auth::ConnectToFailed connectToFailed(std::move(packet)); + connectToFailed.Read(); + HandleConnectToFailed(connectToFailed); + break; + } + default: + { + sessionGuard.lock(); - OpcodeHandler const* handler = opcodeTable[opcode]; - if (!handler) - { - TC_LOG_ERROR("network.opcode", "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet.GetOpcode())).c_str(), _worldSession->GetPlayerInfo().c_str()); - break; - } + LogOpcodeText(opcode, sessionGuard); - // Our Idle timer will reset on any non PING opcodes. - // Catches people idling on the login screen and any lingering ingame connections. - _worldSession->ResetTimeOutTime(); + if (!_worldSession) + { + TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); + return ReadDataHandlerResult::Error; + } - // Copy the packet to the heap before enqueuing - _worldSession->QueuePacket(new WorldPacket(std::move(packet))); + OpcodeHandler const* handler = opcodeTable[opcode]; + if (!handler) + { + TC_LOG_ERROR("network.opcode", "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet.GetOpcode())).c_str(), _worldSession->GetPlayerInfo().c_str()); break; } - } - } - else - { - std::string initializer(reinterpret_cast<char const*>(_packetBuffer.GetReadPointer()), std::min(_packetBuffer.GetActiveSize(), ClientConnectionInitialize.length())); - if (initializer != ClientConnectionInitialize) - return ReadDataHandlerResult::Error; - - _compressionStream = new z_stream(); - _compressionStream->zalloc = (alloc_func)NULL; - _compressionStream->zfree = (free_func)NULL; - _compressionStream->opaque = (voidpf)NULL; - _compressionStream->avail_in = 0; - _compressionStream->next_in = NULL; - int32 z_res = deflateInit2(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION), Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); - if (z_res != Z_OK) - { - TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res)); - return ReadDataHandlerResult::Error; - } - _initialized = true; - _headerBuffer.Resize(SizeOfClientHeader[1][0]); - _packetBuffer.Reset(); - HandleSendAuthSession(); + // Our Idle timer will reset on any non PING opcodes. + // Catches people idling on the login screen and any lingering ingame connections. + _worldSession->ResetTimeOutTime(); + + // Copy the packet to the heap before enqueuing + _worldSession->QueuePacket(new WorldPacket(std::move(packet))); + break; + } } return ReadDataHandlerResult::Ok; @@ -480,8 +523,8 @@ void WorldSocket::WritePacketToBuffer(EncryptablePacket const& packet, MessageBu if (packetSize > MinSizeForCompression && packet.NeedsEncryption()) { CompressedWorldPacket cmp; - cmp.UncompressedSize = packetSize + 4; - cmp.UncompressedAdler = adler32(adler32(0x9827D8F1, (Bytef*)&opcode, 4), packet.contents(), packetSize); + cmp.UncompressedSize = packetSize + 2; + cmp.UncompressedAdler = adler32(adler32(0x9827D8F1, (Bytef*)&opcode, 2), packet.contents(), packetSize); // Reserve space for compression info - uncompressed size and checksums uint8* compressionInfo = buffer.GetWritePointer(); @@ -500,15 +543,17 @@ void WorldSocket::WritePacketToBuffer(EncryptablePacket const& packet, MessageBu else if (!packet.empty()) buffer.Write(packet.contents(), packet.size()); + packetSize += 2 /*opcode*/; + if (packet.NeedsEncryption()) { header.Normal.Size = packetSize; header.Normal.Command = opcode; - _authCrypt.EncryptSend((uint8*)&header, sizeOfHeader); + _authCrypt.EncryptSend((uint8*)&header, 4); } else { - header.Setup.Size = packetSize + 4; + header.Setup.Size = packetSize; header.Setup.Command = opcode; } @@ -518,12 +563,12 @@ void WorldSocket::WritePacketToBuffer(EncryptablePacket const& packet, MessageBu uint32 WorldSocket::CompressPacket(uint8* buffer, WorldPacket const& packet) { uint32 opcode = packet.GetOpcode(); - uint32 bufferSize = deflateBound(_compressionStream, packet.size() + sizeof(opcode)); + uint32 bufferSize = deflateBound(_compressionStream, packet.size() + sizeof(uint16)); _compressionStream->next_out = buffer; _compressionStream->avail_out = bufferSize; _compressionStream->next_in = (Bytef*)&opcode; - _compressionStream->avail_in = sizeof(uint32); + _compressionStream->avail_in = sizeof(uint16); int32 z_res = deflate(_compressionStream, Z_NO_FLUSH); if (z_res != Z_OK) @@ -554,7 +599,6 @@ struct AccountInfo std::string LastIP; std::string LockCountry; LocaleConstant Locale; - std::string OS; bool IsBanned; } BattleNet; @@ -566,6 +610,7 @@ struct AccountInfo uint8 Expansion; int64 MuteTime; uint32 Recruiter; + std::string OS; bool IsRectuiter; AccountTypes Security; bool IsBanned; @@ -575,8 +620,8 @@ struct AccountInfo explicit AccountInfo(Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 - // SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, ba.os, ba.id, aa.gmLevel, + // 0 1 2 3 4 5 6 7 8 9 10 11 + // SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.gmLevel, // 12 13 14 // bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id // FROM account a LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) @@ -591,7 +636,7 @@ struct AccountInfo Game.MuteTime = fields[6].GetInt64(); BattleNet.Locale = LocaleConstant(fields[7].GetUInt8()); Game.Recruiter = fields[8].GetUInt32(); - BattleNet.OS = fields[9].GetString(); + Game.OS = fields[9].GetString(); BattleNet.Id = fields[10].GetUInt32(); Game.Security = AccountTypes(fields[11].GetUInt8()); BattleNet.IsBanned = fields[12].GetUInt64() != 0; @@ -610,12 +655,12 @@ struct AccountInfo void WorldSocket::HandleAuthSession(std::shared_ptr<WorldPackets::Auth::AuthSession> authSession) { // Client switches packet headers after sending CMSG_AUTH_SESSION - _headerBuffer.Resize(SizeOfClientHeader[1][1]); + _headerBuffer.Resize(SizeOfClientHeader[1]); // Get the account information from the auth database PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME); stmt->setInt32(0, int32(realm.Id.Realm)); - stmt->setString(1, authSession->Account); + stmt->setString(1, authSession->RealmJoinTicket); _queryCallback = std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1); _queryFuture = LoginDatabase.AsyncQuery(stmt); @@ -627,7 +672,6 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: if (!result) { // We can not log here, as we do not know the account. Thus, no accountId. - SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); DelayedCloseSocket(); return; @@ -638,16 +682,43 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: // For hook purposes, we get Remoteaddress at this point. std::string address = GetRemoteIpAddress().to_string(); + HmacSha256 hmac(SHA256_DIGEST_LENGTH, account.Game.SessionKey.AsByteArray(SHA256_DIGEST_LENGTH).get()); + hmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); + hmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + hmac.UpdateData(AuthCheckSeed, 16); + hmac.Finalize(); + + if (memcmp(hmac.GetDigest(), authSession->Digest.data(), authSession->Digest.size()) != 0) + { + TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Game.Id, authSession->RealmJoinTicket.c_str(), address.c_str()); + DelayedCloseSocket(); + return; + } + + HmacSha256 sessionKeyHmac(SHA256_DIGEST_LENGTH, account.Game.SessionKey.AsByteArray(SHA256_DIGEST_LENGTH).get()); + sessionKeyHmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + sessionKeyHmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); + sessionKeyHmac.UpdateData(SessionKeySeed, 16); + sessionKeyHmac.Finalize(); + + uint8 sessionKey[40]; + SessionKeyGenerator<SHA256Hash> sessionKeyGenerator(sessionKeyHmac.GetDigest(), sessionKeyHmac.GetLength()); + sessionKeyGenerator.Generate(sessionKey, 40); + + BigNumber K; + K.SetBinary(sessionKey, 40); + + // Check that Key and account name are the same on client and server + // only do this after verifying credentials - no error message is better than bad encryption making the client crash + _authCrypt.Init(&K); + // As we don't know if attempted login process by ip works, we update last_attempt_ip right away PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP); stmt->setString(0, address); - stmt->setString(1, authSession->Account); + stmt->setString(1, authSession->RealmJoinTicket); LoginDatabase.Execute(stmt); // This also allows to check for possible "hack" attempts on account - // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it - _authCrypt.Init(&account.Game.SessionKey); - // First reject the connection if packet contains invalid data or realm state doesn't allow logging in if (sWorld->IsClosed()) { @@ -668,37 +739,10 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: // Must be done before WorldSession is created bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED); - if (wardenActive && account.BattleNet.OS != "Win" && account.BattleNet.OS != "Wn64" && account.BattleNet.OS != "Mc64") + if (wardenActive && account.Game.OS != "Win" && account.Game.OS != "Wn64" && account.Game.OS != "Mc64") { SendAuthResponseError(AUTH_REJECT); - TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), account.BattleNet.OS.c_str()); - DelayedCloseSocket(); - return; - } - - if (!account.BattleNet.Id || authSession->LoginServerType != 1) - { - SendAuthResponseError(AUTH_REJECT); - TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s (%s) attempted to log in using deprecated login method (GRUNT).", authSession->Account.c_str(), address.c_str()); - DelayedCloseSocket(); - return; - } - - // Check that Key and account name are the same on client and server - uint32 t = 0; - - SHA1Hash sha; - sha.UpdateData(authSession->Account); - sha.UpdateData((uint8*)&t, 4); - sha.UpdateData((uint8*)&authSession->LocalChallenge, 4); - sha.UpdateData((uint8*)&_authSeed, 4); - sha.UpdateBigNumbers(&account.Game.SessionKey, NULL); - sha.Finalize(); - - if (memcmp(sha.GetDigest(), authSession->Digest, SHA_DIGEST_LENGTH) != 0) - { - SendAuthResponseError(AUTH_FAILED); - TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Game.Id, authSession->Account.c_str(), address.c_str()); + TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), account.Game.OS.c_str()); DelayedCloseSocket(); return; } @@ -762,13 +806,13 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: return; } - TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", authSession->Account.c_str(), address.c_str()); + TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", authSession->RealmJoinTicket.c_str(), address.c_str()); // Update the last_ip in the database as it was successful for login stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP); stmt->setString(0, address); - stmt->setString(1, authSession->Account); + stmt->setString(1, authSession->RealmJoinTicket); LoginDatabase.Execute(stmt); @@ -776,13 +820,13 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth:: sScriptMgr->OnAccountLogin(account.Game.Id); _authed = true; - _worldSession = new WorldSession(account.Game.Id, std::move(authSession->Account), account.BattleNet.Id, shared_from_this(), account.Game.Security, + _worldSession = new WorldSession(account.Game.Id, std::move(authSession->RealmJoinTicket), account.BattleNet.Id, shared_from_this(), account.Game.Security, account.Game.Expansion, mutetime, account.BattleNet.Locale, account.Game.Recruiter, account.Game.IsRectuiter); _worldSession->ReadAddonsInfo(authSession->AddonInfo); // Initialize Warden system only if it is enabled by config if (wardenActive) - _worldSession->InitWarden(&account.Game.SessionKey, account.BattleNet.OS); + _worldSession->InitWarden(&account.Game.SessionKey, account.Game.OS); _queryCallback = std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1); _queryFuture = _worldSession->LoadPermissionsAsync(); @@ -811,7 +855,7 @@ void WorldSocket::HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth: } // Client switches packet headers after sending CMSG_AUTH_CONTINUED_SESSION - _headerBuffer.Resize(SizeOfClientHeader[1][1]); + _headerBuffer.Resize(SizeOfClientHeader[1]); uint32 accountId = uint32(key.Fields.AccountId); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION); @@ -841,13 +885,14 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPacket _authCrypt.Init(&k, _encryptSeed.AsByteArray().get(), _decryptSeed.AsByteArray().get()); - SHA1Hash sha; - sha.UpdateData(login); - sha.UpdateBigNumbers(&k, NULL); - sha.UpdateData((uint8*)&_authSeed, 4); - sha.Finalize(); + HmacSha256 hmac(40, k.AsByteArray(40).get()); + hmac.UpdateData(reinterpret_cast<uint8 const*>(&authSession->Key), sizeof(authSession->Key)); + hmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size()); + hmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16); + hmac.UpdateData(ContinuedSessionSeed, 16); + hmac.Finalize(); - if (memcmp(sha.GetDigest(), authSession->Digest, sha.GetLength())) + if (memcmp(hmac.GetDigest(), authSession->Digest.data(), authSession->Digest.size())) { SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT); TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: Authentication failed for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str()); diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 205494ca4ea..a5593e83521 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -52,13 +52,13 @@ union ClientPktHeader struct { uint16 Size; - uint32 Command; + uint16 Command; } Setup; struct { - uint32 Command : 13; - uint32 Size : 19; + uint32 Size; + uint16 Command; } Normal; static bool IsValidSize(uint32 size) { return size < 10240; } @@ -67,12 +67,17 @@ union ClientPktHeader #pragma pack(pop) -class WorldSocket : public Socket<WorldSocket> +class TC_GAME_API WorldSocket : public Socket<WorldSocket> { + static uint32 const ConnectionInitializeMagic; static std::string const ServerConnectionInitialize; static std::string const ClientConnectionInitialize; static uint32 const MinSizeForCompression; + static uint8 const AuthCheckSeed[16]; + static uint8 const SessionKeySeed[16]; + static uint8 const ContinuedSessionSeed[16]; + typedef Socket<WorldSocket> BaseSocket; public: @@ -107,6 +112,7 @@ protected: ReadDataHandlerResult ReadDataHandler(); private: void CheckIpCallback(PreparedQueryResult result); + void InitializeHandler(boost::system::error_code error, std::size_t transferedBytes); /// writes network.opcode log /// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock @@ -130,7 +136,7 @@ private: ConnectionType _type; - uint32 _authSeed; + BigNumber _serverChallenge; WorldPacketCrypt _authCrypt; BigNumber _encryptSeed; BigNumber _decryptSeed; @@ -148,8 +154,6 @@ private: z_stream_s* _compressionStream; - bool _initialized; - PreparedQueryResultFuture _queryFuture; std::function<void(PreparedQueryResult&&)> _queryCallback; std::string _ipCountry; diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp index 4f42e943245..53a22a80449 100644 --- a/src/server/game/Server/WorldSocketMgr.cpp +++ b/src/server/game/Server/WorldSocketMgr.cpp @@ -52,6 +52,12 @@ WorldSocketMgr::~WorldSocketMgr() ASSERT(!_instanceAcceptor, "StopNetwork must be called prior to WorldSocketMgr destruction"); } +WorldSocketMgr& WorldSocketMgr::Instance() +{ + static WorldSocketMgr instance; + return instance; +} + bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) { _tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true); diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h index 2079b62d14f..fd86d3b7931 100644 --- a/src/server/game/Server/WorldSocketMgr.h +++ b/src/server/game/Server/WorldSocketMgr.h @@ -30,18 +30,14 @@ class WorldSocket; /// Manages all sockets connected to peers and network threads -class WorldSocketMgr : public SocketMgr<WorldSocket> +class TC_GAME_API WorldSocketMgr : public SocketMgr<WorldSocket> { typedef SocketMgr<WorldSocket> BaseSocketMgr; public: ~WorldSocketMgr(); - static WorldSocketMgr& Instance() - { - static WorldSocketMgr instance; - return instance; - } + static WorldSocketMgr& Instance(); /// Start network, listen at address:port . bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override; diff --git a/src/server/game/Skills/SkillDiscovery.h b/src/server/game/Skills/SkillDiscovery.h index b7fe1cdc8b2..c2020e5b075 100644 --- a/src/server/game/Skills/SkillDiscovery.h +++ b/src/server/game/Skills/SkillDiscovery.h @@ -23,8 +23,9 @@ class Player; -void LoadSkillDiscoveryTable(); -uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player); -bool HasDiscoveredAllSpells(uint32 spellId, Player* player); -uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player); +TC_GAME_API void LoadSkillDiscoveryTable(); +TC_GAME_API uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player); +TC_GAME_API bool HasDiscoveredAllSpells(uint32 spellId, Player* player); +TC_GAME_API uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player); + #endif diff --git a/src/server/game/Skills/SkillExtraItems.h b/src/server/game/Skills/SkillExtraItems.h index 2889b221600..5a477b65f0b 100644 --- a/src/server/game/Skills/SkillExtraItems.h +++ b/src/server/game/Skills/SkillExtraItems.h @@ -23,12 +23,14 @@ // predef classes used in functions class Player; + // returns true and sets the appropriate info if the player can create a perfect item with the given spellId -bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType); +TC_GAME_API bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType); // load perfection proc info from DB -void LoadSkillPerfectItemTable(); +TC_GAME_API void LoadSkillPerfectItemTable(); // returns true and sets the appropriate info if the player can create extra items with the given spellId -bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax); +TC_GAME_API bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax); // function to load the extra item creation info from DB -void LoadSkillExtraItemTable(); +TC_GAME_API void LoadSkillExtraItemTable(); + #endif diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 1da2f73a2f2..ea6b607e7a3 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -772,10 +772,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= tru { // Haste modifies periodic time of channeled spells if (m_spellInfo->IsChanneled()) - { - if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) - caster->ModSpellCastTime(m_spellInfo, m_period); - } + caster->ModSpellDurationTime(m_spellInfo, m_period); else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) m_period = int32(m_period * caster->GetFloatValue(UNIT_MOD_CAST_SPEED)); } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 95ace9c7a32..0d907e4148c 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -27,7 +27,7 @@ class Aura; typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const* aurApp, uint8 mode, bool apply) const; -class AuraEffect +class TC_GAME_API AuraEffect { friend void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 7ad36c58956..65cdbced339 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -47,7 +47,7 @@ class ChargeDropEvent; // update aura target map every 500 ms instead of every update - reduce amount of grid searcher calls #define UPDATE_TARGET_MAP_INTERVAL 500 -class AuraApplication +class TC_GAME_API AuraApplication { friend void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask); friend void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); @@ -113,7 +113,7 @@ struct AuraLoadEffectInfo }; #pragma pack(pop) -class Aura +class TC_GAME_API Aura { friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); public: @@ -326,7 +326,7 @@ class Aura SpellEffectInfoVector _spelEffectInfos; }; -class UnitAura : public Aura +class TC_GAME_API UnitAura : public Aura { friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); public: @@ -347,7 +347,7 @@ class UnitAura : public Aura DiminishingGroup m_AuraDRGroup:8; // Diminishing }; -class DynObjAura : public Aura +class TC_GAME_API DynObjAura : public Aura { friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); public: @@ -358,7 +358,7 @@ class DynObjAura : public Aura void FillTargetMap(std::map<Unit*, uint32> & targets, Unit* caster) override; }; -class ChargeDropEvent : public BasicEvent +class TC_GAME_API ChargeDropEvent : public BasicEvent { friend class Aura; protected: diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 579dc0b8a06..256600e4010 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2648,7 +2648,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA { // Haste modifies duration of channeled spells if (m_spellInfo->IsChanneled()) - m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this); + m_originalCaster->ModSpellDurationTime(aurSpellInfo, duration, this); else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) { int32 origDuration = duration; @@ -3313,7 +3313,7 @@ void Spell::handle_immediate() modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); // Apply haste mods - m_caster->ModSpellCastTime(m_spellInfo, duration, this); + m_caster->ModSpellDurationTime(m_spellInfo, duration, this); m_spellState = SPELL_STATE_CASTING; m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index a7c9b91a31f..dd6d39f6030 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -115,7 +115,7 @@ enum SpellRangeFlag SPELL_RANGE_RANGED = 2 //hunter range and ranged weapon }; -struct SpellDestination +struct TC_GAME_API SpellDestination { SpellDestination(); SpellDestination(float x, float y, float z, float orientation = 0.0f, uint32 mapId = MAPID_INVALID); @@ -167,7 +167,7 @@ struct SpellLogEffectFeedPetParams int32 ItemID = 0; }; -class SpellCastTargets +class TC_GAME_API SpellCastTargets { public: SpellCastTargets(); @@ -291,7 +291,7 @@ enum SpellEffectHandleMode typedef std::list<std::pair<uint32, ObjectGuid>> DispelList; -class Spell +class TC_GAME_API Spell { friend void Unit::SetCurrentCastSpell(Spell* pSpell); friend class SpellScript; @@ -851,7 +851,7 @@ class Spell namespace Trinity { - struct WorldObjectSpellTargetCheck + struct TC_GAME_API WorldObjectSpellTargetCheck { Unit* _caster; Unit* _referer; @@ -866,7 +866,7 @@ namespace Trinity bool operator()(WorldObject* target); }; - struct WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck + struct TC_GAME_API WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck { float _range; Position const* _position; @@ -875,7 +875,7 @@ namespace Trinity bool operator()(WorldObject* target); }; - struct WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck + struct TC_GAME_API WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck { float _range; Position const* _position; @@ -884,7 +884,7 @@ namespace Trinity bool operator()(WorldObject* target); }; - struct WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck + struct TC_GAME_API WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck { float _coneAngle; WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster, @@ -892,7 +892,7 @@ namespace Trinity bool operator()(WorldObject* target); }; - struct WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck + struct TC_GAME_API WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck { WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo); bool operator()(WorldObject* target); @@ -901,7 +901,7 @@ namespace Trinity typedef void(Spell::*pEffect)(SpellEffIndex effIndex); -class SpellEvent : public BasicEvent +class TC_GAME_API SpellEvent : public BasicEvent { public: SpellEvent(Spell* spell); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 59428220bea..0c2fc2e5d91 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2307,9 +2307,12 @@ void Spell::EffectDispel(SpellEffIndex effIndex) return; // Ok if exist some buffs for dispel try dispel it - uint32 failCount = 0; DispelChargesList success_list; - WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4); + WorldPackets::Spells::DispelFailed dispelFailed; + dispelFailed.CasterGUID = m_caster->GetGUID(); + dispelFailed.VictimGUID = unitTarget->GetGUID(); + dispelFailed.SpellID = m_spellInfo->Id; + // dispel N = damage buffs (or while exist buffs for dispel) for (int32 count = 0; count < damage && !dispel_list.empty();) { @@ -2344,23 +2347,14 @@ void Spell::EffectDispel(SpellEffIndex effIndex) dispel_list.erase(itr); } else - { - if (!failCount) - { - // Failed to dispell - dataFail << m_caster->GetGUID(); // Caster GUID - dataFail << unitTarget->GetGUID(); // Victim GUID - dataFail << uint32(m_spellInfo->Id); // dispel spell id - } - ++failCount; - dataFail << uint32(itr->first->GetId()); // Spell Id - } + dispelFailed.FailedSpells.push_back(int32(itr->first->GetId())); + ++count; } } - if (failCount) - m_caster->SendMessageToSet(&dataFail, true); + if (!dispelFailed.FailedSpells.empty()) + m_caster->SendMessageToSet(dispelFailed.Write(), true); if (success_list.empty()) return; @@ -5163,9 +5157,12 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex /*effIndex*/) return; // Ok if exist some buffs for dispel try dispel it - uint32 failCount = 0; DispelList success_list; - WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4); + WorldPackets::Spells::DispelFailed dispelFailed; + dispelFailed.CasterGUID = m_caster->GetGUID(); + dispelFailed.VictimGUID = unitTarget->GetGUID(); + dispelFailed.SpellID = m_spellInfo->Id; + // dispel N = damage buffs (or while exist buffs for dispel) for (int32 count = 0; count < damage && !steal_list.empty();) { @@ -5190,23 +5187,14 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex /*effIndex*/) steal_list.erase(itr); } else - { - if (!failCount) - { - // Failed to dispell - dataFail << m_caster->GetGUID(); // Caster GUID - dataFail << unitTarget->GetGUID(); // Victim GUID - dataFail << uint32(m_spellInfo->Id); // dispel spell id - } - ++failCount; - dataFail << uint32(itr->first->GetId()); // Spell Id - } + dispelFailed.FailedSpells.push_back(int32(itr->first->GetId())); + ++count; } } - if (failCount) - m_caster->SendMessageToSet(&dataFail, true); + if (!dispelFailed.FailedSpells.empty()) + m_caster->SendMessageToSet(dispelFailed.Write(), true); if (success_list.empty()) return; diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h index c63fdc63e47..f2a3d346fdf 100644 --- a/src/server/game/Spells/SpellHistory.h +++ b/src/server/game/Spells/SpellHistory.h @@ -39,7 +39,7 @@ enum SpellCooldownFlags SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS = 0x2 ///< Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUDE_GCD set }; -class SpellHistory +class TC_GAME_API SpellHistory { public: typedef std::chrono::system_clock Clock; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 8f321bccc6d..b8e9b10efc4 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -204,7 +204,7 @@ enum SpellCustomAttributes uint32 GetTargetFlagMask(SpellTargetObjectTypes objType); -class SpellImplicitTargetInfo +class TC_GAME_API SpellImplicitTargetInfo { private: Targets _target; @@ -235,7 +235,7 @@ private: static StaticData _data[TOTAL_SPELL_TARGETS]; }; -class SpellEffectInfo +class TC_GAME_API SpellEffectInfo { SpellInfo const* _spellInfo; public: @@ -323,7 +323,7 @@ typedef std::unordered_map<uint32, SpellVisualVector> SpellVisualMap; typedef std::vector<AuraEffect*> AuraEffectVector; -class SpellInfo +class TC_GAME_API SpellInfo { public: uint32 Id; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index f735f4034a9..2c062e33259 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -472,6 +472,12 @@ SpellMgr::~SpellMgr() UnloadSpellInfoStore(); } +SpellMgr* SpellMgr::instance() +{ + static SpellMgr instance; + return &instance; +} + /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg) { @@ -3191,6 +3197,8 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; break; case 8145: // Tremor Totem (instant pulse) + spellInfo->AttributesEx2 |= SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS; + /*no break*/ case 6474: // Earthbind Totem (instant pulse) spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY; break; diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index e058ed84407..79721235c17 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -430,7 +430,7 @@ enum EffectRadiusIndex }; // Spell pet auras -class PetAura +class TC_GAME_API PetAura { private: typedef std::unordered_map<uint32, uint32> PetAuraMap; @@ -477,7 +477,7 @@ class PetAura }; typedef std::map<uint32, PetAura> SpellPetAuraMap; -struct SpellArea +struct TC_GAME_API SpellArea { uint32 spellId; uint32 areaId; // zone/subzone/or 0 is not limited to zone @@ -590,14 +590,14 @@ inline bool IsProfessionOrRidingSkill(uint32 skill) bool IsPartOfSkillLine(uint32 skillId, uint32 spellId); // spell diminishing returns -DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto); -DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); -DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group); -int32 GetDiminishingReturnsLimitDuration(SpellInfo const* spellproto); +TC_GAME_API DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto); +TC_GAME_API DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); +TC_GAME_API DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group); +TC_GAME_API int32 GetDiminishingReturnsLimitDuration(SpellInfo const* spellproto); -extern PetFamilySpellsStore sPetFamilySpellsStore; +TC_GAME_API extern PetFamilySpellsStore sPetFamilySpellsStore; -class SpellMgr +class TC_GAME_API SpellMgr { // Constructors private: @@ -606,11 +606,7 @@ class SpellMgr // Accessors (const or static functions) public: - static SpellMgr* instance() - { - static SpellMgr instance; - return &instance; - } + static SpellMgr* instance(); // Spell correctness for client using static bool IsSpellValid(SpellInfo const* spellInfo, Player* player = NULL, bool msg = true); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 02eaa2ef92f..aca3e074b9a 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -52,7 +52,7 @@ enum SpellScriptState #define SPELL_SCRIPT_STATE_END SPELL_SCRIPT_STATE_UNLOADING + 1 // helper class from which SpellScript and SpellAura derive, use these classes instead -class _SpellScript +class TC_GAME_API _SpellScript { // internal use classes & functions // DO NOT OVERRIDE THESE IN SCRIPTS @@ -68,7 +68,7 @@ class _SpellScript std::string const* _GetScriptName() const; protected: - class EffectHook + class TC_GAME_API EffectHook { public: EffectHook(uint8 _effIndex); @@ -82,7 +82,7 @@ class _SpellScript uint8 effIndex; }; - class EffectNameCheck + class TC_GAME_API EffectNameCheck { public: EffectNameCheck(uint16 _effName) { effName = _effName; } @@ -92,7 +92,7 @@ class _SpellScript uint16 effName; }; - class EffectAuraNameCheck + class TC_GAME_API EffectAuraNameCheck { public: EffectAuraNameCheck(uint16 _effAurName) { effAurName = _effAurName; } @@ -149,7 +149,7 @@ enum SpellScriptHookType #define HOOK_SPELL_END SPELL_SCRIPT_HOOK_CHECK_CAST + 1 #define HOOK_SPELL_COUNT HOOK_SPELL_END - HOOK_SPELL_START -class SpellScript : public _SpellScript +class TC_GAME_API SpellScript : public _SpellScript { // internal use classes & functions // DO NOT OVERRIDE THESE IN SCRIPTS @@ -165,7 +165,7 @@ class SpellScript : public _SpellScript SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript) - class CastHandler + class TC_GAME_API CastHandler { public: CastHandler(SpellCastFnType _pCastHandlerScript); @@ -174,7 +174,7 @@ class SpellScript : public _SpellScript SpellCastFnType pCastHandlerScript; }; - class CheckCastHandler + class TC_GAME_API CheckCastHandler { public: CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript); @@ -183,7 +183,7 @@ class SpellScript : public _SpellScript SpellCheckCastFnType _checkCastHandlerScript; }; - class EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook + class TC_GAME_API EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook { public: EffectHandler(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); @@ -194,7 +194,7 @@ class SpellScript : public _SpellScript SpellEffectFnType pEffectHandlerScript; }; - class HitHandler + class TC_GAME_API HitHandler { public: HitHandler(SpellHitFnType _pHitHandlerScript); @@ -203,7 +203,7 @@ class SpellScript : public _SpellScript SpellHitFnType pHitHandlerScript; }; - class TargetHook : public _SpellScript::EffectHook + class TC_GAME_API TargetHook : public _SpellScript::EffectHook { public: TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest); @@ -216,7 +216,7 @@ class SpellScript : public _SpellScript bool dest; }; - class ObjectAreaTargetSelectHandler : public TargetHook + class TC_GAME_API ObjectAreaTargetSelectHandler : public TargetHook { public: ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); @@ -225,7 +225,7 @@ class SpellScript : public _SpellScript SpellObjectAreaTargetSelectFnType pObjectAreaTargetSelectHandlerScript; }; - class ObjectTargetSelectHandler : public TargetHook + class TC_GAME_API ObjectTargetSelectHandler : public TargetHook { public: ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); @@ -234,7 +234,7 @@ class SpellScript : public _SpellScript SpellObjectTargetSelectFnType pObjectTargetSelectHandlerScript; }; - class DestinationTargetSelectHandler : public TargetHook + class TC_GAME_API DestinationTargetSelectHandler : public TargetHook { public: DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); @@ -472,7 +472,7 @@ enum AuraScriptHookType #define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1 #define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START */ -class AuraScript : public _SpellScript +class TC_GAME_API AuraScript : public _SpellScript { // internal use classes & functions // DO NOT OVERRIDE THESE IN SCRIPTS @@ -495,7 +495,7 @@ class AuraScript : public _SpellScript AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript) - class CheckAreaTargetHandler + class TC_GAME_API CheckAreaTargetHandler { public: CheckAreaTargetHandler(AuraCheckAreaTargetFnType pHandlerScript); @@ -503,7 +503,7 @@ class AuraScript : public _SpellScript private: AuraCheckAreaTargetFnType pHandlerScript; }; - class AuraDispelHandler + class TC_GAME_API AuraDispelHandler { public: AuraDispelHandler(AuraDispelFnType pHandlerScript); @@ -511,14 +511,14 @@ class AuraScript : public _SpellScript private: AuraDispelFnType pHandlerScript; }; - class EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook + class TC_GAME_API EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook { public: EffectBase(uint8 _effIndex, uint16 _effName); std::string ToString(); bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) override; }; - class EffectPeriodicHandler : public EffectBase + class TC_GAME_API EffectPeriodicHandler : public EffectBase { public: EffectPeriodicHandler(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); @@ -526,7 +526,7 @@ class AuraScript : public _SpellScript private: AuraEffectPeriodicFnType pEffectHandlerScript; }; - class EffectUpdatePeriodicHandler : public EffectBase + class TC_GAME_API EffectUpdatePeriodicHandler : public EffectBase { public: EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); @@ -534,7 +534,7 @@ class AuraScript : public _SpellScript private: AuraEffectUpdatePeriodicFnType pEffectHandlerScript; }; - class EffectCalcAmountHandler : public EffectBase + class TC_GAME_API EffectCalcAmountHandler : public EffectBase { public: EffectCalcAmountHandler(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); @@ -542,7 +542,7 @@ class AuraScript : public _SpellScript private: AuraEffectCalcAmountFnType pEffectHandlerScript; }; - class EffectCalcPeriodicHandler : public EffectBase + class TC_GAME_API EffectCalcPeriodicHandler : public EffectBase { public: EffectCalcPeriodicHandler(AuraEffectCalcPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); @@ -550,7 +550,7 @@ class AuraScript : public _SpellScript private: AuraEffectCalcPeriodicFnType pEffectHandlerScript; }; - class EffectCalcSpellModHandler : public EffectBase + class TC_GAME_API EffectCalcSpellModHandler : public EffectBase { public: EffectCalcSpellModHandler(AuraEffectCalcSpellModFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); @@ -558,7 +558,7 @@ class AuraScript : public _SpellScript private: AuraEffectCalcSpellModFnType pEffectHandlerScript; }; - class EffectApplyHandler : public EffectBase + class TC_GAME_API EffectApplyHandler : public EffectBase { public: EffectApplyHandler(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode); @@ -567,7 +567,7 @@ class AuraScript : public _SpellScript AuraEffectApplicationModeFnType pEffectHandlerScript; AuraEffectHandleModes mode; }; - class EffectAbsorbHandler : public EffectBase + class TC_GAME_API EffectAbsorbHandler : public EffectBase { public: EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex); @@ -575,7 +575,7 @@ class AuraScript : public _SpellScript private: AuraEffectAbsorbFnType pEffectHandlerScript; }; - class EffectManaShieldHandler : public EffectBase + class TC_GAME_API EffectManaShieldHandler : public EffectBase { public: EffectManaShieldHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex); @@ -583,7 +583,7 @@ class AuraScript : public _SpellScript private: AuraEffectAbsorbFnType pEffectHandlerScript; }; - class EffectSplitHandler : public EffectBase + class TC_GAME_API EffectSplitHandler : public EffectBase { public: EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex); @@ -591,7 +591,7 @@ class AuraScript : public _SpellScript private: AuraEffectSplitFnType pEffectHandlerScript; }; - class CheckProcHandler + class TC_GAME_API CheckProcHandler { public: CheckProcHandler(AuraCheckProcFnType handlerScript); @@ -599,7 +599,7 @@ class AuraScript : public _SpellScript private: AuraCheckProcFnType _HandlerScript; }; - class AuraProcHandler + class TC_GAME_API AuraProcHandler { public: AuraProcHandler(AuraProcFnType handlerScript); @@ -607,7 +607,7 @@ class AuraScript : public _SpellScript private: AuraProcFnType _HandlerScript; }; - class EffectProcHandler : public EffectBase + class TC_GAME_API EffectProcHandler : public EffectBase { public: EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName); @@ -647,7 +647,7 @@ class AuraScript : public _SpellScript AuraApplication const* m_auraApplication; bool m_defaultActionPrevented; - class ScriptStateStore + class TC_GAME_API ScriptStateStore { public: AuraApplication const* _auraApplication; diff --git a/src/server/game/Support/SupportMgr.cpp b/src/server/game/Support/SupportMgr.cpp index 7caccfd7cb2..97a828f44d6 100644 --- a/src/server/game/Support/SupportMgr.cpp +++ b/src/server/game/Support/SupportMgr.cpp @@ -362,6 +362,12 @@ SupportMgr::~SupportMgr() delete s.second; } +SupportMgr* SupportMgr::instance() +{ + static SupportMgr instance; + return &instance; +} + void SupportMgr::Initialize() { SetSupportSystemStatus(sWorld->getBoolConfig(CONFIG_SUPPORT_ENABLED)); @@ -403,6 +409,10 @@ SuggestionTicket* SupportMgr::GetTicket<SuggestionTicket>(uint32 suggestionId) } +template TC_GAME_API BugTicket* SupportMgr::GetTicket<BugTicket>(uint32); +template TC_GAME_API ComplaintTicket* SupportMgr::GetTicket<ComplaintTicket>(uint32); +template TC_GAME_API SuggestionTicket* SupportMgr::GetTicket<SuggestionTicket>(uint32); + template<> uint32 SupportMgr::GetOpenTicketCount<BugTicket>() const { return _openBugTicketCount; } @@ -412,6 +422,10 @@ uint32 SupportMgr::GetOpenTicketCount<ComplaintTicket>() const { return _openCom template<> uint32 SupportMgr::GetOpenTicketCount<SuggestionTicket>() const { return _openSuggestionTicketCount; } +template TC_GAME_API uint32 SupportMgr::GetOpenTicketCount<BugTicket>() const; +template TC_GAME_API uint32 SupportMgr::GetOpenTicketCount<ComplaintTicket>() const; +template TC_GAME_API uint32 SupportMgr::GetOpenTicketCount<SuggestionTicket>() const; + void SupportMgr::LoadBugTickets() { uint32 oldMSTime = getMSTime(); @@ -607,6 +621,10 @@ void SupportMgr::RemoveTicket<SuggestionTicket>(uint32 ticketId) } } +template TC_GAME_API void SupportMgr::RemoveTicket<BugTicket>(uint32); +template TC_GAME_API void SupportMgr::RemoveTicket<ComplaintTicket>(uint32); +template TC_GAME_API void SupportMgr::RemoveTicket<SuggestionTicket>(uint32); + template<> void SupportMgr::CloseTicket<BugTicket>(uint32 ticketId, ObjectGuid closedBy) { @@ -643,6 +661,10 @@ void SupportMgr::CloseTicket<SuggestionTicket>(uint32 ticketId, ObjectGuid close } } +template TC_GAME_API void SupportMgr::CloseTicket<BugTicket>(uint32, ObjectGuid); +template TC_GAME_API void SupportMgr::CloseTicket<ComplaintTicket>(uint32, ObjectGuid); +template TC_GAME_API void SupportMgr::CloseTicket<SuggestionTicket>(uint32, ObjectGuid); + template<> void SupportMgr::ResetTickets<BugTicket>() { @@ -684,6 +706,10 @@ void SupportMgr::ResetTickets<SuggestionTicket>() CharacterDatabase.Execute(stmt); } +template TC_GAME_API void SupportMgr::ResetTickets<BugTicket>(); +template TC_GAME_API void SupportMgr::ResetTickets<ComplaintTicket>(); +template TC_GAME_API void SupportMgr::ResetTickets<SuggestionTicket>(); + template<> void SupportMgr::ShowList<BugTicket>(ChatHandler& handler) const { @@ -711,6 +737,10 @@ void SupportMgr::ShowList<SuggestionTicket>(ChatHandler& handler) const handler.SendSysMessage(itr->second->FormatViewMessageString(handler).c_str()); } +template TC_GAME_API void SupportMgr::ShowList<BugTicket>(ChatHandler&) const; +template TC_GAME_API void SupportMgr::ShowList<ComplaintTicket>(ChatHandler&) const; +template TC_GAME_API void SupportMgr::ShowList<SuggestionTicket>(ChatHandler&) const; + template<> void SupportMgr::ShowClosedList<BugTicket>(ChatHandler& handler) const { @@ -737,3 +767,7 @@ void SupportMgr::ShowClosedList<SuggestionTicket>(ChatHandler& handler) const if (itr->second->IsClosed()) handler.SendSysMessage(itr->second->FormatViewMessageString(handler).c_str()); } + +template TC_GAME_API void SupportMgr::ShowClosedList<BugTicket>(ChatHandler&) const; +template TC_GAME_API void SupportMgr::ShowClosedList<ComplaintTicket>(ChatHandler&) const; +template TC_GAME_API void SupportMgr::ShowClosedList<SuggestionTicket>(ChatHandler&) const; diff --git a/src/server/game/Support/SupportMgr.h b/src/server/game/Support/SupportMgr.h index f79f71e7b2f..aafbbc2dd20 100644 --- a/src/server/game/Support/SupportMgr.h +++ b/src/server/game/Support/SupportMgr.h @@ -50,7 +50,7 @@ enum SupportSpamType using ChatLog = WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketChatLog; -class Ticket +class TC_GAME_API Ticket { public: Ticket(); @@ -116,7 +116,7 @@ protected: std::string _comment; }; -class BugTicket : public Ticket +class TC_GAME_API BugTicket : public Ticket { public: BugTicket(); @@ -140,7 +140,7 @@ private: std::string _note; }; -class ComplaintTicket : public Ticket +class TC_GAME_API ComplaintTicket : public Ticket { public: ComplaintTicket(); @@ -176,7 +176,7 @@ private: std::string _note; }; -class SuggestionTicket : public Ticket +class TC_GAME_API SuggestionTicket : public Ticket { public: SuggestionTicket(); @@ -204,18 +204,14 @@ typedef std::map<uint32, BugTicket*> BugTicketList; typedef std::map<uint32, ComplaintTicket*> ComplaintTicketList; typedef std::map<uint32, SuggestionTicket*> SuggestionTicketList; -class SupportMgr +class TC_GAME_API SupportMgr { private: SupportMgr(); ~SupportMgr(); public: - static SupportMgr* instance() - { - static SupportMgr instance; - return &instance; - } + static SupportMgr* instance(); template<typename T> T* GetTicket(uint32 ticketId); diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index edc9b5a67e6..f4bc3f7fcba 100644 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -76,6 +76,12 @@ class PlayerTextBuilder WorldObject const* _target; }; +CreatureTextMgr* CreatureTextMgr::instance() +{ + static CreatureTextMgr instance; + return &instance; +} + void CreatureTextMgr::LoadCreatureTexts() { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h index d0004ec51d3..5bff16ad812 100644 --- a/src/server/game/Texts/CreatureTextMgr.h +++ b/src/server/game/Texts/CreatureTextMgr.h @@ -76,18 +76,14 @@ typedef std::unordered_map<uint32, CreatureTextHolder> CreatureTextMap; // a typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap; -class CreatureTextMgr +class TC_GAME_API CreatureTextMgr { private: CreatureTextMgr() { } ~CreatureTextMgr() { } public: - static CreatureTextMgr* instance() - { - static CreatureTextMgr instance; - return &instance; - } + static CreatureTextMgr* instance(); void LoadCreatureTexts(); void LoadCreatureTextLocales(); diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.h b/src/server/game/Tools/CharacterDatabaseCleaner.h index ecbd6d0a790..f1e6900a6bb 100644 --- a/src/server/game/Tools/CharacterDatabaseCleaner.h +++ b/src/server/game/Tools/CharacterDatabaseCleaner.h @@ -30,20 +30,20 @@ namespace CharacterDatabaseCleaner CLEANING_FLAG_QUESTSTATUS = 0x10 }; - void CleanDatabase(); + TC_GAME_API void CleanDatabase(); - void CheckUnique(const char* column, const char* table, bool (*check)(uint32)); + TC_GAME_API void CheckUnique(const char* column, const char* table, bool (*check)(uint32)); - bool AchievementProgressCheck(uint32 criteria); - bool SkillCheck(uint32 skill); - bool SpellCheck(uint32 spell_id); - bool TalentCheck(uint32 talent_id); + TC_GAME_API bool AchievementProgressCheck(uint32 criteria); + TC_GAME_API bool SkillCheck(uint32 skill); + TC_GAME_API bool SpellCheck(uint32 spell_id); + TC_GAME_API bool TalentCheck(uint32 talent_id); - void CleanCharacterAchievementProgress(); - void CleanCharacterSkills(); - void CleanCharacterSpell(); - void CleanCharacterTalent(); - void CleanCharacterQuestStatus(); + TC_GAME_API void CleanCharacterAchievementProgress(); + TC_GAME_API void CleanCharacterSkills(); + TC_GAME_API void CleanCharacterSpell(); + TC_GAME_API void CleanCharacterTalent(); + TC_GAME_API void CleanCharacterQuestStatus(); } #endif diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h index 9f95572fd8c..66f4fd3fe13 100644 --- a/src/server/game/Tools/PlayerDump.h +++ b/src/server/game/Tools/PlayerDump.h @@ -65,7 +65,7 @@ enum DumpReturn DUMP_CHARACTER_DELETED }; -class PlayerDump +class TC_GAME_API PlayerDump { public: typedef std::set<ObjectGuid::LowType> DumpGuidSet; @@ -75,7 +75,7 @@ class PlayerDump PlayerDump() { } }; -class PlayerDumpWriter : public PlayerDump +class TC_GAME_API PlayerDumpWriter : public PlayerDump { public: PlayerDumpWriter() { } @@ -94,7 +94,7 @@ class PlayerDumpWriter : public PlayerDump DumpGuidSet items; }; -class PlayerDumpReader : public PlayerDump +class TC_GAME_API PlayerDumpReader : public PlayerDump { public: PlayerDumpReader() { } diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h index 35ee18d4c02..b0aa496cbe8 100644 --- a/src/server/game/Warden/Warden.h +++ b/src/server/game/Warden/Warden.h @@ -92,7 +92,7 @@ struct ClientWardenModule class WorldSession; -class Warden +class TC_GAME_API Warden { friend class WardenWin; friend class WardenMac; diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index 5c4b0fc05b7..13ddae012fe 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -189,6 +189,12 @@ void WardenCheckMgr::LoadWardenOverrides() TC_LOG_INFO("server.loading", ">> Loaded %u warden action overrides.", count); } +WardenCheckMgr* WardenCheckMgr::instance() +{ + static WardenCheckMgr instance; + return &instance; +} + WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 Id) { if (Id < CheckStore.size()) diff --git a/src/server/game/Warden/WardenCheckMgr.h b/src/server/game/Warden/WardenCheckMgr.h index 4107ccc3aff..7349fd5b589 100644 --- a/src/server/game/Warden/WardenCheckMgr.h +++ b/src/server/game/Warden/WardenCheckMgr.h @@ -48,18 +48,14 @@ struct WardenCheckResult BigNumber Result; // MEM_CHECK }; -class WardenCheckMgr +class TC_GAME_API WardenCheckMgr { private: WardenCheckMgr(); ~WardenCheckMgr(); public: - static WardenCheckMgr* instance() - { - static WardenCheckMgr instance; - return &instance; - } + static WardenCheckMgr* instance(); // We have a linear key without any gaps, so we use vector for fast access typedef std::vector<WardenCheck*> CheckContainer; diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp index 6df1dc7561c..834012fe964 100644 --- a/src/server/game/Warden/WardenMac.cpp +++ b/src/server/game/Warden/WardenMac.cpp @@ -16,7 +16,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Cryptography/WardenKeyGeneration.h" +#include "Cryptography/SessionKeyGeneration.h" #include "Common.h" #include "WorldPacket.h" #include "WorldSession.h" @@ -28,6 +28,7 @@ #include "Util.h" #include "WardenMac.h" #include "WardenModuleMac.h" +#include "SHA1.h" #include <openssl/md5.h> @@ -39,7 +40,7 @@ void WardenMac::Init(WorldSession* pClient, BigNumber* K) { _session = pClient; // Generate Warden Key - SHA1Randx WK(K->AsByteArray().get(), K->GetNumBytes()); + SessionKeyGenerator<SHA1Hash> WK(K->AsByteArray().get(), K->GetNumBytes()); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); /* diff --git a/src/server/game/Warden/WardenMac.h b/src/server/game/Warden/WardenMac.h index 26a2d86524e..c7435502f63 100644 --- a/src/server/game/Warden/WardenMac.h +++ b/src/server/game/Warden/WardenMac.h @@ -28,7 +28,7 @@ class WorldSession; class Warden; -class WardenMac : public Warden +class TC_GAME_API WardenMac : public Warden { public: WardenMac(); diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp index b99a6cd3ac9..5362ad56616 100644 --- a/src/server/game/Warden/WardenWin.cpp +++ b/src/server/game/Warden/WardenWin.cpp @@ -17,7 +17,7 @@ */ #include "Cryptography/HmacHash.h" -#include "Cryptography/WardenKeyGeneration.h" +#include "Cryptography/SessionKeyGeneration.h" #include "Common.h" #include "WorldPacket.h" #include "WorldSession.h" @@ -31,6 +31,7 @@ #include "WardenWin.h" #include "WardenModuleWin.h" #include "WardenCheckMgr.h" +#include "SHA1.h" #include <openssl/md5.h> @@ -42,7 +43,7 @@ void WardenWin::Init(WorldSession* session, BigNumber* k) { _session = session; // Generate Warden Key - SHA1Randx WK(k->AsByteArray().get(), k->GetNumBytes()); + SessionKeyGenerator<SHA1Hash> WK(k->AsByteArray().get(), k->GetNumBytes()); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); diff --git a/src/server/game/Warden/WardenWin.h b/src/server/game/Warden/WardenWin.h index 4bf1af77c47..b3e6d7c586c 100644 --- a/src/server/game/Warden/WardenWin.h +++ b/src/server/game/Warden/WardenWin.h @@ -62,7 +62,7 @@ struct WardenInitModuleRequest class WorldSession; class Warden; -class WardenWin : public Warden +class TC_GAME_API WardenWin : public Warden { public: WardenWin(); diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index 393080f044a..92140fbc2af 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/Weather/Weather.h b/src/server/game/Weather/Weather.h index 0135b28522f..e0330b85a60 100644 --- a/src/server/game/Weather/Weather.h +++ b/src/server/game/Weather/Weather.h @@ -62,7 +62,7 @@ enum WeatherState : uint32 }; /// Weather for one zone -class Weather +class TC_GAME_API Weather { public: diff --git a/src/server/game/Weather/WeatherMgr.h b/src/server/game/Weather/WeatherMgr.h index 97c541fd3c0..e3dd4ac9ec4 100644 --- a/src/server/game/Weather/WeatherMgr.h +++ b/src/server/game/Weather/WeatherMgr.h @@ -30,15 +30,15 @@ class Player; namespace WeatherMgr { - void LoadWeatherData(); + TC_GAME_API void LoadWeatherData(); - Weather* FindWeather(uint32 id); - Weather* AddWeather(uint32 zone_id); - void RemoveWeather(uint32 zone_id); + TC_GAME_API Weather* FindWeather(uint32 id); + TC_GAME_API Weather* AddWeather(uint32 zone_id); + TC_GAME_API void RemoveWeather(uint32 zone_id); - void SendFineWeatherUpdateToPlayer(Player* player); + TC_GAME_API void SendFineWeatherUpdateToPlayer(Player* player); - void Update(uint32 diff); + TC_GAME_API void Update(uint32 diff); } #endif diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d2ccb025165..be9b48a81f3 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -43,6 +43,7 @@ #include "GridNotifiersImpl.h" #include "GroupMgr.h" #include "GuildFinderMgr.h" +#include "GameObjectModel.h" #include "InstanceSaveMgr.h" #include "Language.h" #include "LFGMgr.h" @@ -73,17 +74,18 @@ #include <boost/algorithm/string.hpp> -std::atomic<bool> World::m_stopEvent(false); -uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; -std::atomic<uint32> World::m_worldLoopCounter(0); +TC_GAME_API std::atomic<bool> World::m_stopEvent(false); +TC_GAME_API uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; -float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE; -float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE; -float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS; +TC_GAME_API std::atomic<uint32> World::m_worldLoopCounter(0); -int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD; -int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD; -int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD; +TC_GAME_API float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE; +TC_GAME_API float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE; +TC_GAME_API float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS; + +TC_GAME_API int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD; +TC_GAME_API int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD; +TC_GAME_API int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD; /// World constructor World::World() @@ -147,6 +149,12 @@ World::~World() /// @todo free addSessQueue } +World* World::instance() +{ + static World instance; + return &instance; +} + /// Find a player in a specified zone Player* World::FindPlayerInZone(uint32 zone) { @@ -1409,8 +1417,6 @@ void World::LoadConfigSettings(bool reload) sScriptMgr->OnConfigLoad(reload); } -extern void LoadGameObjectModelList(std::string const& dataPath); - /// Initialize the World void World::SetInitialWorldSettings() { @@ -1941,6 +1947,7 @@ void World::SetInitialWorldSettings() m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS); + m_timers[WUPDATE_AUCTIONS_PENDING].SetInterval(250); m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS); //Update "uptime" table based on configuration entry in minutes. m_timers[WUPDATE_CORPSES].SetInterval(20 * MINUTE * IN_MILLISECONDS); @@ -2190,6 +2197,13 @@ void World::Update(uint32 diff) sAuctionMgr->Update(); } + if (m_timers[WUPDATE_AUCTIONS_PENDING].Passed()) + { + m_timers[WUPDATE_AUCTIONS_PENDING].Reset(); + + sAuctionMgr->UpdatePendingAuctions(); + } + /// <li> Handle AHBot operations if (m_timers[WUPDATE_AHBOT].Passed()) { @@ -3468,6 +3482,8 @@ void World::RemoveOldCorpses() m_timers[WUPDATE_CORPSES].SetCurrent(m_timers[WUPDATE_CORPSES].GetInterval()); } +Realm realm; + uint32 GetVirtualRealmAddress() { return uint32(realm.Id.Region) << 24 | uint32(realm.Id.Site) << 16 | realm.Id.Realm; diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 0f9a27c733f..24a23f4f853 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -79,6 +79,7 @@ enum ShutdownExitCode enum WorldTimers { WUPDATE_AUCTIONS, + WUPDATE_AUCTIONS_PENDING, WUPDATE_WEATHERS, WUPDATE_UPTIME, WUPDATE_CORPSES, @@ -555,14 +556,10 @@ struct CharacterInfo }; /// The World -class World +class TC_GAME_API World { public: - static World* instance() - { - static World instance; - return &instance; - } + static World* instance(); static std::atomic<uint32> m_worldLoopCounter; @@ -898,9 +895,11 @@ class World std::deque<PreparedQueryResultFuture> m_realmCharCallbacks; }; -extern Realm realm; -uint32 GetVirtualRealmAddress(); +TC_GAME_API extern Realm realm; + +TC_GAME_API uint32 GetVirtualRealmAddress(); #define sWorld World::instance() + #endif /// @} diff --git a/src/server/ipc/Commands.cpp b/src/server/ipc/Commands.cpp deleted file mode 100644 index 3eb78cbc14a..00000000000 --- a/src/server/ipc/Commands.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "Commands.h" -#include <zmqpp/message.hpp> - -zmqpp::message& operator>>(zmqpp::message& msg, IPC::Header& header) -{ - msg >> header.Channel; - msg >> header.Command; - return msg; -} - -zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::RealmHandle& realm) -{ - msg >> realm.Region; - msg >> realm.Site; - msg >> realm.Realm; - return msg; -} - -zmqpp::message& operator>>(zmqpp::message& msg, IPC::BattlenetComm::Header& header) -{ - msg >> header.Ipc; - msg >> header.Realm; - return msg; -} - -zmqpp::message& operator>>(zmqpp::message& msg, IPC::BattlenetComm::ToonHandle& toonHandle) -{ - msg >> toonHandle.AccountId; - msg >> toonHandle.GameAccountId; - msg >> toonHandle.Guid; - msg >> toonHandle.Name; - return msg; -} - -zmqpp::message& operator<<(zmqpp::message& msg, IPC::Header const& header) -{ - msg << header.Channel; - msg << header.Command; - return msg; -} - -zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::RealmHandle const& realm) -{ - msg << realm.Region; - msg << realm.Site; - msg << realm.Realm; - return msg; -} - -zmqpp::message& operator<<(zmqpp::message& msg, IPC::BattlenetComm::Header const& header) -{ - msg << header.Ipc; - msg << header.Realm; - return msg; -} - -zmqpp::message& operator<<(zmqpp::message& msg, IPC::BattlenetComm::ToonHandle const& toonHandle) -{ - msg << toonHandle.AccountId; - msg << toonHandle.GameAccountId; - msg << toonHandle.Guid; - msg << toonHandle.Name; - return msg; -} diff --git a/src/server/ipc/Commands.h b/src/server/ipc/Commands.h deleted file mode 100644 index 618e8ca0509..00000000000 --- a/src/server/ipc/Commands.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef _COMMANDS_H -#define _COMMANDS_H - -#include "Define.h" -#include "Realm/Realm.h" -#include <string> - -enum Channels -{ - IPC_CHANNEL_BNET, - - MAX_IPC_CHANNELS, -}; - -enum BnetCommands -{ - BNET_CHANGE_TOON_ONLINE_STATE, - - IPC_BNET_MAX_COMMAND -}; - -namespace IPC -{ - struct Header - { - uint8 Channel; - uint8 Command; - }; - - namespace BattlenetComm - { - struct Header - { - IPC::Header Ipc; - Battlenet::RealmHandle Realm; - }; - - struct ToonHandle - { - uint32 AccountId; - uint32 GameAccountId; - uint64 Guid; - std::string Name; - }; - } -} - -namespace zmqpp -{ - class message; -} - -zmqpp::message& operator>>(zmqpp::message& msg, IPC::Header& header); -zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::RealmHandle& realm); -zmqpp::message& operator>>(zmqpp::message& msg, IPC::BattlenetComm::Header& header); -zmqpp::message& operator>>(zmqpp::message& msg, IPC::BattlenetComm::ToonHandle& toonHandle); - -zmqpp::message& operator<<(zmqpp::message& msg, IPC::Header const& header); -zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::RealmHandle const& realm); -zmqpp::message& operator<<(zmqpp::message& msg, IPC::BattlenetComm::Header const& header); -zmqpp::message& operator<<(zmqpp::message& msg, IPC::BattlenetComm::ToonHandle const& toonHandle); - -#endif // _COMMANDS_H diff --git a/src/server/ipc/ZMQTask.cpp b/src/server/ipc/ZMQTask.cpp deleted file mode 100644 index 6d359d9b10a..00000000000 --- a/src/server/ipc/ZMQTask.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "ZMQTask.h" -#include "ZmqContext.h" -#include <zmqpp/message.hpp> - -ZMQTask::ZMQTask() -{ - _poller = new zmqpp::poller(); -} - -ZMQTask::~ZMQTask() -{ - delete _poller; - _poller = NULL; - delete _inproc; - delete _thread; -} - -void ZMQTask::Start() -{ - _inproc = sIpcContext->CreateInprocSubscriber(); - _poller->add(*_inproc); - - HandleOpen(); - _thread = new std::thread(&ZMQTask::Run, this); -} - -void ZMQTask::End() -{ - _thread->join(); - _poller->remove(*_inproc); - _inproc->close(); - HandleClose(); -} - -bool ZMQTask::ProcessExit() -{ - if (_poller->events(*_inproc) == zmqpp::poller::poll_in) - { - int op1; - do - { - zmqpp::message msg; - if (!_inproc->receive(msg, true)) - return false; //No more messages to read from sock. This shouldn't happen. - - // strip 'internalmq.' from message - std::string cmd = msg.get(0).substr(11); - if (cmd == "kill") - return true; - - _inproc->get(zmqpp::socket_option::events, op1); - } while (op1 & zmqpp::poller::poll_in); - } - - return false; -} - -void ZMQTask::Pipeline(zmqpp::socket* from, zmqpp::socket* to) -{ - /* - Push messages from socket to socket. - */ - if (_poller->events(*from) == zmqpp::poller::poll_in) - { - int32 op1, op2; - do - { - zmqpp::message msg; - if (!from->receive(msg, true)) - return; //No more messages to read from socket. This shouldn't happen. - - to->send(msg); - from->get(zmqpp::socket_option::events, op1); - to->get(zmqpp::socket_option::events, op2); - } while(op1 & zmqpp::poller::poll_in && op2 & zmqpp::poller::poll_out); - } -} diff --git a/src/server/ipc/ZMQTask.h b/src/server/ipc/ZMQTask.h deleted file mode 100644 index 85773adbfd1..00000000000 --- a/src/server/ipc/ZMQTask.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef __ZMQTASK_H -#define __ZMQTASK_H - -#include "Define.h" -#include <thread> -#include <zmqpp/poller.hpp> -#include <zmqpp/socket.hpp> - -/* - This class serves as a base for all long running tasks - It is set up to terminate its running task upon receiving "kill" command -*/ -class ZMQTask -{ -public: - ZMQTask(); - virtual ~ZMQTask(); - - void Start(); - void End(); - virtual void Run() = 0; - -protected: - virtual void HandleOpen() { } - virtual void HandleClose() { } - void Pipeline(zmqpp::socket* from, zmqpp::socket* to); - bool ProcessExit(); - - zmqpp::poller* _poller; - - zmqpp::socket* _inproc = nullptr; - std::thread* _thread = nullptr; -}; - -#endif // __ZMQTASK_H diff --git a/src/server/ipc/ZmqContext.cpp b/src/server/ipc/ZmqContext.cpp deleted file mode 100644 index bc062de8e88..00000000000 --- a/src/server/ipc/ZmqContext.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "ZmqContext.h" - -ZmqContext::ZmqContext() : _inproc(nullptr) -{ -} - -ZmqContext::~ZmqContext() -{ -} - -zmqpp::socket* ZmqContext::CreateNewSocket(zmqpp::socket_type type) -{ - std::unique_lock<std::mutex> lock(_mutex); - zmqpp::socket* socket = new zmqpp::socket(_context, type); - socket->set(zmqpp::socket_option::linger, 0); - return socket; -} - -void ZmqContext::Initialize() -{ - _inproc = new zmqpp::socket(_context, zmqpp::socket_type::pub); - _inproc->bind("inproc://workers"); -} - -zmqpp::socket* ZmqContext::CreateInprocSubscriber() -{ - zmqpp::socket* sub = CreateNewSocket(zmqpp::socket_type::sub); - sub->connect("inproc://workers"); - sub->subscribe("internalmq."); - return sub; -} - -void ZmqContext::Close() -{ - _inproc->send("internalmq.kill"); - delete _inproc; - _inproc = nullptr; -} diff --git a/src/server/ipc/ZmqContext.h b/src/server/ipc/ZmqContext.h deleted file mode 100644 index 99f49a8c597..00000000000 --- a/src/server/ipc/ZmqContext.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef __ZMQCONTEX_H -#define __ZMQCONTEX_H - -#include <zmqpp/zmqpp.hpp> -#include <mutex> - -/* - * We need to serialize access to zmq context otherwise stuff blows up. - */ -class ZmqContext -{ -public: - ~ZmqContext(); - - static ZmqContext* Instance() - { - static ZmqContext instance; - return &instance; - } - - zmqpp::socket* CreateNewSocket(zmqpp::socket_type); - void Initialize(); - zmqpp::socket* CreateInprocSubscriber(); - void Close(); - -private: - ZmqContext(); - ZmqContext(ZmqContext const&) = delete; - ZmqContext& operator=(ZmqContext const&) = delete; - - zmqpp::context _context; - std::mutex _mutex; - zmqpp::socket* _inproc; -}; - -#define sIpcContext ZmqContext::Instance() - -#endif diff --git a/src/server/ipc/ZmqListener.cpp b/src/server/ipc/ZmqListener.cpp deleted file mode 100644 index a7cf78f8a92..00000000000 --- a/src/server/ipc/ZmqListener.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "ZmqListener.h" -#include "ZmqContext.h" - -ZmqListener::ZmqListener(std::string const& from, std::string const& to) -{ - _from = sIpcContext->CreateNewSocket(zmqpp::socket_type::sub); - _to = sIpcContext->CreateNewSocket(zmqpp::socket_type::push); - _from->connect(from); - _to->bind(to); -} - -ZmqListener::~ZmqListener() -{ - delete _from; - delete _to; -} - -void ZmqListener::HandleOpen() -{ -} - -void ZmqListener::HandleClose() -{ - _from->close(); - _to->close(); -} - -void ZmqListener::Run() -{ - while (!ProcessExit()) - { - _poller->poll(); - - while (_poller->events(*_from) & zmqpp::poller::poll_in && - _poller->events(*_to) & zmqpp::poller::poll_out) - { - zmqpp::message msg; - _from->receive(msg); - _to->send(msg); - } - } -} - -void ZmqListener::Subscribe(std::string const& keyword) -{ - _from->subscribe(keyword); -} - -void ZmqListener::Unsubscribe(std::string const& keyword) -{ - _from->unsubscribe(keyword); -} diff --git a/src/server/ipc/ZmqListener.h b/src/server/ipc/ZmqListener.h deleted file mode 100644 index 07798b81886..00000000000 --- a/src/server/ipc/ZmqListener.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef __ZMQLISTENER_H -#define __ZMQLISTENER_H - -#include "ZMQTask.h" -#include <zmqpp/zmqpp.hpp> - -class ZmqListener : public ZMQTask -{ -/* - * Read broadcasts from remote PUB socket, and forward them to - * another socket. - * - * from - client SUB socket - * to - listen PUSH socket - * - */ -public: - ZmqListener(std::string const& from, std::string const& to); - ~ZmqListener(); - void Run() override; - - void Subscribe(std::string const& keyword); - void Unsubscribe(std::string const& keyword); - -protected: - void HandleOpen() override; - void HandleClose() override; - -private: - zmqpp::socket* _from; - zmqpp::socket* _to; -}; - -#endif diff --git a/src/server/ipc/ZmqMux.cpp b/src/server/ipc/ZmqMux.cpp deleted file mode 100644 index d6dcd0f73f6..00000000000 --- a/src/server/ipc/ZmqMux.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "ZmqMux.h" -#include "ZmqContext.h" - -ZmqMux::ZmqMux(std::string const& fromUri, std::string const& toUri): - _fromAddress(fromUri) -{ - printf("Opening muxer thread from %s to %s\n", fromUri.c_str(), toUri.c_str()); - _from = sIpcContext->CreateNewSocket(zmqpp::socket_type::pull); - _to = sIpcContext->CreateNewSocket(zmqpp::socket_type::push); - - _from->bind(fromUri); - _to->connect(toUri); -} - -ZmqMux::~ZmqMux() -{ - delete _from; - delete _to; -} - -void ZmqMux::HandleOpen() -{ - _poller->add(*_from); - _poller->add(*_to, zmqpp::poller::poll_out); -} - -bool ZmqMux::Send(zmqpp::message* m, bool dont_block) -{ - if (_socket.get() == nullptr) - { - _socket.reset(sIpcContext->CreateNewSocket(zmqpp::socket_type::push)); - _socket->connect(_fromAddress); - } - - return _socket->send(*m, dont_block); -} - -void ZmqMux::Run() -{ - for (;;) - { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - if (!_poller->poll()) - break; - - if (ProcessExit()) - break; - - Pipeline(_from, _to); - } -} diff --git a/src/server/ipc/ZmqMux.h b/src/server/ipc/ZmqMux.h deleted file mode 100644 index 1009382f101..00000000000 --- a/src/server/ipc/ZmqMux.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef __ZMQMUX_H -#define __ZMQMUX_H - -#include "ZMQTask.h" -#include <string> -#include <boost/thread/tss.hpp> - -/* - * Multiplexes zmq messages from many threads, - * and then passes them to another socket. - */ -class ZmqMux : public ZMQTask -{ -public: - ZmqMux(std::string const& from, std::string const& to); - ~ZmqMux(); - bool Send(zmqpp::message*, bool dont_block = false); - void Run() override; - -protected: - void HandleOpen() override; - -private: - boost::thread_specific_ptr<zmqpp::socket> _socket; - zmqpp::socket* _from; - zmqpp::socket* _to; - std::string const _fromAddress; -}; - -#endif diff --git a/src/server/ipc/ZmqWorker.cpp b/src/server/ipc/ZmqWorker.cpp deleted file mode 100644 index 617730ad013..00000000000 --- a/src/server/ipc/ZmqWorker.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "ZmqWorker.h" -#include "ZmqContext.h" - -ZmqWorker::ZmqWorker(std::string const& taskUri, std::string const& resUri) : - _taskUri(taskUri), _resultsUri(resUri) -{ -} - -ZmqWorker::~ZmqWorker() -{ - delete _taskQueue; - delete _results; -} - -void ZmqWorker::HandleOpen() -{ - _taskQueue = sIpcContext->CreateNewSocket(zmqpp::socket_type::pull); - _results = sIpcContext->CreateNewSocket(zmqpp::socket_type::push); - - _taskQueue->connect(_taskUri); - _results->connect(_resultsUri); - - _poller->add(*_taskQueue); -} - -void ZmqWorker::HandleClose() -{ - _taskQueue->close(); - _results->close(); -} - -void ZmqWorker::Run() -{ - while (!ProcessExit()) - { - _poller->poll(); - if (_poller->events(*_taskQueue) & zmqpp::poller::poll_in) - PerformWork(); - } -} - -void ZmqWorker::PerformWork() -{ - int32 op1; - do - { - zmqpp::message msg; - _taskQueue->receive(msg); - Dispatch(msg); - _taskQueue->get(zmqpp::socket_option::events, op1); - } while (op1 & zmqpp::poller::poll_in); -} diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index b89d12b70a8..c5b6aed89b9 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -10,11 +10,6 @@ # Enable precompiled headers when using the GCC compiler. -if (USE_SCRIPTPCH) - set(scripts_STAT_PCH_HDR PrecompiledHeaders/ScriptPCH.h) - set(scripts_STAT_PCH_SRC PrecompiledHeaders/ScriptPCH.cpp) -endif () - message(STATUS "SCRIPT PREPARATIONS") macro(PrepareScripts name out) @@ -26,134 +21,57 @@ macro(PrepareScripts name out) message(STATUS " -> Prepared: ${name}") endmacro(PrepareScripts) -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - ../game/AI/ScriptedAI/ScriptedEscortAI.cpp - ../game/AI/ScriptedAI/ScriptedCreature.cpp - ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp -) - -PrepareScripts(Spells scripts_STAT_SRCS) -PrepareScripts(Commands scripts_STAT_SRCS) +PrepareScripts(Spells PRIVATE_SOURCES) +PrepareScripts(Commands PRIVATE_SOURCES) if(SCRIPTS) - PrepareScripts(Custom scripts_STAT_SRCS) - PrepareScripts(World scripts_STAT_SRCS) - PrepareScripts(OutdoorPvP scripts_STAT_SRCS) - PrepareScripts(EasternKingdoms scripts_STAT_SRCS) - PrepareScripts(Kalimdor scripts_STAT_SRCS) - PrepareScripts(Outland scripts_STAT_SRCS) - PrepareScripts(Northrend scripts_STAT_SRCS) - PrepareScripts(Maelstrom scripts_STAT_SRCS) - PrepareScripts(Events scripts_STAT_SRCS) - PrepareScripts(Pet scripts_STAT_SRCS) + PrepareScripts(Custom PRIVATE_SOURCES) + PrepareScripts(World PRIVATE_SOURCES) + PrepareScripts(OutdoorPvP PRIVATE_SOURCES) + PrepareScripts(EasternKingdoms PRIVATE_SOURCES) + PrepareScripts(Kalimdor PRIVATE_SOURCES) + PrepareScripts(Outland PRIVATE_SOURCES) + PrepareScripts(Northrend PRIVATE_SOURCES) + PrepareScripts(Maelstrom PRIVATE_SOURCES) + PrepareScripts(Events PRIVATE_SOURCES) + PrepareScripts(Pet PRIVATE_SOURCES) endif() message(STATUS "SCRIPT PREPARATION COMPLETE") message("") -include_directories( - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/src/common/ - ${CMAKE_SOURCE_DIR}/src/common/Collision - ${CMAKE_SOURCE_DIR}/src/common/Collision/Management - ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps - ${CMAKE_SOURCE_DIR}/src/common/Collision/Models - ${CMAKE_SOURCE_DIR}/src/common/Configuration - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/server/database/Database - ${CMAKE_SOURCE_DIR}/src/server/game/Accounts - ${CMAKE_SOURCE_DIR}/src/server/game/Achievements - ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/AI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts - ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse - ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouseBot - ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield - ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield/Zones - ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds - ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds/Zones - ${CMAKE_SOURCE_DIR}/src/server/game/Chat - ${CMAKE_SOURCE_DIR}/src/server/game/Chat/Channels - ${CMAKE_SOURCE_DIR}/src/server/game/Combat - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/DungeonFinding - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/AreaTrigger - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item/Container - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Pet - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Player - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Transport - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Vehicle - ${CMAKE_SOURCE_DIR}/src/server/game/Events - ${CMAKE_SOURCE_DIR}/src/server/game/Globals - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Notifiers - ${CMAKE_SOURCE_DIR}/src/server/game/Groups - ${CMAKE_SOURCE_DIR}/src/server/game/Guilds - ${CMAKE_SOURCE_DIR}/src/server/game/Handlers - ${CMAKE_SOURCE_DIR}/src/server/game/Instances - ${CMAKE_SOURCE_DIR}/src/server/game/Loot - ${CMAKE_SOURCE_DIR}/src/server/game/Mails - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP - ${CMAKE_SOURCE_DIR}/src/server/game/Pools - ${CMAKE_SOURCE_DIR}/src/server/game/Quests - ${CMAKE_SOURCE_DIR}/src/server/game/Reputation - ${CMAKE_SOURCE_DIR}/src/server/game/Scripting - ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Packets - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol - ${CMAKE_SOURCE_DIR}/src/server/game/Skills - ${CMAKE_SOURCE_DIR}/src/server/game/Spells - ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_SOURCE_DIR}/src/server/game/Support - ${CMAKE_SOURCE_DIR}/src/server/game/Texts - ${CMAKE_SOURCE_DIR}/src/server/game/Tickets - ${CMAKE_SOURCE_DIR}/src/server/game/Tools - ${CMAKE_SOURCE_DIR}/src/server/game/Warden - ${CMAKE_SOURCE_DIR}/src/server/game/Weather - ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/ipc - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) +list(APPEND PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.h + ${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp) + +if (USE_SCRIPTPCH) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/ScriptPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/ScriptPCH.cpp) +endif () GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_library(scripts STATIC - ${scripts_STAT_SRCS} - ${scripts_STAT_PCH_SRC} + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) +target_include_directories(scripts + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +target_link_libraries(scripts + PUBLIC + game) + +set_target_properties(scripts + PROPERTIES + FOLDER + "server") + # Generate precompiled header if (USE_SCRIPTPCH) - add_cxx_pch(scripts ${scripts_STAT_PCH_HDR} ${scripts_STAT_PCH_SRC}) + add_cxx_pch(scripts ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif() diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index dc2baa57e5f..8be6e029cf0 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -98,6 +98,7 @@ public: { "transport", rbac::RBAC_PERM_COMMAND_DEBUG_TRANSPORT, false, &HandleDebugTransportCommand, "" }, { "loadcells", rbac::RBAC_PERM_COMMAND_DEBUG_LOADCELLS, false, &HandleDebugLoadCellsCommand, "",}, { "phase", rbac::RBAC_PERM_COMMAND_DEBUG_PHASE, false, &HandleDebugPhaseCommand, "" }, + { "boundary", rbac::RBAC_PERM_COMMAND_DEBUG_BOUNDARY, false, &HandleDebugBoundaryCommand, "" } }; static std::vector<ChatCommand> commandTable = { @@ -1419,6 +1420,33 @@ public: return true; } + static bool HandleDebugBoundaryCommand(ChatHandler* handler, char const* args) + { + Player* player = handler->GetSession()->GetPlayer(); + if (!player) + return false; + Creature* target = handler->getSelectedCreature(); + if (!target || !target->IsAIEnabled || !target->AI()) + { + return false; + } + + char* fill_str = args ? strtok((char*)args, " ") : nullptr; + char* duration_str = args ? strtok(nullptr, " ") : nullptr; + + int duration = duration_str ? atoi(duration_str) : -1; + if (duration <= 0 || duration >= 30 * MINUTE) // arbitary upper limit + duration = 3 * MINUTE; + + bool doFill = fill_str ? (stricmp(fill_str, "FILL") == 0) : false; + + int32 errMsg = target->AI()->VisualizeBoundary(duration, player, doFill); + if (errMsg > 0) + handler->PSendSysMessage(errMsg); + + return true; + } + static bool HandleDebugPhaseCommand(ChatHandler* handler, char const* /*args*/) { Unit* target = handler->getSelectedUnit(); diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp index 269e115189a..d5ed2421efc 100644 --- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp @@ -77,7 +77,7 @@ public: Talk(SAY_RESPAWN); } - bool CheckInRoom() + bool CheckInRoom() override { if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) { diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp index 93583364ef6..238942c15f6 100644 --- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp @@ -78,7 +78,7 @@ public: Talk(SAY_BUFF); } - bool CheckInRoom() + bool CheckInRoom() override { if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) { diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp index 043c78999f3..2108e393578 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp @@ -111,7 +111,7 @@ class boss_alizabal : public CreatureScript Talk(SAY_SLAY); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); me->GetMotionMaster()->MoveTargetedHome(); diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp index 2dbca9eee57..ae94b112533 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp @@ -73,9 +73,9 @@ class boss_occuthar : public CreatureScript events.ScheduleEvent(EVENT_BERSERK, 5 * MINUTE * IN_MILLISECONDS); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); _DespawnAtEvade(); } @@ -188,7 +188,7 @@ class npc_eyestalk : public CreatureScript } } - void EnterEvadeMode() override { } // Never evade + void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade private: InstanceScript* _instance; diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_pit_lord_argaloth.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_pit_lord_argaloth.cpp index 13b675e855c..f89d54ec7dd 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/boss_pit_lord_argaloth.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_pit_lord_argaloth.cpp @@ -58,7 +58,7 @@ class boss_pit_lord_argaloth : public CreatureScript events.ScheduleEvent(EVENT_BERSERK, 5 * MINUTE * IN_MILLISECONDS); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { me->GetMotionMaster()->MoveTargetedHome(); instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp index 3543fccf159..b454f5feaa9 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp @@ -21,10 +21,10 @@ DoorData const doorData[] = { - { GO_ARGALOTH_DOOR, DATA_ARGALOTH, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_OCCUTHAR_DOOR, DATA_OCCUTHAR, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ALIZABAL_DOOR, DATA_ALIZABAL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_ARGALOTH_DOOR, DATA_ARGALOTH, DOOR_TYPE_ROOM }, + { GO_OCCUTHAR_DOOR, DATA_OCCUTHAR, DOOR_TYPE_ROOM }, + { GO_ALIZABAL_DOOR, DATA_ALIZABAL, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_baradin_hold: public InstanceMapScript diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp index bd489d279ae..5e1aad82fa5 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp @@ -198,9 +198,9 @@ class boss_doomrel : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); _instance->SetGuidData(DATA_EVENSTARTER, ObjectGuid::Empty); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp index 102d9e871cb..73704f4f42c 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp @@ -22,14 +22,14 @@ DoorData const doorData[] = { - { GO_BOSSGATE01, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_DRAKE_RIDER_PORTCULLIS, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ALTERAC_VALLEY_GATE, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GATE, DATA_FIREMAW, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GATE, DATA_EBONROC, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GATE, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_VACCUUM_EXIT_GATE, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_BOSSGATE01, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE }, + { GO_DRAKE_RIDER_PORTCULLIS, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE }, + { GO_ALTERAC_VALLEY_GATE, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE }, + { GO_GATE, DATA_FIREMAW, DOOR_TYPE_PASSAGE }, + { GO_GATE, DATA_EBONROC, DOOR_TYPE_PASSAGE }, + { GO_GATE, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE }, + { GO_VACCUUM_EXIT_GATE, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; ObjectData const creatureData[] = diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp index 96e05541684..ced8dd8f37e 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -91,9 +91,9 @@ public: Initialize(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); ResetTimer = 2000; } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index 0a88ba17877..6386bb50e1a 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -30,12 +30,12 @@ DoorData const doorData[] = { - { GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE }, + { GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM }, + { GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE }, + { GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE }, + { GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; Position const KalecgosSpawnPos = { 164.3747f, -397.1197f, 2.151798f, 1.66219f }; diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 1975ebe0021..6038b76f0d0 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -452,8 +452,6 @@ class npc_eye_of_acherus : public CreatureScript ## npc_death_knight_initiate ######*/ -#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!" - enum Spells_DKI { SPELL_DUEL = 52996, @@ -514,7 +512,7 @@ public: if (player->IsInCombat() || creature->IsInCombat()) return true; - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(Player::GetDefaultGossipMenuForSource(creature), 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); } return true; diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index acfdf0523f4..dd43b46795b 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -596,10 +596,10 @@ public: } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { if (!bIsBattle)//do not reset self if we are in battle - npc_escortAI::EnterEvadeMode(); + npc_escortAI::EnterEvadeMode(why); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp index caab177d53f..7096e60fb15 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp @@ -21,8 +21,8 @@ DoorData const doorData[] = { - { GO_HIGH_INQUISITORS_DOOR, DATA_MOGRAINE_AND_WHITE_EVENT, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_HIGH_INQUISITORS_DOOR, DATA_MOGRAINE_AND_WHITE_EVENT, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_scarlet_monastery : public InstanceMapScript diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp index b0b72f96956..0e3e1ff3950 100644 --- a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp @@ -108,7 +108,7 @@ class boss_kirtonos_the_herald : public CreatureScript _JustDied(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GATE_KIRTONOS))) gate->SetGoState(GO_STATE_ACTIVE); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp index 936ae51f163..2534c099169 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp @@ -136,10 +136,10 @@ public: me->SummonCreature(NPC_FELMYST, x, y, z + 30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { if (!Intro) - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void StartIntro() diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index 8319d41a94a..8cdce77a1f5 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -169,12 +169,12 @@ public: me->SetFullHealth(); //dunno why it does not resets health at evade.. } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { bJustReset = true; me->SetVisible(false); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void DoAction(int32 param) override @@ -237,7 +237,7 @@ public: { if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_BOUNDARY); return; } if (HealthBelowPct(10) && !isEnraged) @@ -261,7 +261,7 @@ public: else { TC_LOG_ERROR("scripts", "Didn't find Shathrowar. Kalecgos event reseted."); - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return; } } @@ -423,7 +423,7 @@ public: TalkTimer = 15000; break; case 3: - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); break; default: break; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index c792214ae49..d86b3707606 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -624,9 +624,9 @@ public: Talk(SAY_KJ_SLAY); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); summons.DespawnAll(); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 1c5f4193cd6..23ce70ef8f6 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -151,7 +151,7 @@ public: } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) muru->AI()->Reset(); // Reset encounter. diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp index 3f89e80906d..bb9d3065f64 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp @@ -31,13 +31,13 @@ DoorData const doorData[] = { - { GO_FIRE_BARRIER, DATA_FELMYST, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_MURUS_GATE_1, DATA_MURU, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_MURUS_GATE_2, DATA_MURU, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_BOSS_COLLISION_1, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_BOSS_COLLISION_2, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_FORCE_FIELD, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_FIRE_BARRIER, DATA_FELMYST, DOOR_TYPE_PASSAGE }, + { GO_MURUS_GATE_1, DATA_MURU, DOOR_TYPE_ROOM }, + { GO_MURUS_GATE_2, DATA_MURU, DOOR_TYPE_PASSAGE }, + { GO_BOSS_COLLISION_1, DATA_KALECGOS, DOOR_TYPE_ROOM }, + { GO_BOSS_COLLISION_2, DATA_KALECGOS, DOOR_TYPE_ROOM }, + { GO_FORCE_FIELD, DATA_KALECGOS, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_sunwell_plateau : public InstanceMapScript diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp index f6ae3fc1b91..4c89aab57ba 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -22,12 +22,12 @@ DoorData const doorData[] = { - { GO_VENOXIS_COIL, DATA_VENOXIS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ARENA_DOOR_1, DATA_MANDOKIR, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_FORCEFIELD, DATA_KILNARA, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ZANZIL_DOOR, DATA_ZANZIL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - //{ GO_THE_CACHE_OF_MADNESS_DOOR, DATA_xxxxxxx, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + { GO_VENOXIS_COIL, DATA_VENOXIS, DOOR_TYPE_ROOM }, + { GO_ARENA_DOOR_1, DATA_MANDOKIR, DOOR_TYPE_ROOM }, + { GO_FORCEFIELD, DATA_KILNARA, DOOR_TYPE_ROOM }, + { GO_ZANZIL_DOOR, DATA_ZANZIL, DOOR_TYPE_ROOM }, + //{ GO_THE_CACHE_OF_MADNESS_DOOR, DATA_xxxxxxx, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } }; class instance_zulgurub : public InstanceMapScript diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index d0e62565102..0196461b68e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -417,7 +417,7 @@ void hyjalAI::Reset() } } -void hyjalAI::EnterEvadeMode() +void hyjalAI::EnterEvadeMode(EvadeReason /*why*/) { if (me->GetEntry() != JAINA) me->RemoveAllAuras(); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h index 0c5213ee080..54d3c53039e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h @@ -123,7 +123,7 @@ struct hyjalAI : public npc_escortAI void Reset() override; // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat - void EnterEvadeMode() override; // Send creature back to spawn location and evade. + void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override; // Send creature back to spawn location and evade. void EnterCombat(Unit* /*who*/) override; // Used to reset cooldowns for our spells and to inform the raid that we're under attack diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index 5e100b1c4b2..db62fb8b086 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -43,9 +43,9 @@ Position const GuardianOfTimePos = { 2321.489f, 1268.383f, 132.8507f, 0.418879f DoorData const doorData[] = { - { GO_MALGANIS_GATE_2, DATA_MAL_GANIS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_EXIT_GATE, DATA_MAL_GANIS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_MALGANIS_GATE_2, DATA_MAL_GANIS, DOOR_TYPE_ROOM }, + { GO_EXIT_GATE, DATA_MAL_GANIS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_culling_of_stratholme : public InstanceMapScript diff --git a/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp b/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp index ae608a86413..aeb63dac2c0 100644 --- a/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp +++ b/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp @@ -259,11 +259,11 @@ class npc_blazing_monstrosity : public CreatureScript { } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { _summons.DespawnAll(); _events.Reset(); - PassiveAI::EnterEvadeMode(); + PassiveAI::EnterEvadeMode(why); } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp index 789b79e6d7f..925eb8308aa 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -284,7 +284,7 @@ class npc_omega_stance : public CreatureScript DoCast(me, SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true); } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } }; CreatureAI* GetAI(Creature* creature) const override @@ -308,7 +308,7 @@ class npc_alpha_beam : public CreatureScript anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST); } - void EnterEvadeMode() override { } // Never evade + void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade private: InstanceScript* _instance; diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp index 09f86896c02..6dabe1f0a72 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp @@ -29,19 +29,19 @@ DoorData const doorData[] = { - {GO_ANHUURS_DOOR, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_ANHUURS_BRIDGE, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_ELEVATOR_COL01, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_VAULT_OF_LIGHTS_DOOR, DATA_VAULT_OF_LIGHTS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LIGHTMACHINE_02, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LASERBEAMS01, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LIGHTMACHINE_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LASERBEAMS_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LIGHTMACHINE_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LASERBEAMS_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LIGHTMACHINE_04, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_LASERBEAMS_02, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + {GO_ANHUURS_DOOR, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE }, + {GO_ANHUURS_BRIDGE, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_ELEVATOR_COL01, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE }, + {GO_VAULT_OF_LIGHTS_DOOR, DATA_VAULT_OF_LIGHTS, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_02, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LASERBEAMS01, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LASERBEAMS_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LASERBEAMS_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_04, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ULDUM_LASERBEAMS_02, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE }, + {0, 0, DOOR_TYPE_ROOM } }; class instance_halls_of_origination : public InstanceMapScript diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 772c77bd01a..7da15b1fdce 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -316,20 +316,9 @@ public: MovePoint = iTemp; } - bool CheckInRoom() override - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 95.0f) - { - EnterEvadeMode(); - return false; - } - - return true; - } - void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; //Common to PHASE_START && PHASE_END diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp index da953c0eb97..e5fa2153ad4 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp @@ -31,6 +31,11 @@ EndScriptData */ #include "onyxias_lair.h" #include "TemporarySummon.h" +BossBoundaryData const boundaries = +{ + { DATA_ONYXIA, new CircleBoundary(Position(-34.3697f, -212.3296f), 100.0) } +}; + class instance_onyxias_lair : public InstanceMapScript { public: @@ -47,6 +52,7 @@ public: { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); onyxiaLiftoffTimer = 0; manyWhelpsCounter = 0; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index 04d86a87f14..fa8eb2b706e 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -129,10 +129,10 @@ class boss_ayamiss : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { me->ClearUnitState(UNIT_STATE_ROOT); - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); } void EnterCombat(Unit* attacker) override diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp index 4b6622e43c2..8a564c4974c 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -72,9 +72,9 @@ class boss_buru : public CreatureScript _phase = 0; } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); for (ObjectGuid eggGuid : Eggs) if (Creature* egg = me->GetMap()->GetCreature(eggGuid)) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index a04f0dc376a..e71ac9c1ed4 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -163,11 +163,11 @@ class boss_ossirian : public CreatureScript Talk(SAY_SLAY); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { Cleanup(); summons.DespawnAll(); - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index abfbc8162df..de425fbfce1 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -77,9 +77,9 @@ class boss_skeram : public CreatureScript Talk(SAY_SLAY); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); if (me->IsSummon()) ((TempSummon*)me)->UnSummon(); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp index 595eadd6d2c..9f4c2da91e2 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -190,10 +190,10 @@ class boss_viscidus : public CreatureScript events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000)); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { summons.DespawnAll(); - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp index 01958f15298..36a094d2725 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp @@ -22,8 +22,8 @@ DoorData const doorData[] = { - { GO_PRINCE_TALDARAM_GATE, DATA_PRINCE_TALDARAM, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_PRINCE_TALDARAM_GATE, DATA_PRINCE_TALDARAM, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_ahnkahet : public InstanceMapScript diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp index 9c774a434ab..88003680ec7 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp @@ -21,11 +21,11 @@ DoorData const doorData[] = { - { GO_KRIKTHIR_DOOR, DATA_KRIKTHIR_THE_GATEWATCHER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ANUBARAK_DOOR_1, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ANUBARAK_DOOR_2, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ANUBARAK_DOOR_3, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_KRIKTHIR_DOOR, DATA_KRIKTHIR_THE_GATEWATCHER, DOOR_TYPE_PASSAGE }, + { GO_ANUBARAK_DOOR_1, DATA_ANUBARAK, DOOR_TYPE_ROOM }, + { GO_ANUBARAK_DOOR_2, DATA_ANUBARAK, DOOR_TYPE_ROOM }, + { GO_ANUBARAK_DOOR_3, DATA_ANUBARAK, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; ObjectData const creatureData[] = diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp index d2fdfee859a..f0b5a02e66e 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp @@ -501,8 +501,6 @@ public: } DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); } private: diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp index 10e67704188..b54010b386c 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp @@ -23,6 +23,11 @@ 0 - Sartharion */ +BossBoundaryData const boundaries = +{ + { DATA_SARTHARION, new RectangleBoundary(3218.86f, 3275.69f, 484.68f, 572.4f) } +}; + class instance_obsidian_sanctum : public InstanceMapScript { public: @@ -33,6 +38,8 @@ public: instance_obsidian_sanctum_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); } void OnCreatureCreate(Creature* creature) override diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp index 590c1011d56..fb5642c6f3b 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp @@ -98,7 +98,7 @@ class boss_general_zarithrian : public CreatureScript { _Reset(); if (instance->GetBossState(DATA_SAVIANA_RAGEFIRE) == DONE && instance->GetBossState(DATA_BALTHARUS_THE_WARBORN) == DONE) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); } void EnterCombat(Unit* /*who*/) override @@ -145,13 +145,6 @@ class boss_general_zarithrian : public CreatureScript if (!UpdateVictim()) return; - // Can't use room boundary here, the gameobject is spawned at the same position as the boss. This is just as good anyway. - if (me->GetPositionX() > 3058.0f) - { - EnterEvadeMode(); - return; - } - events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) @@ -228,7 +221,7 @@ class npc_onyx_flamecaller : public CreatureScript _events.ScheduleEvent(EVENT_LAVA_GOUT, 5000); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { // Prevent EvadeMode } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 4a1c7e3c7a7..8c68fe4cc18 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -256,21 +256,9 @@ struct generic_halionAI : public BossAI } } - bool CheckInRoom() override - { - // Rough radius, it is not an exactly perfect circle - if (me->GetDistance2d(HalionControllerSpawnPos.GetPositionX(), HalionControllerSpawnPos.GetPositionY()) > 48.5f) - { - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) - controller->AI()->EnterEvadeMode(); - return false; - } - return true; - } - void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom() || me->HasUnitState(UNIT_STATE_CASTING)) + if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING)) return; events.Update(diff); @@ -323,11 +311,15 @@ class boss_halion : public CreatureScript me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { + if (why == EVADE_REASON_BOUNDARY) + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) + controller->AI()->EnterEvadeMode(); + // Phase 1: We always can evade. Phase 2 & 3: We can evade if and only if the controller tells us to. if (events.IsInPhase(PHASE_ONE) || _canEvade) - generic_halionAI::EnterEvadeMode(); + generic_halionAI::EnterEvadeMode(why); } void EnterCombat(Unit* who) override @@ -497,7 +489,7 @@ class boss_twilight_halion : public CreatureScript } // Never evade - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } void KilledUnit(Unit* victim) override { @@ -1022,7 +1014,7 @@ class npc_meteor_strike_initial : public CreatureScript } void UpdateAI(uint32 /*diff*/) override { } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } private: InstanceScript* _instance; std::list<Creature*> _meteorList; @@ -1148,7 +1140,7 @@ class npc_meteor_strike_flame : public CreatureScript flame->AI()->SetGUID(_rootOwnerGuid); } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } private: InstanceScript* _instance; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp index 2a2f57b84e1..e660c3e2dde 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp @@ -23,10 +23,16 @@ #include "WorldPacket.h" #include "ruby_sanctum.h" +BossBoundaryData const boundaries = +{ + { DATA_GENERAL_ZARITHRIAN, new EllipseBoundary(Position(3013.409f, 529.492f), 45.0, 100.0) }, + { DATA_HALION, new CircleBoundary(Position(3156.037f, 533.2656f), 48.5) } +}; + DoorData const doorData[] = { - {GO_FIRE_FIELD, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE, BOUNDARY_E }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE}, + {GO_FIRE_FIELD, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE }, + {0, 0, DOOR_TYPE_ROOM }, }; class instance_ruby_sanctum : public InstanceMapScript @@ -40,6 +46,7 @@ class instance_ruby_sanctum : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); LoadDoorData(doorData); BaltharusSharedHealth = 0; } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp index 13a89f115e2..af805efc7e7 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" +#include "SpellScript.h" #include "ruby_sanctum.h" #include "Player.h" @@ -45,6 +46,11 @@ enum Events EVENT_XERESTRASZA_EVENT_7 = 7, }; +enum Spells +{ + SPELL_RALLY = 75416 +}; + Position const xerestraszaMovePos = {3151.236f, 379.8733f, 86.31996f, 0.0f}; class npc_xerestrasza : public CreatureScript @@ -165,8 +171,53 @@ class at_baltharus_plateau : public AreaTriggerScript } }; +// 75415 - Rallying Shout +class spell_ruby_sanctum_rallying_shout : public SpellScriptLoader +{ + public: + spell_ruby_sanctum_rallying_shout() : SpellScriptLoader("spell_ruby_sanctum_rallying_shout") { } + + class spell_ruby_sanctum_rallying_shout_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ruby_sanctum_rallying_shout_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_RALLY)) + return false; + return true; + } + + void CountTargets(std::list<WorldObject*>& targets) + { + _targetCount = targets.size(); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (_targetCount && !GetCaster()->HasAura(SPELL_RALLY)) + GetCaster()->CastCustomSpell(SPELL_RALLY, SPELLVALUE_AURA_STACK, _targetCount, GetCaster(), TRIGGERED_FULL_MASK); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ruby_sanctum_rallying_shout_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnEffectHit += SpellEffectFn(spell_ruby_sanctum_rallying_shout_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + + private: + uint32 _targetCount = 0; + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ruby_sanctum_rallying_shout_SpellScript(); + } +}; + void AddSC_ruby_sanctum() { new npc_xerestrasza(); new at_baltharus_plateau(); + new spell_ruby_sanctum_rallying_shout(); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index 5836514dcf6..83daa6e35a2 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -167,10 +167,10 @@ class boss_gormok : public CreatureScript summons.DespawnAll(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void MovementInform(uint32 type, uint32 pointId) override @@ -309,11 +309,6 @@ class npc_snobold_vassal : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); } - void EnterEvadeMode() override - { - ScriptedAI::EnterEvadeMode(); - } - void EnterCombat(Unit* who) override { _targetGUID = who->GetGUID(); @@ -751,10 +746,10 @@ class boss_dreadscale : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - boss_jormungarAI::EnterEvadeMode(); + boss_jormungarAI::EnterEvadeMode(why); } void JustReachedHome() override @@ -924,10 +919,10 @@ class boss_icehowl : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void JustReachedHome() override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index 07b7637927d..83bd1c8fbcb 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -416,10 +416,10 @@ class boss_fjola : public CreatureScript boss_twin_baseAI::EnterCombat(who); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - boss_twin_baseAI::EnterEvadeMode(); + boss_twin_baseAI::EnterEvadeMode(why); } void JustReachedHome() override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index 805c9bc2f6b..b053d95e1bd 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -22,6 +22,14 @@ #include "Player.h" #include "TemporarySummon.h" +BossBoundaryData const boundaries = { + { BOSS_BEASTS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) }, + { BOSS_JARAXXUS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) }, + { BOSS_CRUSADERS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) }, + { BOSS_VALKIRIES, new CircleBoundary(Position(563.26f, 139.6f), 75.0) }, + { BOSS_ANUBARAK, new EllipseBoundary(Position(746.0f, 135.0f), 100.0, 75.0) } +}; + class instance_trial_of_the_crusader : public InstanceMapScript { public: @@ -33,6 +41,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(MAX_ENCOUNTERS); + LoadBossBoundaries(boundaries); TrialCounter = 50; EventStage = 0; NorthrendBeasts = NOT_STARTED; diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 8f9b6313c84..5de0dbd865c 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -1269,7 +1269,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (_despawn) return; @@ -1335,7 +1335,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript } else if (me->getThreatManager().getThreatList().size() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER)) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return false; } @@ -1438,7 +1438,7 @@ struct npc_gauntlet_trash : public ScriptedAI _events.Reset(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (_instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED) _instance->SetData(DATA_WAVE_COUNT, NOT_STARTED); @@ -1546,10 +1546,10 @@ class npc_phantom_mage : public CreatureScript { npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature) { } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { if (!me->HasAura(AURA_HALLUCINATION)) - npc_gauntlet_trash::EnterEvadeMode(); + npc_gauntlet_trash::EnterEvadeMode(why); } void EnterCombat(Unit* /*who*/) override @@ -1626,10 +1626,10 @@ class npc_phantom_hallucination : public CreatureScript DoZoneInCombat(me, 150.0f); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { if (me->GetOwner() && !me->GetOwner()->HasAura(AURA_HALLUCINATION)) - npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode(); + npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode(why); } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index a5659299706..03f12e46bc3 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -166,10 +166,10 @@ class boss_ick : public CreatureScript events.ScheduleEvent(EVENT_SPECIAL, urand(30000, 35000)); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { me->GetMotionMaster()->Clear(); - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void JustDied(Unit* /*killer*/) override @@ -203,7 +203,7 @@ class boss_ick : public CreatureScript if (!me->GetVictim() && me->getThreatManager().isThreatListEmpty()) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 805de607114..af85fc95a64 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -170,7 +170,7 @@ class boss_tyrannus : public CreatureScript me->GetMotionMaster()->MoveChase(victim); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { instance->SetBossState(DATA_TYRANNUS, FAIL); if (Creature* rimefang = GetRimefang()) diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp index e547b84c381..12845d6e2b1 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -27,9 +27,9 @@ Position const EventLeaderPos2 = {1054.368f, 107.14620f, 628.4467f, 0.0f}; DoorData const Doors[] = { - {GO_ICE_WALL, DATA_GARFROST, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_ICE_WALL, DATA_ICK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_HALLS_OF_REFLECTION_PORTCULLIS, DATA_TYRANNUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, + {GO_ICE_WALL, DATA_GARFROST, DOOR_TYPE_PASSAGE }, + {GO_ICE_WALL, DATA_ICK, DOOR_TYPE_PASSAGE }, + {GO_HALLS_OF_REFLECTION_PORTCULLIS, DATA_TYRANNUS, DOOR_TYPE_PASSAGE }, }; class instance_pit_of_saron : public InstanceMapScript diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index 9e43228dc63..053e38ed93e 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -336,7 +336,7 @@ class boss_drakkari_elemental : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { me->DespawnOrUnsummon(); } diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp index 6ec02bfbe33..9f90b228247 100644 --- a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp +++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp @@ -23,12 +23,12 @@ DoorData const doorData[] = { - { GO_GAL_DARAH_DOOR_1, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GAL_DARAH_DOOR_2, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GAL_DARAH_DOOR_3, DATA_GAL_DARAH, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ECK_THE_FEROCIOUS_DOOR, DATA_MOORABI, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ECK_THE_FEROCIOUS_DOOR_BEHIND, DATA_ECK_THE_FEROCIOUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_GAL_DARAH_DOOR_1, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE }, + { GO_GAL_DARAH_DOOR_2, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE }, + { GO_GAL_DARAH_DOOR_3, DATA_GAL_DARAH, DOOR_TYPE_ROOM }, + { GO_ECK_THE_FEROCIOUS_DOOR, DATA_MOORABI, DOOR_TYPE_PASSAGE }, + { GO_ECK_THE_FEROCIOUS_DOOR_BEHIND, DATA_ECK_THE_FEROCIOUS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; ObjectData const creatureData[] = diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 9bc7c382a85..a0ce6700d8d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -173,7 +173,7 @@ class boss_blood_queen_lana_thel : public CreatureScript { if (!instance->CheckRequiredBosses(DATA_BLOOD_QUEEN_LANA_THEL, who->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } @@ -244,9 +244,11 @@ class boss_blood_queen_lana_thel : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - _EnterEvadeMode(); + if (!_EnterEvadeMode(why)) + return; + CleanAuras(); if (_killMinchar) { @@ -257,6 +259,7 @@ class boss_blood_queen_lana_thel : public CreatureScript } else { + me->AddUnitState(UNIT_STATE_EVADE); me->GetMotionMaster()->MoveTargetedHome(); Reset(); } @@ -333,7 +336,7 @@ class boss_blood_queen_lana_thel : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 98108d8fceb..7e9083115b8 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -287,7 +287,7 @@ class boss_deathbringer_saurfang : public CreatureScript if (!instance->CheckRequiredBosses(DATA_DEATHBRINGER_SAURFANG, who->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } @@ -332,9 +332,9 @@ class boss_deathbringer_saurfang : public CreatureScript ScriptedAI::AttackStart(victim); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); if (_introDone) me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); } @@ -390,7 +390,7 @@ class boss_deathbringer_saurfang : public CreatureScript if (target->GetTransport()) { summon->DespawnOrUnsummon(1); - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return; } @@ -420,7 +420,7 @@ class boss_deathbringer_saurfang : public CreatureScript { if (target->GetTransport()) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp index a57d49f9cb9..60a26878a3d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp @@ -115,7 +115,7 @@ class boss_festergut : public CreatureScript { if (!instance->CheckRequiredBosses(DATA_FESTERGUT, who->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } @@ -145,9 +145,9 @@ class boss_festergut : public CreatureScript instance->SetBossState(DATA_FESTERGUT, FAIL); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); if (Creature* professor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PROFESSOR_PUTRICIDE))) professor->AI()->EnterEvadeMode(); } @@ -166,7 +166,7 @@ class boss_festergut : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index eafb4f302eb..bf0d24c9e5e 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -573,7 +573,7 @@ struct gunship_npc_AI : public ScriptedAI } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (!me->IsAlive() || !me->IsInCombat()) return; @@ -622,7 +622,7 @@ protected: { if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return false; } @@ -635,7 +635,7 @@ protected: } else if (me->getThreatManager().isThreatListEmpty()) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return false; } @@ -870,7 +870,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000)); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (!me->IsAlive()) return; @@ -1138,7 +1138,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000)); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (!me->IsAlive()) return; @@ -1716,9 +1716,9 @@ class npc_gunship_mage : public CreatureScript me->SetReactState(REACT_PASSIVE); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void MovementInform(uint32 type, uint32 pointId) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 5a33117e629..a03042ee7ff 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -421,7 +421,7 @@ class boss_lady_deathwhisper : public CreatureScript void UpdateAI(uint32 diff) override { - if ((!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) || !CheckInRoom()) + if ((!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))) return; events.Update(diff); @@ -1043,8 +1043,9 @@ class at_lady_deathwhisper_entrance : public AreaTriggerScript bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/, bool /*entered*/) override { if (InstanceScript* instance = player->GetInstanceScript()) - if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER))) - ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO); + if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE) + if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER))) + ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO); return true; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 9dcadfacb0c..84211547416 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -186,7 +186,7 @@ class boss_lord_marrowgar : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index a702c4ffdf8..b9a7b6ce056 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -564,7 +564,7 @@ class boss_professor_putricide : public CreatureScript void UpdateAI(uint32 diff) override { - if ((!(events.IsInPhase(PHASE_ROTFACE) || events.IsInPhase(PHASE_FESTERGUT)) && !UpdateVictim()) || !CheckInRoom()) + if ((!(events.IsInPhase(PHASE_ROTFACE) || events.IsInPhase(PHASE_FESTERGUT)) && !UpdateVictim())) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index 981d4624cd4..1e5609bbb83 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -119,7 +119,7 @@ class boss_rotface : public CreatureScript { if (!instance->CheckRequiredBosses(DATA_ROTFACE, who->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } @@ -155,9 +155,9 @@ class boss_rotface : public CreatureScript Talk(SAY_KILL); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); if (Creature* professor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PROFESSOR_PUTRICIDE))) professor->AI()->EnterEvadeMode(); } @@ -179,7 +179,7 @@ class boss_rotface : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 2df85a2e176..bbbf222a4e7 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -265,7 +265,7 @@ class boss_sindragosa : public CreatureScript { if (!instance->CheckRequiredBosses(DATA_SINDRAGOSA, victim->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } @@ -276,6 +276,13 @@ class boss_sindragosa : public CreatureScript Talk(SAY_AGGRO); } + void EnterEvadeMode(EvadeReason why) override + { + if (_isInAirPhase && why == EVADE_REASON_BOUNDARY) + return; + BossAI::EnterEvadeMode(why); + } + void JustReachedHome() override { BossAI::JustReachedHome(); @@ -416,7 +423,7 @@ class boss_sindragosa : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 709fab15307..49bd81c472e 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -517,7 +517,7 @@ class boss_the_lich_king : public CreatureScript { if (!instance->CheckRequiredBosses(DATA_THE_LICH_KING, target->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } @@ -560,10 +560,10 @@ class boss_the_lich_king : public CreatureScript return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { instance->SetBossState(DATA_THE_LICH_KING, FAIL); - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) tirion->AI()->EnterEvadeMode(); DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS); @@ -1703,7 +1703,7 @@ class npc_terenas_menethil : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { // no running back home if (!me->IsAlive()) @@ -1946,7 +1946,7 @@ class npc_broken_frostmourne : public CreatureScript _events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6000, 0, PHASE_OUTRO); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index b5e19c54a24..50c09c6e3e0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -557,6 +557,8 @@ class npc_green_dragon_combat_trigger : public CreatureScript if (!me->IsInCombat()) return; + // @TODO check out of bounds on all encounter creatures, evade if matched + std::list<HostileReference*> const& threatList = me->getThreatManager().getThreatList(); if (threatList.empty()) { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 0bb9ede6cc1..d6a4cf87f4c 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1283,16 +1283,16 @@ struct npc_argent_captainAI : public ScriptedAI return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { // not yet following if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != CHASE_MOTION_TYPE || IsUndead) { - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); return; } - if (!_EnterEvadeMode()) + if (!_EnterEvadeMode(why)) return; if (!me->GetVehicle()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index fafb378c31c..1d6b1ffb61e 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -47,34 +47,54 @@ enum TimedEvents EVENT_RESPAWN_GUNSHIP = 4 }; +BossBoundaryData const boundaries = +{ + { DATA_LORD_MARROWGAR, new CircleBoundary(Position(-428.0f,2211.0f), 95.0) }, + { DATA_LORD_MARROWGAR, new RectangleBoundary(-430.0f, -330.0f, 2110.0f, 2310.0f) }, + { DATA_LADY_DEATHWHISPER, new RectangleBoundary(-670.0f, -520.0f, 2145.0f, 2280.0f) }, + { DATA_DEATHBRINGER_SAURFANG, new RectangleBoundary(-565.0f, -465.0f, 2160.0f, 2260.0f) }, + + { DATA_ROTFACE, new RectangleBoundary(4385.0f, 4505.0f, 3082.0f, 3195.0f) }, + { DATA_FESTERGUT, new RectangleBoundary(4205.0f, 4325.0f, 3082.0f, 3195.0f) }, + { DATA_PROFESSOR_PUTRICIDE, new ParallelogramBoundary(Position(4356.0f, 3290.0f), Position(4435.0f, 3194.0f), Position(4280.0f, 3194.0f)) }, + { DATA_PROFESSOR_PUTRICIDE, new RectangleBoundary(4280.0f, 4435.0f, 3150.0f, 4360.0f) }, + + { DATA_BLOOD_PRINCE_COUNCIL, new EllipseBoundary(Position(4660.95f, 2769.194f), 85.0, 60.0) }, + { DATA_BLOOD_QUEEN_LANA_THEL, new CircleBoundary(Position(4595.93f, 2769.365f), 64.0) }, + + { DATA_SISTER_SVALNA, new RectangleBoundary(4291.0f, 4423.0f, 2438.0f, 2653.0f) }, + { DATA_VALITHRIA_DREAMWALKER, new RectangleBoundary(4112.5f, 4293.5f, 2385.0f, 2585.0f) }, + { DATA_SINDRAGOSA, new EllipseBoundary(Position(4408.6f, 2484.0f), 100.0, 75.0) } +}; + DoorData const doorData[] = { - {GO_LORD_MARROWGAR_S_ENTRANCE, DATA_LORD_MARROWGAR, DOOR_TYPE_ROOM, BOUNDARY_N }, - {GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM, BOUNDARY_N }, - {GO_SAURFANG_S_DOOR, DATA_DEATHBRINGER_SAURFANG, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM, BOUNDARY_E }, - {GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM, BOUNDARY_E }, - {GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM, BOUNDARY_E }, - {GO_CRIMSON_HALL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_BLOOD_ELF_COUNCIL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_W }, - {GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_E }, - {GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_DOODAD_ICECROWN_GRATE_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_SISTER_SVALNA, DOOR_TYPE_PASSAGE, BOUNDARY_S }, - {GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM, BOUNDARY_N }, - {GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE, BOUNDARY_S }, - {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_01, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_N }, - {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_02, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_S }, - {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_03, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_N }, - {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_04, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_S }, - {GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_E }, - {GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, - {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SE }, - {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SW }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END + {GO_LORD_MARROWGAR_S_ENTRANCE, DATA_LORD_MARROWGAR, DOOR_TYPE_ROOM }, + {GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE }, + {GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM }, + {GO_SAURFANG_S_DOOR, DATA_DEATHBRINGER_SAURFANG, DOOR_TYPE_PASSAGE }, + {GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM }, + {GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM }, + {GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM }, + {GO_CRIMSON_HALL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_ROOM }, + {GO_BLOOD_ELF_COUNCIL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE }, + {GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_ROOM }, + {GO_DOODAD_ICECROWN_GRATE_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_PASSAGE }, + {GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_SISTER_SVALNA, DOOR_TYPE_PASSAGE }, + {GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM }, + {GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE }, + {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_01, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE }, + {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_02, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE }, + {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_03, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE }, + {GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_04, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE }, + {GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM }, + {GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE }, + {GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE }, + {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM }, + {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM }, + {0, 0, DOOR_TYPE_ROOM } // END }; // this doesnt have to only store questgivers, also can be used for related quest spawns @@ -115,6 +135,7 @@ class instance_icecrown_citadel : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); LoadDoorData(doorData); TeamInInstance = 0; HeroicAttempts = MaxHeroicAttempts; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index b060910e823..9deccccd040 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -173,7 +173,7 @@ public: void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 9b3d0b7555b..ec47b0db101 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -100,7 +100,7 @@ public: void UpdateAI(uint32 diff) override { - if (!UpdateVictimWithGaze() || !CheckInRoom()) + if (!UpdateVictimWithGaze()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 63029141490..6556227fd81 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -391,7 +391,7 @@ class boss_gothik : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); @@ -537,11 +537,11 @@ class npc_gothik_minion : public CreatureScript CombatAI::JustDied(owner); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { if (!gateClose) { - CombatAI::EnterEvadeMode(); + CombatAI::EnterEvadeMode(why); return; } @@ -566,7 +566,7 @@ class npc_gothik_minion : public CreatureScript { if (gateClose && (!isOnSameSide(me) || (me->GetVictim() && !isOnSameSide(me->GetVictim())))) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return; } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index 64d5a7c5133..afa8e97d8e6 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -115,7 +115,7 @@ public: void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index 814718c68a0..3f0090cc507 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -117,7 +117,7 @@ public: void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; if (HealthBelowPct(30) && !me->HasAura(SPELL_FRENZY_HELPER)) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index b820aa3266a..c0b12262a9a 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -88,7 +88,7 @@ public: events.SetPhase(PHASE_NONE); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { Reset(); // teleport back first _EnterEvadeMode(); @@ -205,7 +205,7 @@ public: void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index 667258ba676..68b9e252150 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -231,7 +231,7 @@ class boss_sapphiron : public CreatureScript events.Update(diff); - if ((_phase != PHASE_BIRTH && !UpdateVictim()) || !CheckInRoom()) + if (_phase != PHASE_BIRTH && !UpdateVictim()) return; if (_phase == PHASE_GROUND) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index 4831cc7b41d..675d7d4e308 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -456,6 +456,7 @@ public: { Initialize(); instance = creature->GetInstanceScript(); + SetBoundary(instance->GetBossBoundary(BOSS_THADDIUS)); } void Initialize() @@ -723,6 +724,7 @@ public: { Initialize(); instance = creature->GetInstanceScript(); + SetBoundary(instance->GetBossBoundary(BOSS_THADDIUS)); } void Initialize() @@ -990,7 +992,7 @@ public: { npc_teslaAI(Creature* creature) : ScriptedAI(creature) { } - void EnterEvadeMode() override { } // never stop casting due to evade + void EnterEvadeMode(EvadeReason /*why*/) override { } // never stop casting due to evade void UpdateAI(uint32 /*diff*/) override { } // never do anything unless told void EnterCombat(Unit* /*who*/) override { } void DamageTaken(Unit* /*who*/, uint32& damage) override { damage = 0; } // no, you can't kill it diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 3b6a97dbe1d..2bf50a0b8f5 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -20,42 +20,75 @@ #include "InstanceScript.h" #include "naxxramas.h" +BossBoundaryData const boundaries = +{ + /* Arachnid Quarter */ + { BOSS_ANUBREKHAN, new CircleBoundary(Position(3273.376709f, -3475.876709f), Position(3195.668213f, -3475.930176f)) }, + { BOSS_FAERLINA, new RectangleBoundary(3315.0f, 3402.0f, -3727.0f, -3590.0f) }, + { BOSS_FAERLINA, new CircleBoundary(Position(3372.68f, -3648.2f), Position(3316.0f, -3704.26f)) }, + { BOSS_MAEXXNA, new CircleBoundary(Position(3502.2587f, -3892.1697f), Position(3418.7422f, -3840.271f)) }, + + /* Plague Quarter */ + { BOSS_NOTH, new RectangleBoundary(2618.0f, 2754.0f, -3557.43f, -3450.0f) }, + { BOSS_HEIGAN, new CircleBoundary(Position(2772.57f, -3685.28f), 56.0f) }, + { BOSS_LOATHEB, new CircleBoundary(Position(2909.0f, -3997.41f), 57.0f) }, + + /* Military Quarter */ + { BOSS_RAZUVIOUS, new ZRangeBoundary(260.0f, 287.0f) }, // will not chase onto the upper floor + { BOSS_GOTHIK, new RectangleBoundary(2627.0f, 2764.0f, -3440.0f, -3275.0f) }, + { BOSS_HORSEMEN, new ParallelogramBoundary(AreaBoundary::DoublePosition(2646.0, -2959.0), AreaBoundary::DoublePosition(2529.0, -3075.0), AreaBoundary::DoublePosition(2506.0, -2854.0)) }, + + /* Construct Quarter */ + { BOSS_PATCHWERK, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) }, + { BOSS_PATCHWERK, new CircleBoundary(Position(3130.8576f, -3210.36f), Position(3085.37f, -3219.85f), true) }, // entrance slime circle blocker + { BOSS_GROBBULUS, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) }, + { BOSS_GROBBULUS, new RectangleBoundary(3295.0f, 3340.0f, -3254.2f, -3230.18f, true) }, // entrance door blocker + { BOSS_GLUTH, new CircleBoundary(Position(3293.0f, -3142.0f), 80.0) }, + { BOSS_GLUTH, new ParallelogramBoundary(AreaBoundary::DoublePosition(3401.0, -3149.0), AreaBoundary::DoublePosition(3261.0, -3028.0), AreaBoundary::DoublePosition(3320.0, -3267.0)) }, + { BOSS_GLUTH, new ZRangeBoundary(285.0f, 310.0f) }, + { BOSS_THADDIUS, new ParallelogramBoundary(AreaBoundary::DoublePosition(3478.3, -3070.0), AreaBoundary::DoublePosition(3370.0, -2961.5), AreaBoundary::DoublePosition(3580.0, -2961.5)) }, + + /* Frostwyrm Lair */ + { BOSS_SAPPHIRON, new CircleBoundary(Position(3517.627f, -5255.5f), 110.0) }, + { BOSS_KELTHUZAD, new CircleBoundary(Position(3716.0f, -5107.0f), 85.0) } +}; + DoorData const doorData[] = { - { GO_ROOM_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_PASSAGE_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_PASSAGE_FAERLINA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_MAEXXNA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_MAEXXNA, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW }, - { GO_ROOM_NOTH, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N }, - { GO_PASSAGE_NOTH, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E }, - { GO_ROOM_HEIGAN, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N }, - { GO_PASSAGE_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E }, - { GO_ROOM_LOATHEB, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_LOATHEB, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W }, - { GO_ROOM_GROBBULUS, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_GROBBULUS, BOSS_GROBBULUS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_PASSAGE_GLUTH, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW }, - { GO_ROOM_THADDIUS, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_THADDIUS, BOSS_THADDIUS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ROOM_GOTHIK, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ROOM_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N }, - { GO_PASSAGE_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S }, - { GO_ROOM_HORSEMEN, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GOTHIK_GATE, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_ROOM_HORSEMEN, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE }, - { GO_PASSAGE_SAPPHIRON, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W }, - { GO_ROOM_KELTHUZAD, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_ARAC_EYE_RAMP, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_ARAC_EYE_RAMP_BOSS, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_PLAG_EYE_RAMP, BOSS_LOATHEB, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_PLAG_EYE_RAMP_BOSS, BOSS_LOATHEB, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_MILI_EYE_RAMP, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_MILI_EYE_RAMP_BOSS, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_CONS_EYE_RAMP, BOSS_THADDIUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_CONS_EYE_RAMP_BOSS, BOSS_THADDIUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + { GO_ROOM_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_ROOM }, + { GO_PASSAGE_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_PASSAGE }, + { GO_PASSAGE_FAERLINA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE }, + { GO_ROOM_MAEXXNA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE }, + { GO_ROOM_MAEXXNA, BOSS_MAEXXNA, DOOR_TYPE_ROOM }, + { GO_ROOM_NOTH, BOSS_NOTH, DOOR_TYPE_ROOM }, + { GO_PASSAGE_NOTH, BOSS_NOTH, DOOR_TYPE_PASSAGE }, + { GO_ROOM_HEIGAN, BOSS_NOTH, DOOR_TYPE_PASSAGE }, + { GO_ROOM_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_ROOM }, + { GO_PASSAGE_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_PASSAGE }, + { GO_ROOM_LOATHEB, BOSS_HEIGAN, DOOR_TYPE_PASSAGE }, + { GO_ROOM_LOATHEB, BOSS_LOATHEB, DOOR_TYPE_ROOM }, + { GO_ROOM_GROBBULUS, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE }, + { GO_ROOM_GROBBULUS, BOSS_GROBBULUS, DOOR_TYPE_ROOM }, + { GO_PASSAGE_GLUTH, BOSS_GLUTH, DOOR_TYPE_PASSAGE }, + { GO_ROOM_THADDIUS, BOSS_GLUTH, DOOR_TYPE_PASSAGE }, + { GO_ROOM_THADDIUS, BOSS_THADDIUS, DOOR_TYPE_ROOM }, + { GO_ROOM_GOTHIK, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE }, + { GO_ROOM_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_ROOM }, + { GO_PASSAGE_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_PASSAGE }, + { GO_ROOM_HORSEMEN, BOSS_GOTHIK, DOOR_TYPE_PASSAGE }, + { GO_GOTHIK_GATE, BOSS_GOTHIK, DOOR_TYPE_ROOM }, + { GO_ROOM_HORSEMEN, BOSS_HORSEMEN, DOOR_TYPE_ROOM }, + { GO_PASSAGE_SAPPHIRON, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE }, + { GO_ROOM_KELTHUZAD, BOSS_KELTHUZAD, DOOR_TYPE_ROOM }, + { GO_ARAC_EYE_RAMP, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE }, + { GO_ARAC_EYE_RAMP_BOSS, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE }, + { GO_PLAG_EYE_RAMP, BOSS_LOATHEB, DOOR_TYPE_PASSAGE }, + { GO_PLAG_EYE_RAMP_BOSS, BOSS_LOATHEB, DOOR_TYPE_PASSAGE }, + { GO_MILI_EYE_RAMP, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE }, + { GO_MILI_EYE_RAMP_BOSS, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE }, + { GO_CONS_EYE_RAMP, BOSS_THADDIUS, DOOR_TYPE_PASSAGE }, + { GO_CONS_EYE_RAMP_BOSS, BOSS_THADDIUS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } }; MinionData const minionData[] = @@ -117,6 +150,7 @@ class instance_naxxramas : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); LoadDoorData(doorData); LoadMinionData(minionData); LoadObjectData(nullptr, objectData); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 0d5584e9960..9525d3f14f9 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -574,7 +574,7 @@ public: me->setActive(true); if (!instance->CheckRequiredBosses(DATA_MALYGOS_EVENT)) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return; } @@ -585,7 +585,7 @@ public: instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { instance->SetBossState(DATA_MALYGOS_EVENT, FAIL); @@ -1282,7 +1282,7 @@ public: VehicleAI::Reset(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { } @@ -1341,7 +1341,7 @@ class npc_nexus_lord : public CreatureScript _events.Reset(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { } @@ -1430,7 +1430,7 @@ class npc_scion_of_eternity : public CreatureScript { } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index 6b438e094d6..e5944841ad5 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -21,6 +21,11 @@ #include "eye_of_eternity.h" #include "Player.h" +BossBoundaryData const boundaries = +{ + { DATA_MALYGOS_EVENT, new CircleBoundary(Position(754.362f, 1301.609985f), 280.0) } // sanity check boundary +}; + class instance_eye_of_eternity : public InstanceMapScript { public: @@ -37,6 +42,7 @@ public: { SetHeaders(DataHeader); SetBossNumber(MAX_ENCOUNTER); + LoadBossBoundaries(boundaries); } void OnPlayerEnter(Player* player) override diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index d83e8386f2e..fa2d2712755 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -23,8 +23,8 @@ DoorData const doorData[] = { - { GO_DRAGON_CAGE_DOOR, DATA_DRAKOS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + { GO_DRAGON_CAGE_DOOR, DATA_DRAKOS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } }; Position const VerdisaMove = { 949.188f, 1032.91f, 359.967f, 1.093027f }; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index 1b93b611df6..bc2fbe00f27 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -187,14 +187,14 @@ public: instance->SetBossState(DATA_BJARNGRIM, NOT_STARTED); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { if (me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)) canBuff = true; else canBuff = false; - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp index 33d4758f5a9..37df62ac166 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -21,10 +21,10 @@ DoorData const doorData[] = { - { GO_VOLKHAN_DOOR, DATA_VOLKHAN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_IONAR_DOOR, DATA_IONAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_LOKEN_DOOR, DATA_LOKEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_VOLKHAN_DOOR, DATA_VOLKHAN, DOOR_TYPE_PASSAGE }, + { GO_IONAR_DOOR, DATA_IONAR, DOOR_TYPE_PASSAGE }, + { GO_LOKEN_DOOR, DATA_LOKEN, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_halls_of_lightning : public InstanceMapScript diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index 63f4ed28952..c6822235ce6 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -22,8 +22,8 @@ DoorData const doorData[] = { - { GO_SJONNIR_DOOR, DATA_TRIBUNAL_OF_AGES, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_SJONNIR_DOOR, DATA_TRIBUNAL_OF_AGES, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_halls_of_stone : public InstanceMapScript diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 77657870320..e80da765a5f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -492,10 +492,10 @@ class boss_algalon_the_observer : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { instance->SetBossState(BOSS_ALGALON, FAIL); - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetSheath(SHEATH_STATE_UNARMED); } @@ -545,7 +545,7 @@ class boss_algalon_the_observer : public CreatureScript void UpdateAI(uint32 diff) override { - if ((!(events.IsInPhase(PHASE_ROLE_PLAY) || events.IsInPhase(PHASE_BIG_BANG)) && !UpdateVictim()) || !CheckInRoom()) + if (!(events.IsInPhase(PHASE_ROLE_PLAY) || events.IsInPhase(PHASE_BIG_BANG)) && !UpdateVictim()) return; events.Update(diff); @@ -639,7 +639,7 @@ class boss_algalon_the_observer : public CreatureScript events.ScheduleEvent(EVENT_EVADE, 2500); break; case EVENT_EVADE: - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); break; case EVENT_COSMIC_SMASH: Talk(EMOTE_ALGALON_COSMIC_SMASH); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index e1c02e7ad99..0ce12c9cd70 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -369,7 +369,7 @@ class boss_flame_leviathan : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index 3398d318d85..cd214a0114f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -277,8 +277,6 @@ class boss_ignis : public CreatureScript } DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); } private: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 3378185c2a8..3b7e25f72d9 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -478,7 +478,7 @@ class boss_mimiron : public CreatureScript void UpdateAI(uint32 diff) override { - if ((!UpdateVictim() || !CheckInRoom()) && instance->GetBossState(BOSS_MIMIRON) != DONE) + if (!UpdateVictim() && instance->GetBossState(BOSS_MIMIRON) != DONE) return; events.Update(diff); @@ -846,7 +846,7 @@ class boss_leviathan_mk_ii : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); @@ -999,7 +999,7 @@ class boss_vx_001 : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { summons.DespawnAll(); } @@ -1174,7 +1174,7 @@ class boss_aerial_command_unit : public CreatureScript } } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { summons.DespawnAll(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index f898461154a..3f783e8201c 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -54,10 +54,10 @@ class boss_thorim : public CreatureScript _Reset(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { Talk(SAY_WIPE); - _EnterEvadeMode(); + _EnterEvadeMode(why); } void KilledUnit(Unit* who) override @@ -78,7 +78,7 @@ class boss_thorim : public CreatureScript _EnterCombat(); } - void UpdateAI(uint32 diff) override + void UpdateAI(uint32 /*diff*/) override { if (!UpdateVictim()) return; @@ -86,8 +86,6 @@ class boss_thorim : public CreatureScript // DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index 97864fd6173..a00e0d885cd 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -267,7 +267,7 @@ class boss_xt002 : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index ecd79e7ba63..e96337d2d19 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -447,9 +447,9 @@ class boss_voice_of_yogg_saron : public CreatureScript me->SetInCombatWithZone(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - BossAI::EnterEvadeMode(); + BossAI::EnterEvadeMode(why); for (uint8 i = DATA_SARA; i <= DATA_MIMIRON_YS; ++i) if (Creature* creature = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i))) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 5eee284f351..7271bd5af52 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -24,26 +24,43 @@ #include "WorldPacket.h" #include "ulduar.h" +static BossBoundaryData const boundaries = +{ + { BOSS_LEVIATHAN, new RectangleBoundary(148.0f, 401.3f, -155.0f, 90.0f) }, + { BOSS_IGNIS, new RectangleBoundary(495.0f, 680.0f, 90.0f, 400.0f) }, + { BOSS_RAZORSCALE, new RectangleBoundary(370.0f, 810.0f, -542.0f, -55.0f) }, + { BOSS_XT002, new RectangleBoundary(755.0f, 940.0f, -125.0f, 95.0f) }, + { BOSS_ASSEMBLY_OF_IRON, new CircleBoundary(Position(1587.2f, 121.0f), 90.0) }, + { BOSS_ALGALON, new CircleBoundary(Position(1632.668f, -307.7656f), 45.0) }, + { BOSS_ALGALON, new ZRangeBoundary(410.0f, 440.0f) }, + { BOSS_HODIR, new EllipseBoundary(Position(2001.5f, -240.0f), 50.0, 75.0) }, + { BOSS_THORIM, new CircleBoundary(Position(2134.73f, -263.2f), 50.0) }, + { BOSS_FREYA, new RectangleBoundary(2094.6f, 2520.0f, -250.0f, 200.0f) }, + { BOSS_MIMIRON, new CircleBoundary(Position(2744.0f, 2569.0f), 70.0) }, + { BOSS_VEZAX, new RectangleBoundary(1740.0f, 1930.0f, 31.0f, 228.0f) }, + { BOSS_YOGG_SARON, new CircleBoundary(Position(1980.42f, -27.68f), 105.0) } +}; + static DoorData const doorData[] = { - { GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_IRON_COUNCIL_DOOR, BOSS_ASSEMBLY_OF_IRON, DOOR_TYPE_ROOM, BOUNDARY_N }, - { GO_ARCHIVUM_DOOR, BOSS_ASSEMBLY_OF_IRON, DOOR_TYPE_PASSAGE, BOUNDARY_S }, - { GO_HODIR_ENTRANCE, BOSS_HODIR, DOOR_TYPE_ROOM, BOUNDARY_E }, - { GO_HODIR_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_HODIR_ICE_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_W }, - { GO_MIMIRON_DOOR_1, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_W }, - { GO_MIMIRON_DOOR_2, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_E }, - { GO_MIMIRON_DOOR_3, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE, BOUNDARY_E }, - { GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, - { GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - { GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM }, + { GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM }, + { GO_IRON_COUNCIL_DOOR, BOSS_ASSEMBLY_OF_IRON, DOOR_TYPE_ROOM }, + { GO_ARCHIVUM_DOOR, BOSS_ASSEMBLY_OF_IRON, DOOR_TYPE_PASSAGE }, + { GO_HODIR_ENTRANCE, BOSS_HODIR, DOOR_TYPE_ROOM }, + { GO_HODIR_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE }, + { GO_HODIR_ICE_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE }, + { GO_MIMIRON_DOOR_1, BOSS_MIMIRON, DOOR_TYPE_ROOM }, + { GO_MIMIRON_DOOR_2, BOSS_MIMIRON, DOOR_TYPE_ROOM }, + { GO_MIMIRON_DOOR_3, BOSS_MIMIRON, DOOR_TYPE_ROOM }, + { GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE }, + { GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM }, + { GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM }, + { GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM }, + { GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE }, + { GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE }, + { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE }, + { 0, 0, DOOR_TYPE_ROOM }, }; MinionData const minionData[] = @@ -74,7 +91,7 @@ class instance_ulduar : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(MAX_ENCOUNTER); - + LoadBossBoundaries(boundaries); LoadDoorData(doorData); LoadMinionData(minionData); LoadObjectData(creatureData, nullptr); @@ -818,12 +835,9 @@ class instance_ulduar : public InstanceMapScript { case DATA_COLOSSUS: ColossusData = data; - if (data == 2) + if (data == 2 && GetBossState(BOSS_LEVIATHAN) == NOT_STARTED) { - if (Creature* Leviathan = instance->GetCreature(LeviathanGUID)) - Leviathan->AI()->DoAction(ACTION_MOVE_TO_CENTER_POSITION); - if (GameObject* gameObject = instance->GetGameObject(LeviathanGateGUID)) - gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + _events.ScheduleEvent(EVENT_LEVIATHAN_BREAK_DOOR, 5 * IN_MILLISECONDS); SaveToDB(); } break; @@ -1179,6 +1193,12 @@ class instance_ulduar : public InstanceMapScript } } break; + case EVENT_LEVIATHAN_BREAK_DOOR: + if (Creature* Leviathan = instance->GetCreature(LeviathanGUID)) + Leviathan->AI()->DoAction(ACTION_MOVE_TO_CENTER_POSITION); + if (GameObject* gameObject = instance->GetGameObject(LeviathanGateGUID)) + gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + break; } } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index f9f2f94d587..58c963f9cb5 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -427,7 +427,8 @@ enum UlduarEvents EVENT_DESPAWN_ALGALON = 1, EVENT_UPDATE_ALGALON_TIMER = 2, ACTION_INIT_ALGALON = 6, - EVENT_DESPAWN_LEVIATHAN_VEHICLES = 7 + EVENT_DESPAWN_LEVIATHAN_VEHICLES = 7, + EVENT_LEVIATHAN_BREAK_DOOR = 8 }; enum YoggSaronIllusions diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp index 556756f41a7..fbcf464d8b1 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp @@ -21,9 +21,9 @@ DoorData const doorData[] = { - { GO_GIANT_PORTCULLIS_1, DATA_INGVAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GIANT_PORTCULLIS_2, DATA_INGVAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_GIANT_PORTCULLIS_1, DATA_INGVAR, DOOR_TYPE_PASSAGE }, + { GO_GIANT_PORTCULLIS_2, DATA_INGVAR, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; MinionData const minionData[] = diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp index 910ddfbc572..8f2d5a61770 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp @@ -19,11 +19,16 @@ #include "InstanceScript.h" #include "utgarde_pinnacle.h" +BossBoundaryData const boundaries = +{ + { DATA_KING_YMIRON, new RectangleBoundary(340.0f, 450.0f, -412.0f, -275.0f) } +}; + DoorData const doorData[] = { - { GO_SKADI_THE_RUTHLESS_DOOR, DATA_SKADI_THE_RUTHLESS, DOOR_TYPE_PASSAGE, BOUNDARY_W }, - { GO_KING_YMIRON_DOOR, DATA_KING_YMIRON, DOOR_TYPE_PASSAGE, BOUNDARY_N }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_SKADI_THE_RUTHLESS_DOOR, DATA_SKADI_THE_RUTHLESS, DOOR_TYPE_PASSAGE }, + { GO_KING_YMIRON_DOOR, DATA_KING_YMIRON, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_utgarde_pinnacle : public InstanceMapScript @@ -37,6 +42,7 @@ class instance_utgarde_pinnacle : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); LoadDoorData(doorData); } diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 70ab5516d03..63ca432996f 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -239,7 +239,7 @@ public: } } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } void MoveInLineOfSight(Unit* /*who*/) override { } diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index ec7acf0d894..88217cb384e 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -231,9 +231,9 @@ class npc_tournament_training_dummy : public CreatureScript events.ScheduleEvent(EVENT_DUMMY_RECAST_DEFEND, 5000); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - if (!_EnterEvadeMode()) + if (!_EnterEvadeMode(why)) return; Reset(); @@ -304,7 +304,7 @@ class npc_tournament_training_dummy : public CreatureScript case EVENT_DUMMY_RESET: if (UpdateVictim()) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); events.ScheduleEvent(EVENT_DUMMY_RESET, 10000); } break; diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index 6fd19da5df9..cc0be0bd895 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -337,7 +337,7 @@ public: void AttackStart(Unit* /*who*/) override { } void EnterCombat(Unit* /*who*/) override { } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override { diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp index 94cc67a5177..cbf0d6b1ce5 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp @@ -21,8 +21,8 @@ DoorData const doorData[] = { - { GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; ObjectData const gameObjectData[] = diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp index 2d98fb43190..8acd6067c0b 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp @@ -143,7 +143,7 @@ class boss_ambassador_hellmaw : public CreatureScript if (me->HasAura(SPELL_BANISH)) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); return; } diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp index ac351538ee7..96978e92b19 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp @@ -22,9 +22,9 @@ DoorData const doorData[] = { - { GO_REFECTORY_DOOR, DATA_BLACKHEART_THE_INCITER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_SCREAMING_HALL_DOOR, DATA_GRANDMASTER_VORPIL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_REFECTORY_DOOR, DATA_BLACKHEART_THE_INCITER, DOOR_TYPE_PASSAGE }, + { GO_SCREAMING_HALL_DOOR, DATA_GRANDMASTER_VORPIL, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_shadow_labyrinth : public InstanceMapScript diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index d97c60f3455..6bc502fa5e9 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1181,7 +1181,7 @@ public: void EnterCombat(Unit* /*who*/) override { } void MoveInLineOfSight(Unit* /*who*/) override { } - void EnterEvadeMode() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } void GetIllidanGUID(ObjectGuid guid) { @@ -1439,7 +1439,7 @@ public: } // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { me->RemoveAllAuras(); me->DeleteThreatList(); @@ -1474,7 +1474,7 @@ public: } for (std::vector<Unit*>::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr) (*itr)->setDeathState(JUST_DIED); - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); } void BeginTalk() @@ -1544,7 +1544,7 @@ public: { if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); ++WalkCount; } diff --git a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp index 9da6bdaee18..708a095d70a 100644 --- a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp +++ b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp @@ -408,7 +408,7 @@ struct boss_illidari_councilAI : public ScriptedAI LoadGUIDs(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { for (uint8 i = 0; i < 4; ++i) { @@ -419,7 +419,7 @@ struct boss_illidari_councilAI : public ScriptedAI return; } } - ScriptedAI::EnterEvadeMode(); + ScriptedAI::EnterEvadeMode(why); } void DamageTaken(Unit* done_by, uint32 &damage) override diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp index 1521b04375b..86ad7958957 100644 --- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -21,18 +21,18 @@ DoorData const doorData[] = { - { GO_NAJENTUS_GATE, DATA_HIGH_WARLORD_NAJENTUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_NAJENTUS_GATE, DATA_SUPREMUS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_SUPREMUS_GATE, DATA_SUPREMUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_SHADE_OF_AKAMA_DOOR, DATA_SHADE_OF_AKAMA, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_TERON_DOOR_1, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_TERON_DOOR_2, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_GURTOGG_DOOR, DATA_GURTOGG_BLOODBOIL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_TEMPLE_DOOR, DATA_RELIQUARY_OF_SOULS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_MOTHER_SHAHRAZ_DOOR, DATA_MOTHER_SHAHRAZ, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_COUNCIL_DOOR_1, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_COUNCIL_DOOR_2, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_NAJENTUS_GATE, DATA_HIGH_WARLORD_NAJENTUS, DOOR_TYPE_PASSAGE }, + { GO_NAJENTUS_GATE, DATA_SUPREMUS, DOOR_TYPE_ROOM }, + { GO_SUPREMUS_GATE, DATA_SUPREMUS, DOOR_TYPE_PASSAGE }, + { GO_SHADE_OF_AKAMA_DOOR, DATA_SHADE_OF_AKAMA, DOOR_TYPE_ROOM }, + { GO_TERON_DOOR_1, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM }, + { GO_TERON_DOOR_2, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM }, + { GO_GURTOGG_DOOR, DATA_GURTOGG_BLOODBOIL, DOOR_TYPE_PASSAGE }, + { GO_TEMPLE_DOOR, DATA_RELIQUARY_OF_SOULS, DOOR_TYPE_PASSAGE }, + { GO_MOTHER_SHAHRAZ_DOOR, DATA_MOTHER_SHAHRAZ, DOOR_TYPE_PASSAGE }, + { GO_COUNCIL_DOOR_1, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM }, + { GO_COUNCIL_DOOR_2, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_black_temple : public InstanceMapScript diff --git a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp index 9b23f458186..67f980cf192 100644 --- a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp +++ b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp @@ -21,9 +21,9 @@ DoorData const doorData[] = { - { GO_MAULGAR_DOOR, DATA_MAULGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GRUUL_DOOR, DATA_GRUUL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_MAULGAR_DOOR, DATA_MAULGAR, DOOR_TYPE_PASSAGE }, + { GO_GRUUL_DOOR, DATA_GRUUL, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END }; MinionData const minionData[] = diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp index f021a876b81..92b74c029ba 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp @@ -22,13 +22,13 @@ DoorData const doorData[] = { - { GO_PRISON_DOOR_01, DATA_KELIDAN_THE_BREAKER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_PRISON_DOOR_02, DATA_THE_MAKER, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_PRISON_DOOR_03, DATA_THE_MAKER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_PRISON_DOOR_04, DATA_BROGGOK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_PRISON_DOOR_05, DATA_BROGGOK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { GO_SUMMON_DOOR, DATA_KELIDAN_THE_BREAKER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_PRISON_DOOR_01, DATA_KELIDAN_THE_BREAKER, DOOR_TYPE_PASSAGE }, + { GO_PRISON_DOOR_02, DATA_THE_MAKER, DOOR_TYPE_ROOM }, + { GO_PRISON_DOOR_03, DATA_THE_MAKER, DOOR_TYPE_PASSAGE }, + { GO_PRISON_DOOR_04, DATA_BROGGOK, DOOR_TYPE_PASSAGE }, + { GO_PRISON_DOOR_05, DATA_BROGGOK, DOOR_TYPE_ROOM }, + { GO_SUMMON_DOOR, DATA_KELIDAN_THE_BREAKER, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_blood_furnace : public InstanceMapScript diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp index 21694d20208..30ffac54345 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -34,9 +34,9 @@ EndScriptData */ DoorData const doorData[] = { - { GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + { GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE }, + { GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } }; class instance_shattered_halls : public InstanceMapScript diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 7f3a908b830..102d567e810 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -484,7 +484,7 @@ class npc_ember_of_alar : public CreatureScript DoZoneInCombat(); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { me->setDeathState(JUST_DIED); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp index 16cdbdda3ad..edfa2aedf92 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp @@ -94,6 +94,8 @@ class boss_void_reaver : public CreatureScript if (!UpdateVictim()) return; + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) return; @@ -154,8 +156,6 @@ class boss_void_reaver : public CreatureScript } DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); } private: diff --git a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp index 0d54d8fc22e..a751ed546ff 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp @@ -36,9 +36,9 @@ EndScriptData */ DoorData const doorData[] = { - { GO_ARCANE_DOOR_LEFT, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_SW }, - { GO_ARCANE_DOOR_RIGHT, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_SE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_ARCANE_DOOR_LEFT, DATA_KAELTHAS, DOOR_TYPE_ROOM/*, BOUNDARY_SW */ }, + { GO_ARCANE_DOOR_RIGHT, DATA_KAELTHAS, DOOR_TYPE_ROOM/*, BOUNDARY_SE */ }, + { 0, 0, DOOR_TYPE_ROOM } // END }; ObjectData const gameObjectData[] = diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp index 77018c6f43c..c2f93fd3910 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp @@ -22,10 +22,10 @@ static DoorData const doorData[] = { - { GO_DOOR_MOARG_1, DATA_GATEWATCHER_IRON_HAND, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_DOOR_MOARG_2, DATA_GATEWATCHER_GYROKILL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_DOOR_NETHERMANCER, DATA_NETHERMANCER_SEPRETHREA, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + { GO_DOOR_MOARG_1, DATA_GATEWATCHER_IRON_HAND, DOOR_TYPE_PASSAGE }, + { GO_DOOR_MOARG_2, DATA_GATEWATCHER_GYROKILL, DOOR_TYPE_PASSAGE }, + { GO_DOOR_NETHERMANCER, DATA_NETHERMANCER_SEPRETHREA, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } }; class instance_mechanar : public InstanceMapScript diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp index 2d8654a9b48..148420ad1a0 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp @@ -21,9 +21,9 @@ DoorData const doorData[] = { - { GO_CONTAINMENT_CORE_SECURITY_FIELD_ALPHA, DATA_SOCCOTHRATES, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { GO_CONTAINMENT_CORE_SECURITY_FIELD_BETA, DATA_DALLIAH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_CONTAINMENT_CORE_SECURITY_FIELD_ALPHA, DATA_SOCCOTHRATES, DOOR_TYPE_PASSAGE }, + { GO_CONTAINMENT_CORE_SECURITY_FIELD_BETA, DATA_DALLIAH, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM } // END }; class instance_arcatraz : public InstanceMapScript diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 6ca8d6a247a..3ebdb846c4d 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -168,9 +168,9 @@ public: } // Override Evade Mode event, recast buff that was removed by standard handler - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - npc_escortAI::EnterEvadeMode(); + npc_escortAI::EnterEvadeMode(why); DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true); } diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index 274fa27c9d0..76a9f57c214 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -24,11 +24,24 @@ #include "ScriptedCreature.h" #include "CombatAI.h" #include "Pet.h" +#include "PetAI.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" enum MageSpells { SPELL_MAGE_CLONE_ME = 45204, - SPELL_MAGE_MASTERS_THREAT_LIST = 58838 + SPELL_MAGE_MASTERS_THREAT_LIST = 58838, + SPELL_MAGE_FROST_BOLT = 59638, + SPELL_MAGE_FIRE_BLAST = 59637 +}; + +enum MirrorImageTimers +{ + TIMER_MIRROR_IMAGE_INIT = 0, + TIMER_MIRROR_IMAGE_FROST_BOLT = 4000, + TIMER_MIRROR_IMAGE_FIRE_BLAST = 6000 }; class npc_pet_mage_mirror_image : public CreatureScript @@ -40,22 +53,186 @@ class npc_pet_mage_mirror_image : public CreatureScript { npc_pet_mage_mirror_imageAI(Creature* creature) : CasterAI(creature) { } + void Init() + { + Unit* owner = me->GetCharmerOrOwner(); + + std::list<Unit*> targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); + me->VisitNearbyObject(40.0f, searcher); + + Unit* highestThreatUnit = nullptr; + float highestThreat = 0.0f; + Unit* nearestPlayer = nullptr; + for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) + { + // Consider only units without CC + if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) + { + // Take first found unit + if (!highestThreatUnit && (*iter)->GetTypeId() != TYPEID_PLAYER) + { + highestThreatUnit = (*iter); + continue; + } + if (!nearestPlayer && ((*iter)->GetTypeId() == TYPEID_PLAYER)) + { + nearestPlayer = (*iter); + continue; + } + // else compare best fit unit with current unit + ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); + for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) + { + // Try to find threat referenced to owner + if ((*trig_citr)->getTarget() == owner) + { + // Check if best fit hostile unit hs lower threat than this current unit + if (highestThreat < (*trig_citr)->getThreat()) + { + // If so, update best fit unit + highestThreat = (*trig_citr)->getThreat(); + highestThreatUnit = (*iter); + break; + } + } + } + // In case no unit with threat was found so far, always check for nearest unit (only for players) + if ((*iter)->GetTypeId() == TYPEID_PLAYER) + { + // If this player is closer than the previous one, update it + if (me->GetDistance((*iter)->GetPosition()) < me->GetDistance(nearestPlayer->GetPosition())) + nearestPlayer = (*iter); + } + } + } + // Prioritize units with threat referenced to owner + if (highestThreat > 0.0f && highestThreatUnit) + me->Attack(highestThreatUnit, false); + // If there is no such target, try to attack nearest hostile unit if such exists + else if (nearestPlayer) + me->Attack(nearestPlayer, false); + } + + bool IsInThreatList(Unit* target) + { + Unit* owner = me->GetCharmerOrOwner(); + + std::list<Unit*> targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); + me->VisitNearbyObject(40.0f, searcher); + + for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) + { + if ((*iter) == target) + { + // Consider only units without CC + if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) + { + ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); + for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) + { + // Try to find threat referenced to owner + if ((*trig_citr)->getTarget() == owner) + return true; + } + } + } + } + return false; + } + void InitializeAI() override { CasterAI::InitializeAI(); Unit* owner = me->GetOwner(); if (!owner) return; - // Inherit Master's Threat List (not yet implemented) - owner->CastSpell((Unit*)NULL, SPELL_MAGE_MASTERS_THREAT_LIST, true); + // here mirror image casts on summoner spell (not present in client dbc) 49866 // here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcast by mirror images (stats related?) // Clone Me! owner->CastSpell(me, SPELL_MAGE_CLONE_ME, false); } + void EnterCombat(Unit* who) override + { + if (me->GetVictim() && !me->GetVictim()->HasBreakableByDamageCrowdControlAura(me)) + { + me->CastSpell(who, SPELL_MAGE_FIRE_BLAST, false); + events.ScheduleEvent(SPELL_MAGE_FROST_BOLT, TIMER_MIRROR_IMAGE_INIT); + events.ScheduleEvent(SPELL_MAGE_FIRE_BLAST, TIMER_MIRROR_IMAGE_FIRE_BLAST); + } + else + EnterEvadeMode(EVADE_REASON_OTHER); + } + + void Reset() override + { + events.Reset(); + } + + void UpdateAI(uint32 diff) override + { + Unit* owner = me->GetCharmerOrOwner(); + Unit* target = owner->getAttackerForHelper(); + + events.Update(diff); + + // prevent CC interrupts by images + if (me->GetVictim() && me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me)) + { + me->InterruptNonMeleeSpells(false); + return; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + if (!owner) + return; + + // assign target if image doesnt have any or the target is not actual + if (!target || me->GetVictim() != target) + { + Unit* ownerTarget = nullptr; + if (Player* owner = me->GetCharmerOrOwner()->ToPlayer()) + ownerTarget = owner->GetSelectedUnit(); + + // recognize which victim will be choosen + if (ownerTarget && ownerTarget->GetTypeId() == TYPEID_PLAYER) + { + if (!ownerTarget->HasBreakableByDamageCrowdControlAura(ownerTarget)) + me->Attack(ownerTarget, false); + } + else if (ownerTarget && (ownerTarget->GetTypeId() != TYPEID_PLAYER) && IsInThreatList(ownerTarget)) + { + if (!ownerTarget->HasBreakableByDamageCrowdControlAura(ownerTarget)) + me->Attack(ownerTarget, false); + } + else + Init(); + } + + if (uint32 spellId = events.ExecuteEvent()) + { + if (spellId == SPELL_MAGE_FROST_BOLT) + { + events.ScheduleEvent(SPELL_MAGE_FROST_BOLT, TIMER_MIRROR_IMAGE_FROST_BOLT); + DoCastVictim(spellId); + } + else if (spellId == SPELL_MAGE_FIRE_BLAST) + { + DoCastVictim(spellId); + events.ScheduleEvent(SPELL_MAGE_FIRE_BLAST, TIMER_MIRROR_IMAGE_FIRE_BLAST); + } + } + } + // Do not reload Creature templates on evade mode enter - prevent visual lost - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (me->IsInEvadeMode() || !me->IsAlive()) return; @@ -68,6 +245,7 @@ class npc_pet_mage_mirror_image : public CreatureScript me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE); } + Init(); } }; diff --git a/src/server/scripts/Pet/pet_priest.cpp b/src/server/scripts/Pet/pet_priest.cpp index 61ac54f8ac0..a3110ce8f8b 100644 --- a/src/server/scripts/Pet/pet_priest.cpp +++ b/src/server/scripts/Pet/pet_priest.cpp @@ -44,7 +44,7 @@ class npc_pet_pri_lightwell : public CreatureScript DoCast(me, SPELL_PRIEST_LIGHTWELL_CHARGES, false); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (!me->IsAlive()) return; diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/scripts/ScriptLoader.cpp index ccc4c39ccd1..145977a5f79 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/scripts/ScriptLoader.cpp @@ -19,7 +19,6 @@ #include "World.h" void AddSpellsScripts(); -void AddSC_SmartScripts(); void AddCommandsScripts(); #ifdef SCRIPTS @@ -38,7 +37,6 @@ void AddCustomScripts(); void AddScripts() { AddSpellsScripts(); - AddSC_SmartScripts(); AddCommandsScripts(); #ifdef SCRIPTS AddWorldScripts(); diff --git a/src/server/game/Scripting/ScriptLoader.h b/src/server/scripts/ScriptLoader.h index 57b62df22d1..57b62df22d1 100644 --- a/src/server/game/Scripting/ScriptLoader.h +++ b/src/server/scripts/ScriptLoader.h diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index aea3cf455c8..85e94c19f93 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4114,6 +4114,44 @@ public: } }; +enum LandmineKnockbackAchievement +{ + SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT = 57064 +}; + +class spell_gen_landmine_knockback_achievement : public SpellScriptLoader +{ +public: + spell_gen_landmine_knockback_achievement() : SpellScriptLoader("spell_gen_landmine_knockback_achievement") { } + + class spell_gen_landmine_knockback_achievement_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_landmine_knockback_achievement_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Player* target = GetHitPlayer()) + { + Aura const* aura = GetHitAura(); + if (!aura || aura->GetStackAmount() < 10) + return; + + target->CastSpell(target, SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT, true); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_landmine_knockback_achievement_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_landmine_knockback_achievement_SpellScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -4201,4 +4239,5 @@ void AddSC_generic_spell_scripts() new spell_gen_gm_freeze(); new spell_gen_stand(); new spell_gen_mixology_bonus(); + new spell_gen_landmine_knockback_achievement(); } diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index 1b884c14464..4e4d5cdf4fd 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -410,6 +410,80 @@ class spell_pilgrims_bounty_buff_food : public SpellScriptLoader } }; +enum TheTurkinator +{ + SPELL_KILL_COUNTER_VISUAL = 62015, + SPELL_KILL_COUNTER_VISUAL_MAX = 62021, + EMOTE_TURKEY_HUNTER = 0, + EMOTE_TURKEY_DOMINATION = 1, + EMOTE_TURKEY_SLAUGHTER = 2, + EMOTE_TURKEY_TRIUMPH = 3 +}; + +class spell_pilgrims_bounty_turkey_tracker : public SpellScriptLoader +{ + public: + spell_pilgrims_bounty_turkey_tracker() : SpellScriptLoader("spell_pilgrims_bounty_turkey_tracker") { } + + class spell_pilgrims_bounty_turkey_tracker_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pilgrims_bounty_turkey_tracker_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_KILL_COUNTER_VISUAL) || !sSpellMgr->GetSpellInfo(SPELL_KILL_COUNTER_VISUAL_MAX)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Creature* caster = GetCaster()->ToCreature(); + Unit* target = GetHitUnit(); + + if (!target || !caster) + return; + + if (target->HasAura(SPELL_KILL_COUNTER_VISUAL_MAX)) + return; + + if (Aura const* aura = target->GetAura(GetSpellInfo()->Id)) + { + switch (aura->GetStackAmount()) + { + case 10: + caster->AI()->Talk(EMOTE_TURKEY_HUNTER, target); + break; + case 20: + caster->AI()->Talk(EMOTE_TURKEY_DOMINATION, target); + break; + case 30: + caster->AI()->Talk(EMOTE_TURKEY_SLAUGHTER, target); + break; + case 40: + caster->AI()->Talk(EMOTE_TURKEY_TRIUMPH, target); + target->CastSpell(target, SPELL_KILL_COUNTER_VISUAL_MAX, true); + target->RemoveAurasDueToSpell(GetSpellInfo()->Id); + break; + default: + return; + } + target->CastSpell(target, SPELL_KILL_COUNTER_VISUAL, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_pilgrims_bounty_turkey_tracker_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_pilgrims_bounty_turkey_tracker_SpellScript(); + } +}; + enum Mistletoe { SPELL_CREATE_MISTLETOE = 26206, @@ -973,6 +1047,7 @@ void AddSC_holiday_spell_scripts() new spell_pilgrims_bounty_buff_food("spell_gen_spice_bread_stuffing", SPELL_WELL_FED_HIT_TRIGGER); new spell_pilgrims_bounty_buff_food("spell_gen_pumpkin_pie", SPELL_WELL_FED_SPIRIT_TRIGGER); new spell_pilgrims_bounty_buff_food("spell_gen_candied_sweet_potato", SPELL_WELL_FED_HASTE_TRIGGER); + new spell_pilgrims_bounty_turkey_tracker(); // Winter Veil new spell_winter_veil_mistletoe(); new spell_winter_veil_px_238_winter_wondervolt(); diff --git a/src/server/scripts/World/npc_taxi.cpp b/src/server/scripts/World/npc_taxi.cpp index 364caebd932..a200ba545d8 100644 --- a/src/server/scripts/World/npc_taxi.cpp +++ b/src/server/scripts/World/npc_taxi.cpp @@ -33,30 +33,8 @@ EndScriptData #define GOSSIP_SUSURRUS "I am ready." #define GOSSIP_NETHER_DRAKE "I'm ready to fly! Take me up, dragon!" #define GOSSIP_BRAZEN "I am ready to go to Durnholde Keep." -#define GOSSIP_IRONWING "I'd like to take a flight around Stormwind Harbor." -#define GOSSIP_DABIREE1 "Fly me to Murketh and Shaadraz Gateways" -#define GOSSIP_DABIREE2 "Fly me to Shatter Point" -#define GOSSIP_WINDBELLOW1 "Fly me to The Abyssal Shelf" -#define GOSSIP_WINDBELLOW2 "Fly me to Honor Point" -#define GOSSIP_BRACK1 "Fly me to Murketh and Shaadraz Gateways" -#define GOSSIP_BRACK2 "Fly me to The Abyssal Shelf" -#define GOSSIP_BRACK3 "Fly me to Spinebreaker Post" -#define GOSSIP_IRENA "Fly me to Skettis please" -#define GOSSIP_CLOUDBREAKER1 "Speaking of action, I've been ordered to undertake an air strike." -#define GOSSIP_CLOUDBREAKER2 "I need to intercept the Dawnblade reinforcements." -#define GOSSIP_DRAGONHAWK "<Ride the dragonhawk to Sun's Reach>" #define GOSSIP_VERONIA "Fly me to Manaforge Coruu please" -#define GOSSIP_DEESAK "Fly me to Ogri'la please" -#define GOSSIP_AFRASASTRASZ1 "I would like to take a flight to the ground, Lord Of Afrasastrasz." -#define GOSSIP_AFRASASTRASZ2 "My Lord, I must go to the upper floor of the temple." -#define GOSSIP_TARIOLSTRASZ1 "My Lord, I must go to the upper floor of the temple." -#define GOSSIP_TARIOLSTRASZ2 "Can you spare a drake to travel to Lord Of Afrasastrasz, in the middle of the temple?" -#define GOSSIP_TORASTRASZA1 "I would like to see Lord Of Afrasastrasz, in the middle of the temple." -#define GOSSIP_TORASTRASZA2 "Yes, Please. I would like to return to the ground floor of the temple." #define GOSSIP_CRIMSONWING "<Ride the gryphons to Survey Alcaz Island>" -#define GOSSIP_WILLIAMKEILAR1 "Take me to Northpass Tower." -#define GOSSIP_WILLIAMKEILAR2 "Take me to Eastwall Tower." -#define GOSSIP_WILLIAMKEILAR3 "Take me to Crown Guard Tower." class npc_taxi : public CreatureScript { @@ -81,91 +59,15 @@ public: case 18725: // Old Hillsbrad Foothills - Brazen player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRAZEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); break; - case 29154: // Stormwind City - Thargold Ironwing - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - break; - case 19409: // Hellfire Peninsula - Wing Commander Dabir'ee - //Mission: The Murketh and Shaadraz Gateways - if (player->GetQuestStatus(10146) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - - //Shatter Point - if (!player->GetQuestRewardStatus(10340)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - break; - case 20235: // Hellfire Peninsula - Gryphoneer Windbellow - //Mission: The Abyssal Shelf || Return to the Abyssal Shelf - if (player->GetQuestStatus(10163) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10346) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - - //Go to the Front - if (player->GetQuestStatus(10382) != QUEST_STATUS_NONE && !player->GetQuestRewardStatus(10382)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - break; - case 19401: // Hellfire Peninsula - Wing Commander Brack - //Mission: The Murketh and Shaadraz Gateways - if (player->GetQuestStatus(10129) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); - - //Mission: The Abyssal Shelf || Return to the Abyssal Shelf - if (player->GetQuestStatus(10162) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10347) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); - - //Spinebreaker Post - if (player->GetQuestStatus(10242) == QUEST_STATUS_COMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); - break; - case 23413: // Blade's Edge Mountains - Skyguard Handler Irena - if (player->GetReputationRank(1031) >= REP_HONORED) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRENA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - break; - case 25059: // Isle of Quel'Danas - Ayren Cloudbreaker - if (player->GetQuestStatus(11532) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11533) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - - if (player->GetQuestStatus(11542) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - break; - case 25236: // Isle of Quel'Danas - Unrestrained Dragonhawk - if (player->GetQuestStatus(11542) == QUEST_STATUS_COMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_COMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DRAGONHAWK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - break; case 20162: // Netherstorm - Veronia //Behind Enemy Lines if (player->GetQuestStatus(10652) != QUEST_STATUS_REWARDED) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VERONIA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); break; - case 23415: // Terokkar Forest - Skyguard Handler Deesak - if (player->GetReputationRank(1031) >= REP_HONORED) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEESAK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16); - break; - case 27575: // Dragonblight - Lord Afrasastrasz - // middle -> ground - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 17); - // middle -> top - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 18); - break; - case 26443: // Dragonblight - Tariolstrasz //need to check if quests are required before gossip available (12123, 12124) - // ground -> top - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 19); - // ground -> middle - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20); - break; - case 26949: // Dragonblight - Torastrasza - // top -> middle - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); - // top -> ground - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); - break; case 23704: // Dustwallow Marsh - Cassa Crimsonwing if (player->GetQuestStatus(11142) == QUEST_STATUS_INCOMPLETE) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+25); break; - case 17209: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 27); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28); - break; } player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -195,102 +97,14 @@ public: player->ActivateTaxiPathTo(534); //TaxiPath 534 } break; - case GOSSIP_ACTION_INFO_DEF + 3: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 53335, true); //TaxiPath 1041 (Stormwind Harbor) - break; - case GOSSIP_ACTION_INFO_DEF + 4: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 33768, true); //TaxiPath 585 (Gateways Murket and Shaadraz) - break; - case GOSSIP_ACTION_INFO_DEF + 5: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 35069, true); //TaxiPath 612 (Taxi - Hellfire Peninsula - Expedition Point to Shatter Point) - break; - case GOSSIP_ACTION_INFO_DEF + 6: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 33899, true); //TaxiPath 589 (Aerial Assault Flight (Alliance)) - break; - case GOSSIP_ACTION_INFO_DEF + 7: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 35065, true); //TaxiPath 607 (Taxi - Hellfire Peninsula - Shatter Point to Beach Head) - break; - case GOSSIP_ACTION_INFO_DEF + 8: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 33659, true); //TaxiPath 584 (Gateways Murket and Shaadraz) - break; - case GOSSIP_ACTION_INFO_DEF + 9: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 33825, true); //TaxiPath 587 (Aerial Assault Flight (Horde)) - break; - case GOSSIP_ACTION_INFO_DEF + 10: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 34578, true); //TaxiPath 604 (Taxi - Reaver's Fall to Spinebreaker Ridge) - break; - case GOSSIP_ACTION_INFO_DEF + 11: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 41278, true); //TaxiPath 706 - break; - case GOSSIP_ACTION_INFO_DEF + 12: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 45071, true); //TaxiPath 779 - break; - case GOSSIP_ACTION_INFO_DEF + 13: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 45113, true); //TaxiPath 784 - break; - case GOSSIP_ACTION_INFO_DEF + 14: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 45353, true); //TaxiPath 788 - break; case GOSSIP_ACTION_INFO_DEF + 15: player->CLOSE_GOSSIP_MENU(); player->CastSpell(player, 34905, true); //TaxiPath 606 break; - case GOSSIP_ACTION_INFO_DEF + 16: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 41279, true); //TaxiPath 705 (Taxi - Skettis to Skyguard Outpost) - break; - case GOSSIP_ACTION_INFO_DEF + 17: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(882); - break; - case GOSSIP_ACTION_INFO_DEF + 18: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(881); - break; - case GOSSIP_ACTION_INFO_DEF + 19: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(878); - break; - case GOSSIP_ACTION_INFO_DEF + 20: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(883); - break; - case GOSSIP_ACTION_INFO_DEF + 21: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(880); - break; - case GOSSIP_ACTION_INFO_DEF + 22: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(879); - break; case GOSSIP_ACTION_INFO_DEF + 25: player->CLOSE_GOSSIP_MENU(); player->CastSpell(player, 42295, true); break; - case GOSSIP_ACTION_INFO_DEF + 26: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(494); - break; - case GOSSIP_ACTION_INFO_DEF + 27: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(495); - break; - case GOSSIP_ACTION_INFO_DEF + 28: - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(496); - break; } return true; diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 90d15131bc4..87616548350 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -1434,9 +1434,9 @@ public: _events.ScheduleEvent(EVENT_TD_DESPAWN, 15000); } - void EnterEvadeMode() override + void EnterEvadeMode(EvadeReason why) override { - if (!_EnterEvadeMode()) + if (!_EnterEvadeMode(why)) return; Reset(); diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index fd6ff91e135..ce6c13bd932 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -8,74 +8,61 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Cryptography Cryptography/*.cpp Cryptography/*.h) -file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h) -file(GLOB_RECURSE sources_Dynamic Dynamic/*.cpp Dynamic/*.h) -file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h) -file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h) -file(GLOB_RECURSE sources_Realm Realm/*.cpp Realm/*.h) -if(WIN32) - file(GLOB_RECURSE sources_Service Service/*.cpp Service/*.h) -endif(WIN32) - -file(GLOB sources_localdir *.cpp *.h) - -# Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in shared project -# It needs to be included both in bnetserver and worldserver for the static global variable to be properly initialized -# and to handle crash logs on windows -set(sources_Debugging Debugging/Errors.cpp Debugging/Errors.h) - -# -# Build shared sourcelist -# +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) if (USE_COREPCH) - set(shared_STAT_PCH_HDR PrecompiledHeaders/sharedPCH.h) - set(shared_STAT_PCH_SRC PrecompiledHeaders/sharedPCH.cpp) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/sharedPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/sharedPCH.cpp) endif() -set(shared_STAT_SRCS - ${shared_STAT_SRCS} - ${sources_Cryptography} - ${sources_DataStores} - ${sources_Dynamic} - ${sources_Networking} - ${sources_Packets} - ${sources_Realm} - ${sources_Service} - ${sources_localdir} -) +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_definitions(-DTRINITY_API_EXPORT_SHARED) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic - ${CMAKE_CURRENT_SOURCE_DIR}/Networking - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/common/ - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/server/database - ${CMAKE_SOURCE_DIR}/src/server/database/Database - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} +add_library(shared + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -add_library(shared STATIC - ${shared_STAT_SRCS} - ${shared_STAT_PCH_SRC} -) +target_include_directories(shared + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_dependencies(shared revision_data.h) +target_link_libraries(shared + PUBLIC + database + rapidjson) + +set_target_properties(shared + PROPERTIES + FOLDER + "server") + +if( BUILD_SHARED_LIBS ) + if( UNIX ) + install(TARGETS shared + LIBRARY + DESTINATION lib) + elseif( WIN32 ) + install(TARGETS shared + RUNTIME + DESTINATION "${CMAKE_INSTALL_PREFIX}") + endif() +endif() # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(shared ${shared_STAT_PCH_HDR} ${shared_STAT_PCH_SRC}) + add_cxx_pch(shared ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif () diff --git a/src/server/shared/DataStores/DB2StorageLoader.h b/src/server/shared/DataStores/DB2StorageLoader.h index 0b83bc43dc4..41705c67f19 100644 --- a/src/server/shared/DataStores/DB2StorageLoader.h +++ b/src/server/shared/DataStores/DB2StorageLoader.h @@ -24,7 +24,7 @@ #include <cassert> #include <list> -class DB2FileLoader +class TC_SHARED_API DB2FileLoader { public: DB2FileLoader(); @@ -114,7 +114,7 @@ private: int unk5; // WDB2 }; -class DB2DatabaseLoader +class TC_SHARED_API DB2DatabaseLoader { public: explicit DB2DatabaseLoader(std::string const& storageName) : _storageName(storageName) { } diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h index cbbd786337c..e58031e6ccc 100644 --- a/src/server/shared/DataStores/DBCFileLoader.h +++ b/src/server/shared/DataStores/DBCFileLoader.h @@ -23,7 +23,7 @@ #include "Utilities/ByteConverter.h" #include <cassert> -class DBCFileLoader +class TC_SHARED_API DBCFileLoader { public: DBCFileLoader(); diff --git a/src/server/shared/Networking/AsyncAcceptor.h b/src/server/shared/Networking/AsyncAcceptor.h index d21801a64ac..e2f4045ccff 100644 --- a/src/server/shared/Networking/AsyncAcceptor.h +++ b/src/server/shared/Networking/AsyncAcceptor.h @@ -21,6 +21,7 @@ #include "Log.h" #include <boost/asio.hpp> #include <functional> +#include <atomic> using boost::asio::ip::tcp; diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index 07f427652aa..0674ede57d8 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -55,11 +55,11 @@ public: virtual bool Update() { - if (!IsOpen()) + if (_closed) return false; #ifndef TC_SOCKET_USE_IOCP - if (_isWritingAsync || _writeQueue.empty()) + if (_isWritingAsync || (_writeQueue.empty() && !_closing)) return true; for (; HandleQueue();) @@ -90,6 +90,17 @@ public: std::bind(&Socket<T>::ReadHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } + void AsyncReadWithCallback(void (T::*callback)(boost::system::error_code, std::size_t)) + { + if (!IsOpen()) + return; + + _readBuffer.Normalize(); + _readBuffer.EnsureFreeSpace(); + _socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), _readBuffer.GetRemainingSpace()), + std::bind(callback, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + } + void QueuePacket(MessageBuffer&& buffer) { _writeQueue.push(std::move(buffer)); @@ -153,7 +164,6 @@ protected: GetRemoteIpAddress().to_string().c_str(), err.value(), err.message().c_str()); } - private: void ReadHandlerInternal(boost::system::error_code error, size_t transferredBytes) { @@ -197,9 +207,6 @@ private: bool HandleQueue() { - if (!IsOpen()) - return false; - if (_writeQueue.empty()) return false; @@ -216,11 +223,15 @@ private: return AsyncProcessQueue(); _writeQueue.pop(); + if (_closing && _writeQueue.empty()) + CloseSocket(); return false; } else if (bytesSent == 0) { _writeQueue.pop(); + if (_closing && _writeQueue.empty()) + CloseSocket(); return false; } else if (bytesSent < bytesToSend) // now n > 0 @@ -230,6 +241,8 @@ private: } _writeQueue.pop(); + if (_closing && _writeQueue.empty()) + CloseSocket(); return !_writeQueue.empty(); } diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index b8c6ee1c36e..2373e632c44 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -37,7 +37,7 @@ class MessageBuffer; // Root of ByteBuffer exception hierarchy -class ByteBufferException : public std::exception +class TC_SHARED_API ByteBufferException : public std::exception { public: ~ByteBufferException() throw() { } @@ -51,7 +51,7 @@ private: std::string msg_; }; -class ByteBufferPositionException : public ByteBufferException +class TC_SHARED_API ByteBufferPositionException : public ByteBufferException { public: ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize); @@ -59,7 +59,7 @@ public: ~ByteBufferPositionException() throw() { } }; -class ByteBufferSourceException : public ByteBufferException +class TC_SHARED_API ByteBufferSourceException : public ByteBufferException { public: ByteBufferSourceException(size_t pos, size_t size, size_t valueSize); @@ -67,7 +67,7 @@ public: ~ByteBufferSourceException() throw() { } }; -class ByteBuffer +class TC_SHARED_API ByteBuffer { public: static size_t const DEFAULT_SIZE = 0x1000; diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h index 585a98e4569..87d333a4bf6 100644 --- a/src/server/shared/Realm/Realm.h +++ b/src/server/shared/Realm/Realm.h @@ -41,7 +41,7 @@ enum RealmFlags namespace Battlenet { - struct RealmHandle + struct TC_SHARED_API RealmHandle { RealmHandle() : Region(0), Site(0), Realm(0) { } RealmHandle(uint8 region, uint8 battlegroup, uint32 index) @@ -78,7 +78,7 @@ enum RealmType }; // Storage object for a realm -struct Realm +struct TC_SHARED_API Realm { Battlenet::RealmHandle Id; uint32 Build; diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 0d1a296e68a..7fb4c6d2b75 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -8,122 +8,29 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources_CommandLine CommandLine/*.cpp CommandLine/*.h) -file(GLOB_RECURSE sources_RemoteAccess RemoteAccess/*.cpp RemoteAccess/*.h) -file(GLOB_RECURSE sources_TCSoap TCSoap/*.cpp TCSoap/*.h) -file(GLOB sources_localdir *.cpp *.h) - -if (USE_COREPCH) - set(worldserver_PCH_HDR PrecompiledHeaders/worldPCH.h) - set(worldserver_PCH_SRC PrecompiledHeaders/worldPCH.cpp) -endif() - -set(worldserver_SRCS - ${worldserver_SRCS} - ${sources_CommandLine} - ${sources_RemoteAccess} - ${sources_TCSoap} - ${sources_localdir} -) +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) if( WIN32 ) - set(worldserver_SRCS - ${worldserver_SRCS} - ${sources_windows_Debugging} - ) + list(APPEND PRIVATE_SOURCES ${sources_windows}) if ( MSVC ) - set(worldserver_SRCS - ${worldserver_SRCS} - worldserver.rc - ) + list(APPEND PRIVATE_SOURCES worldserver.rc) endif() endif() -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/CommandLine - ${CMAKE_CURRENT_SOURCE_DIR}/RemoteAccess - ${CMAKE_CURRENT_SOURCE_DIR}/TCSoap - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/gsoap - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/src/common/ - ${CMAKE_SOURCE_DIR}/src/common/Collision - ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps - ${CMAKE_SOURCE_DIR}/src/common/Collision/Models - ${CMAKE_SOURCE_DIR}/src/common/Configuration - ${CMAKE_SOURCE_DIR}/src/common/Cryptography - ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/server/authserver/Realms - ${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/game - ${CMAKE_SOURCE_DIR}/src/server/game/Accounts - ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds - ${CMAKE_SOURCE_DIR}/src/server/game/Chat - ${CMAKE_SOURCE_DIR}/src/server/game/Combat - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item/Container - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Pet - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Player - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Vehicle - ${CMAKE_SOURCE_DIR}/src/server/game/Globals - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Groups - ${CMAKE_SOURCE_DIR}/src/server/game/Handlers - ${CMAKE_SOURCE_DIR}/src/server/game/Instances - ${CMAKE_SOURCE_DIR}/src/server/game/Loot - ${CMAKE_SOURCE_DIR}/src/server/game/Mails - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Quests - ${CMAKE_SOURCE_DIR}/src/server/game/Scripting - ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol - ${CMAKE_SOURCE_DIR}/src/server/game/Spells - ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_SOURCE_DIR}/src/server/game/Weather - ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/ipc - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${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/Service - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} - ${ZMQ_INCLUDE_DIR} -) +if (USE_COREPCH) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/worldPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/worldPCH.cpp) +endif() GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(worldserver - ${worldserver_SRCS} - ${worldserver_PCH_SRC} + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) if( NOT WIN32 ) @@ -139,27 +46,27 @@ endif() set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAGS}") target_link_libraries(worldserver - game - scripts - shared - database - ipc - common - g3dlib - gsoap - Detour - zmqpp - format - ${JEMALLOC_LIBRARY} - ${READLINE_LIBRARY} - ${TERMCAP_LIBRARY} - ${MYSQL_LIBRARY} - ${OPENSSL_LIBRARIES} - ${ZLIB_LIBRARIES} - ${ZMQ_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - ${Boost_LIBRARIES} -) + PUBLIC + scripts + gsoap + readline) + +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) + +target_include_directories(worldserver + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +set_target_properties(worldserver + PROPERTIES + FOLDER + "server") if( WIN32 ) if ( MSVC ) @@ -185,5 +92,5 @@ endif() # Generate precompiled header if( USE_COREPCH ) - add_cxx_pch(worldserver ${worldserver_PCH_HDR} ${worldserver_PCH_SRC}) + add_cxx_pch(worldserver ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif() diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 906937e974b..8c801736ef4 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -21,8 +21,6 @@ /// \file #include "Common.h" -#include "Commands.h" -#include "ZmqContext.h" #include "DatabaseEnv.h" #include "AsyncAcceptor.h" #include "RASession.h" @@ -35,6 +33,7 @@ #include "InstanceSaveMgr.h" #include "ObjectAccessor.h" #include "ScriptMgr.h" +#include "ScriptLoader.h" #include "OutdoorPvP/OutdoorPvPMgr.h" #include "BattlegroundMgr.h" #include "TCSoap.h" @@ -42,7 +41,6 @@ #include "GitRevision.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" -#include "BattlenetServerManager.h" #include "Realm/Realm.h" #include "DatabaseLoader.h" #include "AppenderDB.h" @@ -80,12 +78,6 @@ uint32 _worldLoopCounter(0); uint32 _lastChangeMsTime(0); uint32 _maxCoreStuckTimeInMs(0); -WorldDatabaseWorkerPool WorldDatabase; ///< Accessor to the world database -CharacterDatabaseWorkerPool CharacterDatabase; ///< Accessor to the character database -HotfixDatabaseWorkerPool HotfixDatabase; ///< Accessor to the hotfix database -LoginDatabaseWorkerPool LoginDatabase; ///< Accessor to the realm/login database -Realm realm; - void SignalHandler(const boost::system::error_code& error, int signalNumber); void FreezeDetectorHandler(const boost::system::error_code& error); AsyncAcceptor* StartRaSocketAcceptor(boost::asio::io_service& ioService); @@ -199,6 +191,7 @@ extern int main(int argc, char** argv) LoadRealmInfo(); // Initialize the World + sScriptMgr->SetScriptLoader(AddScripts); sWorld->SetInitialWorldSettings(); // Launch CliRunnable thread @@ -244,10 +237,6 @@ extern int main(int argc, char** argv) TC_LOG_INFO("server.worldserver", "Starting up anti-freeze thread (%u seconds max stuck time)...", coreStuckTime); } - sIpcContext->Initialize(); - - sBattlenetServer.InitializeConnection(); - TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon) ready...", GitRevision::GetFullVersion()); sScriptMgr->OnStartup(); @@ -261,10 +250,6 @@ extern int main(int argc, char** argv) sScriptMgr->OnShutdown(); - sIpcContext->Close(); - - sBattlenetServer.CloseConnection(); - sWorld->KickAll(); // save and kick all players sWorld->UpdateSessions(1); // real players unload required UpdateSessions call diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index b6787e25e19..3e65a8589e4 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -589,6 +589,9 @@ StrictPetNames = 0 # 6 - (Spanish) # 7 - (Spanish Mexico) # 8 - (Russian) +# 9 - (none) +# 10 - (ptBR) +# 11 - (itIT) DBC.Locale = 0 @@ -3245,6 +3248,46 @@ AuctionHouseBot.forceIncludeItems = "" AuctionHouseBot.forceExcludeItems = "" # +# AuctionHouseBot.Class.RandomStackRatio.* +# Description: Used to determine how often a stack of the class will be single or randomly-size stacked when posted +# Value needs to be between 0 and 100, no decimal. Anything higher than 100 will be treated as 100 +# Examples: 100 = stacks will always be random in size +# 50 = half the time the stacks are random, the other half being single stack +# 0 = stacks will always single size +# Default: Consumable: 20 (20% random stack size, 80% single stack size) +# Container: 0 (100% single stack size) +# Weapon: 0 (100% single stack size) +# Gem: 20 (20% random stack size, 80% single stack size) +# Armor: 0 (100% single stack size) +# Reagent: 100 (100% random stack size) +# Projectile: 100 (100% random stack size) +# TradeGood: 50 (50% random stack size, 50% single stack size) +# Generic: 100 (100% random stack size) +# Recipe: 0 (100% single stack size) +# Quiver: 0 (100% single stack size) +# Quest: 100 (100% random stack size) +# Key: 100 (100% random stack size) +# Misc: 100 (100% random stack size) +# Glyph: 0 (100% single stack size) +# + +AuctionHouseBot.Class.RandomStackRatio.Consumable = 20 +AuctionHouseBot.Class.RandomStackRatio.Container = 0 +AuctionHouseBot.Class.RandomStackRatio.Weapon = 0 +AuctionHouseBot.Class.RandomStackRatio.Gem = 20 +AuctionHouseBot.Class.RandomStackRatio.Armor = 0 +AuctionHouseBot.Class.RandomStackRatio.Reagent = 100 +AuctionHouseBot.Class.RandomStackRatio.Projectile = 100 +AuctionHouseBot.Class.RandomStackRatio.TradeGood = 50 +AuctionHouseBot.Class.RandomStackRatio.Generic = 100 +AuctionHouseBot.Class.RandomStackRatio.Recipe = 0 +AuctionHouseBot.Class.RandomStackRatio.Quiver = 0 +AuctionHouseBot.Class.RandomStackRatio.Quest = 100 +AuctionHouseBot.Class.RandomStackRatio.Key = 100 +AuctionHouseBot.Class.RandomStackRatio.Misc = 100 +AuctionHouseBot.Class.RandomStackRatio.Glyph = 0 + +# ################################################################################################### ################################################################################################### @@ -3623,24 +3666,3 @@ PacketSpoof.BanDuration = 86400 # ################################################################################################### - -################################################################################################### -# IPC SETTINGS -# -# BnetServer.Address -# Description: Determines IP address of battle.net server to connect to. -# Default: 127.0.0.1 -# - -BnetServer.Address = 127.0.0.1 - -# -# BnetServer.Port -# Description: Determines port to use when connecting to battle.net server. -# Default: 1118 -# - -BnetServer.Port = 1118 - -# -################################################################################################### diff --git a/src/tools/connection_patcher/CMakeLists.txt b/src/tools/connection_patcher/CMakeLists.txt index 781547f628b..3fad34fabb1 100644 --- a/src/tools/connection_patcher/CMakeLists.txt +++ b/src/tools/connection_patcher/CMakeLists.txt @@ -8,15 +8,6 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -include_directories( - ${CMAKE_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/common/Cryptography - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${OPENSSL_INCLUDE_DIR} -) - set(HEADER_FILES Helper.hpp Patcher.hpp @@ -42,10 +33,8 @@ if (MSVC) endif () target_link_libraries(connection_patcher - common - ${OPENSSL_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${Boost_LIBRARIES} + PUBLIC + common ) if (UNIX) diff --git a/src/tools/connection_patcher/Program.cpp b/src/tools/connection_patcher/Program.cpp index 4f1baccbd95..209815db60a 100644 --- a/src/tools/connection_patcher/Program.cpp +++ b/src/tools/connection_patcher/Program.cpp @@ -96,7 +96,7 @@ namespace Connection_Patcher } template<typename PATCH, typename PATTERN> - void do_patches(Patcher* patcher, boost::filesystem::path output, bool patchVersionPath, uint32_t buildNumber) + void do_patches(Patcher* patcher, boost::filesystem::path output, uint32_t buildNumber) { std::cout << "patching Portal\n"; // '.logon.battle.net' -> '' to allow for set portal 'host' @@ -117,18 +117,16 @@ namespace Connection_Patcher // Creep::Instance::LoadModule() to allow for unsigned auth module patcher->Patch(PATCH::Signature(), PATTERN::Signature()); - if (patchVersionPath) - { - std::cout << "patching Versions\n"; - // sever the connection to blizzard's versions file to stop it from updating and replace with custom version - // hardcode %s.patch.battle.net:1119/%s/versions to trinity6.github.io/%s/%s/build/versi - std::string verPatch(Patches::Common::VersionsFile()); - std::string buildPattern = "build"; - - boost::algorithm::replace_all(verPatch, buildPattern, std::to_string(buildNumber)); - std::vector<unsigned char> verVec(verPatch.begin(), verPatch.end()); - patcher->Patch(verVec, Patterns::Common::VersionsFile()); - } + std::cout << "patching Versions\n"; + // sever the connection to blizzard's versions file to stop it from updating and replace with custom version + // this is good practice with or without the retail version, just to stop the exe from auto-patching randomly + // hardcode %s.patch.battle.net:1119/%s/versions to trinity6.github.io/%s/%s/build/versi + std::string verPatch(Patches::Common::VersionsFile()); + std::string buildPattern = "build"; + + boost::algorithm::replace_all(verPatch, buildPattern, std::to_string(buildNumber)); + std::vector<unsigned char> verVec(verPatch.begin(), verPatch.end()); + patcher->Patch(verVec, Patterns::Common::VersionsFile()); patcher->Finish(output); @@ -142,7 +140,6 @@ namespace Connection_Patcher all.add_options() ("help,h", "print usage message") ("path", po::value<std::string>()->required(), "Path to the Wow.exe") - ("extra,e", po::value<uint32_t>()->implicit_value(0), "Enable patching of versions file download path. Version can be specified explicitly.") ("modulePath,m", po::value<std::string>(), "Path to the Battle.net module download destination.") ; @@ -176,9 +173,6 @@ int main(int argc, char** argv) try { - bool patchVersionPath = false; - int wowBuild = 0; - auto vm = GetConsoleArguments(argc, argv); // exit if help is enabled @@ -211,19 +205,14 @@ int main(int argc, char** argv) Patcher patcher(binary_path); - if (vm.count("extra")) - { - patchVersionPath = true; - wowBuild = vm["extra"].as<uint32_t>(); - - if (wowBuild == 0) - wowBuild = Helper::GetBuildNumber(patcher.GetBinary()); + // always set wowBuild to current build of the .exe files + int wowBuild = Helper::GetBuildNumber(patcher.GetBinary()); - if (wowBuild == 0 || wowBuild < 10000 || wowBuild > 65535) // Build number has to be exactly 5 characters long - throw std::runtime_error("Could not retrieve build number or it was out of range. Build: " + std::to_string(wowBuild)); + // define logical limits in case the exe was tinkered with and the build number was changed + if (wowBuild == 0 || wowBuild < 10000 || wowBuild > 65535) // Build number has to be exactly 5 characters long + throw std::runtime_error("Build number was out of range. Build: " + std::to_string(wowBuild)); - std::cout << "Determined build number: " << std::to_string(wowBuild) << std::endl; - } + std::cout << "Determined build number: " << std::to_string(wowBuild) << std::endl; switch (patcher.GetType()) { @@ -232,7 +221,7 @@ int main(int argc, char** argv) boost::algorithm::replace_all(renamed_binary_path, ".exe", "_Patched.exe"); do_patches<Patches::Windows::x86, Patterns::Windows::x86> - (&patcher, renamed_binary_path, patchVersionPath, wowBuild); + (&patcher, renamed_binary_path, wowBuild); do_module<Patches::Windows::x86, Patterns::Windows::x86> ( "8f52906a2c85b416a595702251570f96d3522f39237603115f2f1ab24962043c.auth" @@ -245,7 +234,7 @@ int main(int argc, char** argv) boost::algorithm::replace_all(renamed_binary_path, ".exe", "_Patched.exe"); do_patches<Patches::Windows::x64, Patterns::Windows::x64> - (&patcher, renamed_binary_path, patchVersionPath, wowBuild); + (&patcher, renamed_binary_path, wowBuild); do_module<Patches::Windows::x64, Patterns::Windows::x64> ( "0a3afee2cade3a0e8b458c4b4660104cac7fc50e2ca9bef0d708942e77f15c1d.auth" @@ -262,7 +251,7 @@ int main(int argc, char** argv) ); do_patches<Patches::Mac::x64, Patterns::Mac::x64> - (&patcher, renamed_binary_path, patchVersionPath, wowBuild); + (&patcher, renamed_binary_path, wowBuild); { namespace fs = boost::filesystem; diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index 32fccaa2038..656bee3d5a0 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -9,34 +9,38 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources *.cpp *.h) - -include_directories ( - ${CMAKE_SOURCE_DIR}/dep/CascLib/src - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared +CollectSourceFiles( ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/loadlib -) - -include_directories(${include_Dirs}) + PRIVATE_SOURCES) add_executable(mapextractor - ${sources} + ${PRIVATE_SOURCES} ) +target_include_directories(mapextractor + PUBLIC + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/loadlib) + target_link_libraries(mapextractor - casc - common - format - ${BZIP2_LIBRARIES} - ${ZLIB_LIBRARIES} - ${Boost_LIBRARIES} -) + PUBLIC + common + casc) + +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES) + +target_include_directories(mapextractor + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_dependencies(mapextractor casc) +set_target_properties(mapextractor + PROPERTIES + FOLDER + "tools") if( UNIX ) install(TARGETS mapextractor DESTINATION bin) diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt index adc3410aa6e..7e34fea6acc 100644 --- a/src/tools/mmaps_generator/CMakeLists.txt +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -8,43 +8,34 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE mmap_gen_sources *.cpp *.h) +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES) -set(mmap_gen_Includes - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/dep/bzip2 - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/common/Collision - ${CMAKE_SOURCE_DIR}/src/common/Collision/Management - ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps - ${CMAKE_SOURCE_DIR}/src/common/Collision/Models -) +add_executable(mmaps_generator ${PRIVATE_SOURCES}) -include_directories(${mmap_gen_Includes}) +target_link_libraries(mmaps_generator + PUBLIC + common + Recast + Detour + zlib + bzip2) -add_executable(mmaps_generator ${mmap_gen_sources}) +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES) -target_link_libraries(mmaps_generator - common - g3dlib - Recast - Detour - format - ${BZIP2_LIBRARIES} - ${ZLIB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${Boost_LIBRARIES} -) +target_include_directories(mmaps_generator + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +set_target_properties(mmaps_generator + PROPERTIES + FOLDER + "tools") if( UNIX ) install(TARGETS mmaps_generator DESTINATION bin) diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt index b2b17f49289..28e8b374143 100644 --- a/src/tools/vmap4_assembler/CMakeLists.txt +++ b/src/tools/vmap4_assembler/CMakeLists.txt @@ -9,24 +9,17 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -include_directories( - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Collision - ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps - ${CMAKE_SOURCE_DIR}/src/common/Collision/Models - ${ZLIB_INCLUDE_DIR} -) - add_executable(vmap4assembler VMapAssembler.cpp) -add_dependencies(vmap4assembler casc) target_link_libraries(vmap4assembler common - g3dlib - ${ZLIB_LIBRARIES} -) + casc + zlib) + +set_target_properties(vmap4assembler + PROPERTIES + FOLDER + "tools") if( UNIX ) install(TARGETS vmap4assembler DESTINATION bin) diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index 18d770af707..feaf7ddb215 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -9,25 +9,32 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources *.cpp *.h) +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES) -include_directories( - ${CMAKE_SOURCE_DIR}/src/common - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/dep/CascLib/src -) - -add_executable(vmap4extractor ${sources}) +add_executable(vmap4extractor ${PRIVATE_SOURCES}) target_link_libraries(vmap4extractor - casc - common - ${BZIP2_LIBRARIES} - ${ZLIB_LIBRARIES} - ${Boost_LIBRARIES} -) + PUBLIC + common + casc + bzip2) + +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES) + +target_include_directories(vmap4extractor + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_dependencies(vmap4extractor casc) +set_target_properties(vmap4extractor + PROPERTIES + FOLDER + "tools") if( UNIX ) install(TARGETS vmap4extractor DESTINATION bin) |