Core/Misc: backported most boost changes from master branch
This commit is contained in:
1 parent
66f3e78248
commit
0927c5af40
167 files changed
+1605
-484
No files matched your search
@@ -120,6 +120,12 @@ if(PERFORMANCE_PROFILING)
|
||||
add_definitions(-DPERFORMANCE_PROFILING)
|
||||
endif()
|
||||
|
||||
if(WITH_BOOST_STACKTRACE)
|
||||
if (BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE)
|
||||
add_definitions(-DBOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE="${BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
message("")
|
||||
message(" *** WITH_DYNAMIC_LINKING - INFO!")
|
||||
|
||||
@@ -32,6 +32,7 @@ if(SERVERS)
|
||||
add_subdirectory(zmqpp)
|
||||
add_subdirectory(rapidjson)
|
||||
add_subdirectory(efsw)
|
||||
add_subdirectory(short_alloc)
|
||||
endif()
|
||||
|
||||
if(TOOLS)
|
||||
|
||||
+60
-42
@@ -8,13 +8,25 @@
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
set(BOOST_SEARCH_HINTS)
|
||||
if(WIN32)
|
||||
if(DEFINED ENV{BOOST_ROOT})
|
||||
set(BOOST_ROOT $ENV{BOOST_ROOT})
|
||||
list(APPEND BOOST_LIBRARYDIR
|
||||
${BOOST_ROOT}/lib${PLATFORM}-msvc-14.2 )
|
||||
elseif(NOT DEFINED Boost_DIR AND NOT DEFINED BOOST_ROOT AND NOT DEFINED BOOSTROOT)
|
||||
message(FATAL_ERROR "No BOOST_ROOT environment variable could be found! Please make sure it is set and the points to your Boost installation.")
|
||||
endif()
|
||||
if(DEFINED BOOST_ROOT AND MSVC)
|
||||
# insert a dot (.) character before last digit of MSVC_TOOLSET_VERSION
|
||||
# turn 143 into 14.3
|
||||
string(LENGTH "${MSVC_TOOLSET_VERSION}" _BOOST_MSVC_TOOLSET_VERSION_LENGTH)
|
||||
math(EXPR _BOOST_MSVC_TOOLSET_VERSION_LENGTH "${_BOOST_MSVC_TOOLSET_VERSION_LENGTH} - 1" OUTPUT_FORMAT DECIMAL)
|
||||
string(SUBSTRING "${MSVC_TOOLSET_VERSION}" 0 ${_BOOST_MSVC_TOOLSET_VERSION_LENGTH} _BOOST_MSVC_TOOLSET_VERSION_MAJOR)
|
||||
string(SUBSTRING "${MSVC_TOOLSET_VERSION}" ${_BOOST_MSVC_TOOLSET_VERSION_LENGTH} -1 _BOOST_MSVC_TOOLSET_VERSION_MINOR)
|
||||
|
||||
file(TO_CMAKE_PATH "${BOOST_ROOT}" BOOST_ROOT)
|
||||
set(BOOST_SEARCH_HINTS "${BOOST_ROOT}/lib${PLATFORM}-msvc-${_BOOST_MSVC_TOOLSET_VERSION_MAJOR}.${_BOOST_MSVC_TOOLSET_VERSION_MINOR}/cmake")
|
||||
|
||||
unset(_BOOST_MSVC_TOOLSET_VERSION_LENGTH)
|
||||
unset(_BOOST_MSVC_TOOLSET_VERSION_MAJOR)
|
||||
unset(_BOOST_MSVC_TOOLSET_VERSION_MINOR)
|
||||
endif()
|
||||
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
@@ -22,42 +34,32 @@ if(WIN32)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
endif()
|
||||
|
||||
set(Boost_NO_WARN_NEW_VERSIONS ON)
|
||||
|
||||
include (CheckCXXSourceCompiles)
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <regex>
|
||||
int main() { std::wregex r(L\".*\"); }"
|
||||
STD_HAS_WORKING_WREGEX)
|
||||
|
||||
if (WIN32)
|
||||
# On windows the requirements are higher according to the wiki.
|
||||
set(BOOST_REQUIRED_VERSION 1.78)
|
||||
else()
|
||||
set(BOOST_REQUIRED_VERSION 1.71)
|
||||
set(BOOST_REQUIRED_VERSION 1.74)
|
||||
endif()
|
||||
|
||||
if (STD_HAS_WORKING_WREGEX)
|
||||
find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem thread program_options iostreams)
|
||||
else()
|
||||
find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem thread program_options iostreams regex)
|
||||
find_package(Boost ${BOOST_REQUIRED_VERSION}
|
||||
REQUIRED
|
||||
COMPONENTS
|
||||
system
|
||||
filesystem
|
||||
thread
|
||||
program_options
|
||||
regex
|
||||
locale
|
||||
CONFIG
|
||||
HINTS
|
||||
${BOOST_SEARCH_HINTS})
|
||||
|
||||
if(NOT Boost_FOUND)
|
||||
if(NOT DEFINED ENV{BOOST_ROOT} AND NOT DEFINED Boost_DIR AND NOT DEFINED BOOST_ROOT AND NOT DEFINED BOOSTROOT)
|
||||
message(FATAL_ERROR "No BOOST_ROOT environment variable could be found! Please make sure it is set and the points to your Boost installation.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Find if Boost was compiled in C++03 mode because it requires -DBOOST_NO_CXX11_SCOPED_ENUMS
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_IOSTREAMS_LIBRARY})
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
|
||||
check_cxx_source_compiles("
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
int main() { boost::filesystem::copy_file(boost::filesystem::path(), boost::filesystem::path()); }"
|
||||
boost_filesystem_copy_links_without_NO_SCOPED_ENUM)
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
add_library(boost INTERFACE)
|
||||
|
||||
target_link_libraries(boost
|
||||
@@ -70,19 +72,35 @@ target_include_directories(boost
|
||||
|
||||
target_compile_definitions(boost
|
||||
INTERFACE
|
||||
-DBOOST_ALL_NO_LIB
|
||||
-DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE
|
||||
-DBOOST_ASIO_NO_DEPRECATED
|
||||
-DBOOST_BIND_NO_PLACEHOLDERS)
|
||||
BOOST_ALL_NO_LIB
|
||||
BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE
|
||||
BOOST_ASIO_NO_DEPRECATED
|
||||
BOOST_BIND_NO_PLACEHOLDERS
|
||||
BOOST_SYSTEM_USE_UTF8)
|
||||
|
||||
if (WITH_BOOST_STACKTRACE AND NOT WIN32)
|
||||
message(STATUS "libbacktrace will be linked")
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
if (BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE)
|
||||
check_include_file("${BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE}" HAS_BACKTRACE)
|
||||
target_compile_definitions(boost
|
||||
INTERFACE
|
||||
BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE=${BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE})
|
||||
else()
|
||||
check_include_file("backtrace.h" HAS_BACKTRACE)
|
||||
endif()
|
||||
|
||||
if (NOT HAS_BACKTRACE)
|
||||
message(FATAL_ERROR "Required header 'backtrace.h' not found. If building with a compiler other than GCC, please specify the full path in the CMake option BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE.")
|
||||
endif()
|
||||
|
||||
if (NOT boost_filesystem_copy_links_without_NO_SCOPED_ENUM)
|
||||
target_compile_definitions(boost
|
||||
INTERFACE
|
||||
-DBOOST_NO_CXX11_SCOPED_ENUMS)
|
||||
endif()
|
||||
BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
|
||||
if (NOT STD_HAS_WORKING_WREGEX)
|
||||
target_compile_definitions(boost
|
||||
target_link_libraries(boost
|
||||
INTERFACE
|
||||
-DTC_HAS_BROKEN_WSTRING_REGEX)
|
||||
backtrace)
|
||||
endif()
|
||||
@@ -0,0 +1,15 @@
|
||||
# This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
#
|
||||
# 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(short_alloc INTERFACE)
|
||||
|
||||
target_include_directories(short_alloc
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -0,0 +1,162 @@
|
||||
#ifndef SHORT_ALLOC_H
|
||||
#define SHORT_ALLOC_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Howard Hinnant
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace short_alloc
|
||||
{
|
||||
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
||||
class arena
|
||||
{
|
||||
alignas(alignment) char buf_[N];
|
||||
char* ptr_;
|
||||
|
||||
public:
|
||||
~arena() {ptr_ = nullptr;}
|
||||
arena() noexcept : ptr_(buf_) {}
|
||||
arena(const arena&) = delete;
|
||||
arena& operator=(const arena&) = delete;
|
||||
|
||||
template <std::size_t ReqAlign> char* allocate(std::size_t n);
|
||||
void deallocate(char* p, std::size_t n) noexcept;
|
||||
|
||||
static constexpr std::size_t size() noexcept {return N;}
|
||||
std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
|
||||
void reset() noexcept {ptr_ = buf_;}
|
||||
|
||||
private:
|
||||
static
|
||||
std::size_t
|
||||
align_up(std::size_t n) noexcept
|
||||
{return (n + (alignment-1)) & ~(alignment-1);}
|
||||
|
||||
bool
|
||||
pointer_in_buffer(char* p) noexcept
|
||||
{
|
||||
return std::uintptr_t(buf_) <= std::uintptr_t(p) &&
|
||||
std::uintptr_t(p) <= std::uintptr_t(buf_) + N;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N, std::size_t alignment>
|
||||
template <std::size_t ReqAlign>
|
||||
char*
|
||||
arena<N, alignment>::allocate(std::size_t n)
|
||||
{
|
||||
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
|
||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||
auto const aligned_n = align_up(n);
|
||||
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
|
||||
{
|
||||
char* r = ptr_;
|
||||
ptr_ += aligned_n;
|
||||
return r;
|
||||
}
|
||||
|
||||
static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
|
||||
"alignment that is larger than alignof(std::max_align_t), and "
|
||||
"cannot be guaranteed by normal operator new");
|
||||
return static_cast<char*>(::operator new(n));
|
||||
}
|
||||
|
||||
template <std::size_t N, std::size_t alignment>
|
||||
void
|
||||
arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
|
||||
{
|
||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||
if (pointer_in_buffer(p))
|
||||
{
|
||||
n = align_up(n);
|
||||
if (p + n == ptr_)
|
||||
ptr_ = p;
|
||||
}
|
||||
else
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||
class short_alloc
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
static auto constexpr alignment = Align;
|
||||
static auto constexpr size = N;
|
||||
using arena_type = arena<size, alignment>;
|
||||
|
||||
private:
|
||||
arena_type& a_;
|
||||
|
||||
public:
|
||||
short_alloc(const short_alloc&) = default;
|
||||
short_alloc& operator=(const short_alloc&) = delete;
|
||||
|
||||
short_alloc(arena_type& a) noexcept : a_(a)
|
||||
{
|
||||
static_assert(size % alignment == 0,
|
||||
"size N needs to be a multiple of alignment Align");
|
||||
}
|
||||
template <class U>
|
||||
short_alloc(const short_alloc<U, N, alignment>& a) noexcept
|
||||
: a_(a.a_) {}
|
||||
|
||||
template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
|
||||
|
||||
T* allocate(std::size_t n)
|
||||
{
|
||||
return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
|
||||
}
|
||||
void deallocate(T* p, std::size_t n) noexcept
|
||||
{
|
||||
a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
|
||||
}
|
||||
|
||||
template <class T1, std::size_t N1, std::size_t A1,
|
||||
class U, std::size_t M, std::size_t A2>
|
||||
friend
|
||||
bool
|
||||
operator==(const short_alloc<T1, N1, A1>& x, const short_alloc<U, M, A2>& y) noexcept;
|
||||
|
||||
template <class U, std::size_t M, std::size_t A> friend class short_alloc;
|
||||
};
|
||||
|
||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline
|
||||
bool
|
||||
operator==(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||
{
|
||||
return N == M && A1 == A2 && &x.a_ == &y.a_;
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline
|
||||
bool
|
||||
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
}
|
||||
#endif // SHORT_ALLOC_H
|
||||
@@ -18,18 +18,17 @@
|
||||
#ifndef DeadlineTimer_h__
|
||||
#define DeadlineTimer_h__
|
||||
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include "Duration.h"
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
namespace Trinity
|
||||
namespace Trinity::Asio
|
||||
{
|
||||
namespace Asio
|
||||
class DeadlineTimer : public boost::asio::basic_waitable_timer<std::chrono::steady_clock, boost::asio::wait_traits<std::chrono::steady_clock>, boost::asio::io_context::executor_type>
|
||||
{
|
||||
class DeadlineTimer : public boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::io_context::executor_type>
|
||||
{
|
||||
public:
|
||||
using basic_deadline_timer::basic_deadline_timer;
|
||||
};
|
||||
}
|
||||
public:
|
||||
using basic_waitable_timer::basic_waitable_timer;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DeadlineTimer_h__
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "IoContext.h"
|
||||
#include "Optional.h"
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
namespace Trinity
|
||||
|
||||
@@ -71,7 +71,8 @@ target_link_libraries(common
|
||||
openssl
|
||||
valgrind
|
||||
threads
|
||||
jemalloc)
|
||||
jemalloc
|
||||
short_alloc)
|
||||
|
||||
add_dependencies(common revision_data.h)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include "Util.h"
|
||||
#include <boost/filesystem/directory.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 TRINITYCORE_FLAT_SET_H
|
||||
#define TRINITYCORE_FLAT_SET_H
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace Trinity::Containers
|
||||
{
|
||||
template <class Key, class Compare = std::less<Key>, class KeyContainer = std::vector<Key>>
|
||||
class FlatSet
|
||||
{
|
||||
public:
|
||||
using iterator = typename KeyContainer::iterator;
|
||||
using const_iterator = typename KeyContainer::const_iterator;
|
||||
|
||||
bool empty() const { return _storage.empty(); }
|
||||
auto size() const { return _storage.size(); }
|
||||
|
||||
auto begin() { return _storage.begin(); }
|
||||
auto begin() const { return _storage.begin(); }
|
||||
|
||||
auto end() { return _storage.end(); }
|
||||
auto end() const { return _storage.end(); }
|
||||
|
||||
auto find(Key const& value) const
|
||||
{
|
||||
auto end = this->end();
|
||||
auto itr = std::lower_bound(this->begin(), end, value, Compare());
|
||||
if (itr != end && Compare()(value, *itr))
|
||||
itr = end;
|
||||
|
||||
return itr;
|
||||
}
|
||||
|
||||
auto find(Key const& value)
|
||||
{
|
||||
auto end = this->end();
|
||||
auto itr = std::lower_bound(this->begin(), end, value, Compare());
|
||||
if (itr != end && Compare()(value, *itr))
|
||||
itr = end;
|
||||
|
||||
return itr;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
Key newElement(std::forward<Args>(args)...);
|
||||
auto end = this->end();
|
||||
auto itr = std::lower_bound(this->begin(), end, newElement, Compare());
|
||||
if (itr != end && !Compare()(newElement, *itr))
|
||||
return { itr, false };
|
||||
|
||||
return { _storage.emplace(itr, std::move(newElement)), true };
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(Key const& key) { return emplace(key); }
|
||||
|
||||
std::size_t erase(Key const& key)
|
||||
{
|
||||
auto itr = this->find(key);
|
||||
if (itr == this->end())
|
||||
return 0;
|
||||
|
||||
this->erase(itr);
|
||||
return 1;
|
||||
}
|
||||
auto erase(const_iterator itr) { return _storage.erase(itr); }
|
||||
|
||||
void clear() { _storage.clear(); }
|
||||
|
||||
void shrink_to_fit() { _storage.shrink_to_fit(); }
|
||||
|
||||
friend bool operator==(FlatSet const& left, FlatSet const& right)
|
||||
{
|
||||
return left._storage == right._storage;
|
||||
}
|
||||
|
||||
friend bool operator!=(FlatSet const& left, FlatSet const& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
private:
|
||||
KeyContainer _storage;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TRINITYCORE_FLAT_SET_H
|
||||
@@ -20,13 +20,13 @@
|
||||
#include "AppenderFile.h"
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "Duration.h"
|
||||
#include "Errors.h"
|
||||
#include "Logger.h"
|
||||
#include "LogMessage.h"
|
||||
#include "LogOperation.h"
|
||||
#include "Strand.h"
|
||||
#include "Util.h"
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
Log::Log() : AppenderId(0), lowestLogLevel(LOG_LEVEL_FATAL), _ioContext(nullptr), _strand(nullptr)
|
||||
|
||||
@@ -200,7 +200,7 @@ void Metric::ScheduleSend()
|
||||
{
|
||||
if (_enabled)
|
||||
{
|
||||
_batchTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
|
||||
_batchTimer->expires_after(std::chrono::seconds(_updateInterval));
|
||||
_batchTimer->async_wait(std::bind(&Metric::SendBatch, this));
|
||||
}
|
||||
else
|
||||
@@ -230,7 +230,7 @@ void Metric::ScheduleOverallStatusLog()
|
||||
{
|
||||
if (_enabled)
|
||||
{
|
||||
_overallStatusTimer->expires_from_now(boost::posix_time::seconds(_overallStatusTimerInterval));
|
||||
_overallStatusTimer->expires_after(std::chrono::seconds(_overallStatusTimerInterval));
|
||||
_overallStatusTimer->async_wait([this](const boost::system::error_code&)
|
||||
{
|
||||
_overallStatusTimerTriggered = true;
|
||||
|
||||
@@ -23,14 +23,15 @@
|
||||
*/
|
||||
|
||||
#include "Define.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace ByteConverter
|
||||
{
|
||||
template<size_t T>
|
||||
inline void convert(char *val)
|
||||
{
|
||||
std::swap(*val, *(val + T - 1));
|
||||
char tmp = *val;
|
||||
*val = *(val + T - 1);
|
||||
*(val + T - 1) = tmp;
|
||||
convert<T - 2>(val + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "Define.h"
|
||||
#include "Duration.h"
|
||||
#include "Random.h"
|
||||
#include "advstd.h"
|
||||
#include <map>
|
||||
|
||||
class EventProcessor;
|
||||
@@ -88,7 +87,7 @@ private:
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using is_lambda_event = std::enable_if_t<!advstd::is_base_of_v<BasicEvent, std::remove_pointer_t<advstd::remove_cvref_t<T>>>>;
|
||||
using is_lambda_event = std::enable_if_t<!std::is_base_of_v<BasicEvent, std::remove_pointer_t<std::remove_cvref_t<T>>>>;
|
||||
|
||||
class TC_COMMON_API EventProcessor
|
||||
{
|
||||
|
||||
@@ -27,39 +27,39 @@ namespace Trinity
|
||||
*
|
||||
* @brief Utility class to enable range for loop syntax for multimap.equal_range uses
|
||||
*/
|
||||
template<class iterator>
|
||||
template<class iterator, class end_iterator = iterator>
|
||||
class IteratorPair
|
||||
{
|
||||
public:
|
||||
constexpr IteratorPair() : _iterators() { }
|
||||
constexpr IteratorPair(iterator first, iterator second) : _iterators(first, second) { }
|
||||
constexpr IteratorPair(std::pair<iterator, iterator> iterators) : _iterators(iterators) { }
|
||||
constexpr IteratorPair(iterator first, end_iterator second) : _iterators(first, second) { }
|
||||
constexpr IteratorPair(std::pair<iterator, end_iterator> iterators) : _iterators(iterators) { }
|
||||
|
||||
constexpr iterator begin() const { return _iterators.first; }
|
||||
constexpr iterator end() const { return _iterators.second; }
|
||||
constexpr end_iterator end() const { return _iterators.second; }
|
||||
|
||||
private:
|
||||
std::pair<iterator, iterator> _iterators;
|
||||
std::pair<iterator, end_iterator> _iterators;
|
||||
};
|
||||
|
||||
namespace Containers
|
||||
{
|
||||
template<typename iterator>
|
||||
constexpr Trinity::IteratorPair<iterator> MakeIteratorPair(iterator first, iterator second)
|
||||
template<typename iterator, class end_iterator = iterator>
|
||||
constexpr IteratorPair<iterator, end_iterator> MakeIteratorPair(iterator first, end_iterator second)
|
||||
{
|
||||
return { first, second };
|
||||
}
|
||||
|
||||
template<typename iterator>
|
||||
constexpr Trinity::IteratorPair<iterator> MakeIteratorPair(std::pair<iterator, iterator> iterators)
|
||||
template<typename iterator, class end_iterator = iterator>
|
||||
constexpr IteratorPair<iterator, end_iterator> MakeIteratorPair(std::pair<iterator, end_iterator> iterators)
|
||||
{
|
||||
return iterators;
|
||||
}
|
||||
|
||||
template<class M>
|
||||
inline auto MapEqualRange(M& map, typename M::key_type const& key) -> IteratorPair<decltype(map.begin())>
|
||||
auto MapEqualRange(M& map, typename M::key_type const& key)
|
||||
{
|
||||
return { map.equal_range(key) };
|
||||
return MakeIteratorPair(map.equal_range(key));
|
||||
}
|
||||
}
|
||||
//! namespace Containers
|
||||
|
||||
@@ -18,32 +18,157 @@
|
||||
#ifndef TRINITY_MEMORY_H
|
||||
#define TRINITY_MEMORY_H
|
||||
|
||||
#include "CompilerDefs.h"
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
|
||||
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
#endif
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Impl
|
||||
{
|
||||
template<typename T, typename Del>
|
||||
struct unique_ptr_deleter
|
||||
struct stateful_unique_ptr_deleter
|
||||
{
|
||||
using pointer = T;
|
||||
unique_ptr_deleter(Del deleter) : _deleter(std::move(deleter)) { }
|
||||
|
||||
void operator()(pointer ptr) const { _deleter(ptr); }
|
||||
explicit(false) stateful_unique_ptr_deleter(Del deleter) : _deleter(std::move(deleter)) { }
|
||||
void operator()(pointer ptr) const { (void)_deleter(ptr); }
|
||||
|
||||
private:
|
||||
Del _deleter;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename Del>
|
||||
auto make_unique_ptr_with_deleter(T ptr, Del&& deleter)
|
||||
template<typename T, auto Del>
|
||||
struct stateless_unique_ptr_deleter
|
||||
{
|
||||
using Deleter_t = Impl::unique_ptr_deleter<T, Del>;
|
||||
using pointer = T;
|
||||
void operator()(pointer ptr) const
|
||||
{
|
||||
if constexpr (std::is_member_function_pointer_v<decltype(Del)>)
|
||||
(void)(ptr->*Del)();
|
||||
else
|
||||
(void)Del(ptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return std::unique_ptr<T, Deleter_t>(ptr, Deleter_t(std::forward<Del>(deleter)));
|
||||
/**
|
||||
* Convenience function to construct type aliases for std::unique_ptr stateful deleters (such as lambda with captures)
|
||||
* @tparam Ptr Type of the pointer
|
||||
* @tparam Del Type of object freeing function (deduced from argument)
|
||||
* @param deleter Object deleter
|
||||
*
|
||||
* Example use
|
||||
* @code
|
||||
* void FreeV1(Resource*);
|
||||
* void FreeV2(Resource*);
|
||||
*
|
||||
* using ResourceDeleter = decltype(Trinity::unique_ptr_deleter<Resource*>(&FreeV1));
|
||||
*
|
||||
* std::unique_ptr<Resource, ResourceDeleter> resource = Trinity::make_unique_ptr_with_deleter(GetResourceV1(), &FreeV1);
|
||||
* // do stuff ...
|
||||
* // ... later get new resource
|
||||
* resource = Trinity::make_unique_ptr_with_deleter(GetResourceV2(), &FreeV2);
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Ptr, typename Del> requires std::invocable<Del, Ptr> && std::is_pointer_v<Ptr>
|
||||
Impl::stateful_unique_ptr_deleter<Ptr, Del> unique_ptr_deleter(Del deleter)
|
||||
{
|
||||
return Impl::stateful_unique_ptr_deleter<Ptr, Del>(std::move(deleter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to construct type aliases for std::unique_ptr stateful deleters (such as lambda with captures)
|
||||
*
|
||||
* Main use is for forming struct/class members without the call to make_unique_ptr_with_deleter
|
||||
* @tparam Ptr Type of the pointer
|
||||
* @tparam Del The freeing function. This can be either a free function pointer that accepts T* as argument, pointer to a member function of T that accepts no arguments or a lambda with no captures
|
||||
*
|
||||
* Example use
|
||||
* @code
|
||||
* using FileDeleter = decltype(Trinity::unique_ptr_deleter<FILE*, &::fclose>());
|
||||
*
|
||||
* class Resource
|
||||
* {
|
||||
* std::unique_ptr<FILE, FileDeleter> File;
|
||||
* };
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Ptr, auto Del> requires std::invocable<decltype(Del), Ptr> && std::is_pointer_v<Ptr>
|
||||
Impl::stateless_unique_ptr_deleter<Ptr, Del> unique_ptr_deleter()
|
||||
{
|
||||
return Impl::stateless_unique_ptr_deleter<Ptr, Del>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to construct a std::unique_ptr object with custom stateful deleter (such as lambda with captures)
|
||||
* @tparam Ptr Type of the pointer
|
||||
* @tparam T Type of the pointed-to object (defaults to std::remove_pointer_t<Ptr>)
|
||||
* @tparam Del Type of object freeing function (deduced from second argument)
|
||||
* @param ptr Raw pointer to owned object
|
||||
* @param deleter Object deleter
|
||||
*
|
||||
* Example use
|
||||
* @code
|
||||
* class Resource
|
||||
* {
|
||||
* };
|
||||
* class ResourceService
|
||||
* {
|
||||
* Resource* Create();
|
||||
* void Destroy(Resource*);
|
||||
* };
|
||||
*
|
||||
* ResourceService* service = GetResourceService();
|
||||
*
|
||||
* // Lambda that captures all required variables for destruction
|
||||
* auto resource = Trinity::make_unique_ptr_with_deleter(service->Create(), [service](Resource* res){ service->Destroy(res); });
|
||||
* @endcode
|
||||
*/
|
||||
template<typename Ptr, typename T = std::remove_pointer_t<Ptr>, typename Del> requires std::invocable<Del, Ptr> && std::is_pointer_v<Ptr>
|
||||
std::unique_ptr<T, Impl::stateful_unique_ptr_deleter<Ptr, Del>> make_unique_ptr_with_deleter(Ptr ptr, Del deleter)
|
||||
{
|
||||
return std::unique_ptr<T, Impl::stateful_unique_ptr_deleter<Ptr, Del>>(ptr, std::move(deleter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to construct a std::unique_ptr object with custom stateless deleter (function pointer, captureless lambda)
|
||||
* @tparam Del The freeing function. This can be either a free function pointer that accepts T* as argument, pointer to a member function of T that accepts no arguments or a lambda with no captures
|
||||
* @tparam Ptr Type of the pointer
|
||||
* @tparam T Type of the pointed-to object (defaults to std::remove_pointer_t<Ptr>)
|
||||
* @param ptr Raw pointer to owned object
|
||||
*
|
||||
* Example uses
|
||||
* @code
|
||||
* void DestroyResource(Resource*);
|
||||
* class Resource
|
||||
* {
|
||||
* void Destroy();
|
||||
* };
|
||||
*
|
||||
* // Free function
|
||||
* auto free = Trinity::make_unique_ptr_with_deleter<&DestroyResource>(new Resource());
|
||||
*
|
||||
* // Member function
|
||||
* auto member = Trinity::make_unique_ptr_with_deleter<&Resource::Destroy>(new Resource());
|
||||
*
|
||||
* // Lambda
|
||||
* auto lambda = Trinity::make_unique_ptr_with_deleter<[](Resource* res){ res->Destroy(); }>(new Resource());
|
||||
* @endcode
|
||||
*/
|
||||
template<auto Del, typename Ptr, typename T = std::remove_pointer_t<Ptr>> requires std::invocable<decltype(Del), Ptr> && std::is_pointer_v<Ptr>
|
||||
std::unique_ptr<T, Impl::stateless_unique_ptr_deleter<Ptr, Del>> make_unique_ptr_with_deleter(Ptr ptr)
|
||||
{
|
||||
return std::unique_ptr<T, Impl::stateless_unique_ptr_deleter<Ptr, Del>>(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // TRINITY_MEMORY_H
|
||||
@@ -18,15 +18,11 @@
|
||||
#ifndef TrinityCore_Regex_h__
|
||||
#define TrinityCore_Regex_h__
|
||||
|
||||
#ifndef TC_HAS_BROKEN_WSTRING_REGEX
|
||||
#include <regex>
|
||||
#define TC_REGEX_NAMESPACE std
|
||||
#else
|
||||
// std::wregex doesn't work with patterns provided in db2 files
|
||||
// so we have to use boost
|
||||
#include <boost/regex.hpp>
|
||||
#define TC_REGEX_NAMESPACE boost
|
||||
#endif
|
||||
|
||||
// regex compatibility layer, required for clang building with libstdc++-4.9
|
||||
namespace Trinity
|
||||
{
|
||||
using regex = TC_REGEX_NAMESPACE :: regex;
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
#include "StartProcess.h"
|
||||
#include "Errors.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Optional.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/iostreams/copy.hpp>
|
||||
#include <boost/process/args.hpp>
|
||||
#include <boost/process/child.hpp>
|
||||
#include <boost/process/env.hpp>
|
||||
@@ -32,41 +32,9 @@
|
||||
#include <boost/process/search_path.hpp>
|
||||
|
||||
using namespace boost::process;
|
||||
using namespace boost::iostreams;
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class TCLogSink
|
||||
{
|
||||
T callback_;
|
||||
|
||||
public:
|
||||
typedef char char_type;
|
||||
typedef sink_tag category;
|
||||
|
||||
// Requires a callback type which has a void(std::string) signature
|
||||
TCLogSink(T callback)
|
||||
: callback_(std::move(callback)) { }
|
||||
|
||||
std::streamsize write(char const* str, std::streamsize size)
|
||||
{
|
||||
std::string consoleStr(str, size);
|
||||
std::string utf8;
|
||||
if (consoleToUtf8(consoleStr, utf8))
|
||||
callback_(utf8);
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
auto MakeTCLogSink(T&& callback)
|
||||
-> TCLogSink<typename std::decay<T>::type>
|
||||
{
|
||||
return { std::forward<T>(callback) };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static int CreateChildProcess(T waiter, std::string const& executable,
|
||||
std::vector<std::string> const& argsVector,
|
||||
@@ -98,12 +66,7 @@ static int CreateChildProcess(T waiter, std::string const& executable,
|
||||
}
|
||||
|
||||
// prepare file with only read permission (boost process opens with read_write)
|
||||
std::shared_ptr<FILE> inputFile(!input.empty() ? fopen(input.c_str(), "rb") : nullptr, [](FILE* ptr)
|
||||
{
|
||||
if (ptr != nullptr)
|
||||
fclose(ptr);
|
||||
});
|
||||
|
||||
auto inputFile = Trinity::make_unique_ptr_with_deleter(!input.empty() ? fopen(input.c_str(), "rb") : nullptr, &::fclose);
|
||||
// Start the child process
|
||||
child c = [&]()
|
||||
{
|
||||
@@ -133,18 +96,20 @@ static int CreateChildProcess(T waiter, std::string const& executable,
|
||||
}
|
||||
}();
|
||||
|
||||
auto outInfo = MakeTCLogSink([&](std::string const& msg)
|
||||
std::string line;
|
||||
while (std::getline(outStream, line, '\n'))
|
||||
{
|
||||
TC_LOG_INFO(logger, "%s", msg.c_str());
|
||||
});
|
||||
std::erase(line, '\r');
|
||||
if (!line.empty())
|
||||
TC_LOG_INFO(logger, "%s", line.c_str());
|
||||
}
|
||||
|
||||
auto outError = MakeTCLogSink([&](std::string const& msg)
|
||||
while (std::getline(errStream, line, '\n'))
|
||||
{
|
||||
TC_LOG_ERROR(logger, "%s", msg.c_str());
|
||||
});
|
||||
|
||||
copy(outStream, outInfo);
|
||||
copy(errStream, outError);
|
||||
std::erase(line, '\r');
|
||||
if (!line.empty())
|
||||
TC_LOG_ERROR(logger, "%s", line.c_str());
|
||||
}
|
||||
|
||||
// Call the waiter in the current scope to prevent
|
||||
// the streams from closing too early on leaving the scope.
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "Optional.h"
|
||||
#include "Random.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifndef Types_h__
|
||||
#define Types_h__
|
||||
|
||||
#include "advstd.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace Trinity
|
||||
};
|
||||
|
||||
template<template<typename...> typename Check, typename T1, typename... Ts>
|
||||
struct find_type_if<Check, T1, Ts...> : std::conditional_t<Check<T1>::value, advstd::type_identity<T1>, find_type_if<Check, Ts...>>
|
||||
struct find_type_if<Check, T1, Ts...> : std::conditional_t<Check<T1>::value, std::type_identity<T1>, find_type_if<Check, Ts...>>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 TRINITYCORE_UNIQUE_TRACKABLE_PTR_H
|
||||
#define TRINITYCORE_UNIQUE_TRACKABLE_PTR_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
template <typename T>
|
||||
class unique_trackable_ptr;
|
||||
|
||||
template <typename T>
|
||||
class unique_weak_ptr;
|
||||
|
||||
template <typename T>
|
||||
class unique_strong_ref_ptr;
|
||||
|
||||
/**
|
||||
* \brief Specialized variant of std::shared_ptr that enforces unique ownership and/or std::unique_ptr with std::weak_ptr capabilities
|
||||
* Implementation has the same overhead as a std::shared_ptr, that is, a separate allocation for control block that holds use counters
|
||||
* \tparam T Type of held object
|
||||
*/
|
||||
template <typename T>
|
||||
class unique_trackable_ptr
|
||||
{
|
||||
public:
|
||||
using element_type = T;
|
||||
using pointer = T*;
|
||||
|
||||
unique_trackable_ptr() : _ptr() { }
|
||||
|
||||
explicit unique_trackable_ptr(pointer ptr)
|
||||
: _ptr(ptr) { }
|
||||
|
||||
template <typename Deleter, std::enable_if_t<std::conjunction_v<std::is_move_constructible<Deleter>, std::is_invocable<Deleter&, T*&>>, int> = 0>
|
||||
explicit unique_trackable_ptr(pointer ptr, Deleter deleter)
|
||||
: _ptr(ptr, std::move(deleter)) { }
|
||||
|
||||
unique_trackable_ptr(unique_trackable_ptr const&) = delete;
|
||||
|
||||
unique_trackable_ptr(unique_trackable_ptr&& other) noexcept
|
||||
: _ptr(std::move(other._ptr)) { }
|
||||
|
||||
template <typename T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
|
||||
unique_trackable_ptr(unique_trackable_ptr<T2>&& other) noexcept
|
||||
: _ptr(std::move(other)._ptr) { }
|
||||
|
||||
unique_trackable_ptr& operator=(unique_trackable_ptr const&) = delete;
|
||||
|
||||
unique_trackable_ptr& operator=(unique_trackable_ptr&& other) noexcept
|
||||
{
|
||||
_ptr = std::move(other._ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
|
||||
unique_trackable_ptr& operator=(unique_trackable_ptr<T2>&& other) noexcept
|
||||
{
|
||||
_ptr = std::move(other)._ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~unique_trackable_ptr() = default;
|
||||
|
||||
unique_trackable_ptr& operator=(std::nullptr_t)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(unique_trackable_ptr& other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(_ptr, other._ptr);
|
||||
}
|
||||
|
||||
element_type& operator*() const
|
||||
{
|
||||
return *_ptr;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
return _ptr.operator->();
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
{
|
||||
return _ptr.get();
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(_ptr);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
_ptr.reset();
|
||||
}
|
||||
|
||||
void reset(pointer ptr)
|
||||
{
|
||||
_ptr.reset(ptr);
|
||||
}
|
||||
|
||||
template <class Deleter, std::enable_if_t<std::conjunction_v<std::is_move_constructible<Deleter>, std::is_invocable<Deleter&, T*&>>, int> = 0>
|
||||
void reset(pointer ptr, Deleter deleter)
|
||||
{
|
||||
_ptr.reset(ptr, std::move(deleter));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T0>
|
||||
friend class unique_trackable_ptr;
|
||||
|
||||
template <typename T0>
|
||||
friend class unique_weak_ptr;
|
||||
|
||||
template <typename T0, typename... Args>
|
||||
friend std::enable_if_t<!std::is_array_v<T0>, unique_trackable_ptr<T0>> make_unique_trackable(Args&&... args);
|
||||
|
||||
template <typename T0>
|
||||
friend std::enable_if_t<std::is_unbounded_array_v<T0>, unique_trackable_ptr<T0>> make_unique_trackable(std::size_t N);
|
||||
|
||||
template <typename T0>
|
||||
friend std::enable_if_t<std::is_unbounded_array_v<T0>, unique_trackable_ptr<T0>> make_unique_trackable(std::size_t N, std::remove_extent_t<T0> const& val);
|
||||
|
||||
template <typename T0>
|
||||
friend std::enable_if_t<std::is_bounded_array_v<T0>, unique_trackable_ptr<T0>> make_unique_trackable();
|
||||
|
||||
template <typename T0>
|
||||
friend std::enable_if_t<std::is_bounded_array_v<T0>, unique_trackable_ptr<T0>> make_unique_trackable(std::remove_extent_t<T0> const& val);
|
||||
|
||||
std::shared_ptr<element_type> _ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Trinity::unique_trackable_ptr companion class, replicating what std::weak_ptr is to std::shared_ptr
|
||||
* \tparam T Type of held object
|
||||
*/
|
||||
template <typename T>
|
||||
class unique_weak_ptr
|
||||
{
|
||||
public:
|
||||
using element_type = T;
|
||||
using pointer = T*;
|
||||
|
||||
unique_weak_ptr() = default;
|
||||
|
||||
unique_weak_ptr(unique_trackable_ptr<T> const& trackable)
|
||||
: _ptr(trackable._ptr) { }
|
||||
|
||||
unique_weak_ptr(unique_weak_ptr const& other) = default;
|
||||
|
||||
template <typename T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
|
||||
unique_weak_ptr(unique_weak_ptr<T2> const& other) noexcept
|
||||
: _ptr(other._ptr) { }
|
||||
|
||||
unique_weak_ptr(unique_weak_ptr&& other) noexcept = default;
|
||||
|
||||
template <typename T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
|
||||
unique_weak_ptr(unique_weak_ptr<T2>&& other) noexcept
|
||||
: _ptr(std::move(other)._ptr) { }
|
||||
|
||||
unique_weak_ptr& operator=(unique_trackable_ptr<T> const& trackable)
|
||||
{
|
||||
_ptr = trackable._ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_weak_ptr& operator=(unique_weak_ptr const& other) = default;
|
||||
|
||||
template <typename T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
|
||||
unique_weak_ptr& operator=(unique_weak_ptr<T2>&& other)
|
||||
{
|
||||
_ptr = std::move(other)._ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_weak_ptr& operator=(unique_weak_ptr&& other) noexcept = default;
|
||||
|
||||
~unique_weak_ptr() = default;
|
||||
|
||||
void swap(unique_weak_ptr& other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(_ptr, other._ptr);
|
||||
}
|
||||
|
||||
bool expired() const
|
||||
{
|
||||
return _ptr.expired();
|
||||
}
|
||||
|
||||
unique_strong_ref_ptr<element_type> lock() const
|
||||
{
|
||||
return unique_strong_ref_ptr<element_type>(_ptr.lock());
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T0>
|
||||
friend class unique_weak_ptr;
|
||||
|
||||
template <typename T0>
|
||||
friend class unique_strong_ref_ptr;
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_weak_ptr<To> static_pointer_cast(unique_weak_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_weak_ptr<To> const_pointer_cast(unique_weak_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_weak_ptr<To> reinterpret_pointer_cast(unique_weak_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_weak_ptr<To> dynamic_pointer_cast(unique_weak_ptr<From> const& other);
|
||||
|
||||
std::weak_ptr<element_type> _ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Result of unique_weak_ptr::lock() function, this class holds a temporary strong reference to held object
|
||||
* to prevent it from being deallocated by another thread while it is being actively accessed.
|
||||
* This class is non-movable and non-copypable and is intended only for short lived local variables
|
||||
* \tparam T Type of held object
|
||||
*/
|
||||
template <typename T>
|
||||
class unique_strong_ref_ptr
|
||||
{
|
||||
public:
|
||||
using element_type = T;
|
||||
using pointer = T*;
|
||||
|
||||
unique_strong_ref_ptr(unique_strong_ref_ptr const&) = delete;
|
||||
unique_strong_ref_ptr(unique_strong_ref_ptr&&) = delete;
|
||||
unique_strong_ref_ptr& operator=(unique_strong_ref_ptr const&) = delete;
|
||||
unique_strong_ref_ptr& operator=(unique_strong_ref_ptr&&) = delete;
|
||||
|
||||
~unique_strong_ref_ptr() = default;
|
||||
|
||||
element_type& operator*() const
|
||||
{
|
||||
return *_ptr;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
return _ptr.operator->();
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
{
|
||||
return _ptr.get();
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(_ptr);
|
||||
}
|
||||
|
||||
operator unique_weak_ptr<T>() const
|
||||
{
|
||||
unique_weak_ptr<T> weak;
|
||||
weak._ptr = _ptr;
|
||||
return weak;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T0>
|
||||
friend class unique_weak_ptr;
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> static_pointer_cast(unique_strong_ref_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> static_pointer_cast(unique_strong_ref_ptr<From>&& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> const_pointer_cast(unique_strong_ref_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> const_pointer_cast(unique_strong_ref_ptr<From>&& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> reinterpret_pointer_cast(unique_strong_ref_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> reinterpret_pointer_cast(unique_strong_ref_ptr<From>&& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> dynamic_pointer_cast(unique_strong_ref_ptr<From> const& other);
|
||||
|
||||
template <class To, class From>
|
||||
friend unique_strong_ref_ptr<To> dynamic_pointer_cast(unique_strong_ref_ptr<From>&& other);
|
||||
|
||||
unique_strong_ref_ptr(std::shared_ptr<element_type> ptr) : _ptr(std::move(ptr)) { }
|
||||
|
||||
std::shared_ptr<element_type> _ptr;
|
||||
};
|
||||
|
||||
// unique_trackable_ptr funcions
|
||||
|
||||
template <typename T1, typename T2>
|
||||
bool operator==(unique_trackable_ptr<T1> const& left, unique_trackable_ptr<T2> const& right)
|
||||
{
|
||||
return left.get() == right.get();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
std::strong_ordering operator<=>(unique_trackable_ptr<T1> const& left, unique_trackable_ptr<T2> const& right)
|
||||
{
|
||||
return left.get() <=> right.get();
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
bool operator==(unique_trackable_ptr<T1> const& left, std::nullptr_t)
|
||||
{
|
||||
return left.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
std::strong_ordering operator<=>(unique_trackable_ptr<T1> const& left, std::nullptr_t)
|
||||
{
|
||||
return left.get() <=> nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
std::enable_if_t<!std::is_array_v<T>, unique_trackable_ptr<T>> make_unique_trackable(Args&&... args)
|
||||
{
|
||||
unique_trackable_ptr<T> ptr;
|
||||
ptr._ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_unbounded_array_v<T>, unique_trackable_ptr<T>> make_unique_trackable(std::size_t N)
|
||||
{
|
||||
unique_trackable_ptr<T> ptr;
|
||||
ptr._ptr = std::make_shared<T>(N);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_unbounded_array_v<T>, unique_trackable_ptr<T>> make_unique_trackable(std::size_t N, std::remove_extent_t<T> const& val)
|
||||
{
|
||||
unique_trackable_ptr<T> ptr;
|
||||
ptr._ptr = std::make_shared<T>(N, val);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_bounded_array_v<T>, unique_trackable_ptr<T>> make_unique_trackable()
|
||||
{
|
||||
unique_trackable_ptr<T> ptr;
|
||||
ptr._ptr = std::make_shared<T>();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_bounded_array_v<T>, unique_trackable_ptr<T>> make_unique_trackable(std::remove_extent_t<T> const& val)
|
||||
{
|
||||
unique_trackable_ptr<T> ptr;
|
||||
ptr._ptr = std::make_shared<T>(val);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// unique_weak_ptr funcions
|
||||
|
||||
template <class To, class From>
|
||||
unique_weak_ptr<To> static_pointer_cast(unique_weak_ptr<From> const& other)
|
||||
{
|
||||
unique_weak_ptr<To> to;
|
||||
to._ptr = std::static_pointer_cast<To>(other._ptr.lock());
|
||||
return to;
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_weak_ptr<To> const_pointer_cast(unique_weak_ptr<From> const& other)
|
||||
{
|
||||
unique_weak_ptr<To> to;
|
||||
to._ptr = std::const_pointer_cast<To>(other._ptr.lock());
|
||||
return to;
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_weak_ptr<To> reinterpret_pointer_cast(unique_weak_ptr<From> const& other)
|
||||
{
|
||||
unique_weak_ptr<To> to;
|
||||
to._ptr = std::reinterpret_pointer_cast<To>(other._ptr.lock());
|
||||
return to;
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_weak_ptr<To> dynamic_pointer_cast(unique_weak_ptr<From> const& other)
|
||||
{
|
||||
unique_weak_ptr<To> to;
|
||||
to._ptr = std::dynamic_pointer_cast<To>(other._ptr.lock());
|
||||
return to;
|
||||
}
|
||||
|
||||
// unique_strong_ref_ptr funcions
|
||||
|
||||
template <typename T1, typename T2>
|
||||
bool operator==(unique_strong_ref_ptr<T1> const& left, unique_strong_ref_ptr<T2> const& right)
|
||||
{
|
||||
return left.get() == right.get();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
std::strong_ordering operator<=>(unique_strong_ref_ptr<T1> const& left, unique_strong_ref_ptr<T2> const& right)
|
||||
{
|
||||
return left.get() <=> right.get();
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
bool operator==(unique_strong_ref_ptr<T1> const& left, std::nullptr_t)
|
||||
{
|
||||
return left.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
std::strong_ordering operator<=>(unique_strong_ref_ptr<T1> const& left, std::nullptr_t)
|
||||
{
|
||||
return left.get() <=> nullptr;
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> static_pointer_cast(unique_strong_ref_ptr<From> const& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::static_pointer_cast<To>(other._ptr));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> static_pointer_cast(unique_strong_ref_ptr<From>&& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::static_pointer_cast<To>(std::move(other._ptr)));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> const_pointer_cast(unique_strong_ref_ptr<From> const& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::const_pointer_cast<To>(other._ptr));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> const_pointer_cast(unique_strong_ref_ptr<From>&& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::const_pointer_cast<To>(std::move(other._ptr)));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> reinterpret_pointer_cast(unique_strong_ref_ptr<From> const& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::reinterpret_pointer_cast<To>(other._ptr));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> reinterpret_pointer_cast(unique_strong_ref_ptr<From>&& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::reinterpret_pointer_cast<To>(std::move(other._ptr)));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> dynamic_pointer_cast(unique_strong_ref_ptr<From> const& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::dynamic_pointer_cast<To>(other._ptr));
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
unique_strong_ref_ptr<To> dynamic_pointer_cast(unique_strong_ref_ptr<From>&& other)
|
||||
{
|
||||
return unique_strong_ref_ptr<To>(std::dynamic_pointer_cast<To>(std::move(other._ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TRINITYCORE_UNIQUE_TRACKABLE_PTR_H
|
||||
@@ -18,71 +18,9 @@
|
||||
#ifndef TRINITY_ADVSTD_H
|
||||
#define TRINITY_ADVSTD_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
// this namespace holds implementations of upcoming stdlib features that our c++ version doesn't have yet
|
||||
namespace advstd {
|
||||
// C++17 std::apply (constrained to only function pointers, not all callable)
|
||||
template <typename... Ts>
|
||||
using apply_tuple_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Ts>>...>;
|
||||
template <typename R, typename... Ts, std::size_t... I>
|
||||
R apply_impl(R(*func)(Ts...), apply_tuple_type<Ts...>&& args, std::index_sequence<I...>)
|
||||
{
|
||||
return func(std::get<I>(std::forward<apply_tuple_type<Ts...>>(args))...);
|
||||
}
|
||||
template <typename R, typename... Ts>
|
||||
R apply(R(*func)(Ts...), apply_tuple_type<Ts...>&& args)
|
||||
{
|
||||
return apply_impl(func, std::forward<apply_tuple_type<Ts...>>(args), std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
#define forward_1v(stdname, type) template <typename T> constexpr type stdname ## _v = std::stdname<T>::value
|
||||
#define forward_2v(stdname, type) template <typename U, typename V> constexpr type stdname ## _v = std::stdname<U,V>::value
|
||||
|
||||
// C++17 std::is_same_v
|
||||
forward_2v(is_same, bool);
|
||||
|
||||
// C++17 std::is_integral_v
|
||||
forward_1v(is_integral, bool);
|
||||
|
||||
// C++17 std::is_assignable_v
|
||||
forward_2v(is_assignable, bool);
|
||||
|
||||
// C++17 std::is_signed_v
|
||||
forward_1v(is_signed, bool);
|
||||
|
||||
// C++17 std::is_unsigned_v
|
||||
forward_1v(is_unsigned, bool);
|
||||
|
||||
// C++17 std::is_base_of_v
|
||||
forward_2v(is_base_of, bool);
|
||||
|
||||
// C++17 std::is_floating_point_v
|
||||
forward_1v(is_floating_point, bool);
|
||||
|
||||
// C++17 std::tuple_size_v
|
||||
forward_1v(tuple_size, size_t);
|
||||
|
||||
#undef forward_1v
|
||||
#undef forward_2v
|
||||
|
||||
// C++20 std::remove_cvref_t
|
||||
template <class T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
// C++20 std::type_identity
|
||||
template <typename T>
|
||||
struct type_identity
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
// C++20 std::type_identity_t
|
||||
template <typename T>
|
||||
using type_identity_t = typename type_identity<T>::type;
|
||||
namespace advstd
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -207,7 +207,7 @@ int main(int argc, char** argv)
|
||||
// Enabled a timed callback for handling the database keep alive ping
|
||||
int32 dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30);
|
||||
std::shared_ptr<Trinity::Asio::DeadlineTimer> dbPingTimer = std::make_shared<Trinity::Asio::DeadlineTimer>(*ioContext);
|
||||
dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval));
|
||||
dbPingTimer->expires_after(std::chrono::minutes(dbPingInterval));
|
||||
dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, std::weak_ptr<Trinity::Asio::DeadlineTimer>(dbPingTimer), dbPingInterval, std::placeholders::_1));
|
||||
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
@@ -215,7 +215,7 @@ int main(int argc, char** argv)
|
||||
if (m_ServiceStatus != -1)
|
||||
{
|
||||
serviceStatusWatchTimer = std::make_shared<Trinity::Asio::DeadlineTimer>(*ioContext);
|
||||
serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1));
|
||||
serviceStatusWatchTimer->expires_after(1s);
|
||||
serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher,
|
||||
std::weak_ptr<Trinity::Asio::DeadlineTimer>(serviceStatusWatchTimer),
|
||||
std::weak_ptr<Trinity::Asio::IoContext>(ioContext),
|
||||
@@ -280,7 +280,7 @@ void KeepDatabaseAliveHandler(std::weak_ptr<Trinity::Asio::DeadlineTimer> dbPing
|
||||
TC_LOG_INFO("server.bnetserver", "Ping MySQL to keep connection alive");
|
||||
LoginDatabase.KeepAlive();
|
||||
|
||||
dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval));
|
||||
dbPingTimer->expires_after(std::chrono::minutes(dbPingInterval));
|
||||
dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, dbPingTimerRef, dbPingInterval, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
@@ -299,7 +299,7 @@ void ServiceStatusWatcher(std::weak_ptr<Trinity::Asio::DeadlineTimer> serviceSta
|
||||
}
|
||||
else if (std::shared_ptr<Trinity::Asio::DeadlineTimer> serviceStatusWatchTimer = serviceStatusWatchTimerRef.lock())
|
||||
{
|
||||
serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1));
|
||||
serviceStatusWatchTimer->expires_after(1s);
|
||||
serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher, serviceStatusWatchTimerRef, ioContext, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ void BNetRealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
|
||||
if (_updateInterval)
|
||||
{
|
||||
_updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
|
||||
_updateTimer->expires_after(std::chrono::seconds(_updateInterval));
|
||||
_updateTimer->async_wait(std::bind(&BNetRealmList::UpdateRealms, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
|
||||
#include "UpdateFetcher.h"
|
||||
#include "Common.h"
|
||||
#include "Duration.h"
|
||||
#include "DBUpdater.h"
|
||||
#include "Field.h"
|
||||
#include "Log.h"
|
||||
#include "QueryResult.h"
|
||||
#include "Util.h"
|
||||
#include "SHA1.h"
|
||||
#include <boost/filesystem/directory.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "UnitAI.h"
|
||||
#include "Containers.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "MotionMaster.h"
|
||||
@@ -265,14 +266,97 @@ void UnitAI::FillAISpellInfo()
|
||||
}
|
||||
}
|
||||
|
||||
ThreatManager& UnitAI::GetThreatManager()
|
||||
Unit* UnitAI::FinalizeTargetSelection(std::list<Unit*>& targetList, SelectAggroTarget targetType)
|
||||
{
|
||||
return me->GetThreatManager();
|
||||
// maybe nothing fulfills the predicate
|
||||
if (targetList.empty())
|
||||
return nullptr;
|
||||
|
||||
switch (targetType)
|
||||
{
|
||||
case SELECT_TARGET_MAXTHREAT:
|
||||
case SELECT_TARGET_MINTHREAT:
|
||||
case SELECT_TARGET_MAXDISTANCE:
|
||||
case SELECT_TARGET_MINDISTANCE:
|
||||
return targetList.front();
|
||||
case SELECT_TARGET_RANDOM:
|
||||
return Trinity::Containers::SelectRandomContainerElement(targetList);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UnitAI::SortByDistance(std::list<Unit*>& list, bool ascending)
|
||||
bool UnitAI::PrepareTargetListSelection(std::list<Unit*>& targetList, SelectAggroTarget targetType, uint32 offset)
|
||||
{
|
||||
list.sort(Trinity::ObjectDistanceOrderPred(me, ascending));
|
||||
targetList.clear();
|
||||
ThreatManager& mgr = me->GetThreatManager();
|
||||
// shortcut: we're gonna ignore the first <offset> elements, and there's at most <offset> elements, so we ignore them all - nothing to do here
|
||||
if (mgr.GetThreatListSize() <= offset)
|
||||
return false;
|
||||
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
{
|
||||
for (ThreatReference const* ref : mgr.GetUnsortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
targetList.push_back(ref->GetVictim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* currentVictim = mgr.GetCurrentVictim();
|
||||
if (currentVictim)
|
||||
targetList.push_back(currentVictim);
|
||||
|
||||
for (ThreatReference const* ref : mgr.GetSortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
Unit* thisTarget = ref->GetVictim();
|
||||
if (thisTarget != currentVictim)
|
||||
targetList.push_back(thisTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// shortcut: the list isn't gonna get any larger
|
||||
if (targetList.size() <= offset)
|
||||
{
|
||||
targetList.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// right now, list is unsorted for DISTANCE types - re-sort by SelectTargetMethod::MaxDistance
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
targetList.sort(Trinity::ObjectDistanceOrderPred(me, targetType == SELECT_TARGET_MINDISTANCE));
|
||||
|
||||
// now the list is MAX sorted, reverse for MIN types
|
||||
if (targetType == SELECT_TARGET_MINTHREAT)
|
||||
targetList.reverse();
|
||||
|
||||
// ignore the first <offset> elements
|
||||
while (offset)
|
||||
{
|
||||
targetList.pop_front();
|
||||
--offset;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnitAI::FinalizeTargetListSelection(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType)
|
||||
{
|
||||
if (targetList.size() <= num)
|
||||
return;
|
||||
|
||||
if (targetType == SELECT_TARGET_RANDOM)
|
||||
Trinity::Containers::RandomResize(targetList, num);
|
||||
else
|
||||
targetList.resize(num);
|
||||
}
|
||||
|
||||
DefaultTargetSelector::DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withTank, int32 aura)
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
#ifndef TRINITY_UNITAI_H
|
||||
#define TRINITY_UNITAI_H
|
||||
|
||||
#include "Containers.h"
|
||||
#include "Errors.h"
|
||||
#include "EventMap.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SpellDefines.h"
|
||||
#include "ThreatManager.h"
|
||||
|
||||
#define CAST_AI(a, b) (dynamic_cast<a*>(b))
|
||||
#define ENSURE_AI(a,b) (EnsureAI<a>(b))
|
||||
@@ -170,30 +169,10 @@ class TC_GAME_API UnitAI
|
||||
template<class PREDICATE>
|
||||
Unit* SelectTarget(SelectAggroTarget targetType, uint32 offset, PREDICATE const& predicate)
|
||||
{
|
||||
ThreatManager& mgr = GetThreatManager();
|
||||
// shortcut: if we ignore the first <offset> elements, and there are at most <offset> elements, then we ignore ALL elements
|
||||
if (mgr.GetThreatListSize() <= offset)
|
||||
return nullptr;
|
||||
|
||||
std::list<Unit*> targetList;
|
||||
SelectTargetList(targetList, mgr.GetThreatListSize(), targetType, offset, predicate);
|
||||
SelectTargetList(targetList, std::numeric_limits<uint32>::max(), targetType, offset, predicate);
|
||||
|
||||
// maybe nothing fulfills the predicate
|
||||
if (targetList.empty())
|
||||
return nullptr;
|
||||
|
||||
switch (targetType)
|
||||
{
|
||||
case SELECT_TARGET_MAXTHREAT:
|
||||
case SELECT_TARGET_MINTHREAT:
|
||||
case SELECT_TARGET_MAXDISTANCE:
|
||||
case SELECT_TARGET_MINDISTANCE:
|
||||
return targetList.front();
|
||||
case SELECT_TARGET_RANDOM:
|
||||
return Trinity::Containers::SelectRandomContainerElement(targetList);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return FinalizeTargetSelection(targetList, targetType);
|
||||
}
|
||||
|
||||
// Select the best (up to) <num> targets (in <targetType> order) from the threat list that fulfill the following:
|
||||
@@ -212,71 +191,13 @@ class TC_GAME_API UnitAI
|
||||
template <class PREDICATE>
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset, PREDICATE const& predicate)
|
||||
{
|
||||
targetList.clear();
|
||||
ThreatManager& mgr = GetThreatManager();
|
||||
// shortcut: we're gonna ignore the first <offset> elements, and there's at most <offset> elements, so we ignore them all - nothing to do here
|
||||
if (mgr.GetThreatListSize() <= offset)
|
||||
if (!PrepareTargetListSelection(targetList, targetType, offset))
|
||||
return;
|
||||
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
{
|
||||
for (ThreatReference const* ref : mgr.GetUnsortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
targetList.push_back(ref->GetVictim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* currentVictim = mgr.GetCurrentVictim();
|
||||
if (currentVictim)
|
||||
targetList.push_back(currentVictim);
|
||||
|
||||
for (ThreatReference const* ref : mgr.GetSortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
Unit* thisTarget = ref->GetVictim();
|
||||
if (thisTarget != currentVictim)
|
||||
targetList.push_back(thisTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// shortcut: the list isn't gonna get any larger
|
||||
if (targetList.size() <= offset)
|
||||
{
|
||||
targetList.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
SortByDistance(targetList, targetType == SELECT_TARGET_MINDISTANCE);
|
||||
|
||||
// now the list is MAX sorted, reverse for MIN types
|
||||
if (targetType == SELECT_TARGET_MINTHREAT)
|
||||
targetList.reverse();
|
||||
|
||||
// ignore the first <offset> elements
|
||||
while (offset)
|
||||
{
|
||||
targetList.pop_front();
|
||||
--offset;
|
||||
}
|
||||
|
||||
// then finally filter by predicate
|
||||
targetList.remove_if([&predicate](Unit* target) { return !predicate(target); });
|
||||
|
||||
if (targetList.size() <= num)
|
||||
return;
|
||||
|
||||
if (targetType == SELECT_TARGET_RANDOM)
|
||||
Trinity::Containers::RandomResize(targetList, num);
|
||||
else
|
||||
targetList.resize(num);
|
||||
FinalizeTargetListSelection(targetList, num, targetType);
|
||||
}
|
||||
|
||||
// Called when the unit enters combat
|
||||
@@ -330,8 +251,9 @@ class TC_GAME_API UnitAI
|
||||
UnitAI(UnitAI const& right) = delete;
|
||||
UnitAI& operator=(UnitAI const& right) = delete;
|
||||
|
||||
ThreatManager& GetThreatManager();
|
||||
void SortByDistance(std::list<Unit*>& list, bool ascending = true);
|
||||
Unit* FinalizeTargetSelection(std::list<Unit*>& targetList, SelectAggroTarget targetType);
|
||||
bool PrepareTargetListSelection(std::list<Unit*>& targetList, SelectAggroTarget targetType, uint32 offset);
|
||||
void FinalizeTargetListSelection(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "SpellHistory.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "Vehicle.h"
|
||||
#include <queue>
|
||||
|
||||
//Disable CreatureAI when charmed
|
||||
void CreatureAI::OnCharmed(bool isNew)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "AreaBoundary.h"
|
||||
#include "Cell.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "DBCStores.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
@@ -111,9 +112,12 @@ bool SummonList::HasEntry(uint32 entry) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void SummonList::DoActionImpl(int32 action, StorageType const& summons)
|
||||
void SummonList::DoActionImpl(int32 action, StorageType& summons, uint16 max)
|
||||
{
|
||||
for (auto const& guid : summons)
|
||||
if (max)
|
||||
Trinity::Containers::RandomResize(summons, max);
|
||||
|
||||
for (ObjectGuid const& guid : summons)
|
||||
{
|
||||
Creature* summon = ObjectAccessor::GetCreature(*me, guid);
|
||||
if (summon && summon->IsAIEnabled())
|
||||
|
||||
@@ -97,9 +97,9 @@ public:
|
||||
void DoAction(int32 info, Predicate&& predicate, uint16 max = 0)
|
||||
{
|
||||
// We need to use a copy of SummonList here, otherwise original SummonList would be modified
|
||||
StorageType listCopy = storage_;
|
||||
Trinity::Containers::RandomResize<StorageType, Predicate>(listCopy, std::forward<Predicate>(predicate), max);
|
||||
DoActionImpl(info, listCopy);
|
||||
StorageType listCopy;
|
||||
std::copy_if(std::begin(storage_), std::end(storage_), std::inserter(listCopy, std::end(listCopy)), predicate);
|
||||
DoActionImpl(info, listCopy, max);
|
||||
}
|
||||
|
||||
void DoZoneInCombat(uint32 entry = 0);
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
bool HasEntry(uint32 entry) const;
|
||||
|
||||
private:
|
||||
void DoActionImpl(int32 action, StorageType const& summons);
|
||||
void DoActionImpl(int32 action, StorageType& summons, uint16 max);
|
||||
|
||||
Creature* me;
|
||||
StorageType storage_;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Creature.h"
|
||||
#include "CreatureTextMgr.h"
|
||||
#include "CreatureTextMgrImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "GameEventMgr.h"
|
||||
#include "GameObject.h"
|
||||
#include "GossipDef.h"
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#ifndef TRINITY_CHATCOMMAND_H
|
||||
#define TRINITY_CHATCOMMAND_H
|
||||
|
||||
#include "advstd.h"
|
||||
#include "ChatCommandArgs.h"
|
||||
#include "ChatCommandTags.h"
|
||||
#include "Define.h"
|
||||
@@ -169,7 +168,7 @@ class TC_GAME_API CommandArgs
|
||||
template <typename T1, typename T2, typename... Ts>
|
||||
auto TryConsume()
|
||||
{
|
||||
Optional<std::tuple<advstd::remove_cvref_t<T1>, advstd::remove_cvref_t<T2>, advstd::remove_cvref_t<Ts>...>> rv;
|
||||
Optional<std::tuple<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, std::remove_cvref_t<Ts>...>> rv;
|
||||
rv.emplace();
|
||||
if (!TryConsumeToTuple<0>(rv.value()))
|
||||
rv = std::nullopt;
|
||||
@@ -179,7 +178,7 @@ class TC_GAME_API CommandArgs
|
||||
template <typename T1>
|
||||
auto TryConsume()
|
||||
{
|
||||
using T = advstd::remove_cvref_t<T1>;
|
||||
using T = std::remove_cvref_t<T1>;
|
||||
Optional<T> rv;
|
||||
rv.emplace();
|
||||
if (char const* next = CommandArgsConsumerSingle<T>::TryConsumeTo(rv.value(), _args))
|
||||
@@ -214,8 +213,8 @@ class TC_GAME_API CommandArgs
|
||||
char const* _args;
|
||||
};
|
||||
|
||||
template <typename T> struct ChatCommandHandlerToTuple { static_assert(!advstd::is_same_v<T,T>, "Invalid command handler signature"); };
|
||||
template <typename... Ts> struct ChatCommandHandlerToTuple<bool(*)(ChatHandler*, Ts...)> { using type = std::tuple<ChatHandler*, advstd::remove_cvref_t<Ts>...>; };
|
||||
template <typename T> struct ChatCommandHandlerToTuple { static_assert(!std::is_same_v<T,T>, "Invalid command handler signature"); };
|
||||
template <typename... Ts> struct ChatCommandHandlerToTuple<bool(*)(ChatHandler*, Ts...)> { using type = std::tuple<ChatHandler*, std::remove_cvref_t<Ts>...>; };
|
||||
|
||||
template <typename T> struct ChatCommandStoreLastArg { static void store(T&, CommandArgs&) {} };
|
||||
template <> struct ChatCommandStoreLastArg<char const*> { static void store(char const*& arg, CommandArgs& args) { arg = args.GetRemainingArgs(); } };
|
||||
@@ -240,9 +239,9 @@ class TC_GAME_API ChatCommand
|
||||
CommandArgs args(argsStr);
|
||||
if (args.TryConsumeToTuple<1>(arguments))
|
||||
{
|
||||
auto& last = std::get<advstd::tuple_size_v<tuple_type>-1>(arguments);
|
||||
ChatCommandStoreLastArg<advstd::remove_cvref_t<decltype(last)>>::store(last, args);
|
||||
return advstd::apply(reinterpret_cast<TypedHandler>(handler), std::move(arguments));
|
||||
auto& last = std::get<std::tuple_size_v<tuple_type>-1>(arguments);
|
||||
ChatCommandStoreLastArg<std::remove_cvref_t<decltype(last)>>::store(last, args);
|
||||
return std::apply(reinterpret_cast<TypedHandler>(handler), std::move(arguments));
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
@@ -37,11 +37,11 @@ namespace ChatCommands {
|
||||
|* *|
|
||||
\****************************************************************************************/
|
||||
template <typename T, typename = void>
|
||||
struct ArgInfo { static_assert(!advstd::is_same_v<T,T>, "Invalid command parameter type - see ChatCommandArgs.h for possible types"); };
|
||||
struct ArgInfo { static_assert(!std::is_same_v<T,T>, "Invalid command parameter type - see ChatCommandArgs.h for possible types"); };
|
||||
|
||||
// catch-all for signed integral types
|
||||
template <typename T>
|
||||
struct ArgInfo<T, std::enable_if_t<advstd::is_integral_v<T> && advstd::is_signed_v<T>>>
|
||||
struct ArgInfo<T, std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>>>
|
||||
{
|
||||
static char const* TryConsume(T& val, char const* args)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ struct ArgInfo<T, std::enable_if_t<advstd::is_integral_v<T> && advstd::is_signed
|
||||
|
||||
// catch-all for unsigned integral types
|
||||
template <typename T>
|
||||
struct ArgInfo<T, std::enable_if_t<advstd::is_integral_v<T> && advstd::is_unsigned_v<T>>>
|
||||
struct ArgInfo<T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>>>
|
||||
{
|
||||
static char const* TryConsume(T& val, char const* args)
|
||||
{
|
||||
@@ -69,7 +69,7 @@ struct ArgInfo<T, std::enable_if_t<advstd::is_integral_v<T> && advstd::is_unsign
|
||||
|
||||
// catch-all for floating point types
|
||||
template <typename T>
|
||||
struct ArgInfo<T, std::enable_if_t<advstd::is_floating_point_v<T>>>
|
||||
struct ArgInfo<T, std::enable_if_t<std::is_floating_point_v<T>>>
|
||||
{
|
||||
static char const* TryConsume(T& val, char const* args)
|
||||
{
|
||||
@@ -100,7 +100,7 @@ struct ArgInfo<std::string, void>
|
||||
|
||||
// a container tag
|
||||
template <typename T>
|
||||
struct ArgInfo<T, std::enable_if_t<advstd::is_base_of_v<ContainerTag, T>>>
|
||||
struct ArgInfo<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>
|
||||
{
|
||||
static char const* TryConsume(T& tag, char const* args)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ struct are_all_assignable
|
||||
template <typename T1, typename T2, typename... Ts>
|
||||
struct are_all_assignable<T1, T2, Ts...>
|
||||
{
|
||||
static constexpr bool value = advstd::is_assignable_v<T1&, T2> && are_all_assignable<T1, Ts...>::value;
|
||||
static constexpr bool value = std::is_assignable_v<T1&, T2> && are_all_assignable<T1, Ts...>::value;
|
||||
};
|
||||
|
||||
template <size_t index, typename T1, typename... Ts>
|
||||
|
||||
@@ -32,7 +32,7 @@ template <typename linktag>
|
||||
struct Hyperlink : public ContainerTag
|
||||
{
|
||||
typedef typename linktag::value_type value_type;
|
||||
typedef advstd::remove_cvref_t<value_type> storage_type;
|
||||
typedef std::remove_cvref_t<value_type> storage_type;
|
||||
|
||||
public:
|
||||
operator value_type() const { return val; }
|
||||
@@ -105,7 +105,7 @@ struct base_tag
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::enable_if_t<advstd::is_integral_v<T> && advstd::is_unsigned_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
||||
static std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
||||
{
|
||||
try { val = std::stoull(std::string(pos, len)); }
|
||||
catch (...) { return false; }
|
||||
@@ -113,7 +113,7 @@ struct base_tag
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::enable_if_t<advstd::is_integral_v<T> && advstd::is_signed_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
||||
static std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
||||
{
|
||||
try { val = std::stoll(std::string(pos, len)); }
|
||||
catch (...) { return false; }
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ChatCommands {
|
||||
\****************************************************************************************/
|
||||
struct ContainerTag {};
|
||||
template <typename T>
|
||||
struct tag_base<T, std::enable_if_t<advstd::is_base_of_v<ContainerTag, T>>>
|
||||
struct tag_base<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>
|
||||
{
|
||||
using type = typename T::value_type;
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "Containers.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "Player.h"
|
||||
#include "TemporarySummon.h"
|
||||
@@ -32,9 +33,14 @@
|
||||
#include "ObjectAccessor.h"
|
||||
#include "WorldPacket.h"
|
||||
#include <algorithm>
|
||||
#include <boost/heap/fibonacci_heap.hpp>
|
||||
|
||||
const CompareThreatLessThan ThreatManager::CompareThreat;
|
||||
|
||||
class ThreatManager::Heap : public boost::heap::fibonacci_heap<ThreatReference const*, boost::heap::compare<CompareThreatLessThan>>
|
||||
{
|
||||
};
|
||||
|
||||
void ThreatReference::AddThreat(float amount)
|
||||
{
|
||||
if (amount == 0.0f)
|
||||
@@ -151,6 +157,24 @@ void ThreatReference::UnregisterAndFree()
|
||||
delete this;
|
||||
}
|
||||
|
||||
class ThreatReferenceImpl : public ThreatReference
|
||||
{
|
||||
public:
|
||||
explicit ThreatReferenceImpl(ThreatManager* mgr, Unit* victim) : ThreatReference(mgr, victim) {}
|
||||
|
||||
ThreatManager::Heap::handle_type _handle;
|
||||
};
|
||||
|
||||
void ThreatReference::HeapNotifyIncreased()
|
||||
{
|
||||
_mgr._sortedThreatList->increase(static_cast<ThreatReferenceImpl*>(this)->_handle);
|
||||
}
|
||||
|
||||
void ThreatReference::HeapNotifyDecreased()
|
||||
{
|
||||
_mgr._sortedThreatList->decrease(static_cast<ThreatReferenceImpl*>(this)->_handle);
|
||||
}
|
||||
|
||||
/*static*/ bool ThreatManager::CanHaveThreatList(Unit const* who)
|
||||
{
|
||||
Creature const* cWho = who->ToCreature();
|
||||
@@ -171,7 +195,8 @@ void ThreatReference::UnregisterAndFree()
|
||||
return true;
|
||||
}
|
||||
|
||||
ThreatManager::ThreatManager(Unit* owner) : _owner(owner), _ownerCanHaveThreatList(false), _needClientUpdate(false), _updateTimer(THREAT_UPDATE_INTERVAL), _currentVictimRef(nullptr), _fixateRef(nullptr)
|
||||
ThreatManager::ThreatManager(Unit* owner) : _owner(owner), _ownerCanHaveThreatList(false), _needClientUpdate(false), _updateTimer(THREAT_UPDATE_INTERVAL),
|
||||
_sortedThreatList(std::make_unique<Heap>()), _currentVictimRef(nullptr), _fixateRef(nullptr)
|
||||
{
|
||||
for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
|
||||
_singleSchoolModifiers[i] = 1.0f;
|
||||
@@ -180,7 +205,7 @@ ThreatManager::ThreatManager(Unit* owner) : _owner(owner), _ownerCanHaveThreatLi
|
||||
ThreatManager::~ThreatManager()
|
||||
{
|
||||
ASSERT(_myThreatListEntries.empty(), "ThreatManager::~ThreatManager - %s: we still have %zu things threatening us, one of them is %s.", _owner->GetGUID().ToString().c_str(), _myThreatListEntries.size(), _myThreatListEntries.begin()->first.ToString().c_str());
|
||||
ASSERT(_sortedThreatList.empty(), "ThreatManager::~ThreatManager - %s: we still have %zu things threatening us, one of them is %s.", _owner->GetGUID().ToString().c_str(), _sortedThreatList.size(), (*_sortedThreatList.begin())->GetVictim()->GetGUID().ToString().c_str());
|
||||
ASSERT(_sortedThreatList->empty(), "ThreatManager::~ThreatManager - %s: we still have %zu things threatening us, one of them is %s.", _owner->GetGUID().ToString().c_str(), _sortedThreatList->size(), (*_sortedThreatList->begin())->GetVictim()->GetGUID().ToString().c_str());
|
||||
ASSERT(_threatenedByMe.empty(), "ThreatManager::~ThreatManager - %s: we are still threatening %zu things, one of them is %s.", _owner->GetGUID().ToString().c_str(), _threatenedByMe.size(), _threatenedByMe.begin()->first.ToString().c_str());
|
||||
}
|
||||
|
||||
@@ -219,7 +244,7 @@ Unit* ThreatManager::GetLastVictim() const
|
||||
|
||||
Unit* ThreatManager::GetAnyTarget() const
|
||||
{
|
||||
for (ThreatReference const* ref : _sortedThreatList)
|
||||
for (ThreatReference const* ref : *_sortedThreatList)
|
||||
if (!ref->IsOffline())
|
||||
return ref->GetVictim();
|
||||
return nullptr;
|
||||
@@ -228,8 +253,8 @@ Unit* ThreatManager::GetAnyTarget() const
|
||||
bool ThreatManager::IsThreatListEmpty(bool includeOffline) const
|
||||
{
|
||||
if (includeOffline)
|
||||
return _sortedThreatList.empty();
|
||||
for (ThreatReference const* ref : _sortedThreatList)
|
||||
return _sortedThreatList->empty();
|
||||
for (ThreatReference const* ref : *_sortedThreatList)
|
||||
if (ref->IsAvailable())
|
||||
return false;
|
||||
return true;
|
||||
@@ -252,11 +277,44 @@ float ThreatManager::GetThreat(Unit const* who, bool includeOffline) const
|
||||
return (includeOffline || it->second->IsAvailable()) ? it->second->GetThreat() : 0.0f;
|
||||
}
|
||||
|
||||
size_t ThreatManager::GetThreatListSize() const
|
||||
{
|
||||
return _sortedThreatList->size();
|
||||
}
|
||||
|
||||
Trinity::IteratorPair<ThreatManager::ThreatListIterator, std::nullptr_t> ThreatManager::GetUnsortedThreatList() const
|
||||
{
|
||||
auto itr = _myThreatListEntries.begin();
|
||||
auto end = _myThreatListEntries.end();
|
||||
std::function<ThreatReference const* ()> generator = [itr, end]() mutable -> ThreatReference const*
|
||||
{
|
||||
if (itr == end)
|
||||
return nullptr;
|
||||
|
||||
return (itr++)->second;
|
||||
};
|
||||
return { ThreatListIterator{ std::move(generator) }, nullptr };
|
||||
}
|
||||
|
||||
Trinity::IteratorPair<ThreatManager::ThreatListIterator, std::nullptr_t> ThreatManager::GetSortedThreatList() const
|
||||
{
|
||||
auto itr = _sortedThreatList->ordered_begin();
|
||||
auto end = _sortedThreatList->ordered_end();
|
||||
std::function<ThreatReference const* ()> generator = [itr, end]() mutable -> ThreatReference const*
|
||||
{
|
||||
if (itr == end)
|
||||
return nullptr;
|
||||
|
||||
return *(itr++);
|
||||
};
|
||||
return { ThreatListIterator{ std::move(generator) }, nullptr };
|
||||
}
|
||||
|
||||
std::vector<ThreatReference*> ThreatManager::GetModifiableThreatList()
|
||||
{
|
||||
std::vector<ThreatReference*> list;
|
||||
list.reserve(_myThreatListEntries.size());
|
||||
for (auto it = _sortedThreatList.ordered_begin(), end = _sortedThreatList.ordered_end(); it != end; ++it)
|
||||
for (auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end(); it != end; ++it)
|
||||
list.push_back(const_cast<ThreatReference*>(*it));
|
||||
return list;
|
||||
}
|
||||
@@ -388,7 +446,7 @@ void ThreatManager::AddThreat(Unit* target, float amount, SpellInfo const* spell
|
||||
}
|
||||
|
||||
// ok, we're now in combat - create the threat list reference and push it to the respective managers
|
||||
ThreatReference* ref = new ThreatReference(this, target);
|
||||
ThreatReference* ref = new ThreatReferenceImpl(this, target);
|
||||
PutThreatListRef(target->GetGUID(), ref);
|
||||
target->GetThreatManager().PutThreatenedByMeRef(_owner->GetGUID(), ref);
|
||||
|
||||
@@ -411,10 +469,10 @@ void ThreatManager::ScaleThreat(Unit* target, float factor)
|
||||
|
||||
void ThreatManager::MatchUnitThreatToHighestThreat(Unit* target)
|
||||
{
|
||||
if (_sortedThreatList.empty())
|
||||
if (_sortedThreatList->empty())
|
||||
return;
|
||||
|
||||
auto it = _sortedThreatList.ordered_begin(), end = _sortedThreatList.ordered_end();
|
||||
auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
|
||||
ThreatReference const* highest = *it;
|
||||
if (!highest->IsAvailable())
|
||||
return;
|
||||
@@ -523,7 +581,7 @@ void ThreatManager::UpdateVictim()
|
||||
|
||||
ThreatReference const* ThreatManager::ReselectVictim()
|
||||
{
|
||||
if (_sortedThreatList.empty())
|
||||
if (_sortedThreatList->empty())
|
||||
return nullptr;
|
||||
|
||||
for (auto const& pair : _myThreatListEntries)
|
||||
@@ -537,7 +595,7 @@ ThreatReference const* ThreatManager::ReselectVictim()
|
||||
if (oldVictimRef && oldVictimRef->IsOffline())
|
||||
oldVictimRef = nullptr;
|
||||
// in 99% of cases - we won't need to actually look at anything beyond the first element
|
||||
ThreatReference const* highest = _sortedThreatList.top();
|
||||
ThreatReference const* highest = _sortedThreatList->top();
|
||||
// if the highest reference is offline, the entire list is offline, and we indicate this
|
||||
if (!highest->IsAvailable())
|
||||
return nullptr;
|
||||
@@ -555,7 +613,7 @@ ThreatReference const* ThreatManager::ReselectVictim()
|
||||
return highest;
|
||||
// If we get here, highest threat is ranged, but below 130% of current - there might be a melee that breaks 110% below us somewhere, so now we need to actually look at the next highest element
|
||||
// luckily, this is a heap, so getting the next highest element is O(log n), and we're just gonna do that repeatedly until we've seen enough targets (or find a target)
|
||||
auto it = _sortedThreatList.ordered_begin(), end = _sortedThreatList.ordered_end();
|
||||
auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
|
||||
while (it != end)
|
||||
{
|
||||
ThreatReference const* next = *it;
|
||||
@@ -763,45 +821,33 @@ void ThreatManager::SendRemoveToClients(Unit const* victim) const
|
||||
|
||||
void ThreatManager::SendThreatListToClients(bool newHighest) const
|
||||
{
|
||||
uint32 availableReferences = 0;
|
||||
for (ThreatReference const* ref : _sortedThreatList)
|
||||
if (ref->IsAvailable())
|
||||
++availableReferences;
|
||||
auto fillSharedPacketDataAndSend = [&](auto& packet)
|
||||
{
|
||||
packet.UnitGUID = _owner->GetGUID();
|
||||
packet.ThreatList.reserve(_sortedThreatList->size());
|
||||
for (ThreatReference const* ref : *_sortedThreatList)
|
||||
{
|
||||
if (!ref->IsAvailable())
|
||||
continue;
|
||||
|
||||
WorldPackets::Combat::ThreatInfo threatInfo;
|
||||
threatInfo.UnitGUID = ref->GetVictim()->GetGUID();
|
||||
threatInfo.Threat = int64(ref->GetThreat() * 100);
|
||||
packet.ThreatList.push_back(threatInfo);
|
||||
}
|
||||
_owner->SendMessageToSet(packet.Write(), false);
|
||||
};
|
||||
|
||||
if (newHighest)
|
||||
{
|
||||
WorldPackets::Combat::HighestThreatUpdate packet;
|
||||
packet.UnitGUID = _owner->GetGUID();
|
||||
packet.HighestThreatGUID = _currentVictimRef->GetVictim()->GetGUID();
|
||||
packet.ThreatList.reserve(availableReferences);
|
||||
for (ThreatReference const* ref : _sortedThreatList)
|
||||
{
|
||||
if (!ref->IsAvailable())
|
||||
continue;
|
||||
|
||||
WorldPackets::Combat::ThreatInfo info;
|
||||
info.UnitGUID = ref->GetVictim()->GetGUID();
|
||||
info.Threat = uint32(ref->GetThreat() * 100);
|
||||
packet.ThreatList.push_back(info);
|
||||
}
|
||||
_owner->SendMessageToSet(packet.Write(), false);
|
||||
WorldPackets::Combat::HighestThreatUpdate highestThreatUpdate;
|
||||
highestThreatUpdate.HighestThreatGUID = _currentVictimRef->GetVictim()->GetGUID();
|
||||
fillSharedPacketDataAndSend(highestThreatUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPackets::Combat::ThreatUpdate packet;
|
||||
packet.UnitGUID = _owner->GetGUID();
|
||||
packet.ThreatList.reserve(availableReferences);
|
||||
for (ThreatReference const* ref : _sortedThreatList)
|
||||
{
|
||||
if (!ref->IsAvailable())
|
||||
continue;
|
||||
|
||||
WorldPackets::Combat::ThreatInfo info;
|
||||
info.UnitGUID = ref->GetVictim()->GetGUID();
|
||||
info.Threat = uint32(ref->GetThreat() * 100);
|
||||
packet.ThreatList.push_back(info);
|
||||
}
|
||||
_owner->SendMessageToSet(packet.Write(), false);
|
||||
WorldPackets::Combat::ThreatUpdate threatUpdate;
|
||||
fillSharedPacketDataAndSend(threatUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -811,7 +857,7 @@ void ThreatManager::PutThreatListRef(ObjectGuid const& guid, ThreatReference* re
|
||||
auto& inMap = _myThreatListEntries[guid];
|
||||
ASSERT(!inMap, "Duplicate threat reference at %p being inserted on %s for %s - memory leak!", ref, _owner->GetGUID().ToString().c_str(), guid.ToString().c_str());
|
||||
inMap = ref;
|
||||
ref->_handle = _sortedThreatList.push(ref);
|
||||
static_cast<ThreatReferenceImpl*>(ref)->_handle = _sortedThreatList->push(ref);
|
||||
}
|
||||
|
||||
void ThreatManager::PurgeThreatListRef(ObjectGuid const& guid)
|
||||
@@ -821,7 +867,7 @@ void ThreatManager::PurgeThreatListRef(ObjectGuid const& guid)
|
||||
return;
|
||||
ThreatReference* ref = it->second;
|
||||
_myThreatListEntries.erase(it);
|
||||
_sortedThreatList.erase(ref->_handle);
|
||||
_sortedThreatList->erase(static_cast<ThreatReferenceImpl*>(ref)->_handle);
|
||||
|
||||
if (_fixateRef == ref)
|
||||
_fixateRef = nullptr;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "IteratorPair.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "SharedDefines.h"
|
||||
#include <boost/heap/fibonacci_heap.hpp>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -81,7 +80,7 @@ struct CompareThreatLessThan
|
||||
class TC_GAME_API ThreatManager
|
||||
{
|
||||
public:
|
||||
typedef boost::heap::fibonacci_heap<ThreatReference const*, boost::heap::compare<CompareThreatLessThan>> threat_list_heap;
|
||||
class Heap;
|
||||
class ThreatListIterator;
|
||||
static const uint32 THREAT_UPDATE_INTERVAL = 1000u;
|
||||
|
||||
@@ -115,14 +114,14 @@ class TC_GAME_API ThreatManager
|
||||
bool IsThreatenedBy(Unit const* who, bool includeOffline = false) const;
|
||||
// returns ThreatReference amount if a ref exists, 0.0f otherwise
|
||||
float GetThreat(Unit const* who, bool includeOffline = false) const;
|
||||
size_t GetThreatListSize() const { return _sortedThreatList.size(); }
|
||||
size_t GetThreatListSize() const;
|
||||
// fastest of the three threat list getters - gets the threat list in "arbitrary" order
|
||||
// iterators will invalidate on adding/removing entries from the threat list; slightly less finicky than GetSorted.
|
||||
Trinity::IteratorPair<ThreatListIterator> GetUnsortedThreatList() const { return { _myThreatListEntries.begin(), _myThreatListEntries.end() }; }
|
||||
Trinity::IteratorPair<ThreatListIterator, std::nullptr_t> GetUnsortedThreatList() const;
|
||||
// slightly slower than GetUnsorted, but, well...sorted - only use it if you need the sorted property, of course
|
||||
// this iterator pair will invalidate on any modification (even indirect) of the threat list; spell casts and similar can all induce this!
|
||||
// note: current tank is NOT guaranteed to be the first entry in this list - check GetLastVictim separately if you want that!
|
||||
Trinity::IteratorPair<threat_list_heap::ordered_iterator> GetSortedThreatList() const { return { _sortedThreatList.ordered_begin(), _sortedThreatList.ordered_end() }; }
|
||||
Trinity::IteratorPair<ThreatListIterator, std::nullptr_t> GetSortedThreatList() const;
|
||||
// slowest of the three threat list getters (by far), but lets you modify the threat references - this is also sorted
|
||||
std::vector<ThreatReference*> GetModifiableThreatList();
|
||||
|
||||
@@ -198,7 +197,7 @@ class TC_GAME_API ThreatManager
|
||||
|
||||
bool _needClientUpdate;
|
||||
uint32 _updateTimer;
|
||||
threat_list_heap _sortedThreatList;
|
||||
std::unique_ptr<Heap> _sortedThreatList;
|
||||
std::unordered_map<ObjectGuid, ThreatReference*> _myThreatListEntries;
|
||||
|
||||
// AI notifies are delayed to ensure we are in a consistent state before we call out to arbitrary logic
|
||||
@@ -231,19 +230,27 @@ class TC_GAME_API ThreatManager
|
||||
|
||||
class ThreatListIterator
|
||||
{
|
||||
private:
|
||||
decltype(_myThreatListEntries)::const_iterator _it;
|
||||
private:
|
||||
std::function<ThreatReference const* ()> _generator;
|
||||
ThreatReference const* _current;
|
||||
|
||||
public:
|
||||
ThreatReference const* operator*() const { return _it->second; }
|
||||
ThreatReference const* operator->() const { return _it->second; }
|
||||
ThreatListIterator& operator++() { ++_it; return *this; }
|
||||
bool operator==(ThreatListIterator const& o) const { return _it == o._it; }
|
||||
bool operator!=(ThreatListIterator const& o) const { return _it != o._it; }
|
||||
ThreatListIterator(decltype(_it) it) : _it(it) {}
|
||||
friend ThreatManager;
|
||||
explicit ThreatListIterator(std::function<ThreatReference const* ()>&& generator)
|
||||
: _generator(std::move(generator)), _current(_generator()) {
|
||||
}
|
||||
|
||||
public:
|
||||
ThreatReference const* operator*() const { return _current; }
|
||||
ThreatReference const* operator->() const { return _current; }
|
||||
ThreatListIterator& operator++() { _current = _generator(); return *this; }
|
||||
bool operator==(ThreatListIterator const& o) const { return _current == o._current; }
|
||||
bool operator!=(ThreatListIterator const& o) const { return _current != o._current; }
|
||||
bool operator==(std::nullptr_t) const { return _current == nullptr; }
|
||||
bool operator!=(std::nullptr_t) const { return _current != nullptr; }
|
||||
};
|
||||
|
||||
friend class ThreatReference;
|
||||
friend class ThreatReferenceImpl;
|
||||
friend struct CompareThreatLessThan;
|
||||
friend class debug_commandscript;
|
||||
};
|
||||
@@ -274,16 +281,18 @@ class TC_GAME_API ThreatReference
|
||||
|
||||
void ClearThreat(); // dealloc's this
|
||||
|
||||
private:
|
||||
protected:
|
||||
static bool FlagsAllowFighting(Unit const* a, Unit const* b);
|
||||
|
||||
ThreatReference(ThreatManager* mgr, Unit* victim) :
|
||||
explicit ThreatReference(ThreatManager* mgr, Unit* victim) :
|
||||
_owner(reinterpret_cast<Creature*>(mgr->_owner)), _mgr(*mgr), _victim(victim),
|
||||
_baseAmount(0.0f), _tempModifier(0), _taunted(TAUNT_STATE_NONE)
|
||||
{
|
||||
_online = ONLINE_STATE_OFFLINE;
|
||||
}
|
||||
|
||||
virtual ~ThreatReference() = default;
|
||||
|
||||
void UnregisterAndFree();
|
||||
|
||||
bool ShouldBeOffline() const;
|
||||
@@ -291,14 +300,13 @@ class TC_GAME_API ThreatReference
|
||||
void UpdateTauntState(TauntState state = TAUNT_STATE_NONE);
|
||||
Creature* const _owner;
|
||||
ThreatManager& _mgr;
|
||||
void HeapNotifyIncreased() { _mgr._sortedThreatList.increase(_handle); }
|
||||
void HeapNotifyDecreased() { _mgr._sortedThreatList.decrease(_handle); }
|
||||
void HeapNotifyIncreased();
|
||||
void HeapNotifyDecreased();
|
||||
Unit* const _victim;
|
||||
OnlineState _online;
|
||||
float _baseAmount;
|
||||
int32 _tempModifier; // Temporary effects (auras with SPELL_AURA_MOD_TOTAL_THREAT) - set from victim's threatmanager in ThreatManager::UpdateMyTempModifiers
|
||||
TauntState _taunted;
|
||||
ThreatManager::threat_list_heap::handle_type _handle;
|
||||
|
||||
public:
|
||||
ThreatReference(ThreatReference const&) = delete;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Common.h"
|
||||
#include "Containers.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAISelector.h"
|
||||
#include "CreatureGroups.h"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ArchaeologyMgr.h"
|
||||
#include "Battleground.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "CreatureAISelector.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DBCStores.h"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "CombatPackets.h"
|
||||
#include "Common.h"
|
||||
#include "ConditionMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "CreatureGroups.h"
|
||||
@@ -88,6 +89,7 @@
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include <cmath>
|
||||
#include <queue>
|
||||
|
||||
float baseMoveSpeed[MAX_MOVE_TYPE] =
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <boost/accumulators/statistics/variance.hpp>
|
||||
#include <boost/accumulators/accumulators.hpp>
|
||||
#include <boost/accumulators/statistics.hpp>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
|
||||
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recvData*/)
|
||||
{
|
||||
@@ -845,7 +846,7 @@ void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
|
||||
serverTime = clockDelta + clientTime
|
||||
*/
|
||||
int64 clockDelta = (int64)(serverTimeAtSent + lagDelay) - (int64)clientTimestamp;
|
||||
_timeSyncClockDeltaQueue.push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
|
||||
_timeSyncClockDeltaQueue->push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
|
||||
ComputeNewClockDelta();
|
||||
}
|
||||
|
||||
@@ -858,19 +859,18 @@ void WorldSession::ComputeNewClockDelta()
|
||||
|
||||
accumulator_set<uint32, features<tag::mean, tag::median, tag::variance(lazy)> > latencyAccumulator;
|
||||
|
||||
for (auto pair : _timeSyncClockDeltaQueue)
|
||||
latencyAccumulator(pair.second);
|
||||
for (auto [_, roundTripDuration] : *_timeSyncClockDeltaQueue)
|
||||
latencyAccumulator(roundTripDuration);
|
||||
|
||||
uint32 latencyMedian = static_cast<uint32>(std::round(median(latencyAccumulator)));
|
||||
uint32 latencyStandardDeviation = static_cast<uint32>(std::round(sqrt(variance(latencyAccumulator))));
|
||||
|
||||
accumulator_set<int64, features<tag::mean> > clockDeltasAfterFiltering;
|
||||
uint32 sampleSizeAfterFiltering = 0;
|
||||
for (auto pair : _timeSyncClockDeltaQueue)
|
||||
for (auto [clockDelta, roundTripDuration] : *_timeSyncClockDeltaQueue)
|
||||
{
|
||||
if (pair.second < latencyStandardDeviation + latencyMedian)
|
||||
{
|
||||
clockDeltasAfterFiltering(pair.first);
|
||||
if (roundTripDuration < latencyStandardDeviation + latencyMedian) {
|
||||
clockDeltasAfterFiltering(clockDelta);
|
||||
sampleSizeAfterFiltering++;
|
||||
}
|
||||
}
|
||||
@@ -882,8 +882,5 @@ void WorldSession::ComputeNewClockDelta()
|
||||
_timeSyncClockDelta = meanClockDelta;
|
||||
}
|
||||
else if (_timeSyncClockDelta == 0)
|
||||
{
|
||||
std::pair<int64, uint32> back = _timeSyncClockDeltaQueue.back();
|
||||
_timeSyncClockDelta = back.first;
|
||||
}
|
||||
_timeSyncClockDelta = _timeSyncClockDeltaQueue->back().first;
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "BattlefieldMgr.h"
|
||||
#include "Battleground.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DynamicTree.h"
|
||||
@@ -53,6 +54,7 @@
|
||||
#include "World.h"
|
||||
#include "WorldStateMgr.h"
|
||||
#include "WorldStatePackets.h"
|
||||
#include <boost/heap/fibonacci_heap.hpp>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
@@ -65,6 +67,18 @@ GridState* si_GridStates[MAX_GRID_STATE];
|
||||
ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), DefaultWeather(nullptr), WeatherId(WEATHER_STATE_FINE),
|
||||
Intensity(0.0f) { }
|
||||
|
||||
struct RespawnInfoWithHandle;
|
||||
struct RespawnListContainer : boost::heap::fibonacci_heap<RespawnInfoWithHandle*, boost::heap::compare<CompareRespawnInfo>>
|
||||
{
|
||||
};
|
||||
|
||||
struct RespawnInfoWithHandle : RespawnInfo
|
||||
{
|
||||
explicit RespawnInfoWithHandle(RespawnInfo const& other) : RespawnInfo(other) { }
|
||||
|
||||
RespawnListContainer::handle_type handle;
|
||||
};
|
||||
|
||||
RespawnInfo::~RespawnInfo() = default;
|
||||
|
||||
Map::~Map()
|
||||
@@ -125,7 +139,7 @@ m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
|
||||
m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD),
|
||||
m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transports.end()),
|
||||
i_gridExpiry(expiry), m_terrain(sTerrainMgr.LoadTerrain(id)), m_forceEnabledNavMeshFilterFlags(0), m_forceDisabledNavMeshFilterFlags(0),
|
||||
i_scriptLock(false), _respawnCheckTimer(0)
|
||||
i_scriptLock(false), _respawnTimes(std::make_unique<RespawnListContainer>()), _respawnCheckTimer(0)
|
||||
{
|
||||
for (uint32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x)
|
||||
{
|
||||
@@ -1874,7 +1888,7 @@ void Map::Respawn(RespawnInfo* info, CharacterDatabaseTransaction dbTrans)
|
||||
if (info->respawnTime <= GameTime::GetGameTime())
|
||||
return;
|
||||
info->respawnTime = GameTime::GetGameTime();
|
||||
_respawnTimes.increase(info->handle);
|
||||
_respawnTimes->increase(static_cast<RespawnInfoWithHandle*>(info)->handle);
|
||||
SaveRespawnInfoDB(*info, dbTrans);
|
||||
}
|
||||
|
||||
@@ -1928,8 +1942,8 @@ bool Map::AddRespawnInfo(RespawnInfo const& info)
|
||||
else
|
||||
ASSERT(false, "Invalid respawn info for spawn id (%u,%u) being inserted", uint32(info.type), info.spawnId);
|
||||
|
||||
RespawnInfo* ri = new RespawnInfo(info);
|
||||
ri->handle = _respawnTimes.push(ri);
|
||||
RespawnInfoWithHandle* ri = new RespawnInfoWithHandle(info);
|
||||
ri->handle = _respawnTimes->push(ri);
|
||||
bySpawnIdMap.emplace(ri->spawnId, ri);
|
||||
return true;
|
||||
}
|
||||
@@ -1960,9 +1974,9 @@ RespawnInfo* Map::GetRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawn
|
||||
|
||||
void Map::UnloadAllRespawnInfos() // delete everything from memory
|
||||
{
|
||||
for (RespawnInfo* info : _respawnTimes)
|
||||
for (RespawnInfo* info : *_respawnTimes)
|
||||
delete info;
|
||||
_respawnTimes.clear();
|
||||
_respawnTimes->clear();
|
||||
_creatureRespawnTimesBySpawnId.clear();
|
||||
_gameObjectRespawnTimesBySpawnId.clear();
|
||||
}
|
||||
@@ -1980,7 +1994,7 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, CharacterDatabaseTransaction dbTr
|
||||
spawnMap.erase(it);
|
||||
|
||||
// respawn heap
|
||||
_respawnTimes.erase(info->handle);
|
||||
_respawnTimes->erase(static_cast<RespawnInfoWithHandle*>(info)->handle);
|
||||
|
||||
// database
|
||||
DeleteRespawnInfoFromDB(info->type, info->spawnId, dbTrans);
|
||||
@@ -2029,16 +2043,16 @@ void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gr
|
||||
void Map::ProcessRespawns()
|
||||
{
|
||||
time_t now = GameTime::GetGameTime();
|
||||
while (!_respawnTimes.empty())
|
||||
while (!_respawnTimes->empty())
|
||||
{
|
||||
RespawnInfo* next = _respawnTimes.top();
|
||||
RespawnInfoWithHandle* next = _respawnTimes->top();
|
||||
if (now < next->respawnTime) // done for this tick
|
||||
break;
|
||||
|
||||
if (uint32 poolId = sPoolMgr->IsPartOfAPool(next->type, next->spawnId)) // is this part of a pool?
|
||||
{ // if yes, respawn will be handled by (external) pooling logic, just delete the respawn time
|
||||
// step 1: remove entry from maps to avoid it being reachable by outside logic
|
||||
_respawnTimes.pop();
|
||||
_respawnTimes->pop();
|
||||
GetRespawnMapForType(next->type).erase(next->spawnId);
|
||||
|
||||
// step 2: tell pooling logic to do its thing
|
||||
@@ -2051,7 +2065,7 @@ void Map::ProcessRespawns()
|
||||
else if (CheckRespawn(next)) // see if we're allowed to respawn
|
||||
{ // ok, respawn
|
||||
// step 1: remove entry from maps to avoid it being reachable by outside logic
|
||||
_respawnTimes.pop();
|
||||
_respawnTimes->pop();
|
||||
GetRespawnMapForType(next->type).erase(next->spawnId);
|
||||
|
||||
// step 2: do the respawn, which involves external logic
|
||||
@@ -2063,7 +2077,7 @@ void Map::ProcessRespawns()
|
||||
}
|
||||
else if (!next->respawnTime)
|
||||
{ // just remove this respawn entry without rescheduling
|
||||
_respawnTimes.pop();
|
||||
_respawnTimes->pop();
|
||||
GetRespawnMapForType(next->type).erase(next->spawnId);
|
||||
RemoveRespawnTime(next->type, next->spawnId, nullptr, true);
|
||||
delete next;
|
||||
@@ -2071,7 +2085,7 @@ void Map::ProcessRespawns()
|
||||
else
|
||||
{ // new respawn time, update heap position
|
||||
ASSERT(now < next->respawnTime); // infinite loop guard
|
||||
_respawnTimes.decrease(next->handle);
|
||||
_respawnTimes->decrease(next->handle);
|
||||
SaveRespawnInfoDB(*next);
|
||||
}
|
||||
}
|
||||
@@ -2759,8 +2773,8 @@ void InstanceMap::Update(uint32 t_diff)
|
||||
{
|
||||
Map::Update(t_diff);
|
||||
|
||||
if (i_data)
|
||||
i_data->Update(t_diff);
|
||||
if (i_data)
|
||||
i_data->Update(t_diff);
|
||||
}
|
||||
|
||||
void InstanceMap::RemovePlayerFromMap(Player* player, bool remove)
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "WorldStateDefines.h"
|
||||
#include "Transaction.h"
|
||||
#include "Weather.h"
|
||||
#include <boost/heap/fibonacci_heap.hpp>
|
||||
#include <bitset>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
@@ -118,8 +117,7 @@ struct CompareRespawnInfo
|
||||
bool operator()(RespawnInfo const* a, RespawnInfo const* b) const;
|
||||
};
|
||||
using ZoneDynamicInfoMap = std::unordered_map<uint32 /*zoneId*/, ZoneDynamicInfo>;
|
||||
using RespawnListContainer = boost::heap::fibonacci_heap<RespawnInfo*, boost::heap::compare<CompareRespawnInfo>>;
|
||||
using RespawnListHandle = RespawnListContainer::handle_type;
|
||||
struct RespawnListContainer;
|
||||
using RespawnInfoMap = std::unordered_map<ObjectGuid::LowType, RespawnInfo*>;
|
||||
struct TC_GAME_API RespawnInfo
|
||||
{
|
||||
@@ -130,7 +128,6 @@ struct TC_GAME_API RespawnInfo
|
||||
uint32 entry;
|
||||
time_t respawnTime;
|
||||
uint32 gridId;
|
||||
RespawnListHandle handle;
|
||||
};
|
||||
inline bool CompareRespawnInfo::operator()(RespawnInfo const* a, RespawnInfo const* b) const
|
||||
{
|
||||
@@ -700,7 +697,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
m_activeNonPlayers.erase(obj);
|
||||
}
|
||||
|
||||
RespawnListContainer _respawnTimes;
|
||||
std::unique_ptr<RespawnListContainer> _respawnTimes;
|
||||
RespawnInfoMap _creatureRespawnTimesBySpawnId;
|
||||
RespawnInfoMap _gameObjectRespawnTimesBySpawnId;
|
||||
RespawnInfoMap& GetRespawnMapForType(SpawnObjectType type)
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "Define.h"
|
||||
#include "EnumFlag.h"
|
||||
#include "FlatSet.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <map>
|
||||
|
||||
class PhasingHandler;
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
typename Container::iterator Iterator;
|
||||
bool Erased;
|
||||
};
|
||||
typedef boost::container::flat_set<PhaseRef> PhaseContainer;
|
||||
using PhaseContainer = Trinity::Containers::FlatSet<PhaseRef>;
|
||||
typedef std::map<uint32, VisibleMapIdRef> VisibleMapIdContainer;
|
||||
typedef std::map<uint32, UiMapPhaseIdRef> UiMapPhaseIdContainer;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define PacketUtilities_h__
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
#include <short_alloc/short_alloc.h>
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
@@ -31,21 +32,49 @@ namespace WorldPackets
|
||||
/**
|
||||
* Utility class for automated prevention of loop counter spoofing in client packets
|
||||
*/
|
||||
template<typename T, std::size_t N = 1000 /*select a sane default limit*/>
|
||||
template<typename T, std::size_t N>
|
||||
class Array
|
||||
{
|
||||
typedef std::vector<T> storage_type;
|
||||
|
||||
typedef typename storage_type::value_type value_type;
|
||||
typedef typename storage_type::size_type size_type;
|
||||
typedef typename storage_type::reference reference;
|
||||
typedef typename storage_type::const_reference const_reference;
|
||||
typedef typename storage_type::iterator iterator;
|
||||
typedef typename storage_type::const_iterator const_iterator;
|
||||
|
||||
public:
|
||||
Array() : _limit(N) { }
|
||||
Array(size_type limit) : _limit(limit) { }
|
||||
using allocator_type = short_alloc::short_alloc<T, (N * sizeof(T) + (alignof(std::max_align_t) - 1)) & ~(alignof(std::max_align_t) - 1)>;
|
||||
using arena_type = typename allocator_type::arena_type;
|
||||
|
||||
using storage_type = std::vector<T, allocator_type>;
|
||||
|
||||
using max_capacity = std::integral_constant<std::size_t, N>;
|
||||
|
||||
using value_type = typename storage_type::value_type;
|
||||
using size_type = typename storage_type::size_type;
|
||||
using pointer = typename storage_type::pointer;
|
||||
using const_pointer = typename storage_type::const_pointer;
|
||||
using reference = typename storage_type::reference;
|
||||
using const_reference = typename storage_type::const_reference;
|
||||
using iterator = typename storage_type::iterator;
|
||||
using const_iterator = typename storage_type::const_iterator;
|
||||
|
||||
Array() : _storage(_data) {}
|
||||
|
||||
Array(Array const& other) : Array()
|
||||
{
|
||||
for (T const& element : other)
|
||||
_storage.push_back(element);
|
||||
}
|
||||
|
||||
Array(Array&& other) noexcept = delete;
|
||||
|
||||
Array& operator=(Array const& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
_storage.clear();
|
||||
for (T const& element : other)
|
||||
_storage.push_back(element);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array& operator=(Array&& other) noexcept = delete;
|
||||
|
||||
iterator begin() { return _storage.begin(); }
|
||||
const_iterator begin() const { return _storage.begin(); }
|
||||
@@ -53,6 +82,9 @@ namespace WorldPackets
|
||||
iterator end() { return _storage.end(); }
|
||||
const_iterator end() const { return _storage.end(); }
|
||||
|
||||
pointer data() { return _storage.data(); }
|
||||
const_pointer data() const { return _storage.data(); }
|
||||
|
||||
size_type size() const { return _storage.size(); }
|
||||
bool empty() const { return _storage.empty(); }
|
||||
|
||||
@@ -61,39 +93,48 @@ namespace WorldPackets
|
||||
|
||||
void resize(size_type newSize)
|
||||
{
|
||||
if (newSize > _limit)
|
||||
throw PacketArrayMaxCapacityException(newSize, _limit);
|
||||
if (newSize > max_capacity::value)
|
||||
throw PacketArrayMaxCapacityException(newSize, max_capacity::value);
|
||||
|
||||
_storage.resize(newSize);
|
||||
}
|
||||
|
||||
void reserve(size_type newSize)
|
||||
{
|
||||
if (newSize > _limit)
|
||||
throw PacketArrayMaxCapacityException(newSize, _limit);
|
||||
|
||||
_storage.reserve(newSize);
|
||||
}
|
||||
|
||||
void push_back(value_type const& value)
|
||||
{
|
||||
if (_storage.size() >= _limit)
|
||||
throw PacketArrayMaxCapacityException(_storage.size() + 1, _limit);
|
||||
if (_storage.size() >= max_capacity::value)
|
||||
throw PacketArrayMaxCapacityException(_storage.size() + 1, max_capacity::value);
|
||||
|
||||
_storage.push_back(value);
|
||||
}
|
||||
|
||||
void push_back(value_type&& value)
|
||||
{
|
||||
if (_storage.size() >= _limit)
|
||||
throw PacketArrayMaxCapacityException(_storage.size() + 1, _limit);
|
||||
if (_storage.size() >= max_capacity::value)
|
||||
throw PacketArrayMaxCapacityException(_storage.size() + 1, max_capacity::value);
|
||||
|
||||
_storage.push_back(std::forward<value_type>(value));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
T& emplace_back(Args&&... args)
|
||||
{
|
||||
_storage.emplace_back(std::forward<Args>(args)...);
|
||||
return _storage.back();
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return _storage.erase(first, last);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_storage.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
arena_type _data;
|
||||
storage_type _storage;
|
||||
size_type _limit;
|
||||
};
|
||||
|
||||
void CheckCompactArrayMaskOverflow(std::size_t index, std::size_t limit);
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSocket.h"
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include <zlib.h>
|
||||
|
||||
namespace {
|
||||
@@ -136,7 +137,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
|
||||
expireTime(60000), // 1 min after socket loss, session is deleted
|
||||
forceExit(false),
|
||||
m_currentBankerGUID(),
|
||||
_timeSyncClockDeltaQueue(6),
|
||||
_timeSyncClockDeltaQueue(std::make_unique<boost::circular_buffer<std::pair<int64, uint32>>>(6)),
|
||||
_timeSyncClockDelta(0),
|
||||
_pendingTimeSyncRequests(),
|
||||
_gameClient(new GameClient(this))
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "SharedDefines.h"
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include <boost/circular_buffer_fwd.hpp>
|
||||
|
||||
class BigNumber;
|
||||
class Creature;
|
||||
@@ -1415,7 +1415,7 @@ class TC_GAME_API WorldSession
|
||||
bool forceExit;
|
||||
ObjectGuid m_currentBankerGUID;
|
||||
|
||||
boost::circular_buffer<std::pair<int64, uint32>> _timeSyncClockDeltaQueue; // first member: clockDelta. Second member: latency of the packet exchange that was used to compute that clockDelta.
|
||||
std::unique_ptr<boost::circular_buffer<std::pair<int64, uint32>>> _timeSyncClockDeltaQueue; // first member: clockDelta. Second member: latency of the packet exchange that was used to compute that clockDelta.
|
||||
int64 _timeSyncClockDelta;
|
||||
void ComputeNewClockDelta();
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Battleground.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Common.h"
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DB2Stores.h"
|
||||
@@ -4807,7 +4808,7 @@ static std::pair<int32, SpellHealPredictionType> CalcPredictedHealing(SpellInfo
|
||||
points += unitCaster->SpellHealingBonusDone(target,
|
||||
spellInfo, spellEffectInfo.CalcValue(unitCaster, nullptr, target),
|
||||
DIRECT_DAMAGE, i, 1, spell);
|
||||
|
||||
|
||||
if (target != unitCaster && (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER || spellEffectInfo.TargetB.GetTarget() == TARGET_UNIT_CASTER))
|
||||
type = SPELL_HEAL_PREDICTION_TARGET_AND_CASTER; // Binding Heal-like spells
|
||||
else if (spellEffectInfo.TargetA.GetCheckType() == TARGET_CHECK_PARTY || spellEffectInfo.TargetB.GetCheckType() == TARGET_CHECK_PARTY)
|
||||
@@ -4816,7 +4817,7 @@ static std::pair<int32, SpellHealPredictionType> CalcPredictedHealing(SpellInfo
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (withPeriodic)
|
||||
{
|
||||
switch (spellEffectInfo.ApplyAuraName)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "CellImpl.h"
|
||||
#include "Chat.h"
|
||||
#include "Common.h"
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DBCStores.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
@@ -402,7 +403,7 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket const*
|
||||
case TEXT_RANGE_PERSONAL:
|
||||
if (!whisperTarget || !whisperTarget->IsPlayer())
|
||||
return;
|
||||
|
||||
|
||||
whisperTarget->ToPlayer()->SendDirectMessage(data);
|
||||
return;
|
||||
case TEXT_RANGE_NORMAL:
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "CharacterDatabaseCleaner.h"
|
||||
#include "Chat.h"
|
||||
#include "Config.h"
|
||||
#include "Containers.h"
|
||||
#include "CreatureAIRegistry.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "CreatureTextMgr.h"
|
||||
|
||||
@@ -42,12 +42,11 @@ EndScriptData */
|
||||
#include "VMapManager2.h"
|
||||
#include "World.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/filesystem/directory.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <numeric>
|
||||
|
||||
class server_commandscript : public CommandScript
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "baradin_hold.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MoveSpline.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "baradin_hold.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "baradin_hold.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Map.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "CommonPredicates.h"
|
||||
#include "Creature.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "Creature.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "MotionMaster.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
+1
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "blackrock_depths.h"
|
||||
#include "Containers.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "Group.h"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "CommonPredicates.h"
|
||||
#include "Containers.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "Map.h"
|
||||
#include "MoveSpline.h"
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "CommonPredicates.h"
|
||||
#include "Containers.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
@@ -203,7 +204,7 @@ struct boss_chimaeron : public BossAI
|
||||
if (Creature* nefarius = instance->GetCreature(DATA_LORD_VICTOR_NEFARIUS_GENERIC))
|
||||
if (nefarius->IsAIEnabled())
|
||||
nefarius->AI()->DoAction(ACTION_CHIMAERON_DEFEATED);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
@@ -244,7 +245,7 @@ struct boss_chimaeron : public BossAI
|
||||
{
|
||||
case SPELL_MASSACRE:
|
||||
{
|
||||
// Hotfix (2011-01-05): "Chimaeron now resets his melee attack cycle after each Massacre and removes the Double Attack buff."
|
||||
// Hotfix (2011-01-05): "Chimaeron now resets his melee attack cycle after each Massacre and removes the Double Attack buff."
|
||||
me->RemoveAurasDueToSpell(SPELL_DOUBLE_ATTACK);
|
||||
me->resetAttackTimer();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
+1
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "blackwing_descent.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "CommonPredicates.h"
|
||||
#include "DBCStores.h"
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
@@ -328,7 +329,7 @@ struct boss_omnotron_defense_system : public BossAI
|
||||
golem->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
instance->SetBossState(DATA_OMNOTRON_DEFENSE_SYSTEM, FAIL);
|
||||
RemoveDebuffsFromRaid();
|
||||
summons.DespawnAll();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "molten_core.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "GameEventMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "deadmines.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "deadmines.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "GridNotifiers.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "Containers.h"
|
||||
#include "deadmines.h"
|
||||
#include "GameObject.h"
|
||||
#include "InstanceScript.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "gilneas.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "CombatAI.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MoveSplineInit.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
@@ -23,6 +23,7 @@ SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "karazhan.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
@@ -23,6 +23,7 @@ SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "karazhan.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
@@ -23,6 +23,7 @@ SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "karazhan.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "scarlet_monastery.h"
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "Group.h"
|
||||
#include "InstanceScript.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "shadowfang_keep.h"
|
||||
#include "Containers.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
@@ -75,7 +76,7 @@ enum Spells
|
||||
|
||||
SPELL_SUMMON_SPIRIT_OF_RAZORCLAW_THE_BUTCHER_DUMMY = 93921, // Dummy Summon
|
||||
SPELL_SUMMON_SPIRIT_OF_RAZORCLAW_THE_BUTCHER_SUMMON = 93924,
|
||||
|
||||
|
||||
SPELL_SUMMON_SPIRIT_OF_RETHILGORE_DUMMY = 93925, // Dummy Summon
|
||||
SPELL_SUMMON_SPIRIT_OF_RETHILGORE_SUMMON = 93927,
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "shadowfang_keep.h"
|
||||
#include "Containers.h"
|
||||
#include "GameEventMgr.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "shadowfang_keep.h"
|
||||
#include "Containers.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "throne_of_the_tides.h"
|
||||
#include "Containers.h"
|
||||
#include "GameObject.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "ObjectMgr.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "throne_of_the_tides.h"
|
||||
#include "AreaBoundary.h"
|
||||
#include "Containers.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "InstanceScript.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "zulgurub.h"
|
||||
#include "GridNotifiers.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "GridNotifiers.h"
|
||||
#include "Containers.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Containers.h"
|
||||
#include "DynamicObject.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "CellImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "GameEventMgr.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Battlefield/BattlefieldTB.h"
|
||||
#include "Containers.h"
|
||||
#include "DBCStores.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "Containers.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "CombatAI.h"
|
||||
@@ -307,7 +308,7 @@ struct npc_westfall_hobo_witness : public ScriptedAI
|
||||
me->SetFacingToObject(player);
|
||||
|
||||
uint16 slot = player->FindQuestSlot(QUEST_MURDER_WAS_THE_CASE_THAT_THEY_GAVE_ME);
|
||||
|
||||
|
||||
if (player->GetQuestSlotCounter(slot, CLUE1) == 0)
|
||||
{
|
||||
player->CastSpell(player, SPELL_HOBO_INFORMATION_1);
|
||||
@@ -315,7 +316,7 @@ struct npc_westfall_hobo_witness : public ScriptedAI
|
||||
me->DespawnOrUnsummon(12s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (player->GetQuestSlotCounter(slot, CLUE2) == 0)
|
||||
{
|
||||
player->CastSpell(player, SPELL_HOBO_INFORMATION_2);
|
||||
@@ -323,7 +324,7 @@ struct npc_westfall_hobo_witness : public ScriptedAI
|
||||
me->DespawnOrUnsummon(12s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (player->GetQuestSlotCounter(slot, CLUE3) == 0)
|
||||
{
|
||||
player->CastSpell(player, SPELL_HOBO_INFORMATION_3);
|
||||
@@ -331,7 +332,7 @@ struct npc_westfall_hobo_witness : public ScriptedAI
|
||||
me->DespawnOrUnsummon(12s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (player->GetQuestSlotCounter(slot, CLUE4) == 0)
|
||||
{
|
||||
player->CastSpell(player, SPELL_HOBO_INFORMATION_4);
|
||||
@@ -368,7 +369,7 @@ struct npc_westfall_hobo_witness : public ScriptedAI
|
||||
who->ToCreature()->AI()->DoAction(ACTION_AGGRO_HOBO_DONE);
|
||||
me->CastSpell(me, SPELL_SUMMON_RAGAMUFFIN_LOOTER);
|
||||
}
|
||||
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
ScriptedAI::Reset();
|
||||
@@ -1303,7 +1304,7 @@ enum WestFallText
|
||||
SAY_NPC_HOMELESS_STORMWIND_CITIZEN_2 = 12,
|
||||
SAY_NPC_TRANSIENT = 17,
|
||||
SAY_NPC_WEST_PLAINS_DRIFTER = 11,
|
||||
SAY_NPC_WEST_PLAINS_DRIFTER_FOLLOWER = 6
|
||||
SAY_NPC_WEST_PLAINS_DRIFTER_FOLLOWER = 6
|
||||
};
|
||||
|
||||
struct npc_westfall_westfall_stew: public ScriptedAI
|
||||
@@ -1398,10 +1399,10 @@ struct npc_westfall_homless_stormwind_citizen : public ScriptedAI
|
||||
case EVENT_START:
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
|
||||
|
||||
if (me->HasAura(SPELL_COSMETIC_SLEEP))
|
||||
me->RemoveAurasDueToSpell(SPELL_COSMETIC_SLEEP);
|
||||
|
||||
|
||||
_events.ScheduleEvent(EVENT_MOVE_TO_STEW, 2s);
|
||||
break;
|
||||
}
|
||||
@@ -1511,10 +1512,10 @@ struct npc_westfall_west_plains_drifter : public ScriptedAI
|
||||
{
|
||||
case EVENT_START:
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
|
||||
|
||||
if (me->HasAura(SPELL_COSMETIC_SLEEP))
|
||||
me->RemoveAurasDueToSpell(SPELL_COSMETIC_SLEEP);
|
||||
|
||||
|
||||
_events.ScheduleEvent(EVENT_MOVE_TO_STEW, 2s);
|
||||
break;
|
||||
case EVENT_MOVE_TO_STEW:
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "dragon_soul.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "GameObject.h"
|
||||
#include "Group.h"
|
||||
#include "InstanceScript.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "DBCStores.h"
|
||||
#include "firelands.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "firelands.h"
|
||||
#include "Containers.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "firelands.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "PassiveAI.h"
|
||||
#include "PathGenerator.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "firelands.h"
|
||||
#include "Containers.h"
|
||||
#include "DynamicObject.h"
|
||||
#include "GameObject.h"
|
||||
#include "InstanceScript.h"
|
||||
|
||||
Loaded 100 of 167 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user