Merge remote-tracking branch 'tc/3.3.5' into 4.3.4

Note: additional hand-picked ports from 6.x to fix build

Conflicts:
	sql/updates/world/2016_02_22_00_world.sql
	sql/updates/world/2016_02_22_01_world.sql
	sql/updates/world/2016_02_22_02_world.sql
	sql/updates/world/2016_03_07_00_world.sql
	src/server/authserver/Realms/RealmList.cpp
	src/server/authserver/Realms/RealmList.h
	src/server/authserver/Server/AuthSession.cpp
	src/server/game/Accounts/AccountMgr.cpp
	src/server/game/AuctionHouse/AuctionHouseMgr.cpp
	src/server/game/Chat/Chat.cpp
	src/server/game/Conditions/ConditionMgr.cpp
	src/server/game/Conditions/ConditionMgr.h
	src/server/game/Entities/Player/Player.cpp
	src/server/game/Handlers/CharacterHandler.cpp
	src/server/game/Handlers/MiscHandler.cpp
	src/server/game/Scripting/ScriptLoader.cpp
	src/server/game/Scripting/ScriptLoader.h
	src/server/game/Server/WorldSession.cpp
	src/server/game/Server/WorldSocket.cpp
	src/server/game/World/World.cpp
	src/server/game/World/World.h
	src/server/scripts/CMakeLists.txt
	src/server/scripts/Commands/cs_gm.cpp
	src/server/scripts/Commands/cs_misc.cpp
	src/server/scripts/Commands/cs_rbac.cpp
	src/server/scripts/Commands/cs_ticket.cpp
	src/server/scripts/Commands/cs_wp.cpp
	src/server/scripts/EasternKingdoms/CMakeLists.txt
	src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
	src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
	src/server/scripts/Kalimdor/CMakeLists.txt
	src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp
	src/server/scripts/Kalimdor/zone_orgrimmar.cpp
	src/server/scripts/OutdoorPvP/CMakeLists.txt
	src/server/scripts/Spells/spell_dk.cpp
	src/server/scripts/Spells/spell_hunter.cpp
	src/server/shared/CMakeLists.txt
	src/server/worldserver/CMakeLists.txt
	src/server/worldserver/Main.cpp
	src/tools/mmaps_generator/CMakeLists.txt
This commit is contained in:
ariel-
2016-03-11 18:32:07 -03:00
143 changed files with 4022 additions and 4094 deletions

View File

@@ -57,6 +57,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/database
${CMAKE_SOURCE_DIR}/src/server/database/Database
${CMAKE_SOURCE_DIR}/src/server/database/Logging
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
${CMAKE_SOURCE_DIR}/src/server/shared/Service
@@ -79,10 +80,10 @@ if( NOT WIN32 )
endif()
target_link_libraries(authserver
common
shared
format
database
common
format
${MYSQL_LIBRARY}
${OPENSSL_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}

View File

@@ -134,7 +134,7 @@ int main(int argc, char** argv)
// Get the list of realms for the server
sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
if (sRealmList->size() == 0)
if (sRealmList->GetRealms().empty())
{
TC_LOG_ERROR("server.authserver", "No valid realms specified.");
StopDB();
@@ -194,6 +194,8 @@ int main(int argc, char** argv)
sAuthSocketMgr.StopNetwork();
sRealmList->Close();
// Close the Database Pool and library
StopDB();

View File

@@ -16,104 +16,62 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <boost/asio/ip/tcp.hpp>
#include "Common.h"
#include "RealmList.h"
#include "Database/DatabaseEnv.h"
#include "Util.h"
#include "RealmList.h"
#include <boost/asio/ip/tcp.hpp>
ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const
{
ip::address realmIp;
// Attempt to send best address for client
if (clientAddr.is_loopback())
{
// Try guessing if realm is also connected locally
if (LocalAddress.is_loopback() || ExternalAddress.is_loopback())
realmIp = clientAddr;
else
{
// Assume that user connecting from the machine that authserver is located on
// has all realms available in his local network
realmIp = LocalAddress;
}
}
else
{
if (clientAddr.is_v4() &&
(clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) ==
(LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()))
{
realmIp = LocalAddress;
}
else
realmIp = ExternalAddress;
}
ip::tcp::endpoint endpoint(realmIp, port);
// Return external IP
return endpoint;
}
RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)), _resolver(nullptr)
{
}
namespace boost { namespace asio { namespace ip { class address; } } }
RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) { }
RealmList::~RealmList()
{
delete _resolver;
delete _updateTimer;
}
// Load the realm list from the database
void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval)
{
_updateInterval = updateInterval;
_updateTimer = new boost::asio::deadline_timer(ioService);
_resolver = new boost::asio::ip::tcp::resolver(ioService);
m_UpdateInterval = updateInterval;
// Get the content of the realmlist table in the database
UpdateRealms(true);
UpdateRealms(true, boost::system::error_code());
}
void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build)
void RealmList::Close()
{
_updateTimer->cancel();
}
void RealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel,
float population)
{
// Create new if not exist or update existed
Realm& realm = m_realms[name];
realm.m_ID = id;
realm.name = name;
realm.icon = icon;
realm.flag = flag;
realm.timezone = timezone;
realm.allowedSecurityLevel = allowedSecurityLevel;
realm.populationLevel = population;
Realm& realm = _realms[id];
realm.Id = id;
realm.Build = build;
realm.Name = name;
realm.Type = icon;
realm.Flags = flag;
realm.Timezone = timezone;
realm.AllowedSecurityLevel = allowedSecurityLevel;
realm.PopulationLevel = population;
realm.ExternalAddress = address;
realm.LocalAddress = localAddr;
realm.LocalSubnetMask = localSubmask;
realm.port = port;
realm.gamebuild = build;
realm.Port = port;
}
void RealmList::UpdateIfNeed()
void RealmList::UpdateRealms(bool init, boost::system::error_code const& error)
{
// maybe disabled or updated recently
if (!m_UpdateInterval || m_NextUpdateTime > time(NULL))
if (error)
return;
m_NextUpdateTime = time(NULL) + m_UpdateInterval;
// Clears Realm list
m_realms.clear();
// Get the content of the realmlist table in the database
UpdateRealms();
}
void RealmList::UpdateRealms(bool init)
{
TC_LOG_INFO("server.authserver", "Updating Realm List...");
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
@@ -165,17 +123,25 @@ void RealmList::UpdateRealms(bool init)
uint16 port = fields[5].GetUInt16();
uint8 icon = fields[6].GetUInt8();
if (icon == REALM_TYPE_FFA_PVP)
icon = REALM_TYPE_PVP;
if (icon >= MAX_CLIENT_REALM_TYPE)
icon = REALM_TYPE_NORMAL;
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
uint8 timezone = fields[8].GetUInt8();
uint8 allowedSecurityLevel = fields[9].GetUInt8();
float pop = fields[10].GetFloat();
uint32 build = fields[11].GetUInt32();
uint8 region = fields[12].GetUInt8();
uint8 battlegroup = fields[13].GetUInt8();
UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone,
(allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
Battlenet::RealmHandle id{ region, battlegroup, realmId };
UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag,
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
if (init)
TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port);
TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port);
}
catch (std::exception& ex)
{
@@ -185,4 +151,19 @@ void RealmList::UpdateRealms(bool init)
}
while (result->NextRow());
}
if (_updateInterval)
{
_updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
_updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, false, std::placeholders::_1));
}
}
Realm const* RealmList::GetRealm(Battlenet::RealmHandle const& id) const
{
auto itr = _realms.find(id);
if (itr != _realms.end())
return &itr->second;
return NULL;
}

View File

@@ -19,50 +19,20 @@
#ifndef _REALMLIST_H
#define _REALMLIST_H
#include "Common.h"
#include "Realm/Realm.h"
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
#include "Common.h"
#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
};
// Storage object for a realm
struct Realm
{
ip::address ExternalAddress;
ip::address LocalAddress;
ip::address LocalSubnetMask;
uint16 port;
std::string name;
uint8 icon;
RealmFlags flag;
uint8 timezone;
uint32 m_ID;
AccountTypes allowedSecurityLevel;
float populationLevel;
uint32 gamebuild;
ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
};
/// Storage object for the list of realms on the server
class RealmList
{
public:
typedef std::map<std::string, Realm> RealmMap;
typedef std::map<Battlenet::RealmHandle, Realm> RealmMap;
static RealmList* instance()
{
@@ -73,25 +43,21 @@ public:
~RealmList();
void Initialize(boost::asio::io_service& ioService, uint32 updateInterval);
void Close();
void UpdateIfNeed();
void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; }
RealmMap::const_iterator begin() const { return m_realms.begin(); }
RealmMap::const_iterator end() const { return m_realms.end(); }
uint32 size() const { return m_realms.size(); }
RealmMap const& GetRealms() const { return _realms; }
Realm const* GetRealm(Battlenet::RealmHandle const& id) const;
private:
RealmList();
void UpdateRealms(bool init = false);
void UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build);
void UpdateRealms(bool init, boost::system::error_code const& error);
void UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
RealmMap m_realms;
uint32 m_UpdateInterval;
time_t m_NextUpdateTime;
RealmMap _realms;
uint32 _updateInterval;
boost::asio::deadline_timer* _updateTimer;
boost::asio::ip::tcp::resolver* _resolver;
};

View File

@@ -571,6 +571,8 @@ bool AuthSession::HandleLogonProof()
TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str());
// Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
// No SQL injection (escaped user name) and IP address as received by socket
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
stmt->setString(0, K.AsHexStr());
stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
@@ -842,22 +844,19 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
} while (result->NextRow());
}
// Update realm list if need
sRealmList->UpdateIfNeed();
// Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
ByteBuffer pkt;
size_t RealmListSize = 0;
for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms())
{
const Realm &realm = i->second;
const Realm &realm = i.second;
// don't work with realms which not compatible with the client
bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.gamebuild));
bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.Build == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.Build));
// No SQL injection. id of realm is controlled by the database.
uint32 flag = realm.flag;
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild);
uint32 flag = realm.Flags;
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.Build);
if (!okBuild)
{
if (!buildInfo)
@@ -869,7 +868,7 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
if (!buildInfo)
flag &= ~REALM_FLAG_SPECIFYBUILD;
std::string name = i->first;
std::string name = realm.Name;
if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
{
std::ostringstream ss;
@@ -877,19 +876,19 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
name = ss.str();
}
uint8 lock = (realm.allowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
uint8 lock = (realm.AllowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
pkt << uint8(realm.icon); // realm type
pkt << uint8(realm.Type); // realm type
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
pkt << uint8(lock); // if 1, then realm locked
pkt << uint8(flag); // RealmFlags
pkt << name;
pkt << boost::lexical_cast<std::string>(realm.GetAddressForClient(GetRemoteIpAddress()));
pkt << float(realm.populationLevel);
pkt << uint8(characterCounts[realm.m_ID]);
pkt << uint8(realm.timezone); // realm category
pkt << float(realm.PopulationLevel);
pkt << uint8(characterCounts[realm.Id.Realm]);
pkt << uint8(realm.Timezone); // realm category
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
pkt << uint8(realm.m_ID);
pkt << uint8(realm.Id.Realm);
else
pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients
@@ -953,6 +952,7 @@ void AuthSession::SetVSFields(const std::string& rI)
x.SetBinary(sha.GetDigest(), sha.GetLength());
v = g.ModExp(x, N);
// No SQL injection (username escaped)
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_VS);
stmt->setString(0, v.AsHexStr());
stmt->setString(1, s.AsHexStr());

View File

@@ -137,6 +137,26 @@ WrongPass.Logging = 0
BanExpiryCheckInterval = 60
#
# SourceDirectory
# Description: The path to your TrinityCore source directory.
# If the path is left empty, the built-in CMAKE_SOURCE_DIR is used.
# Example: "../TrinityCore"
# Default: ""
SourceDirectory = ""
#
# MySQLExecutable
# Description: The path to your mysql cli binary.
# If the path is left empty, built-in path from cmake is used.
# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
# "mysql.exe"
# "/usr/bin/mysql"
# Default: ""
MySQLExecutable = ""
#
###################################################################################################
@@ -180,26 +200,6 @@ LoginDatabase.WorkerThreads = 1
Updates.EnableDatabases = 0
#
# Updates.SourcePath
# Description: The path to your TrinityCore source directory.
# If the path is left empty, built-in CMAKE_SOURCE_DIR is used.
# Example: "../TrinityCore"
# Default: ""
Updates.SourcePath = ""
#
# Updates.MySqlCLIPath
# Description: The path to your mysql cli binary.
# If the path is left empty, built-in path from cmake is used.
# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
# "mysql.exe"
# "/usr/bin/mysql"
# Default: ""
Updates.MySqlCLIPath = ""
#
# Updates.AutoSetup
# Description: Auto populate empty databases.