aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/DataStores/DB2FileLoader.cpp12
-rw-r--r--src/server/bnetserver/REST/LoginHttpSession.cpp62
-rw-r--r--src/server/bnetserver/REST/LoginHttpSession.h49
-rw-r--r--src/server/bnetserver/REST/LoginRESTService.cpp28
-rw-r--r--src/server/bnetserver/REST/LoginRESTService.h14
-rw-r--r--src/server/bnetserver/Server/Session.cpp3
-rw-r--r--src/server/bnetserver/Server/SslContext.cpp33
-rw-r--r--src/server/bnetserver/Server/SslContext.h5
-rw-r--r--src/server/game/Entities/Object/Object.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp11
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp55
-rw-r--r--src/server/game/Quests/QuestDef.h49
-rw-r--r--src/server/game/Quests/enuminfo_QuestDef.cpp128
-rw-r--r--src/server/game/Server/Packets/SystemPackets.cpp4
-rw-r--r--src/server/game/Server/Packets/SystemPackets.h5
-rw-r--r--src/server/shared/Networking/Http/HttpSocket.h3
17 files changed, 210 insertions, 256 deletions
diff --git a/src/common/DataStores/DB2FileLoader.cpp b/src/common/DataStores/DB2FileLoader.cpp
index 57ec7df6e3f..7a586178794 100644
--- a/src/common/DataStores/DB2FileLoader.cpp
+++ b/src/common/DataStores/DB2FileLoader.cpp
@@ -2076,19 +2076,23 @@ void DB2FileLoader::Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo)
if (loadInfo)
{
uint32 fieldIndex = 0;
+ std::string signValidationResult;
if (!loadInfo->Meta->HasIndexFieldInData())
{
- ASSERT(!loadInfo->Fields[0].IsSigned, "ID must be unsigned in %s", source->GetFileName());
+ if (loadInfo->Fields[0].IsSigned)
+ signValidationResult += Trinity::StringFormat("ID must be unsigned in {}", source->GetFileName());
++fieldIndex;
}
for (uint32 f = 0; f < loadInfo->Meta->FieldCount; ++f)
{
- ASSERT(loadInfo->Fields[fieldIndex].IsSigned == _impl->IsSignedField(f),
- "Field %s in %s must be %s%s", loadInfo->Fields[fieldIndex].Name, source->GetFileName(), _impl->IsSignedField(f) ? "signed" : "unsigned",
- _impl->GetExpectedSignMismatchReason(f));
+ if (loadInfo->Fields[fieldIndex].IsSigned != _impl->IsSignedField(f))
+ signValidationResult += Trinity::StringFormat("Field {} in {} must be {}{}", loadInfo->Fields[fieldIndex].Name,
+ source->GetFileName(), _impl->IsSignedField(f) ? "signed" : "unsigned", _impl->GetExpectedSignMismatchReason(f));
fieldIndex += loadInfo->Meta->Fields[f].ArraySize;
}
+ if (!signValidationResult.empty())
+ throw DB2FileLoadException(std::move(signValidationResult));
}
}
diff --git a/src/server/bnetserver/REST/LoginHttpSession.cpp b/src/server/bnetserver/REST/LoginHttpSession.cpp
index 95112cb8836..aff579de7f9 100644
--- a/src/server/bnetserver/REST/LoginHttpSession.cpp
+++ b/src/server/bnetserver/REST/LoginHttpSession.cpp
@@ -23,17 +23,20 @@
namespace Battlenet
{
-LoginHttpSession::LoginHttpSession(boost::asio::ip::tcp::socket&& socket)
- : SslSocket(std::move(socket), SslContext::instance())
+template<template<typename> typename SocketImpl>
+LoginHttpSession<SocketImpl>::LoginHttpSession(boost::asio::ip::tcp::socket&& socket, LoginHttpSessionWrapper& owner)
+ : BaseSocket(std::move(socket), SslContext::instance()), _owner(owner)
{
}
-LoginHttpSession::~LoginHttpSession() = default;
+template<template<typename> typename SocketImpl>
+LoginHttpSession<SocketImpl>::~LoginHttpSession() = default;
-void LoginHttpSession::Start()
+template<template<typename> typename SocketImpl>
+void LoginHttpSession<SocketImpl>::Start()
{
- std::string ip_address = GetRemoteIpAddress().to_string();
- TC_LOG_TRACE("server.http.session", "{} Accepted connection", GetClientInfo());
+ std::string ip_address = this->GetRemoteIpAddress().to_string();
+ TC_LOG_TRACE("server.http.session", "{} Accepted connection", this->GetClientInfo());
// Verify that this IP is not in the ip_banned table
LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
@@ -41,11 +44,12 @@ void LoginHttpSession::Start()
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
stmt->setString(0, ip_address);
- _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt)
- .WithPreparedCallback([sess = shared_from_this()](PreparedQueryResult result) { sess->CheckIpCallback(std::move(result)); }));
+ this->_queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback([sess = this->shared_from_this()](PreparedQueryResult result) { sess->CheckIpCallback(std::move(result)); }));
}
-void LoginHttpSession::CheckIpCallback(PreparedQueryResult result)
+template<template<typename> typename SocketImpl>
+void LoginHttpSession<SocketImpl>::CheckIpCallback(PreparedQueryResult result)
{
if (result)
{
@@ -60,21 +64,30 @@ void LoginHttpSession::CheckIpCallback(PreparedQueryResult result)
if (banned)
{
- TC_LOG_DEBUG("server.http.session", "{} tries to log in using banned IP!", GetClientInfo());
- CloseSocket();
+ TC_LOG_DEBUG("server.http.session", "{} tries to log in using banned IP!", this->GetClientInfo());
+ this->CloseSocket();
return;
}
}
- AsyncHandshake();
+ if constexpr (std::is_same_v<BaseSocket, Trinity::Net::Http::SslSocket<LoginHttpSession<Trinity::Net::Http::SslSocket>>>)
+ {
+ this->AsyncHandshake();
+ }
+ else
+ {
+ this->ResetHttpParser();
+ this->AsyncRead();
+ }
}
-Trinity::Net::Http::RequestHandlerResult LoginHttpSession::RequestHandler(Trinity::Net::Http::RequestContext& context)
+template<template<typename> typename SocketImpl>
+Trinity::Net::Http::RequestHandlerResult LoginHttpSession<SocketImpl>::RequestHandler(Trinity::Net::Http::RequestContext& context)
{
- return sLoginService.HandleRequest(shared_from_this(), context);
+ return sLoginService.HandleRequest(_owner.shared_from_this(), context);
}
-std::shared_ptr<Trinity::Net::Http::SessionState> LoginHttpSession::ObtainSessionState(Trinity::Net::Http::RequestContext& context) const
+std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context, boost::asio::ip::address const& remoteAddress)
{
using namespace std::string_literals;
@@ -92,27 +105,38 @@ std::shared_ptr<Trinity::Net::Http::SessionState> LoginHttpSession::ObtainSessio
if (eq != std::string_view::npos)
name = cookie.substr(0, eq);
- return name == SESSION_ID_COOKIE;
+ return name == LoginHttpSessionWrapper::SESSION_ID_COOKIE;
});
if (sessionIdItr != cookies.end())
{
std::string_view value = sessionIdItr->substr(eq + 1);
- state = sLoginService.FindAndRefreshSessionState(value, GetRemoteIpAddress());
+ state = sLoginService.FindAndRefreshSessionState(value, remoteAddress);
}
}
if (!state)
{
- state = sLoginService.CreateNewSessionState(GetRemoteIpAddress());
+ state = sLoginService.CreateNewSessionState(remoteAddress);
std::string_view host = Trinity::Net::Http::ToStdStringView(context.request[boost::beast::http::field::host]);
if (std::size_t port = host.find(':'); port != std::string_view::npos)
host.remove_suffix(host.length() - port);
context.response.insert(boost::beast::http::field::set_cookie, Trinity::StringFormat("{}={}; Path=/bnetserver; Domain={}; Secure; HttpOnly; SameSite=None",
- SESSION_ID_COOKIE, boost::uuids::to_string(state->Id), host));
+ LoginHttpSessionWrapper::SESSION_ID_COOKIE, boost::uuids::to_string(state->Id), host));
}
return state;
}
+
+template class LoginHttpSession<Trinity::Net::Http::SslSocket>;
+template class LoginHttpSession<Trinity::Net::Http::Socket>;
+
+LoginHttpSessionWrapper::LoginHttpSessionWrapper(boost::asio::ip::tcp::socket&& socket)
+{
+ if (!SslContext::UsesDevWildcardCertificate())
+ _socket = std::make_shared<LoginHttpSession<Trinity::Net::Http::SslSocket>>(std::move(socket), *this);
+ else
+ _socket = std::make_shared<LoginHttpSession<Trinity::Net::Http::Socket>>(std::move(socket), *this);
+}
}
diff --git a/src/server/bnetserver/REST/LoginHttpSession.h b/src/server/bnetserver/REST/LoginHttpSession.h
index 2ee70d5afa5..6bd1ec113d0 100644
--- a/src/server/bnetserver/REST/LoginHttpSession.h
+++ b/src/server/bnetserver/REST/LoginHttpSession.h
@@ -18,8 +18,10 @@
#ifndef TRINITYCORE_LOGIN_HTTP_SESSION_H
#define TRINITYCORE_LOGIN_HTTP_SESSION_H
+#include "HttpSocket.h"
#include "HttpSslSocket.h"
#include "SRP6.h"
+#include <variant>
namespace Battlenet
{
@@ -28,12 +30,16 @@ struct LoginSessionState : public Trinity::Net::Http::SessionState
std::unique_ptr<Trinity::Crypto::SRP::BnetSRP6Base> Srp;
};
-class LoginHttpSession : public Trinity::Net::Http::SslSocket<LoginHttpSession>
+class LoginHttpSessionWrapper;
+std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context, boost::asio::ip::address const& remoteAddress);
+
+template<template<typename> typename SocketImpl>
+class LoginHttpSession : public SocketImpl<LoginHttpSession<SocketImpl>>
{
-public:
- static constexpr std::string_view SESSION_ID_COOKIE = "JSESSIONID";
+ using BaseSocket = SocketImpl<LoginHttpSession<SocketImpl>>;
- explicit LoginHttpSession(boost::asio::ip::tcp::socket&& socket);
+public:
+ explicit LoginHttpSession(boost::asio::ip::tcp::socket&& socket, LoginHttpSessionWrapper& owner);
~LoginHttpSession();
void Start() override;
@@ -42,10 +48,41 @@ public:
Trinity::Net::Http::RequestHandlerResult RequestHandler(Trinity::Net::Http::RequestContext& context) override;
- LoginSessionState* GetSessionState() const { return static_cast<LoginSessionState*>(_state.get()); }
+ LoginSessionState* GetSessionState() const { return static_cast<LoginSessionState*>(this->_state.get()); }
protected:
- std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context) const override;
+ std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context) const override
+ {
+ return Battlenet::ObtainSessionState(context, this->GetRemoteIpAddress());
+ }
+
+ LoginHttpSessionWrapper& _owner;
+};
+
+class LoginHttpSessionWrapper : public Trinity::Net::Http::AbstractSocket, public std::enable_shared_from_this<LoginHttpSessionWrapper>
+{
+public:
+ static constexpr std::string_view SESSION_ID_COOKIE = "JSESSIONID";
+
+ explicit LoginHttpSessionWrapper(boost::asio::ip::tcp::socket&& socket);
+
+ void Start() { return std::visit([&](auto&& socket) { return socket->Start(); }, _socket); }
+ bool Update() { return std::visit([&](auto&& socket) { return socket->Update(); }, _socket); }
+ boost::asio::ip::address GetRemoteIpAddress() const { return std::visit([&](auto&& socket) { return socket->GetRemoteIpAddress(); }, _socket); }
+ bool IsOpen() const { return std::visit([&](auto&& socket) { return socket->IsOpen(); }, _socket); }
+ void CloseSocket() { return std::visit([&](auto&& socket) { return socket->CloseSocket(); }, _socket); }
+
+ void SendResponse(Trinity::Net::Http::RequestContext& context) override { return std::visit([&](auto&& socket) { return socket->SendResponse(context); }, _socket); }
+ void QueueQuery(QueryCallback&& queryCallback) override { return std::visit([&](auto&& socket) { return socket->QueueQuery(std::move(queryCallback)); }, _socket); }
+ std::string GetClientInfo() const override { return std::visit([&](auto&& socket) { return socket->GetClientInfo(); }, _socket); }
+ Optional<boost::uuids::uuid> GetSessionId() const override { return std::visit([&](auto&& socket) { return socket->GetSessionId(); }, _socket); }
+ LoginSessionState* GetSessionState() const { return std::visit([&](auto&& socket) { return socket->GetSessionState(); }, _socket); }
+
+private:
+ std::variant<
+ std::shared_ptr<LoginHttpSession<Trinity::Net::Http::SslSocket>>,
+ std::shared_ptr<LoginHttpSession<Trinity::Net::Http::Socket>>
+ > _socket;
};
}
#endif // TRINITYCORE_LOGIN_HTTP_SESSION_H
diff --git a/src/server/bnetserver/REST/LoginRESTService.cpp b/src/server/bnetserver/REST/LoginRESTService.cpp
index 7587510bafc..c9aabb248a3 100644
--- a/src/server/bnetserver/REST/LoginRESTService.cpp
+++ b/src/server/bnetserver/REST/LoginRESTService.cpp
@@ -25,6 +25,7 @@
#include "IteratorPair.h"
#include "ProtobufJSON.h"
#include "Resolver.h"
+#include "SslContext.h"
#include "Timer.h"
#include "Util.h"
@@ -43,32 +44,32 @@ bool LoginRESTService::StartNetwork(Trinity::Asio::IoContext& ioContext, std::st
using Trinity::Net::Http::RequestHandlerFlag;
- RegisterHandler(boost::beast::http::verb::get, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+ RegisterHandler(boost::beast::http::verb::get, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
return HandleGetForm(std::move(session), context);
});
- RegisterHandler(boost::beast::http::verb::get, "/bnetserver/gameAccounts/", [](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+ RegisterHandler(boost::beast::http::verb::get, "/bnetserver/gameAccounts/", [](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
return HandleGetGameAccounts(std::move(session), context);
});
- RegisterHandler(boost::beast::http::verb::get, "/bnetserver/portal/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+ RegisterHandler(boost::beast::http::verb::get, "/bnetserver/portal/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
return HandleGetPortal(std::move(session), context);
});
- RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+ RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
return HandlePostLogin(std::move(session), context);
}, RequestHandlerFlag::DoNotLogRequestContent);
- RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/srp/", [](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+ RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/srp/", [](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
return HandlePostLoginSrpChallenge(std::move(session), context);
});
- RegisterHandler(boost::beast::http::verb::post, "/bnetserver/refreshLoginTicket/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+ RegisterHandler(boost::beast::http::verb::post, "/bnetserver/refreshLoginTicket/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
return HandlePostRefreshLoginTicket(std::move(session), context);
});
@@ -165,17 +166,18 @@ std::string LoginRESTService::ExtractAuthorization(HttpRequest const& request)
return ticket;
}
-LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetForm(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const
+LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetForm(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const
{
JSON::Login::FormInputs form = _formInputs;
- form.set_srp_url(Trinity::StringFormat("https://{}:{}/bnetserver/login/srp/", GetHostnameForClient(session->GetRemoteIpAddress()), _port));
+ form.set_srp_url(Trinity::StringFormat("http{}://{}:{}/bnetserver/login/srp/", !SslContext::UsesDevWildcardCertificate() ? "s" : "",
+ GetHostnameForClient(session->GetRemoteIpAddress()), _port));
context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8");
context.response.body() = ::JSON::Serialize(form);
return RequestHandlerResult::Handled;
}
-LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetGameAccounts(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetGameAccounts(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
std::string ticket = ExtractAuthorization(context.request);
if (ticket.empty())
@@ -224,14 +226,14 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetGameAccounts(s
return RequestHandlerResult::Async;
}
-LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetPortal(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const
+LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetPortal(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const
{
context.response.set(boost::beast::http::field::content_type, "text/plain");
context.response.body() = Trinity::StringFormat("{}:{}", GetHostnameForClient(session->GetRemoteIpAddress()), sConfigMgr->GetIntDefault("BattlenetPort", 1119));
return RequestHandlerResult::Handled;
}
-LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const
+LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const
{
std::shared_ptr<JSON::Login::LoginForm> loginForm = std::make_shared<JSON::Login::LoginForm>();
if (!::JSON::Deserialize(context.request.body(), loginForm.get()))
@@ -395,7 +397,7 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::sh
return RequestHandlerResult::Async;
}
-LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context)
{
JSON::Login::LoginForm loginForm;
if (!::JSON::Deserialize(context.request.body(), &loginForm))
@@ -482,7 +484,7 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChall
return RequestHandlerResult::Async;
}
-LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const
+LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const
{
std::string ticket = ExtractAuthorization(context.request);
if (ticket.empty())
diff --git a/src/server/bnetserver/REST/LoginRESTService.h b/src/server/bnetserver/REST/LoginRESTService.h
index 5683c262590..bcc99808505 100644
--- a/src/server/bnetserver/REST/LoginRESTService.h
+++ b/src/server/bnetserver/REST/LoginRESTService.h
@@ -42,7 +42,7 @@ enum class BanMode
BAN_ACCOUNT = 1
};
-class LoginRESTService : public Trinity::Net::Http::HttpService<LoginHttpSession>
+class LoginRESTService : public Trinity::Net::Http::HttpService<LoginHttpSessionWrapper>
{
public:
using RequestHandlerResult = Trinity::Net::Http::RequestHandlerResult;
@@ -67,13 +67,13 @@ private:
static std::string ExtractAuthorization(HttpRequest const& request);
- RequestHandlerResult HandleGetForm(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const;
- static RequestHandlerResult HandleGetGameAccounts(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context);
- RequestHandlerResult HandleGetPortal(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const;
+ RequestHandlerResult HandleGetForm(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const;
+ static RequestHandlerResult HandleGetGameAccounts(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context);
+ RequestHandlerResult HandleGetPortal(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const;
- RequestHandlerResult HandlePostLogin(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const;
- static RequestHandlerResult HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context);
- RequestHandlerResult HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const;
+ RequestHandlerResult HandlePostLogin(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const;
+ static RequestHandlerResult HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context);
+ RequestHandlerResult HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const;
static std::unique_ptr<Trinity::Crypto::SRP::BnetSRP6Base> CreateSrpImplementation(SrpVersion version, SrpHashFunction hashFunction,
std::string const& username, Trinity::Crypto::SRP::Salt const& salt, Trinity::Crypto::SRP::Verifier const& verifier);
diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp
index b450df14e1d..c94ee6e3e56 100644
--- a/src/server/bnetserver/Server/Session.cpp
+++ b/src/server/bnetserver/Server/Session.cpp
@@ -260,7 +260,8 @@ uint32 Battlenet::Session::HandleLogon(authentication::v1::LogonRequest const* l
challenge::v1::ChallengeExternalRequest externalChallenge;
externalChallenge.set_payload_type("web_auth_url");
- externalChallenge.set_payload(Trinity::StringFormat("https://{}:{}/bnetserver/login/", sLoginService.GetHostnameForClient(GetRemoteIpAddress()), sLoginService.GetPort()));
+ externalChallenge.set_payload(Trinity::StringFormat("http{}://{}:{}/bnetserver/login/", !SslContext::UsesDevWildcardCertificate() ? "s" : "",
+ sLoginService.GetHostnameForClient(GetRemoteIpAddress()), sLoginService.GetPort()));
Service<challenge::v1::ChallengeListener>(this).OnExternalChallenge(&externalChallenge);
return ERROR_OK;
}
diff --git a/src/server/bnetserver/Server/SslContext.cpp b/src/server/bnetserver/Server/SslContext.cpp
index 92d95f24cc5..52daff1645d 100644
--- a/src/server/bnetserver/Server/SslContext.cpp
+++ b/src/server/bnetserver/Server/SslContext.cpp
@@ -24,6 +24,8 @@
#include <openssl/store.h>
#include <openssl/ui.h>
+bool Battlenet::SslContext::_usesDevWildcardCertificate = false;
+
namespace
{
auto CreatePasswordUiMethodFromPemCallback(::pem_password_cb* callback)
@@ -114,6 +116,37 @@ bool Battlenet::SslContext::Initialize()
if (sk_X509_num(certs) > 0)
{
X509* cert = sk_X509_shift(certs);
+
+ _usesDevWildcardCertificate = [&]
+ {
+ X509_NAME const* nm = X509_get_subject_name(cert);
+ int32 lastpos = -1;
+ while (true)
+ {
+ lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos);
+ if (lastpos == -1)
+ break;
+
+ X509_NAME_ENTRY* e = X509_NAME_get_entry(nm, lastpos);
+ if (!e)
+ continue;
+
+ ASN1_STRING* text = X509_NAME_ENTRY_get_data(e);
+ if (!text)
+ continue;
+
+ unsigned char* utf8TextRaw = nullptr;
+ if (int utf8Length = ASN1_STRING_to_UTF8(&utf8TextRaw, text); utf8Length >= 0)
+ {
+ auto utf8Text = Trinity::make_unique_ptr_with_deleter(utf8TextRaw, [](unsigned char* ptr) { ::OPENSSL_free(ptr); });
+ if (std::string_view(reinterpret_cast<char const*>(utf8Text.get()), utf8Length) == "*.*")
+ return true;
+ }
+ }
+
+ return false;
+ }();
+
SSL_CTX_use_cert_and_key(nativeContext, cert, key, certs, 1);
}
diff --git a/src/server/bnetserver/Server/SslContext.h b/src/server/bnetserver/Server/SslContext.h
index 470deffd97e..330c0db221b 100644
--- a/src/server/bnetserver/Server/SslContext.h
+++ b/src/server/bnetserver/Server/SslContext.h
@@ -28,6 +28,11 @@ namespace Battlenet
static bool Initialize();
static boost::asio::ssl::context& instance();
+
+ static bool UsesDevWildcardCertificate() { return _usesDevWildcardCertificate; }
+
+ private:
+ static bool _usesDevWildcardCertificate;
};
}
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 90456bb9db3..07d40b0c518 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -468,7 +468,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
bool hasMoveCurveID = createProperties && createProperties->MoveCurveId != 0;
bool hasAreaTriggerSphere = shape.IsSphere();
bool hasAreaTriggerBox = shape.IsBox();
- bool hasAreaTriggerPolygon = createProperties && shape.IsPolygon();
+ bool hasAreaTriggerPolygon = shape.IsPolygon();
bool hasAreaTriggerCylinder = shape.IsCylinder();
bool hasDisk = shape.IsDisk();
bool hasBoundedPlane = shape.IsBoundedPlane();
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 6e0ea087591..198ff620cd0 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -15431,7 +15431,7 @@ bool Player::SatisfyQuestRace(Quest const* qInfo, bool msg) const
return true;
}
-bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) const
+bool Player::SatisfyQuestMinReputation(Quest const* qInfo, bool msg) const
{
uint32 fIdMin = qInfo->GetRequiredMinRepFaction(); //Min required rep
if (fIdMin && GetReputationMgr().GetReputation(fIdMin) < qInfo->GetRequiredMinRepValue())
@@ -15444,7 +15444,11 @@ bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) const
}
return false;
}
+ return true;
+}
+bool Player::SatisfyQuestMaxReputation(Quest const* qInfo, bool msg) const
+{
uint32 fIdMax = qInfo->GetRequiredMaxRepFaction(); //Max required rep
if (fIdMax && GetReputationMgr().GetReputation(fIdMax) >= qInfo->GetRequiredMaxRepValue())
{
@@ -15460,6 +15464,11 @@ bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) const
return true;
}
+bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) const
+{
+ return SatisfyQuestMinReputation(qInfo, msg) && SatisfyQuestMaxReputation(qInfo, msg);
+}
+
bool Player::SatisfyQuestStatus(Quest const* qInfo, bool msg) const
{
if (GetQuestStatus(qInfo->GetQuestId()) == QUEST_STATUS_REWARDED)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index c1d90e42754..c2f8df1f92e 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -718,7 +718,6 @@ enum ChildEquipmentSlots
CHILD_EQUIPMENT_SLOT_END = 141,
};
-// slots past 214 are guessed (unused in client)
enum EquipableSpellSlots
{
EQUIPABLE_SPELL_OFFENSIVE_SLOT1 = 211,
@@ -1556,6 +1555,8 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
bool SatisfyQuestDependentBreadcrumbQuests(Quest const* qInfo, bool msg) const;
bool SatisfyQuestClass(Quest const* qInfo, bool msg) const;
bool SatisfyQuestRace(Quest const* qInfo, bool msg) const;
+ bool SatisfyQuestMinReputation(Quest const* qInfo, bool msg) const;
+ bool SatisfyQuestMaxReputation(Quest const* qInfo, bool msg) const;
bool SatisfyQuestReputation(Quest const* qInfo, bool msg) const;
bool SatisfyQuestStatus(Quest const* qInfo, bool msg) const;
bool SatisfyQuestConditions(Quest const* qInfo, bool msg) const;
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 04b6792ba7f..3c086d612ec 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -625,7 +625,6 @@ void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty&
if (!receiver->IsAlive())
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::Dead);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::DeadToRecipient, quest);
continue;
}
@@ -634,14 +633,12 @@ void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty&
case QUEST_STATUS_REWARDED:
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::AlreadyDone);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::AlreadyDoneToRecipient, quest);
continue;
}
case QUEST_STATUS_INCOMPLETE:
case QUEST_STATUS_COMPLETE:
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::OnQuest);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::OnQuestToRecipient, quest);
continue;
}
default:
@@ -651,70 +648,18 @@ void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty&
if (!receiver->SatisfyQuestLog(false))
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::LogFull);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::LogFullToRecipient, quest);
continue;
}
if (!receiver->SatisfyQuestDay(quest, false))
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::AlreadyDone);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::AlreadyDoneToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestMinLevel(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::LowLevel);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::LowLevelToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestMaxLevel(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::HighLevel);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::HighLevelToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestClass(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::Class);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::ClassToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestRace(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::Race);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::RaceToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestReputation(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::LowFaction);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::LowFactionToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestDependentQuests(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::Prerequisite);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::PrerequisiteToRecipient, quest);
- continue;
- }
-
- if (!receiver->SatisfyQuestExpansion(quest, false))
- {
- sender->SendPushToPartyResponse(receiver, QuestPushReason::Expansion);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::ExpansionToRecipient, quest);
continue;
}
if (!receiver->CanTakeQuest(quest, false))
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::Invalid);
- receiver->SendPushToPartyResponse(sender, QuestPushReason::InvalidToRecipient, quest);
continue;
}
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index a518302143a..09227d689cd 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -76,46 +76,19 @@ enum class QuestPushReason : uint8
{
Success = 0, // "Sharing quest with %s..."
Invalid = 1, // "%s is not eligible for that quest"
- InvalidToRecipient = 2, // "%s's attempt to share quest "%s" failed. You are not eligible for that quest."
- Accepted = 3, // "%s has accepted your quest"
- Declined = 4, // "%s has declined your quest"
+ Accepted = 2, // "%s's attempt to share quest "%s" failed. You are not eligible for that quest."
+ Declined = 3, // "%s has declined your quest"
+ TooFar = 4, // "%s is too far away to receive your quest"
Busy = 5, // "%s is busy"
Dead = 6, // "%s is dead."
- DeadToRecipient = 7, // "%s's attempt to share quest "%s" failed. You are dead."
- LogFull = 8, // "%s's quest log is full"
- LogFullToRecipient = 9, // "%s's attempt to share quest "%s" failed. Your quest log is full."
- OnQuest = 10, // "%s is already on that quest"
- OnQuestToRecipient = 11, // "%s's attempt to share quest "%s" failed. You are already on that quest."
- AlreadyDone = 12, // "%s has completed that quest"
- AlreadyDoneToRecipient = 13, // "%s's attempt to share quest "%s" failed. You have completed that quest."
- NotDaily = 14, // "That quest cannot be shared today"
- TimerExpired = 15, // "Quest sharing timer has expired"
- NotInParty = 16, // "You are not in a party"
- DifferentServerDaily = 17, // "%s is not eligible for that quest today"
- DifferentServerDailyToRecipient = 18, // "%s's attempt to share quest "%s" failed. You are not eligible for that quest today."
- NotAllowed = 19, // "That quest cannot be shared"
- Prerequisite = 20, // "%s hasn't completed all of the prerequisite quests required for that quest."
- PrerequisiteToRecipient = 21, // "%s's attempt to share quest "%s" failed. You must complete all of the prerequisite quests first."
- LowLevel = 22, // "%s is too low level for that quest."
- LowLevelToRecipient = 23, // "%s's attempt to share quest "%s" failed. You are too low level for that quest."
- HighLevel = 24, // "%s is too high level for that quest."
- HighLevelToRecipient = 25, // "%s's attempt to share quest "%s" failed. You are too high level for that quest."
- Class = 26, // "%s is the wrong class for that quest."
- ClassToRecipient = 27, // "%s's attempt to share quest "%s" failed. You are the wrong class for that quest."
- Race = 28, // "%s is the wrong race for that quest."
- RaceToRecipient = 29, // "%s's attempt to share quest "%s" failed. You are the wrong race for that quest."
- LowFaction = 30, // "%s's reputation is too low for that quest."
- LowFactionToRecipient = 31, // "%s's attempt to share quest "%s" failed. Your reputation is too low for that quest."
- Expansion = 32, // "%s doesn't own the required expansion for that quest."
- ExpansionToRecipient = 33, // "%s's attempt to share quest "%s" failed. You do not own the required expansion for that quest."
- NotGarrisonOwner = 34, // "%s must own a garrison to accept that quest."
- NotGarrisonOwnerToRecipient = 35, // "%s's attempt to share quest "%s" failed. You must own a garrison to accept that quest."
- WrongCovenant = 36, // "%s is in the wrong covenant for that quest."
- WrongCovenantToRecipient = 37, // "%s's attempt to share quest "%s" failed. You are in the wrong covenant for that quest."
- NewPlayerExperience = 38, // "%s must complete Exile's Reach to accept that quest."
- NewPlayerExperienceToRecipient = 39, // "%s's attempt to share quest "%s" failed. You must complete Exile's Reach to accept that quest."
- WrongFaction = 40, // "%s is the wrong faction for that quest."
- WrongFactionToRecipient = 41 // "%s's attempt to share quest "%s" failed. You are the wrong faction for that quest."
+ LogFull = 7, // "%s's quest log is full"
+ OnQuest = 8, // "%s is already on that quest"
+ AlreadyDone = 9, // "%s has completed that quest"
+ NotDaily = 10, // "That quest cannot be shared today."
+ TimerExpired = 11, // "Quest sharing timer has expired"
+ NotInParty = 12, // "You are not in a party"
+ DifferentServerDaily = 13, // "%s is not eligible for that quest today."
+ NotAllowed = 14 // "That quest cannot be shared."
};
enum QuestTradeSkill
diff --git a/src/server/game/Quests/enuminfo_QuestDef.cpp b/src/server/game/Quests/enuminfo_QuestDef.cpp
index 594b5e7730e..b61233b2329 100644
--- a/src/server/game/Quests/enuminfo_QuestDef.cpp
+++ b/src/server/game/Quests/enuminfo_QuestDef.cpp
@@ -108,52 +108,24 @@ TC_API_EXPORT EnumText EnumUtils<QuestPushReason>::ToString(QuestPushReason valu
{
case QuestPushReason::Success: return { "Success", "Success", "\042Sharing quest with %s...\042" };
case QuestPushReason::Invalid: return { "Invalid", "Invalid", "\042%s is not eligible for that quest\042" };
- case QuestPushReason::InvalidToRecipient: return { "InvalidToRecipient", "InvalidToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are not eligible for that quest.\042" };
case QuestPushReason::Accepted: return { "Accepted", "Accepted", "\042%s has accepted your quest\042" };
case QuestPushReason::Declined: return { "Declined", "Declined", "\042%s has declined your quest\042" };
case QuestPushReason::Busy: return { "Busy", "Busy", "\042%s is busy\042" };
case QuestPushReason::Dead: return { "Dead", "Dead", "\042%s is dead.\042" };
- case QuestPushReason::DeadToRecipient: return { "DeadToRecipient", "DeadToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are dead.\042" };
case QuestPushReason::LogFull: return { "LogFull", "LogFull", "\042%s's quest log is full\042" };
- case QuestPushReason::LogFullToRecipient: return { "LogFullToRecipient", "LogFullToRecipient", "\042%s's attempt to share quest \042%s\042 failed. Your quest log is full.\042" };
case QuestPushReason::OnQuest: return { "OnQuest", "OnQuest", "\042%s is already on that quest\042" };
- case QuestPushReason::OnQuestToRecipient: return { "OnQuestToRecipient", "OnQuestToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are already on that quest.\042" };
case QuestPushReason::AlreadyDone: return { "AlreadyDone", "AlreadyDone", "\042%s has completed that quest\042" };
- case QuestPushReason::AlreadyDoneToRecipient: return { "AlreadyDoneToRecipient", "AlreadyDoneToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You have completed that quest.\042" };
case QuestPushReason::NotDaily: return { "NotDaily", "NotDaily", "\042That quest cannot be shared today\042" };
case QuestPushReason::TimerExpired: return { "TimerExpired", "TimerExpired", "\042Quest sharing timer has expired\042" };
case QuestPushReason::NotInParty: return { "NotInParty", "NotInParty", "\042You are not in a party\042" };
case QuestPushReason::DifferentServerDaily: return { "DifferentServerDaily", "DifferentServerDaily", "\042%s is not eligible for that quest today\042" };
- case QuestPushReason::DifferentServerDailyToRecipient: return { "DifferentServerDailyToRecipient", "DifferentServerDailyToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are not eligible for that quest today.\042" };
case QuestPushReason::NotAllowed: return { "NotAllowed", "NotAllowed", "\042That quest cannot be shared\042" };
- case QuestPushReason::Prerequisite: return { "Prerequisite", "Prerequisite", "\042%s hasn't completed all of the prerequisite quests required for that quest.\042" };
- case QuestPushReason::PrerequisiteToRecipient: return { "PrerequisiteToRecipient", "PrerequisiteToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You must complete all of the prerequisite quests first.\042" };
- case QuestPushReason::LowLevel: return { "LowLevel", "LowLevel", "\042%s is too low level for that quest.\042" };
- case QuestPushReason::LowLevelToRecipient: return { "LowLevelToRecipient", "LowLevelToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are too low level for that quest.\042" };
- case QuestPushReason::HighLevel: return { "HighLevel", "HighLevel", "\042%s is too high level for that quest.\042" };
- case QuestPushReason::HighLevelToRecipient: return { "HighLevelToRecipient", "HighLevelToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are too high level for that quest.\042" };
- case QuestPushReason::Class: return { "Class", "Class", "\042%s is the wrong class for that quest.\042" };
- case QuestPushReason::ClassToRecipient: return { "ClassToRecipient", "ClassToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are the wrong class for that quest.\042" };
- case QuestPushReason::Race: return { "Race", "Race", "\042%s is the wrong race for that quest.\042" };
- case QuestPushReason::RaceToRecipient: return { "RaceToRecipient", "RaceToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are the wrong race for that quest.\042" };
- case QuestPushReason::LowFaction: return { "LowFaction", "LowFaction", "\042%s's reputation is too low for that quest.\042" };
- case QuestPushReason::LowFactionToRecipient: return { "LowFactionToRecipient", "LowFactionToRecipient", "\042%s's attempt to share quest \042%s\042 failed. Your reputation is too low for that quest.\042" };
- case QuestPushReason::Expansion: return { "Expansion", "Expansion", "\042%s doesn't own the required expansion for that quest.\042" };
- case QuestPushReason::ExpansionToRecipient: return { "ExpansionToRecipient", "ExpansionToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You do not own the required expansion for that quest.\042" };
- case QuestPushReason::NotGarrisonOwner: return { "NotGarrisonOwner", "NotGarrisonOwner", "\042%s must own a garrison to accept that quest.\042" };
- case QuestPushReason::NotGarrisonOwnerToRecipient: return { "NotGarrisonOwnerToRecipient", "NotGarrisonOwnerToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You must own a garrison to accept that quest.\042" };
- case QuestPushReason::WrongCovenant: return { "WrongCovenant", "WrongCovenant", "\042%s is in the wrong covenant for that quest.\042" };
- case QuestPushReason::WrongCovenantToRecipient: return { "WrongCovenantToRecipient", "WrongCovenantToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are in the wrong covenant for that quest.\042" };
- case QuestPushReason::NewPlayerExperience: return { "NewPlayerExperience", "NewPlayerExperience", "\042%s must complete Exile's Reach to accept that quest.\042" };
- case QuestPushReason::NewPlayerExperienceToRecipient: return { "NewPlayerExperienceToRecipient", "NewPlayerExperienceToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You must complete Exile's Reach to accept that quest.\042" };
- case QuestPushReason::WrongFaction: return { "WrongFaction", "WrongFaction", "\042%s is the wrong faction for that quest.\042" };
- case QuestPushReason::WrongFactionToRecipient: return { "WrongFactionToRecipient", "WrongFactionToRecipient", "\042%s's attempt to share quest \042%s\042 failed. You are the wrong faction for that quest.\042" };
default: throw std::out_of_range("value");
}
}
template <>
-TC_API_EXPORT size_t EnumUtils<QuestPushReason>::Count() { return 42; }
+TC_API_EXPORT size_t EnumUtils<QuestPushReason>::Count() { return 15; }
template <>
TC_API_EXPORT QuestPushReason EnumUtils<QuestPushReason>::FromIndex(size_t index)
@@ -162,46 +134,19 @@ TC_API_EXPORT QuestPushReason EnumUtils<QuestPushReason>::FromIndex(size_t index
{
case 0: return QuestPushReason::Success;
case 1: return QuestPushReason::Invalid;
- case 2: return QuestPushReason::InvalidToRecipient;
- case 3: return QuestPushReason::Accepted;
- case 4: return QuestPushReason::Declined;
+ case 2: return QuestPushReason::Accepted;
+ case 3: return QuestPushReason::Declined;
+ case 4: return QuestPushReason::TooFar;
case 5: return QuestPushReason::Busy;
case 6: return QuestPushReason::Dead;
- case 7: return QuestPushReason::DeadToRecipient;
- case 8: return QuestPushReason::LogFull;
- case 9: return QuestPushReason::LogFullToRecipient;
- case 10: return QuestPushReason::OnQuest;
- case 11: return QuestPushReason::OnQuestToRecipient;
- case 12: return QuestPushReason::AlreadyDone;
- case 13: return QuestPushReason::AlreadyDoneToRecipient;
- case 14: return QuestPushReason::NotDaily;
- case 15: return QuestPushReason::TimerExpired;
- case 16: return QuestPushReason::NotInParty;
- case 17: return QuestPushReason::DifferentServerDaily;
- case 18: return QuestPushReason::DifferentServerDailyToRecipient;
- case 19: return QuestPushReason::NotAllowed;
- case 20: return QuestPushReason::Prerequisite;
- case 21: return QuestPushReason::PrerequisiteToRecipient;
- case 22: return QuestPushReason::LowLevel;
- case 23: return QuestPushReason::LowLevelToRecipient;
- case 24: return QuestPushReason::HighLevel;
- case 25: return QuestPushReason::HighLevelToRecipient;
- case 26: return QuestPushReason::Class;
- case 27: return QuestPushReason::ClassToRecipient;
- case 28: return QuestPushReason::Race;
- case 29: return QuestPushReason::RaceToRecipient;
- case 30: return QuestPushReason::LowFaction;
- case 31: return QuestPushReason::LowFactionToRecipient;
- case 32: return QuestPushReason::Expansion;
- case 33: return QuestPushReason::ExpansionToRecipient;
- case 34: return QuestPushReason::NotGarrisonOwner;
- case 35: return QuestPushReason::NotGarrisonOwnerToRecipient;
- case 36: return QuestPushReason::WrongCovenant;
- case 37: return QuestPushReason::WrongCovenantToRecipient;
- case 38: return QuestPushReason::NewPlayerExperience;
- case 39: return QuestPushReason::NewPlayerExperienceToRecipient;
- case 40: return QuestPushReason::WrongFaction;
- case 41: return QuestPushReason::WrongFactionToRecipient;
+ case 7: return QuestPushReason::LogFull;
+ case 8: return QuestPushReason::OnQuest;
+ case 9: return QuestPushReason::AlreadyDone;
+ case 10: return QuestPushReason::NotDaily;
+ case 11: return QuestPushReason::TimerExpired;
+ case 12: return QuestPushReason::NotInParty;
+ case 13: return QuestPushReason::DifferentServerDaily;
+ case 14: return QuestPushReason::NotAllowed;
default: throw std::out_of_range("index");
}
}
@@ -213,46 +158,19 @@ TC_API_EXPORT size_t EnumUtils<QuestPushReason>::ToIndex(QuestPushReason value)
{
case QuestPushReason::Success: return 0;
case QuestPushReason::Invalid: return 1;
- case QuestPushReason::InvalidToRecipient: return 2;
- case QuestPushReason::Accepted: return 3;
- case QuestPushReason::Declined: return 4;
+ case QuestPushReason::Accepted: return 2;
+ case QuestPushReason::Declined: return 3;
+ case QuestPushReason::TooFar: return 4;
case QuestPushReason::Busy: return 5;
case QuestPushReason::Dead: return 6;
- case QuestPushReason::DeadToRecipient: return 7;
- case QuestPushReason::LogFull: return 8;
- case QuestPushReason::LogFullToRecipient: return 9;
- case QuestPushReason::OnQuest: return 10;
- case QuestPushReason::OnQuestToRecipient: return 11;
- case QuestPushReason::AlreadyDone: return 12;
- case QuestPushReason::AlreadyDoneToRecipient: return 13;
- case QuestPushReason::NotDaily: return 14;
- case QuestPushReason::TimerExpired: return 15;
- case QuestPushReason::NotInParty: return 16;
- case QuestPushReason::DifferentServerDaily: return 17;
- case QuestPushReason::DifferentServerDailyToRecipient: return 18;
- case QuestPushReason::NotAllowed: return 19;
- case QuestPushReason::Prerequisite: return 20;
- case QuestPushReason::PrerequisiteToRecipient: return 21;
- case QuestPushReason::LowLevel: return 22;
- case QuestPushReason::LowLevelToRecipient: return 23;
- case QuestPushReason::HighLevel: return 24;
- case QuestPushReason::HighLevelToRecipient: return 25;
- case QuestPushReason::Class: return 26;
- case QuestPushReason::ClassToRecipient: return 27;
- case QuestPushReason::Race: return 28;
- case QuestPushReason::RaceToRecipient: return 29;
- case QuestPushReason::LowFaction: return 30;
- case QuestPushReason::LowFactionToRecipient: return 31;
- case QuestPushReason::Expansion: return 32;
- case QuestPushReason::ExpansionToRecipient: return 33;
- case QuestPushReason::NotGarrisonOwner: return 34;
- case QuestPushReason::NotGarrisonOwnerToRecipient: return 35;
- case QuestPushReason::WrongCovenant: return 36;
- case QuestPushReason::WrongCovenantToRecipient: return 37;
- case QuestPushReason::NewPlayerExperience: return 38;
- case QuestPushReason::NewPlayerExperienceToRecipient: return 39;
- case QuestPushReason::WrongFaction: return 40;
- case QuestPushReason::WrongFactionToRecipient: return 41;
+ case QuestPushReason::LogFull: return 7;
+ case QuestPushReason::OnQuest: return 8;
+ case QuestPushReason::AlreadyDone: return 9;
+ case QuestPushReason::NotDaily: return 10;
+ case QuestPushReason::TimerExpired: return 11;
+ case QuestPushReason::NotInParty: return 12;
+ case QuestPushReason::DifferentServerDaily: return 13;
+ case QuestPushReason::NotAllowed: return 14;
default: throw std::out_of_range("value");
}
}
diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp
index 59131fa2c4a..deebdf14345 100644
--- a/src/server/game/Server/Packets/SystemPackets.cpp
+++ b/src/server/game/Server/Packets/SystemPackets.cpp
@@ -205,7 +205,7 @@ WorldPacket const* FeatureSystemStatusGlueScreen::Write()
_worldPacket.WriteBit(KioskModeEnabled);
_worldPacket.WriteBit(CompetitiveModeEnabled);
- _worldPacket.WriteBit(false); // unused, 10.0.2
+ _worldPacket.WriteBit(IsBoostEnabled);
_worldPacket.WriteBit(TrialBoostEnabled);
_worldPacket.WriteBit(TokenBalanceEnabled);
_worldPacket.WriteBit(LiveRegionCharacterListEnabled);
@@ -254,7 +254,7 @@ WorldPacket const* FeatureSystemStatusGlueScreen::Write()
_worldPacket << PlayerNameQueryInterval;
_worldPacket << uint32(DebugTimeEvents.size());
_worldPacket << int32(Unused1007);
- _worldPacket << int32(Unused440);
+ _worldPacket << int32(EventRealmQueues);
if (LaunchETA)
_worldPacket << int32(*LaunchETA);
diff --git a/src/server/game/Server/Packets/SystemPackets.h b/src/server/game/Server/Packets/SystemPackets.h
index aebb3e658c9..88ab5ee2433 100644
--- a/src/server/game/Server/Packets/SystemPackets.h
+++ b/src/server/game/Server/Packets/SystemPackets.h
@@ -195,6 +195,7 @@ namespace WorldPackets
bool IsExpansionPreorderInStore = false; // NYI
bool KioskModeEnabled = false; // NYI
bool CompetitiveModeEnabled = false; // NYI
+ bool IsBoostEnabled = false; // classic only
bool TrialBoostEnabled = false; // NYI
bool TokenBalanceEnabled = false; // NYI
bool LiveRegionCharacterListEnabled = false; // NYI
@@ -207,7 +208,7 @@ namespace WorldPackets
bool Unused1000 = false;
bool AccountSaveDataExportEnabled = false;
bool AccountLockedByExport = false;
- bool IsNameReservationEnabled = false; // NYI
+ bool IsNameReservationEnabled = false; // NYI classic only
Optional<EuropaTicketConfig> EuropaTicketSystemStatus;
std::vector<int32> LiveRegionCharacterCopySourceRegions;
uint32 TokenPollTimeSeconds = 0; // NYI
@@ -227,7 +228,7 @@ namespace WorldPackets
Optional<int32> LaunchETA;
std::vector<DebugTimeEventInfo> DebugTimeEvents;
int32 Unused1007 = 0;
- int32 Unused440 = 0;
+ uint32 EventRealmQueues = 0;
Optional<std::string> RealmHiddenAlert;
};
diff --git a/src/server/shared/Networking/Http/HttpSocket.h b/src/server/shared/Networking/Http/HttpSocket.h
index 2bd18efd565..9a333a8e779 100644
--- a/src/server/shared/Networking/Http/HttpSocket.h
+++ b/src/server/shared/Networking/Http/HttpSocket.h
@@ -53,7 +53,8 @@ class Socket : public BaseSocket<Derived, Impl::BoostBeastSocketWrapper>
using SocketBase = BaseSocket<Derived, Impl::BoostBeastSocketWrapper>;
public:
- explicit Socket(boost::asio::ip::tcp::socket&& socket)
+ template<typename... Args>
+ explicit Socket(boost::asio::ip::tcp::socket&& socket, Args&&...)
: SocketBase(std::move(socket)) { }
Socket(Socket const& other) = delete;