mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
EULA dialog implementation
Display the EULA (fetched from masterserver), which the end user MUST accept before they can make use of the multiplayer features of R5Reloaded. NOTE: user doesn't need to agree to this to use the listenserver.
This commit is contained in:
parent
5d2a331170
commit
22c82d6f1d
@ -241,6 +241,8 @@ ConVar* con_suggest_showflags = nullptr;
|
||||
|
||||
ConVar* origin_disconnectWhenOffline = nullptr;
|
||||
ConVar* discord_updatePresence = nullptr;
|
||||
ConVar* eula_version = nullptr;
|
||||
ConVar* eula_version_accepted = nullptr;
|
||||
|
||||
ConVar* settings_reflex = nullptr;
|
||||
ConVar* serverbrowser_hideEmptyServers = nullptr;
|
||||
@ -560,6 +562,8 @@ void ConVar_InitShipped(void)
|
||||
#ifndef DEDICATED
|
||||
origin_disconnectWhenOffline = g_pCVar->FindVar("origin_disconnectWhenOffline");
|
||||
discord_updatePresence = g_pCVar->FindVar("discord_updatePresence");
|
||||
eula_version = g_pCVar->FindVar("eula_version");
|
||||
eula_version_accepted = g_pCVar->FindVar("eula_version_accepted");
|
||||
#endif // !DEDICATED
|
||||
mp_gamemode = g_pCVar->FindVar("mp_gamemode");
|
||||
ip_cvar = g_pCVar->FindVar("ip");
|
||||
|
@ -233,6 +233,8 @@ extern ConVar* con_suggest_showflags;
|
||||
|
||||
extern ConVar* origin_disconnectWhenOffline;
|
||||
extern ConVar* discord_updatePresence;
|
||||
extern ConVar* eula_version;
|
||||
extern ConVar* eula_version_accepted;
|
||||
#endif // !DEDICATED
|
||||
//-------------------------------------------------------------------------
|
||||
// FILESYSTEM |
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "vgui/vgui_baseui_interface.h"
|
||||
#include "vgui/vgui_debugpanel.h"
|
||||
#include "vgui/vgui_fpspanel.h"
|
||||
#include "vgui/vgui_controls/RichText.h"
|
||||
#include "vguimatsurface/MatSystemSurface.h"
|
||||
#include "engine/client/vengineclient_impl.h"
|
||||
#include "engine/client/cdll_engine_int.h"
|
||||
@ -515,6 +516,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
|
||||
// VGui
|
||||
REGISTER(VEngineVGui); // REGISTER CLIENT ONLY!
|
||||
REGISTER(VFPSPanel); // REGISTER CLIENT ONLY!
|
||||
REGISTER(VVGUIRichText); // REGISTER CLIENT ONLY!
|
||||
REGISTER(VMatSystemSurface);
|
||||
|
||||
// Client
|
||||
|
@ -1,4 +1,4 @@
|
||||
//=============================================================================//
|
||||
//=============================================================================//
|
||||
//
|
||||
// Purpose: Expose native code to VScript API
|
||||
//
|
||||
@ -290,6 +290,25 @@ namespace VScriptCode
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
SQRESULT GetEULAContents(HSQUIRRELVM v)
|
||||
{
|
||||
MSEulaData_t eulaData;
|
||||
if (g_pMasterServer->GetEULA(eulaData))
|
||||
{
|
||||
// set EULA version cvar to the newly fetched EULA version
|
||||
eula_version->SetValue(eulaData.version);
|
||||
|
||||
sq_pushstring(v, eulaData.contents.c_str(), -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning(eDLL_T::UI, "Failed to load EULA Data\n");
|
||||
sq_pushstring(v, "Failed to load EULA Data", -1);
|
||||
}
|
||||
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: connect to server from native server browser entries
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -400,6 +419,7 @@ void Script_RegisterUIFunctions(CSquirrelVM* s)
|
||||
|
||||
// Misc main menu functions
|
||||
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetPromoData, "Gets promo data for specified slot type", "string", "int");
|
||||
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetEULAContents, "Gets EULA contents from masterserver", "string", "");
|
||||
|
||||
// Functions for connecting to servers
|
||||
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToServer, "Joins server by ip address and encryption key", "void", "string, string");
|
||||
|
@ -117,6 +117,7 @@ bool CPylon::GetServerByToken(NetGameServer_t& outGameServer,
|
||||
requestJson.SetObject();
|
||||
|
||||
rapidjson::Document::AllocatorType& allocator = requestJson.GetAllocator();
|
||||
requestJson.AddMember("version", rapidjson::Value(SDK_VERSION, requestJson.GetAllocator()), allocator);
|
||||
requestJson.AddMember("token", rapidjson::Value(token.c_str(), requestJson.GetAllocator()), allocator);
|
||||
|
||||
rapidjson::Document responseJson;
|
||||
@ -340,6 +341,60 @@ bool CPylon::AuthForConnection(const uint64_t nucleusId, const char* ipAddress,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ValidateEULAData(const rapidjson::Document& doc)
|
||||
{
|
||||
if (!doc.HasMember("data") || !doc["data"].IsObject())
|
||||
return false;
|
||||
|
||||
const rapidjson::Value& data = doc["data"];
|
||||
|
||||
if (!data.HasMember("version") || !data["version"].IsInt())
|
||||
return false;
|
||||
|
||||
if (!data.HasMember("lang") || !data["lang"].IsString())
|
||||
return false;
|
||||
|
||||
if (!data.HasMember("contents") || !data["contents"].IsString())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsEULAUpToDate()
|
||||
{
|
||||
return (eula_version_accepted->GetInt() == eula_version->GetInt());
|
||||
}
|
||||
|
||||
bool CPylon::GetEULA(MSEulaData_t& outData) const
|
||||
{
|
||||
rapidjson::Document requestJson;
|
||||
requestJson.SetObject();
|
||||
|
||||
rapidjson::Document responseJson;
|
||||
|
||||
CURLINFO status;
|
||||
|
||||
string outMessage;
|
||||
|
||||
if (!SendRequest("/eula", requestJson, responseJson, outMessage, status, "eula fetch error", false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateEULAData(responseJson))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const rapidjson::Value& data = responseJson["data"];
|
||||
|
||||
outData.version = data["version"].GetInt();
|
||||
outData.language = data["lang"].GetString();
|
||||
outData.contents = data["contents"].GetString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends request to Pylon Master Server.
|
||||
// Input : *endpoint -
|
||||
@ -347,11 +402,19 @@ bool CPylon::AuthForConnection(const uint64_t nucleusId, const char* ipAddress,
|
||||
// &responseJson -
|
||||
// &outMessage -
|
||||
// &status -
|
||||
// checkEula -
|
||||
// Output : True on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::SendRequest(const char* endpoint, const rapidjson::Document& requestJson,
|
||||
rapidjson::Document& responseJson, string& outMessage, CURLINFO& status, const char* errorText) const
|
||||
rapidjson::Document& responseJson, string& outMessage, CURLINFO& status,
|
||||
const char* errorText, const bool checkEula) const
|
||||
{
|
||||
if (checkEula && !IsEULAUpToDate())
|
||||
{
|
||||
outMessage = "EULA not accepted";
|
||||
return false;
|
||||
}
|
||||
|
||||
rapidjson::StringBuffer stringBuffer;
|
||||
JSON_DocumentToBufferDeserialize(requestJson, stringBuffer);
|
||||
|
||||
|
@ -4,6 +4,13 @@
|
||||
#include "serverlisting.h"
|
||||
#include "localize/ilocalize.h"
|
||||
|
||||
struct MSEulaData_t
|
||||
{
|
||||
int version;
|
||||
string language;
|
||||
string contents;
|
||||
};
|
||||
|
||||
class CPylon
|
||||
{
|
||||
public:
|
||||
@ -18,11 +25,13 @@ public:
|
||||
|
||||
bool AuthForConnection(const uint64_t nucleusId, const char* ipAddress, const char* authCode, string& outToken, string& outMessage) const;
|
||||
|
||||
bool GetEULA(MSEulaData_t& outData) const;
|
||||
|
||||
void ExtractError(const rapidjson::Document& resultBody, string& outMessage, CURLINFO status, const char* errorText = nullptr) const;
|
||||
void ExtractError(const string& response, string& outMessage, CURLINFO status, const char* messageText = nullptr) const;
|
||||
|
||||
void LogBody(const rapidjson::Document& responseJson) const;
|
||||
bool SendRequest(const char* endpoint, const rapidjson::Document& requestJson, rapidjson::Document& responseJson, string& outMessage, CURLINFO& status, const char* errorText = nullptr) const;
|
||||
bool SendRequest(const char* endpoint, const rapidjson::Document& requestJson, rapidjson::Document& responseJson, string& outMessage, CURLINFO& status, const char* errorText = nullptr, const bool checkEula = true) const;
|
||||
bool QueryServer(const char* endpoint, const char* request, string& outResponse, string& outMessage, CURLINFO& outStatus) const;
|
||||
|
||||
inline const string& GetCurrentToken() const { return m_Token; }
|
||||
|
@ -16,4 +16,9 @@ add_sources( SOURCE_GROUP "Debug"
|
||||
"vgui_fpspanel.h"
|
||||
)
|
||||
|
||||
add_sources( SOURCE_GROUP "vgui_controls"
|
||||
"vgui_controls/RichText.cpp"
|
||||
"vgui_controls/RichText.h"
|
||||
)
|
||||
|
||||
end_sources()
|
||||
|
56
r5dev/vgui/vgui_controls/RichText.cpp
Normal file
56
r5dev/vgui/vgui_controls/RichText.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: Implements all the functions exported by the GameUI dll.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include <core/stdafx.h>
|
||||
#include <tier1/cvar.h>
|
||||
#include <engine/sys_utils.h>
|
||||
#include <vgui/vgui_controls/RichText.h>
|
||||
#include <vguimatsurface/MatSystemSurface.h>
|
||||
|
||||
void RichText_SetText(vgui::RichText* thisptr, const char* text)
|
||||
{
|
||||
thisptr->SetText(text);
|
||||
}
|
||||
|
||||
void vgui::RichText::SetText(const char* text)
|
||||
{
|
||||
// Originally 4096, increased to 8192
|
||||
WCHAR unicode[VGUI_RICHTEXT_MAX_LEN];
|
||||
|
||||
if (text && *text)
|
||||
{
|
||||
if (text[0] == '#')
|
||||
{
|
||||
this->__vftable->ResolveLocalizedTextAndVariables(this, text, unicode, sizeof(unicode));
|
||||
this->__vftable->SetText(this, unicode);
|
||||
}
|
||||
else
|
||||
{
|
||||
unicode[0] = 0;
|
||||
MultiByteToWideChar(CP_UTF8, 0, text, -1, unicode, VGUI_RICHTEXT_MAX_LEN);
|
||||
unicode[VGUI_RICHTEXT_MAX_LEN - 1] = 0;
|
||||
this->__vftable->SetText(this, unicode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->__vftable->SetText(this, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void VVGUIRichText::Attach() const
|
||||
{
|
||||
DetourAttach((LPVOID*)&vgui_RichText_SetText, &RichText_SetText);
|
||||
}
|
||||
|
||||
void VVGUIRichText::Detach() const
|
||||
{
|
||||
DetourDetach((LPVOID*)&vgui_RichText_SetText, &RichText_SetText);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
50
r5dev/vgui/vgui_controls/RichText.h
Normal file
50
r5dev/vgui/vgui_controls/RichText.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include <engine/server/sv_main.h>
|
||||
#include <vguimatsurface/MatSystemSurface.h>
|
||||
|
||||
#define VGUI_RICHTEXT_MAX_LEN 8192
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class RichText;
|
||||
|
||||
struct vgui_RichText_vtbl
|
||||
{
|
||||
void* funcs_0[239];
|
||||
__int64(__fastcall* SetText)(vgui::RichText*, WCHAR*);
|
||||
void* funcs_780[43];
|
||||
__int64(__fastcall* ResolveLocalizedTextAndVariables)(vgui::RichText*, const CHAR*, WCHAR*, __int64);
|
||||
};
|
||||
|
||||
class RichText
|
||||
{
|
||||
public:
|
||||
vgui_RichText_vtbl* __vftable;
|
||||
|
||||
public:
|
||||
void SetText(const char* text);
|
||||
};
|
||||
};
|
||||
|
||||
/* ==== RICHTEXT ===================================================================================================================================================== */
|
||||
inline CMemory p_vgui_RichText_SetText;
|
||||
inline void(*vgui_RichText_SetText)(vgui::RichText* thisptr, const char* text);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class VVGUIRichText : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogFunAdr("vgui::RichText::SetText", p_vgui_RichText_SetText.GetPtr());
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
p_vgui_RichText_SetText = g_GameDll.FindPatternSIMD("40 53 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9");
|
||||
vgui_RichText_SetText = p_vgui_RichText_SetText.RCast<void(*)(vgui::RichText*, const char*)>();
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
virtual void GetCon(void) const { }
|
||||
virtual void Attach(void) const;
|
||||
virtual void Detach(void) const;
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
Loading…
x
Reference in New Issue
Block a user