diff options
-rw-r--r-- | src/common/DataStores/DB2FileLoader.cpp | 12 | ||||
-rw-r--r-- | src/server/bnetserver/REST/LoginHttpSession.cpp | 62 | ||||
-rw-r--r-- | src/server/bnetserver/REST/LoginHttpSession.h | 49 | ||||
-rw-r--r-- | src/server/bnetserver/REST/LoginRESTService.cpp | 28 | ||||
-rw-r--r-- | src/server/bnetserver/REST/LoginRESTService.h | 14 | ||||
-rw-r--r-- | src/server/bnetserver/Server/Session.cpp | 3 | ||||
-rw-r--r-- | src/server/bnetserver/Server/SslContext.cpp | 33 | ||||
-rw-r--r-- | src/server/bnetserver/Server/SslContext.h | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 3 | ||||
-rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 55 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.h | 49 | ||||
-rw-r--r-- | src/server/game/Quests/enuminfo_QuestDef.cpp | 128 | ||||
-rw-r--r-- | src/server/game/Server/Packets/SystemPackets.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Server/Packets/SystemPackets.h | 5 | ||||
-rw-r--r-- | src/server/shared/Networking/Http/HttpSocket.h | 3 |
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; |