diff options
Diffstat (limited to 'src')
166 files changed, 5271 insertions, 1300 deletions
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 05cbe51b15d..e691b9527a5 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -25,6 +25,8 @@ if( SERVERS ) add_subdirectory(game) add_subdirectory(collision) add_subdirectory(authserver) + add_subdirectory(ipc) + add_subdirectory(bnetserver) add_subdirectory(scripts) add_subdirectory(worldserver) else() diff --git a/src/server/authserver/Authentication/AuthCodes.h b/src/server/authserver/Authentication/AuthCodes.h index c42a11007d8..bc7f0c43f17 100644 --- a/src/server/authserver/Authentication/AuthCodes.h +++ b/src/server/authserver/Authentication/AuthCodes.h @@ -104,63 +104,6 @@ enum GameAccountFlags GAMEACCOUNT_FLAG_DEATH_KNIGHT_OK = 0x20000000, }; -namespace Battlenet -{ - enum AuthResult - { - AUTH_OK = 0, - AUTH_INTERNAL_ERROR = 100, - AUTH_CORRUPTED_MODULE = 101, - AUTH_NO_BATTLETAGS = 102, - AUTH_BAD_SERVER_PROOF = 103, - AUTH_UNKNOWN_ACCOUNT = 104, - AUTH_CLOSED = 105, - AUTH_LOGIN_TIMEOUT = 106, - AUTH_NO_GAME_ACCOUNTS = 107, - AUTH_INVALID_TOKEN = 108, - AUTH_INVALID_PROGRAM = 109, - AUTH_INVALID_OS = 110, - AUTH_UNSUPPORTED_LANGUAGE = 111, - AUTH_REGION_BAD_VERSION = 112, - AUTH_TEMP_OUTAGE = 113, - AUTH_CANT_DOWNLOAD_MODULE = 114, - AUTH_DUPLICATE_LOGON = 115, - AUTH_BAD_CREDENTIALS_2 = 116, - AUTH_VERSION_CHECK_SUCCEEDED = 117, - AUTH_BAD_VERSION_HASH = 118, - AUTH_CANT_RETRIEVE_PORTAL_LIST = 119, - AUTH_DARK_PORTAL_DOES_NOT_EXIST = 120, - AUTH_DARK_PORTAL_FILE_CORRUPTED = 121, - AUTH_BATTLENET_MAINTENANCE = 122, - AUTH_LOGON_TOO_FAST = 123, - AUTH_USE_GRUNT_LOGON = 124, - AUTH_NO_GAME_ACCOUNTS_IN_REGION = 140, - AUTH_ACCOUNT_LOCKED = 141, - - LOGIN_SERVER_BUSY = 200, - LOGIN_NO_GAME_ACCOUNT = 201, - LOGIN_BANNED = 202, - LOGIN_SUSPENDED = 203, - LOGIN_GAME_ACCOUNT_LOCKED = 204, - LOGIN_ALREADY_ONLINE = 205, - LOGIN_NOTIME = 206, - LOGIN_EXPIRED = 207, - LOGIN_EXPIRED_2 = 208, - LOGIN_PARENTALCONTROL = 209, - LOGIN_TRIAL_EXPIRED = 210, - LOGIN_ANTI_INDULGENCE = 211, - LOGIN_INCORRECT_REGION = 212, - LOGIN_LOCKED_ENFORCED = 213, - LOGIN_CHARGEBACK = 214, - LOGIN_IGR_WITHOUT_BNET = 215, - LOGIN_UNLOCKABLE_LOCK = 216, - LOGIN_IGR_REQUIRED = 217, - LOGIN_PAYMENT_CHANGED = 218, - LOGIN_INVALID_PAYMENT = 219, - LOGIN_INVALID_ACCOUNT_STATE = 220 - }; -} - enum ExpansionFlags { POST_BC_EXP_FLAG = 0x2, diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index ae706973ff7..b40b8c906f4 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -58,7 +58,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Authentication ${CMAKE_CURRENT_SOURCE_DIR}/Realms ${CMAKE_CURRENT_SOURCE_DIR}/Server - ${CMAKE_CURRENT_SOURCE_DIR}/Server/BattlenetPackets ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index e614b2b79fa..5f08ebe3127 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -25,8 +25,6 @@ */ #include "AuthSocketMgr.h" -#include "BattlenetManager.h" -#include "BattlenetSessionManager.h" #include "Common.h" #include "Config.h" #include "DatabaseEnv.h" @@ -117,18 +115,9 @@ int main(int argc, char** argv) return 1; } - int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); - if (bnport < 0 || bnport > 0xFFFF) - { - TC_LOG_ERROR("server.authserver", "Specified battle.net port (%d) out of allowed range (1-65535)", bnport); - StopDB(); - return 1; - } - std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); sAuthSocketMgr.StartNetwork(_ioService, bindIp, port); - sBattlenetSessionMgr.StartNetwork(_ioService, bindIp, bnport); // Set signal handlers boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); @@ -145,8 +134,6 @@ int main(int argc, char** argv) _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); _dbPingTimer.async_wait(KeepDatabaseAliveHandler); - sBattlenetMgr->Load(); - // Start the io service worker loop _ioService.run(); diff --git a/src/server/authserver/PrecompiledHeaders/authPCH.h b/src/server/authserver/PrecompiledHeaders/authPCH.h index b509f8caaa0..90424161344 100644 --- a/src/server/authserver/PrecompiledHeaders/authPCH.h +++ b/src/server/authserver/PrecompiledHeaders/authPCH.h @@ -2,9 +2,6 @@ #include "Configuration/Config.h" #include "Database/DatabaseEnv.h" #include "Log.h" -#include "BattlenetManager.h" #include "RealmList.h" #include "ByteBuffer.h" -#include "BattlenetPackets.h" #include "AuthSession.h" -#include "BattlenetSession.h" diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp index 2110dc1fecc..15302c74ac6 100644 --- a/src/server/authserver/Realms/RealmList.cpp +++ b/src/server/authserver/Realms/RealmList.cpp @@ -19,7 +19,6 @@ #include <boost/asio/ip/tcp.hpp> #include "Common.h" #include "RealmList.h" -#include "BattlenetManager.h" #include "Database/DatabaseEnv.h" #include "Util.h" @@ -78,7 +77,7 @@ void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInte } void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr, - ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build, uint8 region, uint8 battlegroup) + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build) { // Create new if not exist or update existed Realm& realm = m_realms[name]; @@ -91,15 +90,11 @@ void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address cons realm.allowedSecurityLevel = allowedSecurityLevel; realm.populationLevel = population; - // Append port to IP address. - realm.ExternalAddress = address; realm.LocalAddress = localAddr; realm.LocalSubnetMask = localSubmask; realm.port = port; realm.gamebuild = build; - realm.Region = region; - realm.Battlegroup = battlegroup; } void RealmList::UpdateIfNeed() @@ -175,11 +170,9 @@ void RealmList::UpdateRealms(bool init) uint8 allowedSecurityLevel = fields[9].GetUInt8(); float pop = fields[10].GetFloat(); uint32 build = fields[11].GetUInt32(); - uint8 region = fields[12].GetUInt8(); - uint8 battlegroup = fields[13].GetUInt8(); UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone, - (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build, region, battlegroup); + (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build); if (init) TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port); @@ -193,16 +186,3 @@ void RealmList::UpdateRealms(bool init) while (result->NextRow()); } } - -Realm const* RealmList::GetRealm(Battlenet::RealmId const& id) const -{ - auto itr = std::find_if(m_realms.begin(), m_realms.end(), [id](RealmMap::value_type const& pair) - { - return pair.second.Region == id.Region && pair.second.Battlegroup == id.Battlegroup && pair.second.m_ID == id.Index; - }); - - if (itr != m_realms.end()) - return &itr->second; - - return NULL; -} diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h index 0063b1a60c8..9d5771144a9 100644 --- a/src/server/authserver/Realms/RealmList.h +++ b/src/server/authserver/Realms/RealmList.h @@ -54,17 +54,10 @@ struct Realm AccountTypes allowedSecurityLevel; float populationLevel; uint32 gamebuild; - uint8 Region; - uint8 Battlegroup; ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; }; -namespace Battlenet -{ - struct RealmId; -} - /// Storage object for the list of realms on the server class RealmList { @@ -88,14 +81,13 @@ public: RealmMap::const_iterator begin() const { return m_realms.begin(); } RealmMap::const_iterator end() const { return m_realms.end(); } uint32 size() const { return m_realms.size(); } - Realm const* GetRealm(Battlenet::RealmId const& id) const; private: RealmList(); void UpdateRealms(bool init = false); void UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr, - ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build, uint8 region, uint8 battlegroup); + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build); RealmMap m_realms; uint32 m_UpdateInterval; diff --git a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h b/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h deleted file mode 100644 index 50ec9416ec1..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ConnectionPackets_h__ -#define ConnectionPackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - namespace Connection - { - enum Opcode - { - CMSG_PING = 0x0, - CMSG_ENABLE_ENCRYPTION = 0x5, - CMSG_LOGOUT_REQUEST = 0x6, - CMSG_DISCONNECT_REQUEST = 0x7, // Not implemented - CMSG_CONNECTION_CLOSING = 0x9, // Not implemented - - SMSG_PONG = 0x0, - SMSG_BOOM = 0x1, // Not implemented - SMSG_REGULATOR_UPDATE = 0x2, // Not implemented - SMSG_SERVER_VERSION = 0x3, // Not implemented - SMSG_STUN_SERVERS = 0x4 // Not implemented - }; - - class Pong final : public ServerPacket - { - public: - Pong() : ServerPacket(PacketHeader(SMSG_PONG, CONNECTION)) - { - } - - void Write() override { } - std::string ToString() const override; - }; - } -} - -#endif // ConnectionPackets_h__ diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist index e0ef6982353..b7dee9ac08b 100644 --- a/src/server/authserver/authserver.conf.dist +++ b/src/server/authserver/authserver.conf.dist @@ -54,13 +54,6 @@ MaxPingTime = 30 RealmServerPort = 3724 # -# BattlenetPort -# Description: TCP port to reach the auth server for battle.net connections. -# Default: 1119 - -BattlenetPort = 1119 - -# # # BindIP # Description: Bind auth server to IP/hostname diff --git a/src/server/bnetserver/Authentication/AuthCodes.cpp b/src/server/bnetserver/Authentication/AuthCodes.cpp new file mode 100644 index 00000000000..908bc30b719 --- /dev/null +++ b/src/server/bnetserver/Authentication/AuthCodes.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "AuthCodes.h" +#include <cstddef> + +namespace AuthHelper +{ + static RealmBuildInfo const PostBcAcceptedClientBuilds[] = + { + {15595, 4, 3, 4, ' '}, + {14545, 4, 2, 2, ' '}, + {13623, 4, 0, 6, 'a'}, + {13930, 3, 3, 5, 'a'}, // 3.3.5a China Mainland build + {12340, 3, 3, 5, 'a'}, + {11723, 3, 3, 3, 'a'}, + {11403, 3, 3, 2, ' '}, + {11159, 3, 3, 0, 'a'}, + {10505, 3, 2, 2, 'a'}, + {9947, 3, 1, 3, ' '}, + {8606, 2, 4, 3, ' '}, + {6141, 1, 12, 3, ' '}, + {6005, 1, 12, 2, ' '}, + {5875, 1, 12, 1, ' '}, + {0, 0, 0, 0, ' '} // terminator + }; + + RealmBuildInfo const* GetBuildInfo(int build) + { + for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i) + if (PostBcAcceptedClientBuilds[i].Build == build) + return &PostBcAcceptedClientBuilds[i]; + + return nullptr; + } + + bool IsBuildSupportingBattlenet(int build) + { + return build >= 15595; + } +} diff --git a/src/server/bnetserver/Authentication/AuthCodes.h b/src/server/bnetserver/Authentication/AuthCodes.h new file mode 100644 index 00000000000..3c3b002551c --- /dev/null +++ b/src/server/bnetserver/Authentication/AuthCodes.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * 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 _AUTHCODES_H +#define _AUTHCODES_H + +enum GameAccountFlags +{ + GAMEACCOUNT_FLAG_GM = 0x00000001, + GAMEACCOUNT_FLAG_NOKICK = 0x00000002, + GAMEACCOUNT_FLAG_COLLECTOR = 0x00000004, + GAMEACCOUNT_FLAG_WOW_TRIAL = 0x00000008, + GAMEACCOUNT_FLAG_CANCELLED = 0x00000010, + GAMEACCOUNT_FLAG_IGR = 0x00000020, + GAMEACCOUNT_FLAG_WHOLESALER = 0x00000040, + GAMEACCOUNT_FLAG_PRIVILEGED = 0x00000080, + GAMEACCOUNT_FLAG_EU_FORBID_ELV = 0x00000100, + GAMEACCOUNT_FLAG_EU_FORBID_BILLING = 0x00000200, + GAMEACCOUNT_FLAG_WOW_RESTRICTED = 0x00000400, + GAMEACCOUNT_FLAG_REFERRAL = 0x00000800, + GAMEACCOUNT_FLAG_BLIZZARD = 0x00001000, + GAMEACCOUNT_FLAG_RECURRING_BILLING = 0x00002000, + GAMEACCOUNT_FLAG_NOELECTUP = 0x00004000, + GAMEACCOUNT_FLAG_KR_CERTIFICATE = 0x00008000, + GAMEACCOUNT_FLAG_EXPANSION_COLLECTOR = 0x00010000, + GAMEACCOUNT_FLAG_DISABLE_VOICE = 0x00020000, + GAMEACCOUNT_FLAG_DISABLE_VOICE_SPEAK = 0x00040000, + GAMEACCOUNT_FLAG_REFERRAL_RESURRECT = 0x00080000, + GAMEACCOUNT_FLAG_EU_FORBID_CC = 0x00100000, + GAMEACCOUNT_FLAG_OPENBETA_DELL = 0x00200000, + GAMEACCOUNT_FLAG_PROPASS = 0x00400000, + GAMEACCOUNT_FLAG_PROPASS_LOCK = 0x00800000, + GAMEACCOUNT_FLAG_PENDING_UPGRADE = 0x01000000, + GAMEACCOUNT_FLAG_RETAIL_FROM_TRIAL = 0x02000000, + GAMEACCOUNT_FLAG_EXPANSION2_COLLECTOR = 0x04000000, + GAMEACCOUNT_FLAG_OVERMIND_LINKED = 0x08000000, + GAMEACCOUNT_FLAG_DEMOS = 0x10000000, + GAMEACCOUNT_FLAG_DEATH_KNIGHT_OK = 0x20000000, +}; + +namespace Battlenet +{ + enum AuthResult + { + AUTH_OK = 0, + AUTH_INTERNAL_ERROR = 100, + AUTH_CORRUPTED_MODULE = 101, + AUTH_NO_BATTLETAGS = 102, + AUTH_BAD_SERVER_PROOF = 103, + AUTH_UNKNOWN_ACCOUNT = 104, + AUTH_CLOSED = 105, + AUTH_LOGIN_TIMEOUT = 106, + AUTH_NO_GAME_ACCOUNTS = 107, + AUTH_INVALID_TOKEN = 108, + AUTH_INVALID_PROGRAM = 109, + AUTH_INVALID_OS = 110, + AUTH_UNSUPPORTED_LANGUAGE = 111, + AUTH_REGION_BAD_VERSION = 112, + AUTH_TEMP_OUTAGE = 113, + AUTH_CANT_DOWNLOAD_MODULE = 114, + AUTH_DUPLICATE_LOGON = 115, + AUTH_BAD_CREDENTIALS_2 = 116, + AUTH_VERSION_CHECK_SUCCEEDED = 117, + AUTH_BAD_VERSION_HASH = 118, + AUTH_CANT_RETRIEVE_PORTAL_LIST = 119, + AUTH_DARK_PORTAL_DOES_NOT_EXIST = 120, + AUTH_DARK_PORTAL_FILE_CORRUPTED = 121, + AUTH_BATTLENET_MAINTENANCE = 122, + AUTH_LOGON_TOO_FAST = 123, + AUTH_USE_GRUNT_LOGON = 124, + AUTH_NO_GAME_ACCOUNTS_IN_REGION = 140, + AUTH_ACCOUNT_LOCKED = 141, + + LOGIN_SERVER_BUSY = 200, + LOGIN_NO_GAME_ACCOUNT = 201, + LOGIN_BANNED = 202, + LOGIN_SUSPENDED = 203, + LOGIN_GAME_ACCOUNT_LOCKED = 204, + LOGIN_ALREADY_ONLINE = 205, + LOGIN_NOTIME = 206, + LOGIN_EXPIRED = 207, + LOGIN_EXPIRED_2 = 208, + LOGIN_PARENTALCONTROL = 209, + LOGIN_TRIAL_EXPIRED = 210, + LOGIN_ANTI_INDULGENCE = 211, + LOGIN_INCORRECT_REGION = 212, + LOGIN_LOCKED_ENFORCED = 213, + LOGIN_CHARGEBACK = 214, + LOGIN_IGR_WITHOUT_BNET = 215, + LOGIN_UNLOCKABLE_LOCK = 216, + LOGIN_IGR_REQUIRED = 217, + LOGIN_PAYMENT_CHANGED = 218, + LOGIN_INVALID_PAYMENT = 219, + LOGIN_INVALID_ACCOUNT_STATE = 220 + }; +} + +struct RealmBuildInfo +{ + int Build; + int MajorVersion; + int MinorVersion; + int BugfixVersion; + int HotfixVersion; +}; + +namespace AuthHelper +{ + RealmBuildInfo const* GetBuildInfo(int build); + bool IsBuildSupportingBattlenet(int build); +} + +#endif diff --git a/src/server/authserver/Server/BattlenetPacketCrypt.cpp b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp index de4cf73f71c..de4cf73f71c 100644 --- a/src/server/authserver/Server/BattlenetPacketCrypt.cpp +++ b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp diff --git a/src/server/authserver/Server/BattlenetPacketCrypt.h b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.h index dde687651d3..a09d3417dfe 100644 --- a/src/server/authserver/Server/BattlenetPacketCrypt.h +++ b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.h @@ -15,8 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __BATTLENETPACKETCRYPT_H__ -#define __BATTLENETPACKETCRYPT_H__ +#ifndef BattlenetPacketCrypt_h__ +#define BattlenetPacketCrypt_h__ #include "PacketCrypt.h" @@ -32,5 +32,5 @@ namespace Battlenet void Init(BigNumber* K) override; }; } +#endif // BattlenetPacketCrypt_h__ -#endif // __BATTLENETPACKETCRYPT_H__ diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt new file mode 100644 index 00000000000..5b854018d47 --- /dev/null +++ b/src/server/bnetserver/CMakeLists.txt @@ -0,0 +1,121 @@ +# Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +########### bnetserver ############### + +file(GLOB_RECURSE sources_authentication Authentication/*.cpp Authentication/*.h) +file(GLOB_RECURSE sources_realms Realms/*.cpp Realms/*.h) +file(GLOB_RECURSE sources_server Server/*.cpp Server/*.h) +file(GLOB_RECURSE sources_packets Packets/*.cpp Packets/*.h) +file(GLOB sources_localdir *.cpp *.h) + +if (USE_COREPCH) + set(bnetserver_PCH_HDR PrecompiledHeaders/bnetPCH.h) + set(bnetserver_PCH_SRC PrecompiledHeaders/bnetPCH.cpp) +endif() + +set(bnetserver_SRCS + ${bnetserver_SRCS} + ${sources_authentication} + ${sources_realms} + ${sources_server} + ${sources_packets} + ${sources_localdir} +) + +if( WIN32 ) + set(bnetserver_SRCS + ${bnetserver_SRCS} + ${sources_windows_Debugging} + ) + if ( MSVC ) + set(bnetserver_SRCS + ${bnetserver_SRCS} + bnetserver.rc + ) + endif () +endif() + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/zmqpp + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration + ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging + ${CMAKE_SOURCE_DIR}/src/server/shared/Packets + ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography + ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication + ${CMAKE_SOURCE_DIR}/src/server/shared/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Networking + ${CMAKE_SOURCE_DIR}/src/server/shared/Threading + ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/ipc + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Authentication + ${CMAKE_CURRENT_SOURCE_DIR}/Realms + ${CMAKE_CURRENT_SOURCE_DIR}/Server + ${CMAKE_CURRENT_SOURCE_DIR}/Packets + ${MYSQL_INCLUDE_DIR} + ${OPENSSL_INCLUDE_DIR} + ${VALGRIND_INCLUDE_DIR} + ${ZMQ_INCLUDE_DIR} +) + +add_executable(bnetserver + ${bnetserver_SRCS} + ${bnetserver_PCH_SRC} +) + +add_dependencies(bnetserver revision.h) + +if( NOT WIN32 ) + set_target_properties(bnetserver PROPERTIES + COMPILE_DEFINITIONS _TRINITY_BNET_CONFIG="${CONF_DIR}/bnetserver.conf" + ) +endif() + +target_link_libraries(bnetserver + ipc + shared + zmqpp + ${MYSQL_LIBRARY} + ${OPENSSL_LIBRARIES} + ${ZMQ_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES} +) + +if( WIN32 ) + if ( MSVC ) + add_custom_command(TARGET bnetserver + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.conf.dist ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/ + ) + elseif ( MINGW ) + add_custom_command(TARGET bnetserver + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.conf.dist ${CMAKE_BINARY_DIR}/bin/ + ) + endif() +endif() + +if( UNIX ) + install(TARGETS bnetserver DESTINATION bin) + install(FILES bnetserver.conf.dist DESTINATION ${CONF_DIR}) +elseif( WIN32 ) + install(TARGETS bnetserver DESTINATION "${CMAKE_INSTALL_PREFIX}") + install(FILES bnetserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}") +endif() + +# Generate precompiled header +if (USE_COREPCH) + add_cxx_pch(bnetserver ${bnetserver_PCH_HDR} ${bnetserver_PCH_SRC}) +endif() diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp new file mode 100644 index 00000000000..ce90019c011 --- /dev/null +++ b/src/server/bnetserver/Main.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +/** +* @file main.cpp +* @brief Authentication Server main program +* +* This file contains the main program for the +* authentication server +*/ + +#include "ComponentManager.h" +#include "ModuleManager.h" +#include "SessionManager.h" +#include "Common.h" +#include "Config.h" +#include "DatabaseEnv.h" +#include "Log.h" +#include "ProcessPriority.h" +#include "RealmList.h" +#include "SystemConfig.h" +#include "Util.h" +#include "ZmqContext.h" +#include <cstdlib> +#include <iostream> +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/program_options.hpp> +#include <openssl/opensslv.h> +#include <openssl/crypto.h> + +using boost::asio::ip::tcp; +using namespace boost::program_options; + +#ifndef _TRINITY_BNET_CONFIG +# define _TRINITY_BNET_CONFIG "bnetserver.conf" +#endif + +bool StartDB(); +void StopDB(); +void SignalHandler(const boost::system::error_code& error, int signalNumber); +void KeepDatabaseAliveHandler(const boost::system::error_code& error); +variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile); + +boost::asio::io_service _ioService; +boost::asio::deadline_timer _dbPingTimer(_ioService); +uint32 _dbPingInterval; +LoginDatabaseWorkerPool LoginDatabase; + +int main(int argc, char** argv) +{ + std::string configFile = _TRINITY_BNET_CONFIG; + auto vm = GetConsoleArguments(argc, argv, configFile); + // exit if help is enabled + if (vm.count("help")) + return 0; + + std::string configError; + if (!sConfigMgr->LoadInitial(configFile, configError)) + { + printf("Error in config file: %s\n", configError.c_str()); + return 1; + } + + TC_LOG_INFO("server.bnetserver", "%s (bnetserver)", _FULLVERSION); + TC_LOG_INFO("server.bnetserver", "<Ctrl-C> to stop.\n"); + TC_LOG_INFO("server.bnetserver", "Using configuration file %s.", configFile.c_str()); + TC_LOG_INFO("server.bnetserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); + TC_LOG_INFO("server.bnetserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); + + // bnetserver PID file creation + std::string pidFile = sConfigMgr->GetStringDefault("PidFile", ""); + if (!pidFile.empty()) + { + if (uint32 pid = CreatePIDFile(pidFile)) + TC_LOG_INFO("server.bnetserver", "Daemon PID: %u\n", pid); + else + { + TC_LOG_ERROR("server.bnetserver", "Cannot create PID file %s.\n", pidFile.c_str()); + return 1; + } + } + + int32 worldListenPort = sConfigMgr->GetIntDefault("WorldserverListenPort", 1118); + if (worldListenPort < 0 || worldListenPort > 0xFFFF) + { + TC_LOG_ERROR("server.bnetserver", "Specified worldserver listen port (%d) out of allowed range (1-65535)", worldListenPort); + return 1; + } + + // Initialize the database connection + if (!StartDB()) + return 1; + + sIpcContext->Initialize(); + + // Get the list of realms for the server + sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10), worldListenPort); + + // Start the listening port (acceptor) for auth connections + int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); + if (bnport < 0 || bnport > 0xFFFF) + { + TC_LOG_ERROR("server.bnetserver", "Specified battle.net port (%d) out of allowed range (1-65535)", bnport); + StopDB(); + return 1; + } + + std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); + + sSessionMgr.StartNetwork(_ioService, bindIp, bnport); + + // Set signal handlers + boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); +#if PLATFORM == PLATFORM_WINDOWS + signals.add(SIGBREAK); +#endif + signals.async_wait(SignalHandler); + + // Set process priority according to configuration settings + SetProcessPriority("server.bnetserver"); + + // Enabled a timed callback for handling the database keep alive ping + _dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30); + _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + + sComponentMgr->Load(); + sModuleMgr->Load(); + + // Start the io service worker loop + _ioService.run(); + + sIpcContext->Close(); + + sRealmList->Close(); + + // Close the Database Pool and library + StopDB(); + + TC_LOG_INFO("server.bnetserver", "Halting process..."); + return 0; +} + + +/// Initialize connection to the database +bool StartDB() +{ + MySQL::Library_Init(); + + std::string dbstring = sConfigMgr->GetStringDefault("LoginDatabaseInfo", ""); + if (dbstring.empty()) + { + TC_LOG_ERROR("server.bnetserver", "Database not specified"); + return false; + } + + int32 worker_threads = sConfigMgr->GetIntDefault("LoginDatabase.WorkerThreads", 1); + if (worker_threads < 1 || worker_threads > 32) + { + TC_LOG_ERROR("server.bnetserver", "Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1."); + worker_threads = 1; + } + + int32 synch_threads = sConfigMgr->GetIntDefault("LoginDatabase.SynchThreads", 1); + if (synch_threads < 1 || synch_threads > 32) + { + TC_LOG_ERROR("server.bnetserver", "Improper value specified for LoginDatabase.SynchThreads, defaulting to 1."); + synch_threads = 1; + } + + if (!LoginDatabase.Open(dbstring, uint8(worker_threads), uint8(synch_threads))) + { + TC_LOG_ERROR("server.bnetserver", "Cannot connect to database"); + return false; + } + + TC_LOG_INFO("server.bnetserver", "Started auth database connection pool."); + sLog->SetRealmId(0); // Enables DB appenders when realm is set. + return true; +} + +/// Close the connection to the database +void StopDB() +{ + LoginDatabase.Close(); + MySQL::Library_End(); +} + +void SignalHandler(const boost::system::error_code& error, int /*signalNumber*/) +{ + if (!error) + _ioService.stop(); +} + +void KeepDatabaseAliveHandler(const boost::system::error_code& error) +{ + if (!error) + { + TC_LOG_INFO("server.bnetserver", "Ping MySQL to keep connection alive"); + LoginDatabase.KeepAlive(); + + _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + } +} + +variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile) +{ + options_description all("Allowed options"); + all.add_options() + ("help,h", "print usage message") + ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_BNET_CONFIG), "use <arg> as configuration file") + ; + variables_map variablesMap; + try + { + store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap); + notify(variablesMap); + } + catch (std::exception& e) { + std::cerr << e.what() << "\n"; + } + + if (variablesMap.count("help")) { + std::cout << all << "\n"; + } + + return variablesMap; +} diff --git a/src/server/bnetserver/Packets/AchievementPackets.h b/src/server/bnetserver/Packets/AchievementPackets.h new file mode 100644 index 00000000000..99a0f19d0a2 --- /dev/null +++ b/src/server/bnetserver/Packets/AchievementPackets.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef AchievementPackets_h__ +#define AchievementPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Achievement + { + enum Opcode + { + CMSG_LISTEN_REQUEST = 0x0, // Not implemented + CMSG_CRITERIA_FLUSH_REQUEST = 0x3, // Not implemented + CMSG_CHANGE_TROPHY_CASE_REQUEST = 0x5, // Not implemented + + SMSG_DATA = 0x2, // Not implemented + SMSG_CRITERIA_FLUSH_RESPONSE = 0x3, // Not implemented + SMSG_ACHIEVEMENT_HANDLE_UPDATE = 0x4, // Not implemented + SMSG_CHANGE_TROPHY_CASE_RESULT = 0x6 // Not implemented + }; + } +} + +#endif // AchievementPackets_h__ + diff --git a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.cpp b/src/server/bnetserver/Packets/AuthenticationPackets.cpp index 4d9c4476295..f6743a7c2f0 100644 --- a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.cpp +++ b/src/server/bnetserver/Packets/AuthenticationPackets.cpp @@ -16,44 +16,9 @@ */ #include "AuthenticationPackets.h" +#include "Session.h" #include "Util.h" -void Battlenet::Authentication::LogonRequest3::Read() -{ - Program = _stream.ReadFourCC(); - Platform = _stream.ReadFourCC(); - Locale = _stream.ReadFourCC(); - - Components.resize(_stream.Read<uint32>(6)); - for (size_t i = 0; i < Components.size(); ++i) - { - Component& component = Components[i]; - component.Program = _stream.ReadFourCC(); - component.Platform = _stream.ReadFourCC(); - component.Build = _stream.Read<uint32>(32); - } - - if (_stream.Read<uint32>(1)) - Login = _stream.ReadString(9, 3); - - Compatibility = _stream.Read<uint64>(64); -} - -std::string Battlenet::Authentication::LogonRequest3::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::LogonRequest3 Program: " << Program << ", Platform: " << Platform << ", Locale: " << Locale; - for (Component const& component : Components) - stream << std::endl << "Battlenet::Component Program: " << component.Program << ", Platform: " << component.Platform << ", Build: " << component.Build; - - if (!Login.empty()) - stream << std::endl << " Login: " << Login; - - stream << " Compatibility: " << Compatibility; - - return stream.str(); -} - void Battlenet::Authentication::ResumeRequest::Read() { Program = _stream.ReadFourCC(); @@ -81,13 +46,18 @@ std::string Battlenet::Authentication::ResumeRequest::ToString() const for (Component const& component : Components) stream << std::endl << "Battlenet::Component Program: " << component.Program << ", Platform: " << component.Platform << ", Build: " << component.Build; - stream << std::endl << "Battlenet::Authentication::ResumeRequest Login: " << Login; - stream << std::endl << "Battlenet::Authentication::ResumeRequest Region: " << uint32(Region); - stream << std::endl << "Battlenet::Authentication::ResumeRequest GameAccountName: " << GameAccountName; + stream << std::endl << "Login: " << Login; + stream << std::endl << "Region: " << uint32(Region); + stream << std::endl << "GameAccountName: " << GameAccountName; return stream.str(); } +void Battlenet::Authentication::ResumeRequest::CallHandler(Session* session) +{ + session->HandleResumeRequest(*this); +} + Battlenet::Authentication::ProofRequest::~ProofRequest() { for (size_t i = 0; i < Modules.size(); ++i) @@ -147,6 +117,52 @@ std::string Battlenet::Authentication::ProofResponse::ToString() const return stream.str(); } +void Battlenet::Authentication::ProofResponse::CallHandler(Session* session) +{ + session->HandleProofResponse(*this); +} + +void Battlenet::Authentication::LogonRequest3::Read() +{ + Program = _stream.ReadFourCC(); + Platform = _stream.ReadFourCC(); + Locale = _stream.ReadFourCC(); + + Components.resize(_stream.Read<uint32>(6)); + for (size_t i = 0; i < Components.size(); ++i) + { + Component& component = Components[i]; + component.Program = _stream.ReadFourCC(); + component.Platform = _stream.ReadFourCC(); + component.Build = _stream.Read<uint32>(32); + } + + if (_stream.Read<uint32>(1)) + Login = _stream.ReadString(9, 3); + + Compatibility = _stream.Read<uint64>(64); +} + +std::string Battlenet::Authentication::LogonRequest3::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::LogonRequest3 Program: " << Program << ", Platform: " << Platform << ", Locale: " << Locale; + for (Component const& component : Components) + stream << std::endl << "Battlenet::Component Program: " << component.Program << ", Platform: " << component.Platform << ", Build: " << component.Build; + + if (!Login.empty()) + stream << std::endl << " Login: " << Login; + + stream << " Compatibility: " << Compatibility; + + return stream.str(); +} + +void Battlenet::Authentication::LogonRequest3::CallHandler(Session* session) +{ + session->HandleLogonRequest(*this); +} + Battlenet::Authentication::LogonResponse::~LogonResponse() { for (ModuleInfo* m : Modules) diff --git a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h b/src/server/bnetserver/Packets/AuthenticationPackets.h index 44e3d7e18b8..bcaa0e72011 100644 --- a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h +++ b/src/server/bnetserver/Packets/AuthenticationPackets.h @@ -18,7 +18,9 @@ #ifndef AuthenticationPackets_h__ #define AuthenticationPackets_h__ -#include "BattlenetPacketsBase.h" +#include "PacketsBase.h" +#include "ComponentManager.h" +#include "ModuleManager.h" namespace Battlenet { @@ -41,25 +43,6 @@ namespace Battlenet SMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_REQUEST_2 = 0x8 // Not implemented }; - class LogonRequest3 final : public ClientPacket - { - public: - LogonRequest3(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_LOGON_REQUEST_3, AUTHENTICATION) && "Invalid packet header for LogonRequest3"); - } - - void Read() override; - std::string ToString() const override; - - std::string Program; - std::string Platform; - std::string Locale; - std::vector<Component> Components; - std::string Login; - uint64 Compatibility; - }; - class ResumeRequest final : public ClientPacket { public: @@ -70,6 +53,7 @@ namespace Battlenet void Read() override; std::string ToString() const override; + void CallHandler(Session* session) override; std::string Program; std::string Platform; @@ -92,20 +76,29 @@ namespace Battlenet void Read() override; std::string ToString() const override; + void CallHandler(Session* session) override; std::vector<BitStream*> Modules; }; - class ProofRequest final : public ServerPacket + class LogonRequest3 final : public ClientPacket { public: - ProofRequest() : ServerPacket(PacketHeader(SMSG_PROOF_REQUEST, AUTHENTICATION)) { } - ~ProofRequest(); + LogonRequest3(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_LOGON_REQUEST_3, AUTHENTICATION) && "Invalid packet header for LogonRequest3"); + } - void Write() override; + void Read() override; std::string ToString() const override; + void CallHandler(Session* session) override; - std::vector<ModuleInfo*> Modules; + std::string Program; + std::string Platform; + std::string Locale; + std::vector<Component> Components; + std::string Login; + uint64 Compatibility; }; class ResponseFailure @@ -192,6 +185,18 @@ namespace Battlenet int32 PingTimeout; Regulator RegulatorRules; }; + + class ProofRequest final : public ServerPacket + { + public: + ProofRequest() : ServerPacket(PacketHeader(SMSG_PROOF_REQUEST, AUTHENTICATION)) { } + ~ProofRequest(); + + void Write() override; + std::string ToString() const override; + + std::vector<ModuleInfo*> Modules; + }; } } diff --git a/src/server/authserver/Server/BattlenetBitStream.cpp b/src/server/bnetserver/Packets/BitStream.cpp index 712c9e58f08..5f002f6b1d9 100644 --- a/src/server/authserver/Server/BattlenetBitStream.cpp +++ b/src/server/bnetserver/Packets/BitStream.cpp @@ -15,7 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "BattlenetBitStream.h" +#include "BitStream.h" template<> bool Battlenet::BitStream::Read<bool>(uint32 /*bitCount*/) diff --git a/src/server/authserver/Server/BattlenetBitStream.h b/src/server/bnetserver/Packets/BitStream.h index 3601c3b0b0c..54c61ab3bbf 100644 --- a/src/server/authserver/Server/BattlenetBitStream.h +++ b/src/server/bnetserver/Packets/BitStream.h @@ -15,8 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __BATTLENETBITSTREAM_H__ -#define __BATTLENETBITSTREAM_H__ +#ifndef BitStream_h__ +#define BitStream_h__ #include "Common.h" #include "ByteConverter.h" @@ -212,14 +212,6 @@ namespace Battlenet } } - void SetReadPos(uint32 bits) - { - if (bits > _writePos) - throw BitStreamPositionException(true, bits, 0, _writePos); - - _readPos = bits; - } - bool IsRead() const { return _readPos >= _writePos; } uint8* GetBuffer() { return _buffer.data(); } @@ -227,6 +219,10 @@ namespace Battlenet size_t GetSize() const { return ((_writePos + 7) & ~7) / 8; } + // These methods are meant to only be used when their corresponding actions in the client ignore the value completely + void ReadSkip(uint32 bitCount) { _readPos += bitCount; } + void WriteSkip(uint32 bitCount) { Write(0, bitCount); } + private: uint32 _writePos; uint32 _readPos; @@ -240,4 +236,4 @@ namespace Battlenet void BitStream::Write<bool>(bool value, uint32 bitCount); } -#endif // __BATTLENETBITSTREAM_H__ +#endif // BitStream_h__ diff --git a/src/server/bnetserver/Packets/CachePackets.cpp b/src/server/bnetserver/Packets/CachePackets.cpp new file mode 100644 index 00000000000..deacfd34065 --- /dev/null +++ b/src/server/bnetserver/Packets/CachePackets.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Session.h" +#include "Util.h" +#include "CachePackets.h" + +void Battlenet::Cache::GetStreamItemsRequest::Read() +{ + _stream.WriteSkip(31); + Index = _stream.Read<uint32>(32); + ReferenceTime = _stream.Read<int32>(32) - std::numeric_limits<int32>::min(); + _stream.Read<bool>(1); // StreamDirection + _stream.Read<uint8>(6); // Module count, always 0 + Locale = _stream.ReadFourCC(); + if (_stream.Read<bool>(1)) + { + ItemName = _stream.ReadFourCC(); + Channel = _stream.ReadFourCC(); + } + else + _stream.Read<uint16>(16); +} + +std::string Battlenet::Cache::GetStreamItemsRequest::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Cache::GetStreamItemsRequest Channel: " << Channel << ", ItemName: " << ItemName + << ", Locale: " << Locale << ", Index: " << Index; + return stream.str(); +} + +void Battlenet::Cache::GetStreamItemsRequest::CallHandler(Session* session) +{ + session->HandleGetStreamItemsRequest(*this); +} + +Battlenet::Cache::GetStreamItemsResponse::~GetStreamItemsResponse() +{ + for (size_t i = 0; i < Modules.size(); ++i) + delete Modules[i]; +} + +void Battlenet::Cache::GetStreamItemsResponse::Write() +{ + _stream.Write(0, 16); + _stream.Write(1, 16); + _stream.Write(Index, 32); + _stream.Write(Modules.size(), 6); + for (ModuleInfo const* info : Modules) + { + _stream.WriteBytes(info->Type.c_str(), 4); + _stream.WriteFourCC(info->Region); + _stream.WriteBytes(info->ModuleId, 32); + _stream.WriteSkip(27); + _stream.WriteBytes(info->Data, 4); + } +} + +std::string Battlenet::Cache::GetStreamItemsResponse::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Cache::GetStreamItemsResponse modules " << Modules.size(); + for (ModuleInfo const* module : Modules) + stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize); + + return stream.str(); +} diff --git a/src/server/bnetserver/Packets/CachePackets.h b/src/server/bnetserver/Packets/CachePackets.h new file mode 100644 index 00000000000..a65ab2651c8 --- /dev/null +++ b/src/server/bnetserver/Packets/CachePackets.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CachePackets_h__ +#define CachePackets_h__ + +#include "ModuleManager.h" +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Cache + { + enum Opcode + { + CMSG_GATEWAY_LOOKUP_REQUEST = 0x2, // Not implemented + CMSG_CONNECT_REQUEST = 0x4, // Not implemented + CMSG_DATA_CHUNK = 0x7, // Not implemented + CMSG_GET_STREAM_ITEMS_REQUEST = 0x9, + + SMSG_GATEWAY_LOOKUP_RESPONSE = 0x3, // Not implemented + SMSG_CONNECT_RESPONSE = 0x4, // Not implemented + SMSG_PUBLISH_LIST_RESPONSE = 0x7, // Not implemented + SMSG_RESULT = 0x8, // Not implemented + SMSG_GET_STREAM_ITEMS_RESPONSE = 0x9 + }; + + class GetStreamItemsRequest final : public ClientPacket + { + public: + GetStreamItemsRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_GET_STREAM_ITEMS_REQUEST, CACHE) && "Invalid packet header for GetStreamItemsRequest"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session); + + std::string Channel; + std::string ItemName; + std::string Locale; + uint32 Index; + int32 ReferenceTime; + }; + + class GetStreamItemsResponse final : public ServerPacket + { + public: + GetStreamItemsResponse() : ServerPacket(PacketHeader(SMSG_GET_STREAM_ITEMS_RESPONSE, CACHE)) + { + } + + ~GetStreamItemsResponse(); + + void Write() override; + std::string ToString() const override; + + uint32 Index; + std::vector<ModuleInfo*> Modules; + }; + } +} + +#endif // CachePackets_h__ diff --git a/src/server/bnetserver/Packets/ChatPackets.h b/src/server/bnetserver/Packets/ChatPackets.h new file mode 100644 index 00000000000..fc4b638754c --- /dev/null +++ b/src/server/bnetserver/Packets/ChatPackets.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ChatPackets_h__ +#define ChatPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Chat + { + enum Opcode + { + CMSG_JOIN_REQUEST_2 = 0x00, // Not implemented + CMSG_LEAVE_REQUEST = 0x02, // Not implemented + CMSG_INVITE_REQUEST = 0x03, // Not implemented + CMSG_CREATE_AND_INVITE_REQUEST = 0x0A, // Not implemented + CMSG_MESSAGE_SEND = 0x0B, // Not implemented + CMSG_DATAGRAM_CONNECTION_UPDATE = 0x0D, // Not implemented + CMSG_REPORT_SPAM_REQUEST = 0x0E, // Not implemented + CMSG_WHISPER_SEND = 0x13, // Not implemented + CMSG_ENUM_CATEGORY_DESCRIPTIONS = 0x15, // Not implemented + CMSG_ENUM_CONFERENCE_DESCRIPTIONS = 0x17, // Not implemented + CMSG_ENUM_CONFERENCE_MEMBER_COUNTS = 0x19, // Not implemented + CMSG_MODIFY_CHANNEL_LIST_REQUEST = 0x1B, // Not implemented + + SMSG_MEMBERSHIP_CHANGE_NOTIFY = 0x01, // Not implemented + SMSG_INVITE_NOTIFY = 0x04, // Not implemented + SMSG_INVITE_CANCELED = 0x07, // Not implemented + SMSG_MESSAGE_RECV = 0x0B, // Not implemented + SMSG_MESSAGE_UNDELIVERABLE = 0x0C, // Not implemented + SMSG_DATAGRAM_CONNECTION_UPDATE = 0x0D, // Not implemented + SMSG_INVITE_FAILURE = 0x0F, // Not implemented + SMSG_SYSTEM_MESSAGE = 0x10, // Not implemented + SMSG_MESSAGE_BLOCKED = 0x12, // Not implemented + SMSG_WHISPER_RECV = 0x13, // Not implemented + SMSG_WHISPER_UNDELIVERABLE = 0x14, // Not implemented + SMSG_CATEGORY_DESCRIPTIONS = 0x16, // Not implemented + SMSG_CONFERENCE_DESCRIPTIONS = 0x18, // Not implemented + SMSG_CONFERENCE_MEMBER_COUNTS = 0x1A, // Not implemented + SMSG_JOIN_NOTIFY_2 = 0x1B, // Not implemented + SMSG_MODIFY_CHANNEL_LIST_RESPONSE = 0x1C, // Not implemented + SMSG_CONFIG_CHANGED = 0x1D // Not implemented + }; + } +} + +#endif // ChatPackets_h__ diff --git a/src/server/bnetserver/Packets/ConnectionPackets.cpp b/src/server/bnetserver/Packets/ConnectionPackets.cpp new file mode 100644 index 00000000000..3b7a9949552 --- /dev/null +++ b/src/server/bnetserver/Packets/ConnectionPackets.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Session.h" +#include "ConnectionPackets.h" + +std::string Battlenet::Connection::Ping::ToString() const +{ + return "Battlenet::Connection::Ping"; +} + +void Battlenet::Connection::Ping::CallHandler(Session* session) +{ + session->HandlePing(*this); +} + +std::string Battlenet::Connection::EnableEncryption::ToString() const +{ + return "Battlenet::Connection::EnableEncryption"; +} + +void Battlenet::Connection::EnableEncryption::CallHandler(Session* session) +{ + session->HandleEnableEncryption(*this); +} + +std::string Battlenet::Connection::LogoutRequest::ToString() const +{ + return "Battlenet::Connection::LogoutRequest"; +} + +void Battlenet::Connection::LogoutRequest::CallHandler(Session* session) +{ + session->HandleLogoutRequest(*this); +} + +void Battlenet::Connection::DisconnectRequest::Read() +{ + Timeout = _stream.Read<uint16>(16); + Tick = _stream.Read<uint32>(32); +} + +std::string Battlenet::Connection::DisconnectRequest::ToString() const +{ + std::ostringstream str; + str << "Battlenet::Connection::DisconnectRequest Timeout: " << Timeout << ", Tick: " << Tick; + return str.str(); +} + +void Battlenet::Connection::ConnectionClosing::Read() +{ + Packets.resize(_stream.Read<uint8>(6)); + for (size_t i = 0; i < Packets.size(); ++i) + { + PacketInfo& info = Packets[i]; + info.CommandName = _stream.ReadFourCC(); + info.Timestamp = _stream.Read<uint32>(32); + info.Size = _stream.Read<uint32>(16); + info.Channel = _stream.ReadFourCC(); + info.LayerId = _stream.Read<uint32>(16); + } + + Reason = _stream.Read<ClosingReason>(4); + _stream.ReadBytes(_stream.Read<uint8>(8)); // BadData + + if (_stream.Read<bool>(1)) // HasHeader + { + Header.Opcode = _stream.Read<uint32>(6); + if (_stream.Read<bool>(1)) + Header.Channel = _stream.Read<int32>(4); + } + + Now = _stream.Read<time_t>(32); +} + +std::string Battlenet::Connection::ConnectionClosing::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Connection::ConnectionClosing Reason: " << Reason << ", Now: " << Now << ", Packet history size: " << Packets.size(); + for (PacketInfo const& packet : Packets) + stream << std::endl << "Battlenet::Connection::ConnectionClosing::PacketInfo LayerId: " << packet.LayerId + << ", Channel: " << packet.Channel << ", CommandName: " << packet.CommandName << ", Size: " << packet.Size << ", Timestamp: " << packet.Timestamp; + + return stream.str(); +} + +void Battlenet::Connection::ConnectionClosing::CallHandler(Session* session) +{ + session->HandleConnectionClosing(*this); +} + +std::string Battlenet::Connection::Pong::ToString() const +{ + return "Battlenet::Connection::Pong"; +} diff --git a/src/server/bnetserver/Packets/ConnectionPackets.h b/src/server/bnetserver/Packets/ConnectionPackets.h new file mode 100644 index 00000000000..8572cd5d854 --- /dev/null +++ b/src/server/bnetserver/Packets/ConnectionPackets.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ConnectionPackets_h__ +#define ConnectionPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Connection + { + enum Opcode + { + CMSG_PING = 0x0, + CMSG_ENABLE_ENCRYPTION = 0x5, + CMSG_LOGOUT_REQUEST = 0x6, + CMSG_DISCONNECT_REQUEST = 0x7, // Not handled + CMSG_CONNECTION_CLOSING = 0x9, + + SMSG_PONG = 0x0, + SMSG_BOOM = 0x1, // Not implemented + SMSG_REGULATOR_UPDATE = 0x2, // Not implemented + SMSG_SERVER_VERSION = 0x3, // Not implemented + SMSG_STUN_SERVERS = 0x4 // Not implemented + }; + + class Ping final : public ClientPacket + { + public: + Ping(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_PING, CONNECTION) && "Invalid packet header for Ping"); + } + + void Read() override { } + std::string ToString() const override; + void CallHandler(Session* session) override; + }; + + class EnableEncryption final : public ClientPacket + { + public: + EnableEncryption(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_ENABLE_ENCRYPTION, CONNECTION) && "Invalid packet header for EnableEncryption"); + } + + void Read() override { } + std::string ToString() const override; + void CallHandler(Session* session) override; + }; + + class LogoutRequest final : public ClientPacket + { + public: + LogoutRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_LOGOUT_REQUEST, CONNECTION) && "Invalid packet header for LogoutRequest"); + } + + void Read() override { } + std::string ToString() const override; + void CallHandler(Session* session) override; + }; + + class DisconnectRequest final : public ClientPacket + { + public: + DisconnectRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_DISCONNECT_REQUEST, CONNECTION) && "Invalid packet header for DisconnectRequest"); + } + + void Read() override; + std::string ToString() const override; + + uint16 Timeout; + uint32 Tick; + }; + + class ConnectionClosing final : public ClientPacket + { + public: + enum ClosingReason + { + PACKET_TOO_LARGE, + PACKET_CORRUPT, + PACKET_INVALID, + PACKET_INCORRECT, + HEADER_CORRUPT, + HEADER_IGNORED, + HEADER_INCORRECT, + PACKET_REJECTED, + CHANNEL_UNHANDLED, + COMMAND_UNHANDLED, + COMMAND_BAD_PERMISSIONS, + DIRECT_CALL, + TIMEOUT, + }; + + struct PacketInfo + { + uint16 LayerId; + std::string Channel; + uint32 Timestamp; + std::string CommandName; + uint16 Size; + }; + + ConnectionClosing(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_CONNECTION_CLOSING, CONNECTION) && "Invalid packet header for ConnectionClosing"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) override; + + PacketHeader Header; + ClosingReason Reason; + std::vector<PacketInfo> Packets; + time_t Now; + }; + + class Pong final : public ServerPacket + { + public: + Pong() : ServerPacket(PacketHeader(SMSG_PONG, CONNECTION)) + { + } + + void Write() override { } + std::string ToString() const override; + }; + } +} + +#endif // ConnectionPackets_h__ diff --git a/src/server/bnetserver/Packets/FriendsPackets.cpp b/src/server/bnetserver/Packets/FriendsPackets.cpp new file mode 100644 index 00000000000..2659ec6204f --- /dev/null +++ b/src/server/bnetserver/Packets/FriendsPackets.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Session.h" +#include "FriendsPackets.h" + +void Battlenet::Friends::GetFriendsOfFriend::Read() +{ + uint8 unk = _stream.Read<uint8>(2); + uint32 unk1 = _stream.Read<uint32>(32); +} + +std::string Battlenet::Friends::GetFriendsOfFriend::ToString() const +{ + return "Battlenet::Friends::GetFriendsOfFriend"; +} + +void Battlenet::Friends::SocialNetworkCheckConnected::Read() +{ + SocialNetworkId = _stream.Read<uint32>(32); +} + +std::string Battlenet::Friends::SocialNetworkCheckConnected::ToString() const +{ + return "Battlenet::Friends::SocialNetworkCheckConnected SocialNetworkId " + std::to_string(SocialNetworkId); +} + +void Battlenet::Friends::SocialNetworkCheckConnected::CallHandler(Session* session) +{ + session->HandleSocialNetworkCheckConnected(*this); +} + +void Battlenet::Friends::RealIdFriendInvite::Read() +{ + _stream.Read<uint32>(32); + uint8 type = _stream.Read<uint8>(3); + + switch (type) + { + case 0: + { + _stream.Read<uint32>(32); // Presence Id? + break; + } + case 1: // GameAccount? + { + _stream.Read<uint8>(8); + _stream.Read<uint32>(32); + _stream.Read<uint32>(32); + uint8 size = _stream.Read<uint8>(7); // Only if *(a1 + 16) <= 0x64 + _stream.ReadBytes(size); + break; + } + case 2: + Email = _stream.ReadString(9, 3); + break; + case 3: + { + _stream.Read<uint32>(32); + break; + } + case 4: + { + _stream.Read<uint64>(64); + _stream.Read<uint32>(32); + break; + } + } + + _stream.Read<uint8>(1); + + if (_stream.Read<uint8>(1)) + Message = _stream.ReadString(9); + + _stream.Read<uint32>(32); +} + +std::string Battlenet::Friends::RealIdFriendInvite::ToString() const +{ + return "Battlenet::Friends::RealIdFriendInvite Mail: " + Email + " Message: " + Message; +} + +std::string Battlenet::Friends::FriendInviteResult::ToString() const +{ + return "Battlenet::Friends::RealIdFriendInviteResult"; +} + +void Battlenet::Friends::FriendInviteResult::Write() +{ + bool hasNames = false; + _stream.Write(hasNames, 1); + if (hasNames) + { + _stream.WriteString("Testing1", 8); + _stream.WriteString("Testing2", 8); + } + _stream.Write(5, 32); + + _stream.Write(0, 0xC); // Ignored + + _stream.Write(1, 16); + + bool moreInfo = true; + _stream.Write(moreInfo, 1); + if (moreInfo) + { + _stream.Write(0, 8); + _stream.Write(4, 32); + _stream.Write(3, 32); + _stream.WriteString("Testing3", 7, 2); + } +} + +std::string Battlenet::Friends::SocialNetworkCheckConnectedResult::ToString() const +{ + return "Battlenet::Friends::SocialNetworkCheckConnectedResult"; +} + +void Battlenet::Friends::SocialNetworkCheckConnectedResult::Write() +{ + _stream.WriteSkip(23); + _stream.Write(Result, 16); + _stream.Write(SocialNetworkId, 32); +} diff --git a/src/server/bnetserver/Packets/FriendsPackets.h b/src/server/bnetserver/Packets/FriendsPackets.h new file mode 100644 index 00000000000..ea4d6d2ea92 --- /dev/null +++ b/src/server/bnetserver/Packets/FriendsPackets.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FriendsPackets_h__ +#define FriendsPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Friends + { + enum Opcode + { + CMSG_FRIEND_INVITE = 0x01, // Not implemented + CMSG_FRIEND_INVITE_RESPONSE = 0x02, // Not implemented + CMSG_FRIEND_REMOVE = 0x04, // Not implemented + CMSG_FRIEND_NOTE = 0x05, // Not implemented + CMSG_TOONS_OF_FRIEND_REQUEST = 0x06, // Not implemented + CMSG_BLOCK_ADD = 0x08, // Not implemented + CMSG_BLOCK_REMOVE = 0x0A, // Not implemented + CMSG_GET_FRIENDS_OF_FRIEND = 0x0B, // Not implemented + CMSG_GET_SOCIAL_NETWORK_FRIENDS = 0x0D, // Won't support + CMSG_SOCIAL_NETWORK_CONNECT = 0x0F, // Won't support + CMSG_SOCIAL_NETWORK_DISCONNECT = 0x11, // Won't support + CMSG_SOCIAL_NETWORK_CHECK_CONNECTED = 0x13, + CMSG_REALID_FRIEND_INVITE = 0x16, // Not implemented + + SMSG_FRIEND_INVITE_NOTIFY = 0x01, // Not implemented + SMSG_FRIEND_INVITE_RESULT = 0x03, // Not implemented + SMSG_TOONS_OF_FRIEND_NOTIFY = 0x06, // Not implemented + SMSG_BLOCK_INVITE_NOTIFY = 0x07, // Not implemented + SMSG_BLOCK_ADD_FAILURE = 0x09, // Not implemented + SMSG_FRIENDS_OF_FRIEND = 0x0C, // Not implemented + SMSG_SOCIAL_NETWORK_FRIENDS = 0x0E, // Won't support + SMSG_SOCIAL_NETWORK_CONNECT_RESULT = 0x10, // Won't support + SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT = 0x12, // Won't support + SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT = 0x14, + SMSG_MAX_FRIENDS_NOTIFY = 0x15, // Not implemented + SMSG_FRIENDS_LIST_NOTIFY_3 = 0x18 // Not implemented + }; + + class GetFriendsOfFriend final : public ClientPacket + { + public: + GetFriendsOfFriend(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS) && "Invalid packet header for GetFriendsOfFriend"); + } + + void Read() override; + std::string ToString() const override; + }; + + class SocialNetworkCheckConnected final : public ClientPacket + { + public: + SocialNetworkCheckConnected(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS) && "Invalid packet header for SocialNetworkCheckConnected"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) override; + + uint32 SocialNetworkId; + }; + + class RealIdFriendInvite final : public ClientPacket + { + public: + RealIdFriendInvite(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_REALID_FRIEND_INVITE, FRIENDS) && "Invalid packet header for RealIdFriendInvite"); + } + + void Read() override; + std::string ToString() const override; + + std::string Email; + std::string Message; + }; + + class FriendInviteResult final : public ServerPacket + { + public: + FriendInviteResult() : ServerPacket(PacketHeader(SMSG_FRIEND_INVITE_RESULT, FRIENDS)) + { + } + + void Write() override; + std::string ToString() const override; + }; + + class FriendsOfFriend final : public ServerPacket + { + public: + FriendsOfFriend() : ServerPacket(PacketHeader(SMSG_FRIENDS_OF_FRIEND, FRIENDS)) + { + } + + void Write() override; + std::string ToString() const override; + }; + + class SocialNetworkCheckConnectedResult final : public ServerPacket + { + public: + SocialNetworkCheckConnectedResult() : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS)), + Result(4601), SocialNetworkId(0) // 4601 = The Facebook add friend service is unavailable right now. Please try again later. + { + } + + void Write() override; + std::string ToString() const override; + + uint16 Result; + uint32 SocialNetworkId; + }; + } +} + +#endif // FriendsPackets_h__ diff --git a/src/server/bnetserver/Packets/PacketManager.cpp b/src/server/bnetserver/Packets/PacketManager.cpp new file mode 100644 index 00000000000..cbfd0c8b2b6 --- /dev/null +++ b/src/server/bnetserver/Packets/PacketManager.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "PacketManager.h" + +Battlenet::ClientPacket* Battlenet::PacketManager::CreateClientPacket(PacketHeader const& header, BitStream& stream) +{ + auto packetInfo = _clientPacketTable.find(header); + if (packetInfo == _clientPacketTable.end()) + return nullptr; + + if (!packetInfo->second.Constructor) + return nullptr; + + ClientPacket* packet = packetInfo->second.Constructor(header, stream); + packet->Read(); + return packet; +} + +char const* Battlenet::PacketManager::GetClientPacketName(PacketHeader const& header) +{ + auto packetInfo = _clientPacketTable.find(header); + if (packetInfo == _clientPacketTable.end()) + return nullptr; + + return packetInfo->second.Name; +} + +char const* Battlenet::PacketManager::GetServerPacketName(PacketHeader const& header) +{ + auto packetInfo = _serverPacketTable.find(header); + if (packetInfo == _serverPacketTable.end()) + return nullptr; + + return packetInfo->second.Name; +} + +bool Battlenet::PacketManager::IsHandled(PacketHeader const& header) +{ + auto packetInfo = _clientPacketTable.find(header); + if (packetInfo == _clientPacketTable.end()) + return false; + + return packetInfo->second.HasHandler; +} + +Battlenet::PacketManager::PacketManager() +{ + RegisterAuthenticationPackets(); + RegisterConnectionPackets(); + RegisterWoWRealmPackets(); + RegisterFriendsPackets(); + RegisterPresencePackets(); + RegisterChatPackets(); + RegisterSupportPackets(); + RegisterCachePackets(); + RegisterAchievementPackets(); + RegisterProfilePackets(); +} + +#define REGISTER_CLIENT_PACKET(header, packetClass) RegisterClientPacket<packetClass>(header, #packetClass) +#define REGISTER_SERVER_PACKET(header, packetClass) RegisterPacketName(_serverPacketTable, header, #packetClass) +#define REGISTER_CLIENT_PACKET_NAME(header, name) RegisterPacketName(_clientPacketTable, header, name) +#define REGISTER_SERVER_PACKET_NAME(header, name) RegisterPacketName(_serverPacketTable, header, name) + +void Battlenet::PacketManager::RegisterAuthenticationPackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest3"); + REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION), Authentication::ResumeRequest); + REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION), Authentication::ProofResponse); + REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_LOGON_REQUEST_3, AUTHENTICATION), Authentication::LogonRequest3); + + REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_LOGON_RESPONSE, AUTHENTICATION), Authentication::LogonResponse); + REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_RESUME_RESPONSE, AUTHENTICATION), Authentication::ResumeResponse); + REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_PROOF_REQUEST, AUTHENTICATION), Authentication::ProofRequest); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_PATCH, AUTHENTICATION), "Authentication::Patch"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_AUTHORIZED_LICENSES, AUTHENTICATION), "Authentication::AuthorizedLicenses"); +} + +void Battlenet::PacketManager::RegisterConnectionPackets() +{ + REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_PING, CONNECTION), Connection::Ping); + REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_ENABLE_ENCRYPTION, CONNECTION), Connection::EnableEncryption); + REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_LOGOUT_REQUEST, CONNECTION), Connection::LogoutRequest); + REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_DISCONNECT_REQUEST, CONNECTION), Connection::DisconnectRequest); + REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_CONNECTION_CLOSING, CONNECTION), Connection::ConnectionClosing); + + REGISTER_SERVER_PACKET(PacketHeader(Connection::SMSG_PONG, CONNECTION), Connection::Pong); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_BOOM, CONNECTION), "Connection::Boom"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_REGULATOR_UPDATE, CONNECTION), "Connection::RegulatorUpdate"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_SERVER_VERSION, CONNECTION), "Connection::ServerVersion"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_STUN_SERVERS, CONNECTION), "Connection::STUNServers"); +} + +void Battlenet::PacketManager::RegisterWoWRealmPackets() +{ + REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM), WoWRealm::ListSubscribeRequest); + REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_LIST_UNSUBSCRIBE, WOWREALM), WoWRealm::ListUnsubscribe); + REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_JOIN_REQUEST_V2, WOWREALM), WoWRealm::JoinRequestV2); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(WoWRealm::CMSG_MULTI_LOGON_REQUEST_V2, WOWREALM), "WoWRealm::MultiLogonRequestV2"); + + REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM), WoWRealm::ListSubscribeResponse); + REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_UPDATE, WOWREALM), WoWRealm::ListUpdate); + REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_COMPLETE, WOWREALM), WoWRealm::ListComplete); + REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_TOON_READY, WOWREALM), WoWRealm::ToonReady); + REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_TOON_LOGGED_OUT, WOWREALM), WoWRealm::ToonLoggedOut); + REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_JOIN_RESPONSE_V2, WOWREALM), WoWRealm::JoinResponseV2); +} + +void Battlenet::PacketManager::RegisterFriendsPackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_INVITE, FRIENDS), "Friends::FriendInvite"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_INVITE_RESPONSE, FRIENDS), "Friends::FriendInviteResponse"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_REMOVE, FRIENDS), "Friends::FriendRemove"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_NOTE, FRIENDS), "Friends::FriendNote"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_TOONS_OF_FRIEND_REQUEST, FRIENDS), "Friends::ToonsOfFriendRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_BLOCK_ADD, FRIENDS), "Friends::BlockAdd"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_BLOCK_REMOVE, FRIENDS), "Friends::BlockRemove"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS), "Friends::GetFriendsOfFriend"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_GET_SOCIAL_NETWORK_FRIENDS, FRIENDS), "Friends::GetSocialNetworkFriends"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS), "Friends::SocialNetworkConnect"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_DISCONNECT, FRIENDS), "Friends::SocialNetworkDisconnect"); + REGISTER_CLIENT_PACKET(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS), Friends::SocialNetworkCheckConnected); + REGISTER_CLIENT_PACKET(PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS), Friends::GetFriendsOfFriend); + REGISTER_CLIENT_PACKET(PacketHeader(Friends::CMSG_REALID_FRIEND_INVITE, FRIENDS), Friends::RealIdFriendInvite); + + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITE_NOTIFY, FRIENDS), "Friends::FriendInviteNotify"); + REGISTER_SERVER_PACKET(PacketHeader(Friends::SMSG_FRIEND_INVITE_RESULT, FRIENDS), Friends::FriendInviteResult); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_TOONS_OF_FRIEND_NOTIFY, FRIENDS), "Friends::ToonsOfFriendNotify"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_BLOCK_INVITE_NOTIFY, FRIENDS), "Friends::BlockInviteNotify"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_BLOCK_ADD_FAILURE, FRIENDS), "Friends::BlockAddFailure"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_OF_FRIEND, FRIENDS), "Friends::FriendsOfFriend"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_FRIENDS, FRIENDS), "Friends::SocialNetworkFriends"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_CONNECT_RESULT, FRIENDS), "Friends::SocialNetworkConnectResult"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT, FRIENDS), "Friends::SocialNetworkDisconnectResult"); + REGISTER_SERVER_PACKET(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS), Friends::SocialNetworkCheckConnectedResult); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_MAX_FRIENDS_NOTIFY, FRIENDS), "Friends::MaxFriendsNotify"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_LIST_NOTIFY_3, FRIENDS), "Friends::FriendsListNotify3"); +} + +void Battlenet::PacketManager::RegisterPresencePackets() +{ + REGISTER_CLIENT_PACKET(PacketHeader(Presence::CMSG_UPDATE_REQUEST, PRESENCE), Presence::UpdateRequest); + REGISTER_CLIENT_PACKET(PacketHeader(Presence::CMSG_STATISTIC_SUBSCRIBE, PRESENCE), Presence::StatisticSubscribe); + + REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_UPDATE_NOTIFY, PRESENCE), "Presence::UpdateNotify"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_FIELD_SPEC_ANNOUNCE, PRESENCE), "Presence::FieldSpecAnnounce"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_STATISTICS_UPDATE, PRESENCE), "Presence::StatisticsUpdate"); +} + +void Battlenet::PacketManager::RegisterChatPackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_JOIN_REQUEST_2, CHAT), "Chat::JoinRequest2"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_LEAVE_REQUEST, CHAT), "Chat::LeaveRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_INVITE_REQUEST, CHAT), "Chat::InviteRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_CREATE_AND_INVITE_REQUEST, CHAT), "Chat::CreateAndInviteRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MESSAGE_SEND, CHAT), "Chat::MessageSend"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_DATAGRAM_CONNECTION_UPDATE, CHAT), "Chat::DatagramConnectionUpdate"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_REPORT_SPAM_REQUEST, CHAT), "Chat::ReportSpamRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_WHISPER_SEND, CHAT), "Chat::WhisperSend"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CATEGORY_DESCRIPTIONS, CHAT), "Chat::EnumCategoryDescriptions"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CONFERENCE_DESCRIPTIONS, CHAT), "Chat::EnumConferenceDescriptions"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CONFERENCE_MEMBER_COUNTS, CHAT), "Chat::EnumConferenceMemberCounts"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MODIFY_CHANNEL_LIST_REQUEST, CHAT), "Chat::ModifyChannelListRequest"); + + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MEMBERSHIP_CHANGE_NOTIFY, CHAT), "Chat::MembershipChangeNotify"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_NOTIFY, CHAT), "Chat::InviteNotify"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_CANCELED, CHAT), "Chat::InviteCanceled"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_RECV, CHAT), "Chat::MessageRecv"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_UNDELIVERABLE, CHAT), "Chat::MessageUndeliverable"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_DATAGRAM_CONNECTION_UPDATE, CHAT), "Chat::DatagramConnectionUpdate"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_FAILURE, CHAT), "Chat::InviteFailed"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_SYSTEM_MESSAGE, CHAT), "Chat::SystemMessage"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_BLOCKED, CHAT), "Chat::MessageBlocked"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_RECV, CHAT), "Chat::WhisperRecv"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_UNDELIVERABLE, CHAT), "Chat::WhisperUndeliverable"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CATEGORY_DESCRIPTIONS, CHAT), "Chat::CategoryDescriptions"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFERENCE_DESCRIPTIONS, CHAT), "Chat::ConferenceDescriptions"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFERENCE_MEMBER_COUNTS, CHAT), "Chat::ConferenceMemberCounts"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_JOIN_NOTIFY_2, CHAT), "Chat::JoinNotify2"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MODIFY_CHANNEL_LIST_RESPONSE, CHAT), "Chat::ModifyChannelListResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFIG_CHANGED, CHAT), "Chat::ConfigChanged"); +} + +void Battlenet::PacketManager::RegisterSupportPackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Support::CMSG_COMPLAINT_REQUEST, SUPPORT), "Support::ComplaintRequest"); +} + +void Battlenet::PacketManager::RegisterAchievementPackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_LISTEN_REQUEST, ACHIEVEMENT), "Achievement::ListenRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_CRITERIA_FLUSH_REQUEST, ACHIEVEMENT), "Achievement::CriteriaFlushRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_CHANGE_TROPHY_CASE_REQUEST, ACHIEVEMENT), "Achievement::ChangeTrophyCaseRequest"); + + REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_DATA, ACHIEVEMENT), "Achievement::Data"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_CRITERIA_FLUSH_RESPONSE, ACHIEVEMENT), "Achievement::CriteriaFlushResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_ACHIEVEMENT_HANDLE_UPDATE, ACHIEVEMENT), "Achievement::AchievementHandleUpdate"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_CHANGE_TROPHY_CASE_RESULT, ACHIEVEMENT), "Achievement::ChangeTrophyCaseResult"); +} + +void Battlenet::PacketManager::RegisterCachePackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_GATEWAY_LOOKUP_REQUEST, CACHE), "Cache::GatewayLookupRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_CONNECT_REQUEST, CACHE), "Cache::ConnectRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_DATA_CHUNK, CACHE), "Cache::DataChunk"); + REGISTER_CLIENT_PACKET(PacketHeader(Cache::CMSG_GET_STREAM_ITEMS_REQUEST, CACHE), Cache::GetStreamItemsRequest); + + REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_GATEWAY_LOOKUP_RESPONSE, CACHE), "Cache::GatewayLookupResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_CONNECT_RESPONSE, CACHE), "Cache::ConnectResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_PUBLISH_LIST_RESPONSE, CACHE), "Cache::PublishListResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_RESULT, CACHE), "Cache::Result"); + REGISTER_SERVER_PACKET(PacketHeader(Cache::SMSG_GET_STREAM_ITEMS_RESPONSE, CACHE), Cache::GetStreamItemsResponse); +} + +void Battlenet::PacketManager::RegisterProfilePackets() +{ + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_READ_REQUEST, PROFILE), "Profile::ReadRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_ADDRESS_QUERY_REQUEST, PROFILE), "Profile::AddressQueryRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_RESOLVE_TOON_HANDLE_TO_NAME_REQUEST, PROFILE), "Profile::ResolveHandleToToonNameRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_RESOLVE_TOON_NAME_TO_HANDLE_REQUEST, PROFILE), "Profile::ResolveToonNameToHandleRequest"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_CHANGE_SETTINGS, PROFILE), "Profile::ChangeSettings"); + + REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_READ_RESPONSE, PROFILE), "Profile::ReadResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_ADDRESS_QUERY_RESPONSE, PROFILE), "Profile::AddressQueryResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_RESOLVE_TOON_HANDLE_TO_NAME_RESPONSE, PROFILE), "Profile::ResolveHandleToToonNameResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_RESOLVE_TOON_NAME_TO_HANDLE_RESPONSE, PROFILE), "Profile::ResolveToonNameToHandleResponse"); + REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_SETTINGS_AVAILABLE, PROFILE), "Profile::SettingsAvailable"); +} diff --git a/src/server/bnetserver/Packets/PacketManager.h b/src/server/bnetserver/Packets/PacketManager.h new file mode 100644 index 00000000000..1e64e6a502c --- /dev/null +++ b/src/server/bnetserver/Packets/PacketManager.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PacketManager_h__ +#define PacketManager_h__ + +#include "Packets.h" +#include <map> +#include <type_traits> + +template<typename T> +struct has_call_handler +{ + template<typename U, void(U::*)(Battlenet::Session*)> struct test_has_call_handler { }; + template<typename U> static char Test(test_has_call_handler<U, &U::CallHandler>*); + template<typename U> static int Test(...); + static const bool value = sizeof(Test<T>(nullptr)) == sizeof(char); +}; + +namespace Battlenet +{ + class PacketManager + { + typedef ClientPacket*(*PacketCreateFn)(PacketHeader const& header, BitStream& stream); + + struct PacketInfo + { + PacketCreateFn Constructor; + char const* Name; + bool HasHandler; + }; + + PacketManager(); + + void RegisterAuthenticationPackets(); + void RegisterConnectionPackets(); + void RegisterWoWRealmPackets(); + void RegisterFriendsPackets(); + void RegisterPresencePackets(); + void RegisterChatPackets(); + void RegisterSupportPackets(); + void RegisterAchievementPackets(); + void RegisterCachePackets(); + void RegisterProfilePackets(); + + template<class PacketType> + static ClientPacket* New(PacketHeader const& header, BitStream& stream) + { + return new PacketType(header, stream); + } + + void RegisterPacketName(std::map<PacketHeader, PacketInfo>& packetTable, PacketHeader const& header, char const* name) + { + PacketInfo& info = packetTable[header]; + info.Constructor = nullptr; + info.Name = name; + info.HasHandler = false; + } + + template<class PacketType> + void RegisterClientPacket(PacketHeader const& header, char const* name) + { + PacketInfo& info = _clientPacketTable[header]; + info.Constructor = &New<PacketType>; + info.Name = name; + info.HasHandler = has_call_handler<PacketType>::value; + } + + public: + ClientPacket* CreateClientPacket(PacketHeader const& header, BitStream& stream); + + char const* GetClientPacketName(PacketHeader const& header); + char const* GetServerPacketName(PacketHeader const& header); + + bool IsHandled(PacketHeader const& header); + + static PacketManager& Instance() + { + static PacketManager instance; + return instance; + } + + private: + std::map<PacketHeader, PacketInfo> _clientPacketTable; + std::map<PacketHeader, PacketInfo> _serverPacketTable; + }; +} + +#define sPacketManager Battlenet::PacketManager::Instance() + +#endif // PacketManager_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h b/src/server/bnetserver/Packets/Packets.h index 15c609b3ba4..f62ba6f65cd 100644 --- a/src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h +++ b/src/server/bnetserver/Packets/Packets.h @@ -15,11 +15,18 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef BattlenetPackets_h__ -#define BattlenetPackets_h__ +#ifndef Packets_h__ +#define Packets_h__ #include "AuthenticationPackets.h" #include "ConnectionPackets.h" #include "WoWRealmPackets.h" +#include "FriendsPackets.h" +#include "PresencePackets.h" +#include "ChatPackets.h" +#include "SupportPackets.h" +#include "AchievementPackets.h" +#include "CachePackets.h" +#include "ProfilePackets.h" -#endif // BattlenetPackets_h__ +#endif // Packets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp b/src/server/bnetserver/Packets/PacketsBase.cpp index 034bb8ba0a4..fd3bebcf471 100644 --- a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp +++ b/src/server/bnetserver/Packets/PacketsBase.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "BattlenetPackets.h" +#include "Packets.h" +#include "Session.h" #include <sstream> std::string Battlenet::PacketHeader::ToString() const @@ -36,3 +37,8 @@ Battlenet::ServerPacket::~ServerPacket() { delete &_stream; } + +void Battlenet::ClientPacket::CallHandler(Session* session) +{ + session->LogUnhandledPacket(GetHeader()); +} diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h b/src/server/bnetserver/Packets/PacketsBase.h index af02eb91f43..0f86621d6a6 100644 --- a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h +++ b/src/server/bnetserver/Packets/PacketsBase.h @@ -15,12 +15,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef BattlenetPacketsBase_h__ -#define BattlenetPacketsBase_h__ +#ifndef PacketsBase_h__ +#define PacketsBase_h__ #include "AuthCodes.h" -#include "BattlenetBitStream.h" -#include "BattlenetManager.h" +#include "BitStream.h" #include "Define.h" #include "Errors.h" #include <string> @@ -31,13 +30,14 @@ using boost::asio::ip::tcp; namespace Battlenet { class BitStream; + class Session; enum Channel { AUTHENTICATION = 0, CONNECTION = 1, WOWREALM = 2, - FRIEND = 3, + FRIENDS = 3, PRESENCE = 4, CHAT = 5, SUPPORT = 7, @@ -99,7 +99,8 @@ namespace Battlenet public: ClientPacket(PacketHeader const& header, BitStream& stream) : Packet(header, stream) { } - void Write() override final { ASSERT(!"Write not implemented for this packet."); } + void Write() override final { ASSERT(!"Write not implemented for client packets."); } + virtual void CallHandler(Session* session); }; class ServerPacket : public Packet @@ -116,4 +117,4 @@ namespace Battlenet }; } -#endif // BattlenetPacketsBase_h__ +#endif // PacketsBase_h__ diff --git a/src/server/bnetserver/Packets/PresencePackets.cpp b/src/server/bnetserver/Packets/PresencePackets.cpp new file mode 100644 index 00000000000..b72bf8daca8 --- /dev/null +++ b/src/server/bnetserver/Packets/PresencePackets.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Session.h" +#include "PresencePackets.h" + +void Battlenet::Presence::UpdateRequest::Read() +{ + +} + +std::string Battlenet::Presence::UpdateRequest::ToString() const +{ + return "Battlenet::Presence::UpdateRequest"; +} + +void Battlenet::Presence::StatisticSubscribe::Read() +{ +} + +std::string Battlenet::Presence::StatisticSubscribe::ToString() const +{ + return "Battlenet::Presence::StatisticSubscribe"; +} diff --git a/src/server/bnetserver/Packets/PresencePackets.h b/src/server/bnetserver/Packets/PresencePackets.h new file mode 100644 index 00000000000..45b8f3e0e82 --- /dev/null +++ b/src/server/bnetserver/Packets/PresencePackets.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PresencePackets_h__ +#define PresencePackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Presence + { + enum Opcode + { + CMSG_UPDATE_REQUEST = 0x0, // Not implemented + CMSG_STATISTIC_SUBSCRIBE = 0x2, // Not implemented + + SMSG_UPDATE_NOTIFY = 0x0, // Not implemented + SMSG_FIELD_SPEC_ANNOUNCE = 0x1, // Not implemented + SMSG_STATISTICS_UPDATE = 0x3 // Not implemented + }; + + class UpdateRequest final : public ClientPacket + { + public: + UpdateRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_UPDATE_REQUEST, PRESENCE) && "Invalid packet header for UpdateRequest"); + } + + void Read() override; + std::string ToString() const override; + }; + + class StatisticSubscribe final : public ClientPacket + { + public: + StatisticSubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_STATISTIC_SUBSCRIBE, PRESENCE) && "Invalid packet header for StatisticSubscribe"); + } + + void Read() override; + std::string ToString() const override; + }; + } +} + +#endif // PresencePackets_h__ diff --git a/src/server/bnetserver/Packets/ProfilePackets.h b/src/server/bnetserver/Packets/ProfilePackets.h new file mode 100644 index 00000000000..bf413471f62 --- /dev/null +++ b/src/server/bnetserver/Packets/ProfilePackets.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ProfilePackets_h__ +#define ProfilePackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Profile + { + enum Opcode + { + CMSG_READ_REQUEST = 0x0, // Not implemented + CMSG_ADDRESS_QUERY_REQUEST = 0x1, // Not implemented + CMSG_RESOLVE_TOON_HANDLE_TO_NAME_REQUEST = 0x2, // Not implemented + CMSG_RESOLVE_TOON_NAME_TO_HANDLE_REQUEST = 0x3, // Not implemented + CMSG_CHANGE_SETTINGS = 0x5, // Not implemented + + SMSG_READ_RESPONSE = 0x0, // Not implemented + SMSG_ADDRESS_QUERY_RESPONSE = 0x1, // Not implemented + SMSG_RESOLVE_TOON_HANDLE_TO_NAME_RESPONSE = 0x2, // Not implemented + SMSG_RESOLVE_TOON_NAME_TO_HANDLE_RESPONSE = 0x3, // Not implemented + SMSG_SETTINGS_AVAILABLE = 0x4 // Not implemented + }; + } +} + +#endif // ProfilePackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp b/src/server/bnetserver/Packets/SupportPackets.h index 9f53961c6ab..43f51bd564e 100644 --- a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp +++ b/src/server/bnetserver/Packets/SupportPackets.h @@ -15,9 +15,20 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ConnectionPackets.h" +#ifndef SupportPackets_h__ +#define SupportPackets_h__ -std::string Battlenet::Connection::Pong::ToString() const +#include "PacketsBase.h" + +namespace Battlenet { - return "Battlenet::Connection::Pong"; + namespace Support + { + enum Opcode + { + CMSG_COMPLAINT_REQUEST = 0x0 // Not implemented + }; + } } + +#endif // SupportPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp b/src/server/bnetserver/Packets/WoWRealmPackets.cpp index 76577670a50..714c43b8eb4 100644 --- a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp +++ b/src/server/bnetserver/Packets/WoWRealmPackets.cpp @@ -16,9 +16,50 @@ */ #include "WoWRealmPackets.h" +#include "Session.h" #include <boost/lexical_cast.hpp> #include <boost/asio/ip/address.hpp> +std::string Battlenet::WoWRealm::ListSubscribeRequest::ToString() const +{ + return "Battlenet::WoWRealm::ListSubscribeRequest"; +} + +void Battlenet::WoWRealm::ListSubscribeRequest::CallHandler(Session* session) +{ + session->HandleListSubscribeRequest(*this); +} + +std::string Battlenet::WoWRealm::ListUnsubscribe::ToString() const +{ + return "Battlenet::WoWRealm::ListUnsubscribe"; +} + +void Battlenet::WoWRealm::ListUnsubscribe::CallHandler(Session* session) +{ + session->HandleListUnsubscribe(*this); +} + +void Battlenet::WoWRealm::JoinRequestV2::Read() +{ + Realm.Battlegroup = _stream.Read<uint8>(8); + Realm.Index = _stream.Read<uint32>(32); + Realm.Region = _stream.Read<uint8>(8); + ClientSeed = _stream.Read<uint32>(32); +} + +std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::WoWRealm::JoinRequestV2 ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Battlegroup) << " Index " << Realm.Index; + return stream.str().c_str(); +} + +void Battlenet::WoWRealm::JoinRequestV2::CallHandler(Session* session) +{ + session->HandleJoinRequestV2(*this); +} + Battlenet::WoWRealm::ListSubscribeResponse::~ListSubscribeResponse() { for (ServerPacket* realmData : RealmData) @@ -86,7 +127,7 @@ void Battlenet::WoWRealm::ListUpdate::Write() if (!Version.empty()) { _stream.WriteString(Version, 5); - _stream.Write(Build, 32); + _stream.Write(Id.Build, 32); boost::asio::ip::address_v4::bytes_type ip = Address.address().to_v4().to_bytes(); uint16 port = Address.port(); @@ -101,38 +142,53 @@ void Battlenet::WoWRealm::ListUpdate::Write() _stream.Write(Flags, 8); } - _stream.Write(Region, 8); + _stream.Write(Id.Region, 8); _stream.Write(0, 12); - _stream.Write(Battlegroup, 8); - _stream.Write(Index, 32); + _stream.Write(Id.Battlegroup, 8); + _stream.Write(Id.Index, 32); } std::string Battlenet::WoWRealm::ListUpdate::ToString() const { std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListUpdate Timezone " << Timezone << " Population " << Population << " Lock " << uint32(Lock) << " Type " << Type << " Name " << Name - << " Flags " << uint32(Flags) << " Region " << uint32(Region) << " Battlegroup " << uint32(Battlegroup) << " Index " << Index; + stream << "Battlenet::WoWRealm::ListUpdate"; + if (UpdateState == UPDATE) + { + stream << " Timezone: " << Timezone << " Population: " << Population << " Lock: " << uint32(Lock) << " Type: " << Type << " Name: " << Name + << " Flags: " << uint32(Flags) << " Region: " << uint32(Id.Region) << " Battlegroup: " << uint32(Id.Battlegroup) << " Index: " << Id.Index; - if (!Version.empty()) - stream << " Version " << Version; + if (!Version.empty()) + stream << " Version: " << Version; + } + else + stream << " Delete realm [Region: " << uint32(Id.Region) << " Battlegroup : " << uint32(Id.Battlegroup) << " Index : " << Id.Index << "]"; return stream.str().c_str(); } -void Battlenet::WoWRealm::JoinRequestV2::Read() +void Battlenet::WoWRealm::ToonReady::Write() { - ClientSeed = _stream.Read<uint32>(32); - _stream.Read<uint32>(20); - Realm.Region = _stream.Read<uint8>(8); - _stream.Read<uint32>(12); - Realm.Battlegroup = _stream.Read<uint8>(8); - Realm.Index = _stream.Read<uint32>(32); + _stream.Write(Realm.Region, 8); + _stream.WriteFourCC(Game); + uint32 realmAddress = ((Realm.Battlegroup << 16) & 0xFF0000) | uint16(Realm.Index); + _stream.Write(realmAddress, 32); + _stream.WriteString(Name, 7, -2); + _stream.WriteSkip(21); + _stream.Write(0, 64); // Unknown + _stream.Write(0, 32); // Unknown + _stream.Write(Guid, 64); + _stream.Write(realmAddress, 32); + _stream.Write(Realm.Region, 8); + _stream.WriteFourCC(Game); } -std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const +std::string Battlenet::WoWRealm::ToonReady::ToString() const { std::ostringstream stream; - stream << "Battlenet::WoWRealm::JoinRequestV2 ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Battlegroup) << " Index " << Realm.Index; + stream << "Battlenet::WoWRealm::ToonReady" << " Game: " << Game + << ", Region: " << uint32(Realm.Region) << ", Battlegroup: " << uint32(Realm.Battlegroup) << ", Index: " << Realm.Index + << ", Guid: " << Guid << ", Name: " << Name; + return stream.str().c_str(); } diff --git a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h b/src/server/bnetserver/Packets/WoWRealmPackets.h index 881ddd3186a..b411c63100a 100644 --- a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h +++ b/src/server/bnetserver/Packets/WoWRealmPackets.h @@ -18,7 +18,8 @@ #ifndef WoWRealmPackets_h__ #define WoWRealmPackets_h__ -#include "BattlenetPacketsBase.h" +#include "PacketsBase.h" +#include "RealmList.h" namespace Battlenet { @@ -27,7 +28,7 @@ namespace Battlenet enum Opcode { CMSG_LIST_SUBSCRIBE_REQUEST = 0x0, - CMSG_LIST_UNSUBSCRIBE = 0x1, // Not implemented + CMSG_LIST_UNSUBSCRIBE = 0x1, CMSG_JOIN_REQUEST_V2 = 0x8, CMSG_MULTI_LOGON_REQUEST_V2 = 0x9, // Not implemented @@ -39,6 +40,32 @@ namespace Battlenet SMSG_JOIN_RESPONSE_V2 = 0x8 }; + class ListSubscribeRequest final : public ClientPacket + { + public: + ListSubscribeRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM) && "Invalid packet header for ListSubscribeRequest"); + } + + void Read() override { } + std::string ToString() const override; + void CallHandler(Session* session) override; + }; + + class ListUnsubscribe final : public ClientPacket + { + public: + ListUnsubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_LIST_UNSUBSCRIBE, WOWREALM) && "Invalid packet header for ListUnsubscribe"); + } + + void Read() override { } + std::string ToString() const override; + void CallHandler(Session* session) override; + }; + class JoinRequestV2 final : public ClientPacket { public: @@ -49,6 +76,7 @@ namespace Battlenet void Read() override; std::string ToString() const override; + void CallHandler(Session* session) override; uint32 ClientSeed; RealmId Realm; @@ -95,8 +123,7 @@ namespace Battlenet }; ListUpdate() : ServerPacket(PacketHeader(SMSG_LIST_UPDATE, WOWREALM)), UpdateState(UPDATE), - Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""), - Flags(0), Region(0), Battlegroup(0), Index(0), Build(0) + Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""), Flags(0) { } @@ -112,10 +139,7 @@ namespace Battlenet std::string Version; tcp::endpoint Address; uint8 Flags; - uint8 Region; - uint8 Battlegroup; - uint32 Index; - uint32 Build; + RealmId Id; }; class ListComplete final : public ServerPacket @@ -129,6 +153,33 @@ namespace Battlenet std::string ToString() const override { return "Battlenet::WoWRealm::ListComplete"; } }; + class ToonReady final : public ServerPacket + { + public: + ToonReady() : ServerPacket(PacketHeader(SMSG_TOON_READY, WOWREALM)), Game("WoW"), Guid(0) + { + } + + void Write() override; + std::string ToString() const override; + + std::string Game; + RealmId Realm; + uint64 Guid; + std::string Name; + }; + + class ToonLoggedOut final : public ServerPacket + { + public: + ToonLoggedOut() : ServerPacket(PacketHeader(SMSG_TOON_LOGGED_OUT, WOWREALM)) + { + } + + void Write() override { } + std::string ToString() const override { return "Battlenet::WoWRealm::ToonLoggedOut"; } + }; + class JoinResponseV2 final : public ServerPacket { public: @@ -139,7 +190,7 @@ namespace Battlenet }; JoinResponseV2() : ServerPacket(PacketHeader(SMSG_JOIN_RESPONSE_V2, WOWREALM)), - ServerSeed(0), Response(SUCCESS), ResponseCode(26) + Response(SUCCESS), ResponseCode(26), ServerSeed(0) { } diff --git a/src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp new file mode 100644 index 00000000000..60b1d41a1a8 --- /dev/null +++ b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp @@ -0,0 +1 @@ +#include "bnetPCH.h" diff --git a/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h new file mode 100644 index 00000000000..82cd5393489 --- /dev/null +++ b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h @@ -0,0 +1,10 @@ +#include "Common.h" +#include "Configuration/Config.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "ComponentManager.h" +#include "ModuleManager.h" +#include "RealmList.h" +#include "ByteBuffer.h" +#include "Packets.h" +#include "Session.h" diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp new file mode 100644 index 00000000000..cc7e1d492a8 --- /dev/null +++ b/src/server/bnetserver/Realms/RealmList.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "SessionManager.h" +#include "Util.h" +#include "Commands.h" +#include "RealmList.h" +#include <boost/asio/ip/tcp.hpp> + +Battlenet::RealmId& Battlenet::RealmId::operator=(Battlenet::RealmHandle const& handle) +{ + Region = handle.Region; + Battlegroup = handle.Battlegroup; + Index = handle.Index; + return *this; +} + +ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const +{ + ip::address realmIp; + + // Attempt to send best address for client + if (clientAddr.is_loopback()) + { + // Try guessing if realm is also connected locally + if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) + realmIp = clientAddr; + else + { + // Assume that user connecting from the machine that bnetserver is located on + // has all realms available in his local network + realmIp = LocalAddress; + } + } + else + { + if (clientAddr.is_v4() && + (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == + (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) + { + realmIp = LocalAddress; + } + else + realmIp = ExternalAddress; + } + + ip::tcp::endpoint endpoint(realmIp, Port); + + // Return external IP + return endpoint; +} + +RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr), _worldListener(nullptr) +{ +} + +RealmList::~RealmList() +{ + delete _updateTimer; + delete _resolver; + delete _worldListener; +} + +// Load the realm list from the database +void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval, uint16 worldListenPort) +{ + _updateInterval = updateInterval; + _updateTimer = new boost::asio::deadline_timer(ioService); + _resolver = new boost::asio::ip::tcp::resolver(ioService); + + // Get the content of the realmlist table in the database + UpdateRealms(boost::system::error_code()); + + _worldListener = new WorldListener(worldListenPort); + _worldListener->Start(); +} + +void RealmList::Close() +{ + _worldListener->End(); +} + +template<typename FieldType> +inline void UpdateField(FieldType& out, FieldType const& in, bool& changed) +{ + if (out != in) + { + out = in; + changed = true; + } +} + +void RealmList::UpdateRealm(Battlenet::RealmId const& id, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, + float population) +{ + // Create new if not exist or update existed + Realm& realm = _realms[id]; + + realm.Keep = true; + + realm.Id = id; + UpdateField(realm.Name, name, realm.Updated); + UpdateField(realm.Type, icon, realm.Updated); + UpdateField(realm.Flags, flag, realm.Updated); + UpdateField(realm.Timezone, timezone, realm.Updated); + UpdateField(realm.AllowedSecurityLevel, allowedSecurityLevel, realm.Updated); + UpdateField(realm.PopulationLevel, population, realm.Updated); + UpdateField(realm.ExternalAddress, address, realm.Updated); + UpdateField(realm.LocalAddress, localAddr, realm.Updated); + UpdateField(realm.LocalSubnetMask, localSubmask, realm.Updated); + UpdateField(realm.Port, port, realm.Updated); +} + +void RealmList::UpdateRealms(boost::system::error_code const& error) +{ + if (error) + return; + + TC_LOG_DEBUG("realmlist", "Updating Realm List..."); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + // Circle through results and add them to the realm map + if (result) + { + do + { + try + { + boost::asio::ip::tcp::resolver::iterator end; + + Field* fields = result->Fetch(); + std::string name = fields[1].GetString(); + boost::asio::ip::tcp::resolver::query externalAddressQuery(ip::tcp::v4(), fields[2].GetString(), ""); + + boost::system::error_code ec; + boost::asio::ip::tcp::resolver::iterator endPoint = _resolver->resolve(externalAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("realmlist", "Could not resolve address %s", fields[2].GetString().c_str()); + continue; + } + + ip::address externalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localAddressQuery(ip::tcp::v4(), fields[3].GetString(), ""); + endPoint = _resolver->resolve(localAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("realmlist", "Could not resolve address %s", fields[3].GetString().c_str()); + continue; + } + + ip::address localAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localSubmaskQuery(ip::tcp::v4(), fields[4].GetString(), ""); + endPoint = _resolver->resolve(localSubmaskQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("realmlist", "Could not resolve address %s", fields[4].GetString().c_str()); + continue; + } + + ip::address localSubmask = (*endPoint).endpoint().address(); + + uint16 port = fields[5].GetUInt16(); + uint8 icon = fields[6].GetUInt8(); + RealmFlags flag = RealmFlags(fields[7].GetUInt8()); + uint8 timezone = fields[8].GetUInt8(); + uint8 allowedSecurityLevel = fields[9].GetUInt8(); + float pop = fields[10].GetFloat(); + uint32 realmId = fields[0].GetUInt32(); + uint32 build = fields[11].GetUInt32(); + uint8 region = fields[12].GetUInt8(); + uint8 battlegroup = fields[13].GetUInt8(); + + Battlenet::RealmId id{ region, battlegroup, realmId, build }; + + UpdateRealm(id, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone, + (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); + + TC_LOG_TRACE("realmlist", "Realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + } + catch (std::exception& ex) + { + TC_LOG_ERROR("realmlist", "Realmlist::UpdateRealms has thrown an exception: %s", ex.what()); + ASSERT(false); + } + } + while (result->NextRow()); + } + + std::vector<Realm const*> updatedRealms; + std::vector<Battlenet::RealmId> deletedRealms; + + for (RealmMap::value_type& pair : _realms) + { + if (pair.second.Updated) + updatedRealms.push_back(&pair.second); + else if (!pair.second.Keep) + deletedRealms.push_back(pair.first); + + pair.second.Updated = false; + pair.second.Keep = false; + } + + for (Battlenet::RealmId const& deleted : deletedRealms) + _realms.erase(deleted); + + if (!updatedRealms.empty() || !deletedRealms.empty()) + { + sSessionMgr.LockedForEach([&updatedRealms, &deletedRealms](Battlenet::Session* session) + { + if (session->IsSubscribedToRealmListUpdates()) + session->UpdateRealms(updatedRealms, deletedRealms); + }); + } + + if (_updateInterval) + { + _updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval)); + _updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, std::placeholders::_1)); + } +} + +Realm const* RealmList::GetRealm(Battlenet::RealmId const& id) const +{ + auto itr = _realms.find(id); + if (itr != _realms.end()) + return &itr->second; + + return NULL; +} diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h new file mode 100644 index 00000000000..dc78a00dfdd --- /dev/null +++ b/src/server/bnetserver/Realms/RealmList.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * 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 _REALMLIST_H +#define _REALMLIST_H + +#include "Common.h" +#include "WorldListener.h" +#include <boost/asio/ip/address.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/deadline_timer.hpp> + +using namespace boost::asio; + +enum RealmFlags +{ + REALM_FLAG_NONE = 0x00, + REALM_FLAG_INVALID = 0x01, + REALM_FLAG_OFFLINE = 0x02, + REALM_FLAG_SPECIFYBUILD = 0x04, + REALM_FLAG_UNK1 = 0x08, + REALM_FLAG_UNK2 = 0x10, + REALM_FLAG_RECOMMENDED = 0x20, + REALM_FLAG_NEW = 0x40, + REALM_FLAG_FULL = 0x80 +}; + +#pragma pack(push, 1) + +namespace Battlenet +{ + struct RealmHandle; + + struct RealmId + { + RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { } + RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build) + : Region(region), Battlegroup(battlegroup), Index(index), Build(build) { } + + uint8 Region; + uint8 Battlegroup; + uint32 Index; + uint32 Build; + + bool operator<(RealmId const& r) const + { + return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0; + } + + RealmId& operator=(RealmHandle const& handle); + }; +} + +#pragma pack(pop) + +// Storage object for a realm +struct Realm +{ + Battlenet::RealmId Id; + ip::address ExternalAddress; + ip::address LocalAddress; + ip::address LocalSubnetMask; + uint16 Port; + std::string Name; + uint8 Type; + RealmFlags Flags; + uint8 Timezone; + AccountTypes AllowedSecurityLevel; + float PopulationLevel; + bool Updated; + bool Keep; + + ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; +}; + +/// Storage object for the list of realms on the server +class RealmList +{ +public: + typedef std::map<Battlenet::RealmId, Realm> RealmMap; + + static RealmList* instance() + { + static RealmList instance; + return &instance; + } + + ~RealmList(); + + void Initialize(boost::asio::io_service& ioService, uint32 updateInterval, uint16 worldListenPort); + void Close(); + + RealmMap const& GetRealms() const { return _realms; } + Realm const* GetRealm(Battlenet::RealmId const& id) const; + +private: + RealmList(); + + void UpdateRealms(boost::system::error_code const& error); + void UpdateRealm(Battlenet::RealmId const& id, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); + + RealmMap _realms; + uint32 _updateInterval; + boost::asio::deadline_timer* _updateTimer; + boost::asio::ip::tcp::resolver* _resolver; + WorldListener* _worldListener; +}; + +#define sRealmList RealmList::instance() +#endif diff --git a/src/server/bnetserver/Realms/WorldListener.cpp b/src/server/bnetserver/Realms/WorldListener.cpp new file mode 100644 index 00000000000..30886a67310 --- /dev/null +++ b/src/server/bnetserver/Realms/WorldListener.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Log.h" +#include "SessionManager.h" +#include "WoWRealmPackets.h" +#include "ZmqContext.h" +#include "WorldListener.h" + +WorldListener::HandlerTable const WorldListener::_handlers; + +WorldListener::HandlerTable::HandlerTable() +{ +#define DEFINE_HANDLER(opc, func) _handlers[opc] = { func, #opc } + + DEFINE_HANDLER(BNET_CHANGE_TOON_ONLINE_STATE, &WorldListener::HandleToonOnlineStatusChange); + +#undef DEFINE_HANDLER +} + +WorldListener::WorldListener(uint16 worldListenPort) : _worldListenPort(worldListenPort) +{ + _worldSocket = sIpcContext->CreateNewSocket(zmqpp::socket_type::pull); +} + +WorldListener::~WorldListener() +{ + delete _worldSocket; +} + +void WorldListener::Run() +{ + while (!ProcessExit()) + { + _poller->poll(); + if (_poller->events(*_worldSocket) & zmqpp::poller::poll_in) + { + int32 op1; + do + { + zmqpp::message msg; + _worldSocket->receive(msg); + Dispatch(msg); + _worldSocket->get(zmqpp::socket_option::events, op1); + } while (op1 & zmqpp::poller::poll_in); + } + } +} + +void WorldListener::HandleOpen() +{ + _worldSocket->bind(std::string("tcp://*:") + std::to_string(_worldListenPort)); + _poller->add(*_worldSocket); + TC_LOG_INFO("server.ipc", "Listening on connections from worldservers..."); +} + +void WorldListener::HandleClose() +{ + _worldSocket->close(); + TC_LOG_INFO("server.ipc", "Shutting down connections from worldservers..."); +} + +void WorldListener::Dispatch(zmqpp::message& msg) const +{ + Battlenet::Header ipcHeader; + msg >> ipcHeader; + + if (ipcHeader.Ipc.Channel != IPC_CHANNEL_BNET) + return; + + if (ipcHeader.Ipc.Command < IPC_BNET_MAX_COMMAND) + (this->*_handlers[ipcHeader.Ipc.Command].Handler)(ipcHeader.Realm, msg); +} + +void WorldListener::HandleToonOnlineStatusChange(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const +{ + Battlenet::ToonHandle toonHandle; + bool online; + msg >> toonHandle; + msg >> online; + + if (Battlenet::Session* session = sSessionMgr.GetSession(toonHandle.AccountId, toonHandle.GameAccountId)) + { + if (online) + { + Battlenet::WoWRealm::ToonReady* toonReady = new Battlenet::WoWRealm::ToonReady(); + toonReady->Realm = realm; + toonReady->Guid = toonHandle.Guid; + toonReady->Name = toonHandle.Name; + session->AsyncWrite(toonReady); + } + else + session->AsyncWrite(new Battlenet::WoWRealm::ToonLoggedOut()); + } +} diff --git a/src/server/bnetserver/Realms/WorldListener.h b/src/server/bnetserver/Realms/WorldListener.h new file mode 100644 index 00000000000..04d5342449c --- /dev/null +++ b/src/server/bnetserver/Realms/WorldListener.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WorldListener_h__ +#define WorldListener_h__ + +#include "ZMQTask.h" +#include "Commands.h" + +class WorldListener : public ZMQTask +{ +public: + explicit WorldListener(uint16 worldListenPort); + ~WorldListener(); + void Run() override; + +protected: + void HandleOpen() override; + void HandleClose() override; + +private: + void Dispatch(zmqpp::message& msg) const; + + typedef void(WorldListener::*PacketHandler)(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const; + class HandlerTable + { + public: + HandlerTable(); + + struct HandlerInfo + { + PacketHandler Handler; + char const* Name; + }; + + HandlerInfo const& operator[](uint8 opcode) const { return _handlers[opcode]; } + + private: + HandlerInfo _handlers[IPC_BNET_MAX_COMMAND]; + }; + + void HandleToonOnlineStatusChange(Battlenet::RealmHandle const& realm, zmqpp::message& msg) const; + + zmqpp::socket* _worldSocket; + uint16 _worldListenPort; + static HandlerTable const _handlers; +}; + +#endif // WorldListener_h__ diff --git a/src/server/bnetserver/Server/ComponentManager.cpp b/src/server/bnetserver/Server/ComponentManager.cpp new file mode 100644 index 00000000000..be1f22022f4 --- /dev/null +++ b/src/server/bnetserver/Server/ComponentManager.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ComponentManager.h" +#include "DatabaseEnv.h" + +Battlenet::ComponentMgr::~ComponentMgr() +{ + for (Component* component : _components) + delete component; +} + +void Battlenet::ComponentMgr::Load() +{ + QueryResult result = LoginDatabase.Query("SELECT Program, Platform, Build FROM battlenet_components"); + if (result) + { + do + { + Field* fields = result->Fetch(); + Component* component = new Component(); + component->Program = fields[0].GetString(); + component->Platform = fields[1].GetString(); + component->Build = fields[2].GetUInt32(); + + _components.insert(component); + _programs.insert(component->Program); + _platforms.insert(component->Platform); + + } while (result->NextRow()); + } +} + +bool Battlenet::ComponentMgr::HasComponent(Battlenet::Component const* component) const +{ + for (Component const* c : _components) + if (component->Program == c->Program && component->Platform == c->Platform && component->Build == c->Build) + return true; + + return false; +} diff --git a/src/server/bnetserver/Server/ComponentManager.h b/src/server/bnetserver/Server/ComponentManager.h new file mode 100644 index 00000000000..865cfca7f62 --- /dev/null +++ b/src/server/bnetserver/Server/ComponentManager.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ComponentManager_h__ +#define ComponentManager_h__ + +#include "Define.h" +#include <cstring> +#include <string> +#include <set> + +namespace Battlenet +{ + struct Component + { + std::string Program; + std::string Platform; + uint32 Build; + }; + + class ComponentMgr + { + ComponentMgr() { } + ~ComponentMgr(); + + public: + void Load(); + bool HasComponent(Component const* component) const; + bool HasProgram(std::string const& program) const { return _programs.count(program) != 0; } + bool HasPlatform(std::string const& platform) const { return _platforms.count(platform) != 0; } + + static ComponentMgr* instance() + { + static ComponentMgr instance; + return &instance; + } + + private: + std::set<Component*> _components; + std::set<std::string> _programs; + std::set<std::string> _platforms; + }; +} + +#define sComponentMgr Battlenet::ComponentMgr::instance() + +#endif // ComponentManager_h__ diff --git a/src/server/authserver/Server/BattlenetManager.cpp b/src/server/bnetserver/Server/ModuleManager.cpp index f470c365b56..05cee2ff42e 100644 --- a/src/server/authserver/Server/BattlenetManager.cpp +++ b/src/server/bnetserver/Server/ModuleManager.cpp @@ -15,46 +15,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "BattlenetManager.h" +#include "ModuleManager.h" #include "DatabaseEnv.h" -BattlenetMgr::~BattlenetMgr() +Battlenet::ModuleManager::~ModuleManager() { - for (Battlenet::Component* component : _components) - delete component; - for (auto const& m : _modules) delete m.second; } -void BattlenetMgr::Load() -{ - LoadComponents(); - LoadModules(); -} - -void BattlenetMgr::LoadComponents() -{ - QueryResult result = LoginDatabase.Query("SELECT Program, Platform, Build FROM battlenet_components"); - if (result) - { - do - { - Field* fields = result->Fetch(); - Battlenet::Component* component = new Battlenet::Component(); - component->Program = fields[0].GetString(); - component->Platform = fields[1].GetString(); - component->Build = fields[2].GetUInt32(); - - _components.insert(component); - _programs.insert(component->Program); - _platforms.insert(component->Platform); - - } while (result->NextRow()); - } -} - -void BattlenetMgr::LoadModules() +void Battlenet::ModuleManager::Load() { QueryResult result = LoginDatabase.Query("SELECT `Hash`, `Name`, `Type`, `System`, `Data` FROM battlenet_modules"); if (result) @@ -62,7 +32,7 @@ void BattlenetMgr::LoadModules() do { Field* fields = result->Fetch(); - Battlenet::ModuleInfo* module = new Battlenet::ModuleInfo(); + ModuleInfo* module = new ModuleInfo(); module->Type = fields[2].GetString(); HexStrToByteArray(fields[0].GetString(), module->ModuleId); std::string data = fields[4].GetString(); @@ -78,19 +48,11 @@ void BattlenetMgr::LoadModules() } } -bool BattlenetMgr::HasComponent(Battlenet::Component const* component) const -{ - for (Battlenet::Component const* c : _components) - if (component->Program == c->Program && component->Platform == c->Platform && component->Build == c->Build) - return true; - - return false; -} - -Battlenet::ModuleInfo* BattlenetMgr::CreateModule(std::string const& os, std::string const& name) const +Battlenet::ModuleInfo* Battlenet::ModuleManager::CreateModule(std::string const& os, std::string const& name) const { - Battlenet::ModuleKey key { os, name }; - ASSERT(_modules.count(key)); + ModuleKey key { os, name }; + if (!_modules.count(key)) + return nullptr; - return new Battlenet::ModuleInfo(*_modules.at(key)); + return new ModuleInfo(*_modules.at(key)); } diff --git a/src/server/authserver/Server/BattlenetManager.h b/src/server/bnetserver/Server/ModuleManager.h index bd01619ef06..36ffb2fec3f 100644 --- a/src/server/authserver/Server/BattlenetManager.h +++ b/src/server/bnetserver/Server/ModuleManager.h @@ -15,24 +15,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __BATTLENETMANAGER_H__ -#define __BATTLENETMANAGER_H__ +#ifndef ModuleManager_h__ +#define ModuleManager_h__ #include "Define.h" #include <cstring> #include <string> -#include <set> #include <map> namespace Battlenet { - struct Component - { - std::string Program; - std::string Platform; - uint32 Build; - }; - struct ModuleKey { std::string Platform; @@ -74,43 +66,29 @@ namespace Battlenet uint8* Data; }; - struct RealmId + class ModuleManager { - uint8 Region; - uint8 Battlegroup; - uint32 Index; - uint32 Build; - }; -} + ModuleManager() { } + ~ModuleManager(); -class BattlenetMgr -{ - BattlenetMgr() { } - ~BattlenetMgr(); + public: + void Load(); + ModuleInfo* CreateModule(std::string const& os, std::string const& name) const; -public: - void Load(); - bool HasComponent(Battlenet::Component const* component) const; - bool HasProgram(std::string const& program) const { return _programs.count(program) != 0; } - bool HasPlatform(std::string const& platform) const { return _platforms.count(platform) != 0; } - Battlenet::ModuleInfo* CreateModule(std::string const& os, std::string const& name) const; - - static BattlenetMgr* instance() - { - static BattlenetMgr instance; - return &instance; - } + static ModuleManager* instance() + { + static ModuleManager instance; + return &instance; + } -private: - void LoadComponents(); - void LoadModules(); + private: + void LoadComponents(); + void LoadModules(); - std::set<Battlenet::Component*> _components; - std::set<std::string> _programs; - std::set<std::string> _platforms; - std::map<Battlenet::ModuleKey, Battlenet::ModuleInfo*> _modules; -}; + std::map<ModuleKey, ModuleInfo*> _modules; + }; +} -#define sBattlenetMgr BattlenetMgr::instance() +#define sModuleMgr Battlenet::ModuleManager::instance() -#endif // __BATTLENETMANAGER_H__ +#endif // ModuleManager_h__ diff --git a/src/server/authserver/Server/BattlenetSession.cpp b/src/server/bnetserver/Server/Session.cpp index 860c557b46a..edd00e5db2d 100644 --- a/src/server/authserver/Server/BattlenetSession.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -16,35 +16,15 @@ */ #include "AuthCodes.h" -#include "BattlenetBitStream.h" -#include "BattlenetSessionManager.h" +#include "BitStream.h" +#include "PacketManager.h" +#include "SessionManager.h" #include "Database/DatabaseEnv.h" #include "HmacHash.h" #include "Log.h" #include "RealmList.h" #include "SHA256.h" #include <map> -#include <boost/asio/write.hpp> - -std::map<Battlenet::PacketHeader, Battlenet::Session::PacketHandler> InitHandlers() -{ - std::map<Battlenet::PacketHeader, Battlenet::Session::PacketHandler> handlers; - - handlers[Battlenet::PacketHeader(Battlenet::Authentication::CMSG_LOGON_REQUEST_3, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleLogonRequest; - handlers[Battlenet::PacketHeader(Battlenet::Authentication::CMSG_RESUME_REQUEST, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleResumeRequest; - handlers[Battlenet::PacketHeader(Battlenet::Authentication::CMSG_PROOF_RESPONSE, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleProofResponse; - - handlers[Battlenet::PacketHeader(Battlenet::Connection::CMSG_PING, Battlenet::CONNECTION)] = &Battlenet::Session::HandlePing; - handlers[Battlenet::PacketHeader(Battlenet::Connection::CMSG_ENABLE_ENCRYPTION, Battlenet::CONNECTION)] = &Battlenet::Session::HandleEnableEncryption; - handlers[Battlenet::PacketHeader(Battlenet::Connection::CMSG_LOGOUT_REQUEST, Battlenet::CONNECTION)] = &Battlenet::Session::HandleLogoutRequest; - - handlers[Battlenet::PacketHeader(Battlenet::WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, Battlenet::WOWREALM)] = &Battlenet::Session::HandleListSubscribeRequest; - handlers[Battlenet::PacketHeader(Battlenet::WoWRealm::CMSG_JOIN_REQUEST_V2, Battlenet::WOWREALM)] = &Battlenet::Session::HandleJoinRequestV2; - - return handlers; -} - -std::map<Battlenet::PacketHeader, Battlenet::Session::PacketHandler> Handlers = InitHandlers(); Battlenet::Session::ModuleHandler const Battlenet::Session::ModuleHandlers[MODULE_COUNT] = { @@ -58,7 +38,7 @@ Battlenet::Session::ModuleHandler const Battlenet::Session::ModuleHandlers[MODUL Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _accountId(0), _accountName(), _locale(), _os(), _build(0), _gameAccountId(0), _gameAccountName(), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(), - _reconnectProof(), _crypt(), _authed(false) + _reconnectProof(), _crypt(), _authed(false), _subscribedToRealmListUpdates(false) { static uint8 const N_Bytes[] = { @@ -83,8 +63,7 @@ Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _ Battlenet::Session::~Session() { - sBattlenetSessionMgr.RemoveSession(this); - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::OnClose"); + sSessionMgr.RemoveSession(this); } void Battlenet::Session::_SetVSFields(std::string const& pstr) @@ -109,7 +88,12 @@ void Battlenet::Session::_SetVSFields(std::string const& pstr) LoginDatabase.Execute(stmt); } -bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& packet) +void Battlenet::Session::LogUnhandledPacket(PacketHeader const& header) +{ + TC_LOG_DEBUG("session.packets", "%s Received unhandled packet %s", GetClientInfo().c_str(), sPacketManager.GetClientPacketName(header)); +} + +void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest) { // Verify that this IP is not in the ip_banned table LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); @@ -119,68 +103,65 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac stmt->setString(0, ip_address); if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_BANNED); - AsyncWrite(complete); - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Banned ip '%s:%d' tries to login!", ip_address.c_str(), GetRemotePort()); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(LOGIN_BANNED); + AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Banned ip '%s:%d' tries to login!", ip_address.c_str(), GetRemotePort()); + return; } - Authentication::LogonRequest3 info(header, packet); - info.Read(); - - if (info.Program != "WoW") + if (logonRequest.Program != "WoW") { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_INVALID_PROGRAM); - AsyncWrite(complete); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); + AsyncWrite(logonResponse); + return; } - if (!sBattlenetMgr->HasPlatform(info.Platform)) + if (!sComponentMgr->HasPlatform(logonRequest.Platform)) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_INVALID_OS); - AsyncWrite(complete); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_INVALID_OS); + AsyncWrite(logonResponse); + return; } - if (!sBattlenetMgr->HasPlatform(info.Locale)) + if (!sComponentMgr->HasPlatform(logonRequest.Locale)) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); - AsyncWrite(complete); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); + AsyncWrite(logonResponse); + return; } - for (Component const& component : info.Components) + for (Component const& component : logonRequest.Components) { - if (!sBattlenetMgr->HasComponent(&component)) + if (!sComponentMgr->HasComponent(&component)) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - if (!sBattlenetMgr->HasProgram(component.Program)) - complete->SetAuthResult(AUTH_INVALID_PROGRAM); - else if (!sBattlenetMgr->HasPlatform(component.Platform)) - complete->SetAuthResult(AUTH_INVALID_OS); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + if (!sComponentMgr->HasProgram(component.Program)) + logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); + else if (!sComponentMgr->HasPlatform(component.Platform)) + logonResponse->SetAuthResult(AUTH_INVALID_OS); else { if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build)) - complete->SetAuthResult(AUTH_REGION_BAD_VERSION); + logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION); else - complete->SetAuthResult(AUTH_USE_GRUNT_LOGON); + logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON); } - AsyncWrite(complete); - return true; + AsyncWrite(logonResponse); + return; } if (component.Platform == "base") _build = component.Build; } - _accountName = info.Login; - _locale = info.Locale; - _os = info.Platform; + _accountName = logonRequest.Login; + _locale = logonRequest.Locale; + _os = logonRequest.Platform; Utf8ToUpperOnlyLatin(_accountName); stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); @@ -189,10 +170,10 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - AsyncWrite(complete); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + AsyncWrite(logonResponse); + return; } Field* fields = result->Fetch(); @@ -202,22 +183,22 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac // If the IP is 'locked', check that the player comes indeed from the correct IP address if (fields[2].GetUInt8() == 1) // if ip is locked { - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str()); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str()); if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); - AsyncWrite(complete); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED); + AsyncWrite(logonResponse); + return; } } else { - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is not locked to ip", _accountName.c_str()); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to ip", _accountName.c_str()); std::string accountCountry = fields[3].GetString(); if (accountCountry.empty() || accountCountry == "00") - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is not locked to country", _accountName.c_str()); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to country", _accountName.c_str()); else if (!accountCountry.empty()) { uint32 ip = inet_addr(ip_address.c_str()); @@ -228,13 +209,13 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt)) { std::string loginCountry = (*sessionCountryQuery)[0].GetString(); - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str()); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str()); if (loginCountry != accountCountry) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); - AsyncWrite(complete); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED); + AsyncWrite(logonResponse); + return; } } } @@ -252,19 +233,19 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac Field* fields = banresult->Fetch(); if (fields[0].GetUInt32() == fields[1].GetUInt32()) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_BANNED); - AsyncWrite(complete); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(LOGIN_BANNED); + AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); + return; } else { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_SUSPENDED); - AsyncWrite(complete); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); - return true; + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(LOGIN_SUSPENDED); + AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); + return; } } @@ -274,8 +255,8 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac I.SetBinary(sha.GetDigest(), sha.GetLength()); - ModuleInfo* password = sBattlenetMgr->CreateModule(_os, "Password"); - ModuleInfo* thumbprint = sBattlenetMgr->CreateModule(_os, "Thumbprint"); + ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password"); + ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); std::string pStr = fields[0].GetString(); @@ -309,39 +290,33 @@ bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& pac _modulesWaitingForData.push(MODULE_PASSWORD); - Authentication::ProofRequest* request = new Authentication::ProofRequest(); - request->Modules.push_back(password); + Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); + proofRequest->Modules.push_back(password); // if has authenticator, send Token module - request->Modules.push_back(thumbprint); - AsyncWrite(request); - return true; + proofRequest->Modules.push_back(thumbprint); + AsyncWrite(proofRequest); } -bool Battlenet::Session::HandleResumeRequest(PacketHeader& header, BitStream& packet) +void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest) { - Authentication::ResumeRequest reconnect(header, packet); - reconnect.Read(); - - TC_LOG_DEBUG("server.battlenet", "%s", reconnect.ToString().c_str()); - - _accountName = reconnect.Login; - _locale = reconnect.Locale; - _os = reconnect.Platform; - auto baseComponent = std::find_if(reconnect.Components.begin(), reconnect.Components.end(), [](Component const& c) { return c.Program == "base"; }); - if (baseComponent != reconnect.Components.end()) + _accountName = resumeRequest.Login; + _locale = resumeRequest.Locale; + _os = resumeRequest.Platform; + auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; }); + if (baseComponent != resumeRequest.Components.end()) _build = baseComponent->Build; Utf8ToUpperOnlyLatin(_accountName); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); stmt->setString(0, _accountName); - stmt->setString(1, reconnect.GameAccountName); + stmt->setString(1, resumeRequest.GameAccountName); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { - Authentication::ResumeResponse* resume = new Authentication::ResumeResponse(); - resume->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - AsyncWrite(resume); - return false; + Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); + resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + AsyncWrite(resumeResponse); + return; } Field* fields = result->Fetch(); @@ -349,10 +324,10 @@ bool Battlenet::Session::HandleResumeRequest(PacketHeader& header, BitStream& pa _accountId = fields[0].GetUInt32(); K.SetHexStr(fields[1].GetString().c_str()); _gameAccountId = fields[2].GetUInt32(); - _gameAccountName = reconnect.GameAccountName; + _gameAccountName = resumeRequest.GameAccountName; - ModuleInfo* thumbprint = sBattlenetMgr->CreateModule(_os, "Thumbprint"); - ModuleInfo* resume = sBattlenetMgr->CreateModule(_os, "Resume"); + ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); + ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); BitStream resumeData; uint8 state = 0; _reconnectProof.SetRand(16 * 8); @@ -366,30 +341,26 @@ bool Battlenet::Session::HandleResumeRequest(PacketHeader& header, BitStream& pa _modulesWaitingForData.push(MODULE_RESUME); - Authentication::ProofRequest* request = new Authentication::ProofRequest(); - request->Modules.push_back(thumbprint); - request->Modules.push_back(resume); - AsyncWrite(request); - return true; + Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); + proofRequest->Modules.push_back(thumbprint); + proofRequest->Modules.push_back(resume); + AsyncWrite(proofRequest); } -bool Battlenet::Session::HandleProofResponse(PacketHeader& header, BitStream& packet) +void Battlenet::Session::HandleProofResponse(Authentication::ProofResponse const& proofResponse) { - Authentication::ProofResponse proof(header, packet); - proof.Read(); - - if (_modulesWaitingForData.size() < proof.Modules.size()) + if (_modulesWaitingForData.size() < proofResponse.Modules.size()) { Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); AsyncWrite(complete); - return true; + return; } ServerPacket* response = nullptr; - for (size_t i = 0; i < proof.Modules.size(); ++i) + for (size_t i = 0; i < proofResponse.Modules.size(); ++i) { - if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proof.Modules[i], &response)) + if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proofResponse.Modules[i], &response)) break; _modulesWaitingForData.pop(); @@ -402,36 +373,35 @@ bool Battlenet::Session::HandleProofResponse(PacketHeader& header, BitStream& pa } AsyncWrite(response); - return true; + return; } -bool Battlenet::Session::HandlePing(PacketHeader& /*header*/, BitStream& /*packet*/) +void Battlenet::Session::HandlePing(Connection::Ping const& /*ping*/) { AsyncWrite(new Connection::Pong()); - return true; } -bool Battlenet::Session::HandleEnableEncryption(PacketHeader& /*header*/, BitStream& /*packet*/) +void Battlenet::Session::HandleEnableEncryption(Connection::EnableEncryption const& /*enableEncryption*/) { _crypt.Init(&K); - return true; } -bool Battlenet::Session::HandleLogoutRequest(PacketHeader& /*header*/, BitStream& /*packet*/) +void Battlenet::Session::HandleLogoutRequest(Connection::LogoutRequest const& /*logoutRequest*/) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); stmt->setString(0, ""); stmt->setBool(1, false); stmt->setUInt32(2, _accountId); LoginDatabase.Execute(stmt); - return true; } -bool Battlenet::Session::HandleListSubscribeRequest(PacketHeader& /*header*/, BitStream& /*packet*/) +void Battlenet::Session::HandleConnectionClosing(Connection::ConnectionClosing const& /*connectionClosing*/) { - sRealmList->UpdateIfNeed(); +} - WoWRealm::ListSubscribeResponse* counts = new WoWRealm::ListSubscribeResponse(); +void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& /*listSubscribeRequest*/) +{ + WoWRealm::ListSubscribeResponse* listSubscribeResponse = new WoWRealm::ListSubscribeResponse(); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS); stmt->setUInt32(0, _gameAccountId); @@ -442,87 +412,50 @@ bool Battlenet::Session::HandleListSubscribeRequest(PacketHeader& /*header*/, Bi { Field* fields = countResult->Fetch(); uint32 build = fields[4].GetUInt32(); - counts->CharacterCounts.push_back({ { fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0) }, fields[0].GetUInt8() }); + listSubscribeResponse->CharacterCounts.push_back({ RealmId(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0)), fields[0].GetUInt8() }); } while (countResult->NextRow()); } - for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) - { - Realm const& realm = i->second; - - uint32 flag = realm.flag; - RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild); - if (realm.gamebuild != _build) - { - if (!buildInfo) - continue; - - flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for - } - - if (!buildInfo) - flag &= ~REALM_FLAG_SPECIFYBUILD; - - WoWRealm::ListUpdate* update = new WoWRealm::ListUpdate(); - update->Timezone = realm.timezone; - update->Population = realm.populationLevel; - update->Lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; - update->Type = realm.icon; - update->Name = realm.name; - - if (flag & REALM_FLAG_SPECIFYBUILD) - { - std::ostringstream version; - version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build; - - update->Version = version.str(); - update->Address = realm.GetAddressForClient(GetRemoteIpAddress()); - update->Build = buildInfo->Build; - } - - update->Flags = flag; - update->Region = realm.Region; - update->Battlegroup = realm.Battlegroup; - update->Index = realm.m_ID; - - counts->RealmData.push_back(update); - } + for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms()) + listSubscribeResponse->RealmData.push_back(BuildListUpdate(&i.second)); - counts->RealmData.push_back(new WoWRealm::ListComplete()); + listSubscribeResponse->RealmData.push_back(new WoWRealm::ListComplete()); - AsyncWrite(counts); - return true; + AsyncWrite(listSubscribeResponse); + _subscribedToRealmListUpdates = true; } -bool Battlenet::Session::HandleJoinRequestV2(PacketHeader& header, BitStream& packet) +void Battlenet::Session::HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& /*listUnsubscribe*/) { - WoWRealm::JoinRequestV2 join(header, packet); - join.Read(); + _subscribedToRealmListUpdates = false; +} - WoWRealm::JoinResponseV2* result = new WoWRealm::JoinResponseV2(); - Realm const* realm = sRealmList->GetRealm(join.Realm); - if (!realm || realm->flag & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE)) +void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest) +{ + WoWRealm::JoinResponseV2* joinResponse = new WoWRealm::JoinResponseV2(); + Realm const* realm = sRealmList->GetRealm(joinRequest.Realm); + if (!realm || realm->Flags & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE)) { - result->Response = WoWRealm::JoinResponseV2::FAILURE; - AsyncWrite(result); - return true; + joinResponse->Response = WoWRealm::JoinResponseV2::FAILURE; + AsyncWrite(joinResponse); + return; } - result->ServerSeed = uint32(rand32()); + joinResponse->ServerSeed = uint32(rand32()); uint8 sessionKey[40]; HmacSha1 hmac(K.GetNumBytes(), K.AsByteArray().get()); hmac.UpdateData((uint8*)"WoW\0", 4); - hmac.UpdateData((uint8*)&join.ClientSeed, 4); - hmac.UpdateData((uint8*)&result->ServerSeed, 4); + hmac.UpdateData((uint8*)&joinRequest.ClientSeed, 4); + hmac.UpdateData((uint8*)&joinResponse->ServerSeed, 4); hmac.Finalize(); memcpy(sessionKey, hmac.GetDigest(), hmac.GetLength()); HmacSha1 hmac2(K.GetNumBytes(), K.AsByteArray().get()); hmac2.UpdateData((uint8*)"WoW\0", 4); - hmac2.UpdateData((uint8*)&result->ServerSeed, 4); - hmac2.UpdateData((uint8*)&join.ClientSeed, 4); + hmac2.UpdateData((uint8*)&joinResponse->ServerSeed, 4); + hmac2.UpdateData((uint8*)&joinRequest.ClientSeed, 4); hmac2.Finalize(); memcpy(sessionKey + hmac.GetLength(), hmac2.GetDigest(), hmac2.GetLength()); @@ -530,53 +463,92 @@ bool Battlenet::Session::HandleJoinRequestV2(PacketHeader& header, BitStream& pa LoginDatabase.DirectPExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = %u, failed_logins = 0, os = '%s' WHERE id = %u", ByteArrayToHexStr(sessionKey, 40, true).c_str(), GetRemoteIpAddress().to_string().c_str(), GetLocaleByName(_locale), _os.c_str(), _gameAccountId); - result->IPv4.emplace_back(realm->ExternalAddress, realm->port); + joinResponse->IPv4.emplace_back(realm->ExternalAddress, realm->Port); if (realm->ExternalAddress != realm->LocalAddress) - result->IPv4.emplace_back(realm->LocalAddress, realm->port); + joinResponse->IPv4.emplace_back(realm->LocalAddress, realm->Port); - AsyncWrite(result); - return true; + AsyncWrite(joinResponse); +} + +void Battlenet::Session::HandleSocialNetworkCheckConnected(Friends::SocialNetworkCheckConnected const& socialNetworkCheckConnected) +{ + Friends::SocialNetworkCheckConnectedResult* socialNetworkCheckConnectedResult = new Friends::SocialNetworkCheckConnectedResult(); + socialNetworkCheckConnectedResult->SocialNetworkId = socialNetworkCheckConnected.SocialNetworkId; + AsyncWrite(socialNetworkCheckConnectedResult); +} + +void Battlenet::Session::HandleGetStreamItemsRequest(Cache::GetStreamItemsRequest const& getStreamItemsRequest) +{ + if (ModuleInfo* module = sModuleMgr->CreateModule(getStreamItemsRequest.Locale, getStreamItemsRequest.ItemName)) + { + Cache::GetStreamItemsResponse* getStreamItemsResponse = new Cache::GetStreamItemsResponse(); + getStreamItemsResponse->Index = getStreamItemsRequest.Index; + getStreamItemsResponse->Modules.push_back(module); + AsyncWrite(getStreamItemsResponse); + } +} + +inline std::string PacketToStringHelper(Battlenet::ClientPacket const* packet) +{ + if (sLog->ShouldLog("session.packets", LOG_LEVEL_TRACE)) + return packet->ToString(); + + return sPacketManager.GetClientPacketName(packet->GetHeader()); +} + +inline std::string PacketToStringHelper(Battlenet::ServerPacket const* packet) +{ + if (sLog->ShouldLog("session.packets", LOG_LEVEL_TRACE)) + return packet->ToString(); + + return sPacketManager.GetServerPacketName(packet->GetHeader()); } void Battlenet::Session::ReadHandler() { - BitStream packet(std::move(GetReadBuffer())); - _crypt.DecryptRecv(packet.GetBuffer(), packet.GetSize()); + BitStream stream(std::move(GetReadBuffer())); + _crypt.DecryptRecv(stream.GetBuffer(), stream.GetSize()); - while (!packet.IsRead()) + while (!stream.IsRead()) { try { PacketHeader header; - header.Opcode = packet.Read<uint32>(6); - if (packet.Read<bool>(1)) - header.Channel = packet.Read<int32>(4); + header.Opcode = stream.Read<uint32>(6); + if (stream.Read<bool>(1)) + header.Channel = stream.Read<int32>(4); if (header.Channel != AUTHENTICATION && !_authed) { - TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::ReadDataHandler Received not allowed packet %s", header.ToString().c_str()); + TC_LOG_DEBUG("session.packets", "%s Received not allowed %s. Client has not authed yet.", GetClientInfo().c_str(), header.ToString().c_str()); CloseSocket(); return; } - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::ReadDataHandler %s", header.ToString().c_str()); - std::map<PacketHeader, PacketHandler>::const_iterator itr = Handlers.find(header); - if (itr != Handlers.end()) + if (ClientPacket* packet = sPacketManager.CreateClientPacket(header, stream)) { - if ((this->*(itr->second))(header, packet)) - break; + if (sPacketManager.IsHandled(header)) + TC_LOG_DEBUG("session.packets", "%s Received %s", GetClientInfo().c_str(), PacketToStringHelper(packet).c_str()); + + packet->CallHandler(this); + delete packet; + } + else if (sPacketManager.GetClientPacketName(header)) + { + LogUnhandledPacket(header); + break; } else { - TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::ReadDataHandler Unhandled opcode %s", header.ToString().c_str()); + TC_LOG_DEBUG("session.packets", "%s Received unknown %s", GetClientInfo().c_str(), header.ToString().c_str()); break; } - packet.AlignToNextByte(); + stream.AlignToNextByte(); } catch (BitStreamPositionException const& e) { - TC_LOG_ERROR("server.battlenet", "Battlenet::Session::ReadDataHandler Exception: %s", e.what()); + TC_LOG_ERROR("session.packets", "%s Exception thrown during packet processing %s", GetClientInfo().c_str(), e.what()); CloseSocket(); return; } @@ -588,7 +560,7 @@ void Battlenet::Session::ReadHandler() void Battlenet::Session::Start() { - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::Start"); + TC_LOG_TRACE("session", "Accepted connection from %s", GetRemoteIpAddress().to_string().c_str()); AsyncRead(); } @@ -600,7 +572,7 @@ void Battlenet::Session::AsyncWrite(ServerPacket* packet) return; } - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::AsyncWrite %s", packet->ToString().c_str()); + TC_LOG_DEBUG("session.packets", "%s Sending %s", GetClientInfo().c_str(), PacketToStringHelper(packet).c_str()); packet->Write(); @@ -627,17 +599,17 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke { if (dataStream->GetSize() != 1 + 128 + 32 + 128) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, logonResponse); return false; } if (dataStream->Read<uint8>(8) != 2) // State { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, logonResponse); return false; } @@ -649,9 +621,9 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke if (A.isZero()) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, logonResponse); return false; } @@ -725,9 +697,9 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke stmt->setString(0, _accountName); LoginDatabase.Execute(stmt); - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - ReplaceResponse(response, complete); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + ReplaceResponse(response, logonResponse); return false; } @@ -740,9 +712,9 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke if (!numAccounts) { - Authentication::LogonResponse* noAccounts = new Authentication::LogonResponse(); - noAccounts->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, noAccounts); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); + ReplaceResponse(response, logonResponse); return false; } @@ -761,7 +733,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke serverProof.SetRand(128 * 8); // just send garbage, server signature check is patched out in client BitStream stream; - ModuleInfo* password = sBattlenetMgr->CreateModule(_os, "Password"); + ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password"); uint8 state = 3; stream.WriteBytes(&state, 1); @@ -772,8 +744,8 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke password->Data = new uint8[password->DataSize]; memcpy(password->Data, stream.GetBuffer(), password->DataSize); - Authentication::ProofRequest* request = new Authentication::ProofRequest(); - request->Modules.push_back(password); + Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); + proofRequest->Modules.push_back(password); if (numAccounts > 1) { BitStream accounts; @@ -794,43 +766,43 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke accounts.WriteString(name.str(), 8); } while (result->NextRow()); - ModuleInfo* selectGameAccount = sBattlenetMgr->CreateModule(_os, "SelectGameAccount"); + ModuleInfo* selectGameAccount = sModuleMgr->CreateModule(_os, "SelectGameAccount"); selectGameAccount->DataSize = accounts.GetSize(); selectGameAccount->Data = new uint8[selectGameAccount->DataSize]; memcpy(selectGameAccount->Data, accounts.GetBuffer(), selectGameAccount->DataSize); - request->Modules.push_back(selectGameAccount); + proofRequest->Modules.push_back(selectGameAccount); _modulesWaitingForData.push(MODULE_SELECT_GAME_ACCOUNT); } else { if (fields[4].GetBool()) { - delete request; + delete proofRequest; - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); if (fields[2].GetUInt32() == fields[3].GetUInt32()) { - complete->SetAuthResult(LOGIN_BANNED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + logonResponse->SetAuthResult(LOGIN_BANNED); + TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::Password] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); } else { - complete->SetAuthResult(LOGIN_SUSPENDED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + logonResponse->SetAuthResult(LOGIN_SUSPENDED); + TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::Password] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); } - ReplaceResponse(response, complete); + ReplaceResponse(response, logonResponse); return false; } _gameAccountId = fields[0].GetUInt32(); _gameAccountName = fields[1].GetString(); - request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint")); + proofRequest->Modules.push_back(sModuleMgr->CreateModule(_os, "RiskFingerprint")); _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); } - ReplaceResponse(response, request); + ReplaceResponse(response, proofRequest); return true; } @@ -838,9 +810,9 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se { if (dataStream->Read<uint8>(8) != 1) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, logonResponse); return false; } @@ -848,9 +820,9 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se std::string account = dataStream->ReadString(8); if (account.empty()) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, complete); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); + ReplaceResponse(response, logonResponse); return false; } @@ -879,28 +851,28 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se Field* fields = result->Fetch(); if (fields[4].GetBool()) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); if (fields[2].GetUInt32() == fields[3].GetUInt32()) { - complete->SetAuthResult(LOGIN_BANNED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::SelectGameAccount] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + logonResponse->SetAuthResult(LOGIN_BANNED); + TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::SelectGameAccount] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); } else { - complete->SetAuthResult(LOGIN_SUSPENDED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::SelectGameAccount] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + logonResponse->SetAuthResult(LOGIN_SUSPENDED); + TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::SelectGameAccount] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); } - ReplaceResponse(response, complete); + ReplaceResponse(response, logonResponse); return false; } _gameAccountId = fields[0].GetUInt32(); _gameAccountName = fields[1].GetString(); - Authentication::ProofRequest* request = new Authentication::ProofRequest(); - request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint")); - ReplaceResponse(response, request); + Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); + proofRequest->Modules.push_back(sModuleMgr->CreateModule(_os, "RiskFingerprint")); + ReplaceResponse(response, proofRequest); _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); return true; @@ -908,16 +880,16 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se bool Battlenet::Session::HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); if (dataStream->Read<uint8>(8) == 1) { - complete->AccountId = _accountId; - complete->GameAccountName = _gameAccountName; - complete->GameAccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK; + logonResponse->AccountId = _accountId; + logonResponse->GameAccountName = _gameAccountName; + logonResponse->GameAccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK; PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_FAILED_LOGINS); stmt->setUInt32(0, _accountId); if (PreparedQueryResult failedLoginsResult = LoginDatabase.Query(stmt)) - complete->FailedLogins = (*failedLoginsResult)[0].GetUInt32(); + logonResponse->FailedLogins = (*failedLoginsResult)[0].GetUInt32(); SQLTransaction trans = LoginDatabase.BeginTransaction(); @@ -937,12 +909,12 @@ bool Battlenet::Session::HandleRiskFingerprintModule(BitStream* dataStream, Serv LoginDatabase.CommitTransaction(trans); _authed = true; - sBattlenetSessionMgr.AddSession(this); + sSessionMgr.AddSession(this); } else - complete->SetAuthResult(AUTH_BAD_VERSION_HASH); + logonResponse->SetAuthResult(AUTH_BAD_VERSION_HASH); - ReplaceResponse(response, complete); + ReplaceResponse(response, logonResponse); return true; } @@ -950,9 +922,9 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* { if (dataStream->Read<uint8>(8) != 1) { - Authentication::ResumeResponse* complete = new Authentication::ResumeResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); + Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); + resumeResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, resumeResponse); return false; } @@ -994,10 +966,10 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* stmt->setString(0, _accountName); LoginDatabase.Execute(stmt); - TC_LOG_DEBUG("server.battlenet", "[Battlenet::Resume] Invalid proof!"); - Authentication::ResumeResponse* result = new Authentication::ResumeResponse(); - result->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - ReplaceResponse(response, result); + TC_LOG_DEBUG("session", "[Battlenet::Resume] Invalid proof!"); + Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); + resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + ReplaceResponse(response, resumeResponse); return false; } @@ -1013,7 +985,7 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* serverProof.UpdateData(clientChallenge.get(), 16); serverProof.Finalize(); - ModuleInfo* resume = sBattlenetMgr->CreateModule(_os, "Resume"); + ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); BitStream resumeData; uint8 state = 2; @@ -1024,18 +996,80 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* resume->Data = new uint8[resume->DataSize]; memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); - Authentication::ResumeResponse* result = new Authentication::ResumeResponse(); - result->Modules.push_back(resume); - ReplaceResponse(response, result); + Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); + resumeResponse->Modules.push_back(resume); + ReplaceResponse(response, resumeResponse); _authed = true; - sBattlenetSessionMgr.AddSession(this); + sSessionMgr.AddSession(this); return true; } bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response) { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); + TC_LOG_ERROR("session.packets", "Unhandled module."); + Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); + logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, logonResponse); return false; } + +void Battlenet::Session::UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmId>& deletedRealms) +{ + for (Realm const* realm : realms) + AsyncWrite(BuildListUpdate(realm)); + + for (RealmId& deleted : deletedRealms) + { + WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate(); + listUpdate->UpdateState = WoWRealm::ListUpdate::DELETED; + listUpdate->Id = deleted; + AsyncWrite(listUpdate); + } +} + +Battlenet::WoWRealm::ListUpdate* Battlenet::Session::BuildListUpdate(Realm const* realm) const +{ + uint32 flag = realm->Flags & ~REALM_FLAG_SPECIFYBUILD; + RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm->Id.Build); + if (realm->Id.Build != _build) + { + flag |= REALM_FLAG_INVALID; + if (buildInfo) + flag |= REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for + } + + WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate(); + listUpdate->Timezone = realm->Timezone; + listUpdate->Population = realm->PopulationLevel; + listUpdate->Lock = (realm->AllowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; + listUpdate->Type = realm->Type; + listUpdate->Name = realm->Name; + + if (flag & REALM_FLAG_SPECIFYBUILD) + { + std::ostringstream version; + version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build; + + listUpdate->Version = version.str(); + listUpdate->Address = realm->GetAddressForClient(GetRemoteIpAddress()); + } + + listUpdate->Flags = flag; + listUpdate->Id = realm->Id; + return listUpdate; +} + +std::string Battlenet::Session::GetClientInfo() const +{ + std::ostringstream stream; + stream << '[' << GetRemoteIpAddress() << ':' << GetRemotePort(); + if (!_accountName.empty()) + stream << ", Account: " << _accountName; + + if (!_gameAccountName.empty()) + stream << ", Game account: " << _gameAccountName; + + stream << ']'; + + return stream.str(); +} diff --git a/src/server/authserver/Server/BattlenetSession.h b/src/server/bnetserver/Server/Session.h index c3e4afee19b..ded5170ae32 100644 --- a/src/server/authserver/Server/BattlenetSession.h +++ b/src/server/bnetserver/Server/Session.h @@ -15,16 +15,17 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _BATTLENETSOCKET_H -#define _BATTLENETSOCKET_H +#ifndef Session_h__ +#define Session_h__ -#include "BattlenetPackets.h" +#include "Packets.h" #include "BattlenetPacketCrypt.h" #include "Socket.h" #include "BigNumber.h" #include <memory> #include <boost/asio/ip/tcp.hpp> +struct Realm; using boost::asio::ip::tcp; namespace Battlenet @@ -59,24 +60,39 @@ namespace Battlenet explicit Session(tcp::socket&& socket); ~Session(); - typedef bool(Session::*PacketHandler)(PacketHeader& socket, BitStream& packet); + void LogUnhandledPacket(PacketHeader const& header); // Authentication - bool HandleLogonRequest(PacketHeader& header, BitStream& packet); - bool HandleResumeRequest(PacketHeader& header, BitStream& packet); - bool HandleProofResponse(PacketHeader& header, BitStream& packet); + void HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest); + void HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest); + void HandleProofResponse(Authentication::ProofResponse const& proofResponse); // Connection - bool HandlePing(PacketHeader& header, BitStream& packet); - bool HandleEnableEncryption(PacketHeader& header, BitStream& packet); - bool HandleLogoutRequest(PacketHeader& header, BitStream& packet); + void HandlePing(Connection::Ping const& ping); + void HandleEnableEncryption(Connection::EnableEncryption const& enableEncryption); + void HandleLogoutRequest(Connection::LogoutRequest const& logoutRequest); + void HandleConnectionClosing(Connection::ConnectionClosing const& connectionClosing); // WoWRealm - bool HandleListSubscribeRequest(PacketHeader& header, BitStream& packet); - bool HandleJoinRequestV2(PacketHeader& header, BitStream& packet); + void HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& listSubscribeRequest); + void HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& listUnsubscribe); + void HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest); + + // Friends + void HandleSocialNetworkCheckConnected(Friends::SocialNetworkCheckConnected const& socialNetworkCheckConnected); + + // Cache + void HandleGetStreamItemsRequest(Cache::GetStreamItemsRequest const& getStreamItemsRequest); void Start() override; + void UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmId>& deletedRealms); + + uint32 GetAccountId() const { return _accountId; } + uint32 GetGameAccountId() const { return _gameAccountId; } + + bool IsSubscribedToRealmListUpdates() const { return _subscribedToRealmListUpdates; } + void AsyncWrite(ServerPacket* packet); protected: @@ -94,6 +110,9 @@ namespace Battlenet bool HandleResumeModule(BitStream* dataStream, ServerPacket** response); bool UnhandledModule(BitStream* dataStream, ServerPacket** response); + WoWRealm::ListUpdate* BuildListUpdate(Realm const* realm) const; + std::string GetClientInfo() const; + uint32 _accountId; std::string _accountName; std::string _locale; @@ -121,8 +140,9 @@ namespace Battlenet PacketCrypt _crypt; bool _authed; + bool _subscribedToRealmListUpdates; }; } -#endif // _BATTLENETSOCKET_H +#endif // Session_h__ diff --git a/src/server/bnetserver/Server/SessionManager.cpp b/src/server/bnetserver/Server/SessionManager.cpp new file mode 100644 index 00000000000..9e5836dab8d --- /dev/null +++ b/src/server/bnetserver/Server/SessionManager.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "SessionManager.h" + +bool Battlenet::SessionManager::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) +{ + if (!BaseSocketMgr::StartNetwork(service, bindIp, port)) + return false; + + _acceptor->AsyncAcceptManaged(&OnSocketAccept); + return true; +} + +NetworkThread<Battlenet::Session>* Battlenet::SessionManager::CreateThreads() const +{ + return new NetworkThread<Session>[GetNetworkThreadCount()]; +} + +void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock) +{ + sSessionMgr.OnSocketOpen(std::forward<tcp::socket>(sock)); +} + +void Battlenet::SessionManager::AddSession(Session* session) +{ + std::unique_lock<boost::shared_mutex> lock(_sessionMutex); + _sessions[{ session->GetAccountId(), session->GetGameAccountId() }] = session; + _sessionsByAccountId[session->GetAccountId()].push_back(session); +} + +void Battlenet::SessionManager::RemoveSession(Session* session) +{ + std::unique_lock<boost::shared_mutex> lock(_sessionMutex); + _sessions.erase({ session->GetAccountId(), session->GetGameAccountId() }); + _sessionsByAccountId[session->GetAccountId()].remove(session); +} + +Battlenet::Session* Battlenet::SessionManager::GetSession(uint32 accountId, uint32 gameAccountId) const +{ + auto itr = _sessions.find({ accountId, gameAccountId }); + if (itr != _sessions.end()) + return itr->second; + + return nullptr; +} + +std::list<Battlenet::Session*> Battlenet::SessionManager::GetSessions(uint32 accountId) const +{ + std::list<Session*> sessions; + auto itr = _sessionsByAccountId.find(accountId); + if (itr != _sessionsByAccountId.end()) + sessions = itr->second; + + return sessions; +} diff --git a/src/server/authserver/Server/BattlenetSessionManager.h b/src/server/bnetserver/Server/SessionManager.h index b5a54438ef1..08ca5ce2b4e 100644 --- a/src/server/authserver/Server/BattlenetSessionManager.h +++ b/src/server/bnetserver/Server/SessionManager.h @@ -15,11 +15,13 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef BattlenetSessionManager_h__ -#define BattlenetSessionManager_h__ +#ifndef SessionManager_h__ +#define SessionManager_h__ -#include "BattlenetSession.h" +#include "Session.h" #include "SocketMgr.h" +#include <boost/thread/locks.hpp> +#include <boost/thread/shared_mutex.hpp> namespace Battlenet { @@ -28,7 +30,7 @@ namespace Battlenet struct SessionInfo { uint32 AccountId; - uint32 GameAccountIndex; + uint32 GameAccountId; bool operator<(SessionInfo const& right) const { @@ -41,6 +43,8 @@ namespace Battlenet class SessionManager : SocketMgr<Session> { typedef SocketMgr<Session> BaseSocketMgr; + typedef std::map<SessionInfo, Session*> SessionMap; + typedef std::map<uint32, std::list<Session*>> SessionByAccountMap; public: static SessionManager& Instance() @@ -52,9 +56,20 @@ namespace Battlenet bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override; // noop for now, will be needed later to broadcast realmlist updates for example - void AddSession(Session* /*session*/) { } + void AddSession(Session* /*session*/); - void RemoveSession(Session* /*session*/) { } + void RemoveSession(Session* /*session*/); + + Session* GetSession(uint32 accountId, uint32 gameAccountId) const; + std::list<Session*> GetSessions(uint32 accountId) const; + + template<typename Iterator> + void LockedForEach(Iterator iterator) + { + boost::shared_lock<boost::shared_mutex> lock(_sessionMutex); + for (SessionMap::value_type const& pair : _sessions) + iterator(pair.second); + } protected: NetworkThread<Session>* CreateThreads() const override; @@ -62,10 +77,12 @@ namespace Battlenet private: static void OnSocketAccept(tcp::socket&& sock); - std::map<SessionInfo, Session> _sessions; + SessionMap _sessions; + SessionByAccountMap _sessionsByAccountId; + boost::shared_mutex _sessionMutex; }; } -#define sBattlenetSessionMgr Battlenet::SessionManager::Instance() +#define sSessionMgr Battlenet::SessionManager::Instance() -#endif // BattlenetSessionManager_h__ +#endif // SessionManager_h__ diff --git a/src/server/bnetserver/bnetserver.conf.dist b/src/server/bnetserver/bnetserver.conf.dist new file mode 100644 index 00000000000..102ddb9906a --- /dev/null +++ b/src/server/bnetserver/bnetserver.conf.dist @@ -0,0 +1,260 @@ +############################################### +# Trinity Core Auth Server configuration file # +############################################### +[authserver] + +################################################################################################### +# SECTION INDEX +# +# EXAMPLE CONFIG +# AUTH SERVER SETTINGS +# MYSQL SETTINGS +# LOGGING SYSTEM SETTINGS +# +################################################################################################### + +################################################################################################### +# EXAMPLE CONFIG +# +# Variable +# Description: Brief description what the variable is doing. +# Important: Annotation for important things about this variable. +# Example: "Example, i.e. if the value is a string" +# Default: 10 - (Enabled|Comment|Variable name in case of grouped config options) +# 0 - (Disabled|Comment|Variable name in case of grouped config options) +# +# Note to developers: +# - Copy this example to keep the formatting. +# - Line breaks should be at column 100. +################################################################################################### + +################################################################################################### +# AUTH SERVER SETTINGS +# +# LogsDir +# Description: Logs directory setting. +# Important: LogsDir needs to be quoted, as the string might contain space characters. +# Logs directory must exists, or log file creation will be disabled. +# Default: "" - (Log files will be stored in the current path) + +LogsDir = "" + +# +# MaxPingTime +# Description: Time (in minutes) between database pings. +# Default: 30 + +MaxPingTime = 30 + +# +# WorldserverListenPort +# Description: TCP port to listen on for incoming worldserver IPC. +# Default: 1118 + +WorldserverListenPort = 1118 + +# +# BattlenetPort +# Description: TCP port to reach the auth server for battle.net connections. +# Default: 1119 + +BattlenetPort = 1119 + +# +# +# BindIP +# Description: Bind auth server to IP/hostname +# Default: "0.0.0.0" - (Bind to all IPs on the system) + +BindIP = "0.0.0.0" + +# +# PidFile +# Description: Auth server PID file. +# Example: "./authserver.pid" - (Enabled) +# Default: "" - (Disabled) + +PidFile = "" + +# +# UseProcessors +# Description: Processors mask for Windows and Linux based multi-processor systems. +# Example: A computer with 2 CPUs: +# 1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3 +# Default: 0 - (Selected by OS) +# 1+ - (Bit mask value of selected processors) + +UseProcessors = 0 + +# +# ProcessPriority +# Description: Process priority setting for Windows and Linux based systems. +# Details: On Linux, a nice value of -15 is used. (requires superuser). On Windows, process is set to HIGH class. +# Default: 0 - (Normal) +# 1 - (High) + +ProcessPriority = 0 + +# +# RealmsStateUpdateDelay +# Description: Time (in seconds) between realm list updates. +# Default: 10 +# 0 - (Disabled) + +RealmsStateUpdateDelay = 10 + +# +# WrongPass.MaxCount +# Description: Number of login attemps with wrong password before the account or IP will be +# banned. +# Default: 0 - (Disabled) +# 1+ - (Enabled) + +WrongPass.MaxCount = 0 + +# +# WrongPass.BanTime +# Description: Time (in seconds) for banning account or IP for invalid login attempts. +# Default: 600 - (10 minutes) +# 0 - (Permanent ban) + +WrongPass.BanTime = 600 + +# +# WrongPass.BanType +# Description: Ban type for invalid login attempts. +# Default: 0 - (Ban IP) +# 1 - (Ban Account) + +WrongPass.BanType = 0 + +# +################################################################################################### + +################################################################################################### +# MYSQL SETTINGS +# +# LoginDatabaseInfo +# Description: Database connection settings for the realm server. +# Example: "hostname;port;username;password;database" +# ".;somenumber;username;password;database" - (Use named pipes on Windows +# "enable-named-pipe" to [mysqld] +# section my.ini) +# ".;/path/to/unix_socket;username;password;database" - (use Unix sockets on +# Unix/Linux) +# Default: "127.0.0.1;3306;trinity;trinity;auth" + +LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" + +# +# LoginDatabase.WorkerThreads +# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL +# statements. Each worker thread is mirrored with its own connection to the +# Default: 1 + +LoginDatabase.WorkerThreads = 1 + +# +# Wrong.Password.Login.Logging +# Description: Additionally log attempted wrong password logging +# Default: 0 - (Disabled) +# 1 - (Enabled) + +Wrong.Password.Login.Logging = 0 +# +################################################################################################### + +################################################################################################### +# +# LOGGING SYSTEM SETTINGS +# +# Appender config values: Given a appender "name" +# Appender.name +# Description: Defines 'where to log' +# Format: Type,LogLevel,Flags,optional1,optional2,optional3 +# +# Type +# 0 - (None) +# 1 - (Console) +# 2 - (File) +# 3 - (DB) +# +# LogLevel +# 0 - (Disabled) +# 1 - (Trace) +# 2 - (Debug) +# 3 - (Info) +# 4 - (Warn) +# 5 - (Error) +# 6 - (Fatal) +# +# Flags: +# 0 - None +# 1 - Prefix Timestamp to the text +# 2 - Prefix Log Level to the text +# 4 - Prefix Log Filter type to the text +# 8 - Append timestamp to the log file name. Format: YYYY-MM-DD_HH-MM-SS (Only used with Type = 2) +# 16 - Make a backup of existing file before overwrite (Only used with Mode = w) +# +# Colors (read as optional1 if Type = Console) +# Format: "fatal error warn info debug trace" +# 0 - BLACK +# 1 - RED +# 2 - GREEN +# 3 - BROWN +# 4 - BLUE +# 5 - MAGENTA +# 6 - CYAN +# 7 - GREY +# 8 - YELLOW +# 9 - LRED +# 10 - LGREEN +# 11 - LBLUE +# 12 - LMAGENTA +# 13 - LCYAN +# 14 - WHITE +# Example: "13 11 9 5 3 1" +# +# File: Name of the file (read as optional1 if Type = File) +# Allows to use one "%s" to create dynamic files +# +# Mode: Mode to open the file (read as optional2 if Type = File) +# a - (Append) +# w - (Overwrite) +# +# MaxFileSize: Maximum file size of the log file before creating a new log file +# (read as optional3 if Type = File) +# Size is measured in bytes expressed in a 64-bit unsigned integer. +# Maximum value is 4294967295 (4 gb). Leave blank for no limit. +# NOTE: Does not work with dynamic filenames. +# Example: 536870912 (512 mb) +# + +Appender.Console=1,2,0 +Appender.Bnet=2,2,0,Bnet.log,w + +# Logger config values: Given a logger "name" +# Logger.name +# Description: Defines 'What to log' +# Format: LogLevel,AppenderList +# +# LogLevel +# 0 - (Disabled) +# 1 - (Trace) +# 2 - (Debug) +# 3 - (Info) +# 4 - (Warn) +# 5 - (Error) +# 6 - (Fatal) +# +# AppenderList: List of appenders linked to logger +# (Using spaces as separator). +# + +Logger.root=3,Console Bnet +Logger.realmlist=3,Console Bnet +Logger.session=3,Console Bnet +Logger.session.packets=3,Console Bnet + +# +################################################################################################### diff --git a/src/server/bnetserver/bnetserver.ico b/src/server/bnetserver/bnetserver.ico Binary files differnew file mode 100644 index 00000000000..da318f48a8c --- /dev/null +++ b/src/server/bnetserver/bnetserver.ico diff --git a/src/server/bnetserver/bnetserver.rc b/src/server/bnetserver/bnetserver.rc new file mode 100644 index 00000000000..f030203fdcd --- /dev/null +++ b/src/server/bnetserver/bnetserver.rc @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resource.h" +#include "revision.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" //"afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "bnetserver.ico" + +///////////////////////////////////////////////////////////////////////////// +// Neutre (Par défaut système) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUSD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION + +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + +#ifndef _DEBUG + FILEFLAGS 0 +#else + #define VER_PRERELEASE VS_FF_PRERELEASE + #define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD + #define VER_DEBUG 0 + FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG) +#endif + +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080004b0" + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", "TrinityCore Battle.net Server Daemon" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "bnetserver" + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename", "bnetserver.exe" + VALUE "ProductName", "TrinityCore Battle.net Server" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x800, 1200 + END +END +#endif diff --git a/src/server/bnetserver/resource.h b/src/server/bnetserver/resource.h new file mode 100644 index 00000000000..7dc5cb9ef7b --- /dev/null +++ b/src/server/bnetserver/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TrinityCore.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt index 1c5fcbee52e..3aac255be29 100644 --- a/src/server/collision/CMakeLists.txt +++ b/src/server/collision/CMakeLists.txt @@ -47,6 +47,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores + ${CMAKE_SOURCE_DIR}/src/server/ipc ${CMAKE_SOURCE_DIR}/src/server/game/Addons ${CMAKE_SOURCE_DIR}/src/server/game/Conditions ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp index b08cd92d638..51f016f6e96 100644 --- a/src/server/collision/Management/MMapFactory.cpp +++ b/src/server/collision/Management/MMapFactory.cpp @@ -17,9 +17,7 @@ */ #include "MMapFactory.h" -#include "World.h" #include "Config.h" -#include "DisableMgr.h" namespace MMAP { @@ -35,12 +33,6 @@ namespace MMAP return g_MMapManager; } - bool MMapFactory::IsPathfindingEnabled(uint32 mapId) - { - return sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) - && !DisableMgr::IsDisabledFor(DISABLE_TYPE_MMAP, mapId, NULL, MMAP_DISABLE_PATHFINDING); - } - void MMapFactory::clear() { if (g_MMapManager) diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 484fdcd8ea4..b9ac7e204da 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -25,10 +25,9 @@ #include "ModelInstance.h" #include "WorldModel.h" #include <G3D/Vector3.h> -#include "DisableMgr.h" -#include "DBCStores.h" #include "Log.h" #include "VMapDefinitions.h" +#include "Errors.h" using G3D::Vector3; @@ -36,6 +35,8 @@ namespace VMAP { VMapManager2::VMapManager2() { + GetLiquidFlagsPtr = &GetLiquidFlagsDummy; + IsVMAPDisabledForPtr = &IsVMAPDisabledForDummy; } VMapManager2::~VMapManager2(void) @@ -134,7 +135,7 @@ namespace VMAP bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) { - if (!isLineOfSightCalcEnabled() || DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS)) + if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) return true; InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); @@ -157,7 +158,7 @@ namespace VMAP */ bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist) { - if (isLineOfSightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS)) + if (isLineOfSightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) { InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree != iInstanceMapTrees.end()) @@ -187,7 +188,7 @@ namespace VMAP float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) { - if (isHeightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_HEIGHT)) + if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT)) { InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree != iInstanceMapTrees.end()) @@ -206,7 +207,7 @@ namespace VMAP bool VMapManager2::getAreaInfo(unsigned int mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const { - if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_AREAFLAG)) + if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) { InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree != iInstanceMapTrees.end()) @@ -224,7 +225,7 @@ namespace VMAP bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const { - if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LIQUIDSTATUS)) + if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) { InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree != iInstanceMapTrees.end()) @@ -236,7 +237,7 @@ namespace VMAP floor = info.ground_Z; ASSERT(floor < std::numeric_limits<float>::max()); type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc - if (reqLiquidType && !(GetLiquidFlags(type) & reqLiquidType)) + if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) return false; if (info.hitInstance->GetLiquidLevel(pos, info, level)) return true; diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h index 04292e7d8e4..9c419270b5a 100644 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/server/collision/Management/VMapManager2.h @@ -66,6 +66,14 @@ namespace VMAP typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap; typedef std::unordered_map<std::string, ManagedModel> ModelFileMap; + enum DisableTypes + { + VMAP_DISABLE_AREAFLAG = 0x1, + VMAP_DISABLE_HEIGHT = 0x2, + VMAP_DISABLE_LOS = 0x4, + VMAP_DISABLE_LIQUIDSTATUS = 0x8 + }; + class VMapManager2 : public IVMapManager { protected: @@ -78,6 +86,9 @@ namespace VMAP bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ + static uint32 GetLiquidFlagsDummy(uint32) { return 0; } + static bool IsVMAPDisabledForDummy(uint32 /*entry*/, uint8 /*flags*/) { return false; } + public: // public for debug G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; @@ -114,6 +125,12 @@ namespace VMAP virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y) override; public: void getInstanceMapTree(InstanceTreeMap &instanceMapTree); + + typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType); + GetLiquidFlagsFn GetLiquidFlagsPtr; + + typedef bool(*IsVMAPDisabledForFn)(uint32 entry, uint8 flags); + IsVMAPDisabledForFn IsVMAPDisabledForPtr; }; } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index fb3bbd17a69..ccfeb61206f 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -83,13 +83,13 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3 { for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i) { - SMART_EVENT eventType = SMART_EVENT((*i).GetEventType()); + SMART_EVENT eventType = SMART_EVENT(i->GetEventType()); if (eventType == SMART_EVENT_LINK)//special handling continue; - if (eventType == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/) + if (eventType == e /*&& (!i->event.event_phase_mask || IsInPhase(i->event.event_phase_mask)) && !(i->event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && i->runOnce)*/) { - ConditionList conds = sConditionMgr->GetConditionsForSmartEvent((*i).entryOrGuid, (*i).event_id, (*i).source_type); + ConditionList conds = sConditionMgr->GetConditionsForSmartEvent(i->entryOrGuid, i->event_id, i->source_type); ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject()); if (sConditionMgr->IsObjectMeetToConditions(info, conds)) @@ -167,7 +167,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { if (IsCreature(*itr)) - sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker())? GetLastInvoker() : 0); + sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); else if (IsPlayer(*itr) && me) { Unit* templastInvoker = GetLastInvoker(); @@ -2262,8 +2262,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.link && e.link != e.event_id) { - SmartScriptHolder linked = FindLinkedEvent(e.link); - if (linked.GetActionType() && linked.GetEventType() == SMART_EVENT_LINK) + SmartScriptHolder& linked = SmartAIMgr::FindLinkedEvent(mEvents, e.link); + if (linked) ProcessEvent(linked, unit, var0, var1, bvar, spell, gob); else TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); @@ -2468,10 +2468,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (!IsCreature(*itr)) continue; - if (me && me == *itr) + if (me && me->GetGUID() == (*itr)->GetGUID()) continue; - if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist)) + if ((!e.target.unitRange.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) && baseObject->IsInRange(*itr, float(e.target.unitRange.minDist), float(e.target.unitRange.maxDist))) l->push_back(*itr); } @@ -2487,10 +2487,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (!IsCreature(*itr)) continue; - if (me && me == *itr) + if (me && me->GetGUID() == (*itr)->GetGUID()) continue; - if ((e.target.unitDistance.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature) || !e.target.unitDistance.creature) + if (!e.target.unitDistance.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature) l->push_back(*itr); } @@ -2506,10 +2506,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (!IsGameObject(*itr)) continue; - if (go && go == *itr) + if (go && go->GetGUID() == (*itr)->GetGUID()) continue; - if ((e.target.goDistance.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry) || !e.target.goDistance.entry) + if (!e.target.goDistance.entry || (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry) l->push_back(*itr); } @@ -2525,10 +2525,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (!IsGameObject(*itr)) continue; - if (go && go == *itr) + if (go && go->GetGUID() == (*itr)->GetGUID()) continue; - if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist)) + if ((!e.target.goRange.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) && baseObject->IsInRange(*itr, float(e.target.goRange.minDist), float(e.target.goRange.maxDist))) l->push_back(*itr); } @@ -2537,32 +2537,28 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* } case SMART_TARGET_CREATURE_GUID: { - Creature* target = NULL; if (!scriptTrigger && !baseObject) { TC_LOG_ERROR("sql.sql", "SMART_TARGET_CREATURE_GUID can not be used without invoker"); break; } - target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid); - - if (target && (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry)) - l->push_back(target); + if (Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid)) + if (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry) + l->push_back(target); break; } case SMART_TARGET_GAMEOBJECT_GUID: { - GameObject* target = NULL; if (!scriptTrigger && !baseObject) { TC_LOG_ERROR("sql.sql", "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker"); break; } - target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid); - - if (target && (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry)) - l->push_back(target); + if (GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid)) + if (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry) + l->push_back(target); break; } case SMART_TARGET_PLAYER_RANGE: @@ -2601,26 +2597,21 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* } case SMART_TARGET_CLOSEST_CREATURE: { - Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead); - if (target) + if (Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead)) l->push_back(target); break; } case SMART_TARGET_CLOSEST_GAMEOBJECT: { - GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100)); - if (target) + if (GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100))) l->push_back(target); break; } case SMART_TARGET_CLOSEST_PLAYER: { if (me) - { - Player* target = me->SelectNearestPlayer((float)e.target.playerDistance.dist); - if (target) + if (Player* target = me->SelectNearestPlayer(float(e.target.playerDistance.dist))) l->push_back(target); - } break; } case SMART_TARGET_OWNER_OR_SUMMONER: @@ -2653,7 +2644,6 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me) if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly != 0)) l->push_back(target); - break; } case SMART_TARGET_CLOSEST_FRIENDLY: @@ -2661,7 +2651,6 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me) if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly != 0)) l->push_back(target); - break; } case SMART_TARGET_POSITION: diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 02bc1a2b487..b59b62c5697 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -257,21 +257,6 @@ class SmartScript } } } - SmartScriptHolder FindLinkedEvent(uint32 link) - { - if (!mEvents.empty()) - { - for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i) - { - if (i->event_id == link) - { - return (*i); - } - } - } - SmartScriptHolder s; - return s; - } }; #endif diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 2a7fd1369e2..0b2fdfc6bee 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -91,7 +91,6 @@ void SmartWaypointMgr::LoadFromDB() while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms", count, total, GetMSTimeDiffToNow(oldMSTime)); - } SmartWaypointMgr::~SmartWaypointMgr() @@ -192,23 +191,23 @@ void SmartAIMgr::LoadSmartAIFromDB() } else { - CreatureData const* creature = sObjectMgr->GetCreatureData(uint32(abs(temp.entryOrGuid))); + CreatureData const* creature = sObjectMgr->GetCreatureData(uint32(std::abs(temp.entryOrGuid))); if (!creature) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature guid (%u) does not exist, skipped loading.", uint32(abs(temp.entryOrGuid))); + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature guid (%u) does not exist, skipped loading.", uint32(std::abs(temp.entryOrGuid))); continue; } CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature->id); if (!creatureInfo) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) does not exist, skipped loading.", uint32(temp.entryOrGuid)); + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (%u) does not exist, skipped loading.", creature->id, uint32(std::abs(temp.entryOrGuid))); continue; } if (creatureInfo->AIName != "SmartAI") { - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) is not using SmartAI, skipped loading.", uint32(temp.entryOrGuid)); + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (%u) is not using SmartAI, skipped loading.", creature->id, uint32(std::abs(temp.entryOrGuid))); continue; } } @@ -263,26 +262,29 @@ void SmartAIMgr::LoadSmartAIFromDB() } while (result->NextRow()); - // TO-DO: Find better way - for (uint8 i = 0; i < SMART_SCRIPT_TYPE_MAX; i++) + // Post Loading Validation + for (uint8 i = 0; i < SMART_SCRIPT_TYPE_MAX; ++i) { - for (auto itr = mEventMap[i].begin(); itr != mEventMap[i].end(); ++itr) + for (SmartAIEventMap::iterator itr = mEventMap[i].begin(); itr != mEventMap[i].end(); ++itr) { - for (auto e : mEventMap[i][itr->first]) + for (SmartScriptHolder const& e : itr->second) { - bool found = false; - if (e.link && e.link != e.event_id) + if (e.link) { - for (auto linked : mEventMap[i][itr->first]) + if (!FindLinkedEvent(itr->second, e.link)) { - if (linked.event_id == e.link) - if (linked.GetActionType() && linked.GetEventType() == SMART_EVENT_LINK) - found = true; + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); } + } - if (!found) - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); + if (e.GetEventType() == SMART_EVENT_LINK) + { + if (!FindLinkedSourceEvent(itr->second, e.event_id)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry %d SourceType %u, Event %u, Link Source Event not found or invalid. Event will never trigger.", + e.entryOrGuid, e.GetScriptType(), e.event_id); + } } } } @@ -295,8 +297,13 @@ void SmartAIMgr::LoadSmartAIFromDB() bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e) { + if (std::abs(e.target.o) > 2 * float(M_PI)) + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u has abs(`target.o` = %f) > 2*PI (orientation is expressed in radians)", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.target.o); + if (e.GetActionType() == SMART_ACTION_INSTALL_AI_TEMPLATE) return true; // AI template has special handling + switch (e.GetTargetType()) { case SMART_TARGET_CREATURE_DISTANCE: @@ -375,27 +382,38 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetEventType()); return false; } + // in SMART_SCRIPT_TYPE_TIMED_ACTIONLIST all event types are overriden by core if (e.GetScriptType() != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && !(SmartAIEventMask[e.event.type][1] & SmartAITypeMask[e.GetScriptType()][1])) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d, event type %u can not be used for Script type %u", e.entryOrGuid, e.GetEventType(), e.GetScriptType()); return false; } + if (e.action.type <= 0 || e.action.type >= SMART_ACTION_END) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid action type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetActionType()); return false; } + if (e.event.event_phase_mask > SMART_EVENT_PHASE_ALL) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid phase mask (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_phase_mask); return false; } + if (e.event.event_flags > SMART_EVENT_FLAGS_ALL) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event flags (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_flags); return false; } + + if (e.link && e.link == e.event_id) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d SourceType %u, Event %u, Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id); + return false; + } + if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST) { e.event.type = SMART_EVENT_UPDATE_OOC;//force default OOC, can change when calling the script! @@ -407,8 +425,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } else { - uint32 type = e.event.type; - switch (type) + switch (e.GetEventType()) { case SMART_EVENT_UPDATE: case SMART_EVENT_UPDATE_IC: @@ -568,17 +585,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_EVENT_TEXT_OVER: - //if (e.event.textOver.textGroupID && !IsTextValid(e, e.event.textOver.textGroupID)) return false;// 0 is a valid text group! - break; - case SMART_EVENT_LINK: - { - if (e.link && e.link == e.event_id) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u, Event %u, Link Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id); + if (!IsTextValid(e, e.event.textOver.textGroupID)) return false; - } break; - } case SMART_EVENT_DUMMY_EFFECT: { if (!IsSpellValid(e, e.event.dummy.spell)) @@ -686,6 +695,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; } break; + case SMART_EVENT_LINK: case SMART_EVENT_GO_STATE_CHANGED: case SMART_EVENT_GO_EVENT_INFORM: case SMART_EVENT_TIMED_EVENT_TRIGGERED: @@ -729,14 +739,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) switch (e.GetActionType()) { case SMART_ACTION_TALK: - { - if (e.GetScriptType() == SMART_SCRIPT_TYPE_CREATURE) - { - if (!IsTextValid(e, e.action.talk.textGroupID)) - return false; - } + case SMART_ACTION_SIMPLE_TALK: + if (!IsTextValid(e, e.action.talk.textGroupID)) + return false; break; - } case SMART_ACTION_SET_FACTION: if (e.action.faction.factionID && !sFactionTemplateStore.LookupEntry(e.action.faction.factionID)) { @@ -816,7 +822,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!IsSpellValid(e, e.action.cast.spell)) return false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell); + SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT2)) @@ -979,10 +985,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!NotNULL(e, e.action.item.count)) return false; - CacheSpellContainerBounds sBounds = GetCreditItemSpellContainerBounds(e.action.item.entry); + CacheSpellContainerBounds sBounds = GetCreateItemSpellContainerBounds(e.action.item.entry); for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr) TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Create Item: There is a create item spell for item %u (SpellId: %u effect: %u)", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.item.entry, itr->second.first, itr->second.second); + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.item.entry, itr->second.first, itr->second.second); break; } case SMART_ACTION_TELEPORT: @@ -1183,7 +1189,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SET_NPC_FLAG: case SMART_ACTION_ADD_NPC_FLAG: case SMART_ACTION_REMOVE_NPC_FLAG: - case SMART_ACTION_SIMPLE_TALK: case SMART_ACTION_CROSS_CAST: case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: case SMART_ACTION_RANDOM_MOVE: @@ -1214,32 +1219,47 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return true; } -bool SmartAIMgr::IsTextValid(SmartScriptHolder const& e, uint32 id) // unused +bool SmartAIMgr::IsTextValid(SmartScriptHolder const& e, uint32 id) { - bool error = false; + if (e.GetScriptType() != SMART_SCRIPT_TYPE_CREATURE) + return true; + uint32 entry = 0; - if (e.entryOrGuid >= 0) - entry = uint32(e.entryOrGuid); + if (e.GetEventType() == SMART_EVENT_TEXT_OVER) + { + entry = e.event.textOver.creatureEntry; + } else { - entry = uint32(abs(e.entryOrGuid)); - CreatureData const* data = sObjectMgr->GetCreatureData(entry); - if (!data) + switch (e.GetTargetType()) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Creature guid %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; + case SMART_TARGET_CREATURE_DISTANCE: + case SMART_TARGET_CREATURE_RANGE: + case SMART_TARGET_CLOSEST_CREATURE: + return true; // ignore + default: + if (e.entryOrGuid < 0) + { + entry = uint32(std::abs(e.entryOrGuid)); + CreatureData const* data = sObjectMgr->GetCreatureData(entry); + if (!data) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Creature guid %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + else + entry = data->id; + } + else + entry = uint32(e.entryOrGuid); + break; } - else - entry = data->id; } if (!entry || !sCreatureTextMgr->TextExist(entry, uint8(id))) - error = true; - - if (error) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Text id %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.source_type, e.GetActionType(), id); + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Text id %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), id); return false; } @@ -1299,7 +1319,7 @@ CacheSpellContainerBounds SmartAIMgr::GetKillCreditSpellContainerBounds(uint32 k return KillCreditSpellStore.equal_range(killCredit); } -CacheSpellContainerBounds SmartAIMgr::GetCreditItemSpellContainerBounds(uint32 itemId) const +CacheSpellContainerBounds SmartAIMgr::GetCreateItemSpellContainerBounds(uint32 itemId) const { return CreateItemSpellStore.equal_range(itemId); } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index bdd1dfc6ae0..a567a4be35e 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1355,6 +1355,8 @@ struct SmartScriptHolder bool active; bool runOnce; bool enableTimed; + + operator bool() const { return entryOrGuid != 0; } }; typedef std::unordered_map<uint32, WayPoint*> WPPath; @@ -1477,6 +1479,30 @@ class SmartAIMgr } } + static SmartScriptHolder& FindLinkedSourceEvent(SmartAIEventList& list, uint32 eventId) + { + SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), + [eventId](SmartScriptHolder& source) { return source.link == eventId; }); + + if (itr != list.end()) + return *itr; + + static SmartScriptHolder SmartScriptHolderDummy; + return SmartScriptHolderDummy; + } + + static SmartScriptHolder& FindLinkedEvent(SmartAIEventList& list, uint32 link) + { + SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), + [link](SmartScriptHolder& linked) { return linked.event_id == link && linked.GetEventType() == SMART_EVENT_LINK; }); + + if (itr != list.end()) + return *itr; + + static SmartScriptHolder SmartScriptHolderDummy; + return SmartScriptHolderDummy; + } + private: //event stores SmartAIEventMap mEventMap[SMART_SCRIPT_TYPE_MAX]; @@ -1484,16 +1510,6 @@ class SmartAIMgr bool IsEventValid(SmartScriptHolder& e); bool IsTargetValid(SmartScriptHolder const& e); - /*inline bool IsTargetValid(SmartScriptHolder e, int32 target) - { - if (target < SMART_TARGET_NONE || target >= SMART_TARGET_END) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Target type %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), target); - return false; - } - return true; - }*/ - bool IsMinMaxValid(SmartScriptHolder const& e, uint32 min, uint32 max) { if (max < min) @@ -1623,7 +1639,7 @@ class SmartAIMgr CacheSpellContainerBounds GetSummonCreatureSpellContainerBounds(uint32 creatureEntry) const; CacheSpellContainerBounds GetSummonGameObjectSpellContainerBounds(uint32 gameObjectEntry) const; CacheSpellContainerBounds GetKillCreditSpellContainerBounds(uint32 killCredit) const; - CacheSpellContainerBounds GetCreditItemSpellContainerBounds(uint32 itemId) const; + CacheSpellContainerBounds GetCreateItemSpellContainerBounds(uint32 itemId) const; CacheSpellContainer SummonCreatureSpellStore; CacheSpellContainer SummonGameObjectSpellStore; diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 682df18b2d1..4abcf35fe57 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -84,7 +84,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId) ObjectGuid guid(HIGHGUID_PLAYER, (*result)[0].GetUInt32()); // Kick if player is online - if (Player* p = ObjectAccessor::FindPlayer(guid)) + if (Player* p = ObjectAccessor::FindConnectedPlayer(guid)) { WorldSession* s = p->GetSession(); s->KickPlayer(); // mark session to remove at next session list update diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 79512e57fe3..9390ec80208 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -93,7 +93,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& uint32 bidderAccId = 0; ObjectGuid bidderGuid(HIGHGUID_PLAYER, auction->bidder); - Player* bidder = ObjectAccessor::FindPlayer(bidderGuid); + Player* bidder = ObjectAccessor::FindConnectedPlayer(bidderGuid); // data for gm.log std::string bidderName; bool logGmTrade = false; @@ -107,7 +107,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& else { bidderAccId = sObjectMgr->GetPlayerAccountIdByGUID(bidderGuid); - logGmTrade = AccountMgr::HasPermission(bidderAccId, rbac::RBAC_PERM_LOG_GM_TRADE, realmID); + logGmTrade = AccountMgr::HasPermission(bidderAccId, rbac::RBAC_PERM_LOG_GM_TRADE, realmHandle.Index); if (logGmTrade && !sObjectMgr->GetPlayerNameByGUID(bidderGuid, bidderName)) bidderName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); @@ -157,7 +157,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, SQLTransaction& trans) { ObjectGuid owner_guid(HIGHGUID_PLAYER, auction->owner); - Player* owner = ObjectAccessor::FindPlayer(owner_guid); + Player* owner = ObjectAccessor::FindConnectedPlayer(owner_guid); uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid); // owner exist (online or offline) if (owner || owner_accId) @@ -169,7 +169,7 @@ void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, SQLTrans void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransaction& trans) { ObjectGuid owner_guid(HIGHGUID_PLAYER, auction->owner); - Player* owner = ObjectAccessor::FindPlayer(owner_guid); + Player* owner = ObjectAccessor::FindConnectedPlayer(owner_guid); uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid); // owner exist if (owner || owner_accId) @@ -200,7 +200,7 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, SQLTransacti return; ObjectGuid owner_guid(HIGHGUID_PLAYER, auction->owner); - Player* owner = ObjectAccessor::FindPlayer(owner_guid); + Player* owner = ObjectAccessor::FindConnectedPlayer(owner_guid); uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid); // owner exist if (owner || owner_accId) @@ -223,7 +223,7 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, SQLTransacti void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans) { ObjectGuid oldBidder_guid(HIGHGUID_PLAYER, auction->bidder); - Player* oldBidder = ObjectAccessor::FindPlayer(oldBidder_guid); + Player* oldBidder = ObjectAccessor::FindConnectedPlayer(oldBidder_guid); uint32 oldBidder_accId = 0; if (!oldBidder) @@ -245,7 +245,7 @@ void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 new void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans, Item* item) { ObjectGuid bidder_guid = ObjectGuid(HIGHGUID_PLAYER, auction->bidder); - Player* bidder = ObjectAccessor::FindPlayer(bidder_guid); + Player* bidder = ObjectAccessor::FindConnectedPlayer(bidder_guid); uint32 bidder_accId = 0; if (!bidder) diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index ab90fca0115..3dcc126f872 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -422,7 +422,7 @@ void Battlefield::BroadcastPacketToQueue(WorldPacket& data) const { for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (GuidSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(*itr)) player->SendDirectMessage(&data); } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 4c5994f6b3a..326adb66c72 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -253,7 +253,7 @@ void BattlefieldWG::OnBattleStart() for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) { // Kick player in orb room, TODO: offline player ? - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) { float x, y, z; player->GetPosition(x, y, z); @@ -356,7 +356,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer) for (GuidSet::const_iterator itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr) { - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) { player->CastSpell(player, SPELL_ESSENCE_OF_WINTERGRASP, true); player->CastSpell(player, SPELL_VICTORY_REWARD, true); @@ -369,13 +369,13 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer) } for (GuidSet::const_iterator itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->CastSpell(player, SPELL_DEFEAT_REWARD, true); for (uint8 team = 0; team < 2; ++team) { for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) RemoveAurasFromPlayer(player); m_PlayersInWar[team].clear(); @@ -394,7 +394,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer) { for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) { - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) { player->RemoveAurasDueToSpell(m_DefenderTeam == TEAM_ALLIANCE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player->GetGUID()); player->AddAura(m_DefenderTeam == TEAM_HORDE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player); @@ -620,7 +620,7 @@ void BattlefieldWG::HandleKill(Player* killer, Unit* victim) if (victim->GetTypeId() == TYPEID_PLAYER) { for (GuidSet::const_iterator itr = m_PlayersInWar[killerTeam].begin(); itr != m_PlayersInWar[killerTeam].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (player->GetDistance2d(killer) < 40) PromotePlayer(player); return; @@ -635,7 +635,7 @@ void BattlefieldWG::HandleKill(Player* killer, Unit* victim) { again = true; for (GuidSet::const_iterator iter = m_PlayersInWar[killerTeam].begin(); iter != m_PlayersInWar[killerTeam].end(); ++iter) - if (Player* player = sObjectAccessor->FindPlayer(*iter)) + if (Player* player = ObjectAccessor::FindPlayer(*iter)) if (player->GetDistance2d(killer) < 40.0f) PromotePlayer(player); } @@ -847,7 +847,7 @@ void BattlefieldWG::SendInitWorldStatesToAll() { for (uint8 team = 0; team < 2; team++) for (GuidSet::iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) SendInitWorldStatesTo(player); } @@ -858,7 +858,7 @@ void BattlefieldWG::BrokenWallOrTower(TeamId /*team*/) { for (GuidSet::const_iterator itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) { - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) IncrementQuest(player, WGQuest[player->GetTeamId()][2], true); } }*/ @@ -876,12 +876,12 @@ void BattlefieldWG::UpdatedDestroyedTowerCount(TeamId team) // Remove buff stack on attackers for (GuidSet::const_iterator itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->RemoveAuraFromStack(SPELL_TOWER_CONTROL); // Add buff stack to defenders for (GuidSet::const_iterator itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) { player->CastSpell(player, SPELL_TOWER_CONTROL, true); DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WG_TOWER_DESTROY, player); @@ -986,7 +986,7 @@ void BattlefieldWG::UpdateTenacity() if (team != TEAM_NEUTRAL) { for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (player->getLevel() >= m_MinLevel) player->RemoveAurasDueToSpell(SPELL_TENACITY); @@ -1014,7 +1014,7 @@ void BattlefieldWG::UpdateTenacity() buff_honor = 0; for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->SetAuraStack(SPELL_TENACITY, player, newStack); for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) @@ -1024,7 +1024,7 @@ void BattlefieldWG::UpdateTenacity() if (buff_honor != 0) { for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) - if (Player* player = sObjectAccessor->FindPlayer(*itr)) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->CastSpell(player, buff_honor, true); for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) if (Creature* creature = GetCreature(*itr)) diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp index 39fff2529b9..b75a71f32b7 100644 --- a/src/server/game/Battlegrounds/Arena.cpp +++ b/src/server/game/Battlegrounds/Arena.cpp @@ -180,7 +180,7 @@ void Arena::EndBattleground(uint32 winner) if (sWorld->getBoolConfig(CONFIG_ARENA_LOG_EXTENDED_INFO)) for (auto const& score : PlayerScores) - if (Player* player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, score.first))) + if (Player* player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HIGHGUID_PLAYER, score.first))) { TC_LOG_DEBUG("bg.arena", "Statistics match Type: %u for %s (GUID: %u, Team: %d, IP: %s): %s", GetArenaType(), player->GetName().c_str(), score.first, player->GetArenaTeamId(GetArenaType() == 5 ? 2 : GetArenaType() == 3), diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index c26238cdc9c..8a0b0d04df6 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -120,7 +120,7 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid) // Check if player is already in a similar arena team if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0) { - TC_LOG_DEBUG("bg.arena", "Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), playerGuid.GetCounter(), GetType()); + TC_LOG_DEBUG("bg.arena", "Arena: %s %s already has an arena team of type %u", playerGuid.ToString().c_str(), playerName.c_str(), GetType()); return false; } @@ -179,7 +179,7 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid) player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1); } - TC_LOG_INFO("bg.arena", "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), playerGuid.GetCounter(), GetType(), GetId(), GetName().c_str()); + TC_LOG_INFO("bg.arena", "Player: %s [%s] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), playerGuid.ToString().c_str(), GetType(), GetId(), GetName().c_str()); return true; } @@ -245,7 +245,7 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result) // Delete member if character information is missing if (newMember.Name.empty()) { - TC_LOG_ERROR("sql.sql", "ArenaTeam %u has member with empty name - probably player %u doesn't exist, deleting him from memberlist!", arenaTeamId, newMember.Guid.GetCounter()); + TC_LOG_ERROR("sql.sql", "ArenaTeam %u has member with empty name - probably %s doesn't exist, deleting him from memberlist!", arenaTeamId, newMember.Guid.ToString().c_str()); DelMember(newMember.Guid, true); continue; } @@ -408,7 +408,7 @@ void ArenaTeam::Roster(WorldSession* session) for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr) { - player = ObjectAccessor::FindPlayer(itr->Guid); + player = ObjectAccessor::FindConnectedPlayer(itr->Guid); data << uint64(itr->Guid); // guid data << uint8((player ? 1 : 0)); // online flag @@ -465,7 +465,7 @@ void ArenaTeam::NotifyStatsChanged() // This is called after a rated match ended // Updates arena team stats for every member of the team (not only the ones who participated!) for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(itr->Guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(itr->Guid)) SendStats(player->GetSession()); } @@ -512,7 +512,7 @@ void ArenaTeamMember::ModifyMatchmakerRating(int32 mod, uint32 /*slot*/) void ArenaTeam::BroadcastPacket(WorldPacket* packet) { for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(itr->Guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(itr->Guid)) player->GetSession()->SendPacket(packet); } @@ -611,7 +611,7 @@ uint32 ArenaTeam::GetAverageMMR(Group* group) const for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr) { // Skip if player is not online - if (!ObjectAccessor::FindPlayer(itr->Guid)) + if (!ObjectAccessor::FindConnectedPlayer(itr->Guid)) continue; // Skip if player is not a member of group @@ -699,7 +699,7 @@ void ArenaTeam::FinishGame(int32 mod) // Check if rating related achivements are met for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr) - if (Player* member = ObjectAccessor::FindPlayer(itr->Guid)) + if (Player* member = ObjectAccessor::FindConnectedPlayer(itr->Guid)) member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING, Stats.Rating, Type); } diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index b1189e6c03e..52843b97a51 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -598,10 +598,11 @@ Player* Battleground::_GetPlayer(ObjectGuid guid, bool offlineRemove, char const Player* player = NULL; if (!offlineRemove) { + // should this be ObjectAccessor::FindConnectedPlayer() to return players teleporting ? player = ObjectAccessor::FindPlayer(guid); if (!player) - TC_LOG_ERROR("bg.battleground", "Battleground::%s: player (GUID: %u) not found for BG (map: %u, instance id: %u)!", - context, guid.GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::%s: player (%s) not found for BG (map: %u, instance id: %u)!", + context, guid.ToString().c_str(), m_MapId, m_InstanceID); } return player; } @@ -1478,8 +1479,8 @@ void Battleground::DoorClose(uint32 type) } } else - TC_LOG_ERROR("bg.battleground", "Battleground::DoorClose: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgObjects[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::DoorClose: door gameobject (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgObjects[type].ToString().c_str(), m_MapId, m_InstanceID); } void Battleground::DoorOpen(uint32 type) @@ -1490,8 +1491,8 @@ void Battleground::DoorOpen(uint32 type) obj->SetGoState(GO_STATE_ACTIVE); } else - TC_LOG_ERROR("bg.battleground", "Battleground::DoorOpen: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgObjects[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::DoorOpen: door gameobject (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgObjects[type].ToString().c_str(), m_MapId, m_InstanceID); } GameObject* Battleground::GetBGObject(uint32 type, bool logError) @@ -1500,11 +1501,11 @@ GameObject* Battleground::GetBGObject(uint32 type, bool logError) if (!obj) { if (logError) - TC_LOG_ERROR("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgObjects[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgObjects[type].ToString().c_str(), m_MapId, m_InstanceID); else - TC_LOG_INFO("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgObjects[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_INFO("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgObjects[type].ToString().c_str(), m_MapId, m_InstanceID); } return obj; } @@ -1515,11 +1516,11 @@ Creature* Battleground::GetBGCreature(uint32 type, bool logError) if (!creature) { if (logError) - TC_LOG_ERROR("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgCreatures[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgCreatures[type].ToString().c_str(), m_MapId, m_InstanceID); else - TC_LOG_INFO("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgCreatures[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_INFO("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgCreatures[type].ToString().c_str(), m_MapId, m_InstanceID); } return creature; } @@ -1600,8 +1601,8 @@ bool Battleground::DelCreature(uint32 type) return true; } - TC_LOG_ERROR("bg.battleground", "Battleground::DelCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgCreatures[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::DelCreature: creature (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgCreatures[type].ToString().c_str(), m_MapId, m_InstanceID); BgCreatures[type].Clear(); return false; } @@ -1618,8 +1619,8 @@ bool Battleground::DelObject(uint32 type) BgObjects[type].Clear(); return true; } - TC_LOG_ERROR("bg.battleground", "Battleground::DelObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, BgObjects[type].GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::DelObject: gameobject (type: %u, %s) not found for BG (map: %u, instance id: %u)!", + type, BgObjects[type].ToString().c_str(), m_MapId, m_InstanceID); BgObjects[type].Clear(); return false; } @@ -1734,8 +1735,8 @@ void Battleground::HandleTriggerBuff(ObjectGuid go_guid) index--; if (index < 0) { - TC_LOG_ERROR("bg.battleground", "Battleground::HandleTriggerBuff: cannot find buff gameobject (GUID: %u, entry: %u, type: %u) in internal data for BG (map: %u, instance id: %u)!", - go_guid.GetCounter(), obj->GetEntry(), obj->GetGoType(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::HandleTriggerBuff: cannot find buff gameobject (%s, entry: %u, type: %u) in internal data for BG (map: %u, instance id: %u)!", + go_guid.ToString().c_str(), obj->GetEntry(), obj->GetGoType(), m_MapId, m_InstanceID); return; } @@ -1858,8 +1859,8 @@ int32 Battleground::GetObjectType(ObjectGuid guid) for (uint32 i = 0; i < BgObjects.size(); ++i) if (BgObjects[i] == guid) return i; - TC_LOG_ERROR("bg.battleground", "Battleground::GetObjectType: player used gameobject (GUID: %u) which is not in internal data for BG (map: %u, instance id: %u), cheating?", - guid.GetCounter(), m_MapId, m_InstanceID); + TC_LOG_ERROR("bg.battleground", "Battleground::GetObjectType: player used gameobject (%s) which is not in internal data for BG (map: %u, instance id: %u), cheating?", + guid.ToString().c_str(), m_MapId, m_InstanceID); return -1; } diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 375c896fd39..8bc37e023e8 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -293,7 +293,7 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) std::string playerName = "Unknown"; if (Player* player = ObjectAccessor::FindPlayer(guid)) playerName = player->GetName(); - TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: couldn't find player %s (GUID: %u)", playerName.c_str(), guid.GetCounter()); + TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: couldn't find player %s (%s)", playerName.c_str(), guid.ToString().c_str()); return; } @@ -328,10 +328,10 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) //player can't be in queue without group, but just in case if (bracket_id == -1) { - TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: ERROR Cannot find groupinfo for player GUID: %u", guid.GetCounter()); + TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: ERROR Cannot find groupinfo for %s", guid.ToString().c_str()); return; } - TC_LOG_DEBUG("bg.battleground", "BattlegroundQueue: Removing player GUID %u, from bracket_id %u", guid.GetCounter(), (uint32)bracket_id); + TC_LOG_DEBUG("bg.battleground", "BattlegroundQueue: Removing %s, from bracket_id %u", guid.ToString().c_str(), (uint32)bracket_id); // ALL variables are correctly set // We can ignore leveling up in queue - it should not cause crash @@ -361,8 +361,8 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) { if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId)) { - TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for %u by opponents rating: %u", guid.GetCounter(), group->OpponentsTeamRating); - if (Player* player = ObjectAccessor::FindPlayer(guid)) + TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for %s by opponents rating: %u", guid.ToString().c_str(), group->OpponentsTeamRating); + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) at->MemberLost(player, group->OpponentsMatchmakerRating); else at->OfflineMemberLost(guid, group->OpponentsMatchmakerRating); @@ -385,7 +385,7 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) { // remove next player, this is recursive // first send removal information - if (Player* plr2 = ObjectAccessor::FindPlayer(group->Players.begin()->first)) + if (Player* plr2 = ObjectAccessor::FindConnectedPlayer(group->Players.begin()->first)) { Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType); @@ -450,7 +450,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, for (std::map<ObjectGuid, PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) { // get the player - Player* player = ObjectAccessor::FindPlayer(itr->first); + Player* player = ObjectAccessor::FindConnectedPlayer(itr->first); // if offline, skip him, this should not happen - player is removed from queue when he logs out if (!player) continue; @@ -981,7 +981,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { - Player* player = ObjectAccessor::FindPlayer(m_PlayerGuid); + Player* player = ObjectAccessor::FindConnectedPlayer(m_PlayerGuid); // player logged off (we should do nothing, he is correctly removed from queue in another procedure) if (!player) return true; @@ -1024,7 +1024,7 @@ void BGQueueInviteEvent::Abort(uint64 /*e_time*/) */ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { - Player* player = ObjectAccessor::FindPlayer(m_PlayerGuid); + Player* player = ObjectAccessor::FindConnectedPlayer(m_PlayerGuid); if (!player) // player logged off (we should do nothing, he is correctly removed from queue in another procedure) return true; diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 0d1b460500e..27b3ea2c381 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -111,6 +111,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/zlib + ${CMAKE_SOURCE_DIR}/dep/zmqpp ${CMAKE_SOURCE_DIR}/src/server/collision ${CMAKE_SOURCE_DIR}/src/server/collision/Management ${CMAKE_SOURCE_DIR}/src/server/collision/Models @@ -129,6 +130,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/ipc ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Accounts ${CMAKE_CURRENT_SOURCE_DIR}/Achievements @@ -205,6 +207,7 @@ include_directories( ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} + ${ZMQ_INCLUDE_DIR} ) add_library(game STATIC diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index 2e62e8514a0..5270e42d0b1 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -350,7 +350,7 @@ CalendarEventStore CalendarMgr::GetPlayerEvents(ObjectGuid guid) if (CalendarEvent* event = GetEvent(itr->first)) // NULL check added as attempt to fix #11512 events.insert(event); - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) if ((*itr)->GetGuildId() == player->GetGuildId()) events.insert(*itr); @@ -424,7 +424,7 @@ void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite) bool hasStatusTime = statusTime != 946684800; // 01/01/2000 00:00:00 ObjectGuid invitee = invite.GetInviteeGUID(); - Player* player = ObjectAccessor::FindPlayer(invitee); + Player* player = ObjectAccessor::FindConnectedPlayer(invitee); uint8 level = player ? player->getLevel() : Player::GetLevelFromDB(invitee); @@ -441,7 +441,7 @@ void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite) if (!calendarEvent) // Pre-invite { - if (Player* playerSender = ObjectAccessor::FindPlayer(invite.GetSenderGUID())) + if (Player* playerSender = ObjectAccessor::FindConnectedPlayer(invite.GetSenderGUID())) playerSender->SendDirectMessage(&data); } else @@ -542,13 +542,13 @@ void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEven guild->BroadcastPacket(&data); } else - if (Player* player = ObjectAccessor::FindPlayer(invite.GetInviteeGUID())) + if (Player* player = ObjectAccessor::FindConnectedPlayer(invite.GetInviteeGUID())) player->SendDirectMessage(&data); } void CalendarMgr::SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarSendEventType sendType) { - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); if (!player) return; @@ -596,7 +596,7 @@ void CalendarMgr::SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calend void CalendarMgr::SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarInviteStatus status) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { WorldPacket data(SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT, 8 + 4 + 4 + 1); data << uint64(calendarEvent.GetEventId()); @@ -610,7 +610,7 @@ void CalendarMgr::SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEv void CalendarMgr::SendCalendarClearPendingAction(ObjectGuid guid) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { WorldPacket data(SMSG_CALENDAR_CLEAR_PENDING_ACTION, 0); player->SendDirectMessage(&data); @@ -619,7 +619,7 @@ void CalendarMgr::SendCalendarClearPendingAction(ObjectGuid guid) void CalendarMgr::SendCalendarCommandResult(ObjectGuid guid, CalendarError err, char const* param /*= NULL*/) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { WorldPacket data(SMSG_CALENDAR_COMMAND_RESULT, 0); data << uint32(0); @@ -652,7 +652,7 @@ void CalendarMgr::SendPacketToAllEventRelatives(WorldPacket& packet, CalendarEve // Send packet to all invitees if event is non-guild, in other case only to non-guild invitees (packet was broadcasted for them) CalendarInviteStore invites = _invites[calendarEvent.GetEventId()]; for (CalendarInviteStore::iterator itr = invites.begin(); itr != invites.end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer((*itr)->GetInviteeGUID())) + if (Player* player = ObjectAccessor::FindConnectedPlayer((*itr)->GetInviteeGUID())) if (!calendarEvent.IsGuildEvent() || (calendarEvent.IsGuildEvent() && player->GetGuildId() != calendarEvent.GetGuildId())) player->SendDirectMessage(&packet); } diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp index 654ce8da2b9..6d984ab2e66 100644 --- a/src/server/game/Chat/Channels/Channel.cpp +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -296,7 +296,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b return; } - Player* bad = sObjectAccessor->FindPlayerByName(badname); + Player* bad = ObjectAccessor::FindConnectedPlayerByName(badname); ObjectGuid victim = bad ? bad->GetGUID() : ObjectGuid::Empty; if (!victim || !IsOn(victim)) { @@ -366,7 +366,7 @@ void Channel::UnBan(Player const* player, std::string const& badname) return; } - Player* bad = sObjectAccessor->FindPlayerByName(badname); + Player* bad = ObjectAccessor::FindConnectedPlayerByName(badname); ObjectGuid victim = bad ? bad->GetGUID() : ObjectGuid::Empty; if (!victim || !IsBanned(victim)) @@ -439,7 +439,7 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo if (guid == _ownerGUID && std::string(p2n) == player->GetName() && mod) return; - Player* newp = sObjectAccessor->FindPlayerByName(p2n); + Player* newp = ObjectAccessor::FindConnectedPlayerByName(p2n); ObjectGuid victim = newp ? newp->GetGUID() : ObjectGuid::Empty; if (!victim || !IsOn(victim) || @@ -487,7 +487,7 @@ void Channel::SetOwner(Player const* player, std::string const& newname) return; } - Player* newp = sObjectAccessor->FindPlayerByName(newname); + Player* newp = ObjectAccessor::FindConnectedPlayerByName(newname); ObjectGuid victim = newp ? newp->GetGUID() : ObjectGuid::Empty; if (!victim || !IsOn(victim) || @@ -543,7 +543,7 @@ void Channel::List(Player const* player) uint32 count = 0; for (PlayerContainer::const_iterator i = playersStore.begin(); i != playersStore.end(); ++i) { - Player* member = ObjectAccessor::FindPlayer(i->first); + Player* member = ObjectAccessor::FindConnectedPlayer(i->first); // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all @@ -621,7 +621,7 @@ void Channel::Say(ObjectGuid guid, std::string const& what, uint32 lang) } WorldPacket data; - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name); else ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), guid, guid, what, 0, "", "", 0, false, _name); @@ -641,7 +641,7 @@ void Channel::Invite(Player const* player, std::string const& newname) return; } - Player* newp = sObjectAccessor->FindPlayerByName(newname); + Player* newp = ObjectAccessor::FindConnectedPlayerByName(newname); if (!newp || !newp->isGMVisible()) { WorldPacket data; @@ -723,7 +723,7 @@ void Channel::SetOwner(ObjectGuid guid, bool exclaim) void Channel::SendToAll(WorldPacket* data, ObjectGuid guid) { for (PlayerContainer::const_iterator i = playersStore.begin(); i != playersStore.end(); ++i) - if (Player* player = ObjectAccessor::FindPlayer(i->first)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(i->first)) if (!guid || !player->GetSocial()->HasIgnore(guid.GetCounter())) player->GetSession()->SendPacket(data); } @@ -732,13 +732,13 @@ void Channel::SendToAllButOne(WorldPacket* data, ObjectGuid who) { for (PlayerContainer::const_iterator i = playersStore.begin(); i != playersStore.end(); ++i) if (i->first != who) - if (Player* player = ObjectAccessor::FindPlayer(i->first)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(i->first)) player->GetSession()->SendPacket(data); } void Channel::SendToOne(WorldPacket* data, ObjectGuid who) { - if (Player* player = ObjectAccessor::FindPlayer(who)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(who)) player->GetSession()->SendPacket(data); } diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index ace13989efb..501f73c460f 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -160,7 +160,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac if (target) target_sec = target->GetSecurity(); else if (target_account) - target_sec = AccountMgr::GetSecurity(target_account, realmID); + target_sec = AccountMgr::GetSecurity(target_account, realmHandle.Index); else return true; // caller must report error for (target == NULL && target_account == 0) @@ -765,7 +765,7 @@ Player* ChatHandler::getSelectedPlayer() if (!selected) return m_session->GetPlayer(); - return ObjectAccessor::FindPlayer(selected); + return ObjectAccessor::FindConnectedPlayer(selected); } Unit* ChatHandler::getSelectedUnit() @@ -810,7 +810,7 @@ Player* ChatHandler::getSelectedPlayerOrSelf() return m_session->GetPlayer(); // first try with selected target - Player* targetPlayer = ObjectAccessor::FindPlayer(selected); + Player* targetPlayer = ObjectAccessor::FindConnectedPlayer(selected); // if the target is not a player, then return self if (!targetPlayer) targetPlayer = m_session->GetPlayer(); @@ -1090,7 +1090,7 @@ ObjectGuid ChatHandler::extractGuidFromLink(char* text) if (!normalizePlayerName(name)) return ObjectGuid::Empty; - if (Player* player = sObjectAccessor->FindPlayerByName(name)) + if (Player* player = ObjectAccessor::FindPlayerByName(name)) return player->GetGUID(); if (ObjectGuid guid = sObjectMgr->GetPlayerGUIDByName(name)) @@ -1148,7 +1148,7 @@ bool ChatHandler::extractPlayerTarget(char* args, Player** player, ObjectGuid* p return false; } - Player* pl = sObjectAccessor->FindPlayerByName(name); + Player* pl = ObjectAccessor::FindPlayerByName(name); // if allowed player pointer if (player) @@ -1312,7 +1312,7 @@ bool ChatHandler::GetPlayerGroupAndGUIDByName(const char* cname, Player*& player return false; } - player = sObjectAccessor->FindPlayerByName(name); + player = ObjectAccessor::FindPlayerByName(name); if (offline) guid = sObjectMgr->GetPlayerGUIDByName(name.c_str()); } diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp index 3f325be1e83..eb50545b510 100644 --- a/src/server/game/Conditions/DisableMgr.cpp +++ b/src/server/game/Conditions/DisableMgr.cpp @@ -21,8 +21,8 @@ #include "ObjectMgr.h" #include "OutdoorPvP.h" #include "SpellMgr.h" -#include "VMapManager2.h" #include "Player.h" +#include "World.h" namespace DisableMgr { @@ -193,28 +193,28 @@ void LoadDisables() switch (mapEntry->map_type) { case MAP_COMMON: - if (flags & VMAP_DISABLE_AREAFLAG) + if (flags & VMAP::VMAP_DISABLE_AREAFLAG) TC_LOG_INFO("misc", "Areaflag disabled for world map %u.", entry); - if (flags & VMAP_DISABLE_LIQUIDSTATUS) + if (flags & VMAP::VMAP_DISABLE_LIQUIDSTATUS) TC_LOG_INFO("misc", "Liquid status disabled for world map %u.", entry); break; case MAP_INSTANCE: case MAP_RAID: - if (flags & VMAP_DISABLE_HEIGHT) + if (flags & VMAP::VMAP_DISABLE_HEIGHT) TC_LOG_INFO("misc", "Height disabled for instance map %u.", entry); - if (flags & VMAP_DISABLE_LOS) + if (flags & VMAP::VMAP_DISABLE_LOS) TC_LOG_INFO("misc", "LoS disabled for instance map %u.", entry); break; case MAP_BATTLEGROUND: - if (flags & VMAP_DISABLE_HEIGHT) + if (flags & VMAP::VMAP_DISABLE_HEIGHT) TC_LOG_INFO("misc", "Height disabled for battleground map %u.", entry); - if (flags & VMAP_DISABLE_LOS) + if (flags & VMAP::VMAP_DISABLE_LOS) TC_LOG_INFO("misc", "LoS disabled for battleground map %u.", entry); break; case MAP_ARENA: - if (flags & VMAP_DISABLE_HEIGHT) + if (flags & VMAP::VMAP_DISABLE_HEIGHT) TC_LOG_INFO("misc", "Height disabled for arena map %u.", entry); - if (flags & VMAP_DISABLE_LOS) + if (flags & VMAP::VMAP_DISABLE_LOS) TC_LOG_INFO("misc", "LoS disabled for arena map %u.", entry); break; default: @@ -387,4 +387,15 @@ bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags return false; } +bool IsVMAPDisabledFor(uint32 entry, uint8 flags) +{ + return IsDisabledFor(DISABLE_TYPE_VMAP, entry, NULL, flags); +} + +bool IsPathfindingEnabled(uint32 mapId) +{ + return sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) + && !IsDisabledFor(DISABLE_TYPE_MMAP, mapId, NULL, MMAP_DISABLE_PATHFINDING); +} + } // Namespace diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h index 0930da78547..f6c65abe90a 100644 --- a/src/server/game/Conditions/DisableMgr.h +++ b/src/server/game/Conditions/DisableMgr.h @@ -19,6 +19,7 @@ #ifndef TRINITY_DISABLEMGR_H #define TRINITY_DISABLEMGR_H +#include "VMapManager2.h" #include "Define.h" class Unit; @@ -49,14 +50,6 @@ enum SpellDisableTypes SPELL_DISABLE_LOS) }; -enum VmapDisableTypes -{ - VMAP_DISABLE_AREAFLAG = 0x1, - VMAP_DISABLE_HEIGHT = 0x2, - VMAP_DISABLE_LOS = 0x4, - VMAP_DISABLE_LIQUIDSTATUS = 0x8 -}; - enum MMapDisableTypes { MMAP_DISABLE_PATHFINDING = 0x0 @@ -67,6 +60,8 @@ namespace DisableMgr void LoadDisables(); bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0); void CheckQuestDisables(); + bool IsVMAPDisabledFor(uint32 entry, uint8 flags); + bool IsPathfindingEnabled(uint32 mapId); } #endif //TRINITY_DISABLEMGR_H diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 4bed997bced..3946d7b543f 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -490,8 +490,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const // Can't join. Send result if (joinData.result != LFG_JOIN_OK) { - TC_LOG_DEBUG("lfg.join", "%u joining with %u members. Result: %u, Dungeons: %s", - guid.GetCounter(), grp ? grp->GetMembersCount() : 1, joinData.result, ConcatenateDungeons(dungeons).c_str()); + TC_LOG_DEBUG("lfg.join", "%s joining with %u members. Result: %u, Dungeons: %s", + guid.ToString().c_str(), grp ? grp->GetMembersCount() : 1, joinData.result, ConcatenateDungeons(dungeons).c_str()); if (!dungeons.empty()) // Only should show lockmap when have no dungeons available joinData.lockmap.clear(); @@ -503,7 +503,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const if (isRaid) { - TC_LOG_DEBUG("lfg.join", "%u trying to join raid browser and it's disabled.", guid.GetCounter()); + TC_LOG_DEBUG("lfg.join", "%s trying to join raid browser and it's disabled.", guid.ToString().c_str()); return; } @@ -569,7 +569,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const debugNames.append(player->GetName()); } - TC_LOG_DEBUG("lfg.join", "%u joined (%s), Members: %s. Dungeons (%u): %s", guid.GetCounter(), + TC_LOG_DEBUG("lfg.join", "%s joined (%s), Members: %s. Dungeons (%u): %s", guid.ToString().c_str(), grp ? "group" : "player", debugNames.c_str(), uint32(dungeons.size()), ConcatenateDungeons(dungeons).c_str()); } @@ -583,7 +583,7 @@ void LFGMgr::LeaveLfg(ObjectGuid guid) { ObjectGuid gguid = guid.IsGroup() ? guid : GetGroup(guid); - TC_LOG_DEBUG("lfg.leave", "%u left (%s)", guid.GetCounter(), guid == gguid ? "group" : "player"); + TC_LOG_DEBUG("lfg.leave", "%s left (%s)", guid.ToString().c_str(), guid == gguid ? "group" : "player"); LfgState state = GetState(guid); switch (state) @@ -772,10 +772,9 @@ void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& playe Check if a group can be formed with the given group roles @param[in] groles Map of roles to check - @param[in] removeLeaderFlag Determines if we have to remove leader flag (only used first call, Default = true) @return True if roles are compatible */ -bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true*/) +bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles) { if (groles.empty()) return false; @@ -784,21 +783,18 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true uint8 tank = 0; uint8 healer = 0; - if (removeLeaderFlag) - for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it) - it->second &= ~PLAYER_ROLE_LEADER; - for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it) { - if (it->second == PLAYER_ROLE_NONE) + uint8 role = it->second & ~PLAYER_ROLE_LEADER; + if (role == PLAYER_ROLE_NONE) return false; - if (it->second & PLAYER_ROLE_DAMAGE) + if (role & PLAYER_ROLE_DAMAGE) { - if (it->second != PLAYER_ROLE_DAMAGE) + if (role != PLAYER_ROLE_DAMAGE) { it->second -= PLAYER_ROLE_DAMAGE; - if (CheckGroupRoles(groles, false)) + if (CheckGroupRoles(groles)) return true; it->second += PLAYER_ROLE_DAMAGE; } @@ -808,12 +804,12 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true damage++; } - if (it->second & PLAYER_ROLE_HEALER) + if (role & PLAYER_ROLE_HEALER) { - if (it->second != PLAYER_ROLE_HEALER) + if (role != PLAYER_ROLE_HEALER) { it->second -= PLAYER_ROLE_HEALER; - if (CheckGroupRoles(groles, false)) + if (CheckGroupRoles(groles)) return true; it->second += PLAYER_ROLE_HEALER; } @@ -823,12 +819,12 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true healer++; } - if (it->second & PLAYER_ROLE_TANK) + if (role & PLAYER_ROLE_TANK) { - if (it->second != PLAYER_ROLE_TANK) + if (role != PLAYER_ROLE_TANK) { it->second -= PLAYER_ROLE_TANK; - if (CheckGroupRoles(groles, false)) + if (CheckGroupRoles(groles)) return true; it->second += PLAYER_ROLE_TANK; } @@ -945,7 +941,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, ObjectGuid guid, bool accept) LfgProposalPlayer& player = itProposalPlayer->second; player.accept = LfgAnswer(accept); - TC_LOG_DEBUG("lfg.proposal.update", "Player %u, Proposal %u, Selection: %u", guid.GetCounter(), proposalId, accept); + TC_LOG_DEBUG("lfg.proposal.update", "%s, Proposal %u, Selection: %u", guid.ToString().c_str(), proposalId, accept); if (!accept) { RemoveProposal(itProposal, LFG_UPDATETYPE_PROPOSAL_DECLINED); @@ -1073,12 +1069,12 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate if (it->second.accept == LFG_ANSWER_DENY) { updateData.updateType = type; - TC_LOG_DEBUG("lfg.proposal.remove", "%u didn't accept. Removing from queue and compatible cache", guid.GetCounter()); + TC_LOG_DEBUG("lfg.proposal.remove", "%s didn't accept. Removing from queue and compatible cache", guid.ToString().c_str()); } else { updateData.updateType = LFG_UPDATETYPE_REMOVED_FROM_QUEUE; - TC_LOG_DEBUG("lfg.proposal.remove", "%u in same group that someone that didn't accept. Removing from queue and compatible cache", guid.GetCounter()); + TC_LOG_DEBUG("lfg.proposal.remove", "%s in same group that someone that didn't accept. Removing from queue and compatible cache", guid.ToString().c_str()); } RestoreState(guid, "Proposal Fail (didn't accepted or in group with someone that didn't accept"); @@ -1092,7 +1088,7 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate } else { - TC_LOG_DEBUG("lfg.proposal.remove", "Readding %u to queue.", guid.GetCounter()); + TC_LOG_DEBUG("lfg.proposal.remove", "Readding %s to queue.", guid.ToString().c_str()); SetState(guid, LFG_STATE_QUEUED); if (gguid != guid) { @@ -1325,13 +1321,13 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId) uint32 gDungeonId = GetDungeon(gguid); if (gDungeonId != dungeonId) { - TC_LOG_DEBUG("lfg.dungeon.finish", "Group %u finished dungeon %u but queued for %u", gguid.GetCounter(), dungeonId, gDungeonId); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group %s finished dungeon %u but queued for %u", gguid.ToString().c_str(), dungeonId, gDungeonId); return; } if (GetState(gguid) == LFG_STATE_FINISHED_DUNGEON) // Shouldn't happen. Do not reward multiple times { - TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %u already rewarded", gguid.GetCounter()); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %s already rewarded", gguid.ToString().c_str()); return; } @@ -1343,7 +1339,7 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId) ObjectGuid guid = (*it); if (GetState(guid) == LFG_STATE_FINISHED_DUNGEON) { - TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u already rewarded", gguid.GetCounter(), guid.GetCounter()); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %s, Player: %s already rewarded", gguid.ToString().c_str(), guid.ToString().c_str()); continue; } @@ -1359,14 +1355,14 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId) if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !dungeon->seasonal)) { - TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u dungeon %u is not random or seasonal", gguid.GetCounter(), guid.GetCounter(), rDungeonId); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %s, Player: %s dungeon %u is not random or seasonal", gguid.ToString().c_str(), guid.ToString().c_str(), rDungeonId); continue; } Player* player = ObjectAccessor::FindPlayer(guid); - if (!player || !player->IsInWorld()) + if (!player) { - TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u not found in world", gguid.GetCounter(), guid.GetCounter()); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %s, Player: %s not found in world", gguid.ToString().c_str(), guid.ToString().c_str()); continue; } @@ -1375,7 +1371,7 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId) if (player->GetMapId() != mapId) { - TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u is in map %u and should be in %u to get reward", gguid.GetCounter(), guid.GetCounter(), player->GetMapId(), mapId); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %s, Player: %s is in map %u and should be in %u to get reward", gguid.ToString().c_str(), guid.ToString().c_str(), player->GetMapId(), mapId); continue; } @@ -1406,7 +1402,7 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId) } // Give rewards - TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u done dungeon %u, %s previously done.", gguid.GetCounter(), guid.GetCounter(), GetDungeon(gguid), done? " " : " not"); + TC_LOG_DEBUG("lfg.dungeon.finish", "Group: %s, Player: %s done dungeon %u, %s previously done.", gguid.ToString().c_str(), guid.ToString().c_str(), GetDungeon(gguid), done ? " " : " not"); LfgPlayerRewardData data = LfgPlayerRewardData(dungeon->Entry(), GetDungeon(gguid, false), done, quest); player->GetSession()->SendLfgPlayerReward(data); } @@ -1472,12 +1468,12 @@ LfgState LFGMgr::GetState(ObjectGuid guid) if (guid.IsGroup()) { state = GroupsStore[guid].GetState(); - TC_LOG_TRACE("lfg.data.group.state.get", "Group: %u, State: %u", guid.GetCounter(), state); + TC_LOG_TRACE("lfg.data.group.state.get", "Group: %s, State: %u", guid.ToString().c_str(), state); } else { state = PlayersStore[guid].GetState(); - TC_LOG_TRACE("lfg.data.player.state.get", "Player: %u, State: %u", guid.GetCounter(), state); + TC_LOG_TRACE("lfg.data.player.state.get", "Player: %s, State: %u", guid.ToString().c_str(), state); } return state; @@ -1489,12 +1485,12 @@ LfgState LFGMgr::GetOldState(ObjectGuid guid) if (guid.IsGroup()) { state = GroupsStore[guid].GetOldState(); - TC_LOG_TRACE("lfg.data.group.oldstate.get", "Group: %u, Old state: %u", guid.GetCounter(), state); + TC_LOG_TRACE("lfg.data.group.oldstate.get", "Group: %s, Old state: %u", guid.ToString().c_str(), state); } else { state = PlayersStore[guid].GetOldState(); - TC_LOG_TRACE("lfg.data.player.oldstate.get", "Player: %u, Old state: %u", guid.GetCounter(), state); + TC_LOG_TRACE("lfg.data.player.oldstate.get", "Player: %s, Old state: %u", guid.ToString().c_str(), state); } return state; @@ -1503,7 +1499,7 @@ LfgState LFGMgr::GetOldState(ObjectGuid guid) uint32 LFGMgr::GetDungeon(ObjectGuid guid, bool asId /*= true */) { uint32 dungeon = GroupsStore[guid].GetDungeon(asId); - TC_LOG_TRACE("lfg.data.group.dungeon.get", "Group: %u, asId: %u, Dungeon: %u", guid.GetCounter(), asId, dungeon); + TC_LOG_TRACE("lfg.data.group.dungeon.get", "Group: %s, asId: %u, Dungeon: %u", guid.ToString().c_str(), asId, dungeon); return dungeon; } @@ -1515,7 +1511,7 @@ uint32 LFGMgr::GetDungeonMapId(ObjectGuid guid) if (LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId)) mapId = dungeon->map; - TC_LOG_TRACE("lfg.data.group.dungeon.map", "Group: %u, MapId: %u (DungeonId: %u)", guid.GetCounter(), mapId, dungeonId); + TC_LOG_TRACE("lfg.data.group.dungeon.map", "Group: %s, MapId: %u (DungeonId: %u)", guid.ToString().c_str(), mapId, dungeonId); return mapId; } @@ -1523,30 +1519,30 @@ uint32 LFGMgr::GetDungeonMapId(ObjectGuid guid) uint8 LFGMgr::GetRoles(ObjectGuid guid) { uint8 roles = PlayersStore[guid].GetRoles(); - TC_LOG_TRACE("lfg.data.player.role.get", "Player: %u, Role: %u", guid.GetCounter(), roles); + TC_LOG_TRACE("lfg.data.player.role.get", "Player: %s, Role: %u", guid.ToString().c_str(), roles); return roles; } const std::string& LFGMgr::GetComment(ObjectGuid guid) { - TC_LOG_TRACE("lfg.data.player.comment.get", "Player: %u, Comment: %s", guid.GetCounter(), PlayersStore[guid].GetComment().c_str()); + TC_LOG_TRACE("lfg.data.player.comment.get", "Player: %s, Comment: %s", guid.ToString().c_str(), PlayersStore[guid].GetComment().c_str()); return PlayersStore[guid].GetComment(); } LfgDungeonSet const& LFGMgr::GetSelectedDungeons(ObjectGuid guid) { - TC_LOG_TRACE("lfg.data.player.dungeons.selected.get", "Player: %u, Selected Dungeons: %s", guid.GetCounter(), ConcatenateDungeons(PlayersStore[guid].GetSelectedDungeons()).c_str()); + TC_LOG_TRACE("lfg.data.player.dungeons.selected.get", "Player: %s, Selected Dungeons: %s", guid.ToString().c_str(), ConcatenateDungeons(PlayersStore[guid].GetSelectedDungeons()).c_str()); return PlayersStore[guid].GetSelectedDungeons(); } LfgLockMap const LFGMgr::GetLockedDungeons(ObjectGuid guid) { - TC_LOG_TRACE("lfg.data.player.dungeons.locked.get", "Player: %u, LockedDungeons.", guid.GetCounter()); + TC_LOG_TRACE("lfg.data.player.dungeons.locked.get", "Player: %s, LockedDungeons.", guid.ToString().c_str()); LfgLockMap lock; Player* player = ObjectAccessor::FindPlayer(guid); if (!player) { - TC_LOG_WARN("lfg.data.player.dungeons.locked.get", "Player: %u not ingame while retrieving his LockedDungeons.", guid.GetCounter()); + TC_LOG_WARN("lfg.data.player.dungeons.locked.get", "Player: %s not ingame while retrieving his LockedDungeons.", guid.ToString().c_str()); return lock; } @@ -1612,7 +1608,7 @@ LfgLockMap const LFGMgr::GetLockedDungeons(ObjectGuid guid) uint8 LFGMgr::GetKicksLeft(ObjectGuid guid) { uint8 kicks = GroupsStore[guid].GetKicksLeft(); - TC_LOG_TRACE("lfg.data.group.kickleft.get", "Group: %u, Kicks left: %u", guid.GetCounter(), kicks); + TC_LOG_TRACE("lfg.data.group.kickleft.get", "Group: %s, Kicks left: %u", guid.ToString().c_str(), kicks); return kicks; } @@ -1621,8 +1617,8 @@ void LFGMgr::RestoreState(ObjectGuid guid, char const* debugMsg) if (guid.IsGroup()) { LfgGroupData& data = GroupsStore[guid]; - TC_LOG_TRACE("lfg.data.group.state.restore", "Group: %u (%s), State: %s, Old state: %s", - guid.GetCounter(), debugMsg, GetStateString(data.GetState()).c_str(), + TC_LOG_TRACE("lfg.data.group.state.restore", "Group: %s (%s), State: %s, Old state: %s", + guid.ToString().c_str(), debugMsg, GetStateString(data.GetState()).c_str(), GetStateString(data.GetOldState()).c_str()); data.RestoreState(); @@ -1630,8 +1626,8 @@ void LFGMgr::RestoreState(ObjectGuid guid, char const* debugMsg) else { LfgPlayerData& data = PlayersStore[guid]; - TC_LOG_TRACE("lfg.data.player.state.restore", "Player: %u (%s), State: %s, Old state: %s", - guid.GetCounter(), debugMsg, GetStateString(data.GetState()).c_str(), + TC_LOG_TRACE("lfg.data.player.state.restore", "Player: %s (%s), State: %s, Old state: %s", + guid.ToString().c_str(), debugMsg, GetStateString(data.GetState()).c_str(), GetStateString(data.GetOldState()).c_str()); data.RestoreState(); @@ -1643,8 +1639,8 @@ void LFGMgr::SetState(ObjectGuid guid, LfgState state) if (guid.IsGroup()) { LfgGroupData& data = GroupsStore[guid]; - TC_LOG_TRACE("lfg.data.group.state.set", "Group: %u, New state: %s, Previous: %s, Old state: %s", - guid.GetCounter(), GetStateString(state).c_str(), GetStateString(data.GetState()).c_str(), + TC_LOG_TRACE("lfg.data.group.state.set", "Group: %s, New state: %s, Previous: %s, Old state: %s", + guid.ToString().c_str(), GetStateString(state).c_str(), GetStateString(data.GetState()).c_str(), GetStateString(data.GetOldState()).c_str()); data.SetState(state); @@ -1652,8 +1648,8 @@ void LFGMgr::SetState(ObjectGuid guid, LfgState state) else { LfgPlayerData& data = PlayersStore[guid]; - TC_LOG_TRACE("lfg.data.player.state.set", "Player: %u, New state: %s, Previous: %s, OldState: %s", - guid.GetCounter(), GetStateString(state).c_str(), GetStateString(data.GetState()).c_str(), + TC_LOG_TRACE("lfg.data.player.state.set", "Player: %s, New state: %s, Previous: %s, OldState: %s", + guid.ToString().c_str(), GetStateString(state).c_str(), GetStateString(data.GetState()).c_str(), GetStateString(data.GetOldState()).c_str()); data.SetState(state); @@ -1662,37 +1658,37 @@ void LFGMgr::SetState(ObjectGuid guid, LfgState state) void LFGMgr::SetDungeon(ObjectGuid guid, uint32 dungeon) { - TC_LOG_TRACE("lfg.data.group.dungeon.set", "Group: %u, Dungeon: %u", guid.GetCounter(), dungeon); + TC_LOG_TRACE("lfg.data.group.dungeon.set", "Group: %s, Dungeon: %u", guid.ToString().c_str(), dungeon); GroupsStore[guid].SetDungeon(dungeon); } void LFGMgr::SetRoles(ObjectGuid guid, uint8 roles) { - TC_LOG_TRACE("lfg.data.player.role.set", "Player: %u, Roles: %u", guid.GetCounter(), roles); + TC_LOG_TRACE("lfg.data.player.role.set", "Player: %s, Roles: %u", guid.ToString().c_str(), roles); PlayersStore[guid].SetRoles(roles); } void LFGMgr::SetComment(ObjectGuid guid, std::string const& comment) { - TC_LOG_TRACE("lfg.data.player.comment.set", "Player: %u, Comment: %s", guid.GetCounter(), comment.c_str()); + TC_LOG_TRACE("lfg.data.player.comment.set", "Player: %s, Comment: %s", guid.ToString().c_str(), comment.c_str()); PlayersStore[guid].SetComment(comment); } void LFGMgr::SetSelectedDungeons(ObjectGuid guid, LfgDungeonSet const& dungeons) { - TC_LOG_TRACE("lfg.data.player.dungeon.selected.set", "Player: %u, Dungeons: %s", guid.GetCounter(), ConcatenateDungeons(dungeons).c_str()); + TC_LOG_TRACE("lfg.data.player.dungeon.selected.set", "Player: %s, Dungeons: %s", guid.ToString().c_str(), ConcatenateDungeons(dungeons).c_str()); PlayersStore[guid].SetSelectedDungeons(dungeons); } void LFGMgr::DecreaseKicksLeft(ObjectGuid guid) { GroupsStore[guid].DecreaseKicksLeft(); - TC_LOG_TRACE("lfg.data.group.kicksleft.decrease", "Group: %u, Kicks: %u", guid.GetCounter(), GroupsStore[guid].GetKicksLeft()); + TC_LOG_TRACE("lfg.data.group.kicksleft.decrease", "Group: %s, Kicks: %u", guid.ToString().c_str(), GroupsStore[guid].GetKicksLeft()); } void LFGMgr::RemovePlayerData(ObjectGuid guid) { - TC_LOG_TRACE("lfg.data.player.remove", "Player: %u", guid.GetCounter()); + TC_LOG_TRACE("lfg.data.player.remove", "Player: %s", guid.ToString().c_str()); LfgPlayerDataContainer::iterator it = PlayersStore.find(guid); if (it != PlayersStore.end()) PlayersStore.erase(it); @@ -1700,7 +1696,7 @@ void LFGMgr::RemovePlayerData(ObjectGuid guid) void LFGMgr::RemoveGroupData(ObjectGuid guid) { - TC_LOG_TRACE("lfg.data.group.remove", "Group: %u", guid.GetCounter()); + TC_LOG_TRACE("lfg.data.group.remove", "Group: %s", guid.ToString().c_str()); LfgGroupDataContainer::iterator it = GroupsStore.find(guid); if (it == GroupsStore.end()) return; @@ -1723,7 +1719,7 @@ void LFGMgr::RemoveGroupData(ObjectGuid guid) uint8 LFGMgr::GetTeam(ObjectGuid guid) { uint8 team = PlayersStore[guid].GetTeam(); - TC_LOG_TRACE("lfg.data.player.team.get", "Player: %u, Team: %u", guid.GetCounter(), team); + TC_LOG_TRACE("lfg.data.player.team.get", "Player: %s, Team: %u", guid.ToString().c_str(), team); return team; } @@ -1777,50 +1773,50 @@ ObjectGuid LFGMgr::GetLeader(ObjectGuid guid) bool LFGMgr::HasIgnore(ObjectGuid guid1, ObjectGuid guid2) { - Player* plr1 = ObjectAccessor::FindPlayer(guid1); - Player* plr2 = ObjectAccessor::FindPlayer(guid2); + Player* plr1 = ObjectAccessor::FindConnectedPlayer(guid1); + Player* plr2 = ObjectAccessor::FindConnectedPlayer(guid2); return plr1 && plr2 && (plr1->GetSocial()->HasIgnore(guid2.GetCounter()) || plr2->GetSocial()->HasIgnore(guid1.GetCounter())); } void LFGMgr::SendLfgRoleChosen(ObjectGuid guid, ObjectGuid pguid, uint8 roles) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgRoleChosen(pguid, roles); } void LFGMgr::SendLfgRoleCheckUpdate(ObjectGuid guid, LfgRoleCheck const& roleCheck) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgRoleCheckUpdate(roleCheck); } void LFGMgr::SendLfgUpdateStatus(ObjectGuid guid, LfgUpdateData const& data, bool party) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgUpdateStatus(data, party); } void LFGMgr::SendLfgJoinResult(ObjectGuid guid, LfgJoinResultData const& data) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgJoinResult(data); } void LFGMgr::SendLfgBootProposalUpdate(ObjectGuid guid, LfgPlayerBoot const& boot) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgBootProposalUpdate(boot); } void LFGMgr::SendLfgUpdateProposal(ObjectGuid guid, LfgProposal const& proposal) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgUpdateProposal(proposal); } void LFGMgr::SendLfgQueueStatus(ObjectGuid guid, LfgQueueStatusData const& data) { - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) player->GetSession()->SendLfgQueueStatus(data); } diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 343705a58ab..9f990131a71 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -421,7 +421,7 @@ class LFGMgr /// Gets queue join time time_t GetQueueJoinTime(ObjectGuid guid); /// Checks if given roles match, modifies given roles map with new roles - static bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); + static bool CheckGroupRoles(LfgRolesMap &groles); /// Checks if given players are ignoring each other static bool HasIgnore(ObjectGuid guid1, ObjectGuid guid2); /// Sends queue status to player diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index bac1949d894..f9c059feea9 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -60,8 +60,8 @@ void LFGPlayerScript::OnLogin(Player* player, bool /*loginFirst*/) ObjectGuid gguid2 = group->GetGUID(); if (gguid != gguid2) { - TC_LOG_ERROR("lfg", "%s on group %u but LFG has group %u saved... Fixing.", - player->GetSession()->GetPlayerInfo().c_str(), gguid2.GetCounter(), gguid.GetCounter()); + TC_LOG_ERROR("lfg", "%s on group %s but LFG has group %s saved... Fixing.", + player->GetSession()->GetPlayerInfo().c_str(), gguid2.ToString().c_str(), gguid.ToString().c_str()); sLFGMgr->SetupGroupMember(guid, group->GetGUID()); } } @@ -184,7 +184,7 @@ void LFGGroupScript::OnRemoveMember(Group* group, ObjectGuid guid, RemoveMethod } if (isLFG && state != LFG_STATE_FINISHED_DUNGEON) // Need more players to finish the dungeon - if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid))) + if (Player* leader = ObjectAccessor::FindConnectedPlayer(sLFGMgr->GetLeader(gguid))) leader->GetSession()->SendLfgOfferContinue(sLFGMgr->GetDungeon(gguid, false)); } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 7a0ee24aeca..8f75cd34f28 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -875,7 +875,7 @@ Player* Creature::GetLootRecipient() const { if (!m_lootRecipient) return NULL; - return ObjectAccessor::FindPlayer(m_lootRecipient); + return ObjectAccessor::FindConnectedPlayer(m_lootRecipient); } Group* Creature::GetLootRecipientGroup() const @@ -1887,6 +1887,9 @@ void Creature::CallForHelp(float radius) bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /*= true*/) const { + if (IsInEvadeMode()) + return false; + // is it true? if (!HasReactState(REACT_AGGRESSIVE)) return false; @@ -2416,16 +2419,6 @@ std::string const & Creature::GetNameForLocaleIdx(LocaleConstant loc_idx) const return GetName(); } -//Do not if this works or not, moving creature to another map is very dangerous -void Creature::FarTeleportTo(Map* map, float X, float Y, float Z, float O) -{ - CleanupBeforeRemoveFromMap(false); - GetMap()->RemoveFromMap(this, false); - Relocate(X, Y, Z, O); - SetMap(map); - GetMap()->AddToMap(this); -} - uint32 Creature::GetPetAutoSpellOnPos(uint8 pos) const { if (pos >= MAX_SPELL_CHARM || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index b7c86aebfdf..c147c3e3f27 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -669,8 +669,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject float m_SightDistance, m_CombatDistance; - void FarTeleportTo(Map* map, float X, float Y, float Z, float O); - bool m_isTempWorldObject; //true when possessed // Handling caster facing during spellcast diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 334cd5ce905..46c9c80851b 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2185,7 +2185,7 @@ Player* GameObject::GetLootRecipient() const { if (!m_lootRecipient) return NULL; - return ObjectAccessor::FindPlayer(m_lootRecipient); + return ObjectAccessor::FindConnectedPlayer(m_lootRecipient); } Group* GameObject::GetLootRecipientGroup() const diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0b7f358a1d3..14ca3a645d7 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -151,7 +151,7 @@ uint32 const MasterySpells[MAX_CLASSES] = 87491, // Druid }; -uint64 const MAX_MONEY_AMOUNT = static_cast<uint64>(std::numeric_limits<int64>::max()); +uint64 const MAX_MONEY_AMOUNT = 9999999999ULL; // == PlayerTaxi ================================================ @@ -4834,11 +4834,8 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe { if (Player* pFriend = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, 0, (*resultFriends)[0].GetUInt32()))) { - if (pFriend->IsInWorld()) - { - pFriend->GetSocial()->RemoveFromSocialList(guid, false); - sSocialMgr->SendFriendStatus(pFriend, FRIEND_REMOVED, guid, false); - } + pFriend->GetSocial()->RemoveFromSocialList(guid, false); + sSocialMgr->SendFriendStatus(pFriend, FRIEND_REMOVED, guid, false); } } while (resultFriends->NextRow()); } @@ -21403,7 +21400,7 @@ void Player::RemovePetitionsAndSigns(ObjectGuid guid, uint32 type) ObjectGuid petitionguid = ObjectGuid(HIGHGUID_ITEM, fields[1].GetUInt32()); // send update if charter owner in game - Player* owner = ObjectAccessor::FindPlayer(ownerguid); + Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid); if (owner) owner->GetSession()->SendPetitionQueryOpcode(petitionguid); } while (result->NextRow()); diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp index af076b8a5fb..c4b0165d4bc 100644 --- a/src/server/game/Entities/Player/SocialMgr.cpp +++ b/src/server/game/Entities/Player/SocialMgr.cpp @@ -295,7 +295,7 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet) if (itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND)) { Player* target = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, 0, itr->first)); - if (!target || !target->IsInWorld()) + if (!target) continue; WorldSession* session = target->GetSession(); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 983e2e7c4b3..f237c1aa71a 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -618,19 +618,6 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl switch (obj->GetTypeId()) { - case TYPEID_UNIT: - if (!obj->ToUnit()->GetOwnerGUID().IsPlayer()) // pets should be teleported with player - obj->ToCreature()->FarTeleportTo(newMap, destX, destY, destZ, destO); - break; - case TYPEID_GAMEOBJECT: - { - GameObject* go = obj->ToGameObject(); - go->GetMap()->RemoveFromMap(go, false); - go->Relocate(destX, destY, destZ, destO); - go->SetMap(newMap); - newMap->AddToMap(go); - break; - } case TYPEID_PLAYER: if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT)) RemovePassenger(obj); @@ -639,6 +626,7 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl obj->AddObjectToRemoveList(); break; default: + RemovePassenger(obj); break; } } diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 16dabe4fcad..65b7d19aee3 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -212,6 +212,11 @@ Player* ObjectAccessor::FindPlayer(ObjectGuid guid) return GetObjectInWorld(guid, (Player*)NULL); } +Player* ObjectAccessor::FindConnectedPlayer(ObjectGuid guid) +{ + return HashMapHolder<Player>::Find(guid); +} + Unit* ObjectAccessor::FindUnit(ObjectGuid guid) { return GetObjectInWorld(guid, (Unit*)NULL); @@ -237,6 +242,24 @@ Player* ObjectAccessor::FindPlayerByName(std::string const& name) return NULL; } +Player* ObjectAccessor::FindConnectedPlayerByName(std::string const& name) +{ + boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); + + std::string nameStr = name; + std::transform(nameStr.begin(), nameStr.end(), nameStr.begin(), ::tolower); + HashMapHolder<Player>::MapType const& m = GetPlayers(); + for (HashMapHolder<Player>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter) + { + std::string currentName = iter->second->GetName(); + std::transform(currentName.begin(), currentName.end(), currentName.begin(), ::tolower); + if (nameStr.compare(currentName) == 0) + return iter->second; + } + + return NULL; +} + void ObjectAccessor::SaveAllPlayers() { boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index a23932fb702..0b7f7d11f8d 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -170,6 +170,10 @@ class ObjectAccessor static Unit* FindUnit(ObjectGuid); static Player* FindPlayerByName(std::string const& name); + // this returns Player even if he is not in world, for example teleporting + static Player* FindConnectedPlayer(ObjectGuid); + static Player* FindConnectedPlayerByName(std::string const& name); + // when using this, you must use the hashmapholder's lock static HashMapHolder<Player>::MapType const& GetPlayers() { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index b5cabd70d3c..6ceee339d70 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1782,6 +1782,21 @@ void ObjectMgr::LoadCreatures() data.phaseGroup = 0; } + if (sWorld->getBoolConfig(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA)) + { + uint32 zoneId = 0; + uint32 areaId = 0; + sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); + + PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA); + + stmt->setUInt32(0, zoneId); + stmt->setUInt32(1, areaId); + stmt->setUInt64(2, guid); + + WorldDatabase.Execute(stmt); + } + // Add to grid if not managed by the game event or pool system if (gameEvent == 0 && PoolId == 0) AddCreatureToGrid(guid, &data); @@ -2105,6 +2120,21 @@ void ObjectMgr::LoadGameobjects() data.phaseMask = 1; } + if (sWorld->getBoolConfig(CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA)) + { + uint32 zoneId = 0; + uint32 areaId = 0; + sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); + + PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA); + + stmt->setUInt32(0, zoneId); + stmt->setUInt32(1, areaId); + stmt->setUInt64(2, guid); + + WorldDatabase.Execute(stmt); + } + if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system AddGameobjectToGrid(guid, &data); ++count; @@ -2165,7 +2195,7 @@ ObjectGuid ObjectMgr::GetPlayerGUIDByName(std::string const& name) const bool ObjectMgr::GetPlayerNameByGUID(ObjectGuid guid, std::string& name) const { // prevent DB access for online player - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { name = player->GetName(); return true; @@ -2189,7 +2219,7 @@ bool ObjectMgr::GetPlayerNameByGUID(ObjectGuid guid, std::string& name) const uint32 ObjectMgr::GetPlayerTeamByGUID(ObjectGuid guid) const { // prevent DB access for online player - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { return Player::TeamForRace(player->getRace()); } @@ -2212,7 +2242,7 @@ uint32 ObjectMgr::GetPlayerTeamByGUID(ObjectGuid guid) const uint32 ObjectMgr::GetPlayerAccountIdByGUID(ObjectGuid guid) const { // prevent DB access for online player - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { return player->GetSession()->GetAccountId(); } @@ -5551,7 +5581,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) Player* player = NULL; if (serverUp) - player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, m->receiver)); + player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HIGHGUID_PLAYER, m->receiver)); if (player && player->m_mailsLoaded) { // this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index d5b1022b351..111a5dba77f 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -73,7 +73,7 @@ void VisibleNotifier::SendToSelf() if (it->IsPlayer()) { Player* player = ObjectAccessor::FindPlayer(*it); - if (player && player->IsInWorld() && !player->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + if (player && !player->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) player->UpdateVisibilityOf(&i_player); } } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 53c5139e20f..95d67f3cb8b 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -526,7 +526,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group) if (GetMembersCount() > ((isBGGroup() || isLFGGroup() || isBFGroup()) ? 1u : 2u)) { - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); if (player) { // Battleground group handling @@ -610,7 +610,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R { for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) { - if (ObjectAccessor::FindPlayer(itr->guid)) + if (ObjectAccessor::FindConnectedPlayer(itr->guid)) { ChangeLeader(itr->guid); break; @@ -622,7 +622,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R if (isLFGGroup() && GetMembersCount() == 1) { - Player* leader = ObjectAccessor::FindPlayer(GetLeaderGUID()); + Player* leader = ObjectAccessor::FindConnectedPlayer(GetLeaderGUID()); uint32 mapId = sLFGMgr->GetDungeonMapId(GetGUID()); if (!mapId || !leader || (leader->IsAlive() && leader->GetMapId() != mapId)) { @@ -651,7 +651,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid) if (slot == m_memberSlots.end()) return; - Player* newLeader = ObjectAccessor::FindPlayer(slot->guid); + Player* newLeader = ObjectAccessor::FindConnectedPlayer(slot->guid); // Don't allow switching leader to offline players if (!newLeader) @@ -699,7 +699,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid) CharacterDatabase.CommitTransaction(trans); } - if (Player* oldLeader = ObjectAccessor::FindPlayer(m_leaderGuid)) + if (Player* oldLeader = ObjectAccessor::FindConnectedPlayer(m_leaderGuid)) oldLeader->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); newLeader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); @@ -719,7 +719,7 @@ void Group::Disband(bool hideDestroy /* = false */) Player* player; for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { - player = ObjectAccessor::FindPlayer(citr->guid); + player = ObjectAccessor::FindConnectedPlayer(citr->guid); if (!player) continue; @@ -818,7 +818,7 @@ void Group::SendLootStartRoll(uint32 countDown, uint32 mapid, const Roll &r) for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr) { - Player* p = ObjectAccessor::FindPlayer(itr->first); + Player* p = ObjectAccessor::FindConnectedPlayer(itr->first); if (!p || !p->GetSession()) continue; @@ -865,7 +865,7 @@ void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rol for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { - Player* p = ObjectAccessor::FindPlayer(itr->first); + Player* p = ObjectAccessor::FindConnectedPlayer(itr->first); if (!p || !p->GetSession()) continue; @@ -888,7 +888,7 @@ void Group::SendLootRollWon(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { - Player* p = ObjectAccessor::FindPlayer(itr->first); + Player* p = ObjectAccessor::FindConnectedPlayer(itr->first); if (!p || !p->GetSession()) continue; @@ -908,7 +908,7 @@ void Group::SendLootAllPassed(Roll const& roll) for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { - Player* player = ObjectAccessor::FindPlayer(itr->first); + Player* player = ObjectAccessor::FindConnectedPlayer(itr->first); if (!player || !player->GetSession()) continue; @@ -1000,7 +1000,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) { for (Roll::PlayerVote::const_iterator itr=r->playerVote.begin(); itr != r->playerVote.end(); ++itr) { - Player* p = ObjectAccessor::FindPlayer(itr->first); + Player* p = ObjectAccessor::FindConnectedPlayer(itr->first); if (!p || !p->GetSession()) continue; @@ -1143,7 +1143,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) //Broadcast Pass and Send Rollstart for (Roll::PlayerVote::const_iterator itr = r->playerVote.begin(); itr != r->playerVote.end(); ++itr) { - Player* p = ObjectAccessor::FindPlayer(itr->first); + Player* p = ObjectAccessor::FindConnectedPlayer(itr->first); if (!p || !p->GetSession()) continue; @@ -1206,7 +1206,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) //Broadcast Pass and Send Rollstart for (Roll::PlayerVote::const_iterator itr = r->playerVote.begin(); itr != r->playerVote.end(); ++itr) { - Player* p = ObjectAccessor::FindPlayer(itr->first); + Player* p = ObjectAccessor::FindConnectedPlayer(itr->first); if (!p || !p->GetSession()) continue; @@ -1373,7 +1373,7 @@ void Group::CountTheRoll(Rolls::iterator rollI) } } SendLootRollWon(ObjectGuid::Empty, maxguid, maxresul, ROLL_NEED, *roll); - player = ObjectAccessor::FindPlayer(maxguid); + player = ObjectAccessor::FindConnectedPlayer(maxguid); if (player && player->GetSession()) { @@ -1422,7 +1422,7 @@ void Group::CountTheRoll(Rolls::iterator rollI) } } SendLootRollWon(ObjectGuid::Empty, maxguid, maxresul, rollvote, *roll); - player = ObjectAccessor::FindPlayer(maxguid); + player = ObjectAccessor::FindConnectedPlayer(maxguid); if (player && player->GetSession()) { @@ -1539,7 +1539,7 @@ void Group::SendUpdate() void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot) { - Player* player = ObjectAccessor::FindPlayer(playerGUID); + Player* player = ObjectAccessor::FindConnectedPlayer(playerGUID); if (!player || !player->GetSession() || player->GetGroup() != this) return; @@ -1575,7 +1575,7 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot) if (slot->guid == citr->guid) continue; - Player* member = ObjectAccessor::FindPlayer(citr->guid); + Player* member = ObjectAccessor::FindConnectedPlayer(citr->guid); uint8 onlineState = (member && !member->GetSession()->PlayerLogout()) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; onlineState = onlineState | ((isBGGroup() || isBFGroup()) ? MEMBER_STATUS_PVP : 0); @@ -1667,7 +1667,7 @@ void Group::OfflineReadyCheck() { for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { - Player* player = ObjectAccessor::FindPlayer(citr->guid); + Player* player = ObjectAccessor::FindConnectedPlayer(citr->guid); if (!player || !player->GetSession()) { WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); @@ -1750,7 +1750,7 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group) } // In case the moved player is online, update the player object with the new sub group references - if (Player* player = ObjectAccessor::FindPlayer(guid)) + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) { if (player->GetGroup() == this) player->GetGroupRef().setSubGroup(group); @@ -2175,7 +2175,7 @@ void Group::BroadcastGroupUpdate(void) for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player* pp = ObjectAccessor::FindPlayer(citr->guid); - if (pp && pp->IsInWorld()) + if (pp) { pp->ForceValuesUpdateAtIndex(UNIT_FIELD_BYTES_2); pp->ForceValuesUpdateAtIndex(UNIT_FIELD_FACTIONTEMPLATE); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 3f346a0b8c7..b7f3f2c2f79 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1760,7 +1760,7 @@ void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId) void Guild::HandleInviteMember(WorldSession* session, std::string const& name) { - Player* pInvitee = sObjectAccessor->FindPlayerByName(name); + Player* pInvitee = ObjectAccessor::FindPlayerByName(name); if (!pInvitee) { SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_PLAYER_NOT_FOUND_S, name); @@ -2616,7 +2616,7 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin WorldPacket data; ChatHandler::BuildChatPacket(data, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), NULL, msg); for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) - if (Player* player = itr->second->FindPlayer()) + if (Player* player = itr->second->FindConnectedPlayer()) if (player->GetSession() && _HasRankRight(player, officerOnly ? GR_RIGHT_OFFCHATLISTEN : GR_RIGHT_GCHATLISTEN) && !player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow())) player->GetSession()->SendPacket(&data); @@ -2642,7 +2642,7 @@ void Guild::BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const { for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) if (itr->second->IsRank(rankId)) - if (Player* player = itr->second->FindPlayer()) + if (Player* player = itr->second->FindConnectedPlayer()) player->GetSession()->SendPacket(packet); } @@ -2697,7 +2697,7 @@ void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 max // Members handling bool Guild::AddMember(ObjectGuid guid, uint8 rankId) { - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); // Player cannot be in guild if (player) { @@ -2777,7 +2777,7 @@ bool Guild::AddMember(ObjectGuid guid, uint8 rankId) void Guild::DeleteMember(ObjectGuid guid, bool isDisbanding, bool isKicked, bool canDeleteGuild) { uint32 lowguid = guid.GetCounter(); - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); // Guild master can be deleted when loading guild and guid doesn't exist in characters table // or when he is removed from guild by gm command diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 5448180e0ae..4160edf5250 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -413,6 +413,7 @@ private: void ResetValues(bool weekly = false); inline Player* FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); } + inline Player* FindConnectedPlayer() const { return ObjectAccessor::FindConnectedPlayer(m_guid); } private: uint32 m_guildId; @@ -855,7 +856,7 @@ public: void BroadcastWorker(Do& _do, Player* except = NULL) { for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) - if (Player* player = itr->second->FindPlayer()) + if (Player* player = itr->second->FindConnectedPlayer()) if (player != except) _do(player); } diff --git a/src/server/game/Handlers/ArenaTeamHandler.cpp b/src/server/game/Handlers/ArenaTeamHandler.cpp index d9303d0295a..0f40650691f 100644 --- a/src/server/game/Handlers/ArenaTeamHandler.cpp +++ b/src/server/game/Handlers/ArenaTeamHandler.cpp @@ -147,7 +147,7 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData) if (!normalizePlayerName(invitedName)) return; - player = sObjectAccessor->FindPlayerByName(invitedName); + player = ObjectAccessor::FindPlayerByName(invitedName); } if (!player) diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 954b4483f62..4d3b7dd024e 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -436,7 +436,7 @@ void WorldSession::HandleCalendarEventInvite(WorldPacket& recvData) recvData >> eventId >> inviteId >> name >> isPreInvite >> isGuildEvent; - if (Player* player = sObjectAccessor->FindPlayerByName(name.c_str())) + if (Player* player = ObjectAccessor::FindConnectedPlayerByName(name)) { // Invitee is online inviteeGuid = player->GetGUID(); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index feefaec83ab..bef7aada6e9 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -47,6 +47,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "BattlenetServerManager.h" class LoginQueryHolder : public SQLQueryHolder { @@ -689,13 +690,13 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM); stmt->setUInt32(0, GetAccountId()); - stmt->setUInt32(1, realmID); + stmt->setUInt32(1, realmHandle.Index); trans->Append(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS); stmt->setUInt32(0, createInfo->CharCount); stmt->setUInt32(1, GetAccountId()); - stmt->setUInt32(2, realmID); + stmt->setUInt32(2, realmHandle.Index); trans->Append(stmt); LoginDatabase.CommitTransaction(trans); @@ -784,7 +785,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) { std::string dump; if (PlayerDumpWriter().GetDump(guid.GetCounter(), dump)) - sLog->outCharDump(dump.c_str(), accountId, guid.GetCounter(), name.c_str()); + sLog->outCharDump(dump.c_str(), accountId, guid.GetRawValue(), name.c_str()); } sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(guid); @@ -1139,6 +1140,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin); + sBattlenetServer.SendChangeToonOnlineState(GetBattlenetAccountId(), GetAccountId(), _player->GetGUID(), _player->GetName(), true); + delete holder; } diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index a65c03b25a1..73600ba7c60 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -326,7 +326,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) break; } - Player* receiver = sObjectAccessor->FindPlayerByName(to); + Player* receiver = ObjectAccessor::FindConnectedPlayerByName(to); if (!receiver || (lang != LANG_ADDON && !receiver->isAcceptWhispers() && receiver->GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS) && !receiver->IsInWhisperWhiteList(sender->GetGUID()))) { SendPlayerNotFoundNotice(to); @@ -803,7 +803,7 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData) recvData.ReadByteSeq(guid[7]); recvData.ReadByteSeq(guid[2]); - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); if (!player || !player->GetSession()) return; diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 149d309f995..10a16dc6b48 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -106,7 +106,7 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) return; } - Player* player = sObjectAccessor->FindPlayerByName(memberName); + Player* player = ObjectAccessor::FindPlayerByName(memberName); // no player if (!player) @@ -384,7 +384,7 @@ void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData) else { // Remember leader if online (group pointer will be invalid if group gets disbanded) - Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()); + Player* leader = ObjectAccessor::FindConnectedPlayer(group->GetLeaderGUID()); // uninvite, group can be deleted GetPlayer()->UninviteFromGroup(); @@ -500,7 +500,7 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData) ObjectGuid guid; recvData >> guid; - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); Group* group = GetPlayer()->GetGroup(); if (!group || !player) @@ -755,7 +755,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData) if (guid.IsPlayer()) { - Player* target = ObjectAccessor::FindPlayer(guid); + Player* target = ObjectAccessor::FindConnectedPlayer(guid); if (!target || target->IsHostileTo(GetPlayer())) return; @@ -831,7 +831,7 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData) if (!group->HasFreeSlotSubGroup(groupNr)) return; - Player* movedPlayer = sObjectAccessor->FindPlayerByName(name); + Player* movedPlayer = ObjectAccessor::FindConnectedPlayerByName(name); ObjectGuid guid; if (movedPlayer) @@ -1200,7 +1200,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) ObjectGuid Guid; recvData >> Guid; - Player* player = HashMapHolder<Player>::Find(Guid); + Player* player = ObjectAccessor::FindConnectedPlayer(Guid); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index ea8f86e2adf..654a92f5c4e 100644 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -230,8 +230,8 @@ void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recvData) return; } ObjectGuid gguid = group->GetGUID(); - TC_LOG_DEBUG("lfg", "CMSG_LFG_SET_ROLES: Group %u, Player %s, Roles: %u", - gguid.GetCounter(), GetPlayerInfo().c_str(), roles); + TC_LOG_DEBUG("lfg", "CMSG_LFG_SET_ROLES: Group %s, Player %s, Roles: %u", + gguid.ToString().c_str(), GetPlayerInfo().c_str(), roles); sLFGMgr->UpdateRoleCheck(gguid, guid, roles); } @@ -497,8 +497,8 @@ void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, boo void WorldSession::SendLfgRoleChosen(ObjectGuid guid, uint8 roles) { - TC_LOG_DEBUG("lfg", "SMSG_LFG_ROLE_CHOSEN %s guid: %u roles: %u", - GetPlayerInfo().c_str(), guid.GetCounter(), roles); + TC_LOG_DEBUG("lfg", "SMSG_LFG_ROLE_CHOSEN %s guid: %s roles: %u", + GetPlayerInfo().c_str(), guid.ToString().c_str(), roles); WorldPacket data(SMSG_LFG_ROLE_CHOSEN, 8 + 1 + 4); data << uint64(guid); // Guid @@ -531,7 +531,7 @@ void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck) // Leader info MUST be sent 1st :S ObjectGuid guid = roleCheck.leader; uint8 roles = roleCheck.roles.find(guid)->second; - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); data << uint64(guid); // Guid data << uint8(roles > 0); // Ready data << uint32(roles); // Roles @@ -544,7 +544,7 @@ void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck) guid = it->first; roles = it->second; - player = ObjectAccessor::FindPlayer(guid); + player = ObjectAccessor::FindConnectedPlayer(guid); data << uint64(guid); // Guid data << uint8(roles > 0); // Ready data << uint32(roles); // Roles @@ -709,10 +709,10 @@ void WorldSession::SendLfgBootProposalUpdate(lfg::LfgPlayerBoot const& boot) } } TC_LOG_DEBUG("lfg", "SMSG_LFG_BOOT_PROPOSAL_UPDATE %s inProgress: %u - " - "didVote: %u - agree: %u - victim: %u votes: %u - agrees: %u - left: %u - " + "didVote: %u - agree: %u - victim: %s votes: %u - agrees: %u - left: %u - " "needed: %u - reason %s", GetPlayerInfo().c_str(), uint8(boot.inProgress), uint8(playerVote != lfg::LFG_ANSWER_PENDING), - uint8(playerVote == lfg::LFG_ANSWER_AGREE), boot.victim.GetCounter(), votesNum, agreeNum, + uint8(playerVote == lfg::LFG_ANSWER_AGREE), boot.victim.ToString().c_str(), votesNum, agreeNum, secsleft, lfg::LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str()); WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length()); data << uint8(boot.inProgress); // Vote in progress diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index adf70223db9..e2f9f36163e 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -194,7 +194,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) return; } - Player* receiver = ObjectAccessor::FindPlayer(receiverGuid); + Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid); uint32 receiverTeam = 0; uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails @@ -554,7 +554,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData) if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail { ObjectGuid sender_guid(HIGHGUID_PLAYER, m->sender); - Player* receiver = ObjectAccessor::FindPlayer(sender_guid); + Player* receiver = ObjectAccessor::FindConnectedPlayer(sender_guid); uint32 sender_accId = 0; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 279b06e2cef..a149d066a05 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -258,7 +258,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData) boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType const& m = sObjectAccessor->GetPlayers(); + HashMapHolder<Player>::MapType const& m = ObjectAccessor::GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { Player* target = itr->second; @@ -415,7 +415,8 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/) // not set flags if player can't free move to prevent lost state at logout cancel if (GetPlayer()->CanFreeMove()) { - GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); + if (GetPlayer()->getStandState() == UNIT_STAND_STATE_STAND) + GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); GetPlayer()->SetRooted(true); GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } @@ -608,7 +609,7 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std team = Player::TeamForRace(fields[1].GetUInt8()); friendAccountId = fields[2].GetUInt32(); - if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID))) + if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmHandle.Index))) { if (friendGuid) { @@ -621,7 +622,7 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std else { Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); - if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer())) + if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer())) friendResult = FRIEND_ADDED_ONLINE; else friendResult = FRIEND_ADDED_OFFLINE; @@ -1374,7 +1375,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recvData) return; } - Player* player = sObjectAccessor->FindPlayerByName(charname); + Player* player = ObjectAccessor::FindConnectedPlayerByName(charname); if (!player) { diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index d3d32745c5e..a8df52344a0 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -263,7 +263,7 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData) if (!result) { - TC_LOG_DEBUG("entities.player.items", "Petition %u is not found for player %u %s", petitionguid.GetCounter(), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str()); + TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", petitionguid.ToString().c_str(), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str()); return; } Field* fields = result->Fetch(); @@ -581,7 +581,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); // update for owner if online - if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid)) + if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) owner->GetSession()->SendPacket(&data); } @@ -605,7 +605,7 @@ void WorldSession::HandlePetitionDeclineOpcode(WorldPacket& recvData) Field* fields = result->Fetch(); ObjectGuid ownerguid(HIGHGUID_PLAYER, 0, fields[0].GetUInt32()); - Player* owner = ObjectAccessor::FindPlayer(ownerguid); + Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid); if (owner) // petition owner online { WorldPacket data(MSG_PETITION_DECLINE, 8); @@ -626,7 +626,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData) recvData >> petitionguid; // petition guid recvData >> plguid; // player guid - player = ObjectAccessor::FindPlayer(plguid); + player = ObjectAccessor::FindConnectedPlayer(plguid); if (!player) return; diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 1418cd8a2d8..84f117a0000 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -33,7 +33,7 @@ void WorldSession::SendNameQueryOpcode(ObjectGuid guid) { - Player* player = ObjectAccessor::FindPlayer(guid); + Player* player = ObjectAccessor::FindConnectedPlayer(guid); CharacterNameData const* nameData = sWorld->GetCharacterNameData(guid); WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10)); diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 9f565c8d58d..f739c0f35dd 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -385,7 +385,7 @@ void InstanceSaveManager::LoadResetTimes() if (oldresettime != newresettime) CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '%u' WHERE mapid = '%u' AND difficulty = '%u'", uint32(newresettime), mapid, difficulty); - SetResetTimeFor(mapid, difficulty, newresettime); + InitializeResetTimeFor(mapid, difficulty, newresettime); } while (result->NextRow()); } @@ -422,7 +422,7 @@ void InstanceSaveManager::LoadResetTimes() CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); } - SetResetTimeFor(mapid, difficulty, t); + InitializeResetTimeFor(mapid, difficulty, t); // schedule the global reset/warning uint8 type; diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index 72d180c2373..b2c86d5152b 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -191,11 +191,20 @@ class InstanceSaveManager return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0; } - void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t) + // Use this on startup when initializing reset times + void InitializeResetTimeFor(uint32 mapid, Difficulty d, time_t t) { m_resetTimeByMapDifficulty[MAKE_PAIR32(mapid, d)] = t; } + // Use this only when updating existing reset times + void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t) + { + ResetTimeByMapDifficultyMap::iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid, d)); + ASSERT(itr != m_resetTimeByMapDifficulty.end()); + itr->second = t; + } + ResetTimeByMapDifficultyMap const& GetResetTimeMap() const { return m_resetTimeByMapDifficulty; diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 4a30b4f4b97..35b62bd24c3 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -272,9 +272,14 @@ void LootStore::ReportUnusedIds(LootIdSet const& lootIdSet) const TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d isn't %s and not referenced from loot, and thus useless.", GetName(), *itr, GetEntryName()); } -void LootStore::ReportNonExistingId(uint32 id) const +void LootStore::ReportNonExistingId(uint32 lootId) const { - TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d (%s) does not exist but is used as loot id in DB.", GetName(), id, GetEntryName()); + TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d does not exist", GetName(), lootId); +} + +void LootStore::ReportNonExistingId(uint32 lootId, const char* ownerType, uint32 ownerId) const +{ + TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d does not exist but it is used by %s %d", GetName(), lootId, ownerType, ownerId); } // @@ -1223,7 +1228,7 @@ void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& /*store*/, Lo if (item->reference > 0) { if (!LootTemplates_Reference.GetLootFor(item->reference)) - LootTemplates_Reference.ReportNonExistingId(item->reference); + LootTemplates_Reference.ReportNonExistingId(item->reference, "Reference", item->itemid); else if (ref_set) ref_set->erase(item->reference); } @@ -1235,7 +1240,7 @@ void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& /*store*/, Lo if (item->reference > 0) { if (!LootTemplates_Reference.GetLootFor(item->reference)) - LootTemplates_Reference.ReportNonExistingId(item->reference); + LootTemplates_Reference.ReportNonExistingId(item->reference, "Reference", item->itemid); else if (ref_set) ref_set->erase(item->reference); } @@ -1436,7 +1441,7 @@ void LootTemplate::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_se if (item->reference > 0) { if (!LootTemplates_Reference.GetLootFor(item->reference)) - LootTemplates_Reference.ReportNonExistingId(item->reference); + LootTemplates_Reference.ReportNonExistingId(item->reference, "Reference", item->itemid); else if (ref_set) ref_set->erase(item->reference); } @@ -1530,7 +1535,7 @@ void LoadLootTemplates_Creature() if (uint32 lootid = itr->second.lootid) { if (lootIdSet.find(lootid) == lootIdSet.end()) - LootTemplates_Creature.ReportNonExistingId(lootid); + LootTemplates_Creature.ReportNonExistingId(lootid, "Creature", itr->second.Entry); else lootIdSetUsed.insert(lootid); } @@ -1622,7 +1627,7 @@ void LoadLootTemplates_Gameobject() if (uint32 lootid = itr->second.GetLootId()) { if (lootIdSet.find(lootid) == lootIdSet.end()) - LootTemplates_Gameobject.ReportNonExistingId(lootid); + LootTemplates_Gameobject.ReportNonExistingId(lootid, "Gameobject", itr->second.entry); else lootIdSetUsed.insert(lootid); } @@ -1709,7 +1714,7 @@ void LoadLootTemplates_Pickpocketing() if (uint32 lootid = itr->second.pickpocketLootId) { if (lootIdSet.find(lootid) == lootIdSet.end()) - LootTemplates_Pickpocketing.ReportNonExistingId(lootid); + LootTemplates_Pickpocketing.ReportNonExistingId(lootid, "Creature", itr->second.Entry); else lootIdSetUsed.insert(lootid); } @@ -1796,7 +1801,7 @@ void LoadLootTemplates_Skinning() if (uint32 lootid = itr->second.SkinLootId) { if (lootIdSet.find(lootid) == lootIdSet.end()) - LootTemplates_Skinning.ReportNonExistingId(lootid); + LootTemplates_Skinning.ReportNonExistingId(lootid, "Creature", itr->second.Entry); else lootIdSetUsed.insert(lootid); } @@ -1840,7 +1845,7 @@ void LoadLootTemplates_Spell() // ignore 61756 (Northrend Inscription Research (FAST QA VERSION) for example if (!(spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT) || (spellInfo->Attributes & SPELL_ATTR0_TRADESPELL)) { - LootTemplates_Spell.ReportNonExistingId(spell_id); + LootTemplates_Spell.ReportNonExistingId(spell_id, "Spell", spellInfo->Id); } } else diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index 1685996fd03..52632393ca1 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -216,7 +216,8 @@ class LootStore uint32 LoadAndCollectLootIds(LootIdSet& ids_set); void CheckLootRefs(LootIdSet* ref_set = NULL) const; // check existence reference and remove it from ref_set void ReportUnusedIds(LootIdSet const& ids_set) const; - void ReportNonExistingId(uint32 id) const; + void ReportNonExistingId(uint32 lootId) const; + void ReportNonExistingId(uint32 lootId, const char* ownerType, uint32 ownerId) const; bool HaveLootFor(uint32 loot_id) const { return m_LootTemplates.find(loot_id) != m_LootTemplates.end(); } bool HaveQuestLootFor(uint32 loot_id) const; diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp index 2459e468c25..820a54b9760 100644 --- a/src/server/game/Mails/Mail.cpp +++ b/src/server/game/Mails/Mail.cpp @@ -131,7 +131,7 @@ void MailDraft::deleteIncludedItems(SQLTransaction& trans, bool inDB /*= false*/ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, SQLTransaction& trans) { ObjectGuid receiverGuid(HIGHGUID_PLAYER, receiver_guid); - Player* receiver = ObjectAccessor::FindPlayer(receiverGuid); + Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid); uint32 rc_account = 0; if (!receiver) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index ab50d16d8f5..f5f9546b7b2 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -20,6 +20,7 @@ #include "Battleground.h" #include "MMapFactory.h" #include "CellImpl.h" +#include "DisableMgr.h" #include "DynamicTree.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -119,7 +120,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { - if (!MMAP::MMapFactory::IsPathfindingEnabled(GetId())) + if (!DisableMgr::IsPathfindingEnabled(GetId())) return; bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy); @@ -1585,7 +1586,7 @@ GridMap::~GridMap() unloadData(); } -bool GridMap::loadData(char* filename) +bool GridMap::loadData(const char* filename) { // Unload old data if exist unloadData(); @@ -2967,7 +2968,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) InstanceGroupBind* groupBind = group->GetBoundInstance(this); if (playerBind && playerBind->save != mapSave) { - TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %d and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().GetCounter(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); + TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); if (groupBind) TC_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); //ASSERT(false); @@ -2981,7 +2982,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) // cannot jump to a different instance without resetting it if (groupBind->save != mapSave) { - TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d but he is in group %d which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), group->GetLeaderGUID().GetCounter(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); + TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); TC_LOG_ERROR("maps", "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); if (groupBind->save) TC_LOG_ERROR("maps", "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index c0b50b078d8..cf10f48f82e 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -200,7 +200,7 @@ class GridMap public: GridMap(); ~GridMap(); - bool loadData(char* filaname); + bool loadData(const char* filename); void unloadData(); uint16 getArea(float x, float y) const; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index dbe8c8b0329..2e859a7a56f 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -99,7 +99,12 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature) if (is_air_ok) i_nextMoveTime.Reset(0); else - i_nextMoveTime.Reset(urand(500, 10000)); + { + if (roll_chance_i(50)) + i_nextMoveTime.Reset(urand(5000, 10000)); + else + i_nextMoveTime.Reset(urand(50, 400)); + } creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 2ef465f6775..523cfb7ea2f 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -23,7 +23,7 @@ #include "MMapFactory.h" #include "MMapManager.h" #include "Log.h" - +#include "DisableMgr.h" #include "DetourCommon.h" #include "DetourNavMeshQuery.h" @@ -39,7 +39,7 @@ PathGenerator::PathGenerator(const Unit* owner) : TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); uint32 mapId = _sourceUnit->GetMapId(); - if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) + if (DisableMgr::IsPathfindingEnabled(mapId)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); _navMesh = mmap->GetNavMesh(mapId); diff --git a/src/server/game/Server/BattlenetServerManager.cpp b/src/server/game/Server/BattlenetServerManager.cpp new file mode 100644 index 00000000000..b267926c6ff --- /dev/null +++ b/src/server/game/Server/BattlenetServerManager.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Config.h" +#include "World.h" +#include "ZmqContext.h" +#include "BattlenetServerManager.h" + +void Battlenet::ServerManager::InitializeConnection() +{ + std::string bnetserverAddress = sConfigMgr->GetStringDefault("BnetServer.Address", "127.0.0.1"); + int32 bnetserverPort = sConfigMgr->GetIntDefault("BnetServer.Port", 1118); + _socket = new ZmqMux("inproc://bnetmgr", "tcp://" + bnetserverAddress + ":" + std::to_string(bnetserverPort)); + _socket->Start(); +} + +void Battlenet::ServerManager::CloseConnection() +{ + _socket->End(); + delete _socket; + _socket = nullptr; +} + +Battlenet::Header Battlenet::ServerManager::CreateHeader(BnetCommands command) +{ + Header header; + header.Ipc.Channel = IPC_CHANNEL_BNET; + header.Ipc.Command = command; + header.Realm = realmHandle; + return header; +} + +void Battlenet::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online) +{ + // Do nothing for Grunt login + if (!battlenetAccountId) + return; + + Header header = CreateHeader(BNET_CHANGE_TOON_ONLINE_STATE); + ToonHandle toon; + toon.AccountId = battlenetAccountId; + toon.GameAccountId = gameAccountId; + toon.Guid = guid; + toon.Name = name; + + zmqpp::message msg; + msg << header; + msg << toon; + msg << online; + + _socket->Send(&msg); +} diff --git a/src/server/game/Server/BattlenetServerManager.h b/src/server/game/Server/BattlenetServerManager.h new file mode 100644 index 00000000000..fe103a1c981 --- /dev/null +++ b/src/server/game/Server/BattlenetServerManager.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef BattlenetMgr_h__ +#define BattlenetMgr_h__ + +#include "ZmqMux.h" +#include "Commands.h" + +namespace zmqpp +{ + class socket; +} + +namespace Battlenet +{ + class ServerManager + { + ServerManager() : _socket(nullptr) { } + + public: + void InitializeConnection(); + void CloseConnection(); + + static ServerManager& Instance() + { + static ServerManager instance; + return instance; + } + + void SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online); + + private: + static Header CreateHeader(BnetCommands command); + ZmqMux* _socket; + }; +} + +#define sBattlenetServer Battlenet::ServerManager::Instance() + +#endif // BattlenetMgr_h__ diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 428e0582867..0fd46f0d20b 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -47,6 +47,7 @@ #include "Transport.h" #include "WardenWin.h" #include "WardenMac.h" +#include "BattlenetServerManager.h" namespace { @@ -56,8 +57,7 @@ std::string const DefaultPlayerName = "<none>"; bool MapSessionFilter::Process(WorldPacket* packet) { - Opcodes opcode = DropHighBytes(packet->GetOpcode()); - OpcodeHandler const* opHandle = opcodeTable[opcode]; + OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()]; //let's check if our opcode can be really processed in Map::Update() if (opHandle->ProcessingPlace == PROCESS_INPLACE) @@ -79,8 +79,7 @@ bool MapSessionFilter::Process(WorldPacket* packet) //OR packet handler is not thread-safe! bool WorldSessionFilter::Process(WorldPacket* packet) { - Opcodes opcode = DropHighBytes(packet->GetOpcode()); - OpcodeHandler const* opHandle = opcodeTable[opcode]; + OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()]; //check if packet handler is supposed to be safe if (opHandle->ProcessingPlace == PROCESS_INPLACE) return true; @@ -584,6 +583,9 @@ void WorldSession::LogoutPlayer(bool save) _player->CleanupsBeforeDelete(); TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Logout Character:[%s] (GUID: %u) Level: %d", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel()); + + sBattlenetServer.SendChangeToonOnlineState(GetBattlenetAccountId(), GetAccountId(), _player->GetGUID(), _player->GetName(), false); + if (Map* _map = _player->FindMap()) _map->RemovePlayerFromMap(_player, true); @@ -1145,11 +1147,11 @@ void WorldSession::LoadPermissions() AccountMgr::GetName(id, name); uint8 secLevel = GetSecurity(); - _RBACData = new rbac::RBACData(id, name, realmID, secLevel); + _RBACData = new rbac::RBACData(id, name, realmHandle.Index, secLevel); _RBACData->LoadFromDB(); TC_LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: %u, Name: %s, realmId: %d, secLevel: %u]", - id, name.c_str(), realmID, secLevel); + id, name.c_str(), realmHandle.Index, secLevel); } rbac::RBACData* WorldSession::GetRBACData() @@ -1164,7 +1166,7 @@ bool WorldSession::HasPermission(uint32 permission) bool hasPermission = _RBACData->HasPermission(permission); TC_LOG_DEBUG("rbac", "WorldSession::HasPermission [AccountId: %u, Name: %s, realmId: %d]", - _RBACData->GetId(), _RBACData->GetName().c_str(), realmID); + _RBACData->GetId(), _RBACData->GetName().c_str(), realmHandle.Index); return hasPermission; } @@ -1172,7 +1174,7 @@ bool WorldSession::HasPermission(uint32 permission) void WorldSession::InvalidateRBACData() { TC_LOG_DEBUG("rbac", "WorldSession::Invalidaterbac::RBACData [AccountId: %u, Name: %s, realmId: %d]", - _RBACData->GetId(), _RBACData->GetName().c_str(), realmID); + _RBACData->GetId(), _RBACData->GetName().c_str(), realmHandle.Index); delete _RBACData; _RBACData = NULL; } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 4ec407f5254..02a185b0b63 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -144,7 +144,6 @@ public: virtual bool Process(WorldPacket* /*packet*/) { return true; } virtual bool ProcessLogout() const { return true; } - static Opcodes DropHighBytes(Opcodes opcode) { return Opcodes(opcode & 0xFFFF); } protected: WorldSession* const m_pSession; diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index f37354f7e65..7933ddfeb4d 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -162,7 +162,7 @@ bool WorldSocket::ReadDataHandler() { ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); - Opcodes opcode = PacketFilter::DropHighBytes(Opcodes(header->cmd)); + Opcodes opcode = Opcodes(header->cmd); std::string opcodeName = GetOpcodeNameForLogging(opcode); @@ -213,6 +213,20 @@ bool WorldSocket::ReadDataHandler() return false; } + // prevent invalid memory access/crash with custom opcodes + if (opcode >= NUM_OPCODE_HANDLERS) + { + CloseSocket(); + return false; + } + + OpcodeHandler const* handler = opcodeTable[opcode]; + if (!handler) + { + TC_LOG_ERROR("network.opcode", "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(packet.GetOpcode()).c_str(), _worldSession->GetPlayerInfo().c_str()); + return true; + } + // Our Idle timer will reset on any non PING opcodes. // Catches people idling on the login screen and any lingering ingame connections. _worldSession->ResetTimeOutTime(); @@ -392,7 +406,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) return; } - if (realmIndex != realmID) + if (realmIndex != realmHandle.Index) { SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm)."); @@ -471,7 +485,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); stmt->setUInt32(0, id); - stmt->setInt32(1, int32(realmID)); + stmt->setInt32(1, int32(realmHandle.Index)); result = LoginDatabase.Query(stmt); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 108f23bcc6a..3d0955f5d97 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4383,7 +4383,10 @@ void Spell::TakeAmmo() if (!pItem || pItem->IsBroken() || pItem->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_WAND) return; - if (pItem->GetTemplate()->InventoryType == INVTYPE_THROWN) + if ((pItem->GetTemplate()->InventoryType == INVTYPE_THROWN || + pItem->GetTemplate()->InventoryType == INVTYPE_RANGED || + pItem->GetTemplate()->InventoryType == INVTYPE_RANGEDRIGHT) + && roll_chance_f(sWorld->getRate(RATE_DURABILITY_LOSS_DAMAGE))) { if (pItem->GetMaxStackCount() == 1) { diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d5ddf62b441..46fac6340a8 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2385,6 +2385,14 @@ void SpellMgr::LoadSpellLinked() TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_linked_spell` does not exist", abs(trigger)); continue; } + + if (effect >= 0) + for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + { + if (spellInfo->Effects[j].CalcValue() == abs(effect)) + TC_LOG_ERROR("sql.sql", "Spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack)", abs(trigger), abs(effect), j); + } + spellInfo = GetSpellInfo(abs(effect)); if (!spellInfo) { @@ -3330,7 +3338,7 @@ void SpellMgr::LoadSpellInfoCorrections() break; case 51798: // Brewfest - Relay Race - Intro - Quest Complete case 47134: // Quest Complete - //! HACK: This spell break quest complete for alliance and on retail not used °_O + //! HACK: This spell break quest complete for alliance and on retail not used °_O spellInfo->Effects[EFFECT_0].Effect = 0; break; // ULDUAR SPELLS diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 3a183ec50bc..d3d06d0ee8a 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1303,6 +1303,9 @@ void World::LoadConfigSettings(bool reload) // AHBot m_int_configs[CONFIG_AHBOT_UPDATE_INTERVAL] = sConfigMgr->GetIntDefault("AuctionHouseBot.Update.Interval", 20); + m_bool_configs[CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Creature.Zone.Area.Data", false); + m_bool_configs[CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Gameoject.Zone.Area.Data", false); + // call ScriptMgr if we're reloading the configuration if (reload) sScriptMgr->OnConfigLoad(reload); @@ -1322,6 +1325,13 @@ void World::SetInitialWorldSettings() ///- Initialize detour memory management dtAllocSetCustom(dtCustomAlloc, dtCustomFree); + ///- Initialize VMapManager function pointers (to untangle game/collision circular deps) + if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())) + { + vmmgr2->GetLiquidFlagsPtr = &GetLiquidFlags; + vmmgr2->IsVMAPDisabledForPtr = &DisableMgr::IsVMAPDisabledFor; + } + ///- Initialize config settings LoadConfigSettings(); @@ -1365,7 +1375,7 @@ void World::SetInitialWorldSettings() uint32 server_type = IsFFAPvPRealm() ? uint32(REALM_TYPE_PVP) : getIntConfig(CONFIG_GAME_TYPE); uint32 realm_zone = getIntConfig(CONFIG_REALM_ZONE); - LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); // One-time query + LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmHandle.Index); // One-time query ///- Remove the bones (they should not exist in DB though) and old corpses after a restart PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CORPSES); @@ -1787,7 +1797,7 @@ void World::SetInitialWorldSettings() m_startTime = m_gameTime; LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')", - realmID, uint32(m_startTime), _FULLVERSION); // One-time query + realmHandle.Index, uint32(m_startTime), _FULLVERSION); // One-time query m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS); @@ -2069,7 +2079,7 @@ void World::Update(uint32 diff) stmt->setUInt32(0, tmpDiff); stmt->setUInt16(1, uint16(maxOnlinePlayers)); - stmt->setUInt32(2, realmID); + stmt->setUInt32(2, realmHandle.Index); stmt->setUInt32(3, uint32(m_startTime)); LoginDatabase.Execute(stmt); @@ -2489,7 +2499,7 @@ bool World::RemoveBanAccount(BanMode mode, std::string const& nameOrIP) /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban BanReturn World::BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author) { - Player* pBanned = sObjectAccessor->FindPlayerByName(name); + Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name); uint32 guid = 0; uint32 duration_secs = TimeStringToSecs(duration); @@ -2530,7 +2540,7 @@ BanReturn World::BanCharacter(std::string const& name, std::string const& durati /// Remove a ban from a character bool World::RemoveBanCharacter(std::string const& name) { - Player* pBanned = sObjectAccessor->FindPlayerByName(name); + Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name); uint32 guid = 0; /// Pick a player to ban if not online @@ -2799,13 +2809,13 @@ void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount) PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM); stmt->setUInt32(0, accountId); - stmt->setUInt32(1, realmID); + stmt->setUInt32(1, realmHandle.Index); LoginDatabase.Execute(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS); stmt->setUInt8(0, charCount); stmt->setUInt32(1, accountId); - stmt->setUInt32(2, realmID); + stmt->setUInt32(2, realmHandle.Index); LoginDatabase.Execute(stmt); } } @@ -2974,7 +2984,7 @@ void World::ResetCurrencyWeekCap() void World::LoadDBAllowedSecurityLevel() { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL); - stmt->setInt32(0, int32(realmID)); + stmt->setInt32(0, int32(realmHandle.Index)); PreparedQueryResult result = LoginDatabase.Query(stmt); if (result) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 3bbc4e48eea..2c74e3929fe 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -24,6 +24,7 @@ #define __WORLD_H #include "Common.h" +#include "Commands.h" #include "ObjectGuid.h" #include "Timer.h" #include "SharedDefines.h" @@ -166,6 +167,8 @@ enum WorldBoolConfigs CONFIG_INSTANCES_RESET_ANNOUNCE, CONFIG_IP_BASED_ACTION_LOGGING, CONFIG_ALLOW_TRACK_BOTH_RESOURCES, + CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA, + CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA, BOOL_CONFIG_VALUE_COUNT }; @@ -877,7 +880,7 @@ class World std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks; }; -extern uint32 realmID; +extern Battlenet::RealmHandle realmHandle; #define sWorld World::instance() #endif diff --git a/src/server/ipc/CMakeLists.txt b/src/server/ipc/CMakeLists.txt new file mode 100644 index 00000000000..93a5d630dfe --- /dev/null +++ b/src/server/ipc/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +file(GLOB_RECURSE sources_ipc *.cpp *.h) + +set(ipc_SRCS + ${sources_ipc} +) + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/zmqpp + ${CMAKE_SOURCE_DIR}/src/server/shared/ + ${ZMQ_INCLUDE_DIR} +) + +add_library(ipc STATIC ${ipc_SRCS}) diff --git a/src/server/ipc/Commands.cpp b/src/server/ipc/Commands.cpp new file mode 100644 index 00000000000..8e494fc34b9 --- /dev/null +++ b/src/server/ipc/Commands.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Commands.h" +#include <zmqpp/message.hpp> + +zmqpp::message& operator>>(zmqpp::message& msg, IPCHeader& header) +{ + msg >> header.Channel; + msg >> header.Command; + return msg; +} + +zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::RealmHandle& realm) +{ + msg >> realm.Region; + msg >> realm.Battlegroup; + msg >> realm.Index; + return msg; +} + +zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::Header& header) +{ + msg >> header.Ipc; + msg >> header.Realm; + return msg; +} + +zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::ToonHandle& toonHandle) +{ + msg >> toonHandle.AccountId; + msg >> toonHandle.GameAccountId; + msg >> toonHandle.Guid; + msg >> toonHandle.Name; + return msg; +} + +zmqpp::message& operator<<(zmqpp::message& msg, IPCHeader& header) +{ + msg << header.Channel; + msg << header.Command; + return msg; +} + +zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::RealmHandle& realm) +{ + msg << realm.Region; + msg << realm.Battlegroup; + msg << realm.Index; + return msg; +} + +zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::Header& header) +{ + msg << header.Ipc; + msg << header.Realm; + return msg; +} + +zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::ToonHandle& toonHandle) +{ + msg << toonHandle.AccountId; + msg << toonHandle.GameAccountId; + msg << toonHandle.Guid; + msg << toonHandle.Name; + return msg; +} diff --git a/src/server/ipc/Commands.h b/src/server/ipc/Commands.h new file mode 100644 index 00000000000..05309a45022 --- /dev/null +++ b/src/server/ipc/Commands.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _COMMANDS_H +#define _COMMANDS_H + +#include "Define.h" +#include <string> + +enum Channels +{ + IPC_CHANNEL_BNET, + + MAX_IPC_CHANNELS, +}; + +enum BnetCommands +{ + BNET_CHANGE_TOON_ONLINE_STATE, + + IPC_BNET_MAX_COMMAND +}; + +struct IPCHeader +{ + uint8 Channel; + uint8 Command; +}; + +namespace Battlenet +{ + struct RealmHandle + { + uint8 Region; + uint8 Battlegroup; + uint32 Index; + }; + + struct Header + { + IPCHeader Ipc; + RealmHandle Realm; + }; + + struct ToonHandle + { + uint32 AccountId; + uint32 GameAccountId; + uint64 Guid; + std::string Name; + }; +} + +namespace zmqpp +{ + class message; +} + +zmqpp::message& operator>>(zmqpp::message& msg, IPCHeader& header); +zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::RealmHandle& realm); +zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::Header& header); +zmqpp::message& operator>>(zmqpp::message& msg, Battlenet::ToonHandle& toonHandle); + +zmqpp::message& operator<<(zmqpp::message& msg, IPCHeader& header); +zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::RealmHandle& realm); +zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::Header& header); +zmqpp::message& operator<<(zmqpp::message& msg, Battlenet::ToonHandle& toonHandle); + +#endif // _COMMANDS_H diff --git a/src/server/ipc/ZMQTask.cpp b/src/server/ipc/ZMQTask.cpp new file mode 100644 index 00000000000..0d25dc2babf --- /dev/null +++ b/src/server/ipc/ZMQTask.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ZMQTask.h" +#include "ZmqContext.h" +#include <zmqpp/message.hpp> + +ZMQTask::ZMQTask() +{ + _poller = new zmqpp::poller(); +} + +ZMQTask::~ZMQTask() +{ + delete _poller; + _poller = NULL; + delete _inproc; + delete _thread; +} + +void ZMQTask::Start() +{ + _inproc = sIpcContext->CreateInprocSubscriber(); + _poller->add(*_inproc); + + HandleOpen(); + _thread = new std::thread(&ZMQTask::Run, this); +} + +void ZMQTask::End() +{ + _thread->join(); + _inproc->close(); + HandleClose(); +} + +bool ZMQTask::ProcessExit() +{ + if (_poller->events(*_inproc) == zmqpp::poller::poll_in) + { + int op1; + do + { + zmqpp::message msg; + if (!_inproc->receive(msg, true)) + return false; //No more messages to read from sock. This shouldn't happen. + + // strip 'internalmq.' from message + std::string cmd = msg.get(0).substr(11); + if (cmd == "kill") + return true; + + _inproc->get(zmqpp::socket_option::events, op1); + } while (op1 & zmqpp::poller::poll_in); + } + + return false; +} + +void ZMQTask::Pipeline(zmqpp::socket* from, zmqpp::socket* to) +{ + /* + Push messages from socket to socket. + */ + if (_poller->events(*from) == zmqpp::poller::poll_in) + { + int32 op1, op2; + do + { + zmqpp::message msg; + if (!from->receive(msg, true)) + return; //No more messages to read from socket. This shouldn't happen. + + to->send(msg); + from->get(zmqpp::socket_option::events, op1); + to->get(zmqpp::socket_option::events, op2); + } while(op1 & zmqpp::poller::poll_in && op2 & zmqpp::poller::poll_out); + } +} diff --git a/src/server/ipc/ZMQTask.h b/src/server/ipc/ZMQTask.h new file mode 100644 index 00000000000..24251893aaa --- /dev/null +++ b/src/server/ipc/ZMQTask.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ZMQTASK_H +#define __ZMQTASK_H + +#include "Define.h" +#include <thread> +#include <zmqpp/poller.hpp> +#include <zmqpp/socket.hpp> + +/* + This class serves as a base for all long running tasks + It is set up to terminate its running task upon receiving "kill" command +*/ +class ZMQTask +{ +public: + ZMQTask(); + virtual ~ZMQTask(); + + void Start(); + void End(); + virtual void Run() = 0; + +protected: + virtual void HandleOpen() { } + virtual void HandleClose() { } + void Pipeline(zmqpp::socket* from, zmqpp::socket* to); + bool ProcessExit(); + + zmqpp::poller* _poller; + + zmqpp::socket* _inproc; + std::thread* _thread; +}; + +#endif // __ZMQTASK_H diff --git a/src/server/ipc/ZmqContext.cpp b/src/server/ipc/ZmqContext.cpp new file mode 100644 index 00000000000..305e6b1d843 --- /dev/null +++ b/src/server/ipc/ZmqContext.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ZmqContext.h" + +ZmqContext::ZmqContext() : _inproc(nullptr) +{ +} + +ZmqContext::~ZmqContext() +{ + delete _inproc; +} + +zmqpp::socket* ZmqContext::CreateNewSocket(zmqpp::socket_type type) +{ + std::unique_lock<std::mutex> lock(_mutex); + return new zmqpp::socket(_context, type); +} + +void ZmqContext::Initialize() +{ + _inproc = new zmqpp::socket(_context, zmqpp::socket_type::pub); + _inproc->bind("inproc://workers"); +} + +zmqpp::socket* ZmqContext::CreateInprocSubscriber() +{ + zmqpp::socket* sub = CreateNewSocket(zmqpp::socket_type::sub); + sub->connect("inproc://workers"); + sub->subscribe("internalmq."); + return sub; +} + +void ZmqContext::Close() +{ + _inproc->send("internalmq.kill"); +} diff --git a/src/server/ipc/ZmqContext.h b/src/server/ipc/ZmqContext.h new file mode 100644 index 00000000000..a6ad12b1b70 --- /dev/null +++ b/src/server/ipc/ZmqContext.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ZMQCONTEX_H +#define __ZMQCONTEX_H + +#include <zmqpp/zmqpp.hpp> +#include <mutex> + +/* + * We need to serialize access to zmq context otherwise stuff blows up. + */ +class ZmqContext +{ +public: + ~ZmqContext(); + + static ZmqContext* Instance() + { + static ZmqContext instance; + return &instance; + } + + zmqpp::socket* CreateNewSocket(zmqpp::socket_type); + void Initialize(); + zmqpp::socket* CreateInprocSubscriber(); + void Close(); + +private: + ZmqContext(); + ZmqContext(ZmqContext const&) = delete; + ZmqContext& operator=(ZmqContext const&) = delete; + + zmqpp::context _context; + std::mutex _mutex; + zmqpp::socket* _inproc; +}; + +#define sIpcContext ZmqContext::Instance() + +#endif diff --git a/src/server/ipc/ZmqListener.cpp b/src/server/ipc/ZmqListener.cpp new file mode 100644 index 00000000000..98333305e58 --- /dev/null +++ b/src/server/ipc/ZmqListener.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ZmqListener.h" +#include "ZmqContext.h" + +ZmqListener::ZmqListener(std::string const& from, std::string const& to) +{ + _from = sIpcContext->CreateNewSocket(zmqpp::socket_type::sub); + _to = sIpcContext->CreateNewSocket(zmqpp::socket_type::push); + _from->connect(from); + _to->bind(to); +} + +ZmqListener::~ZmqListener() +{ + delete _from; + delete _to; +} + +void ZmqListener::HandleOpen() +{ +} + +void ZmqListener::HandleClose() +{ + _from->close(); + _to->close(); +} + +void ZmqListener::Run() +{ + while (!ProcessExit()) + { + _poller->poll(); + + while (_poller->events(*_from) & zmqpp::poller::poll_in && + _poller->events(*_to) & zmqpp::poller::poll_out) + { + zmqpp::message msg; + _from->receive(msg); + _to->send(msg); + } + } +} + +void ZmqListener::Subscribe(std::string const& keyword) +{ + _from->subscribe(keyword); +} + +void ZmqListener::Unsubscribe(std::string const& keyword) +{ + _from->unsubscribe(keyword); +} diff --git a/src/server/authserver/Server/BattlenetSessionManager.cpp b/src/server/ipc/ZmqListener.h index 91ba2b65094..8b79ba67f6d 100644 --- a/src/server/authserver/Server/BattlenetSessionManager.cpp +++ b/src/server/ipc/ZmqListener.h @@ -15,23 +15,37 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "BattlenetSessionManager.h" +#ifndef __ZMQLISTENER_H +#define __ZMQLISTENER_H -bool Battlenet::SessionManager::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) +#include "ZMQTask.h" +#include <zmqpp/zmqpp.hpp> + +class ZmqListener : public ZMQTask { - if (!BaseSocketMgr::StartNetwork(service, bindIp, port)) - return false; +/* + * Read broadcasts from remote PUB socket, and forward them to + * another socket. + * + * from - client SUB socket + * to - listen PUSH socket + * + */ +public: + ZmqListener(std::string const& from, std::string const& to); + ~ZmqListener(); + void Run() override; - _acceptor->AsyncAcceptManaged(&OnSocketAccept); - return true; -} + void Subscribe(std::string const& keyword); + void Unsubscribe(std::string const& keyword); -NetworkThread<Battlenet::Session>* Battlenet::SessionManager::CreateThreads() const -{ - return new NetworkThread<Session>[GetNetworkThreadCount()]; -} +protected: + void HandleOpen() override; + void HandleClose() override; -void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock) -{ - sBattlenetSessionMgr.OnSocketOpen(std::forward<tcp::socket>(sock)); -} +private: + zmqpp::socket* _from; + zmqpp::socket* _to; +}; + +#endif diff --git a/src/server/ipc/ZmqMux.cpp b/src/server/ipc/ZmqMux.cpp new file mode 100644 index 00000000000..4b5a4f48b05 --- /dev/null +++ b/src/server/ipc/ZmqMux.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ZmqMux.h" +#include "ZmqContext.h" + +ZmqMux::ZmqMux(std::string from_uri, std::string to_uri): + _fromAddress(from_uri) +{ + printf("Opening muxer thread from %s to %s\n", from_uri.c_str(), to_uri.c_str()); + _from = sIpcContext->CreateNewSocket(zmqpp::socket_type::pull); + _to = sIpcContext->CreateNewSocket(zmqpp::socket_type::push); + + _from->bind(from_uri); + _to->connect(to_uri); +} + +ZmqMux::~ZmqMux() +{ + delete _from; + delete _to; +} + +void ZmqMux::HandleOpen() +{ + _poller->add(*_from); + _poller->add(*_to, zmqpp::poller::poll_out); +} + +bool ZmqMux::Send(zmqpp::message* m, bool dont_block) +{ + if (_socket.get() == nullptr) + { + _socket.reset(sIpcContext->CreateNewSocket(zmqpp::socket_type::push)); + _socket->connect(_fromAddress); + } + + return _socket->send(*m, dont_block); +} + +void ZmqMux::Run() +{ + for (;;) + { + if (!_poller->poll()) + break; + + if (ProcessExit()) + break; + + Pipeline(_from, _to); + } +} diff --git a/src/server/ipc/ZmqMux.h b/src/server/ipc/ZmqMux.h new file mode 100644 index 00000000000..4b81f11daaf --- /dev/null +++ b/src/server/ipc/ZmqMux.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ZMQMUX_H +#define __ZMQMUX_H + +#include "ZMQTask.h" +#include <string> +#include <boost/thread/tss.hpp> + +/* + * Multiplexes zmq messages from many threads, + * and then passes them to another socket. + */ +class ZmqMux : public ZMQTask +{ +public: + ZmqMux(std::string from, std::string to); + ~ZmqMux(); + bool Send(zmqpp::message*, bool dont_block = false); + void Run() override; + +protected: + void HandleOpen() override; + +private: + boost::thread_specific_ptr<zmqpp::socket> _socket; + zmqpp::socket* _from; + zmqpp::socket* _to; + std::string const _fromAddress; +}; + +#endif diff --git a/src/server/ipc/ZmqWorker.cpp b/src/server/ipc/ZmqWorker.cpp new file mode 100644 index 00000000000..f205ea831b5 --- /dev/null +++ b/src/server/ipc/ZmqWorker.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ZmqWorker.h" +#include "ZmqContext.h" + +ZmqWorker::ZmqWorker(std::string task_uri, std::string res_uri) : + _taskUri(task_uri), _resultsUri(res_uri) +{ +} + +ZmqWorker::~ZmqWorker() +{ + delete _taskQueue; + delete _results; + delete _inproc; +} + +void ZmqWorker::HandleOpen() +{ + _taskQueue = sIpcContext->CreateNewSocket(zmqpp::socket_type::pull); + _results = sIpcContext->CreateNewSocket(zmqpp::socket_type::push); + + _taskQueue->connect(_taskUri); + _results->connect(_resultsUri); + + _poller->add(*_taskQueue); +} + +void ZmqWorker::HandleClose() +{ + _taskQueue->close(); + _results->close(); +} + +void ZmqWorker::Run() +{ + while (!ProcessExit()) + { + _poller->poll(); + if (_poller->events(*_taskQueue) & zmqpp::poller::poll_in) + PerformWork(); + } +} + +void ZmqWorker::PerformWork() +{ + int32 op1; + do + { + zmqpp::message msg; + _taskQueue->receive(msg); + Dispatch(msg); + _taskQueue->get(zmqpp::socket_option::events, op1); + } while (op1 & zmqpp::poller::poll_in); +} diff --git a/src/server/ipc/ZmqWorker.h b/src/server/ipc/ZmqWorker.h new file mode 100644 index 00000000000..b3e221e9129 --- /dev/null +++ b/src/server/ipc/ZmqWorker.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ZMQWORKER_H +#define __ZMQWORKER_H + +#include "ZMQTask.h" +#include <zmqpp/zmqpp.hpp> + +class ZmqWorker : public ZMQTask +{ +public: + ZmqWorker(std::string task_uri, std::string res_uri); + ~ZmqWorker(); + void Run() override; + +protected: + void HandleOpen() override; + void HandleClose() override; + zmqpp::socket* _results; + +private: + void PerformWork(); + virtual void Dispatch(zmqpp::message const&) = 0; + zmqpp::socket* _taskQueue; + std::string _taskUri; + std::string _resultsUri; +}; + +#endif diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index e92c883eeff..eab6a36d02e 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -64,6 +64,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/ipc ${CMAKE_SOURCE_DIR}/src/server/collision ${CMAKE_SOURCE_DIR}/src/server/collision/Management ${CMAKE_SOURCE_DIR}/src/server/collision/Models diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index e11ee0008d2..370d03162d1 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -299,7 +299,7 @@ public: if (!*args) return false; - Player* target = sObjectAccessor->FindPlayerByName(args); + Player* target = ObjectAccessor::FindPlayerByName(args); uint32 targetGuid = 0; std::string name(args); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 8254d08558a..c8961d4fad8 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -776,7 +776,7 @@ public: ObjectGuid characterGuid; uint32 accountId; - Player* player = sObjectAccessor->FindPlayerByName(characterName); + Player* player = ObjectAccessor::FindPlayerByName(characterName); if (player) { characterGuid = player->GetGUID(); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 4b555fcf625..862b683597a 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -559,10 +559,10 @@ public: for (uint8 j = 0; j < bag->GetBagSize(); ++j) if (Item* item2 = bag->GetItemByPos(j)) if (item2->GetState() == state) - handler->PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item2->GetSlot(), item2->GetGUIDLow(), item2->GetOwnerGUID().GetCounter()); + handler->PSendSysMessage("bag: 255 slot: %d %s owner: %s", item2->GetSlot(), item2->GetGUID().ToString().c_str(), item2->GetOwnerGUID().ToString().c_str()); } else if (item->GetState() == state) - handler->PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item->GetSlot(), item->GetGUIDLow(), item->GetOwnerGUID().GetCounter()); + handler->PSendSysMessage("bag: 255 slot: %d %s owner: %s", item->GetSlot(), item->GetGUID().ToString().c_str(), item->GetOwnerGUID().ToString().c_str()); } } } @@ -624,14 +624,14 @@ public: if (item->GetOwnerGUID() != player->GetGUID()) { - handler->PSendSysMessage("The item with slot %d and itemguid %d does have non-matching owner guid (%d) and player guid (%d) !", item->GetSlot(), item->GetGUIDLow(), item->GetOwnerGUID().GetCounter(), player->GetGUIDLow()); + handler->PSendSysMessage("The item with slot %d %s does have non-matching owner guid %s and %s!", item->GetSlot(), item->GetGUID().ToString().c_str(), item->GetOwnerGUID().ToString().c_str(), player->GetGUID().ToString().c_str()); error = true; continue; } if (Bag* container = item->GetContainer()) { - handler->PSendSysMessage("The item with slot %d and guid %d has a container (slot: %d, guid: %d) but shouldn't!", item->GetSlot(), item->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + handler->PSendSysMessage("The item with slot %d %s has a container (slot: %d, %s) but shouldn't!", item->GetSlot(), item->GetGUID().ToString().c_str(), container->GetSlot(), container->GetGUID().ToString().c_str()); error = true; continue; } @@ -684,7 +684,7 @@ public: if (item2->GetOwnerGUID() != player->GetGUID()) { - handler->PSendSysMessage("The item in bag %d at slot %d and with itemguid %d, the owner's guid (%d) and the player's guid (%d) don't match!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), item2->GetOwnerGUID().GetCounter(), player->GetGUIDLow()); + handler->PSendSysMessage("The item in bag %d at slot %d and %s, the owner (%s) and the player (%s) don't match!", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().ToString().c_str(), item2->GetOwnerGUID().ToString().c_str(), player->GetGUID().ToString().c_str()); error = true; continue; } @@ -692,14 +692,14 @@ public: Bag* container = item2->GetContainer(); if (!container) { - handler->PSendSysMessage("The item in bag %d at slot %d with guid %d has no container!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow()); + handler->PSendSysMessage("The item in bag %d at slot %d %s has no container!", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().ToString().c_str()); error = true; continue; } if (container != bag) { - handler->PSendSysMessage("The item in bag %d at slot %d with guid %d has a different container(slot %d guid %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + handler->PSendSysMessage("The item in bag %d at slot %d %s has a different container(slot %d %s)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().ToString().c_str(), container->GetSlot(), container->GetGUID().ToString().c_str()); error = true; continue; } @@ -746,14 +746,14 @@ public: if (item->GetOwnerGUID() != player->GetGUID()) { - handler->PSendSysMessage("queue(%zu): For the item with guid %d, the owner's guid (%d) and the player's guid (%d) don't match!", i, item->GetGUIDLow(), item->GetOwnerGUID().GetCounter(), player->GetGUIDLow()); + handler->PSendSysMessage("queue(%zu): For the item %s, the owner (%s) and the player (%s) don't match!", i, item->GetGUID().ToString().c_str(), item->GetOwnerGUID().ToString().c_str(), player->GetGUID().ToString().c_str()); error = true; continue; } if (item->GetQueuePos() != i) { - handler->PSendSysMessage("queue(%zu): For the item with guid %d, the queuepos doesn't match it's position in the queue!", i, item->GetGUIDLow()); + handler->PSendSysMessage("queue(%zu): For the item %s, the queuepos doesn't match it's position in the queue!", i, item->GetGUID().ToString().c_str()); error = true; continue; } @@ -765,14 +765,14 @@ public: if (test == NULL) { - handler->PSendSysMessage("queue(%zu): The bag(%d) and slot(%d) values for the item with guid %d are incorrect, the player doesn't have any item at that position!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow()); + handler->PSendSysMessage("queue(%zu): The bag(%d) and slot(%d) values for %s are incorrect, the player doesn't have any item at that position!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUID().ToString().c_str()); error = true; continue; } if (test != item) { - handler->PSendSysMessage("queue(%zu): The bag(%d) and slot(%d) values for the item with guid %d are incorrect, an item which guid is %d is there instead!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); + handler->PSendSysMessage("queue(%zu): The bag(%d) and slot(%d) values for the %s are incorrect, %s is there instead!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUID().ToString().c_str(), test->GetGUID().ToString().c_str()); error = true; continue; } diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 27ec4835ce6..24da9e37327 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -121,7 +121,7 @@ public: bool footer = false; boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType const& m = sObjectAccessor->GetPlayers(); + HashMapHolder<Player>::MapType const& m = ObjectAccessor::GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { AccountTypes itrSec = itr->second->GetSession()->GetSecurity(); @@ -163,7 +163,7 @@ public: ///- Get the accounts with GM Level >0 PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_GM_ACCOUNTS); stmt->setUInt8(0, uint8(SEC_MODERATOR)); - stmt->setInt32(1, int32(realmID)); + stmt->setInt32(1, int32(realmHandle.Index)); PreparedQueryResult result = LoginDatabase.Query(stmt); if (result) diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index e39aca6f6a7..a558d977b85 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -343,7 +343,7 @@ public: // Check if iterator is online. If is... Player* p = ObjectAccessor::FindPlayer((*itr).guid); - if (p && p->IsInWorld()) + if (p) { // ... than, it prints information like "is online", where he is, etc... onlineState = "online"; diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index f2067e6c70b..715487eff99 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -211,7 +211,7 @@ public: std::string name = strtok(NULL, " "); if (normalizePlayerName(name)) { - if (Player* player = sObjectAccessor->FindPlayerByName(name)) + if (Player* player = ObjectAccessor::FindPlayerByName(name)) { handler->GetSession()->GetPlayer()->RemoveFromWhisperWhiteList(player->GetGUID()); handler->PSendSysMessage(LANG_COMMAND_WHISPEROFFPLAYER, name.c_str()); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 9277956262f..75dbf975857 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -35,6 +35,7 @@ #include "LFG.h" #include "GroupMgr.h" #include "MMapFactory.h" +#include "DisableMgr.h" class misc_commandscript : public CommandScript { @@ -185,7 +186,7 @@ public: uint32 haveMap = Map::ExistMap(mapId, gridX, gridY) ? 1 : 0; uint32 haveVMap = Map::ExistVMap(mapId, gridX, gridY) ? 1 : 0; - uint32 haveMMap = (MMAP::MMapFactory::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0; + uint32 haveMMap = (DisableMgr::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0; if (haveVMap) { @@ -1541,7 +1542,7 @@ public: // Query the prepared statement for login data stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); - stmt->setInt32(0, int32(realmID)); + stmt->setInt32(0, int32(realmHandle.Index)); stmt->setUInt32(1, accId); PreparedQueryResult result = LoginDatabase.Query(stmt); @@ -2193,7 +2194,7 @@ public: if (args && args[0] != '\0') { - target = sObjectAccessor->FindPlayerByName(args); + target = ObjectAccessor::FindPlayerByName(args); if (!target) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -2281,7 +2282,7 @@ public: // find the player std::string name = arg1; normalizePlayerName(name); - player = sObjectAccessor->FindPlayerByName(name); + player = ObjectAccessor::FindPlayerByName(name); // Check if we have duration set if (arg2 && isNumeric(arg2)) { @@ -2345,7 +2346,7 @@ public: { name = targetName; normalizePlayerName(name); - player = sObjectAccessor->FindPlayerByName(name); + player = ObjectAccessor::FindPlayerByName(name); } else // If no name was entered - use target { @@ -2421,7 +2422,7 @@ public: int32 remaintime = fields[1].GetInt32(); // Save the frozen player to update remaining time in case of future .listfreeze uses // before the frozen state expires - if (Player* frozen = sObjectAccessor->FindPlayerByName(player)) + if (Player* frozen = ObjectAccessor::FindPlayerByName(player)) frozen->SaveToDB(); // Notify the freeze duration if (remaintime == -1) // Permanent duration diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 969027139fc..a6a7fac3cb5 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -25,6 +25,7 @@ #include "ScriptMgr.h" #include "Chat.h" +#include "DisableMgr.h" #include "ObjectMgr.h" #include "Player.h" #include "PointMovementGenerator.h" @@ -209,7 +210,7 @@ public: { uint32 mapId = handler->GetSession()->GetPlayer()->GetMapId(); handler->PSendSysMessage("mmap stats:"); - handler->PSendSysMessage(" global mmap pathfinding is %sabled", MMAP::MMapFactory::IsPathfindingEnabled(mapId) ? "en" : "dis"); + handler->PSendSysMessage(" global mmap pathfinding is %sabled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis"); MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp index 95ef5ab6984..ab960026d69 100644 --- a/src/server/scripts/Commands/cs_rbac.cpp +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -160,7 +160,7 @@ public: if (!rdata)
{
- data->rbac = new rbac::RBACData(accountId, accountName, realmID, AccountMgr::GetSecurity(accountId, realmID));
+ data->rbac = new rbac::RBACData(accountId, accountName, realmHandle.Index, AccountMgr::GetSecurity(accountId, realmHandle.Index));
data->rbac->LoadFromDB();
data->needDelete = true;
}
diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index faf87adc7b6..2823c2c8c5d 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -295,7 +295,7 @@ public: CharacterDatabase.Execute(stmt); boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType const& plist = sObjectAccessor->GetPlayers(); + HashMapHolder<Player>::MapType const& plist = ObjectAccessor::GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) itr->second->SetAtLoginFlag(atLogin); diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 674658f41ff..a06bd95f6b6 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -98,7 +98,7 @@ public: ObjectGuid targetGuid = sObjectMgr->GetPlayerGUIDByName(target); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); // Target must exist and have administrative rights - if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realmID)) + if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realmHandle.Index)) { handler->SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); return true; @@ -122,7 +122,7 @@ public: // Assign ticket SQLTransaction trans = SQLTransaction(NULL); - ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realmID))); + ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realmHandle.Index))); ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); @@ -162,12 +162,9 @@ public: // Inform player, who submitted this ticket, that it is closed if (Player* submitter = ticket->GetPlayer()) { - if (submitter->IsInWorld()) - { - WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); - data << uint32(GMTICKET_RESPONSE_TICKET_DELETED); - submitter->GetSession()->SendPacket(&data); - } + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(GMTICKET_RESPONSE_TICKET_DELETED); + submitter->GetSession()->SendPacket(&data); } return true; } @@ -232,8 +229,7 @@ public: } if (Player* player = ticket->GetPlayer()) - if (player->IsInWorld()) - ticket->SendResponse(player->GetSession()); + ticket->SendResponse(player->GetSession()); SQLTransaction trans = SQLTransaction(NULL); ticket->SetCompleted(); @@ -273,13 +269,10 @@ public: if (Player* player = ticket->GetPlayer()) { - if (player->IsInWorld()) - { - // Force abandon ticket - WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); - data << uint32(GMTICKET_RESPONSE_TICKET_DELETED); - player->GetSession()->SendPacket(&data); - } + // Force abandon ticket + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(GMTICKET_RESPONSE_TICKET_DELETED); + player->GetSession()->SendPacket(&data); } return true; @@ -301,8 +294,7 @@ public: ticket->SetEscalatedStatus(TICKET_IN_ESCALATION_QUEUE); if (Player* player = ticket->GetPlayer()) - if (player->IsInWorld()) - sTicketMgr->SendTicket(player->GetSession(), ticket); + sTicketMgr->SendTicket(player->GetSession(), ticket); sTicketMgr->UpdateLastChange(); return true; @@ -372,13 +364,13 @@ public: // Get security level of player, whom this ticket is assigned to uint32 security = SEC_PLAYER; Player* assignedPlayer = ticket->GetAssignedPlayer(); - if (assignedPlayer && assignedPlayer->IsInWorld()) + if (assignedPlayer) security = assignedPlayer->GetSession()->GetSecurity(); else { ObjectGuid guid = ticket->GetAssignedToGUID(); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid); - security = AccountMgr::GetSecurity(accountId, realmID); + security = AccountMgr::GetSecurity(accountId, realmHandle.Index); } // Check security @@ -435,7 +427,7 @@ public: // Detect target's GUID ObjectGuid guid; - if (Player* player = sObjectAccessor->FindPlayerByName(name)) + if (Player* player = ObjectAccessor::FindPlayerByName(name)) guid = player->GetGUID(); else guid = sObjectMgr->GetPlayerGUIDByName(name); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index c25a061d622..cb3fa49216b 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -204,7 +204,7 @@ class instance_culling_of_stratholme : public InstanceMapScript if (state == DONE) { if (GameObject* go = instance->GetGameObject(_malGanisChestGUID)) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); instance->SummonCreature(NPC_CHROMIE_3, ChromieSummonPos[1]); } break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index d5bd2bcae7e..072dbd81fd8 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -212,7 +212,6 @@ class boss_anubarak_trial : public CreatureScript } void MoveInLineOfSight(Unit* /*who*/) override - { if (!_intro) { diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index 79fb154d6e3..e3ad891fdc7 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -68,15 +68,10 @@ class instance_trial_of_the_crusader : public InstanceMapScript else player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW, 0); - // make sure Anub'arak isnt missing and floor is destroyed after a crash + // make sure Anub'arak isnt missing if (GetBossState(BOSS_LICH_KING) == DONE && TrialCounter && GetBossState(BOSS_ANUBARAK) != DONE) - { - if (Creature* anubArak = ObjectAccessor::GetCreature(*player, GetGuidData(NPC_ANUBARAK))) - anubArak = player->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - - if (GameObject* floor = ObjectAccessor::GetGameObject(*player, GetGuidData(GO_ARGENT_COLISEUM_FLOOR))) - floor->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - } + if (!ObjectAccessor::GetCreature(*player, GetGuidData(NPC_ANUBARAK))) + player->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); } void OpenDoor(ObjectGuid guid) @@ -160,23 +155,15 @@ class instance_trial_of_the_crusader : public InstanceMapScript switch (go->GetEntry()) { case GO_CRUSADERS_CACHE_10: - if (instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_NORMAL) - CrusadersCacheGUID = go->GetGUID(); - break; case GO_CRUSADERS_CACHE_25: - if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL) - CrusadersCacheGUID = go->GetGUID(); - break; case GO_CRUSADERS_CACHE_10_H: - if (instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC) - CrusadersCacheGUID = go->GetGUID(); - break; case GO_CRUSADERS_CACHE_25_H: - if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC) - CrusadersCacheGUID = go->GetGUID(); + CrusadersCacheGUID = go->GetGUID(); break; case GO_ARGENT_COLISEUM_FLOOR: FloorGUID = go->GetGUID(); + if (GetBossState(BOSS_LICH_KING) == DONE) + go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); break; case GO_MAIN_GATE_DOOR: MainGateDoorGUID = go->GetGUID(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index d8ec322c57c..885017c24dd 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -207,11 +207,8 @@ class npc_announcer_toc10 : public CreatureScript creature->CastSpell(creature, SPELL_CORPSE_TELEPORT, false); creature->CastSpell(creature, SPELL_DESTROY_FLOOR_KNOCKUP, false); - Creature* anubArak = ObjectAccessor::GetCreature(*creature, instance->GetGuidData(NPC_ANUBARAK)); - if (!anubArak || !anubArak->IsAlive()) - anubArak = creature->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - - instance->SetBossState(BOSS_ANUBARAK, NOT_STARTED); + if (!ObjectAccessor::GetCreature(*creature, instance->GetGuidData(NPC_ANUBARAK))) + creature->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); if (creature->IsVisible()) creature->SetVisible(false); @@ -319,19 +316,15 @@ class boss_lich_king_toc : public CreatureScript case 5080: { if (GameObject* go = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(GO_ARGENT_COLISEUM_FLOOR))) - { - go->SetDisplayId(DISPLAYID_DESTROYED_FLOOR); - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); - go->SetGoState(GO_STATE_ACTIVE); - } + go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); me->CastSpell(me, SPELL_CORPSE_TELEPORT, false); me->CastSpell(me, SPELL_DESTROY_FLOOR_KNOCKUP, false); _instance->SetBossState(BOSS_LICH_KING, DONE); - Creature* temp = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_ANUBARAK)); - if (!temp || !temp->IsAlive()) - temp = me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + + if (!ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_ANUBARAK))) + me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); _instance->SetData(TYPE_EVENT, 0); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index cf08fb75228..e37148aa508 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -42,9 +42,7 @@ enum SpellIds enum MiscData { - DESPAWN_TIME = 1200000, - - DISPLAYID_DESTROYED_FLOOR = 9060 + DESPAWN_TIME = 1200000 }; const Position ToCSpawnLoc[]= @@ -133,7 +131,7 @@ const Position LichKingLoc[]= const Position AnubarakLoc[]= { - {787.932556f, 133.289780f, 142.612152f, 0}, // 0 - Anub'arak start location + {783.9305f, 132.9722f, 142.6711f, 3.141593f}, // 0 - Anub'arak Spawn Location (sniffed) {695.240051f, 137.834824f, 142.200000f, 0}, // 1 - Anub'arak move point location {694.886353f, 102.484665f, 142.119614f, 0}, // 3 - Nerub Spawn {694.500671f, 185.363968f, 142.117905f, 0}, // 5 - Nerub Spawn @@ -232,13 +230,13 @@ enum CreatureIds NPC_HORDE_WARLOCK = 34450, NPC_HORDE_WARRIOR = 34453, - NPC_LIGHTBANE = 34497, - NPC_DARKBANE = 34496, + NPC_LIGHTBANE = 34497, + NPC_DARKBANE = 34496, - NPC_DARK_ESSENCE = 34567, - NPC_LIGHT_ESSENCE = 34568, + NPC_DARK_ESSENCE = 34567, + NPC_LIGHT_ESSENCE = 34568, - NPC_ANUBARAK = 34564 + NPC_ANUBARAK = 34564 }; enum GameObjectIds diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index 5e55256ae59..d5c07fb6942 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -178,6 +178,8 @@ class boss_rotface : public CreatureScript if (summon->GetEntry() == NPC_VILE_GAS_STALKER) if (Creature* professor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PROFESSOR_PUTRICIDE))) professor->CastSpell(summon, SPELL_VILE_GAS_H, true); + + summons.Summon(summon); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index d6c7b18eabd..880d032265a 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -91,7 +91,7 @@ class instance_halls_of_stone : public InstanceMapScript case GO_TRIBUNAL_CHEST_HERO: TribunalChestGUID = go->GetGUID(); if (GetBossState(DATA_BRANN_EVENT) == DONE) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); break; case GO_TRIBUNAL_SKY_FLOOR: TribunalSkyFloorGUID = go->GetGUID(); @@ -160,7 +160,7 @@ class instance_halls_of_stone : public InstanceMapScript if (state == DONE) { if (GameObject* go = instance->GetGameObject(TribunalChestGUID)) - go->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); } break; default: diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp index e6ffa3f8979..6ec69ee11af 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp @@ -72,7 +72,7 @@ public: struct boss_darkweaver_sythAI : public BossAI { boss_darkweaver_sythAI(Creature* creature) : BossAI(creature, DATA_DARKWEAVER_SYTH) - { + { Initialize(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index dd0e271a02d..23abf48233e 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -117,7 +117,7 @@ public: void Reset() override { - ReliquaryGUID.Clear(); + ReliquaryGUID.Clear(); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index 65cb2c2abce..752ea2feb1c 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -24,7 +24,6 @@ go_ethereum_stasis go_sacred_fire_of_life go_shrine_of_the_birds go_southfury_moonstone -go_field_repair_bot_74A go_orb_of_command go_resonite_cask go_tablet_of_madness @@ -94,24 +93,6 @@ public: }; /*###### -## go_field_repair_bot_74A -######*/ - -class go_field_repair_bot_74A : public GameObjectScript -{ -public: - go_field_repair_bot_74A() : GameObjectScript("go_field_repair_bot_74A") { } - - bool OnGossipHello(Player* player, GameObject* /*go*/) override - { - if (player->HasSkill(SKILL_ENGINEERING) && player->GetBaseSkillValue(SKILL_ENGINEERING) >= 300 && !player->HasSpell(22704)) - player->CastSpell(player, 22864, false); - - return true; - } -}; - -/*###### ## go_gilded_brazier (Paladin First Trail quest (9678)) ######*/ @@ -1213,7 +1194,6 @@ void AddSC_go_scripts() { new go_cat_figurine(); new go_barov_journal(); - new go_field_repair_bot_74A(); new go_gilded_brazier(); new go_orb_of_command(); new go_shrine_of_the_birds(); diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index ecbd0e9244c..531d092d039 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -89,4 +89,6 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_INS_DISABLES, "INSERT INTO disables (entry, sourceType, flags, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_DISABLES, "SELECT entry FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC); + PrepareStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA, "UPDATE creature SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, "UPDATE gameobject SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC); } diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index 8a5bd206021..a398b412c50 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -110,6 +110,8 @@ enum WorldDatabaseStatements WORLD_SEL_DISABLES, WORLD_INS_DISABLES, WORLD_DEL_DISABLES, + WORLD_UPD_CREATURE_ZONE_AREA_DATA, + WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, MAX_WORLDDATABASE_STATEMENTS }; diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index a7b6b418cc4..3305b364f0f 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -334,7 +334,7 @@ bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLog return true; } -void Log::outCharDump(char const* str, uint32 accountId, uint32 guid, char const* name) +void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const* name) { if (!str || !ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) return; diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 78e7e012bbe..e2d4baa5f0e 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -62,7 +62,7 @@ class Log void outMessage(std::string const& f, LogLevel level, char const* str, ...) ATTR_PRINTF(4, 5); void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4); - void outCharDump(char const* str, uint32 account_id, uint32 guid, char const* name); + void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name); void SetRealmId(uint32 id); diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 0cdf5f13f79..65972e680ef 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -47,6 +47,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/gsoap ${CMAKE_SOURCE_DIR}/dep/sockets/include ${CMAKE_SOURCE_DIR}/dep/SFMT + ${CMAKE_SOURCE_DIR}/dep/zmqpp ${CMAKE_SOURCE_DIR}/src/server/collision ${CMAKE_SOURCE_DIR}/src/server/collision/Management ${CMAKE_SOURCE_DIR}/src/server/collision/Models @@ -64,6 +65,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/ipc ${CMAKE_SOURCE_DIR}/src/server/game ${CMAKE_SOURCE_DIR}/src/server/game/Accounts ${CMAKE_SOURCE_DIR}/src/server/game/Achievements @@ -141,6 +143,7 @@ include_directories( ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} + ${ZMQ_INCLUDE_DIR} ) add_executable(worldserver @@ -164,18 +167,21 @@ set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAG target_link_libraries(worldserver game + ipc shared scripts collision g3dlib gsoap Detour + zmqpp ${JEMALLOC_LIBRARY} ${READLINE_LIBRARY} ${TERMCAP_LIBRARY} ${MYSQL_LIBRARY} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} + ${ZMQ_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ) diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 6c93343b8de..c5127b8f3e2 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -20,13 +20,9 @@ /// @{ /// \file -#include <openssl/opensslv.h> -#include <openssl/crypto.h> -#include <boost/asio/io_service.hpp> -#include <boost/asio/deadline_timer.hpp> -#include <boost/program_options.hpp> - #include "Common.h" +#include "Commands.h" +#include "ZmqContext.h" #include "DatabaseEnv.h" #include "AsyncAcceptor.h" #include "RASession.h" @@ -47,6 +43,12 @@ #include "SystemConfig.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" +#include "BattlenetServerManager.h" +#include <openssl/opensslv.h> +#include <openssl/crypto.h> +#include <boost/asio/io_service.hpp> +#include <boost/asio/deadline_timer.hpp> +#include <boost/program_options.hpp> using namespace boost::program_options; @@ -79,7 +81,7 @@ uint32 _maxCoreStuckTimeInMs(0); WorldDatabaseWorkerPool WorldDatabase; ///< Accessor to the world database CharacterDatabaseWorkerPool CharacterDatabase; ///< Accessor to the character database LoginDatabaseWorkerPool LoginDatabase; ///< Accessor to the realm/login database -uint32 realmID; ///< Id of the realm +Battlenet::RealmHandle realmHandle; ///< Id of the realm void SignalHandler(const boost::system::error_code& error, int signalNumber); void FreezeDetectorHandler(const boost::system::error_code& error); @@ -188,7 +190,7 @@ extern int main(int argc, char** argv) } // Set server offline (not connectable) - LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmID); + LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmHandle.Index); // Initialize the World sWorld->SetInitialWorldSettings(); @@ -223,7 +225,7 @@ extern int main(int argc, char** argv) sWorldSocketMgr.StartNetwork(_ioService, worldListener, worldPort); // Set server online (allow connecting now) - LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmID); + LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmHandle.Index); // Start the freeze check callback cycle in 5 seconds (cycle itself is 1 sec) if (int coreStuckTime = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0)) @@ -234,6 +236,10 @@ extern int main(int argc, char** argv) TC_LOG_INFO("server.worldserver", "Starting up anti-freeze thread (%u seconds max stuck time)...", coreStuckTime); } + sIpcContext->Initialize(); + + sBattlenetServer.InitializeConnection(); + TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon) ready...", _FULLVERSION); sScriptMgr->OnStartup(); @@ -245,6 +251,10 @@ extern int main(int argc, char** argv) sScriptMgr->OnShutdown(); + sIpcContext->Close(); + + sBattlenetServer.CloseConnection(); + sWorld->KickAll(); // save and kick all players sWorld->UpdateSessions(1); // real players unload required UpdateSessions call @@ -260,7 +270,7 @@ extern int main(int argc, char** argv) sOutdoorPvPMgr->Die(); // set server offline - LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmID); + LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmHandle.Index); // Clean up threads if any if (soapThread != nullptr) @@ -523,13 +533,24 @@ bool StartDB() } ///- Get the realm Id from the configuration file - realmID = sConfigMgr->GetIntDefault("RealmID", 0); - if (!realmID) + realmHandle.Index = sConfigMgr->GetIntDefault("RealmID", 0); + if (!realmHandle.Index) { TC_LOG_ERROR("server.worldserver", "Realm ID not defined in configuration file"); return false; } - TC_LOG_INFO("server.worldserver", "Realm running as realm ID %d", realmID); + + QueryResult realmIdQuery = LoginDatabase.PQuery("SELECT `Region`,`Battlegroup` FROM `realmlist` WHERE `id`=%u", realmHandle.Index); + if (!realmIdQuery) + { + TC_LOG_ERROR("server.worldserver", "Realm id %u not defined in realmlist table", realmHandle.Index); + return false; + } + + realmHandle.Region = (*realmIdQuery)[0].GetUInt8(); + realmHandle.Battlegroup = (*realmIdQuery)[1].GetUInt8(); + + TC_LOG_INFO("server.worldserver", "Realm running as realm ID %u region %u battlegroup %u", realmHandle.Index, uint32(realmHandle.Region), uint32(realmHandle.Battlegroup)); ///- Clean the database before starting ClearOnlineAccounts(); @@ -556,7 +577,7 @@ void StopDB() void ClearOnlineAccounts() { // Reset online status for all accounts with characters on the current realm - LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online > 0 AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = %d)", realmID); + LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online > 0 AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = %d)", realmHandle.Index); // Reset online status for all characters CharacterDatabase.DirectExecute("UPDATE characters SET online = 0 WHERE online <> 0"); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index d1a4c244ba2..57d97756d70 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -267,9 +267,9 @@ ChangeWeatherInterval = 600000 # # PlayerSaveInterval # Description: Time (in milliseconds) for player save interval. -# Default: 900000 - (15 min) +# Default: 90000 - (90 seconds) -PlayerSaveInterval = 900000 +PlayerSaveInterval = 90000 # # PlayerSave.Stats.MinLevel @@ -289,7 +289,7 @@ PlayerSave.Stats.SaveOnlyOnLogout = 1 # # mmap.enablePathFinding -# Description: Enable/Disable pathfinding using mmaps - experimental. +# Description: Enable/Disable pathfinding using mmaps - recommended. # Default: 0 - (Disabled) # 1 - (Enabled) @@ -2004,9 +2004,9 @@ AutoBroadcast.Center = 0 # # AutoBroadcast.Timer # Description: Timer (in milliseconds) for auto broadcasts. -# Default: 60000 - (60 seconds) +# Default: 60000 - (10 minutes) -AutoBroadcast.Timer = 60000 +AutoBroadcast.Timer = 600000 # ################################################################################################### @@ -2620,6 +2620,20 @@ PlayerDump.DisallowOverwrite = 1 UI.ShowQuestLevelsInDialogs = 0 # +# Calculate.Creature.Zone.Area.Data +# Description: Calculate at loading creature zoneId / areaId and save in creature table (WARNING: SLOW WORLD SERVER STARTUP) +# Default: 0 - (Do not show) + +Calculate.Creature.Zone.Area.Data = 0 + +# +# Calculate.Gameoject.Zone.Area.Data +# Description: Calculate at loading gameobject zoneId / areaId and save in gameobject table (WARNING: SLOW WORLD SERVER STARTUP) +# Default: 0 - (Do not show) + +Calculate.Gameoject.Zone.Area.Data = 0 + +# ################################################################################################### ################################################################################################### @@ -3275,6 +3289,8 @@ Currency.ConquestPointsArenaReward = 180 # ################################################################################################### + +################################################################################################### # PACKET SPOOF PROTECTION SETTINGS # # These settings determine which action to take when harmful packet spoofing is detected. @@ -3308,3 +3324,24 @@ PacketSpoof.BanDuration = 86400 # ################################################################################################### + +################################################################################################### +# IPC SETTINGS +# +# BnetServer.Address +# Description: Determines IP address of battle.net server to connect to. +# Default: 127.0.0.1 +# + +BnetServer.Address = 127.0.0.1 + +# +# BnetServer.Port +# Description: Determines port to use when connecting to battle.net server. +# Default: 1118 +# + +BnetServer.Port = 1118 + +# +################################################################################################### diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 885dd24d760..2f8b35fd52d 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -27,14 +27,6 @@ #include "DetourNavMesh.h" #include "DetourCommon.h" -#include "DisableMgr.h" - -uint32 GetLiquidFlags(uint32 /*liquidType*/) { return 0; } -namespace DisableMgr -{ - bool IsDisabledFor(DisableType /*type*/, uint32 /*entry*/, Unit const* /*unit*/, uint8 /*flags*/ /*= 0*/) { return false; } -} - #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' #define MMAP_VERSION 5 diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 8285fef74f2..694e40dacde 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -62,7 +62,7 @@ namespace MMAP if (*++filter == '\0') // wildcard at end of filter means all remaing chars match return true; - while (true) + for (;;) { if (*filter == *str) break; |