Core/Misc: backported most boost changes from master branch

This commit is contained in:
Ovahlord committed 2025-02-27 23:47:52 +01:00
1 parent 66f3e78248
commit 0927c5af40
167 files changed
+1605 -484

No files matched your search

+6
View File
@@ -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!")
+1
View File
@@ -32,6 +32,7 @@ if(SERVERS)
add_subdirectory(zmqpp)
add_subdirectory(rapidjson)
add_subdirectory(efsw)
add_subdirectory(short_alloc)
endif()
if(TOOLS)
+60 -42
View File
@@ -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()
+15
View File
@@ -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})
+162
View File
@@ -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
+8 -9
View File
@@ -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__
+1
View File
@@ -21,6 +21,7 @@
#include "IoContext.h"
#include "Optional.h"
#include <boost/asio/ip/tcp.hpp>
#include <algorithm>
#include <string>
namespace Trinity
+2 -1
View File
@@ -71,7 +71,8 @@ target_link_libraries(common
openssl
valgrind
threads
jemalloc)
jemalloc
short_alloc)
add_dependencies(common revision_data.h)
+1
View File
@@ -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>
+105
View File
@@ -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
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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;
+3 -2
View File
@@ -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);
}
+1 -2
View File
@@ -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
{
+11 -11
View File
@@ -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
+134 -9
View File
@@ -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
+2 -6
View File
@@ -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;
+13 -48
View File
@@ -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.
-1
View File
@@ -22,7 +22,6 @@
#include "Optional.h"
#include "Random.h"
#include <algorithm>
#include <chrono>
#include <functional>
#include <vector>
#include <queue>
+2 -2
View File
@@ -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...>>
{
};
+494
View File
@@ -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
+2 -64
View File
@@ -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
+4 -4
View File
@@ -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>
+88 -4
View File
@@ -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)
+8 -86
View File
@@ -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
+1
View File
@@ -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;
};
+93 -47
View File
@@ -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;
+28 -20
View File
@@ -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"
+2
View File
@@ -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] =
{
+8 -11
View File
@@ -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;
}
+29 -15
View File
@@ -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)
+2 -5
View File
@@ -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)
+2 -2
View File
@@ -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);
+2 -1
View File
@@ -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))
+2 -2
View File
@@ -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();
+3 -2
View File
@@ -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)
+2 -1
View File
@@ -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:
+1
View File
@@ -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"
+2 -3
View File
@@ -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"
@@ -17,6 +17,7 @@
#include "ScriptMgr.h"
#include "blackrock_depths.h"
#include "Containers.h"
#include "GameObjectAI.h"
#include "GridNotifiers.h"
#include "Group.h"
@@ -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"
@@ -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"
@@ -17,6 +17,7 @@
#include "blackwing_descent.h"
#include "ScriptMgr.h"
#include "Containers.h"
#include "ObjectMgr.h"
#include "CommonPredicates.h"
#include "DBCStores.h"
@@ -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"
@@ -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