From f18829a487ae696ae9691adbaeb556dca5a013f0 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 5 Apr 2024 19:35:41 +0200 Subject: [PATCH 001/113] Tier0: split CPU feature checks into multiple functions --- r5dev/tier0/cpu.cpp | 28 +++++++++++++++++++++++++++- r5dev/tier0/cpu.h | 5 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/r5dev/tier0/cpu.cpp b/r5dev/tier0/cpu.cpp index 7393b4bd..82df6979 100644 --- a/r5dev/tier0/cpu.cpp +++ b/r5dev/tier0/cpu.cpp @@ -575,7 +575,7 @@ const CPUInformation& GetCPUInformation(void) return pi; } -void CheckSystemCPU() +void CheckSystemCPUForSSE2() { const CPUInformation& pi = GetCPUInformation(); @@ -586,6 +586,12 @@ void CheckSystemCPU() TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); } } +} + +void CheckSystemCPUForSSE3() +{ + const CPUInformation& pi = GetCPUInformation(); + if (!pi.m_bSSE3) { if (MessageBoxA(NULL, "SSE3 is required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) @@ -593,6 +599,12 @@ void CheckSystemCPU() TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); } } +} + +void CheckSystemCPUForSupplementalSSE3() +{ + const CPUInformation& pi = GetCPUInformation(); + if (!pi.m_bSSSE3) { if (MessageBoxA(NULL, "SSSE3 (Supplemental SSE3 Instructions) is required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) @@ -600,6 +612,12 @@ void CheckSystemCPU() TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); } } +} + +void CheckSystemCPUForPopCount() +{ + const CPUInformation& pi = GetCPUInformation(); + if (!pi.m_bPOPCNT) { if (MessageBoxA(NULL, "POPCNT is required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) @@ -608,3 +626,11 @@ void CheckSystemCPU() } } } + +void CheckSystemCPU() +{ + CheckSystemCPUForSSE2(); + CheckSystemCPUForSSE3(); + CheckSystemCPUForSupplementalSSE3(); + CheckSystemCPUForPopCount(); +} diff --git a/r5dev/tier0/cpu.h b/r5dev/tier0/cpu.h index 4425c486..0e03beb4 100644 --- a/r5dev/tier0/cpu.h +++ b/r5dev/tier0/cpu.h @@ -130,6 +130,11 @@ const char* GetProcessorBrand(bool bRemovePadding); const CPUInformation& GetCPUInformation(void); +void CheckSystemCPUForSSE2(); +void CheckSystemCPUForSSE3(); +void CheckSystemCPUForSupplementalSSE3(); +void CheckSystemCPUForPopCount(); + void CheckSystemCPU(); #endif // CPU_H From 1052401824d1e60b5f46446cda9aa58737e9c73f Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 5 Apr 2024 19:36:38 +0200 Subject: [PATCH 002/113] ReVPK: fix undefined symbol CheckCPUforSSE2() was removed in commit 504d042e6095b24e125c7d38549db860b2d15a67, but ReVPK still needs to check for it. --- r5dev/revpk/revpk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/revpk/revpk.cpp b/r5dev/revpk/revpk.cpp index bdf5c40c..240d0aa9 100644 --- a/r5dev/revpk/revpk.cpp +++ b/r5dev/revpk/revpk.cpp @@ -49,7 +49,7 @@ CFileSystem_Stdio* FileSystem() //----------------------------------------------------------------------------- static void ReVPK_Init() { - CheckCPUforSSE2(); + CheckSystemCPUForSSE2(); g_CoreMsgVCallback = EngineLoggerSink; lzham_enable_fail_exceptions(true); From 001a8db6841fb631a21b77e1d9f961b8f42156da Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 5 Apr 2024 19:37:00 +0200 Subject: [PATCH 003/113] NetConsole: fix undefined symbol CheckCPUforSSE2() was removed in commit 504d042e6095b24e125c7d38549db860b2d15a67, but NetConsole still needs to check for it. --- r5dev/netconsole/netconsole.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/netconsole/netconsole.cpp b/r5dev/netconsole/netconsole.cpp index 7620fd28..fa46697c 100644 --- a/r5dev/netconsole/netconsole.cpp +++ b/r5dev/netconsole/netconsole.cpp @@ -453,7 +453,7 @@ bool CNetCon::IsConnected(void) //----------------------------------------------------------------------------- int main(int argc, char* argv[]) { - CheckCPUforSSE2(); + CheckSystemCPUForSSE2(); bool bEnableColor = false; From e198980be4f8b7939a922f7edbfd109440c44730 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 5 Apr 2024 19:38:10 +0200 Subject: [PATCH 004/113] ImGui: fix logger not fading in/out with alpha m_fadeAlpha should also be applied on the color logger. --- r5dev/gameui/IConsole.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/r5dev/gameui/IConsole.cpp b/r5dev/gameui/IConsole.cpp index 9bf9fb05..1da1103f 100644 --- a/r5dev/gameui/IConsole.cpp +++ b/r5dev/gameui/IConsole.cpp @@ -242,7 +242,7 @@ bool CConsole::DrawSurface(void) // Eliminate padding around logger child. This padding gets added when // ImGuiChildFlags_Border flag gets set. - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 1.f, 1.f }); numLoggerStyleVars++; + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 1.f, 1.f }); numLoggerStyleVars++; // if we use the legacy theme, also account for one extra space as the // legacy theme has an extra separator at the bottom of the logger. @@ -255,6 +255,7 @@ bool CConsole::DrawSurface(void) ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_OverlayHorizontalScrollbar; + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); numLoggerStyleVars++; ImGui::BeginChild(m_loggerLabel, ImVec2(0, -footerHeightReserve), loggerFlags, colorLoggerWindowFlags); // NOTE: scoped so the mutex releases after we have rendered. From 91d00d0ab35289da2f39af70eaa3ea23d0f54a8e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:56:08 +0200 Subject: [PATCH 005/113] ImGui: also take vertical scrollbar into account Show horizontal scrollbar when console text gets overlapped by the vertical scrollbar. --- r5dev/thirdparty/imgui/misc/imgui_logger.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/r5dev/thirdparty/imgui/misc/imgui_logger.cpp b/r5dev/thirdparty/imgui/misc/imgui_logger.cpp index 4e3721ed..88696a26 100644 --- a/r5dev/thirdparty/imgui/misc/imgui_logger.cpp +++ b/r5dev/thirdparty/imgui/misc/imgui_logger.cpp @@ -765,6 +765,7 @@ void CTextLogger::Render() ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); ImGuiWindow* const pWindow = ImGui::GetCurrentWindow(); + const ImGuiStyle& style = ImGui::GetStyle(); const ImGuiID activeID = ImGui::GetActiveID(); const ImGuiID hoveredID = ImGui::GetHoveredID(); @@ -878,7 +879,8 @@ void CTextLogger::Render() // This dummy is here to let Dear ImGui know where the last character of // the line had ended, so that it could properly process the horizontal // scrollbar - ImGui::Dummy(ImVec2((longest + 2), m_Lines.size() * m_CharAdvance.y)); + const float additional = pWindow->ScrollbarY ? style.ScrollbarSize : 0.0f; + ImGui::Dummy(ImVec2(longest + additional, m_Lines.size() * m_CharAdvance.y)); m_bScrolledToStart = ImGui::GetScrollX() == 0.0f; From b26ed2f7464ae7df5e9678db7537b227a999dfd7 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:24:47 +0200 Subject: [PATCH 006/113] Engine: implement encryption for RCON protocol RCON lacked encryption, added AES-CTR encryption on RCON frames. Slightly adjusted protocol to take this into account (sending nonces, encrypted data itself, etc). --- r5dev/common/callback.cpp | 3 +- r5dev/core/CMakeLists.txt | 10 +- r5dev/core/logger.cpp | 4 +- r5dev/engine/client/cl_rcon.cpp | 127 ++- r5dev/engine/client/cl_rcon.h | 7 +- r5dev/engine/host_state.cpp | 7 - r5dev/engine/net.h | 8 +- r5dev/engine/server/sv_rcon.cpp | 121 +-- r5dev/engine/server/sv_rcon.h | 22 +- r5dev/engine/shared/base_rcon.cpp | 152 ++- r5dev/engine/shared/base_rcon.h | 16 +- r5dev/engine/shared/shared_rcon.cpp | 317 +++++- r5dev/engine/shared/shared_rcon.h | 22 +- r5dev/netconsole/CMakeLists.txt | 11 +- r5dev/netconsole/netconsole.cpp | 65 +- r5dev/netconsole/netconsole.h | 6 +- r5dev/pluginsdk/CMakeLists.txt | 3 +- r5dev/protoc/CMakeLists.txt | 18 +- r5dev/protoc/cl_rcon.pb.cc | 489 ---------- r5dev/protoc/cl_rcon.pb.h | 530 ---------- r5dev/protoc/netcon.pb.cc | 1235 ++++++++++++++++++++++++ r5dev/protoc/netcon.pb.h | 1279 +++++++++++++++++++++++++ r5dev/protoc/sv_rcon.pb.cc | 485 ---------- r5dev/protoc/sv_rcon.pb.h | 529 ---------- r5dev/public/tier0/utility.h | 1 + r5dev/public/tier2/cryptutils.h | 26 + r5dev/resource/protobuf/cl_rcon.proto | 19 - r5dev/resource/protobuf/generate.bat | 3 +- r5dev/resource/protobuf/netcon.proto | 56 ++ r5dev/resource/protobuf/sv_rcon.proto | 18 - r5dev/tier0/utility.cpp | 20 + r5dev/tier2/CMakeLists.txt | 4 +- r5dev/tier2/cryptutils.cpp | 70 ++ 33 files changed, 3393 insertions(+), 2290 deletions(-) delete mode 100644 r5dev/protoc/cl_rcon.pb.cc delete mode 100644 r5dev/protoc/cl_rcon.pb.h create mode 100644 r5dev/protoc/netcon.pb.cc create mode 100644 r5dev/protoc/netcon.pb.h delete mode 100644 r5dev/protoc/sv_rcon.pb.cc delete mode 100644 r5dev/protoc/sv_rcon.pb.h create mode 100644 r5dev/public/tier2/cryptutils.h delete mode 100644 r5dev/resource/protobuf/cl_rcon.proto create mode 100644 r5dev/resource/protobuf/netcon.proto delete mode 100644 r5dev/resource/protobuf/sv_rcon.proto create mode 100644 r5dev/tier2/cryptutils.cpp diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp index 8ea1e366..e47ddbe0 100644 --- a/r5dev/common/callback.cpp +++ b/r5dev/common/callback.cpp @@ -10,6 +10,7 @@ #include "tier0/fasttimer.h" #include "tier1/cvar.h" #include "tier1/fmtstr.h" +#include "engine/shared/shared_rcon.h" #ifndef CLIENT_DLL #include "engine/server/sv_rcon.h" #endif // !CLIENT_DLL @@ -248,7 +249,7 @@ void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString { Msg(eDLL_T::SERVER, "Rebooting RCON server...\n"); RCONServer()->Shutdown(); - RCONServer()->Init(); + RCONServer()->Init(rcon_password.GetString(), RCONServer()->GetKey()); } #endif // !CLIENT_DLL } diff --git a/r5dev/core/CMakeLists.txt b/r5dev/core/CMakeLists.txt index d8f575bf..088125d1 100644 --- a/r5dev/core/CMakeLists.txt +++ b/r5dev/core/CMakeLists.txt @@ -59,8 +59,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "SigCache_Pb" "LiveAPI_Pb" - "SV_RCon_Pb" - "CL_RCon_Pb" + "NetCon_Pb" "rson" "rtech_game" @@ -81,6 +80,10 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "EAThread" "DirtySDK" + "libmbedcrypto" + "libmbedtls" + "libmbedx509" + "networksystem" "pluginsystem" "filesystem" @@ -115,9 +118,6 @@ endif() if( NOT ${PROJECT_NAME} STREQUAL "client" ) target_link_libraries( ${PROJECT_NAME} PRIVATE - "libmbedcrypto" - "libmbedtls" - "libmbedx509" "libjwt" ) endif() diff --git a/r5dev/core/logger.cpp b/r5dev/core/logger.cpp index ebc1ba08..867f774b 100644 --- a/r5dev/core/logger.cpp +++ b/r5dev/core/logger.cpp @@ -284,9 +284,9 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context, if (bToConsole) { #ifndef CLIENT_DLL - if (!LoggedFromClient(context) && RCONServer()->ShouldSend(sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG)) + if (!LoggedFromClient(context) && RCONServer()->ShouldSend(netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG)) { - RCONServer()->SendEncode(formatted.c_str(), pszUpTime, sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, + RCONServer()->SendEncoded(formatted.c_str(), pszUpTime, netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG, int(context), int(logType)); } #endif // !CLIENT_DLL diff --git a/r5dev/engine/client/cl_rcon.cpp b/r5dev/engine/client/cl_rcon.cpp index 5ff53e41..9daf067b 100644 --- a/r5dev/engine/client/cl_rcon.cpp +++ b/r5dev/engine/client/cl_rcon.cpp @@ -7,8 +7,7 @@ #include "core/stdafx.h" #include "tier1/cmd.h" #include "tier1/cvar.h" -#include "protoc/sv_rcon.pb.h" -#include "protoc/cl_rcon.pb.h" +#include "protoc/netcon.pb.h" #include "engine/client/cl_rcon.h" #include "engine/shared/shared_rcon.h" #include "engine/net.h" @@ -19,16 +18,18 @@ //----------------------------------------------------------------------------- // Purpose: console variables //----------------------------------------------------------------------------- -static ConVar rcon_address("rcon_address", "[loopback]:37015", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access address"); +static void RCON_AddressChanged_f(IConVar* pConVar, const char* pOldString); +static void RCON_InputOnlyChanged_f(IConVar* pConVar, const char* pOldString); + +static ConVar cl_rcon_address("cl_rcon_address", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access address (rcon client is disabled if empty)", &RCON_AddressChanged_f); +static ConVar cl_rcon_inputonly("cl_rcon_inputonly", "0", FCVAR_RELEASE, "Tells the rcon server whether or not we are input only.", RCON_InputOnlyChanged_f); //----------------------------------------------------------------------------- // Purpose: console commands //----------------------------------------------------------------------------- -static void RCON_Disconnect_f(); static void RCON_CmdQuery_f(const CCommand& args); static ConCommand rcon("rcon", RCON_CmdQuery_f, "Forward RCON query to remote server", FCVAR_CLIENTDLL | FCVAR_RELEASE, nullptr, "rcon \"\""); -static ConCommand rcon_disconnect("rcon_disconnect", RCON_Disconnect_f, "Disconnect from RCON server", FCVAR_CLIENTDLL | FCVAR_RELEASE); //----------------------------------------------------------------------------- // Purpose: @@ -51,8 +52,9 @@ CRConClient::~CRConClient(void) //----------------------------------------------------------------------------- // Purpose: NETCON systems init //----------------------------------------------------------------------------- -void CRConClient::Init(void) +void CRConClient::Init(const char* pNetKey) { + SetKey(pNetKey); m_bInitialized = true; } @@ -105,18 +107,17 @@ void CRConClient::Disconnect(const char* szReason) //----------------------------------------------------------------------------- bool CRConClient::ProcessMessage(const char* pMsgBuf, const int nMsgLen) { - sv_rcon::response response; - bool bSuccess = Decode(&response, pMsgBuf, nMsgLen); + netcon::response response; - if (!bSuccess) + if (!SH_NetConUnpackEnvelope(this, pMsgBuf, nMsgLen, &response, rcon_debug.GetBool())) { - Error(eDLL_T::CLIENT, NO_ERROR, "Failed to decode RCON buffer\n"); + Disconnect("received invalid message"); return false; } switch (response.responsetype()) { - case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH: + case netcon::response_e::SERVERDATA_RESPONSE_AUTH: { if (!response.responseval().empty()) { @@ -132,7 +133,7 @@ bool CRConClient::ProcessMessage(const char* pMsgBuf, const int nMsgLen) Msg(eDLL_T::NETCON, "%s", response.responsemsg().c_str()); break; } - case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG: + case netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG: { NetMsg(static_cast(response.messagetype()), static_cast(response.messageid()), @@ -165,7 +166,7 @@ void CRConClient::RequestConsoleLog(const bool bWantLog) const SocketHandle_t hSocket = GetSocket(); vector vecMsg; - bool ret = Serialize(vecMsg, "", szEnable, cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG); + bool ret = Serialize(vecMsg, "", szEnable, netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG); if (ret && !Send(hSocket, vecMsg.data(), int(vecMsg.size()))) { @@ -181,9 +182,10 @@ void CRConClient::RequestConsoleLog(const bool bWantLog) // Output : serialized results as string //----------------------------------------------------------------------------- bool CRConClient::Serialize(vector& vecBuf, const char* szReqBuf, - const char* szReqVal, const cl_rcon::request_t requestType) const + const char* szReqVal, const netcon::request_e requestType) const { - return CL_NetConSerialize(this, vecBuf, szReqBuf, szReqVal, requestType); + return CL_NetConSerialize(this, vecBuf, szReqBuf, szReqVal, requestType, + rcon_encryptframes.GetBool(), rcon_debug.GetBool()); } //----------------------------------------------------------------------------- @@ -204,17 +206,6 @@ SocketHandle_t CRConClient::GetSocket(void) return SH_GetNetConSocketHandle(this, 0); } -//----------------------------------------------------------------------------- -// Purpose: request whether to recv logs from RCON server when cvar changes -//----------------------------------------------------------------------------- -static void RCON_InputOnlyChanged_f(IConVar* pConVar, const char* pOldString) -{ - RCONClient()->RequestConsoleLog(RCONClient()->ShouldReceive()); -} - -static ConVar cl_rcon_inputonly("cl_rcon_inputonly", "0", FCVAR_RELEASE, "Tells the rcon server whether or not we are input only.", - false, 0.f, false, 0.f, RCON_InputOnlyChanged_f); - //----------------------------------------------------------------------------- // Purpose: returns whether or not we should receive logs from the server //----------------------------------------------------------------------------- @@ -254,6 +245,49 @@ CRConClient* RCONClient() // Singleton RCON Client. return &s_RCONClient; } +/* +===================== +RCON_AddressChanged_f + + +===================== +*/ +static void RCON_AddressChanged_f(IConVar* pConVar, const char* pOldString) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { + const char* pNewString = pConVarRef->GetString(); + + if (strcmp(pOldString, pNewString) == NULL) + { + return; // Same address. + } + + if (!*pNewString) // Empty address means nothing to network to; shutdown client... + { + RCONClient()->Shutdown(); + } + else + { + RCON_InitClientAndTrySyncKeys(); + } + } +} + +/* +===================== +RCON_InputOnlyChanged_f + + request whether to recv logs + from RCON server when cvar + changes +===================== +*/ +static void RCON_InputOnlyChanged_f(IConVar* pConVar, const char* pOldString) +{ + RCONClient()->RequestConsoleLog(RCONClient()->ShouldReceive()); +} + /* ===================== RCON_CmdQuery_f @@ -268,7 +302,7 @@ static void RCON_CmdQuery_f(const CCommand& args) if (argCount < 2) { - const char* pszAddress = rcon_address.GetString(); + const char* pszAddress = cl_rcon_address.GetString(); if (RCONClient()->IsInitialized() && !RCONClient()->IsConnected() @@ -290,16 +324,23 @@ static void RCON_CmdQuery_f(const CCommand& args) bool bSuccess = false; const SocketHandle_t hSocket = RCONClient()->GetSocket(); - if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value. + if (strcmp(args.Arg(1), "PASS") == 0) { if (argCount > 2) { - bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); + bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", netcon::request_e::SERVERDATA_REQUEST_AUTH); } - else + else // Auth with RCON server using rcon_password ConVar value. { - Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); - return; + const char* storedPassword = rcon_password.GetString(); + + if (!strlen(storedPassword)) + { + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); + return; + } + + bSuccess = RCONClient()->Serialize(vecMsg, storedPassword, "", netcon::request_e::SERVERDATA_REQUEST_AUTH); } if (bSuccess) @@ -311,11 +352,11 @@ static void RCON_CmdQuery_f(const CCommand& args) } else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server. { - RCONClient()->Disconnect("issued by user"); + RCONClient()->Disconnect("ordered by user"); return; } - bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(1), args.ArgS(), cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); + bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(1), args.ArgS(), netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND); if (bSuccess) { RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size())); @@ -329,21 +370,3 @@ static void RCON_CmdQuery_f(const CCommand& args) } } } - -/* -===================== -RCON_Disconnect_f - - Disconnect from RCON server -===================== -*/ -static void RCON_Disconnect_f() -{ - const bool bIsConnected = RCONClient()->IsConnected(); - RCONClient()->Disconnect("issued by user"); - - if (bIsConnected) // Log if client was indeed connected. - { - Msg(eDLL_T::CLIENT, "User closed RCON connection\n"); - } -} diff --git a/r5dev/engine/client/cl_rcon.h b/r5dev/engine/client/cl_rcon.h index 72f8a769..0dd4ed4a 100644 --- a/r5dev/engine/client/cl_rcon.h +++ b/r5dev/engine/client/cl_rcon.h @@ -1,8 +1,7 @@ #pragma once #include "tier1/NetAdr.h" #include "tier2/socketcreator.h" -#include "protoc/sv_rcon.pb.h" -#include "protoc/cl_rcon.pb.h" +#include "protoc/netcon.pb.h" #include "engine/shared/base_rcon.h" class CRConClient : public CNetConBase @@ -11,7 +10,7 @@ public: CRConClient(void); ~CRConClient(void); - void Init(void); + void Init(const char* pNetKey = nullptr); void Shutdown(void); void RunFrame(void); @@ -19,7 +18,7 @@ public: virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override; bool Serialize(vector& vecBuf, const char* szReqBuf, - const char* szReqVal, const cl_rcon::request_t requestType) const; + const char* szReqVal, const netcon::request_e requestType) const; void RequestConsoleLog(const bool bWantLog); bool ShouldReceive(void); diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index 09213da5..6704a7ff 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -299,13 +299,6 @@ void CHostState::Setup(void) #endif // !CLIENT_DLL ConVar_PurgeHostNames(); -#ifndef CLIENT_DLL - RCONServer()->Init(); -#endif // !CLIENT_DLL -#ifndef DEDICATED - RCONClient()->Init(); -#endif // !DEDICATED - #ifndef CLIENT_DLL LiveAPISystem()->Init(); #endif // !CLIENT_DLL diff --git a/r5dev/engine/net.h b/r5dev/engine/net.h index 70e60aab..55eec1b9 100644 --- a/r5dev/engine/net.h +++ b/r5dev/engine/net.h @@ -1,5 +1,9 @@ #pragma once +constexpr unsigned int AES_128_KEY_SIZE = 16; +constexpr unsigned int AES_128_B64_ENCODED_SIZE = 24; +constexpr const char* DEFAULT_NET_ENCRYPTION_KEY = "WDNWLmJYQ2ZlM0VoTid3Yg=="; + #ifndef _TOOLS #include "engine/net_chan.h" #include "tier1/lzss.h" @@ -14,10 +18,6 @@ #define NETMSG_LENGTH_BITS 12 // 512 bytes (11 in Valve Source, 256 bytes). #define NET_MIN_MESSAGE 5 // Even connectionless packets require int32 value (-1) + 1 byte content -constexpr unsigned int AES_128_KEY_SIZE = 16; -constexpr unsigned int AES_128_B64_ENCODED_SIZE = 24; -constexpr const char* DEFAULT_NET_ENCRYPTION_KEY = "WDNWLmJYQ2ZlM0VoTid3Yg=="; - /* ==== CNETCHAN ======================================================================================================================================================== */ inline void*(*v_NET_Init)(bool bDeveloper); inline void(*v_NET_SetKey)(netkey_t* pKey, const char* szHash); diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index b1acbf3d..0fc7b21a 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -11,10 +11,13 @@ #include "engine/cmd.h" #include "engine/net.h" #include "engine/server/sv_rcon.h" -#include "protoc/sv_rcon.pb.h" -#include "protoc/cl_rcon.pb.h" +#include "protoc/netcon.pb.h" #include "common/igameserverdata.h" #include "mbedtls/include/mbedtls/sha512.h" +#include +#include +#include +#include //----------------------------------------------------------------------------- // Purpose: constants @@ -29,13 +32,8 @@ static const char s_BannedMessage[] = "Go away.\n"; //----------------------------------------------------------------------------- static void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString); -static void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); -static ConVar rcon_password("rcon_password", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon is disabled if empty)", false, 0.f, false, 0.f, &RCON_PasswordChanged_f); - -static ConVar sv_rcon_debug("sv_rcon_debug", "0", FCVAR_RELEASE, "Show rcon debug information ( !slower! )"); static ConVar sv_rcon_sendlogs("sv_rcon_sendlogs", "0", FCVAR_RELEASE, "Network console logs to connected and authenticated sockets"); - //static ConVar sv_rcon_banpenalty("sv_rcon_banpenalty" , "10", FCVAR_RELEASE, "Number of minutes to ban users who fail rcon authentication"); static ConVar sv_rcon_maxfailures("sv_rcon_maxfailures", "10", FCVAR_RELEASE, "Max number of times an user can fail rcon authentication before being banned", true, 1.f, false, 0.f); @@ -43,7 +41,7 @@ static ConVar sv_rcon_maxignores("sv_rcon_maxignores", "15", FCVAR_RELEASE, "Max static ConVar sv_rcon_maxsockets("sv_rcon_maxsockets", "32", FCVAR_RELEASE, "Max number of accepted sockets before the server starts closing redundant sockets", true, 1.f, true, MAX_PLAYERS); static ConVar sv_rcon_maxconnections("sv_rcon_maxconnections", "1", FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket", true, 1.f, true, MAX_PLAYERS, &RCON_ConnectionCountChanged_f); -static ConVar sv_rcon_maxpacketsize("sv_rcon_maxpacketsize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a command packet from a non-authenticated netconsole", true, 0.f, false, 0.f); +static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a command frame from a non-authenticated netconsole", true, 0.f, false, 0.f); static ConVar sv_rcon_whitelist_address("sv_rcon_whitelist_address", "", FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts", &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); //----------------------------------------------------------------------------- @@ -54,6 +52,7 @@ CRConServer::CRConServer(void) , m_nAuthConnections(0) , m_bInitialized(false) { + memset(m_PasswordHash, 0, sizeof(m_PasswordHash)); } //----------------------------------------------------------------------------- @@ -62,18 +61,20 @@ CRConServer::CRConServer(void) CRConServer::~CRConServer(void) { // NOTE: do not call Shutdown() from the destructor as the OS's socket - // system would be shutdown by now, call Shutdown() in application + // system would be shutdown by then, call Shutdown() in application // shutdown code instead } //----------------------------------------------------------------------------- // Purpose: NETCON systems init //----------------------------------------------------------------------------- -void CRConServer::Init(void) +void CRConServer::Init(const char* pPassword, const char* pNetKey) { if (!m_bInitialized) { - if (!SetPassword(rcon_password.GetString())) + SetKey(pNetKey); + + if (!SetPassword(pPassword)) { return; } @@ -89,7 +90,9 @@ void CRConServer::Init(void) m_Address.SetFromString(Format("[%s]:%i", pszAddress, hostport->GetInt()).c_str(), true); m_Socket.CreateListenSocket(m_Address); - Msg(eDLL_T::SERVER, "Remote server access initialized ('%s')\n", m_Address.ToString()); + Msg(eDLL_T::SERVER, "Remote server access initialized ('%s') with key %s'%s%s%s'\n", + m_Address.ToString(), g_svReset, g_svGreyB, GetKey(), g_svReset); + m_bInitialized = true; } @@ -232,14 +235,14 @@ void CRConServer::RunFrame(void) if (CheckForBan(data)) { - SendEncode(data.m_hSocket, s_BannedMessage, "", - sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, int(eDLL_T::NETCON)); + SendEncoded(data.m_hSocket, s_BannedMessage, "", + netcon::response_e::SERVERDATA_RESPONSE_AUTH, int(eDLL_T::NETCON)); Disconnect("banned"); continue; } - Recv(data, sv_rcon_maxpacketsize.GetInt()); + Recv(data, sv_rcon_maxframesize.GetInt()); } } } @@ -292,8 +295,8 @@ bool CRConServer::SendToAll(const char* pMsgBuf, const int nMsgLen) const // nMessageType - // Output: true on success, false otherwise //----------------------------------------------------------------------------- -bool CRConServer::SendEncode(const char* pResponseMsg, const char* pResponseVal, - const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const +bool CRConServer::SendEncoded(const char* pResponseMsg, const char* pResponseVal, + const netcon::response_e responseType, const int nMessageId, const int nMessageType) const { vector vecMsg; if (!Serialize(vecMsg, pResponseMsg, pResponseVal, @@ -320,8 +323,8 @@ bool CRConServer::SendEncode(const char* pResponseMsg, const char* pResponseVal, // nMessageType - // Output: true on success, false otherwise //----------------------------------------------------------------------------- -bool CRConServer::SendEncode(const SocketHandle_t hSocket, const char* pResponseMsg, const char* pResponseVal, - const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const +bool CRConServer::SendEncoded(const SocketHandle_t hSocket, const char* pResponseMsg, const char* pResponseVal, + const netcon::response_e responseType, const int nMessageId, const int nMessageType) const { vector vecMsg; if (!Serialize(vecMsg, pResponseMsg, pResponseVal, @@ -349,26 +352,10 @@ bool CRConServer::SendEncode(const SocketHandle_t hSocket, const char* pResponse // Output : serialized results as string //----------------------------------------------------------------------------- bool CRConServer::Serialize(vector& vecBuf, const char* pResponseMsg, const char* pResponseVal, - const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const + const netcon::response_e responseType, const int nMessageId, const int nMessageType) const { - sv_rcon::response response; - - response.set_messageid(nMessageId); - response.set_messagetype(nMessageType); - response.set_responsetype(responseType); - response.set_responsemsg(pResponseMsg); - response.set_responseval(pResponseVal); - - const size_t msgLen = response.ByteSizeLong(); - vecBuf.resize(msgLen); - - if (!Encode(&response, &vecBuf[0], msgLen)) - { - Error(eDLL_T::SERVER, NO_ERROR, "Failed to encode RCON buffer\n"); - return false; - } - - return true; + return SV_NetConSerialize(this, vecBuf, pResponseMsg, pResponseVal, responseType, nMessageId, nMessageType, + rcon_encryptframes.GetBool(), rcon_debug.GetBool()); } //----------------------------------------------------------------------------- @@ -376,7 +363,7 @@ bool CRConServer::Serialize(vector& vecBuf, const char* pResponseMsg, cons // Input : &request - // &data - //----------------------------------------------------------------------------- -void CRConServer::Authenticate(const cl_rcon::request& request, CConnectedNetConsoleData& data) +void CRConServer::Authenticate(const netcon::request& request, CConnectedNetConsoleData& data) { if (data.m_bAuthorized) { @@ -395,19 +382,19 @@ void CRConServer::Authenticate(const cl_rcon::request& request, CConnectedNetCon const char* pSendLogs = (!sv_rcon_sendlogs.GetBool() || data.m_bInputOnly) ? "0" : "1"; - SendEncode(data.m_hSocket, s_AuthMessage, pSendLogs, - sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast(eDLL_T::NETCON)); + SendEncoded(data.m_hSocket, s_AuthMessage, pSendLogs, + netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast(eDLL_T::NETCON)); } else // Bad password. { const netadr_t& netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex); - if (sv_rcon_debug.GetBool()) + if (rcon_debug.GetBool()) { Msg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString()); } - SendEncode(data.m_hSocket, s_WrongPwMessage, "", - sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast(eDLL_T::NETCON)); + SendEncoded(data.m_hSocket, s_WrongPwMessage, "", + netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast(eDLL_T::NETCON)); data.m_bAuthorized = false; data.m_bValidated = false; @@ -442,21 +429,22 @@ bool CRConServer::Comparator(const string& svPassword) const //----------------------------------------------------------------------------- bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen) { - CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex); + netcon::request request; - cl_rcon::request request; - if (!Decode(&request, pMsgBuf, nMsgLen)) + if (!SH_NetConUnpackEnvelope(this, pMsgBuf, nMsgLen, &request, rcon_debug.GetBool())) { - Error(eDLL_T::SERVER, NO_ERROR, "Failed to decode RCON buffer\n"); + Disconnect("received invalid message"); return false; } + CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex); + if (!data.m_bAuthorized && - request.requesttype() != cl_rcon::request_t::SERVERDATA_REQUEST_AUTH) + request.requesttype() != netcon::request_e::SERVERDATA_REQUEST_AUTH) { // Notify netconsole that authentication is required. - SendEncode(data.m_hSocket, s_NoAuthMessage, "", - sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast(eDLL_T::NETCON)); + SendEncoded(data.m_hSocket, s_NoAuthMessage, "", + netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast(eDLL_T::NETCON)); data.m_bValidated = false; data.m_nIgnoredMessage++; @@ -464,12 +452,12 @@ bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen) } switch (request.requesttype()) { - case cl_rcon::request_t::SERVERDATA_REQUEST_AUTH: + case netcon::request_e::SERVERDATA_REQUEST_AUTH: { Authenticate(request, data); break; } - case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND: + case netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND: { if (data.m_bAuthorized) // Only execute if auth was successful. { @@ -477,7 +465,7 @@ bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen) } break; } - case cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG: + case netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG: { if (data.m_bAuthorized) { @@ -507,7 +495,7 @@ bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen) // Purpose: execute commands issued from netconsole (ignores all protection flags) // Input : &request - //----------------------------------------------------------------------------- -void CRConServer::Execute(const cl_rcon::request& request) const +void CRConServer::Execute(const netcon::request& request) const { const string& commandString = request.requestmsg(); const char* const pCommandString = commandString.c_str(); @@ -590,7 +578,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) // Only allow whitelisted at this point. if (!m_WhiteListAddress.CompareAdr(netAdr)) { - if (sv_rcon_debug.GetBool()) + if (rcon_debug.GetBool()) { Msg(eDLL_T::SERVER, "Banned list is full; dropping '%s'\n", szNetAdr); } @@ -680,7 +668,7 @@ void CRConServer::CloseNonAuthConnection(void) // Input : responseType - // Output : true if it should send, false otherwise //----------------------------------------------------------------------------- -bool CRConServer::ShouldSend(const sv_rcon::response_t responseType) const +bool CRConServer::ShouldSend(const netcon::response_e responseType) const { if (!IsInitialized() || !m_Socket.GetAcceptedSocketCount()) { @@ -688,7 +676,7 @@ bool CRConServer::ShouldSend(const sv_rcon::response_t responseType) const return false; } - if (responseType == sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG) + if (responseType == netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG) { if (!sv_rcon_sendlogs.GetBool() || !m_Socket.GetAuthorizedSocketCount()) { @@ -772,23 +760,6 @@ static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldStri } } -//----------------------------------------------------------------------------- -// Purpose: change RCON password on server and drop all connections -//----------------------------------------------------------------------------- -void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString) -{ - if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) - { - if (strcmp(pOldString, pConVarRef->GetString()) == NULL) - return; // Same password. - - if (RCONServer()->IsInitialized()) - RCONServer()->SetPassword(pConVarRef->GetString()); - else - RCONServer()->Init(); // Initialize first. - } -} - /////////////////////////////////////////////////////////////////////////////// static CRConServer s_RCONServer; CRConServer* RCONServer() // Singleton RCON Server. diff --git a/r5dev/engine/server/sv_rcon.h b/r5dev/engine/server/sv_rcon.h index a557181c..71770910 100644 --- a/r5dev/engine/server/sv_rcon.h +++ b/r5dev/engine/server/sv_rcon.h @@ -1,8 +1,7 @@ #pragma once #include "tier1/NetAdr.h" #include "tier2/socketcreator.h" -#include "protoc/sv_rcon.pb.h" -#include "protoc/cl_rcon.pb.h" +#include "protoc/netcon.pb.h" #include "engine/shared/base_rcon.h" #define RCON_MIN_PASSWORD_LEN 8 @@ -15,7 +14,7 @@ public: CRConServer(void); ~CRConServer(void); - void Init(void); + void Init(const char* pPassword, const char* pNetKey = nullptr); void Shutdown(void); bool SetPassword(const char* pszPassword); @@ -24,36 +23,37 @@ public: void Think(void); void RunFrame(void); - bool SendEncode(const char* pResponseMsg, const char* pResponseVal, - const sv_rcon::response_t responseType, + bool SendEncoded(const char* pResponseMsg, const char* pResponseVal, + const netcon::response_e responseType, const int nMessageId = static_cast(eDLL_T::NETCON), const int nMessageType = static_cast(LogType_t::LOG_NET)) const; - bool SendEncode(const SocketHandle_t hSocket, const char* pResponseMsg, - const char* pResponseVal, const sv_rcon::response_t responseType, + bool SendEncoded(const SocketHandle_t hSocket, const char* pResponseMsg, + const char* pResponseVal, const netcon::response_e responseType, const int nMessageId = static_cast(eDLL_T::NETCON), const int nMessageType = static_cast(LogType_t::LOG_NET)) const; bool SendToAll(const char* pMsgBuf, const int nMsgLen) const; - bool Serialize(vector& vecBuf, const char* pResponseMsg, const char* pResponseVal, const sv_rcon::response_t responseType, + bool Serialize(vector& vecBuf, const char* pResponseMsg, const char* pResponseVal, const netcon::response_e responseType, const int nMessageId = static_cast(eDLL_T::NETCON), const int nMessageType = static_cast(LogType_t::LOG_NET)) const; - void Authenticate(const cl_rcon::request& request, CConnectedNetConsoleData& data); + void Authenticate(const netcon::request& request, CConnectedNetConsoleData& data); bool Comparator(const string& svPassword) const; virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override; - void Execute(const cl_rcon::request& request) const; + void Execute(const netcon::request& request) const; bool CheckForBan(CConnectedNetConsoleData& data); virtual void Disconnect(const char* szReason = nullptr) override; void Disconnect(const int nIndex, const char* szReason = nullptr); void CloseNonAuthConnection(void); - bool ShouldSend(const sv_rcon::response_t responseType) const; + bool ShouldSend(const netcon::response_e responseType) const; bool IsInitialized(void) const; int GetAuthenticatedCount(void) const; + void CloseAllSockets() { m_Socket.CloseAllAcceptedSockets(); } private: int m_nConnIndex; diff --git a/r5dev/engine/shared/base_rcon.cpp b/r5dev/engine/shared/base_rcon.cpp index f7e2fb21..bf24f5fb 100644 --- a/r5dev/engine/shared/base_rcon.cpp +++ b/r5dev/engine/shared/base_rcon.cpp @@ -4,9 +4,126 @@ // //===========================================================================// #include "core/stdafx.h" +#include "tier2/cryptutils.h" #include "base_rcon.h" #include "engine/net.h" #include "shared_rcon.h" +#include "protoc/netcon.pb.h" +#include "mbedtls/base64.h" + +//----------------------------------------------------------------------------- +// Purpose: sets the encryption key, a key will always be set, either random or +// the default key on failure +// Input : *pBase64NetKey - +// bUseDefaultOnFailure - +//----------------------------------------------------------------------------- +void CNetConBase::SetKey(const char* pBase64NetKey, const bool bUseDefaultOnFailure/* = false*/) +{ + // Drop all connections as they would be unable to decipher the message + // frames once the key has been swapped. + m_Socket.CloseAllAcceptedSockets(); + + bool parseInput = pBase64NetKey && *pBase64NetKey; + bool genRandom = !parseInput; + + bool failure = false; + + if (parseInput) + { + const size_t keyLen = strlen(pBase64NetKey); + string tokenizedKey; + + if (keyLen != AES_128_B64_ENCODED_SIZE || !IsValidBase64(pBase64NetKey, &tokenizedKey)) + { + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: invalid key (%s)\n", pBase64NetKey); + failure = true; + } + else + { + size_t numBytesDecoded = 0; + + const int decodeRet = mbedtls_base64_decode(m_NetKey, sizeof(m_NetKey), &numBytesDecoded, + reinterpret_cast(tokenizedKey.c_str()), tokenizedKey.length()); + + if (decodeRet != 0) + { + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: decode error (%d)\n", decodeRet); + failure = true; + } + else if (numBytesDecoded != sizeof(m_NetKey)) + { + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: read error (%zu != %zu)\n", numBytesDecoded, sizeof(m_NetKey)); + failure = true; + } + else + { + m_Base64NetKey = tokenizedKey.c_str(); + } + } + } + + bool useDefaultKey = false; // Last resort + + if (genRandom || failure) // Generate random key + { + if (failure && bUseDefaultOnFailure) + { + useDefaultKey = true; + } + else + { + const char* errorMsg = nullptr; + + if (!CryptoGenRandom(m_NetKey, sizeof(m_NetKey), errorMsg)) + { + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: generate error (%s)\n", errorMsg); + useDefaultKey = true; + } + else // Try to encode it + { + char encodedKey[45]; + memset(encodedKey, 0, sizeof(encodedKey)); + + size_t numBytesEncoded = 0; + + const int encodeRet = mbedtls_base64_encode(reinterpret_cast(&encodedKey), + sizeof(encodedKey), &numBytesEncoded, m_NetKey, sizeof(m_NetKey)); + + if (encodeRet != 0) + { + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: encode error (%d)\n", encodeRet); + useDefaultKey = true; + } + else if (numBytesEncoded != sizeof(m_NetKey)) + { + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: write error (%zu != %zu)\n", numBytesEncoded, sizeof(m_NetKey)); + failure = true; + } + else + { + m_Base64NetKey = encodedKey; + } + } + } + } + + if (useDefaultKey) // Use the default key if everything failed (unlikely) + { + size_t numBytesDecoded = 0; + mbedtls_base64_decode(m_NetKey, sizeof(m_NetKey), &numBytesDecoded, + reinterpret_cast(DEFAULT_NET_ENCRYPTION_KEY), AES_128_B64_ENCODED_SIZE); + + m_Base64NetKey = DEFAULT_NET_ENCRYPTION_KEY; + } +} + +//----------------------------------------------------------------------------- +// Purpose: gets the encryption key as a base64 encoded string +//----------------------------------------------------------------------------- +const char* CNetConBase::GetKey(void) const +{ + return m_Base64NetKey.String(); +} //----------------------------------------------------------------------------- // Purpose: connect to remote @@ -56,7 +173,7 @@ bool CNetConBase::ProcessBuffer(CConnectedNetConsoleData& data, data.m_nPayloadRead = 0; } } - else if (data.m_nPayloadRead+1 <= sizeof(int)) // Read size field. + else if (data.m_nPayloadRead < sizeof(int)) // Read size field. { data.m_RecvBuffer[data.m_nPayloadRead++] = *pRecvBuf; @@ -95,6 +212,39 @@ bool CNetConBase::ProcessBuffer(CConnectedNetConsoleData& data, return bSuccess; } +//----------------------------------------------------------------------------- +// Purpose: encrypt message to buffer +// Input : &ctx - +// *pInBuf - +// *pOutBuf - +// nDataLen - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool CNetConBase::Encrypt(CryptoContext_s& ctx, const char* pInBuf, + char* pOutBuf, const size_t nDataLen) const +{ + if (Crypto_GenerateIV(ctx, reinterpret_cast(pInBuf), nDataLen)) + return Crypto_CTREncrypt(ctx, reinterpret_cast(pInBuf), + reinterpret_cast(pOutBuf), m_NetKey, nDataLen); + + return false; // failure +} + +//----------------------------------------------------------------------------- +// Purpose: decrypt message to buffer +// Input : &ctx - +// *pInBuf - +// *pOutBuf - +// nDataLen - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool CNetConBase::Decrypt(CryptoContext_s& ctx, const char* pInBuf, + char* pOutBuf, const size_t nDataLen) const +{ + return Crypto_CTRDecrypt(ctx, reinterpret_cast(pInBuf), + reinterpret_cast(pOutBuf), m_NetKey, nDataLen); +} + //----------------------------------------------------------------------------- // Purpose: encode message to buffer // Input : *pMsg - diff --git a/r5dev/engine/shared/base_rcon.h b/r5dev/engine/shared/base_rcon.h index 5ce54733..8bbf2ec4 100644 --- a/r5dev/engine/shared/base_rcon.h +++ b/r5dev/engine/shared/base_rcon.h @@ -2,14 +2,23 @@ #define BASE_RCON_H #include "tier1/NetAdr.h" +#include "tier2/cryptutils.h" #include "tier2/socketcreator.h" #include "protobuf/message_lite.h" +// Max size of the payload in the envelope frame +#define RCON_MAX_PAYLOAD_SIZE 1024*1024 + class CNetConBase { public: CNetConBase(void) - {} + { + memset(m_NetKey, 0, sizeof(m_NetKey)); + } + + void SetKey(const char* pBase64NetKey, const bool bUseDefaultOnFailure = false); + const char* GetKey(void) const; virtual bool Connect(const char* pHostName, const int nHostPort = SOCKET_ERROR); virtual void Disconnect(const char* szReason = nullptr) { NOTE_UNUSED(szReason); }; @@ -17,6 +26,9 @@ public: virtual bool ProcessBuffer(CConnectedNetConsoleData& data, const char* pRecvBuf, int nRecvLen, const int nMaxLen = SOCKET_ERROR); virtual bool ProcessMessage(const char* /*pMsgBuf*/, int /*nMsgLen*/) { return true; }; + virtual bool Encrypt(CryptoContext_s& ctx, const char* pInBuf, char* pOutBuf, const size_t nDataLen) const; + virtual bool Decrypt(CryptoContext_s& ctx, const char* pInBuf, char* pOutBuf, const size_t nDataLen) const; + virtual bool Encode(google::protobuf::MessageLite* pMsg, char* pMsgBuf, const size_t nMsgLen) const; virtual bool Decode(google::protobuf::MessageLite* pMsg, const char* pMsgBuf, const size_t nMsgLen) const; @@ -29,6 +41,8 @@ public: protected: CSocketCreator m_Socket; netadr_t m_Address; + CryptoKey_t m_NetKey; + CUtlString m_Base64NetKey; }; #endif // BASE_RCON_H diff --git a/r5dev/engine/shared/shared_rcon.cpp b/r5dev/engine/shared/shared_rcon.cpp index 1ead017f..bda8b88c 100644 --- a/r5dev/engine/shared/shared_rcon.cpp +++ b/r5dev/engine/shared/shared_rcon.cpp @@ -6,6 +6,39 @@ #include "core/stdafx.h" #include "base_rcon.h" #include "shared_rcon.h" +#include "protoc/netcon.pb.h" + +//----------------------------------------------------------------------------- +// Purpose: serialize message to vector +// Input : *pBase - +// &vecBuf - +// *pResponseMsg - +// *pResponseVal - +// responseType - +// nMessageId - +// nMessageType - +// bEncrypt - +// bDebug - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool SV_NetConSerialize(const CNetConBase* pBase, vector& vecBuf, const char* pResponseMsg, const char* pResponseVal, + const netcon::response_e responseType, const int nMessageId, const int nMessageType, const bool bEncrypt, const bool bDebug) +{ + netcon::response response; + + response.set_messageid(nMessageId); + response.set_messagetype(nMessageType); + response.set_responsetype(responseType); + response.set_responsemsg(pResponseMsg); + response.set_responseval(pResponseVal); + + if (!SH_NetConPackEnvelope(pBase, vecBuf, response.ByteSizeLong(), &response, bEncrypt, bDebug)) + { + return false; + } + + return true; +} //----------------------------------------------------------------------------- // Purpose: serialize message to vector @@ -14,24 +47,22 @@ // *szReqBuf - // *szReqVal - // *requestType - +// bEncrypt - +// bDebug - // Output : true on success, false otherwise //----------------------------------------------------------------------------- bool CL_NetConSerialize(const CNetConBase* pBase, vector& vecBuf, const char* szReqBuf, - const char* szReqVal, const cl_rcon::request_t requestType) + const char* szReqVal, const netcon::request_e requestType, const bool bEncrypt, const bool bDebug) { - cl_rcon::request request; + netcon::request request; request.set_messageid(-1); request.set_requesttype(requestType); request.set_requestmsg(szReqBuf); request.set_requestval(szReqVal); - const size_t msgLen = request.ByteSizeLong(); - vecBuf.resize(msgLen); - - if (!pBase->Encode(&request, &vecBuf[0], msgLen)) + if (!SH_NetConPackEnvelope(pBase, vecBuf, request.ByteSizeLong(), &request, bEncrypt, bDebug)) { - Error(eDLL_T::CLIENT, NO_ERROR, "Failed to encode RCON buffer\n"); return false; } @@ -83,6 +114,165 @@ bool CL_NetConConnect(CNetConBase* pBase, const char* pHostAdr, const int nHostP return true; } +//----------------------------------------------------------------------------- +// Purpose: packs a message envelope +// Input : *pBase - +// &outMsgBuf - +// nMsgLen - +// *inMsg - +// bEncrypt - +// bDebug - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool SH_NetConPackEnvelope(const CNetConBase* pBase, vector& outMsgBuf, const size_t nMsgLen, + google::protobuf::MessageLite* inMsg, const bool bEncrypt, const bool bDebug) +{ + char* encodeBuf = new char[nMsgLen]; + std::unique_ptr encodedContainer(encodeBuf); + + if (!pBase->Encode(inMsg, encodeBuf, nMsgLen)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to encode RCON message data\n"); + } + + return false; + } + + netcon::envelope envelope; + envelope.set_encrypted(bEncrypt); + + const char* dataBuf = encodeBuf; + std::unique_ptr container; + + if (bEncrypt) + { + char* encryptBuf = new char[nMsgLen]; + container.reset(encryptBuf); + + CryptoContext_s ctx; + if (!pBase->Encrypt(ctx, encodeBuf, encryptBuf, nMsgLen)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to encrypt RCON message data\n"); + } + + return false; + } + + envelope.set_nonce(ctx.ivData, sizeof(ctx.ivData)); + dataBuf = encryptBuf; + } + + envelope.set_data(dataBuf, nMsgLen); + const size_t envelopeSize = envelope.ByteSizeLong(); + + outMsgBuf.resize(envelopeSize); + + if (!pBase->Encode(&envelope, &outMsgBuf[0], envelopeSize)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to encode RCON message envelope\n"); + } + + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: unpacks a message envelope +// Input : *pBase - +// *pMsgBuf - +// nMsgLen - +// *outMsg - +// bEncrypt - +// bDebug - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool SH_NetConUnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf, const size_t nMsgLen, + google::protobuf::MessageLite* outMsg, const bool bDebug) +{ + netcon::envelope envelope; + + if (!pBase->Decode(&envelope, pMsgBuf, nMsgLen)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to decode RCON message envelope\n"); + } + + return false; + } + + const size_t msgLen = envelope.data().size(); + + if (msgLen > RCON_MAX_PAYLOAD_SIZE) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Data in RCON message envelope is too large (%zu > %zu)\n", + msgLen, RCON_MAX_PAYLOAD_SIZE); + + return false; + } + + const char* netMsg = envelope.data().c_str(); + const char* dataBuf = netMsg; + + std::unique_ptr container; + + if (envelope.encrypted()) + { + char* decryptBuf = new char[msgLen]; + container.reset(decryptBuf); + + const size_t ivLen = envelope.nonce().size(); + + if (ivLen != sizeof(CryptoIV_t)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Nonce in RCON message envelope is invalid (%zu != %zu)\n", + ivLen, sizeof(CryptoIV_t)); + } + + return false; + } + + CryptoContext_s ctx; + memcpy(ctx.ivData, envelope.nonce().data(), ivLen); + + if (!pBase->Decrypt(ctx, netMsg, decryptBuf, msgLen)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to decrypt RCON message data\n"); + } + + return false; + } + + dataBuf = decryptBuf; + } + + Assert(dataBuf); + + if (!pBase->Decode(outMsg, dataBuf, msgLen)) + { + if (bDebug) + { + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to decode RCON message data\n"); + } + + return false; + } + + return true; +} + //----------------------------------------------------------------------------- // Purpose: gets the netconsole data // Input : *pBase - @@ -119,3 +309,116 @@ SocketHandle_t SH_GetNetConSocketHandle(CNetConBase* pBase, const int iSocket) return pData->m_hSocket; } + +#ifndef _TOOLS + +#ifndef CLIENT_DLL +#include "engine/server/sv_rcon.h" +#endif // !CLIENT_DLL +#ifndef DEDICATED +#include "engine/client/cl_rcon.h" +#endif // !DEDICATED + +void RCON_KeyChanged_f(IConVar* pConVar, const char* pOldString); +void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); + +ConVar rcon_debug("rcon_debug", "0", FCVAR_RELEASE, "Show rcon debug information ( !slower! )"); +ConVar rcon_encryptframes("rcon_encryptframes", "1", FCVAR_RELEASE, "Whether to encrypt RCON messages"); +ConVar rcon_key("rcon_key", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Base64 remote server access encryption key (random if empty or invalid)", &RCON_KeyChanged_f); +ConVar rcon_password("rcon_password", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon server is disabled if empty)", &RCON_PasswordChanged_f); + +//----------------------------------------------------------------------------- +// Purpose: change RCON key on server and client +//----------------------------------------------------------------------------- +void RCON_KeyChanged_f(IConVar* pConVar, const char* pOldString) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { + const char* pNewString = pConVarRef->GetString(); + + if (strcmp(pOldString, pNewString) == NULL) + return; // Same key. + + +#if !defined(DEDICATED) && !defined(CLIENT_DLL) + RCONServer()->SetKey(pNewString); + RCONClient()->SetKey(RCONServer()->GetKey()); // Sync server & client keys + + Msg(eDLL_T::ENGINE, "Installed RCON Key: %s'%s%s%s'\n", + g_svReset, g_svGreyB, RCONClient()->GetKey(), g_svReset); +#else +#ifdef DEDICATED + RCONServer()->SetKey(pNewString); + + Msg(eDLL_T::SERVER, "Installed RCON Key: %s'%s%s%s'\n", + g_svReset, g_svGreyB, RCONServer()->GetKey(), g_svReset); +#endif // DEDICATED +#ifdef CLIENT_DLL + RCONClient()->SetKey(pNewString); + + Msg(eDLL_T::CLIENT, "Installed RCON Key: %s'%s%s%s'\n", + g_svReset, g_svGreyB, RCONClient()->GetKey(), g_svReset); +#endif // CLIENT_DLL + +#endif // !DEDICATED && !CLIENT_DLL + } +} + +//----------------------------------------------------------------------------- +// Purpose: change RCON password on server and drop all connections +//----------------------------------------------------------------------------- +void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { + const char* pNewString = pConVarRef->GetString(); + + if (strcmp(pOldString, pNewString) == NULL) + return; // Same password. + +#ifndef CLIENT_DLL + if (RCONServer()->IsInitialized()) + { + RCONServer()->SetPassword(pNewString); + } + else // Initialize first +#endif // !CLIENT_DLL + { +#if !defined(DEDICATED) && !defined(CLIENT_DLL) + RCONServer()->Init(pNewString, rcon_key.GetString()); + + if (RCONServer()->IsInitialized()) + { + // Sync server & client keys + RCONClient()->SetKey(RCONServer()->GetKey()); + } +#else +#ifdef DEDICATED + RCONServer()->Init(pNewString, rcon_key.GetString()); +#endif // DEDICATED +#ifdef CLIENT_DLL + RCONClient()->Init(rcon_key.GetString()); +#endif // CLIENT_DLL +#endif // !DEDICATED && !CLIENT_DLL + } + } +} + +#ifndef DEDICATED +void RCON_InitClientAndTrySyncKeys() +{ +#ifndef CLIENT_DLL + if (RCONServer()->IsInitialized()) + { + // Sync server & client keys + RCONClient()->Init(RCONServer()->GetKey()); + } + else +#endif // !CLIENT_DLL + { + RCONClient()->Init(rcon_key.GetString()); + } +} +#endif // !DEDICATED + +#endif // !_TOOLS diff --git a/r5dev/engine/shared/shared_rcon.h b/r5dev/engine/shared/shared_rcon.h index 394a8f9d..c8eb8852 100644 --- a/r5dev/engine/shared/shared_rcon.h +++ b/r5dev/engine/shared/shared_rcon.h @@ -1,13 +1,29 @@ #ifndef SHARED_RCON_H #define SHARED_RCON_H #include "base_rcon.h" -#include "protoc/sv_rcon.pb.h" -#include "protoc/cl_rcon.pb.h" +#include "protoc/netcon.pb.h" + +#ifndef _TOOLS +extern ConVar rcon_debug; +extern ConVar rcon_encryptframes; +extern ConVar rcon_key; +extern ConVar rcon_password; + +#ifndef DEDICATED +extern void RCON_InitClientAndTrySyncKeys(); +#endif // !DEDICATED +#endif // _TOOLS + +bool SV_NetConSerialize(const CNetConBase* pBase, vector& vecBuf, const char* pResponseMsg, const char* pResponseVal, + const netcon::response_e responseType, const int nMessageId, const int nMessageType, const bool bEncrypt, const bool bDebug); bool CL_NetConSerialize(const CNetConBase* pBase, vector& vecBuf, const char* szReqBuf, - const char* szReqVal, const cl_rcon::request_t requestType); + const char* szReqVal, const netcon::request_e requestType, const bool bEncrypt, const bool bDebug); bool CL_NetConConnect(CNetConBase* pBase, const char* pHostAdr, const int nHostPort); +bool SH_NetConPackEnvelope(const CNetConBase* pBase, vector& outMsgBuf, const size_t nMsgLen, google::protobuf::MessageLite* inMsg, const bool bEncrypt, const bool bDebug); +bool SH_NetConUnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf, const size_t nMsgLen, google::protobuf::MessageLite* outMsg, const bool bDebug); + CConnectedNetConsoleData* SH_GetNetConData(CNetConBase* pBase, const int iSocket); SocketHandle_t SH_GetNetConSocketHandle(CNetConBase* pBase, const int iSocket); diff --git a/r5dev/netconsole/CMakeLists.txt b/r5dev/netconsole/CMakeLists.txt index c18e4c43..7b6727ea 100644 --- a/r5dev/netconsole/CMakeLists.txt +++ b/r5dev/netconsole/CMakeLists.txt @@ -48,8 +48,15 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "tier2" "libprotobuf" "libspdlog" - "SV_RCon_Pb" - "CL_RCon_Pb" + "libmbedcrypto" + "libmbedtls" + "libmbedx509" + "NetCon_Pb" "Rpcrt4.lib" "ws2_32.lib" + "bcrypt.lib" + "crypt32.lib" +) +target_include_directories( ${PROJECT_NAME} PRIVATE + "${THIRDPARTY_SOURCE_DIR}/mbedtls/include" ) diff --git a/r5dev/netconsole/netconsole.cpp b/r5dev/netconsole/netconsole.cpp index fa46697c..0543388a 100644 --- a/r5dev/netconsole/netconsole.cpp +++ b/r5dev/netconsole/netconsole.cpp @@ -12,8 +12,7 @@ #include "tier1/NetAdr.h" #include "tier2/socketcreator.h" #include "windows/console.h" -#include "protoc/sv_rcon.pb.h" -#include "protoc/cl_rcon.pb.h" +#include "protoc/netcon.pb.h" #include "engine/net.h" #include "engine/shared/shared_rcon.h" #include "netconsole/netconsole.h" @@ -25,6 +24,7 @@ CNetCon::CNetCon(void) : m_bInitialized(false) , m_bQuitting(false) , m_bPromptConnect(true) + , m_bEncryptFrames(true) , m_flTickInterval(0.05f) { // Empty character set used for ip addresses if we still need to initiate a @@ -216,17 +216,17 @@ void CNetCon::RunInput(const string& lineInput) if (V_strcmp(cmd.Arg(0), "PASS") == 0) // Auth with RCON server. { bSend = Serialize(vecMsg, cmd.Arg(1), "", - cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); + netcon::request_e::SERVERDATA_REQUEST_AUTH); } else // Execute command query. { bSend = Serialize(vecMsg, cmd.Arg(0), cmd.GetCommandString(), - cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); + netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND); } } else // Single arg command query. { - bSend = Serialize(vecMsg, lineInput.c_str(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); + bSend = Serialize(vecMsg, lineInput.c_str(), "", netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND); } if (bSend) // Only send if serialization process was successful. @@ -244,25 +244,47 @@ void CNetCon::RunInput(const string& lineInput) if (cmd.ArgC() > 1) { - const char* inAddr = cmd.Arg(0); - const char* inPort = cmd.Arg(1); + const char* inAdr = cmd.Arg(0); + const char* inKey = cmd.Arg(1); - if (!*inAddr || !*inPort) + if (!*inAdr) { - Warning(eDLL_T::CLIENT, "No IP address or port provided\n"); + Warning(eDLL_T::CLIENT, "No address provided\n"); SetPrompting(true); return; } - if (!Connect(inAddr, atoi(inPort))) + if (!*inKey) + { + Warning(eDLL_T::CLIENT, "No key provided; using default %s'%s%s%s'\n", + g_svReset, g_svGreyB, DEFAULT_NET_ENCRYPTION_KEY, g_svReset); + + SetKey(DEFAULT_NET_ENCRYPTION_KEY, true); + } + else + { + SetKey(inKey, true); + } + + m_bEncryptFrames = true; + + Msg(eDLL_T::CLIENT, "Attempting connection to '%s' with key %s'%s%s%s'\n", + inAdr, g_svReset, g_svGreyB, GetKey(), g_svReset); + + if (!Connect(inAdr)) { SetPrompting(true); return; } } - else + else // No encryption { - if (!Connect(cmd.GetCommandString())) + const char* inAdr = cmd.GetCommandString(); + m_bEncryptFrames = false; + + Msg(eDLL_T::CLIENT, "Attempting connection to '%s'\n", inAdr); + + if (!Connect(inAdr)) { SetPrompting(true); return; @@ -287,7 +309,7 @@ bool CNetCon::RunFrame(void) } else if (GetPrompting()) { - Msg(eDLL_T::NONE, "Enter []: or : "); + Msg(eDLL_T::NONE, "Enter [
]: and : "); SetPrompting(false); } } @@ -360,18 +382,17 @@ void CNetCon::Disconnect(const char* szReason) //----------------------------------------------------------------------------- bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen) { - sv_rcon::response response; - bool bSuccess = Decode(&response, pMsgBuf, nMsgLen); + netcon::response response; - if (!bSuccess) + if (!SH_NetConUnpackEnvelope(this, pMsgBuf, nMsgLen, &response, true)) { - Error(eDLL_T::CLIENT, NO_ERROR, "Failed to decode RCON buffer\n"); + Disconnect("received invalid message"); return false; } switch (response.responsetype()) { - case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH: + case netcon::response_e::SERVERDATA_RESPONSE_AUTH: { if (!response.responseval().empty()) { @@ -379,7 +400,7 @@ bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen) if (!i) // Means we are marked 'input only' on the rcon server. { vector vecMsg; - bool ret = Serialize(vecMsg, "", "1", cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG); + bool ret = Serialize(vecMsg, "", "1", netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG); if (ret && !Send(GetSocket(), vecMsg.data(), int(vecMsg.size()))) { @@ -391,7 +412,7 @@ bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen) Msg(eDLL_T::NETCON, "%s", response.responsemsg().c_str()); break; } - case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG: + case netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG: { NetMsg(static_cast(response.messagetype()), static_cast(response.messageid()), @@ -416,9 +437,9 @@ bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen) // Output : true on success, false otherwise //----------------------------------------------------------------------------- bool CNetCon::Serialize(vector& vecBuf, const char* szReqBuf, - const char* szReqVal, const cl_rcon::request_t requestType) const + const char* szReqVal, const netcon::request_e requestType) const { - return CL_NetConSerialize(this, vecBuf, szReqBuf, szReqVal, requestType); + return CL_NetConSerialize(this, vecBuf, szReqBuf, szReqVal, requestType, m_bEncryptFrames, true); } //----------------------------------------------------------------------------- diff --git a/r5dev/netconsole/netconsole.h b/r5dev/netconsole/netconsole.h index 0d77ab48..6a9f8b73 100644 --- a/r5dev/netconsole/netconsole.h +++ b/r5dev/netconsole/netconsole.h @@ -5,8 +5,7 @@ //===========================================================================// #pragma once #include "tier1/cmd.h" -#include "protoc/cl_rcon.pb.h" -#include "protoc/sv_rcon.pb.h" +#include "protoc/netcon.pb.h" #include "engine/shared/base_rcon.h" constexpr const char* NETCON_VERSION = "2.0.0.1"; @@ -37,7 +36,7 @@ public: virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override; bool Serialize(vector& vecBuf, const char* szReqBuf, - const char* szReqVal, const cl_rcon::request_t requestType) const; + const char* szReqVal, const netcon::request_e requestType) const; SocketHandle_t GetSocket(void); bool IsInitialized(void) const; @@ -47,6 +46,7 @@ private: bool m_bInitialized; bool m_bQuitting; bool m_bPromptConnect; + bool m_bEncryptFrames; float m_flTickInterval; characterset_t m_CharacterSet; diff --git a/r5dev/pluginsdk/CMakeLists.txt b/r5dev/pluginsdk/CMakeLists.txt index 47e85e8e..fc0482d5 100644 --- a/r5dev/pluginsdk/CMakeLists.txt +++ b/r5dev/pluginsdk/CMakeLists.txt @@ -23,8 +23,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "libspdlog" "SigCache_Pb" - "SV_RCon_Pb" - "CL_RCon_Pb" + "NetCon_Pb" "Rpcrt4.lib" ) diff --git a/r5dev/protoc/CMakeLists.txt b/r5dev/protoc/CMakeLists.txt index 8e78d772..c4fce5b3 100644 --- a/r5dev/protoc/CMakeLists.txt +++ b/r5dev/protoc/CMakeLists.txt @@ -23,25 +23,13 @@ add_sources( SOURCE_GROUP "Runtime" end_sources() thirdparty_suppress_warnings() -add_module( "lib" "SV_RCon_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE ) +add_module( "lib" "NetCon_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE ) start_sources() add_sources( SOURCE_GROUP "Runtime" - "sv_rcon.pb.cc" - "sv_rcon.pb.h" -) - -end_sources() -thirdparty_suppress_warnings() - -add_module( "lib" "CL_RCon_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE ) - -start_sources() - -add_sources( SOURCE_GROUP "Runtime" - "cl_rcon.pb.cc" - "cl_rcon.pb.h" + "netcon.pb.cc" + "netcon.pb.h" ) end_sources() diff --git a/r5dev/protoc/cl_rcon.pb.cc b/r5dev/protoc/cl_rcon.pb.cc deleted file mode 100644 index c577a653..00000000 --- a/r5dev/protoc/cl_rcon.pb.cc +++ /dev/null @@ -1,489 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: cl_rcon.proto - -#include "cl_rcon.pb.h" - -#include - -#include -#include -#include -#include -// @@protoc_insertion_point(includes) -#include - -PROTOBUF_PRAGMA_INIT_SEG - -namespace _pb = ::PROTOBUF_NAMESPACE_ID; -namespace _pbi = _pb::internal; - -namespace cl_rcon { -PROTOBUF_CONSTEXPR request::request( - ::_pbi::ConstantInitialized): _impl_{ - /*decltype(_impl_._has_bits_)*/{} - , /*decltype(_impl_._cached_size_)*/{} - , /*decltype(_impl_.requestmsg_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.requestval_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.messageid_)*/0 - , /*decltype(_impl_.messagetype_)*/0 - , /*decltype(_impl_.requesttype_)*/0} {} -struct requestDefaultTypeInternal { - PROTOBUF_CONSTEXPR requestDefaultTypeInternal() - : _instance(::_pbi::ConstantInitialized{}) {} - ~requestDefaultTypeInternal() {} - union { - request _instance; - }; -}; -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 requestDefaultTypeInternal _request_default_instance_; -} // namespace cl_rcon -namespace cl_rcon { -bool request_t_IsValid(int value) { - switch (value) { - case 0: - case 1: - case 2: - return true; - default: - return false; - } -} - -static ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed request_t_strings[3] = {}; - -static const char request_t_names[] = - "SERVERDATA_REQUEST_AUTH" - "SERVERDATA_REQUEST_EXECCOMMAND" - "SERVERDATA_REQUEST_SEND_CONSOLE_LOG"; - -static const ::PROTOBUF_NAMESPACE_ID::internal::EnumEntry request_t_entries[] = { - { {request_t_names + 0, 23}, 1 }, - { {request_t_names + 23, 30}, 0 }, - { {request_t_names + 53, 35}, 2 }, -}; - -static const int request_t_entries_by_number[] = { - 1, // 0 -> SERVERDATA_REQUEST_EXECCOMMAND - 0, // 1 -> SERVERDATA_REQUEST_AUTH - 2, // 2 -> SERVERDATA_REQUEST_SEND_CONSOLE_LOG -}; - -const std::string& request_t_Name( - request_t value) { - static const bool dummy = - ::PROTOBUF_NAMESPACE_ID::internal::InitializeEnumStrings( - request_t_entries, - request_t_entries_by_number, - 3, request_t_strings); - (void) dummy; - int idx = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumName( - request_t_entries, - request_t_entries_by_number, - 3, value); - return idx == -1 ? ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString() : - request_t_strings[idx].get(); -} -bool request_t_Parse( - ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, request_t* value) { - int int_value; - bool success = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumValue( - request_t_entries, 3, name, &int_value); - if (success) { - *value = static_cast(int_value); - } - return success; -} - -// =================================================================== - -class request::_Internal { - public: - using HasBits = decltype(std::declval()._impl_._has_bits_); - static void set_has_messageid(HasBits* has_bits) { - (*has_bits)[0] |= 4u; - } - static void set_has_messagetype(HasBits* has_bits) { - (*has_bits)[0] |= 8u; - } - static void set_has_requesttype(HasBits* has_bits) { - (*has_bits)[0] |= 16u; - } - static void set_has_requestmsg(HasBits* has_bits) { - (*has_bits)[0] |= 1u; - } - static void set_has_requestval(HasBits* has_bits) { - (*has_bits)[0] |= 2u; - } -}; - -request::request(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned) - : ::PROTOBUF_NAMESPACE_ID::MessageLite(arena, is_message_owned) { - SharedCtor(arena, is_message_owned); - // @@protoc_insertion_point(arena_constructor:cl_rcon.request) -} -request::request(const request& from) - : ::PROTOBUF_NAMESPACE_ID::MessageLite() { - request* const _this = this; (void)_this; - new (&_impl_) Impl_{ - decltype(_impl_._has_bits_){from._impl_._has_bits_} - , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.requestmsg_){} - , decltype(_impl_.requestval_){} - , decltype(_impl_.messageid_){} - , decltype(_impl_.messagetype_){} - , decltype(_impl_.requesttype_){}}; - - _internal_metadata_.MergeFrom(from._internal_metadata_); - _impl_.requestmsg_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.requestmsg_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_requestmsg()) { - _this->_impl_.requestmsg_.Set(from._internal_requestmsg(), - _this->GetArenaForAllocation()); - } - _impl_.requestval_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.requestval_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_requestval()) { - _this->_impl_.requestval_.Set(from._internal_requestval(), - _this->GetArenaForAllocation()); - } - ::memcpy(&_impl_.messageid_, &from._impl_.messageid_, - static_cast(reinterpret_cast(&_impl_.requesttype_) - - reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.requesttype_)); - // @@protoc_insertion_point(copy_constructor:cl_rcon.request) -} - -inline void request::SharedCtor( - ::_pb::Arena* arena, bool is_message_owned) { - (void)arena; - (void)is_message_owned; - new (&_impl_) Impl_{ - decltype(_impl_._has_bits_){} - , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.requestmsg_){} - , decltype(_impl_.requestval_){} - , decltype(_impl_.messageid_){0} - , decltype(_impl_.messagetype_){0} - , decltype(_impl_.requesttype_){0} - }; - _impl_.requestmsg_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.requestmsg_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.requestval_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.requestval_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING -} - -request::~request() { - // @@protoc_insertion_point(destructor:cl_rcon.request) - if (auto *arena = _internal_metadata_.DeleteReturnArena()) { - (void)arena; - return; - } - SharedDtor(); -} - -inline void request::SharedDtor() { - GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); - _impl_.requestmsg_.Destroy(); - _impl_.requestval_.Destroy(); -} - -void request::SetCachedSize(int size) const { - _impl_._cached_size_.Set(size); -} - -void request::Clear() { -// @@protoc_insertion_point(message_clear_start:cl_rcon.request) - uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - if (cached_has_bits & 0x00000001u) { - _impl_.requestmsg_.ClearNonDefaultToEmpty(); - } - if (cached_has_bits & 0x00000002u) { - _impl_.requestval_.ClearNonDefaultToEmpty(); - } - } - if (cached_has_bits & 0x0000001cu) { - ::memset(&_impl_.messageid_, 0, static_cast( - reinterpret_cast(&_impl_.requesttype_) - - reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.requesttype_)); - } - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -const char* request::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - _Internal::HasBits has_bits{}; - while (!ctx->Done(&ptr)) { - uint32_t tag; - ptr = ::_pbi::ReadTag(ptr, &tag); - switch (tag >> 3) { - // optional int32 messageID = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { - _Internal::set_has_messageid(&has_bits); - _impl_.messageid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); - CHK_(ptr); - } else - goto handle_unusual; - continue; - // optional int32 messageType = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { - _Internal::set_has_messagetype(&has_bits); - _impl_.messagetype_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); - CHK_(ptr); - } else - goto handle_unusual; - continue; - // optional .cl_rcon.request_t requestType = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { - uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - _internal_set_requesttype(static_cast<::cl_rcon::request_t>(val)); - } else - goto handle_unusual; - continue; - // optional string requestMsg = 4; - case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { - auto str = _internal_mutable_requestmsg(); - ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); - CHK_(ptr); - CHK_(::_pbi::VerifyUTF8(str, nullptr)); - } else - goto handle_unusual; - continue; - // optional string requestVal = 5; - case 5: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 42)) { - auto str = _internal_mutable_requestval(); - ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); - CHK_(ptr); - CHK_(::_pbi::VerifyUTF8(str, nullptr)); - } else - goto handle_unusual; - continue; - default: - goto handle_unusual; - } // switch - handle_unusual: - if ((tag == 0) || ((tag & 7) == 4)) { - CHK_(ptr); - ctx->SetLastTag(tag); - goto message_done; - } - ptr = UnknownFieldParse( - tag, - _internal_metadata_.mutable_unknown_fields(), - ptr, ctx); - CHK_(ptr != nullptr); - } // while -message_done: - _impl_._has_bits_.Or(has_bits); - return ptr; -failure: - ptr = nullptr; - goto message_done; -#undef CHK_ -} - -uint8_t* request::_InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:cl_rcon.request) - uint32_t cached_has_bits = 0; - (void) cached_has_bits; - - // optional int32 messageID = 1; - if (_internal_has_messageid()) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_messageid(), target); - } - - // optional int32 messageType = 2; - if (_internal_has_messagetype()) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_messagetype(), target); - } - - // optional .cl_rcon.request_t requestType = 3; - if (_internal_has_requesttype()) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 3, this->_internal_requesttype(), target); - } - - // optional string requestMsg = 4; - if (_internal_has_requestmsg()) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( - this->_internal_requestmsg().data(), static_cast(this->_internal_requestmsg().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, - "cl_rcon.request.requestMsg"); - target = stream->WriteStringMaybeAliased( - 4, this->_internal_requestmsg(), target); - } - - // optional string requestVal = 5; - if (_internal_has_requestval()) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( - this->_internal_requestval().data(), static_cast(this->_internal_requestval().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, - "cl_rcon.request.requestVal"); - target = stream->WriteStringMaybeAliased( - 5, this->_internal_requestval(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = stream->WriteRaw(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(), - static_cast(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size()), target); - } - // @@protoc_insertion_point(serialize_to_array_end:cl_rcon.request) - return target; -} - -size_t request::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:cl_rcon.request) - size_t total_size = 0; - - uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { - // optional string requestMsg = 4; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_requestmsg()); - } - - // optional string requestVal = 5; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_requestval()); - } - - // optional int32 messageID = 1; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messageid()); - } - - // optional int32 messageType = 2; - if (cached_has_bits & 0x00000008u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messagetype()); - } - - // optional .cl_rcon.request_t requestType = 3; - if (cached_has_bits & 0x00000010u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_requesttype()); - } - - } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - total_size += _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size(); - } - int cached_size = ::_pbi::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void request::CheckTypeAndMergeFrom( - const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) { - MergeFrom(*::_pbi::DownCast( - &from)); -} - -void request::MergeFrom(const request& from) { - request* const _this = this; - // @@protoc_insertion_point(class_specific_merge_from_start:cl_rcon.request) - GOOGLE_DCHECK_NE(&from, _this); - uint32_t cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { - if (cached_has_bits & 0x00000001u) { - _this->_internal_set_requestmsg(from._internal_requestmsg()); - } - if (cached_has_bits & 0x00000002u) { - _this->_internal_set_requestval(from._internal_requestval()); - } - if (cached_has_bits & 0x00000004u) { - _this->_impl_.messageid_ = from._impl_.messageid_; - } - if (cached_has_bits & 0x00000008u) { - _this->_impl_.messagetype_ = from._impl_.messagetype_; - } - if (cached_has_bits & 0x00000010u) { - _this->_impl_.requesttype_ = from._impl_.requesttype_; - } - _this->_impl_._has_bits_[0] |= cached_has_bits; - } - _this->_internal_metadata_.MergeFrom(from._internal_metadata_); -} - -void request::CopyFrom(const request& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:cl_rcon.request) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool request::IsInitialized() const { - return true; -} - -void request::InternalSwap(request* other) { - using std::swap; - auto* lhs_arena = GetArenaForAllocation(); - auto* rhs_arena = other->GetArenaForAllocation(); - _internal_metadata_.InternalSwap(&other->_internal_metadata_); - swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.requestmsg_, lhs_arena, - &other->_impl_.requestmsg_, rhs_arena - ); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.requestval_, lhs_arena, - &other->_impl_.requestval_, rhs_arena - ); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(request, _impl_.requesttype_) - + sizeof(request::_impl_.requesttype_) - - PROTOBUF_FIELD_OFFSET(request, _impl_.messageid_)>( - reinterpret_cast(&_impl_.messageid_), - reinterpret_cast(&other->_impl_.messageid_)); -} - -std::string request::GetTypeName() const { - return "cl_rcon.request"; -} - - -// @@protoc_insertion_point(namespace_scope) -} // namespace cl_rcon -PROTOBUF_NAMESPACE_OPEN -template<> PROTOBUF_NOINLINE ::cl_rcon::request* -Arena::CreateMaybeMessage< ::cl_rcon::request >(Arena* arena) { - return Arena::CreateMessageInternal< ::cl_rcon::request >(arena); -} -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) -#include diff --git a/r5dev/protoc/cl_rcon.pb.h b/r5dev/protoc/cl_rcon.pb.h deleted file mode 100644 index 55fd5689..00000000 --- a/r5dev/protoc/cl_rcon.pb.h +++ /dev/null @@ -1,530 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: cl_rcon.proto - -#ifndef GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto - -#include -#include - -#include -#if PROTOBUF_VERSION < 3021000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include // IWYU pragma: export -#include // IWYU pragma: export -#include -// @@protoc_insertion_point(includes) -#include -#define PROTOBUF_INTERNAL_EXPORT_cl_5frcon_2eproto -PROTOBUF_NAMESPACE_OPEN -namespace internal { -class AnyMetadata; -} // namespace internal -PROTOBUF_NAMESPACE_CLOSE - -// Internal implementation detail -- do not use these members. -struct TableStruct_cl_5frcon_2eproto { - static const uint32_t offsets[]; -}; -namespace cl_rcon { -class request; -struct requestDefaultTypeInternal; -extern requestDefaultTypeInternal _request_default_instance_; -} // namespace cl_rcon -PROTOBUF_NAMESPACE_OPEN -template<> ::cl_rcon::request* Arena::CreateMaybeMessage<::cl_rcon::request>(Arena*); -PROTOBUF_NAMESPACE_CLOSE -namespace cl_rcon { - -enum request_t : int { - SERVERDATA_REQUEST_EXECCOMMAND = 0, - SERVERDATA_REQUEST_AUTH = 1, - SERVERDATA_REQUEST_SEND_CONSOLE_LOG = 2, - request_t_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(), - request_t_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max() -}; -bool request_t_IsValid(int value); -constexpr request_t request_t_MIN = SERVERDATA_REQUEST_EXECCOMMAND; -constexpr request_t request_t_MAX = SERVERDATA_REQUEST_SEND_CONSOLE_LOG; -constexpr int request_t_ARRAYSIZE = request_t_MAX + 1; - -const std::string& request_t_Name(request_t value); -template -inline const std::string& request_t_Name(T enum_t_value) { - static_assert(::std::is_same::value || - ::std::is_integral::value, - "Incorrect type passed to function request_t_Name."); - return request_t_Name(static_cast(enum_t_value)); -} -bool request_t_Parse( - ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, request_t* value); -// =================================================================== - -class request final : - public ::PROTOBUF_NAMESPACE_ID::MessageLite /* @@protoc_insertion_point(class_definition:cl_rcon.request) */ { - public: - inline request() : request(nullptr) {} - ~request() override; - explicit PROTOBUF_CONSTEXPR request(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); - - request(const request& from); - request(request&& from) noexcept - : request() { - *this = ::std::move(from); - } - - inline request& operator=(const request& from) { - CopyFrom(from); - return *this; - } - inline request& operator=(request&& from) noexcept { - if (this == &from) return *this; - if (GetOwningArena() == from.GetOwningArena() - #ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetOwningArena() != nullptr - #endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { - InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const request& default_instance() { - return *internal_default_instance(); - } - static inline const request* internal_default_instance() { - return reinterpret_cast( - &_request_default_instance_); - } - static constexpr int kIndexInFileMessages = - 0; - - friend void swap(request& a, request& b) { - a.Swap(&b); - } - inline void Swap(request* other) { - if (other == this) return; - #ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetOwningArena() != nullptr && - GetOwningArena() == other->GetOwningArena()) { - #else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetOwningArena() == other->GetOwningArena()) { - #endif // !PROTOBUF_FORCE_COPY_IN_SWAP - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(request* other) { - if (other == this) return; - GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - request* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { - return CreateMaybeMessage(arena); - } - void CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) final; - void CopyFrom(const request& from); - void MergeFrom(const request& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - uint8_t* _InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _impl_._cached_size_.Get(); } - - private: - void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); - void SharedDtor(); - void SetCachedSize(int size) const; - void InternalSwap(request* other); - - private: - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "cl_rcon.request"; - } - protected: - explicit request(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned = false); - public: - - std::string GetTypeName() const final; - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kRequestMsgFieldNumber = 4, - kRequestValFieldNumber = 5, - kMessageIDFieldNumber = 1, - kMessageTypeFieldNumber = 2, - kRequestTypeFieldNumber = 3, - }; - // optional string requestMsg = 4; - bool has_requestmsg() const; - private: - bool _internal_has_requestmsg() const; - public: - void clear_requestmsg(); - const std::string& requestmsg() const; - template - void set_requestmsg(ArgT0&& arg0, ArgT... args); - std::string* mutable_requestmsg(); - PROTOBUF_NODISCARD std::string* release_requestmsg(); - void set_allocated_requestmsg(std::string* requestmsg); - private: - const std::string& _internal_requestmsg() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestmsg(const std::string& value); - std::string* _internal_mutable_requestmsg(); - public: - - // optional string requestVal = 5; - bool has_requestval() const; - private: - bool _internal_has_requestval() const; - public: - void clear_requestval(); - const std::string& requestval() const; - template - void set_requestval(ArgT0&& arg0, ArgT... args); - std::string* mutable_requestval(); - PROTOBUF_NODISCARD std::string* release_requestval(); - void set_allocated_requestval(std::string* requestval); - private: - const std::string& _internal_requestval() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestval(const std::string& value); - std::string* _internal_mutable_requestval(); - public: - - // optional int32 messageID = 1; - bool has_messageid() const; - private: - bool _internal_has_messageid() const; - public: - void clear_messageid(); - int32_t messageid() const; - void set_messageid(int32_t value); - private: - int32_t _internal_messageid() const; - void _internal_set_messageid(int32_t value); - public: - - // optional int32 messageType = 2; - bool has_messagetype() const; - private: - bool _internal_has_messagetype() const; - public: - void clear_messagetype(); - int32_t messagetype() const; - void set_messagetype(int32_t value); - private: - int32_t _internal_messagetype() const; - void _internal_set_messagetype(int32_t value); - public: - - // optional .cl_rcon.request_t requestType = 3; - bool has_requesttype() const; - private: - bool _internal_has_requesttype() const; - public: - void clear_requesttype(); - ::cl_rcon::request_t requesttype() const; - void set_requesttype(::cl_rcon::request_t value); - private: - ::cl_rcon::request_t _internal_requesttype() const; - void _internal_set_requesttype(::cl_rcon::request_t value); - public: - - // @@protoc_insertion_point(class_scope:cl_rcon.request) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - struct Impl_ { - ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr requestmsg_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr requestval_; - int32_t messageid_; - int32_t messagetype_; - int requesttype_; - }; - union { Impl_ _impl_; }; - friend struct ::TableStruct_cl_5frcon_2eproto; -}; -// =================================================================== - - -// =================================================================== - -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // __GNUC__ -// request - -// optional int32 messageID = 1; -inline bool request::_internal_has_messageid() const { - bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; - return value; -} -inline bool request::has_messageid() const { - return _internal_has_messageid(); -} -inline void request::clear_messageid() { - _impl_.messageid_ = 0; - _impl_._has_bits_[0] &= ~0x00000004u; -} -inline int32_t request::_internal_messageid() const { - return _impl_.messageid_; -} -inline int32_t request::messageid() const { - // @@protoc_insertion_point(field_get:cl_rcon.request.messageID) - return _internal_messageid(); -} -inline void request::_internal_set_messageid(int32_t value) { - _impl_._has_bits_[0] |= 0x00000004u; - _impl_.messageid_ = value; -} -inline void request::set_messageid(int32_t value) { - _internal_set_messageid(value); - // @@protoc_insertion_point(field_set:cl_rcon.request.messageID) -} - -// optional int32 messageType = 2; -inline bool request::_internal_has_messagetype() const { - bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; - return value; -} -inline bool request::has_messagetype() const { - return _internal_has_messagetype(); -} -inline void request::clear_messagetype() { - _impl_.messagetype_ = 0; - _impl_._has_bits_[0] &= ~0x00000008u; -} -inline int32_t request::_internal_messagetype() const { - return _impl_.messagetype_; -} -inline int32_t request::messagetype() const { - // @@protoc_insertion_point(field_get:cl_rcon.request.messageType) - return _internal_messagetype(); -} -inline void request::_internal_set_messagetype(int32_t value) { - _impl_._has_bits_[0] |= 0x00000008u; - _impl_.messagetype_ = value; -} -inline void request::set_messagetype(int32_t value) { - _internal_set_messagetype(value); - // @@protoc_insertion_point(field_set:cl_rcon.request.messageType) -} - -// optional .cl_rcon.request_t requestType = 3; -inline bool request::_internal_has_requesttype() const { - bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; - return value; -} -inline bool request::has_requesttype() const { - return _internal_has_requesttype(); -} -inline void request::clear_requesttype() { - _impl_.requesttype_ = 0; - _impl_._has_bits_[0] &= ~0x00000010u; -} -inline ::cl_rcon::request_t request::_internal_requesttype() const { - return static_cast< ::cl_rcon::request_t >(_impl_.requesttype_); -} -inline ::cl_rcon::request_t request::requesttype() const { - // @@protoc_insertion_point(field_get:cl_rcon.request.requestType) - return _internal_requesttype(); -} -inline void request::_internal_set_requesttype(::cl_rcon::request_t value) { - _impl_._has_bits_[0] |= 0x00000010u; - _impl_.requesttype_ = value; -} -inline void request::set_requesttype(::cl_rcon::request_t value) { - _internal_set_requesttype(value); - // @@protoc_insertion_point(field_set:cl_rcon.request.requestType) -} - -// optional string requestMsg = 4; -inline bool request::_internal_has_requestmsg() const { - bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; - return value; -} -inline bool request::has_requestmsg() const { - return _internal_has_requestmsg(); -} -inline void request::clear_requestmsg() { - _impl_.requestmsg_.ClearToEmpty(); - _impl_._has_bits_[0] &= ~0x00000001u; -} -inline const std::string& request::requestmsg() const { - // @@protoc_insertion_point(field_get:cl_rcon.request.requestMsg) - return _internal_requestmsg(); -} -template -inline PROTOBUF_ALWAYS_INLINE -void request::set_requestmsg(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.requestmsg_.Set(static_cast(arg0), args..., GetArenaForAllocation()); - // @@protoc_insertion_point(field_set:cl_rcon.request.requestMsg) -} -inline std::string* request::mutable_requestmsg() { - std::string* _s = _internal_mutable_requestmsg(); - // @@protoc_insertion_point(field_mutable:cl_rcon.request.requestMsg) - return _s; -} -inline const std::string& request::_internal_requestmsg() const { - return _impl_.requestmsg_.Get(); -} -inline void request::_internal_set_requestmsg(const std::string& value) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.requestmsg_.Set(value, GetArenaForAllocation()); -} -inline std::string* request::_internal_mutable_requestmsg() { - _impl_._has_bits_[0] |= 0x00000001u; - return _impl_.requestmsg_.Mutable(GetArenaForAllocation()); -} -inline std::string* request::release_requestmsg() { - // @@protoc_insertion_point(field_release:cl_rcon.request.requestMsg) - if (!_internal_has_requestmsg()) { - return nullptr; - } - _impl_._has_bits_[0] &= ~0x00000001u; - auto* p = _impl_.requestmsg_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.requestmsg_.IsDefault()) { - _impl_.requestmsg_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void request::set_allocated_requestmsg(std::string* requestmsg) { - if (requestmsg != nullptr) { - _impl_._has_bits_[0] |= 0x00000001u; - } else { - _impl_._has_bits_[0] &= ~0x00000001u; - } - _impl_.requestmsg_.SetAllocated(requestmsg, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.requestmsg_.IsDefault()) { - _impl_.requestmsg_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - // @@protoc_insertion_point(field_set_allocated:cl_rcon.request.requestMsg) -} - -// optional string requestVal = 5; -inline bool request::_internal_has_requestval() const { - bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; - return value; -} -inline bool request::has_requestval() const { - return _internal_has_requestval(); -} -inline void request::clear_requestval() { - _impl_.requestval_.ClearToEmpty(); - _impl_._has_bits_[0] &= ~0x00000002u; -} -inline const std::string& request::requestval() const { - // @@protoc_insertion_point(field_get:cl_rcon.request.requestVal) - return _internal_requestval(); -} -template -inline PROTOBUF_ALWAYS_INLINE -void request::set_requestval(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.requestval_.Set(static_cast(arg0), args..., GetArenaForAllocation()); - // @@protoc_insertion_point(field_set:cl_rcon.request.requestVal) -} -inline std::string* request::mutable_requestval() { - std::string* _s = _internal_mutable_requestval(); - // @@protoc_insertion_point(field_mutable:cl_rcon.request.requestVal) - return _s; -} -inline const std::string& request::_internal_requestval() const { - return _impl_.requestval_.Get(); -} -inline void request::_internal_set_requestval(const std::string& value) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.requestval_.Set(value, GetArenaForAllocation()); -} -inline std::string* request::_internal_mutable_requestval() { - _impl_._has_bits_[0] |= 0x00000002u; - return _impl_.requestval_.Mutable(GetArenaForAllocation()); -} -inline std::string* request::release_requestval() { - // @@protoc_insertion_point(field_release:cl_rcon.request.requestVal) - if (!_internal_has_requestval()) { - return nullptr; - } - _impl_._has_bits_[0] &= ~0x00000002u; - auto* p = _impl_.requestval_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.requestval_.IsDefault()) { - _impl_.requestval_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void request::set_allocated_requestval(std::string* requestval) { - if (requestval != nullptr) { - _impl_._has_bits_[0] |= 0x00000002u; - } else { - _impl_._has_bits_[0] &= ~0x00000002u; - } - _impl_.requestval_.SetAllocated(requestval, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.requestval_.IsDefault()) { - _impl_.requestval_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - // @@protoc_insertion_point(field_set_allocated:cl_rcon.request.requestVal) -} - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif // __GNUC__ - -// @@protoc_insertion_point(namespace_scope) - -} // namespace cl_rcon - -PROTOBUF_NAMESPACE_OPEN - -template <> struct is_proto_enum< ::cl_rcon::request_t> : ::std::true_type {}; - -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) - -#include -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto diff --git a/r5dev/protoc/netcon.pb.cc b/r5dev/protoc/netcon.pb.cc new file mode 100644 index 00000000..cc7ea65f --- /dev/null +++ b/r5dev/protoc/netcon.pb.cc @@ -0,0 +1,1235 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: netcon.proto + +#include "netcon.pb.h" + +#include + +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +namespace netcon { +PROTOBUF_CONSTEXPR request::request( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.requestmsg_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.requestval_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.messageid_)*/0 + , /*decltype(_impl_.messagetype_)*/0 + , /*decltype(_impl_.requesttype_)*/0} {} +struct requestDefaultTypeInternal { + PROTOBUF_CONSTEXPR requestDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~requestDefaultTypeInternal() {} + union { + request _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 requestDefaultTypeInternal _request_default_instance_; +PROTOBUF_CONSTEXPR response::response( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.responsemsg_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.responseval_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.messageid_)*/0 + , /*decltype(_impl_.messagetype_)*/0 + , /*decltype(_impl_.responsetype_)*/0} {} +struct responseDefaultTypeInternal { + PROTOBUF_CONSTEXPR responseDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~responseDefaultTypeInternal() {} + union { + response _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 responseDefaultTypeInternal _response_default_instance_; +PROTOBUF_CONSTEXPR envelope::envelope( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.nonce_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.data_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.encrypted_)*/false + , /*decltype(_impl_._cached_size_)*/{}} {} +struct envelopeDefaultTypeInternal { + PROTOBUF_CONSTEXPR envelopeDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~envelopeDefaultTypeInternal() {} + union { + envelope _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 envelopeDefaultTypeInternal _envelope_default_instance_; +} // namespace netcon +namespace netcon { +bool request_e_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +static ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed request_e_strings[3] = {}; + +static const char request_e_names[] = + "SERVERDATA_REQUEST_AUTH" + "SERVERDATA_REQUEST_EXECCOMMAND" + "SERVERDATA_REQUEST_SEND_CONSOLE_LOG"; + +static const ::PROTOBUF_NAMESPACE_ID::internal::EnumEntry request_e_entries[] = { + { {request_e_names + 0, 23}, 1 }, + { {request_e_names + 23, 30}, 0 }, + { {request_e_names + 53, 35}, 2 }, +}; + +static const int request_e_entries_by_number[] = { + 1, // 0 -> SERVERDATA_REQUEST_EXECCOMMAND + 0, // 1 -> SERVERDATA_REQUEST_AUTH + 2, // 2 -> SERVERDATA_REQUEST_SEND_CONSOLE_LOG +}; + +const std::string& request_e_Name( + request_e value) { + static const bool dummy = + ::PROTOBUF_NAMESPACE_ID::internal::InitializeEnumStrings( + request_e_entries, + request_e_entries_by_number, + 3, request_e_strings); + (void) dummy; + int idx = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumName( + request_e_entries, + request_e_entries_by_number, + 3, value); + return idx == -1 ? ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString() : + request_e_strings[idx].get(); +} +bool request_e_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, request_e* value) { + int int_value; + bool success = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumValue( + request_e_entries, 3, name, &int_value); + if (success) { + *value = static_cast(int_value); + } + return success; +} +bool response_e_IsValid(int value) { + switch (value) { + case 0: + case 1: + return true; + default: + return false; + } +} + +static ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed response_e_strings[2] = {}; + +static const char response_e_names[] = + "SERVERDATA_RESPONSE_AUTH" + "SERVERDATA_RESPONSE_CONSOLE_LOG"; + +static const ::PROTOBUF_NAMESPACE_ID::internal::EnumEntry response_e_entries[] = { + { {response_e_names + 0, 24}, 0 }, + { {response_e_names + 24, 31}, 1 }, +}; + +static const int response_e_entries_by_number[] = { + 0, // 0 -> SERVERDATA_RESPONSE_AUTH + 1, // 1 -> SERVERDATA_RESPONSE_CONSOLE_LOG +}; + +const std::string& response_e_Name( + response_e value) { + static const bool dummy = + ::PROTOBUF_NAMESPACE_ID::internal::InitializeEnumStrings( + response_e_entries, + response_e_entries_by_number, + 2, response_e_strings); + (void) dummy; + int idx = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumName( + response_e_entries, + response_e_entries_by_number, + 2, value); + return idx == -1 ? ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString() : + response_e_strings[idx].get(); +} +bool response_e_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, response_e* value) { + int int_value; + bool success = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumValue( + response_e_entries, 2, name, &int_value); + if (success) { + *value = static_cast(int_value); + } + return success; +} + +// =================================================================== + +class request::_Internal { + public: + using HasBits = decltype(std::declval()._impl_._has_bits_); + static void set_has_messageid(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_messagetype(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_requesttype(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_requestmsg(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_requestval(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +request::request(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::MessageLite(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:netcon.request) +} +request::request(const request& from) + : ::PROTOBUF_NAMESPACE_ID::MessageLite() { + request* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.requestmsg_){} + , decltype(_impl_.requestval_){} + , decltype(_impl_.messageid_){} + , decltype(_impl_.messagetype_){} + , decltype(_impl_.requesttype_){}}; + + _internal_metadata_.MergeFrom(from._internal_metadata_); + _impl_.requestmsg_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.requestmsg_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_requestmsg()) { + _this->_impl_.requestmsg_.Set(from._internal_requestmsg(), + _this->GetArenaForAllocation()); + } + _impl_.requestval_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.requestval_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_requestval()) { + _this->_impl_.requestval_.Set(from._internal_requestval(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.messageid_, &from._impl_.messageid_, + static_cast(reinterpret_cast(&_impl_.requesttype_) - + reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.requesttype_)); + // @@protoc_insertion_point(copy_constructor:netcon.request) +} + +inline void request::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.requestmsg_){} + , decltype(_impl_.requestval_){} + , decltype(_impl_.messageid_){0} + , decltype(_impl_.messagetype_){0} + , decltype(_impl_.requesttype_){0} + }; + _impl_.requestmsg_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.requestmsg_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.requestval_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.requestval_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +request::~request() { + // @@protoc_insertion_point(destructor:netcon.request) + if (auto *arena = _internal_metadata_.DeleteReturnArena()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void request::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.requestmsg_.Destroy(); + _impl_.requestval_.Destroy(); +} + +void request::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void request::Clear() { +// @@protoc_insertion_point(message_clear_start:netcon.request) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.requestmsg_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.requestval_.ClearNonDefaultToEmpty(); + } + } + if (cached_has_bits & 0x0000001cu) { + ::memset(&_impl_.messageid_, 0, static_cast( + reinterpret_cast(&_impl_.requesttype_) - + reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.requesttype_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear(); +} + +const char* request::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional int32 messageId = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + _Internal::set_has_messageid(&has_bits); + _impl_.messageid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 messageType = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + _Internal::set_has_messagetype(&has_bits); + _impl_.messagetype_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .netcon.request_e requestType = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_requesttype(static_cast<::netcon::request_e>(val)); + } else + goto handle_unusual; + continue; + // optional string requestMsg = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { + auto str = _internal_mutable_requestmsg(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, nullptr)); + } else + goto handle_unusual; + continue; + // optional string requestVal = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 42)) { + auto str = _internal_mutable_requestval(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, nullptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* request::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:netcon.request) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // optional int32 messageId = 1; + if (_internal_has_messageid()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_messageid(), target); + } + + // optional int32 messageType = 2; + if (_internal_has_messagetype()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_messagetype(), target); + } + + // optional .netcon.request_e requestType = 3; + if (_internal_has_requesttype()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this->_internal_requesttype(), target); + } + + // optional string requestMsg = 4; + if (_internal_has_requestmsg()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_requestmsg().data(), static_cast(this->_internal_requestmsg().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "netcon.request.requestMsg"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_requestmsg(), target); + } + + // optional string requestVal = 5; + if (_internal_has_requestval()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_requestval().data(), static_cast(this->_internal_requestval().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "netcon.request.requestVal"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_requestval(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = stream->WriteRaw(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(), + static_cast(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:netcon.request) + return target; +} + +size_t request::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:netcon.request) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + // optional string requestMsg = 4; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_requestmsg()); + } + + // optional string requestVal = 5; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_requestval()); + } + + // optional int32 messageId = 1; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messageid()); + } + + // optional int32 messageType = 2; + if (cached_has_bits & 0x00000008u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messagetype()); + } + + // optional .netcon.request_e requestType = 3; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_requesttype()); + } + + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + total_size += _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size(); + } + int cached_size = ::_pbi::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void request::CheckTypeAndMergeFrom( + const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) { + MergeFrom(*::_pbi::DownCast( + &from)); +} + +void request::MergeFrom(const request& from) { + request* const _this = this; + // @@protoc_insertion_point(class_specific_merge_from_start:netcon.request) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_requestmsg(from._internal_requestmsg()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_requestval(from._internal_requestval()); + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.messageid_ = from._impl_.messageid_; + } + if (cached_has_bits & 0x00000008u) { + _this->_impl_.messagetype_ = from._impl_.messagetype_; + } + if (cached_has_bits & 0x00000010u) { + _this->_impl_.requesttype_ = from._impl_.requesttype_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom(from._internal_metadata_); +} + +void request::CopyFrom(const request& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:netcon.request) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool request::IsInitialized() const { + return true; +} + +void request::InternalSwap(request* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.requestmsg_, lhs_arena, + &other->_impl_.requestmsg_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.requestval_, lhs_arena, + &other->_impl_.requestval_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(request, _impl_.requesttype_) + + sizeof(request::_impl_.requesttype_) + - PROTOBUF_FIELD_OFFSET(request, _impl_.messageid_)>( + reinterpret_cast(&_impl_.messageid_), + reinterpret_cast(&other->_impl_.messageid_)); +} + +std::string request::GetTypeName() const { + return "netcon.request"; +} + + +// =================================================================== + +class response::_Internal { + public: + using HasBits = decltype(std::declval()._impl_._has_bits_); + static void set_has_messageid(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_messagetype(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_responsetype(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_responsemsg(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_responseval(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +response::response(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::MessageLite(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:netcon.response) +} +response::response(const response& from) + : ::PROTOBUF_NAMESPACE_ID::MessageLite() { + response* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.responsemsg_){} + , decltype(_impl_.responseval_){} + , decltype(_impl_.messageid_){} + , decltype(_impl_.messagetype_){} + , decltype(_impl_.responsetype_){}}; + + _internal_metadata_.MergeFrom(from._internal_metadata_); + _impl_.responsemsg_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.responsemsg_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_responsemsg()) { + _this->_impl_.responsemsg_.Set(from._internal_responsemsg(), + _this->GetArenaForAllocation()); + } + _impl_.responseval_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.responseval_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_responseval()) { + _this->_impl_.responseval_.Set(from._internal_responseval(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.messageid_, &from._impl_.messageid_, + static_cast(reinterpret_cast(&_impl_.responsetype_) - + reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.responsetype_)); + // @@protoc_insertion_point(copy_constructor:netcon.response) +} + +inline void response::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.responsemsg_){} + , decltype(_impl_.responseval_){} + , decltype(_impl_.messageid_){0} + , decltype(_impl_.messagetype_){0} + , decltype(_impl_.responsetype_){0} + }; + _impl_.responsemsg_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.responsemsg_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.responseval_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.responseval_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +response::~response() { + // @@protoc_insertion_point(destructor:netcon.response) + if (auto *arena = _internal_metadata_.DeleteReturnArena()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void response::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.responsemsg_.Destroy(); + _impl_.responseval_.Destroy(); +} + +void response::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void response::Clear() { +// @@protoc_insertion_point(message_clear_start:netcon.response) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.responsemsg_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.responseval_.ClearNonDefaultToEmpty(); + } + } + if (cached_has_bits & 0x0000001cu) { + ::memset(&_impl_.messageid_, 0, static_cast( + reinterpret_cast(&_impl_.responsetype_) - + reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.responsetype_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear(); +} + +const char* response::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional int32 messageId = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + _Internal::set_has_messageid(&has_bits); + _impl_.messageid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 messageType = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + _Internal::set_has_messagetype(&has_bits); + _impl_.messagetype_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .netcon.response_e responseType = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_responsetype(static_cast<::netcon::response_e>(val)); + } else + goto handle_unusual; + continue; + // optional string responseMsg = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { + auto str = _internal_mutable_responsemsg(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, nullptr)); + } else + goto handle_unusual; + continue; + // optional string responseVal = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 42)) { + auto str = _internal_mutable_responseval(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, nullptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* response::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:netcon.response) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // optional int32 messageId = 1; + if (_internal_has_messageid()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_messageid(), target); + } + + // optional int32 messageType = 2; + if (_internal_has_messagetype()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_messagetype(), target); + } + + // optional .netcon.response_e responseType = 3; + if (_internal_has_responsetype()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this->_internal_responsetype(), target); + } + + // optional string responseMsg = 4; + if (_internal_has_responsemsg()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_responsemsg().data(), static_cast(this->_internal_responsemsg().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "netcon.response.responseMsg"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_responsemsg(), target); + } + + // optional string responseVal = 5; + if (_internal_has_responseval()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_responseval().data(), static_cast(this->_internal_responseval().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "netcon.response.responseVal"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_responseval(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = stream->WriteRaw(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(), + static_cast(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:netcon.response) + return target; +} + +size_t response::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:netcon.response) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + // optional string responseMsg = 4; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_responsemsg()); + } + + // optional string responseVal = 5; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_responseval()); + } + + // optional int32 messageId = 1; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messageid()); + } + + // optional int32 messageType = 2; + if (cached_has_bits & 0x00000008u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messagetype()); + } + + // optional .netcon.response_e responseType = 3; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_responsetype()); + } + + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + total_size += _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size(); + } + int cached_size = ::_pbi::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void response::CheckTypeAndMergeFrom( + const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) { + MergeFrom(*::_pbi::DownCast( + &from)); +} + +void response::MergeFrom(const response& from) { + response* const _this = this; + // @@protoc_insertion_point(class_specific_merge_from_start:netcon.response) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_responsemsg(from._internal_responsemsg()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_responseval(from._internal_responseval()); + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.messageid_ = from._impl_.messageid_; + } + if (cached_has_bits & 0x00000008u) { + _this->_impl_.messagetype_ = from._impl_.messagetype_; + } + if (cached_has_bits & 0x00000010u) { + _this->_impl_.responsetype_ = from._impl_.responsetype_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom(from._internal_metadata_); +} + +void response::CopyFrom(const response& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:netcon.response) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool response::IsInitialized() const { + return true; +} + +void response::InternalSwap(response* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.responsemsg_, lhs_arena, + &other->_impl_.responsemsg_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.responseval_, lhs_arena, + &other->_impl_.responseval_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(response, _impl_.responsetype_) + + sizeof(response::_impl_.responsetype_) + - PROTOBUF_FIELD_OFFSET(response, _impl_.messageid_)>( + reinterpret_cast(&_impl_.messageid_), + reinterpret_cast(&other->_impl_.messageid_)); +} + +std::string response::GetTypeName() const { + return "netcon.response"; +} + + +// =================================================================== + +class envelope::_Internal { + public: +}; + +envelope::envelope(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::MessageLite(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:netcon.envelope) +} +envelope::envelope(const envelope& from) + : ::PROTOBUF_NAMESPACE_ID::MessageLite() { + envelope* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.nonce_){} + , decltype(_impl_.data_){} + , decltype(_impl_.encrypted_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom(from._internal_metadata_); + _impl_.nonce_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.nonce_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_nonce().empty()) { + _this->_impl_.nonce_.Set(from._internal_nonce(), + _this->GetArenaForAllocation()); + } + _impl_.data_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.data_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_data().empty()) { + _this->_impl_.data_.Set(from._internal_data(), + _this->GetArenaForAllocation()); + } + _this->_impl_.encrypted_ = from._impl_.encrypted_; + // @@protoc_insertion_point(copy_constructor:netcon.envelope) +} + +inline void envelope::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.nonce_){} + , decltype(_impl_.data_){} + , decltype(_impl_.encrypted_){false} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.nonce_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.nonce_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.data_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.data_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +envelope::~envelope() { + // @@protoc_insertion_point(destructor:netcon.envelope) + if (auto *arena = _internal_metadata_.DeleteReturnArena()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void envelope::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.nonce_.Destroy(); + _impl_.data_.Destroy(); +} + +void envelope::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void envelope::Clear() { +// @@protoc_insertion_point(message_clear_start:netcon.envelope) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.nonce_.ClearToEmpty(); + _impl_.data_.ClearToEmpty(); + _impl_.encrypted_ = false; + _internal_metadata_.Clear(); +} + +const char* envelope::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // bool encrypted = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + _impl_.encrypted_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // bytes nonce = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 18)) { + auto str = _internal_mutable_nonce(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // bytes data = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 26)) { + auto str = _internal_mutable_data(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* envelope::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:netcon.envelope) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // bool encrypted = 1; + if (this->_internal_encrypted() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(1, this->_internal_encrypted(), target); + } + + // bytes nonce = 2; + if (!this->_internal_nonce().empty()) { + target = stream->WriteBytesMaybeAliased( + 2, this->_internal_nonce(), target); + } + + // bytes data = 3; + if (!this->_internal_data().empty()) { + target = stream->WriteBytesMaybeAliased( + 3, this->_internal_data(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = stream->WriteRaw(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(), + static_cast(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:netcon.envelope) + return target; +} + +size_t envelope::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:netcon.envelope) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // bytes nonce = 2; + if (!this->_internal_nonce().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_nonce()); + } + + // bytes data = 3; + if (!this->_internal_data().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_data()); + } + + // bool encrypted = 1; + if (this->_internal_encrypted() != 0) { + total_size += 1 + 1; + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + total_size += _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size(); + } + int cached_size = ::_pbi::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void envelope::CheckTypeAndMergeFrom( + const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) { + MergeFrom(*::_pbi::DownCast( + &from)); +} + +void envelope::MergeFrom(const envelope& from) { + envelope* const _this = this; + // @@protoc_insertion_point(class_specific_merge_from_start:netcon.envelope) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_nonce().empty()) { + _this->_internal_set_nonce(from._internal_nonce()); + } + if (!from._internal_data().empty()) { + _this->_internal_set_data(from._internal_data()); + } + if (from._internal_encrypted() != 0) { + _this->_internal_set_encrypted(from._internal_encrypted()); + } + _this->_internal_metadata_.MergeFrom(from._internal_metadata_); +} + +void envelope::CopyFrom(const envelope& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:netcon.envelope) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool envelope::IsInitialized() const { + return true; +} + +void envelope::InternalSwap(envelope* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.nonce_, lhs_arena, + &other->_impl_.nonce_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.data_, lhs_arena, + &other->_impl_.data_, rhs_arena + ); + swap(_impl_.encrypted_, other->_impl_.encrypted_); +} + +std::string envelope::GetTypeName() const { + return "netcon.envelope"; +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace netcon +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::netcon::request* +Arena::CreateMaybeMessage< ::netcon::request >(Arena* arena) { + return Arena::CreateMessageInternal< ::netcon::request >(arena); +} +template<> PROTOBUF_NOINLINE ::netcon::response* +Arena::CreateMaybeMessage< ::netcon::response >(Arena* arena) { + return Arena::CreateMessageInternal< ::netcon::response >(arena); +} +template<> PROTOBUF_NOINLINE ::netcon::envelope* +Arena::CreateMaybeMessage< ::netcon::envelope >(Arena* arena) { + return Arena::CreateMessageInternal< ::netcon::envelope >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/r5dev/protoc/netcon.pb.h b/r5dev/protoc/netcon.pb.h new file mode 100644 index 00000000..cbddcc16 --- /dev/null +++ b/r5dev/protoc/netcon.pb.h @@ -0,0 +1,1279 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: netcon.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_netcon_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_netcon_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3021000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_netcon_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_netcon_2eproto { + static const uint32_t offsets[]; +}; +namespace netcon { +class envelope; +struct envelopeDefaultTypeInternal; +extern envelopeDefaultTypeInternal _envelope_default_instance_; +class request; +struct requestDefaultTypeInternal; +extern requestDefaultTypeInternal _request_default_instance_; +class response; +struct responseDefaultTypeInternal; +extern responseDefaultTypeInternal _response_default_instance_; +} // namespace netcon +PROTOBUF_NAMESPACE_OPEN +template<> ::netcon::envelope* Arena::CreateMaybeMessage<::netcon::envelope>(Arena*); +template<> ::netcon::request* Arena::CreateMaybeMessage<::netcon::request>(Arena*); +template<> ::netcon::response* Arena::CreateMaybeMessage<::netcon::response>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +namespace netcon { + +enum request_e : int { + SERVERDATA_REQUEST_EXECCOMMAND = 0, + SERVERDATA_REQUEST_AUTH = 1, + SERVERDATA_REQUEST_SEND_CONSOLE_LOG = 2, + request_e_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(), + request_e_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max() +}; +bool request_e_IsValid(int value); +constexpr request_e request_e_MIN = SERVERDATA_REQUEST_EXECCOMMAND; +constexpr request_e request_e_MAX = SERVERDATA_REQUEST_SEND_CONSOLE_LOG; +constexpr int request_e_ARRAYSIZE = request_e_MAX + 1; + +const std::string& request_e_Name(request_e value); +template +inline const std::string& request_e_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function request_e_Name."); + return request_e_Name(static_cast(enum_t_value)); +} +bool request_e_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, request_e* value); +enum response_e : int { + SERVERDATA_RESPONSE_AUTH = 0, + SERVERDATA_RESPONSE_CONSOLE_LOG = 1, + response_e_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(), + response_e_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max() +}; +bool response_e_IsValid(int value); +constexpr response_e response_e_MIN = SERVERDATA_RESPONSE_AUTH; +constexpr response_e response_e_MAX = SERVERDATA_RESPONSE_CONSOLE_LOG; +constexpr int response_e_ARRAYSIZE = response_e_MAX + 1; + +const std::string& response_e_Name(response_e value); +template +inline const std::string& response_e_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function response_e_Name."); + return response_e_Name(static_cast(enum_t_value)); +} +bool response_e_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, response_e* value); +// =================================================================== + +class request final : + public ::PROTOBUF_NAMESPACE_ID::MessageLite /* @@protoc_insertion_point(class_definition:netcon.request) */ { + public: + inline request() : request(nullptr) {} + ~request() override; + explicit PROTOBUF_CONSTEXPR request(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + request(const request& from); + request(request&& from) noexcept + : request() { + *this = ::std::move(from); + } + + inline request& operator=(const request& from) { + CopyFrom(from); + return *this; + } + inline request& operator=(request&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const request& default_instance() { + return *internal_default_instance(); + } + static inline const request* internal_default_instance() { + return reinterpret_cast( + &_request_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(request& a, request& b) { + a.Swap(&b); + } + inline void Swap(request* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(request* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + request* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + void CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) final; + void CopyFrom(const request& from); + void MergeFrom(const request& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const; + void InternalSwap(request* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "netcon.request"; + } + protected: + explicit request(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + std::string GetTypeName() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kRequestMsgFieldNumber = 4, + kRequestValFieldNumber = 5, + kMessageIdFieldNumber = 1, + kMessageTypeFieldNumber = 2, + kRequestTypeFieldNumber = 3, + }; + // optional string requestMsg = 4; + bool has_requestmsg() const; + private: + bool _internal_has_requestmsg() const; + public: + void clear_requestmsg(); + const std::string& requestmsg() const; + template + void set_requestmsg(ArgT0&& arg0, ArgT... args); + std::string* mutable_requestmsg(); + PROTOBUF_NODISCARD std::string* release_requestmsg(); + void set_allocated_requestmsg(std::string* requestmsg); + private: + const std::string& _internal_requestmsg() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestmsg(const std::string& value); + std::string* _internal_mutable_requestmsg(); + public: + + // optional string requestVal = 5; + bool has_requestval() const; + private: + bool _internal_has_requestval() const; + public: + void clear_requestval(); + const std::string& requestval() const; + template + void set_requestval(ArgT0&& arg0, ArgT... args); + std::string* mutable_requestval(); + PROTOBUF_NODISCARD std::string* release_requestval(); + void set_allocated_requestval(std::string* requestval); + private: + const std::string& _internal_requestval() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestval(const std::string& value); + std::string* _internal_mutable_requestval(); + public: + + // optional int32 messageId = 1; + bool has_messageid() const; + private: + bool _internal_has_messageid() const; + public: + void clear_messageid(); + int32_t messageid() const; + void set_messageid(int32_t value); + private: + int32_t _internal_messageid() const; + void _internal_set_messageid(int32_t value); + public: + + // optional int32 messageType = 2; + bool has_messagetype() const; + private: + bool _internal_has_messagetype() const; + public: + void clear_messagetype(); + int32_t messagetype() const; + void set_messagetype(int32_t value); + private: + int32_t _internal_messagetype() const; + void _internal_set_messagetype(int32_t value); + public: + + // optional .netcon.request_e requestType = 3; + bool has_requesttype() const; + private: + bool _internal_has_requesttype() const; + public: + void clear_requesttype(); + ::netcon::request_e requesttype() const; + void set_requesttype(::netcon::request_e value); + private: + ::netcon::request_e _internal_requesttype() const; + void _internal_set_requesttype(::netcon::request_e value); + public: + + // @@protoc_insertion_point(class_scope:netcon.request) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr requestmsg_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr requestval_; + int32_t messageid_; + int32_t messagetype_; + int requesttype_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_netcon_2eproto; +}; +// ------------------------------------------------------------------- + +class response final : + public ::PROTOBUF_NAMESPACE_ID::MessageLite /* @@protoc_insertion_point(class_definition:netcon.response) */ { + public: + inline response() : response(nullptr) {} + ~response() override; + explicit PROTOBUF_CONSTEXPR response(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + response(const response& from); + response(response&& from) noexcept + : response() { + *this = ::std::move(from); + } + + inline response& operator=(const response& from) { + CopyFrom(from); + return *this; + } + inline response& operator=(response&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const response& default_instance() { + return *internal_default_instance(); + } + static inline const response* internal_default_instance() { + return reinterpret_cast( + &_response_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(response& a, response& b) { + a.Swap(&b); + } + inline void Swap(response* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(response* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + response* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + void CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) final; + void CopyFrom(const response& from); + void MergeFrom(const response& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const; + void InternalSwap(response* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "netcon.response"; + } + protected: + explicit response(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + std::string GetTypeName() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kResponseMsgFieldNumber = 4, + kResponseValFieldNumber = 5, + kMessageIdFieldNumber = 1, + kMessageTypeFieldNumber = 2, + kResponseTypeFieldNumber = 3, + }; + // optional string responseMsg = 4; + bool has_responsemsg() const; + private: + bool _internal_has_responsemsg() const; + public: + void clear_responsemsg(); + const std::string& responsemsg() const; + template + void set_responsemsg(ArgT0&& arg0, ArgT... args); + std::string* mutable_responsemsg(); + PROTOBUF_NODISCARD std::string* release_responsemsg(); + void set_allocated_responsemsg(std::string* responsemsg); + private: + const std::string& _internal_responsemsg() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_responsemsg(const std::string& value); + std::string* _internal_mutable_responsemsg(); + public: + + // optional string responseVal = 5; + bool has_responseval() const; + private: + bool _internal_has_responseval() const; + public: + void clear_responseval(); + const std::string& responseval() const; + template + void set_responseval(ArgT0&& arg0, ArgT... args); + std::string* mutable_responseval(); + PROTOBUF_NODISCARD std::string* release_responseval(); + void set_allocated_responseval(std::string* responseval); + private: + const std::string& _internal_responseval() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_responseval(const std::string& value); + std::string* _internal_mutable_responseval(); + public: + + // optional int32 messageId = 1; + bool has_messageid() const; + private: + bool _internal_has_messageid() const; + public: + void clear_messageid(); + int32_t messageid() const; + void set_messageid(int32_t value); + private: + int32_t _internal_messageid() const; + void _internal_set_messageid(int32_t value); + public: + + // optional int32 messageType = 2; + bool has_messagetype() const; + private: + bool _internal_has_messagetype() const; + public: + void clear_messagetype(); + int32_t messagetype() const; + void set_messagetype(int32_t value); + private: + int32_t _internal_messagetype() const; + void _internal_set_messagetype(int32_t value); + public: + + // optional .netcon.response_e responseType = 3; + bool has_responsetype() const; + private: + bool _internal_has_responsetype() const; + public: + void clear_responsetype(); + ::netcon::response_e responsetype() const; + void set_responsetype(::netcon::response_e value); + private: + ::netcon::response_e _internal_responsetype() const; + void _internal_set_responsetype(::netcon::response_e value); + public: + + // @@protoc_insertion_point(class_scope:netcon.response) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr responsemsg_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr responseval_; + int32_t messageid_; + int32_t messagetype_; + int responsetype_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_netcon_2eproto; +}; +// ------------------------------------------------------------------- + +class envelope final : + public ::PROTOBUF_NAMESPACE_ID::MessageLite /* @@protoc_insertion_point(class_definition:netcon.envelope) */ { + public: + inline envelope() : envelope(nullptr) {} + ~envelope() override; + explicit PROTOBUF_CONSTEXPR envelope(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + envelope(const envelope& from); + envelope(envelope&& from) noexcept + : envelope() { + *this = ::std::move(from); + } + + inline envelope& operator=(const envelope& from) { + CopyFrom(from); + return *this; + } + inline envelope& operator=(envelope&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const envelope& default_instance() { + return *internal_default_instance(); + } + static inline const envelope* internal_default_instance() { + return reinterpret_cast( + &_envelope_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(envelope& a, envelope& b) { + a.Swap(&b); + } + inline void Swap(envelope* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(envelope* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + envelope* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + void CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) final; + void CopyFrom(const envelope& from); + void MergeFrom(const envelope& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const; + void InternalSwap(envelope* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "netcon.envelope"; + } + protected: + explicit envelope(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + std::string GetTypeName() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNonceFieldNumber = 2, + kDataFieldNumber = 3, + kEncryptedFieldNumber = 1, + }; + // bytes nonce = 2; + void clear_nonce(); + const std::string& nonce() const; + template + void set_nonce(ArgT0&& arg0, ArgT... args); + std::string* mutable_nonce(); + PROTOBUF_NODISCARD std::string* release_nonce(); + void set_allocated_nonce(std::string* nonce); + private: + const std::string& _internal_nonce() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_nonce(const std::string& value); + std::string* _internal_mutable_nonce(); + public: + + // bytes data = 3; + void clear_data(); + const std::string& data() const; + template + void set_data(ArgT0&& arg0, ArgT... args); + std::string* mutable_data(); + PROTOBUF_NODISCARD std::string* release_data(); + void set_allocated_data(std::string* data); + private: + const std::string& _internal_data() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_data(const std::string& value); + std::string* _internal_mutable_data(); + public: + + // bool encrypted = 1; + void clear_encrypted(); + bool encrypted() const; + void set_encrypted(bool value); + private: + bool _internal_encrypted() const; + void _internal_set_encrypted(bool value); + public: + + // @@protoc_insertion_point(class_scope:netcon.envelope) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr nonce_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr data_; + bool encrypted_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_netcon_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// request + +// optional int32 messageId = 1; +inline bool request::_internal_has_messageid() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool request::has_messageid() const { + return _internal_has_messageid(); +} +inline void request::clear_messageid() { + _impl_.messageid_ = 0; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline int32_t request::_internal_messageid() const { + return _impl_.messageid_; +} +inline int32_t request::messageid() const { + // @@protoc_insertion_point(field_get:netcon.request.messageId) + return _internal_messageid(); +} +inline void request::_internal_set_messageid(int32_t value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.messageid_ = value; +} +inline void request::set_messageid(int32_t value) { + _internal_set_messageid(value); + // @@protoc_insertion_point(field_set:netcon.request.messageId) +} + +// optional int32 messageType = 2; +inline bool request::_internal_has_messagetype() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool request::has_messagetype() const { + return _internal_has_messagetype(); +} +inline void request::clear_messagetype() { + _impl_.messagetype_ = 0; + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline int32_t request::_internal_messagetype() const { + return _impl_.messagetype_; +} +inline int32_t request::messagetype() const { + // @@protoc_insertion_point(field_get:netcon.request.messageType) + return _internal_messagetype(); +} +inline void request::_internal_set_messagetype(int32_t value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.messagetype_ = value; +} +inline void request::set_messagetype(int32_t value) { + _internal_set_messagetype(value); + // @@protoc_insertion_point(field_set:netcon.request.messageType) +} + +// optional .netcon.request_e requestType = 3; +inline bool request::_internal_has_requesttype() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool request::has_requesttype() const { + return _internal_has_requesttype(); +} +inline void request::clear_requesttype() { + _impl_.requesttype_ = 0; + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline ::netcon::request_e request::_internal_requesttype() const { + return static_cast< ::netcon::request_e >(_impl_.requesttype_); +} +inline ::netcon::request_e request::requesttype() const { + // @@protoc_insertion_point(field_get:netcon.request.requestType) + return _internal_requesttype(); +} +inline void request::_internal_set_requesttype(::netcon::request_e value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.requesttype_ = value; +} +inline void request::set_requesttype(::netcon::request_e value) { + _internal_set_requesttype(value); + // @@protoc_insertion_point(field_set:netcon.request.requestType) +} + +// optional string requestMsg = 4; +inline bool request::_internal_has_requestmsg() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool request::has_requestmsg() const { + return _internal_has_requestmsg(); +} +inline void request::clear_requestmsg() { + _impl_.requestmsg_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& request::requestmsg() const { + // @@protoc_insertion_point(field_get:netcon.request.requestMsg) + return _internal_requestmsg(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void request::set_requestmsg(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.requestmsg_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:netcon.request.requestMsg) +} +inline std::string* request::mutable_requestmsg() { + std::string* _s = _internal_mutable_requestmsg(); + // @@protoc_insertion_point(field_mutable:netcon.request.requestMsg) + return _s; +} +inline const std::string& request::_internal_requestmsg() const { + return _impl_.requestmsg_.Get(); +} +inline void request::_internal_set_requestmsg(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.requestmsg_.Set(value, GetArenaForAllocation()); +} +inline std::string* request::_internal_mutable_requestmsg() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.requestmsg_.Mutable(GetArenaForAllocation()); +} +inline std::string* request::release_requestmsg() { + // @@protoc_insertion_point(field_release:netcon.request.requestMsg) + if (!_internal_has_requestmsg()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.requestmsg_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.requestmsg_.IsDefault()) { + _impl_.requestmsg_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void request::set_allocated_requestmsg(std::string* requestmsg) { + if (requestmsg != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.requestmsg_.SetAllocated(requestmsg, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.requestmsg_.IsDefault()) { + _impl_.requestmsg_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:netcon.request.requestMsg) +} + +// optional string requestVal = 5; +inline bool request::_internal_has_requestval() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool request::has_requestval() const { + return _internal_has_requestval(); +} +inline void request::clear_requestval() { + _impl_.requestval_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& request::requestval() const { + // @@protoc_insertion_point(field_get:netcon.request.requestVal) + return _internal_requestval(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void request::set_requestval(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.requestval_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:netcon.request.requestVal) +} +inline std::string* request::mutable_requestval() { + std::string* _s = _internal_mutable_requestval(); + // @@protoc_insertion_point(field_mutable:netcon.request.requestVal) + return _s; +} +inline const std::string& request::_internal_requestval() const { + return _impl_.requestval_.Get(); +} +inline void request::_internal_set_requestval(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.requestval_.Set(value, GetArenaForAllocation()); +} +inline std::string* request::_internal_mutable_requestval() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.requestval_.Mutable(GetArenaForAllocation()); +} +inline std::string* request::release_requestval() { + // @@protoc_insertion_point(field_release:netcon.request.requestVal) + if (!_internal_has_requestval()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.requestval_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.requestval_.IsDefault()) { + _impl_.requestval_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void request::set_allocated_requestval(std::string* requestval) { + if (requestval != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.requestval_.SetAllocated(requestval, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.requestval_.IsDefault()) { + _impl_.requestval_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:netcon.request.requestVal) +} + +// ------------------------------------------------------------------- + +// response + +// optional int32 messageId = 1; +inline bool response::_internal_has_messageid() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool response::has_messageid() const { + return _internal_has_messageid(); +} +inline void response::clear_messageid() { + _impl_.messageid_ = 0; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline int32_t response::_internal_messageid() const { + return _impl_.messageid_; +} +inline int32_t response::messageid() const { + // @@protoc_insertion_point(field_get:netcon.response.messageId) + return _internal_messageid(); +} +inline void response::_internal_set_messageid(int32_t value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.messageid_ = value; +} +inline void response::set_messageid(int32_t value) { + _internal_set_messageid(value); + // @@protoc_insertion_point(field_set:netcon.response.messageId) +} + +// optional int32 messageType = 2; +inline bool response::_internal_has_messagetype() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool response::has_messagetype() const { + return _internal_has_messagetype(); +} +inline void response::clear_messagetype() { + _impl_.messagetype_ = 0; + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline int32_t response::_internal_messagetype() const { + return _impl_.messagetype_; +} +inline int32_t response::messagetype() const { + // @@protoc_insertion_point(field_get:netcon.response.messageType) + return _internal_messagetype(); +} +inline void response::_internal_set_messagetype(int32_t value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.messagetype_ = value; +} +inline void response::set_messagetype(int32_t value) { + _internal_set_messagetype(value); + // @@protoc_insertion_point(field_set:netcon.response.messageType) +} + +// optional .netcon.response_e responseType = 3; +inline bool response::_internal_has_responsetype() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool response::has_responsetype() const { + return _internal_has_responsetype(); +} +inline void response::clear_responsetype() { + _impl_.responsetype_ = 0; + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline ::netcon::response_e response::_internal_responsetype() const { + return static_cast< ::netcon::response_e >(_impl_.responsetype_); +} +inline ::netcon::response_e response::responsetype() const { + // @@protoc_insertion_point(field_get:netcon.response.responseType) + return _internal_responsetype(); +} +inline void response::_internal_set_responsetype(::netcon::response_e value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.responsetype_ = value; +} +inline void response::set_responsetype(::netcon::response_e value) { + _internal_set_responsetype(value); + // @@protoc_insertion_point(field_set:netcon.response.responseType) +} + +// optional string responseMsg = 4; +inline bool response::_internal_has_responsemsg() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool response::has_responsemsg() const { + return _internal_has_responsemsg(); +} +inline void response::clear_responsemsg() { + _impl_.responsemsg_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& response::responsemsg() const { + // @@protoc_insertion_point(field_get:netcon.response.responseMsg) + return _internal_responsemsg(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void response::set_responsemsg(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.responsemsg_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:netcon.response.responseMsg) +} +inline std::string* response::mutable_responsemsg() { + std::string* _s = _internal_mutable_responsemsg(); + // @@protoc_insertion_point(field_mutable:netcon.response.responseMsg) + return _s; +} +inline const std::string& response::_internal_responsemsg() const { + return _impl_.responsemsg_.Get(); +} +inline void response::_internal_set_responsemsg(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.responsemsg_.Set(value, GetArenaForAllocation()); +} +inline std::string* response::_internal_mutable_responsemsg() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.responsemsg_.Mutable(GetArenaForAllocation()); +} +inline std::string* response::release_responsemsg() { + // @@protoc_insertion_point(field_release:netcon.response.responseMsg) + if (!_internal_has_responsemsg()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.responsemsg_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.responsemsg_.IsDefault()) { + _impl_.responsemsg_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void response::set_allocated_responsemsg(std::string* responsemsg) { + if (responsemsg != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.responsemsg_.SetAllocated(responsemsg, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.responsemsg_.IsDefault()) { + _impl_.responsemsg_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:netcon.response.responseMsg) +} + +// optional string responseVal = 5; +inline bool response::_internal_has_responseval() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool response::has_responseval() const { + return _internal_has_responseval(); +} +inline void response::clear_responseval() { + _impl_.responseval_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& response::responseval() const { + // @@protoc_insertion_point(field_get:netcon.response.responseVal) + return _internal_responseval(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void response::set_responseval(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.responseval_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:netcon.response.responseVal) +} +inline std::string* response::mutable_responseval() { + std::string* _s = _internal_mutable_responseval(); + // @@protoc_insertion_point(field_mutable:netcon.response.responseVal) + return _s; +} +inline const std::string& response::_internal_responseval() const { + return _impl_.responseval_.Get(); +} +inline void response::_internal_set_responseval(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.responseval_.Set(value, GetArenaForAllocation()); +} +inline std::string* response::_internal_mutable_responseval() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.responseval_.Mutable(GetArenaForAllocation()); +} +inline std::string* response::release_responseval() { + // @@protoc_insertion_point(field_release:netcon.response.responseVal) + if (!_internal_has_responseval()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.responseval_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.responseval_.IsDefault()) { + _impl_.responseval_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void response::set_allocated_responseval(std::string* responseval) { + if (responseval != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.responseval_.SetAllocated(responseval, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.responseval_.IsDefault()) { + _impl_.responseval_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:netcon.response.responseVal) +} + +// ------------------------------------------------------------------- + +// envelope + +// bool encrypted = 1; +inline void envelope::clear_encrypted() { + _impl_.encrypted_ = false; +} +inline bool envelope::_internal_encrypted() const { + return _impl_.encrypted_; +} +inline bool envelope::encrypted() const { + // @@protoc_insertion_point(field_get:netcon.envelope.encrypted) + return _internal_encrypted(); +} +inline void envelope::_internal_set_encrypted(bool value) { + + _impl_.encrypted_ = value; +} +inline void envelope::set_encrypted(bool value) { + _internal_set_encrypted(value); + // @@protoc_insertion_point(field_set:netcon.envelope.encrypted) +} + +// bytes nonce = 2; +inline void envelope::clear_nonce() { + _impl_.nonce_.ClearToEmpty(); +} +inline const std::string& envelope::nonce() const { + // @@protoc_insertion_point(field_get:netcon.envelope.nonce) + return _internal_nonce(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void envelope::set_nonce(ArgT0&& arg0, ArgT... args) { + + _impl_.nonce_.SetBytes(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:netcon.envelope.nonce) +} +inline std::string* envelope::mutable_nonce() { + std::string* _s = _internal_mutable_nonce(); + // @@protoc_insertion_point(field_mutable:netcon.envelope.nonce) + return _s; +} +inline const std::string& envelope::_internal_nonce() const { + return _impl_.nonce_.Get(); +} +inline void envelope::_internal_set_nonce(const std::string& value) { + + _impl_.nonce_.Set(value, GetArenaForAllocation()); +} +inline std::string* envelope::_internal_mutable_nonce() { + + return _impl_.nonce_.Mutable(GetArenaForAllocation()); +} +inline std::string* envelope::release_nonce() { + // @@protoc_insertion_point(field_release:netcon.envelope.nonce) + return _impl_.nonce_.Release(); +} +inline void envelope::set_allocated_nonce(std::string* nonce) { + if (nonce != nullptr) { + + } else { + + } + _impl_.nonce_.SetAllocated(nonce, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.nonce_.IsDefault()) { + _impl_.nonce_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:netcon.envelope.nonce) +} + +// bytes data = 3; +inline void envelope::clear_data() { + _impl_.data_.ClearToEmpty(); +} +inline const std::string& envelope::data() const { + // @@protoc_insertion_point(field_get:netcon.envelope.data) + return _internal_data(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void envelope::set_data(ArgT0&& arg0, ArgT... args) { + + _impl_.data_.SetBytes(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:netcon.envelope.data) +} +inline std::string* envelope::mutable_data() { + std::string* _s = _internal_mutable_data(); + // @@protoc_insertion_point(field_mutable:netcon.envelope.data) + return _s; +} +inline const std::string& envelope::_internal_data() const { + return _impl_.data_.Get(); +} +inline void envelope::_internal_set_data(const std::string& value) { + + _impl_.data_.Set(value, GetArenaForAllocation()); +} +inline std::string* envelope::_internal_mutable_data() { + + return _impl_.data_.Mutable(GetArenaForAllocation()); +} +inline std::string* envelope::release_data() { + // @@protoc_insertion_point(field_release:netcon.envelope.data) + return _impl_.data_.Release(); +} +inline void envelope::set_allocated_data(std::string* data) { + if (data != nullptr) { + + } else { + + } + _impl_.data_.SetAllocated(data, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.data_.IsDefault()) { + _impl_.data_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:netcon.envelope.data) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace netcon + +PROTOBUF_NAMESPACE_OPEN + +template <> struct is_proto_enum< ::netcon::request_e> : ::std::true_type {}; +template <> struct is_proto_enum< ::netcon::response_e> : ::std::true_type {}; + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_netcon_2eproto diff --git a/r5dev/protoc/sv_rcon.pb.cc b/r5dev/protoc/sv_rcon.pb.cc deleted file mode 100644 index 4ef8824c..00000000 --- a/r5dev/protoc/sv_rcon.pb.cc +++ /dev/null @@ -1,485 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: sv_rcon.proto - -#include "sv_rcon.pb.h" - -#include - -#include -#include -#include -#include -// @@protoc_insertion_point(includes) -#include - -PROTOBUF_PRAGMA_INIT_SEG - -namespace _pb = ::PROTOBUF_NAMESPACE_ID; -namespace _pbi = _pb::internal; - -namespace sv_rcon { -PROTOBUF_CONSTEXPR response::response( - ::_pbi::ConstantInitialized): _impl_{ - /*decltype(_impl_._has_bits_)*/{} - , /*decltype(_impl_._cached_size_)*/{} - , /*decltype(_impl_.responsemsg_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.responseval_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.messageid_)*/0 - , /*decltype(_impl_.messagetype_)*/0 - , /*decltype(_impl_.responsetype_)*/0} {} -struct responseDefaultTypeInternal { - PROTOBUF_CONSTEXPR responseDefaultTypeInternal() - : _instance(::_pbi::ConstantInitialized{}) {} - ~responseDefaultTypeInternal() {} - union { - response _instance; - }; -}; -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 responseDefaultTypeInternal _response_default_instance_; -} // namespace sv_rcon -namespace sv_rcon { -bool response_t_IsValid(int value) { - switch (value) { - case 0: - case 1: - return true; - default: - return false; - } -} - -static ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed response_t_strings[2] = {}; - -static const char response_t_names[] = - "SERVERDATA_RESPONSE_AUTH" - "SERVERDATA_RESPONSE_CONSOLE_LOG"; - -static const ::PROTOBUF_NAMESPACE_ID::internal::EnumEntry response_t_entries[] = { - { {response_t_names + 0, 24}, 0 }, - { {response_t_names + 24, 31}, 1 }, -}; - -static const int response_t_entries_by_number[] = { - 0, // 0 -> SERVERDATA_RESPONSE_AUTH - 1, // 1 -> SERVERDATA_RESPONSE_CONSOLE_LOG -}; - -const std::string& response_t_Name( - response_t value) { - static const bool dummy = - ::PROTOBUF_NAMESPACE_ID::internal::InitializeEnumStrings( - response_t_entries, - response_t_entries_by_number, - 2, response_t_strings); - (void) dummy; - int idx = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumName( - response_t_entries, - response_t_entries_by_number, - 2, value); - return idx == -1 ? ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString() : - response_t_strings[idx].get(); -} -bool response_t_Parse( - ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, response_t* value) { - int int_value; - bool success = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumValue( - response_t_entries, 2, name, &int_value); - if (success) { - *value = static_cast(int_value); - } - return success; -} - -// =================================================================== - -class response::_Internal { - public: - using HasBits = decltype(std::declval()._impl_._has_bits_); - static void set_has_messageid(HasBits* has_bits) { - (*has_bits)[0] |= 4u; - } - static void set_has_messagetype(HasBits* has_bits) { - (*has_bits)[0] |= 8u; - } - static void set_has_responsetype(HasBits* has_bits) { - (*has_bits)[0] |= 16u; - } - static void set_has_responsemsg(HasBits* has_bits) { - (*has_bits)[0] |= 1u; - } - static void set_has_responseval(HasBits* has_bits) { - (*has_bits)[0] |= 2u; - } -}; - -response::response(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned) - : ::PROTOBUF_NAMESPACE_ID::MessageLite(arena, is_message_owned) { - SharedCtor(arena, is_message_owned); - // @@protoc_insertion_point(arena_constructor:sv_rcon.response) -} -response::response(const response& from) - : ::PROTOBUF_NAMESPACE_ID::MessageLite() { - response* const _this = this; (void)_this; - new (&_impl_) Impl_{ - decltype(_impl_._has_bits_){from._impl_._has_bits_} - , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.responsemsg_){} - , decltype(_impl_.responseval_){} - , decltype(_impl_.messageid_){} - , decltype(_impl_.messagetype_){} - , decltype(_impl_.responsetype_){}}; - - _internal_metadata_.MergeFrom(from._internal_metadata_); - _impl_.responsemsg_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.responsemsg_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_responsemsg()) { - _this->_impl_.responsemsg_.Set(from._internal_responsemsg(), - _this->GetArenaForAllocation()); - } - _impl_.responseval_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.responseval_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_responseval()) { - _this->_impl_.responseval_.Set(from._internal_responseval(), - _this->GetArenaForAllocation()); - } - ::memcpy(&_impl_.messageid_, &from._impl_.messageid_, - static_cast(reinterpret_cast(&_impl_.responsetype_) - - reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.responsetype_)); - // @@protoc_insertion_point(copy_constructor:sv_rcon.response) -} - -inline void response::SharedCtor( - ::_pb::Arena* arena, bool is_message_owned) { - (void)arena; - (void)is_message_owned; - new (&_impl_) Impl_{ - decltype(_impl_._has_bits_){} - , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.responsemsg_){} - , decltype(_impl_.responseval_){} - , decltype(_impl_.messageid_){0} - , decltype(_impl_.messagetype_){0} - , decltype(_impl_.responsetype_){0} - }; - _impl_.responsemsg_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.responsemsg_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.responseval_.InitDefault(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.responseval_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING -} - -response::~response() { - // @@protoc_insertion_point(destructor:sv_rcon.response) - if (auto *arena = _internal_metadata_.DeleteReturnArena()) { - (void)arena; - return; - } - SharedDtor(); -} - -inline void response::SharedDtor() { - GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); - _impl_.responsemsg_.Destroy(); - _impl_.responseval_.Destroy(); -} - -void response::SetCachedSize(int size) const { - _impl_._cached_size_.Set(size); -} - -void response::Clear() { -// @@protoc_insertion_point(message_clear_start:sv_rcon.response) - uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - if (cached_has_bits & 0x00000001u) { - _impl_.responsemsg_.ClearNonDefaultToEmpty(); - } - if (cached_has_bits & 0x00000002u) { - _impl_.responseval_.ClearNonDefaultToEmpty(); - } - } - if (cached_has_bits & 0x0000001cu) { - ::memset(&_impl_.messageid_, 0, static_cast( - reinterpret_cast(&_impl_.responsetype_) - - reinterpret_cast(&_impl_.messageid_)) + sizeof(_impl_.responsetype_)); - } - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -const char* response::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - _Internal::HasBits has_bits{}; - while (!ctx->Done(&ptr)) { - uint32_t tag; - ptr = ::_pbi::ReadTag(ptr, &tag); - switch (tag >> 3) { - // optional int32 messageID = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { - _Internal::set_has_messageid(&has_bits); - _impl_.messageid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); - CHK_(ptr); - } else - goto handle_unusual; - continue; - // optional int32 messageType = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { - _Internal::set_has_messagetype(&has_bits); - _impl_.messagetype_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); - CHK_(ptr); - } else - goto handle_unusual; - continue; - // optional .sv_rcon.response_t responseType = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { - uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - _internal_set_responsetype(static_cast<::sv_rcon::response_t>(val)); - } else - goto handle_unusual; - continue; - // optional string responseMsg = 4; - case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { - auto str = _internal_mutable_responsemsg(); - ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); - CHK_(ptr); - CHK_(::_pbi::VerifyUTF8(str, nullptr)); - } else - goto handle_unusual; - continue; - // optional string responseVal = 5; - case 5: - if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 42)) { - auto str = _internal_mutable_responseval(); - ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); - CHK_(ptr); - CHK_(::_pbi::VerifyUTF8(str, nullptr)); - } else - goto handle_unusual; - continue; - default: - goto handle_unusual; - } // switch - handle_unusual: - if ((tag == 0) || ((tag & 7) == 4)) { - CHK_(ptr); - ctx->SetLastTag(tag); - goto message_done; - } - ptr = UnknownFieldParse( - tag, - _internal_metadata_.mutable_unknown_fields(), - ptr, ctx); - CHK_(ptr != nullptr); - } // while -message_done: - _impl_._has_bits_.Or(has_bits); - return ptr; -failure: - ptr = nullptr; - goto message_done; -#undef CHK_ -} - -uint8_t* response::_InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:sv_rcon.response) - uint32_t cached_has_bits = 0; - (void) cached_has_bits; - - // optional int32 messageID = 1; - if (_internal_has_messageid()) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_messageid(), target); - } - - // optional int32 messageType = 2; - if (_internal_has_messagetype()) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_messagetype(), target); - } - - // optional .sv_rcon.response_t responseType = 3; - if (_internal_has_responsetype()) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 3, this->_internal_responsetype(), target); - } - - // optional string responseMsg = 4; - if (_internal_has_responsemsg()) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( - this->_internal_responsemsg().data(), static_cast(this->_internal_responsemsg().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, - "sv_rcon.response.responseMsg"); - target = stream->WriteStringMaybeAliased( - 4, this->_internal_responsemsg(), target); - } - - // optional string responseVal = 5; - if (_internal_has_responseval()) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( - this->_internal_responseval().data(), static_cast(this->_internal_responseval().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, - "sv_rcon.response.responseVal"); - target = stream->WriteStringMaybeAliased( - 5, this->_internal_responseval(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = stream->WriteRaw(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(), - static_cast(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size()), target); - } - // @@protoc_insertion_point(serialize_to_array_end:sv_rcon.response) - return target; -} - -size_t response::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:sv_rcon.response) - size_t total_size = 0; - - uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { - // optional string responseMsg = 4; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_responsemsg()); - } - - // optional string responseVal = 5; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_responseval()); - } - - // optional int32 messageID = 1; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messageid()); - } - - // optional int32 messageType = 2; - if (cached_has_bits & 0x00000008u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_messagetype()); - } - - // optional .sv_rcon.response_t responseType = 3; - if (cached_has_bits & 0x00000010u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_responsetype()); - } - - } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - total_size += _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size(); - } - int cached_size = ::_pbi::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void response::CheckTypeAndMergeFrom( - const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) { - MergeFrom(*::_pbi::DownCast( - &from)); -} - -void response::MergeFrom(const response& from) { - response* const _this = this; - // @@protoc_insertion_point(class_specific_merge_from_start:sv_rcon.response) - GOOGLE_DCHECK_NE(&from, _this); - uint32_t cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { - if (cached_has_bits & 0x00000001u) { - _this->_internal_set_responsemsg(from._internal_responsemsg()); - } - if (cached_has_bits & 0x00000002u) { - _this->_internal_set_responseval(from._internal_responseval()); - } - if (cached_has_bits & 0x00000004u) { - _this->_impl_.messageid_ = from._impl_.messageid_; - } - if (cached_has_bits & 0x00000008u) { - _this->_impl_.messagetype_ = from._impl_.messagetype_; - } - if (cached_has_bits & 0x00000010u) { - _this->_impl_.responsetype_ = from._impl_.responsetype_; - } - _this->_impl_._has_bits_[0] |= cached_has_bits; - } - _this->_internal_metadata_.MergeFrom(from._internal_metadata_); -} - -void response::CopyFrom(const response& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:sv_rcon.response) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool response::IsInitialized() const { - return true; -} - -void response::InternalSwap(response* other) { - using std::swap; - auto* lhs_arena = GetArenaForAllocation(); - auto* rhs_arena = other->GetArenaForAllocation(); - _internal_metadata_.InternalSwap(&other->_internal_metadata_); - swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.responsemsg_, lhs_arena, - &other->_impl_.responsemsg_, rhs_arena - ); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.responseval_, lhs_arena, - &other->_impl_.responseval_, rhs_arena - ); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(response, _impl_.responsetype_) - + sizeof(response::_impl_.responsetype_) - - PROTOBUF_FIELD_OFFSET(response, _impl_.messageid_)>( - reinterpret_cast(&_impl_.messageid_), - reinterpret_cast(&other->_impl_.messageid_)); -} - -std::string response::GetTypeName() const { - return "sv_rcon.response"; -} - - -// @@protoc_insertion_point(namespace_scope) -} // namespace sv_rcon -PROTOBUF_NAMESPACE_OPEN -template<> PROTOBUF_NOINLINE ::sv_rcon::response* -Arena::CreateMaybeMessage< ::sv_rcon::response >(Arena* arena) { - return Arena::CreateMessageInternal< ::sv_rcon::response >(arena); -} -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) -#include diff --git a/r5dev/protoc/sv_rcon.pb.h b/r5dev/protoc/sv_rcon.pb.h deleted file mode 100644 index 3d179775..00000000 --- a/r5dev/protoc/sv_rcon.pb.h +++ /dev/null @@ -1,529 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: sv_rcon.proto - -#ifndef GOOGLE_PROTOBUF_INCLUDED_sv_5frcon_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_sv_5frcon_2eproto - -#include -#include - -#include -#if PROTOBUF_VERSION < 3021000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include // IWYU pragma: export -#include // IWYU pragma: export -#include -// @@protoc_insertion_point(includes) -#include -#define PROTOBUF_INTERNAL_EXPORT_sv_5frcon_2eproto -PROTOBUF_NAMESPACE_OPEN -namespace internal { -class AnyMetadata; -} // namespace internal -PROTOBUF_NAMESPACE_CLOSE - -// Internal implementation detail -- do not use these members. -struct TableStruct_sv_5frcon_2eproto { - static const uint32_t offsets[]; -}; -namespace sv_rcon { -class response; -struct responseDefaultTypeInternal; -extern responseDefaultTypeInternal _response_default_instance_; -} // namespace sv_rcon -PROTOBUF_NAMESPACE_OPEN -template<> ::sv_rcon::response* Arena::CreateMaybeMessage<::sv_rcon::response>(Arena*); -PROTOBUF_NAMESPACE_CLOSE -namespace sv_rcon { - -enum response_t : int { - SERVERDATA_RESPONSE_AUTH = 0, - SERVERDATA_RESPONSE_CONSOLE_LOG = 1, - response_t_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(), - response_t_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max() -}; -bool response_t_IsValid(int value); -constexpr response_t response_t_MIN = SERVERDATA_RESPONSE_AUTH; -constexpr response_t response_t_MAX = SERVERDATA_RESPONSE_CONSOLE_LOG; -constexpr int response_t_ARRAYSIZE = response_t_MAX + 1; - -const std::string& response_t_Name(response_t value); -template -inline const std::string& response_t_Name(T enum_t_value) { - static_assert(::std::is_same::value || - ::std::is_integral::value, - "Incorrect type passed to function response_t_Name."); - return response_t_Name(static_cast(enum_t_value)); -} -bool response_t_Parse( - ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, response_t* value); -// =================================================================== - -class response final : - public ::PROTOBUF_NAMESPACE_ID::MessageLite /* @@protoc_insertion_point(class_definition:sv_rcon.response) */ { - public: - inline response() : response(nullptr) {} - ~response() override; - explicit PROTOBUF_CONSTEXPR response(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); - - response(const response& from); - response(response&& from) noexcept - : response() { - *this = ::std::move(from); - } - - inline response& operator=(const response& from) { - CopyFrom(from); - return *this; - } - inline response& operator=(response&& from) noexcept { - if (this == &from) return *this; - if (GetOwningArena() == from.GetOwningArena() - #ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetOwningArena() != nullptr - #endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { - InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const response& default_instance() { - return *internal_default_instance(); - } - static inline const response* internal_default_instance() { - return reinterpret_cast( - &_response_default_instance_); - } - static constexpr int kIndexInFileMessages = - 0; - - friend void swap(response& a, response& b) { - a.Swap(&b); - } - inline void Swap(response* other) { - if (other == this) return; - #ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetOwningArena() != nullptr && - GetOwningArena() == other->GetOwningArena()) { - #else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetOwningArena() == other->GetOwningArena()) { - #endif // !PROTOBUF_FORCE_COPY_IN_SWAP - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(response* other) { - if (other == this) return; - GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - response* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { - return CreateMaybeMessage(arena); - } - void CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) final; - void CopyFrom(const response& from); - void MergeFrom(const response& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - uint8_t* _InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _impl_._cached_size_.Get(); } - - private: - void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); - void SharedDtor(); - void SetCachedSize(int size) const; - void InternalSwap(response* other); - - private: - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "sv_rcon.response"; - } - protected: - explicit response(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned = false); - public: - - std::string GetTypeName() const final; - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kResponseMsgFieldNumber = 4, - kResponseValFieldNumber = 5, - kMessageIDFieldNumber = 1, - kMessageTypeFieldNumber = 2, - kResponseTypeFieldNumber = 3, - }; - // optional string responseMsg = 4; - bool has_responsemsg() const; - private: - bool _internal_has_responsemsg() const; - public: - void clear_responsemsg(); - const std::string& responsemsg() const; - template - void set_responsemsg(ArgT0&& arg0, ArgT... args); - std::string* mutable_responsemsg(); - PROTOBUF_NODISCARD std::string* release_responsemsg(); - void set_allocated_responsemsg(std::string* responsemsg); - private: - const std::string& _internal_responsemsg() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_responsemsg(const std::string& value); - std::string* _internal_mutable_responsemsg(); - public: - - // optional string responseVal = 5; - bool has_responseval() const; - private: - bool _internal_has_responseval() const; - public: - void clear_responseval(); - const std::string& responseval() const; - template - void set_responseval(ArgT0&& arg0, ArgT... args); - std::string* mutable_responseval(); - PROTOBUF_NODISCARD std::string* release_responseval(); - void set_allocated_responseval(std::string* responseval); - private: - const std::string& _internal_responseval() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_responseval(const std::string& value); - std::string* _internal_mutable_responseval(); - public: - - // optional int32 messageID = 1; - bool has_messageid() const; - private: - bool _internal_has_messageid() const; - public: - void clear_messageid(); - int32_t messageid() const; - void set_messageid(int32_t value); - private: - int32_t _internal_messageid() const; - void _internal_set_messageid(int32_t value); - public: - - // optional int32 messageType = 2; - bool has_messagetype() const; - private: - bool _internal_has_messagetype() const; - public: - void clear_messagetype(); - int32_t messagetype() const; - void set_messagetype(int32_t value); - private: - int32_t _internal_messagetype() const; - void _internal_set_messagetype(int32_t value); - public: - - // optional .sv_rcon.response_t responseType = 3; - bool has_responsetype() const; - private: - bool _internal_has_responsetype() const; - public: - void clear_responsetype(); - ::sv_rcon::response_t responsetype() const; - void set_responsetype(::sv_rcon::response_t value); - private: - ::sv_rcon::response_t _internal_responsetype() const; - void _internal_set_responsetype(::sv_rcon::response_t value); - public: - - // @@protoc_insertion_point(class_scope:sv_rcon.response) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - struct Impl_ { - ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr responsemsg_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr responseval_; - int32_t messageid_; - int32_t messagetype_; - int responsetype_; - }; - union { Impl_ _impl_; }; - friend struct ::TableStruct_sv_5frcon_2eproto; -}; -// =================================================================== - - -// =================================================================== - -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // __GNUC__ -// response - -// optional int32 messageID = 1; -inline bool response::_internal_has_messageid() const { - bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; - return value; -} -inline bool response::has_messageid() const { - return _internal_has_messageid(); -} -inline void response::clear_messageid() { - _impl_.messageid_ = 0; - _impl_._has_bits_[0] &= ~0x00000004u; -} -inline int32_t response::_internal_messageid() const { - return _impl_.messageid_; -} -inline int32_t response::messageid() const { - // @@protoc_insertion_point(field_get:sv_rcon.response.messageID) - return _internal_messageid(); -} -inline void response::_internal_set_messageid(int32_t value) { - _impl_._has_bits_[0] |= 0x00000004u; - _impl_.messageid_ = value; -} -inline void response::set_messageid(int32_t value) { - _internal_set_messageid(value); - // @@protoc_insertion_point(field_set:sv_rcon.response.messageID) -} - -// optional int32 messageType = 2; -inline bool response::_internal_has_messagetype() const { - bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; - return value; -} -inline bool response::has_messagetype() const { - return _internal_has_messagetype(); -} -inline void response::clear_messagetype() { - _impl_.messagetype_ = 0; - _impl_._has_bits_[0] &= ~0x00000008u; -} -inline int32_t response::_internal_messagetype() const { - return _impl_.messagetype_; -} -inline int32_t response::messagetype() const { - // @@protoc_insertion_point(field_get:sv_rcon.response.messageType) - return _internal_messagetype(); -} -inline void response::_internal_set_messagetype(int32_t value) { - _impl_._has_bits_[0] |= 0x00000008u; - _impl_.messagetype_ = value; -} -inline void response::set_messagetype(int32_t value) { - _internal_set_messagetype(value); - // @@protoc_insertion_point(field_set:sv_rcon.response.messageType) -} - -// optional .sv_rcon.response_t responseType = 3; -inline bool response::_internal_has_responsetype() const { - bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; - return value; -} -inline bool response::has_responsetype() const { - return _internal_has_responsetype(); -} -inline void response::clear_responsetype() { - _impl_.responsetype_ = 0; - _impl_._has_bits_[0] &= ~0x00000010u; -} -inline ::sv_rcon::response_t response::_internal_responsetype() const { - return static_cast< ::sv_rcon::response_t >(_impl_.responsetype_); -} -inline ::sv_rcon::response_t response::responsetype() const { - // @@protoc_insertion_point(field_get:sv_rcon.response.responseType) - return _internal_responsetype(); -} -inline void response::_internal_set_responsetype(::sv_rcon::response_t value) { - _impl_._has_bits_[0] |= 0x00000010u; - _impl_.responsetype_ = value; -} -inline void response::set_responsetype(::sv_rcon::response_t value) { - _internal_set_responsetype(value); - // @@protoc_insertion_point(field_set:sv_rcon.response.responseType) -} - -// optional string responseMsg = 4; -inline bool response::_internal_has_responsemsg() const { - bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; - return value; -} -inline bool response::has_responsemsg() const { - return _internal_has_responsemsg(); -} -inline void response::clear_responsemsg() { - _impl_.responsemsg_.ClearToEmpty(); - _impl_._has_bits_[0] &= ~0x00000001u; -} -inline const std::string& response::responsemsg() const { - // @@protoc_insertion_point(field_get:sv_rcon.response.responseMsg) - return _internal_responsemsg(); -} -template -inline PROTOBUF_ALWAYS_INLINE -void response::set_responsemsg(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.responsemsg_.Set(static_cast(arg0), args..., GetArenaForAllocation()); - // @@protoc_insertion_point(field_set:sv_rcon.response.responseMsg) -} -inline std::string* response::mutable_responsemsg() { - std::string* _s = _internal_mutable_responsemsg(); - // @@protoc_insertion_point(field_mutable:sv_rcon.response.responseMsg) - return _s; -} -inline const std::string& response::_internal_responsemsg() const { - return _impl_.responsemsg_.Get(); -} -inline void response::_internal_set_responsemsg(const std::string& value) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.responsemsg_.Set(value, GetArenaForAllocation()); -} -inline std::string* response::_internal_mutable_responsemsg() { - _impl_._has_bits_[0] |= 0x00000001u; - return _impl_.responsemsg_.Mutable(GetArenaForAllocation()); -} -inline std::string* response::release_responsemsg() { - // @@protoc_insertion_point(field_release:sv_rcon.response.responseMsg) - if (!_internal_has_responsemsg()) { - return nullptr; - } - _impl_._has_bits_[0] &= ~0x00000001u; - auto* p = _impl_.responsemsg_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.responsemsg_.IsDefault()) { - _impl_.responsemsg_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void response::set_allocated_responsemsg(std::string* responsemsg) { - if (responsemsg != nullptr) { - _impl_._has_bits_[0] |= 0x00000001u; - } else { - _impl_._has_bits_[0] &= ~0x00000001u; - } - _impl_.responsemsg_.SetAllocated(responsemsg, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.responsemsg_.IsDefault()) { - _impl_.responsemsg_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - // @@protoc_insertion_point(field_set_allocated:sv_rcon.response.responseMsg) -} - -// optional string responseVal = 5; -inline bool response::_internal_has_responseval() const { - bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; - return value; -} -inline bool response::has_responseval() const { - return _internal_has_responseval(); -} -inline void response::clear_responseval() { - _impl_.responseval_.ClearToEmpty(); - _impl_._has_bits_[0] &= ~0x00000002u; -} -inline const std::string& response::responseval() const { - // @@protoc_insertion_point(field_get:sv_rcon.response.responseVal) - return _internal_responseval(); -} -template -inline PROTOBUF_ALWAYS_INLINE -void response::set_responseval(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.responseval_.Set(static_cast(arg0), args..., GetArenaForAllocation()); - // @@protoc_insertion_point(field_set:sv_rcon.response.responseVal) -} -inline std::string* response::mutable_responseval() { - std::string* _s = _internal_mutable_responseval(); - // @@protoc_insertion_point(field_mutable:sv_rcon.response.responseVal) - return _s; -} -inline const std::string& response::_internal_responseval() const { - return _impl_.responseval_.Get(); -} -inline void response::_internal_set_responseval(const std::string& value) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.responseval_.Set(value, GetArenaForAllocation()); -} -inline std::string* response::_internal_mutable_responseval() { - _impl_._has_bits_[0] |= 0x00000002u; - return _impl_.responseval_.Mutable(GetArenaForAllocation()); -} -inline std::string* response::release_responseval() { - // @@protoc_insertion_point(field_release:sv_rcon.response.responseVal) - if (!_internal_has_responseval()) { - return nullptr; - } - _impl_._has_bits_[0] &= ~0x00000002u; - auto* p = _impl_.responseval_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.responseval_.IsDefault()) { - _impl_.responseval_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void response::set_allocated_responseval(std::string* responseval) { - if (responseval != nullptr) { - _impl_._has_bits_[0] |= 0x00000002u; - } else { - _impl_._has_bits_[0] &= ~0x00000002u; - } - _impl_.responseval_.SetAllocated(responseval, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.responseval_.IsDefault()) { - _impl_.responseval_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - // @@protoc_insertion_point(field_set_allocated:sv_rcon.response.responseVal) -} - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif // __GNUC__ - -// @@protoc_insertion_point(namespace_scope) - -} // namespace sv_rcon - -PROTOBUF_NAMESPACE_OPEN - -template <> struct is_proto_enum< ::sv_rcon::response_t> : ::std::true_type {}; - -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) - -#include -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_sv_5frcon_2eproto diff --git a/r5dev/public/tier0/utility.h b/r5dev/public/tier0/utility.h index f245e34e..ec7f321d 100644 --- a/r5dev/public/tier0/utility.h +++ b/r5dev/public/tier0/utility.h @@ -8,6 +8,7 @@ int CreateDirHierarchy(const char* filePath); bool IsDirectory(const char* path); bool FileEmpty(ifstream& pFile); MODULEINFO GetModuleInfo(const char* szModule); +bool CryptoGenRandom(unsigned char* pData, const uint32_t nDataLen, const char*& outMsg); ///////////////////////////////////////////////////////////////////////////// // Debug diff --git a/r5dev/public/tier2/cryptutils.h b/r5dev/public/tier2/cryptutils.h new file mode 100644 index 00000000..7bf7e822 --- /dev/null +++ b/r5dev/public/tier2/cryptutils.h @@ -0,0 +1,26 @@ +#ifndef TIER2_CRYPTUTILS_H +#define TIER2_CRYPTUTILS_H + +typedef unsigned char CryptoIV_t[16]; +typedef unsigned char CryptoKey_t[16]; + +struct CryptoContext_s +{ + CryptoContext_s(const int setKeyBits = 128) + : keyBits(setKeyBits) + { + Assert(setKeyBits == 128 || setKeyBits == 192 || setKeyBits == 256); + memset(ivData, 0, sizeof(ivData)); + } + + CryptoIV_t ivData; + int keyBits; +}; + +bool Crypto_GenerateIV(CryptoContext_s& ctx, const unsigned char* const data, const size_t size); +bool Crypto_CTREncrypt(CryptoContext_s& ctx, const unsigned char* const inBuf, unsigned char* const outBuf, + const unsigned char* const key, const size_t size); +bool Crypto_CTRDecrypt(CryptoContext_s& ctx, const unsigned char* const inBuf, unsigned char* const outBuf, + const unsigned char* const key, const size_t size); + +#endif // TIER2_CRYPTUTILS_H diff --git a/r5dev/resource/protobuf/cl_rcon.proto b/r5dev/resource/protobuf/cl_rcon.proto deleted file mode 100644 index c0a0907c..00000000 --- a/r5dev/resource/protobuf/cl_rcon.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto3"; -package cl_rcon; -option optimize_for = LITE_RUNTIME; - -enum request_t -{ - SERVERDATA_REQUEST_EXECCOMMAND = 0; - SERVERDATA_REQUEST_AUTH = 1; - SERVERDATA_REQUEST_SEND_CONSOLE_LOG = 2; -} - -message request -{ - optional int32 messageID = 1; - optional int32 messageType = 2; - optional request_t requestType = 3; - optional string requestMsg = 4; - optional string requestVal = 5; -} diff --git a/r5dev/resource/protobuf/generate.bat b/r5dev/resource/protobuf/generate.bat index e179f451..ebc05ef4 100644 --- a/r5dev/resource/protobuf/generate.bat +++ b/r5dev/resource/protobuf/generate.bat @@ -1,4 +1,3 @@ protoc64 --cpp_out=. sig_map.proto -protoc64 --cpp_out=. sv_rcon.proto -protoc64 --cpp_out=. cl_rcon.proto +protoc64 --cpp_out=. netcon.proto protoc64 --cpp_out=. events.proto diff --git a/r5dev/resource/protobuf/netcon.proto b/r5dev/resource/protobuf/netcon.proto new file mode 100644 index 00000000..2b684f90 --- /dev/null +++ b/r5dev/resource/protobuf/netcon.proto @@ -0,0 +1,56 @@ +////////////////////////////////////////////////////////////////////// +// R5Sdk netconsole protocol +////////////////////////////////////////////////////////////////////// +syntax = "proto3"; +package netcon; +option optimize_for = LITE_RUNTIME; + +////////////////////////////////////////////////////////////////////// +// Request from netconsole +////////////////////////////////////////////////////////////////////// + +enum request_e +{ + SERVERDATA_REQUEST_EXECCOMMAND = 0; + SERVERDATA_REQUEST_AUTH = 1; + SERVERDATA_REQUEST_SEND_CONSOLE_LOG = 2; +} + +message request +{ + optional int32 messageId = 1; + optional int32 messageType = 2; + optional request_e requestType = 3; + optional string requestMsg = 4; + optional string requestVal = 5; +} + +////////////////////////////////////////////////////////////////////// +// Response to netconsole +////////////////////////////////////////////////////////////////////// + +enum response_e +{ + SERVERDATA_RESPONSE_AUTH = 0; + SERVERDATA_RESPONSE_CONSOLE_LOG = 1; +} + +message response +{ + optional int32 messageId = 1; + optional int32 messageType = 2; + optional response_e responseType = 3; + optional string responseMsg = 4; + optional string responseVal = 5; +} + +////////////////////////////////////////////////////////////////////// +// Message envelope +////////////////////////////////////////////////////////////////////// + +message envelope +{ + bool encrypted = 1; + bytes nonce = 2; + bytes data = 3; +} diff --git a/r5dev/resource/protobuf/sv_rcon.proto b/r5dev/resource/protobuf/sv_rcon.proto deleted file mode 100644 index 3a64cfbc..00000000 --- a/r5dev/resource/protobuf/sv_rcon.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; -package sv_rcon; -option optimize_for = LITE_RUNTIME; - -enum response_t -{ - SERVERDATA_RESPONSE_AUTH = 0; - SERVERDATA_RESPONSE_CONSOLE_LOG = 1; -} - -message response -{ - optional int32 messageID = 1; - optional int32 messageType = 2; - optional response_t responseType = 3; - optional string responseMsg = 4; - optional string responseVal = 5; -} diff --git a/r5dev/tier0/utility.cpp b/r5dev/tier0/utility.cpp index 0c55dfd1..42503c1e 100644 --- a/r5dev/tier0/utility.cpp +++ b/r5dev/tier0/utility.cpp @@ -121,6 +121,26 @@ MODULEINFO GetModuleInfo(const char* szModule) return modinfo; } +/////////////////////////////////////////////////////////////////////////////// +// For generating random data. +static BCRYPT_ALG_HANDLE s_bcryptAlgorithmProvider; +bool CryptoGenRandom(unsigned char* pData, const uint32_t nDataLen, const char*& outMsg) +{ + if (!s_bcryptAlgorithmProvider && (BCryptOpenAlgorithmProvider(&s_bcryptAlgorithmProvider, L"RNG", 0, 0) < 0)) + { + outMsg = "Failed to open rng algorithm"; + return false; + } + + if (BCryptGenRandom(s_bcryptAlgorithmProvider, pData, nDataLen, 0) < 0) + { + outMsg = "Failed to generate random data"; + return false; + } + + return true; +} + /////////////////////////////////////////////////////////////////////////////// // For printing output to the debugger. void DbgPrint(LPCSTR sFormat, ...) diff --git a/r5dev/tier2/CMakeLists.txt b/r5dev/tier2/CMakeLists.txt index 3cff30a8..8d3b33ed 100644 --- a/r5dev/tier2/CMakeLists.txt +++ b/r5dev/tier2/CMakeLists.txt @@ -4,6 +4,7 @@ add_module( "lib" "tier2" "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) start_sources() add_sources( SOURCE_GROUP "Utility" + "cryptutils.cpp" "curlutils.cpp" "fileutils.cpp" "meshutils.cpp" @@ -22,11 +23,12 @@ add_sources( SOURCE_GROUP "Public" end_sources() target_include_directories( ${PROJECT_NAME} PRIVATE - "${ENGINE_SOURCE_DIR}/tier0/" + "${ENGINE_SOURCE_DIR}/tier0/" "${ENGINE_SOURCE_DIR}/tier1/" ) target_include_directories( ${PROJECT_NAME} PRIVATE + "${THIRDPARTY_SOURCE_DIR}/mbedtls/include" "${THIRDPARTY_SOURCE_DIR}/dirtysdk/include/" "${THIRDPARTY_SOURCE_DIR}/ea/" ) diff --git a/r5dev/tier2/cryptutils.cpp b/r5dev/tier2/cryptutils.cpp new file mode 100644 index 00000000..bc4b1c90 --- /dev/null +++ b/r5dev/tier2/cryptutils.cpp @@ -0,0 +1,70 @@ +//===========================================================================// +// +// Purpose: A set of utilities to perform encryption/decryption +// +//===========================================================================// +#include "mbedtls/aes.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" + +#include "tier2/cryptutils.h" + +bool Crypto_GenerateIV(CryptoContext_s& ctx, const unsigned char* const data, const size_t size) +{ + mbedtls_entropy_context entropy; + mbedtls_entropy_init(&entropy); + + mbedtls_ctr_drbg_context drbg; + mbedtls_ctr_drbg_init(&drbg); + + const int seedRet = mbedtls_ctr_drbg_seed(&drbg, mbedtls_entropy_func, &entropy, data, size); + int randRet = MBEDTLS_ERR_ERROR_GENERIC_ERROR; + + if (seedRet == 0) + { + randRet = mbedtls_ctr_drbg_random(&drbg, ctx.ivData, sizeof(ctx.ivData)); + } + + mbedtls_ctr_drbg_free(&drbg); + mbedtls_entropy_free(&entropy); + + return randRet == 0; +} + +static bool Crypto_CTRCrypt(CryptoContext_s& ctx, const unsigned char* const inBuf, + unsigned char* const outBuf, const unsigned char* const key, const size_t size) +{ + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + + int cryptRet = MBEDTLS_ERR_ERROR_GENERIC_ERROR; + const int setRet = mbedtls_aes_setkey_enc(&aes, key, ctx.keyBits); + + if (setRet == 0) + { + unsigned char nonceCounter[16]; + unsigned char streamBlock[16]; + + size_t offset = 0; + memcpy(nonceCounter, ctx.ivData, sizeof(nonceCounter)); + + cryptRet = mbedtls_aes_crypt_ctr(&aes, size, &offset, nonceCounter, streamBlock, inBuf, outBuf); + } + + mbedtls_aes_free(&aes); + return cryptRet == 0; +} + +bool Crypto_CTREncrypt(CryptoContext_s& ctx, const unsigned char* const inBuf, unsigned char* const outBuf, + const unsigned char* const key, const size_t size) +{ + return Crypto_CTRCrypt(ctx, inBuf, outBuf, key, size); +} + +bool Crypto_CTRDecrypt(CryptoContext_s& ctx, const unsigned char* const inBuf, unsigned char* const outBuf, + const unsigned char* const key, const size_t size) +{ + return Crypto_CTRCrypt(ctx, inBuf, outBuf, key, size); +} From cc5eda3a7efcbc91e6ebeacbfb9b544313d7b3eb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:09:35 +0200 Subject: [PATCH 007/113] Tier1: remove unrelevant comment No mutex locking should take place here after careful research. --- r5dev/tier1/NetKey.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/r5dev/tier1/NetKey.cpp b/r5dev/tier1/NetKey.cpp index b84f4f3a..38bdf48f 100644 --- a/r5dev/tier1/NetKey.cpp +++ b/r5dev/tier1/NetKey.cpp @@ -10,6 +10,5 @@ ////////////////////////////////////////////////////////////////////// const char* CNetKey::GetBase64NetKey(void) const { - // TODO: should we not acquire lock for m_Mutex here? return m_szBase64; } From 14c07462120e0b1e30329c8a043f5a02f3ca7031 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:15:27 +0200 Subject: [PATCH 008/113] Engine: move rcon_password entirely to server The client doesn't need this convar, client only needs cl_rcon_address. --- r5dev/common/callback.cpp | 7 +--- r5dev/engine/client/cl_rcon.cpp | 13 ++------ r5dev/engine/server/sv_rcon.cpp | 51 +++++++++++++++++++++++++---- r5dev/engine/server/sv_rcon.h | 2 ++ r5dev/engine/shared/base_rcon.cpp | 4 +-- r5dev/engine/shared/shared_rcon.cpp | 50 ++++++++-------------------- r5dev/engine/shared/shared_rcon.h | 4 ++- 7 files changed, 68 insertions(+), 63 deletions(-) diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp index e47ddbe0..e932710c 100644 --- a/r5dev/common/callback.cpp +++ b/r5dev/common/callback.cpp @@ -245,12 +245,7 @@ void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString #ifndef CLIENT_DLL // Reboot the RCON server to switch address type. - if (RCONServer()->IsInitialized()) - { - Msg(eDLL_T::SERVER, "Rebooting RCON server...\n"); - RCONServer()->Shutdown(); - RCONServer()->Init(rcon_password.GetString(), RCONServer()->GetKey()); - } + RCONServer()->Reboot(); #endif // !CLIENT_DLL } } diff --git a/r5dev/engine/client/cl_rcon.cpp b/r5dev/engine/client/cl_rcon.cpp index 9daf067b..213a7d0a 100644 --- a/r5dev/engine/client/cl_rcon.cpp +++ b/r5dev/engine/client/cl_rcon.cpp @@ -330,17 +330,10 @@ static void RCON_CmdQuery_f(const CCommand& args) { bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", netcon::request_e::SERVERDATA_REQUEST_AUTH); } - else // Auth with RCON server using rcon_password ConVar value. + else // Need at least 3 arguments for a password in PASS command (rcon PASS ) { - const char* storedPassword = rcon_password.GetString(); - - if (!strlen(storedPassword)) - { - Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); - return; - } - - bSuccess = RCONClient()->Serialize(vecMsg, storedPassword, "", netcon::request_e::SERVERDATA_REQUEST_AUTH); + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); + return; } if (bSuccess) diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index 0fc7b21a..ae71061e 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -10,14 +10,13 @@ #include "tier2/socketcreator.h" #include "engine/cmd.h" #include "engine/net.h" +#include "engine/shared/shared_rcon.h" #include "engine/server/sv_rcon.h" #include "protoc/netcon.pb.h" #include "common/igameserverdata.h" #include "mbedtls/include/mbedtls/sha512.h" -#include -#include -#include -#include +#include "mbedtls/aes.h" +#include "mbedtls/ctr_drbg.h" //----------------------------------------------------------------------------- // Purpose: constants @@ -30,9 +29,11 @@ static const char s_BannedMessage[] = "Go away.\n"; //----------------------------------------------------------------------------- // Purpose: console variables //----------------------------------------------------------------------------- +static void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString); +static ConVar sv_rcon_password("sv_rcon_password", "", FCVAR_RELEASE, "Remote server access password (rcon server is disabled if empty)", &RCON_PasswordChanged_f); static ConVar sv_rcon_sendlogs("sv_rcon_sendlogs", "0", FCVAR_RELEASE, "Network console logs to connected and authenticated sockets"); //static ConVar sv_rcon_banpenalty("sv_rcon_banpenalty" , "10", FCVAR_RELEASE, "Number of minutes to ban users who fail rcon authentication"); @@ -41,7 +42,7 @@ static ConVar sv_rcon_maxignores("sv_rcon_maxignores", "15", FCVAR_RELEASE, "Max static ConVar sv_rcon_maxsockets("sv_rcon_maxsockets", "32", FCVAR_RELEASE, "Max number of accepted sockets before the server starts closing redundant sockets", true, 1.f, true, MAX_PLAYERS); static ConVar sv_rcon_maxconnections("sv_rcon_maxconnections", "1", FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket", true, 1.f, true, MAX_PLAYERS, &RCON_ConnectionCountChanged_f); -static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a command frame from a non-authenticated netconsole", true, 0.f, false, 0.f); +static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, false, 0.f); static ConVar sv_rcon_whitelist_address("sv_rcon_whitelist_address", "", FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts", &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); //----------------------------------------------------------------------------- @@ -123,6 +124,19 @@ void CRConServer::Shutdown(void) Msg(eDLL_T::SERVER, "Remote server access deinitialized ('%i' accepted sockets closed)\n", nConnCount); } +//----------------------------------------------------------------------------- +// Purpose: reboots the RCON server if initialized +//----------------------------------------------------------------------------- +void CRConServer::Reboot(void) +{ + if (RCONServer()->IsInitialized()) + { + Msg(eDLL_T::SERVER, "Rebooting RCON server...\n"); + RCONServer()->Shutdown(); + RCONServer()->Init(sv_rcon_password.GetString(), RCONServer()->GetKey()); + } +} + //----------------------------------------------------------------------------- // Purpose: run tasks for the RCON server //----------------------------------------------------------------------------- @@ -569,7 +583,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) const char* pszWhiteListAddress = sv_rcon_whitelist_address.GetString(); if (!pszWhiteListAddress[0]) { - Warning(eDLL_T::SERVER, "Banned list overflowed; please use a whitelist address. RCON shutting down...\n"); + Warning(eDLL_T::SERVER, "Banned list overflowed, please use a whitelist address; remote server access shutting down...\n"); Shutdown(); return true; @@ -580,7 +594,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) { if (rcon_debug.GetBool()) { - Msg(eDLL_T::SERVER, "Banned list is full; dropping '%s'\n", szNetAdr); + Msg(eDLL_T::SERVER, "Banned list is full, dropping '%s'\n", szNetAdr); } return true; @@ -704,6 +718,29 @@ int CRConServer::GetAuthenticatedCount(void) const return m_nAuthConnections; } +//----------------------------------------------------------------------------- +// Purpose: change RCON password on server and drop all connections +//----------------------------------------------------------------------------- +static void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { + const char* pNewString = pConVarRef->GetString(); + + if (strcmp(pOldString, pNewString) == NULL) + return; // Same password. + + if (RCONServer()->IsInitialized()) + { + RCONServer()->SetPassword(pNewString); + } + else // Initialize first + { + RCON_InitServerAndTrySyncKeys(pNewString); + } + } +} + //----------------------------------------------------------------------------- // Purpose: change whitelist address on RCON server //----------------------------------------------------------------------------- diff --git a/r5dev/engine/server/sv_rcon.h b/r5dev/engine/server/sv_rcon.h index 71770910..821c7589 100644 --- a/r5dev/engine/server/sv_rcon.h +++ b/r5dev/engine/server/sv_rcon.h @@ -17,6 +17,8 @@ public: void Init(const char* pPassword, const char* pNetKey = nullptr); void Shutdown(void); + void Reboot(void); + bool SetPassword(const char* pszPassword); bool SetWhiteListAddress(const char* pszAddress); diff --git a/r5dev/engine/shared/base_rcon.cpp b/r5dev/engine/shared/base_rcon.cpp index bf24f5fb..2b677e79 100644 --- a/r5dev/engine/shared/base_rcon.cpp +++ b/r5dev/engine/shared/base_rcon.cpp @@ -94,9 +94,9 @@ void CNetConBase::SetKey(const char* pBase64NetKey, const bool bUseDefaultOnFail Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: encode error (%d)\n", encodeRet); useDefaultKey = true; } - else if (numBytesEncoded != sizeof(m_NetKey)) + else if (numBytesEncoded != AES_128_B64_ENCODED_SIZE) { - Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: write error (%zu != %zu)\n", numBytesEncoded, sizeof(m_NetKey)); + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: write error (%zu != %zu)\n", numBytesEncoded, AES_128_B64_ENCODED_SIZE); failure = true; } else diff --git a/r5dev/engine/shared/shared_rcon.cpp b/r5dev/engine/shared/shared_rcon.cpp index bda8b88c..ec20405c 100644 --- a/r5dev/engine/shared/shared_rcon.cpp +++ b/r5dev/engine/shared/shared_rcon.cpp @@ -325,7 +325,6 @@ void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); ConVar rcon_debug("rcon_debug", "0", FCVAR_RELEASE, "Show rcon debug information ( !slower! )"); ConVar rcon_encryptframes("rcon_encryptframes", "1", FCVAR_RELEASE, "Whether to encrypt RCON messages"); ConVar rcon_key("rcon_key", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Base64 remote server access encryption key (random if empty or invalid)", &RCON_KeyChanged_f); -ConVar rcon_password("rcon_password", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon server is disabled if empty)", &RCON_PasswordChanged_f); //----------------------------------------------------------------------------- // Purpose: change RCON key on server and client @@ -364,45 +363,22 @@ void RCON_KeyChanged_f(IConVar* pConVar, const char* pOldString) } } -//----------------------------------------------------------------------------- -// Purpose: change RCON password on server and drop all connections -//----------------------------------------------------------------------------- -void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString) -{ - if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) - { - const char* pNewString = pConVarRef->GetString(); - - if (strcmp(pOldString, pNewString) == NULL) - return; // Same password. - #ifndef CLIENT_DLL - if (RCONServer()->IsInitialized()) - { - RCONServer()->SetPassword(pNewString); - } - else // Initialize first -#endif // !CLIENT_DLL - { -#if !defined(DEDICATED) && !defined(CLIENT_DLL) - RCONServer()->Init(pNewString, rcon_key.GetString()); - - if (RCONServer()->IsInitialized()) - { - // Sync server & client keys - RCONClient()->SetKey(RCONServer()->GetKey()); - } -#else -#ifdef DEDICATED - RCONServer()->Init(pNewString, rcon_key.GetString()); -#endif // DEDICATED -#ifdef CLIENT_DLL - RCONClient()->Init(rcon_key.GetString()); -#endif // CLIENT_DLL -#endif // !DEDICATED && !CLIENT_DLL - } +void RCON_InitServerAndTrySyncKeys(const char* pPassword) +{ +#ifndef DEDICATED + RCONServer()->Init(pPassword, rcon_key.GetString()); + + if (RCONServer()->IsInitialized()) + { + // Sync server & client keys + RCONClient()->SetKey(RCONServer()->GetKey()); } +#else + RCONServer()->Init(pPassword, rcon_key.GetString()); +#endif // !DEDICATED } +#endif // !CLIENT_DLL #ifndef DEDICATED void RCON_InitClientAndTrySyncKeys() diff --git a/r5dev/engine/shared/shared_rcon.h b/r5dev/engine/shared/shared_rcon.h index c8eb8852..b2ed8fcc 100644 --- a/r5dev/engine/shared/shared_rcon.h +++ b/r5dev/engine/shared/shared_rcon.h @@ -7,8 +7,10 @@ extern ConVar rcon_debug; extern ConVar rcon_encryptframes; extern ConVar rcon_key; -extern ConVar rcon_password; +#ifndef CLIENT_DLL +extern void RCON_InitServerAndTrySyncKeys(const char* pPassword); +#endif // !CLIENT_DLL #ifndef DEDICATED extern void RCON_InitClientAndTrySyncKeys(); #endif // !DEDICATED From 73aff0881966b0a73ade47a9aec60d0fcc989aa3 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:16:10 +0200 Subject: [PATCH 009/113] Resource: update RCON cfg files Reflect recent changes made to the RCON system. --- r5dev/resource/cfg/tools/rcon_client.cfg | 2 +- r5dev/resource/cfg/tools/rcon_client_dev.cfg | 2 +- r5dev/resource/cfg/tools/rcon_server.cfg | 4 ++-- r5dev/resource/cfg/tools/rcon_server_dev.cfg | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/r5dev/resource/cfg/tools/rcon_client.cfg b/r5dev/resource/cfg/tools/rcon_client.cfg index 21b6b565..6d088d92 100644 --- a/r5dev/resource/cfg/tools/rcon_client.cfg +++ b/r5dev/resource/cfg/tools/rcon_client.cfg @@ -3,4 +3,4 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -rcon_address "localhost" // The RCON system will attempt to connect to this address when 'rcon' command is issued. +cl_rcon_address "" // The RCON system will attempt to connect to this address when 'rcon' command is issued. Example [::FFFF:127.0.0.1]:37015 (counts for IPv4 and IPv6). diff --git a/r5dev/resource/cfg/tools/rcon_client_dev.cfg b/r5dev/resource/cfg/tools/rcon_client_dev.cfg index 22b16a0a..cf95e3e9 100644 --- a/r5dev/resource/cfg/tools/rcon_client_dev.cfg +++ b/r5dev/resource/cfg/tools/rcon_client_dev.cfg @@ -3,4 +3,4 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -rcon_address "localhost" // The RCON system will attempt to connect to this address when 'rcon' command is issued. +cl_rcon_address "" // The RCON system will attempt to connect to this address when 'rcon' command is issued. Example [::FFFF:127.0.0.1]:37015 (counts for IPv4 and IPv6). diff --git a/r5dev/resource/cfg/tools/rcon_server.cfg b/r5dev/resource/cfg/tools/rcon_server.cfg index 1f016c15..c38db08a 100644 --- a/r5dev/resource/cfg/tools/rcon_server.cfg +++ b/r5dev/resource/cfg/tools/rcon_server.cfg @@ -3,5 +3,5 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. -sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Enter your own IP address in the same format here (counts for IPv4 and IPv6). +sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. +sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). diff --git a/r5dev/resource/cfg/tools/rcon_server_dev.cfg b/r5dev/resource/cfg/tools/rcon_server_dev.cfg index 734e5216..d605c4eb 100644 --- a/r5dev/resource/cfg/tools/rcon_server_dev.cfg +++ b/r5dev/resource/cfg/tools/rcon_server_dev.cfg @@ -3,10 +3,11 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. -sv_rcon_debug "1" // Show RCON debug information ( ! slower! ). +sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. sv_rcon_banpenalty "1" // Number of minutes to ban IP before removing from ban vector. sv_rcon_maxfailures "5" // Max number of tomes a user can ignore RCON authentication before being banned. sv_rcon_maxignores "5" // Max number of times a user can ignore the no-auth message before being banned. sv_rcon_maxsockets "2" // Max number of accepted sockets before the server starts closing redundant sockets. -sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Enter your own IP address in the same format here (counts for IPv4 and IPv6). +sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). + +rcon_debug "1" // Show RCON debug information ( ! slower! ). From 90e4711425e673c10175e603d1dd42ba04ad91ef Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:28:47 +0200 Subject: [PATCH 010/113] Tier2: move random generator from tier0 to tier2 Moved into cryptutils.cpp. --- r5dev/engine/shared/base_rcon.cpp | 2 +- r5dev/public/tier0/utility.h | 1 - r5dev/public/tier2/cryptutils.h | 2 ++ r5dev/tier0/utility.cpp | 20 -------------------- r5dev/tier2/cryptutils.cpp | 18 ++++++++++++++++++ 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/r5dev/engine/shared/base_rcon.cpp b/r5dev/engine/shared/base_rcon.cpp index 2b677e79..5008737e 100644 --- a/r5dev/engine/shared/base_rcon.cpp +++ b/r5dev/engine/shared/base_rcon.cpp @@ -74,7 +74,7 @@ void CNetConBase::SetKey(const char* pBase64NetKey, const bool bUseDefaultOnFail { const char* errorMsg = nullptr; - if (!CryptoGenRandom(m_NetKey, sizeof(m_NetKey), errorMsg)) + if (!Plat_GenerateRandom(m_NetKey, sizeof(m_NetKey), errorMsg)) { Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: generate error (%s)\n", errorMsg); useDefaultKey = true; diff --git a/r5dev/public/tier0/utility.h b/r5dev/public/tier0/utility.h index ec7f321d..f245e34e 100644 --- a/r5dev/public/tier0/utility.h +++ b/r5dev/public/tier0/utility.h @@ -8,7 +8,6 @@ int CreateDirHierarchy(const char* filePath); bool IsDirectory(const char* path); bool FileEmpty(ifstream& pFile); MODULEINFO GetModuleInfo(const char* szModule); -bool CryptoGenRandom(unsigned char* pData, const uint32_t nDataLen, const char*& outMsg); ///////////////////////////////////////////////////////////////////////////// // Debug diff --git a/r5dev/public/tier2/cryptutils.h b/r5dev/public/tier2/cryptutils.h index 7bf7e822..048ac786 100644 --- a/r5dev/public/tier2/cryptutils.h +++ b/r5dev/public/tier2/cryptutils.h @@ -1,6 +1,8 @@ #ifndef TIER2_CRYPTUTILS_H #define TIER2_CRYPTUTILS_H +bool Plat_GenerateRandom(unsigned char* pBuffer, const uint32_t nBufLen, const char*& errorMsg); + typedef unsigned char CryptoIV_t[16]; typedef unsigned char CryptoKey_t[16]; diff --git a/r5dev/tier0/utility.cpp b/r5dev/tier0/utility.cpp index 42503c1e..0c55dfd1 100644 --- a/r5dev/tier0/utility.cpp +++ b/r5dev/tier0/utility.cpp @@ -121,26 +121,6 @@ MODULEINFO GetModuleInfo(const char* szModule) return modinfo; } -/////////////////////////////////////////////////////////////////////////////// -// For generating random data. -static BCRYPT_ALG_HANDLE s_bcryptAlgorithmProvider; -bool CryptoGenRandom(unsigned char* pData, const uint32_t nDataLen, const char*& outMsg) -{ - if (!s_bcryptAlgorithmProvider && (BCryptOpenAlgorithmProvider(&s_bcryptAlgorithmProvider, L"RNG", 0, 0) < 0)) - { - outMsg = "Failed to open rng algorithm"; - return false; - } - - if (BCryptGenRandom(s_bcryptAlgorithmProvider, pData, nDataLen, 0) < 0) - { - outMsg = "Failed to generate random data"; - return false; - } - - return true; -} - /////////////////////////////////////////////////////////////////////////////// // For printing output to the debugger. void DbgPrint(LPCSTR sFormat, ...) diff --git a/r5dev/tier2/cryptutils.cpp b/r5dev/tier2/cryptutils.cpp index bc4b1c90..18b28ed4 100644 --- a/r5dev/tier2/cryptutils.cpp +++ b/r5dev/tier2/cryptutils.cpp @@ -11,6 +11,24 @@ #include "tier2/cryptutils.h" +static BCRYPT_ALG_HANDLE s_algorithmProvider; +bool Plat_GenerateRandom(unsigned char* buffer, const uint32_t bufferSize, const char*& errorMsg) +{ + if (!s_algorithmProvider && (BCryptOpenAlgorithmProvider(&s_algorithmProvider, L"RNG", 0, 0) < 0)) + { + errorMsg = "Failed to open rng algorithm"; + return false; + } + + if (BCryptGenRandom(s_algorithmProvider, buffer, bufferSize, 0) < 0) + { + errorMsg = "Failed to generate random data"; + return false; + } + + return true; +} + bool Crypto_GenerateIV(CryptoContext_s& ctx, const unsigned char* const data, const size_t size) { mbedtls_entropy_context entropy; From 85f9d26d2359ad572f08aa97d9d3af2d633435a2 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:29:51 +0200 Subject: [PATCH 011/113] Engine: use tier2 random generator for netkey Limit usage to only 1 algorithm provider. --- r5dev/engine/net.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/r5dev/engine/net.cpp b/r5dev/engine/net.cpp index 0734c769..dff24f62 100644 --- a/r5dev/engine/net.cpp +++ b/r5dev/engine/net.cpp @@ -8,6 +8,7 @@ #include "engine/net.h" #ifndef _TOOLS #include "tier1/cvar.h" +#include "tier2/cryptutils.h" #include "mathlib/color.h" #include "net.h" #include "net_chan.h" @@ -202,21 +203,16 @@ void NET_GenerateKey() return; // Change callback will handle this. } - BCRYPT_ALG_HANDLE hAlgorithm; - if (BCryptOpenAlgorithmProvider(&hAlgorithm, L"RNG", 0, 0) < 0) + uint8_t keyBuf[AES_128_KEY_SIZE]; + const char* errorMsg = nullptr; + + if (!Plat_GenerateRandom(keyBuf, sizeof(keyBuf), errorMsg)) { - Error(eDLL_T::ENGINE, NO_ERROR, "Failed to open rng algorithm\n"); + Error(eDLL_T::ENGINE, NO_ERROR, "%s\n", errorMsg); return; } - uint8_t pBuffer[AES_128_KEY_SIZE]; - if (BCryptGenRandom(hAlgorithm, pBuffer, AES_128_KEY_SIZE, 0) < 0) - { - Error(eDLL_T::ENGINE, NO_ERROR, "Failed to generate random data\n"); - return; - } - - NET_SetKey(Base64Encode(string(reinterpret_cast(&pBuffer), AES_128_KEY_SIZE))); + NET_SetKey(Base64Encode(string(reinterpret_cast(&keyBuf), AES_128_KEY_SIZE))); } //----------------------------------------------------------------------------- From 64f8f27bc8fe32d83c78695e3d8948e3a6c31037 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:23:48 +0200 Subject: [PATCH 012/113] Engine: initiate rcon connection from address change callback A more user friendly approach. --- r5dev/engine/client/cl_rcon.cpp | 33 +++++++++++++++-------------- r5dev/engine/shared/shared_rcon.cpp | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/r5dev/engine/client/cl_rcon.cpp b/r5dev/engine/client/cl_rcon.cpp index 213a7d0a..ce56c027 100644 --- a/r5dev/engine/client/cl_rcon.cpp +++ b/r5dev/engine/client/cl_rcon.cpp @@ -29,7 +29,7 @@ static ConVar cl_rcon_inputonly("cl_rcon_inputonly", "0", FCVAR_RELEASE, "Tells //----------------------------------------------------------------------------- static void RCON_CmdQuery_f(const CCommand& args); -static ConCommand rcon("rcon", RCON_CmdQuery_f, "Forward RCON query to remote server", FCVAR_CLIENTDLL | FCVAR_RELEASE, nullptr, "rcon \"\""); +static ConCommand rcon("rcon", RCON_CmdQuery_f, "Forward RCON message to remote server", FCVAR_CLIENTDLL | FCVAR_RELEASE, nullptr, "rcon \"\""); //----------------------------------------------------------------------------- // Purpose: @@ -249,7 +249,9 @@ CRConClient* RCONClient() // Singleton RCON Client. ===================== RCON_AddressChanged_f - + changes the address of the rcon + server and attempts to connect + to it ===================== */ static void RCON_AddressChanged_f(IConVar* pConVar, const char* pOldString) @@ -258,11 +260,6 @@ static void RCON_AddressChanged_f(IConVar* pConVar, const char* pOldString) { const char* pNewString = pConVarRef->GetString(); - if (strcmp(pOldString, pNewString) == NULL) - { - return; // Same address. - } - if (!*pNewString) // Empty address means nothing to network to; shutdown client... { RCONClient()->Shutdown(); @@ -270,6 +267,16 @@ static void RCON_AddressChanged_f(IConVar* pConVar, const char* pOldString) else { RCON_InitClientAndTrySyncKeys(); + + if (RCONClient()->IsInitialized() && !RCONClient()->IsConnected()) + { + if (RCONClient()->IsConnected()) + { + RCONClient()->Disconnect("address change requested"); + } + + RCONClient()->Connect(pNewString); + } } } } @@ -302,14 +309,8 @@ static void RCON_CmdQuery_f(const CCommand& args) if (argCount < 2) { - const char* pszAddress = cl_rcon_address.GetString(); - - if (RCONClient()->IsInitialized() - && !RCONClient()->IsConnected() - && pszAddress[0]) - { - RCONClient()->Connect(pszAddress); - } + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no command provided"); + return; } else { @@ -332,7 +333,7 @@ static void RCON_CmdQuery_f(const CCommand& args) } else // Need at least 3 arguments for a password in PASS command (rcon PASS ) { - Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password provided"); return; } diff --git a/r5dev/engine/shared/shared_rcon.cpp b/r5dev/engine/shared/shared_rcon.cpp index ec20405c..9104d608 100644 --- a/r5dev/engine/shared/shared_rcon.cpp +++ b/r5dev/engine/shared/shared_rcon.cpp @@ -81,7 +81,7 @@ bool CL_NetConConnect(CNetConBase* pBase, const char* pHostAdr, const int nHostP string svLocalHost; const bool bValidSocket = nHostPort != SOCKET_ERROR; - if (bValidSocket && strcmp(pHostAdr, "localhost") == 0) + if (bValidSocket && (strcmp(pHostAdr, "localhost") == 0)) { char szHostName[512]; if (!gethostname(szHostName, sizeof(szHostName))) From dea96ddf3194d361da19f001979274625deaaf19 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 11 Apr 2024 01:42:55 +0200 Subject: [PATCH 013/113] RTech: rename pak defines More correct and consistent naming. --- r5dev/engine/cmodel_bsp.cpp | 22 +++++++++--------- r5dev/engine/cmodel_bsp.h | 6 ++--- r5dev/public/rtech/ipakfile.h | 43 +++++++++++++++++++---------------- r5dev/rtech/pak/pakalloc.cpp | 2 +- r5dev/rtech/pak/pakparse.cpp | 16 ++++++------- r5dev/rtech/pak/pakstate.cpp | 4 ++-- r5dev/rtech/pak/paktools.cpp | 2 +- 7 files changed, 50 insertions(+), 45 deletions(-) diff --git a/r5dev/engine/cmodel_bsp.cpp b/r5dev/engine/cmodel_bsp.cpp index 07033291..25949fdc 100644 --- a/r5dev/engine/cmodel_bsp.cpp +++ b/r5dev/engine/cmodel_bsp.cpp @@ -42,13 +42,13 @@ PakHandle_t CustomPakData_t::LoadAndAddPak(const char* const pakFile) if (numHandles >= MAX_CUSTOM_PAKS) { Error(eDLL_T::ENGINE, NO_ERROR, "Tried to load pak '%s', but already reached the SDK's limit of %d!\n", pakFile, MAX_CUSTOM_PAKS); - return INVALID_PAK_HANDLE; + return PAK_INVALID_HANDLE; } const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0); // failure, don't add and return the invalid handle. - if (pakId == INVALID_PAK_HANDLE) + if (pakId == PAK_INVALID_HANDLE) return pakId; handles[numHandles++] = pakId; @@ -64,14 +64,14 @@ void CustomPakData_t::UnloadAndRemoveAll() { const PakHandle_t pakId = handles[numHandles-1]; - if (pakId == INVALID_PAK_HANDLE) + if (pakId == PAK_INVALID_HANDLE) { assert(0); // invalid handles should not be inserted return; } g_pakLoadApi->UnloadAsync(pakId); - handles[numHandles-1] = INVALID_PAK_HANDLE; + handles[numHandles-1] = PAK_INVALID_HANDLE; } } @@ -83,7 +83,7 @@ PakHandle_t CustomPakData_t::LoadBasePak(const char* const pakFile, const EPakTy const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0); // the file is most likely missing - assert(pakId != INVALID_PAK_HANDLE); + assert(pakId != PAK_INVALID_HANDLE); handles[type] = pakId; return pakId; @@ -97,10 +97,10 @@ void CustomPakData_t::UnloadBasePak(const EPakType type) const PakHandle_t pakId = handles[type]; // only unload if it was actually successfully loaded - if (pakId != INVALID_PAK_HANDLE) + if (pakId != PAK_INVALID_HANDLE) { g_pakLoadApi->UnloadAsync(pakId); - handles[type] = INVALID_PAK_HANDLE; + handles[type] = PAK_INVALID_HANDLE; } } @@ -313,7 +313,7 @@ void Mod_QueuedPakCacheFrame() data->keepLoaded = false; data->pakName[0] = '\0'; - data->pakId = INVALID_PAK_HANDLE; + data->pakId = PAK_INVALID_HANDLE; } --numLeftToProcess; --data; @@ -352,7 +352,7 @@ void Mod_QueuedPakCacheFrame() if (*commonData->pakName) break; - commonData->pakId = INVALID_PAK_HANDLE; + commonData->pakId = PAK_INVALID_HANDLE; LOOP_AGAIN_OR_FINISH: ++it; @@ -421,7 +421,7 @@ void Mod_QueuedPakCacheFrame() CHECK_FOR_FAILURE: - if (commonData->pakId != INVALID_PAK_HANDLE) + if (commonData->pakId != PAK_INVALID_HANDLE) { const PakLoadedInfo_t* const pli = Pak_GetPakInfo(commonData->pakId); @@ -502,7 +502,7 @@ void Mod_PreloadLevelPaks(const char* const pszLevelName) snprintf(szPathBuffer, sizeof(szPathBuffer), "%s.rpak", pSubKey->GetName()); const PakHandle_t nPakId = s_customPakData.LoadAndAddPak(szPathBuffer); - if (nPakId == INVALID_PAK_HANDLE) + if (nPakId == PAK_INVALID_HANDLE) Error(eDLL_T::ENGINE, NO_ERROR, "%s: unable to load pak '%s' results '%d'\n", __FUNCTION__, szPathBuffer, nPakId); } } diff --git a/r5dev/engine/cmodel_bsp.h b/r5dev/engine/cmodel_bsp.h index da8eaec5..019134df 100644 --- a/r5dev/engine/cmodel_bsp.h +++ b/r5dev/engine/cmodel_bsp.h @@ -39,7 +39,7 @@ struct CommonPakData_t void Reset() { - pakId = INVALID_PAK_HANDLE; + pakId = PAK_INVALID_HANDLE; keepLoaded = false; basePakName = nullptr; @@ -83,14 +83,14 @@ struct CustomPakData_t // the absolute max number of custom paks, note that the engine's limit // could still be reached before this number as game scripts and other // code still loads paks such as gladiator cards or load screens - MAX_CUSTOM_PAKS = (PAK_MAX_HANDLES - CommonPakData_t::PAK_TYPE_COUNT) + MAX_CUSTOM_PAKS = (PAK_MAX_LOADED_PAKS - CommonPakData_t::PAK_TYPE_COUNT) }; CustomPakData_t() { for (size_t i = 0; i < V_ARRAYSIZE(handles); i++) { - handles[i] = INVALID_PAK_HANDLE; + handles[i] = PAK_INVALID_HANDLE; } // the first # handles are reserved for base SDK paks diff --git a/r5dev/public/rtech/ipakfile.h b/r5dev/public/rtech/ipakfile.h index e2c81a10..f3aab5e5 100644 --- a/r5dev/public/rtech/ipakfile.h +++ b/r5dev/public/rtech/ipakfile.h @@ -1,3 +1,8 @@ +//=============================================================================// +// +// Purpose: pak file constants and types +// +//=============================================================================// #ifndef RTECH_IPACKFILE_H #define RTECH_IPACKFILE_H #include "tier0/jobthread.h" @@ -20,15 +25,15 @@ #define PAK_HEADER_FLAGS_ZSTREAM_ENCODED (1<<9) // max amount of types at runtime in which assets will be tracked -#define PAK_MAX_TYPES 64 -#define PAK_MAX_TYPES_MASK (PAK_MAX_TYPES-1) +#define PAK_MAX_TRACKED_TYPES 64 +#define PAK_MAX_TRACKED_TYPES_MASK (PAK_MAX_TRACKED_TYPES-1) // max amount of global pak assets at runtime -#define PAK_MAX_ASSETS 0x40000 // TODO: rename to PAK_MAX_LOADED_ASSETS -#define PAK_MAX_ASSETS_MASK (PAK_MAX_ASSETS-1) +#define PAK_MAX_LOADED_ASSETS 0x40000 +#define PAK_MAX_LOADED_ASSETS_MASK (PAK_MAX_LOADED_ASSETS-1) // max amount of global pak assets tracked at runtime -#define PAK_MAX_TRACKED_ASSETS (PAK_MAX_ASSETS/2) +#define PAK_MAX_TRACKED_ASSETS (PAK_MAX_LOADED_ASSETS/2) #define PAK_MAX_TRACKED_ASSETS_MASK (PAK_MAX_TRACKED_ASSETS-1) // max amount of segments a pak file could have @@ -42,8 +47,8 @@ #define PAK_MAX_STREAMING_FILE_HANDLES_PER_SET 4 // max amount of paks that could be loaded at runtime -#define PAK_MAX_HANDLES 512 // TODO: rename to PAK_MAX_LOADED_PAKS -#define PAK_MAX_HANDLES_MASK (PAK_MAX_HANDLES-1) +#define PAK_MAX_LOADED_PAKS 512 +#define PAK_MAX_LOADED_PAKS_MASK (PAK_MAX_LOADED_PAKS-1) // max amount of async streaming requests that could be made per pak file, if a // pak file has more patches than this number, and is already trying to stream @@ -82,7 +87,7 @@ #define PLATFORM_PAK_OVERRIDE_PATH PAK_BASE_PATH"Win64_override\\" // the handle that should be returned when a pak failed to load or process -#define INVALID_PAK_HANDLE -1 // TODO: rename to PAK_INVALID_HANDLE +#define PAK_INVALID_HANDLE -1 #define PAK_MAX_DISPATCH_LOAD_JOBS 4 #define PAK_DEFAULT_JOB_GROUP_ID 0x3000 @@ -235,7 +240,7 @@ struct PakAsset_t FORCEINLINE uint8_t HashTableIndexForAssetType() const { - return (((0x1020601 * magic) >> 24) & PAK_MAX_TYPES_MASK); + return (((0x1020601 * magic) >> 24) & PAK_MAX_TRACKED_TYPES_MASK); } }; @@ -264,7 +269,7 @@ struct PakTracker_s int unk_4; int unk_8; char gap_C[644100]; - int loadedAssetIndices[PAK_MAX_HANDLES]; + int loadedAssetIndices[PAK_MAX_LOADED_PAKS]; char gap_9DC04[522240]; }; @@ -318,8 +323,8 @@ public: struct PakGlobals_s { // [ PIXIE ]: Max possible registered assets on Season 3, 0-2 I did not check yet. - PakAssetBinding_t assetBindings[PAK_MAX_TYPES]; - PakAssetShort_t loadedAssets[PAK_MAX_ASSETS]; + PakAssetBinding_t assetBindings[PAK_MAX_TRACKED_TYPES]; + PakAssetShort_t loadedAssets[PAK_MAX_LOADED_ASSETS]; // assets that are tracked across all asset types PakAssetTracker_s trackedAssets[PAK_MAX_TRACKED_ASSETS]; @@ -328,11 +333,11 @@ struct PakGlobals_s RHashMap loadedPakMap; // links to 'loadedPaks' // all currently loaded pak handles - PakLoadedInfo_t loadedPaks[PAK_MAX_HANDLES]; + PakLoadedInfo_t loadedPaks[PAK_MAX_LOADED_PAKS]; RMultiHashMap unkMap2; // links to 'unkIntArray' and 'unkIntArray2' int unkIntArray[PAK_MAX_TRACKED_ASSETS]; - int unkIntArray2[PAK_MAX_ASSETS]; + int unkIntArray2[PAK_MAX_LOADED_ASSETS]; // whether asset streaming (mandatory & optional) is enabled b64 useStreamingSystem; @@ -365,10 +370,10 @@ struct PakGlobals_s int16_t loadedPakCount; int16_t requestedPakCount; - PakHandle_t loadedPakHandles[PAK_MAX_HANDLES]; + PakHandle_t loadedPakHandles[PAK_MAX_LOADED_PAKS]; - JobTypeID_t assetBindJobTypes[PAK_MAX_TYPES]; - JobTypeID_t jobTypeSlots_Unused[PAK_MAX_TYPES]; + JobTypeID_t assetBindJobTypes[PAK_MAX_TRACKED_TYPES]; + JobTypeID_t jobTypeSlots_Unused[PAK_MAX_TRACKED_TYPES]; JobTypeID_t dispatchLoadJobTypes[PAK_MAX_DISPATCH_LOAD_JOBS]; uint8_t dispathLoadJobPriorities[PAK_MAX_DISPATCH_LOAD_JOBS]; // promoted to JobPriority_e @@ -513,7 +518,7 @@ struct PakSegmentHeader_t struct PakSegmentDescriptor_t { - size_t assetTypeCount[PAK_MAX_TYPES]; + size_t assetTypeCount[PAK_MAX_TRACKED_TYPES]; int64_t segmentSizes[PAK_MAX_SEGMENTS]; size_t segmentSizeForType[PAK_SEGMENT_BUFFER_TYPES]; @@ -693,7 +698,7 @@ struct PakMemoryData_t int numShiftedPointers; // array of sizes/offsets in the SF_HEAD segment buffer - __int64 unkAssetTypeBindingSizes[PAK_MAX_TYPES]; + __int64 unkAssetTypeBindingSizes[PAK_MAX_TRACKED_TYPES]; const char* fileName; PakFileHeader_t pakHeader; diff --git a/r5dev/rtech/pak/pakalloc.cpp b/r5dev/rtech/pak/pakalloc.cpp index b3fb82b1..31b0f5eb 100644 --- a/r5dev/rtech/pak/pakalloc.cpp +++ b/r5dev/rtech/pak/pakalloc.cpp @@ -15,7 +15,7 @@ void Pak_AlignSegmentHeaders(PakFile_t* const pak, PakSegmentDescriptor_t* const uint64_t headersSize = 0; uint8_t headerSegmentAlignment = static_cast(desc->segmentAlignmentForType[SF_HEAD]); - for (uint8_t i = 0; i < PAK_MAX_TYPES; ++i) + for (uint8_t i = 0; i < PAK_MAX_TRACKED_TYPES; ++i) { const PakAssetBinding_t& binding = g_pakGlobals->assetBindings[i]; diff --git a/r5dev/rtech/pak/pakparse.cpp b/r5dev/rtech/pak/pakparse.cpp index cfad8e3d..6caef4e3 100644 --- a/r5dev/rtech/pak/pakparse.cpp +++ b/r5dev/rtech/pak/pakparse.cpp @@ -32,10 +32,10 @@ static bool Pak_ResolveAssetDependency(const PakFile_t* const pak, PakGuid_t cur currentIndex++; - if (currentIndex >= PAK_MAX_ASSETS) + if (currentIndex >= PAK_MAX_LOADED_ASSETS) return false; - currentIndex &= PAK_MAX_ASSETS_MASK; + currentIndex &= PAK_MAX_LOADED_ASSETS_MASK; currentGuid = g_pakGlobals->loadedAssets[currentIndex].guid; if (currentGuid == targetGuid) @@ -51,7 +51,7 @@ static bool Pak_ResolveAssetDependency(const PakFile_t* const pak, PakGuid_t cur void Pak_ResolveAssetRelations(PakFile_t* const pak, const PakAsset_t* const asset) { PakPage_t* const pGuidDescriptors = &pak->memoryData.guidDescriptors[asset->dependenciesIndex]; - uint32_t* const v5 = (uint32_t*)g_pakGlobals->loadedPaks[pak->memoryData.pakId & PAK_MAX_HANDLES_MASK].qword50; + uint32_t* const v5 = (uint32_t*)g_pakGlobals->loadedPaks[pak->memoryData.pakId & PAK_MAX_LOADED_PAKS_MASK].qword50; if (pak_debugrelations.GetBool()) Msg(eDLL_T::RTECH, "Resolving relations for asset: '0x%-16llX', dependencies: %-4u; in pak '%s'\n", @@ -65,7 +65,7 @@ void Pak_ResolveAssetRelations(PakFile_t* const pak, const PakAsset_t* const ass const PakGuid_t targetGuid = reinterpret_cast(*pCurrentGuid); // get asset index - int currentIndex = targetGuid & PAK_MAX_ASSETS_MASK; + int currentIndex = targetGuid & PAK_MAX_LOADED_ASSETS_MASK; const PakGuid_t currentGuid = g_pakGlobals->loadedAssets[currentIndex].guid; const int64_t v9 = 2i64 * InterlockedExchangeAdd(v5, 1u); @@ -192,14 +192,14 @@ void Pak_RunAssetLoadingJobs(PakFile_t* const pak) //----------------------------------------------------------------------------- PakHandle_t Pak_LoadAsync(const char* const fileName, CAlignedMemAlloc* const allocator, const int nIdx, const bool bUnk) { - PakHandle_t pakId = INVALID_PAK_HANDLE; + PakHandle_t pakId = PAK_INVALID_HANDLE; if (Pak_FileExists(fileName)) { Msg(eDLL_T::RTECH, "Loading pak file: '%s'\n", fileName); pakId = v_Pak_LoadAsync(fileName, allocator, nIdx, bUnk); - if (pakId == INVALID_PAK_HANDLE) + if (pakId == PAK_INVALID_HANDLE) Error(eDLL_T::RTECH, NO_ERROR, "%s: Failed read '%s' results '%d'\n", __FUNCTION__, fileName, pakId); } else @@ -450,7 +450,7 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) if (pak->patchCount >= pak->memoryData.pakHeader.patchIndex) { FS_CloseAsyncFile(fileStream->fileHandle); - fileStream->fileHandle = INVALID_PAK_HANDLE; + fileStream->fileHandle = PAK_INVALID_HANDLE; fileStream->qword0 = 0; fileStream->finishedLoadingPatches = true; @@ -677,7 +677,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) uint32_t i = 0; PakAsset_t* pAsset = nullptr; - for (int j = pak->memoryData.pakId & PAK_MAX_HANDLES_MASK; i < pak->GetHeader().assetCount; a1->assetGuids[i - 1] = pAsset->guid) + for (int j = pak->memoryData.pakId & PAK_MAX_LOADED_PAKS_MASK; i < pak->GetHeader().assetCount; a1->assetGuids[i - 1] = pAsset->guid) { pAsset = &pak->memoryData.assetEntries[i]; if (pAsset->numRemainingDependencies) diff --git a/r5dev/rtech/pak/pakstate.cpp b/r5dev/rtech/pak/pakstate.cpp index 496d855d..927683b3 100644 --- a/r5dev/rtech/pak/pakstate.cpp +++ b/r5dev/rtech/pak/pakstate.cpp @@ -52,7 +52,7 @@ static void Pak_ListTypes_f() uint32_t nRegistered = 0; - for (int8_t i = 0; i < PAK_MAX_TYPES; ++i) + for (int8_t i = 0; i < PAK_MAX_TRACKED_TYPES; ++i) { PakAssetBinding_t* type = &g_pakGlobals->assetBindings[i]; @@ -135,7 +135,7 @@ static void Pak_Swap_f(const CCommand& args) const char* pakName = nullptr; - PakHandle_t pakHandle = INVALID_PAK_HANDLE; + PakHandle_t pakHandle = PAK_INVALID_HANDLE; const PakLoadedInfo_t* pakInfo = nullptr; if (args.HasOnlyDigits(1)) diff --git a/r5dev/rtech/pak/paktools.cpp b/r5dev/rtech/pak/paktools.cpp index f33038b3..0f850314 100644 --- a/r5dev/rtech/pak/paktools.cpp +++ b/r5dev/rtech/pak/paktools.cpp @@ -255,7 +255,7 @@ PakGuid_t Pak_StringToGuid(const char* const string) //----------------------------------------------------------------------------- PakLoadedInfo_t* Pak_GetPakInfo(const PakHandle_t pakId) { - return &g_pakGlobals->loadedPaks[pakId & PAK_MAX_HANDLES_MASK]; + return &g_pakGlobals->loadedPaks[pakId & PAK_MAX_LOADED_PAKS_MASK]; } //----------------------------------------------------------------------------- From 2587392f88703acbcc8daa0de657ba3e640e4755 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 11 Apr 2024 02:19:36 +0200 Subject: [PATCH 014/113] RTech: use more consistent type names Force consistency between type names (follow scheme used in tier0 and rtech_game export symbols). --- r5dev/datacache/mdlcache.h | 2 +- r5dev/engine/cmodel_bsp.cpp | 6 +- r5dev/public/rtech/ipakfile.h | 130 +++++++++++++++++----------------- r5dev/rtech/pak/pakalloc.cpp | 14 ++-- r5dev/rtech/pak/pakalloc.h | 8 +-- r5dev/rtech/pak/pakdecode.cpp | 52 +++++++------- r5dev/rtech/pak/pakdecode.h | 8 +-- r5dev/rtech/pak/pakencode.cpp | 14 ++-- r5dev/rtech/pak/pakparse.cpp | 92 ++++++++++++------------ r5dev/rtech/pak/pakparse.h | 18 ++--- r5dev/rtech/pak/pakpatch.cpp | 14 ++-- r5dev/rtech/pak/pakpatch.h | 2 +- r5dev/rtech/pak/pakstate.cpp | 14 ++-- r5dev/rtech/pak/pakstate.h | 6 +- r5dev/rtech/pak/pakstream.cpp | 16 ++--- r5dev/rtech/pak/pakstream.h | 8 +-- r5dev/rtech/pak/paktools.cpp | 70 +++++++++--------- r5dev/rtech/pak/paktools.h | 16 ++--- 18 files changed, 245 insertions(+), 245 deletions(-) diff --git a/r5dev/datacache/mdlcache.h b/r5dev/datacache/mdlcache.h index 407fa68a..b1b45b2a 100644 --- a/r5dev/datacache/mdlcache.h +++ b/r5dev/datacache/mdlcache.h @@ -176,7 +176,7 @@ struct studioanimcache_t const char* rigName; int unk0; int numSequences; - PakPage_t sequences; + PakPage_u sequences; int unk1; int unk2; }; diff --git a/r5dev/engine/cmodel_bsp.cpp b/r5dev/engine/cmodel_bsp.cpp index 25949fdc..b5511af7 100644 --- a/r5dev/engine/cmodel_bsp.cpp +++ b/r5dev/engine/cmodel_bsp.cpp @@ -236,8 +236,8 @@ void Mod_QueuedPakCacheFrame() { if (*data->pakName) { - PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(data->pakId); - EPakStatus status; + PakLoadedInfo_s* const pakInfo = Pak_GetPakInfo(data->pakId); + PakStatus_e status; // TODO: revisit this, this appears incorrect but also the way // respawn does this. it this always supposed to be true on @@ -423,7 +423,7 @@ CHECK_FOR_FAILURE: if (commonData->pakId != PAK_INVALID_HANDLE) { - const PakLoadedInfo_t* const pli = Pak_GetPakInfo(commonData->pakId); + const PakLoadedInfo_s* const pli = Pak_GetPakInfo(commonData->pakId); if (pli->handle != commonData->pakId || ((pli->status - 9) & 0xFFFFFFFB) != 0) { diff --git a/r5dev/public/rtech/ipakfile.h b/r5dev/public/rtech/ipakfile.h index f3aab5e5..7c29e02e 100644 --- a/r5dev/public/rtech/ipakfile.h +++ b/r5dev/public/rtech/ipakfile.h @@ -95,7 +95,7 @@ //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- -struct PakFile_t; +struct PakFile_s; //----------------------------------------------------------------------------- // Handle types @@ -106,7 +106,7 @@ typedef uint64_t PakGuid_t; //----------------------------------------------------------------------------- // Page handle types //----------------------------------------------------------------------------- -struct PakPageHeader_t +struct PakPageHeader_s { uint32_t segmentIdx; uint32_t pageAlignment; @@ -120,7 +120,7 @@ struct PakPageHeader_t #define IS_PAKPTR_VALID(pak, ptr) ((ptr)->index != UINT32_MAX && (ptr)->offset != UINT32_MAX && (ptr)->index < (pak)->GetPageCount() && (ptr)->offset <= (pak)->GetPageSize((ptr)->index)) #define ASSERT_PAKPTR_VALID(pak, ptr) Assert(IS_PAKPTR_VALID(pak, ptr), "Invalid pak page pointer") -union PakPage_t +union PakPage_u { struct { @@ -133,7 +133,7 @@ union PakPage_t //----------------------------------------------------------------------------- // Enumerations //----------------------------------------------------------------------------- -enum EPakDecodeMode : int32_t +enum PakDecodeMode_e { MODE_DISABLED = -1, @@ -142,7 +142,7 @@ enum EPakDecodeMode : int32_t MODE_ZSTD }; -enum EPakStreamSet +enum PakStreamSet_e { STREAMING_SET_MANDATORY = 0, STREAMING_SET_OPTIONAL, @@ -151,7 +151,7 @@ enum EPakStreamSet STREAMING_SET_COUNT }; -enum EPakStatus : int32_t +enum PakStatus_e { PAK_STATUS_FREED = 0, PAK_STATUS_LOAD_PENDING = 1, @@ -171,7 +171,7 @@ enum EPakStatus : int32_t PAK_STATUS_BUSY = 15 }; -struct PakAssetBinding_t +struct PakAssetBinding_s { enum EType { @@ -210,15 +210,15 @@ struct PakAssetBinding_t // [ PIXIE ]: Should be the full size across Season 0-3. }; -struct PakAsset_t +struct PakAsset_s { // the guid of this asset, which will be used to index into, and retrieve // this asset from the hash table PakGuid_t guid; uint64_t padding; // Unknown. - PakPage_t headPtr; - PakPage_t dataPtr; + PakPage_u headPtr; + PakPage_u dataPtr; // offset to the streaming data in the streaming set uint64_t streamingDataFileOffset[STREAMING_SET_COUNT]; @@ -244,7 +244,7 @@ struct PakAsset_t } }; -struct PakAssetShort_t +struct PakAssetShort_s { PakGuid_t guid; uint32_t trackerIndex; @@ -273,7 +273,7 @@ struct PakTracker_s char gap_9DC04[522240]; }; -class PakLoadedInfo_t +class PakLoadedInfo_s { public: struct StreamingInfo_t @@ -297,7 +297,7 @@ public: }; PakHandle_t handle; - EPakStatus status; + PakStatus_e status; JobID_t loadJobId; uint32_t padding_maybe; @@ -312,7 +312,7 @@ public: void* segmentBuffers[PAK_SEGMENT_BUFFER_TYPES]; _QWORD qword50; FILETIME fileTime; - PakFile_t* pakFile; + PakFile_s* pakFile; StreamingInfo_t streamInfo[STREAMING_SET_COUNT]; uint32_t fileHandle; uint8_t m_nUnk5; @@ -320,11 +320,11 @@ public: }; //Size: 0x00B8/0x00E8 -struct PakGlobals_s +struct PakGlobalState_s { // [ PIXIE ]: Max possible registered assets on Season 3, 0-2 I did not check yet. - PakAssetBinding_t assetBindings[PAK_MAX_TRACKED_TYPES]; - PakAssetShort_t loadedAssets[PAK_MAX_LOADED_ASSETS]; + PakAssetBinding_s assetBindings[PAK_MAX_TRACKED_TYPES]; + PakAssetShort_s loadedAssets[PAK_MAX_LOADED_ASSETS]; // assets that are tracked across all asset types PakAssetTracker_s trackedAssets[PAK_MAX_TRACKED_ASSETS]; @@ -333,7 +333,7 @@ struct PakGlobals_s RHashMap loadedPakMap; // links to 'loadedPaks' // all currently loaded pak handles - PakLoadedInfo_t loadedPaks[PAK_MAX_LOADED_PAKS]; + PakLoadedInfo_s loadedPaks[PAK_MAX_LOADED_PAKS]; RMultiHashMap unkMap2; // links to 'unkIntArray' and 'unkIntArray2' int unkIntArray[PAK_MAX_TRACKED_ASSETS]; @@ -395,19 +395,19 @@ struct PakGlobals_s uint8_t* patchNumbers; }; -struct PakPatchFileHeader_t +struct PakPatchFileHeader_s { uint64_t compressedSize; uint64_t decompressedSize; }; -struct PakPatchDataHeader_t +struct PakPatchDataHeader_s { uint32_t editStreamSize; uint32_t pageCount; }; -struct PakFileHeader_t +struct PakFileHeader_s { inline uint32_t GetTotalStreamingNamesBufferSize() const { @@ -425,30 +425,30 @@ struct PakFileHeader_t inline uint64_t GetTotalHeaderSize() const { - uint64_t headerSize = sizeof(PakFileHeader_t); + uint64_t headerSize = sizeof(PakFileHeader_s); // if we have patches, we should include the patch header as well if (patchIndex > 0) - headerSize += sizeof(PakPatchDataHeader_t); + headerSize += sizeof(PakPatchDataHeader_s); // the streaming file paths belong to the header as well headerSize += GetTotalStreamingNamesBufferSize(); return headerSize; } - inline EPakDecodeMode GetCompressionMode() const + inline PakDecodeMode_e GetCompressionMode() const { if (flags & PAK_HEADER_FLAGS_ZSTREAM_ENCODED) - return EPakDecodeMode::MODE_ZSTD; + return PakDecodeMode_e::MODE_ZSTD; // NOTE: this should be the first check once we rebuilt function // 14043F300 and alloc ring buffer for the flags individually instead // instead of having to define the main compress flag (which really // just means that the pak is using the RTech decoder) else if (flags & PAK_HEADER_FLAGS_COMPRESSED) - return EPakDecodeMode::MODE_RTECH; + return PakDecodeMode_e::MODE_RTECH; - return EPakDecodeMode::MODE_DISABLED; + return PakDecodeMode_e::MODE_DISABLED; } // file versions @@ -501,7 +501,7 @@ struct PakFileHeader_t uint32_t memPageOffset; uint8_t unk3[0x8]; -}; static_assert(sizeof(PakFileHeader_t) == 0x80); +}; static_assert(sizeof(PakFileHeader_s) == 0x80); // segment flags #define SF_HEAD (0) @@ -509,14 +509,14 @@ struct PakFileHeader_t #define SF_CPU (1 << 1) // 0x2 #define SF_DEV (1 << 8) // 0x80 -struct PakSegmentHeader_t +struct PakSegmentHeader_s { int typeFlags; int dataAlignment; size_t dataSize; }; -struct PakSegmentDescriptor_t +struct PakSegmentDescriptor_s { size_t assetTypeCount[PAK_MAX_TRACKED_TYPES]; int64_t segmentSizes[PAK_MAX_SEGMENTS]; @@ -525,7 +525,7 @@ struct PakSegmentDescriptor_t int segmentAlignmentForType[PAK_SEGMENT_BUFFER_TYPES]; }; -struct PakDecoder_t +struct PakDecoder_s { const uint8_t* inputBuf; uint8_t* outputBuf; @@ -542,7 +542,7 @@ struct PakDecoder_t uint32_t headerOffset; // this field was unused, it now contains the decoder mode - EPakDecodeMode decodeMode; + PakDecodeMode_e decodeMode; // NOTE: unless you are in the RTech decoder, use the getter if you need to // get the current pos!!! @@ -579,13 +579,13 @@ struct PakDecoder_t }; }; -struct PakRingBufferFrame_t +struct PakRingBufferFrame_s { size_t bufIndex; size_t frameLen; }; -struct PakFileStream_t +struct PakFileStream_s { struct Descriptor { @@ -595,7 +595,7 @@ struct PakFileStream_t // NOTE: if this is set, the game sets 'PakMemoryData_t::processedPatchedDataSize' // to 'dataOffset'; else its getting set to 'sizeof(PakFileHeader_t)'. - EPakDecodeMode compressionMode; + PakDecodeMode_e compressionMode; }; _QWORD qword0; @@ -615,11 +615,11 @@ struct PakFileStream_t _QWORD bytesStreamed; }; -typedef struct PakPatchFuncs_s +struct PakPatchFuncs_s { - typedef bool (*PatchFunc_t)(PakFile_t* const pak, size_t* const numAvailableBytes); + typedef bool (*PatchFunc_t)(PakFile_s* const pak, size_t* const numAvailableBytes); - enum EPatchCommands + enum PatchCommands_e { PATCH_CMD0, PATCH_CMD1, @@ -641,9 +641,9 @@ typedef struct PakPatchFuncs_s PatchFunc_t patchFuncs[PATCH_CMD_COUNT]; -} PakPatchFuncs_t; +}; -struct PakMemoryData_t +struct PakMemoryData_s { uint64_t processedPatchedDataSize; char* patchData; // pointer to patch stream data @@ -675,24 +675,24 @@ struct PakMemoryData_t int* loadedAssetIndices; uint8_t** memPageBuffers; - PakPatchFileHeader_t* patchHeaders; + PakPatchFileHeader_s* patchHeaders; unsigned short* patchIndices; char* streamingFilePaths[STREAMING_SET_COUNT]; - PakSegmentHeader_t* segmentHeaders; - PakPageHeader_t* pageHeaders; + PakSegmentHeader_s* segmentHeaders; + PakPageHeader_s* pageHeaders; - PakPage_t* virtualPointers; - PakAsset_t* assetEntries; + PakPage_u* virtualPointers; + PakAsset_s* assetEntries; - PakPage_t* guidDescriptors; + PakPage_u* guidDescriptors; uint32_t* fileRelations; char gap5E0[32]; - PakPatchDataHeader_t* patchDataHeader; - PakAsset_t** ppAssetEntries; + PakPatchDataHeader_s* patchDataHeader; + PakAsset_s** ppAssetEntries; int someAssetCount; int numShiftedPointers; @@ -701,11 +701,11 @@ struct PakMemoryData_t __int64 unkAssetTypeBindingSizes[PAK_MAX_TRACKED_TYPES]; const char* fileName; - PakFileHeader_t pakHeader; - PakPatchFileHeader_t patchHeader; + PakFileHeader_s pakHeader; + PakPatchFileHeader_s patchHeader; }; -struct PakFile_t +struct PakFile_s { int numProcessedPointers; uint32_t processedAssetCount; @@ -715,26 +715,26 @@ struct PakFile_t uint32_t patchCount; uint32_t dword14; - PakFileStream_t fileStream; + PakFileStream_s fileStream; uint64_t inputBytePos; uint8_t byte1F8; char gap1F9[4]; uint8_t byte1FD; bool isOffsetted_MAYBE; bool isCompressed; - PakDecoder_t pakDecoder; + PakDecoder_s pakDecoder; uint8_t* decompBuffer; size_t maxCopySize; uint64_t qword298; - PakMemoryData_t memoryData; + PakMemoryData_s memoryData; inline const char* GetName() const { return memoryData.fileName; } - inline const PakFileHeader_t& GetHeader() const + inline const PakFileHeader_s& GetHeader() const { return memoryData.pakHeader; } @@ -771,7 +771,7 @@ struct PakFile_t return true; } - inline const PakPageHeader_t* GetPageHeader(const uint32_t i) const + inline const PakPageHeader_s* GetPageHeader(const uint32_t i) const { assert(i != UINT32_MAX && i < GetPageCount()); @@ -791,14 +791,14 @@ struct PakFile_t return memoryData.memPageBuffers[index] + offset; } - inline void* GetPointerForPageOffset(const PakPage_t& ptr) const + inline void* GetPointerForPageOffset(const PakPage_u& ptr) const { assert(IsPageOffsetValid(ptr.index, ptr.offset)); return memoryData.memPageBuffers[ptr.index] + ptr.offset; } - inline void* GetPointerForPageOffset(const PakPage_t* ptr) const + inline void* GetPointerForPageOffset(const PakPage_u* ptr) const { assert(IsPageOffsetValid(ptr->index, ptr->offset)); @@ -811,7 +811,7 @@ struct PakFile_t return GetHeader().virtualSegmentCount; } - inline const PakSegmentHeader_t* GetSegmentHeader(const uint32_t i) const + inline const PakSegmentHeader_s* GetSegmentHeader(const uint32_t i) const { assert(i < GetSegmentCount()); @@ -821,11 +821,11 @@ struct PakFile_t static_assert(sizeof(PakTracker_s) == 0x11D410); -static_assert(sizeof(PakFile_t) == 2224); // S3+ -static_assert(sizeof(PakLoadedInfo_t) == 184); -static_assert(sizeof(PakDecoder_t) == 136); -static_assert(sizeof(PakPatchFileHeader_t) == 16); -static_assert(sizeof(PakPatchDataHeader_t) == 8); -static_assert(sizeof(PakGlobals_s) == 0xC98A48); +static_assert(sizeof(PakFile_s) == 2224); // S3+ +static_assert(sizeof(PakLoadedInfo_s) == 184); +static_assert(sizeof(PakDecoder_s) == 136); +static_assert(sizeof(PakPatchFileHeader_s) == 16); +static_assert(sizeof(PakPatchDataHeader_s) == 8); +static_assert(sizeof(PakGlobalState_s) == 0xC98A48); #endif // RTECH_IPACKFILE_H diff --git a/r5dev/rtech/pak/pakalloc.cpp b/r5dev/rtech/pak/pakalloc.cpp index 31b0f5eb..0533bded 100644 --- a/r5dev/rtech/pak/pakalloc.cpp +++ b/r5dev/rtech/pak/pakalloc.cpp @@ -10,14 +10,14 @@ //----------------------------------------------------------------------------- // aligns the segment headers for each asset type //----------------------------------------------------------------------------- -void Pak_AlignSegmentHeaders(PakFile_t* const pak, PakSegmentDescriptor_t* const desc) +void Pak_AlignSegmentHeaders(PakFile_s* const pak, PakSegmentDescriptor_s* const desc) { uint64_t headersSize = 0; uint8_t headerSegmentAlignment = static_cast(desc->segmentAlignmentForType[SF_HEAD]); for (uint8_t i = 0; i < PAK_MAX_TRACKED_TYPES; ++i) { - const PakAssetBinding_t& binding = g_pakGlobals->assetBindings[i]; + const PakAssetBinding_s& binding = g_pakGlobals->assetBindings[i]; if (desc->assetTypeCount[i]) { @@ -41,11 +41,11 @@ void Pak_AlignSegmentHeaders(PakFile_t* const pak, PakSegmentDescriptor_t* const //----------------------------------------------------------------------------- // aligns each individual non-header segment //----------------------------------------------------------------------------- -void Pak_AlignSegments(PakFile_t* const pak, PakSegmentDescriptor_t* const desc) +void Pak_AlignSegments(PakFile_s* const pak, PakSegmentDescriptor_s* const desc) { for (uint16_t i = 0; i < pak->GetSegmentCount(); ++i) { - const PakSegmentHeader_t* const segHeader = pak->GetSegmentHeader(i); + const PakSegmentHeader_s* const segHeader = pak->GetSegmentHeader(i); const uint8_t segmentType = segHeader->typeFlags & (SF_TEMP | SF_CPU); @@ -71,14 +71,14 @@ void Pak_AlignSegments(PakFile_t* const pak, PakSegmentDescriptor_t* const desc) //----------------------------------------------------------------------------- // copy's pages into pre-allocated and aligned segments //----------------------------------------------------------------------------- -void Pak_CopyPagesToSegments(PakFile_t* const pak, PakLoadedInfo_t* const loadedInfo, PakSegmentDescriptor_t* const desc) +void Pak_CopyPagesToSegments(PakFile_s* const pak, PakLoadedInfo_s* const loadedInfo, PakSegmentDescriptor_s* const desc) { for (uint32_t i = 0; i < pak->GetPageCount(); ++i) { - const PakPageHeader_t* const pageHeader = pak->GetPageHeader(i); + const PakPageHeader_s* const pageHeader = pak->GetPageHeader(i); const uint32_t segmentIndex = pageHeader->segmentIdx; - const PakSegmentHeader_t* const segHeader = pak->GetSegmentHeader(segmentIndex); + const PakSegmentHeader_s* const segHeader = pak->GetSegmentHeader(segmentIndex); const int typeFlags = segHeader->typeFlags; // check if header page diff --git a/r5dev/rtech/pak/pakalloc.h b/r5dev/rtech/pak/pakalloc.h index 9d2b2a81..58d06382 100644 --- a/r5dev/rtech/pak/pakalloc.h +++ b/r5dev/rtech/pak/pakalloc.h @@ -2,12 +2,12 @@ #define RTECH_PAKALLOC_H #include "rtech/ipakfile.h" -extern void Pak_AlignSegmentHeaders(PakFile_t* const pak, PakSegmentDescriptor_t* const desc); -extern void Pak_AlignSegments(PakFile_t* const pak, PakSegmentDescriptor_t* const desc); -extern void Pak_CopyPagesToSegments(PakFile_t* const pak, PakLoadedInfo_t* const loadedInfo, PakSegmentDescriptor_t* const desc); +extern void Pak_AlignSegmentHeaders(PakFile_s* const pak, PakSegmentDescriptor_s* const desc); +extern void Pak_AlignSegments(PakFile_s* const pak, PakSegmentDescriptor_s* const desc); +extern void Pak_CopyPagesToSegments(PakFile_s* const pak, PakLoadedInfo_s* const loadedInfo, PakSegmentDescriptor_s* const desc); // something with sorting pages? -inline void (*sub_140442740)(PakAsset_t** assetEntries, PakAsset_t** assetEntry, __int64 idx, PakFile_t* pak); +inline void (*sub_140442740)(PakAsset_s** assetEntries, PakAsset_s** assetEntry, __int64 idx, PakFile_s* pak); /////////////////////////////////////////////////////////////////////////////// class V_PakAlloc : public IDetour diff --git a/r5dev/rtech/pak/pakdecode.cpp b/r5dev/rtech/pak/pakdecode.cpp index cbbf229c..936e6893 100644 --- a/r5dev/rtech/pak/pakdecode.cpp +++ b/r5dev/rtech/pak/pakdecode.cpp @@ -135,7 +135,7 @@ static const unsigned char /*141313180*/ s_defaultDecoderLUT[] = //----------------------------------------------------------------------------- // checks if we have enough output buffer room to decode the data stream //----------------------------------------------------------------------------- -bool Pak_HasEnoughDecodeBufferAvailable(PakDecoder_t* const decoder, const size_t outLen) +bool Pak_HasEnoughDecodeBufferAvailable(PakDecoder_s* const decoder, const size_t outLen) { // make sure caller has copied all data out the ring buffer first before // overwriting it with new decoded data @@ -146,7 +146,7 @@ bool Pak_HasEnoughDecodeBufferAvailable(PakDecoder_t* const decoder, const size_ //----------------------------------------------------------------------------- // checks if we have enough source data streamed to decode the next block //----------------------------------------------------------------------------- -bool Pak_HasEnoughStreamedDataForDecode(PakDecoder_t* const decoder, const size_t inLen) +bool Pak_HasEnoughStreamedDataForDecode(PakDecoder_s* const decoder, const size_t inLen) { // the decoder needs at least this amount of input data streamed in order // to decode the rest of the pak file, as this is where reading has stopped @@ -160,9 +160,9 @@ bool Pak_HasEnoughStreamedDataForDecode(PakDecoder_t* const decoder, const size_ // gets the frame for the data in the ring buffer, the frame returned is always // ending to the end of the ring buffer, or the end of the data itself //----------------------------------------------------------------------------- -PakRingBufferFrame_t Pak_DetermineRingBufferFrame(const uint64_t bufMask, const size_t seekPos, const size_t dataLen) +PakRingBufferFrame_s Pak_DetermineRingBufferFrame(const uint64_t bufMask, const size_t seekPos, const size_t dataLen) { - PakRingBufferFrame_t ring; + PakRingBufferFrame_s ring; ring.bufIndex = seekPos & bufMask; // the total amount of bytes used and available in this frame @@ -178,7 +178,7 @@ PakRingBufferFrame_t Pak_DetermineRingBufferFrame(const uint64_t bufMask, const //----------------------------------------------------------------------------- // initializes the RTech decoder //----------------------------------------------------------------------------- -size_t Pak_RTechDecoderInit(PakDecoder_t* const decoder, const uint8_t* const fileBuffer, +size_t Pak_RTechDecoderInit(PakDecoder_s* const decoder, const uint8_t* const fileBuffer, const uint64_t inputMask, const size_t dataSize, const size_t dataOffset, const size_t headerSize) { uint64_t frameHeader = *(_QWORD*)((inputMask & (dataOffset + headerSize)) + fileBuffer); @@ -243,7 +243,7 @@ size_t Pak_RTechDecoderInit(PakDecoder_t* const decoder, const uint8_t* const fi //----------------------------------------------------------------------------- // decodes the RTech data stream up to available buffer or data //----------------------------------------------------------------------------- -bool Pak_RTechStreamDecode(PakDecoder_t* const decoder, const size_t inLen, const size_t outLen) +bool Pak_RTechStreamDecode(PakDecoder_s* const decoder, const size_t inLen, const size_t outLen) { bool result; // al uint64_t outBufBytePos; // r15 @@ -570,7 +570,7 @@ LABEL_69: //----------------------------------------------------------------------------- // initializes the ZStd decoder //----------------------------------------------------------------------------- -size_t Pak_ZStdDecoderInit(PakDecoder_t* const decoder, const uint8_t* frameHeader, +size_t Pak_ZStdDecoderInit(PakDecoder_s* const decoder, const uint8_t* frameHeader, const size_t dataSize, const size_t headerSize) { ZSTD_DStream* const dctx = ZSTD_createDStream(); @@ -608,7 +608,7 @@ size_t Pak_ZStdDecoderInit(PakDecoder_t* const decoder, const uint8_t* frameHead // decodes the ZStd data stream up to available buffer or data, whichever ends // first //----------------------------------------------------------------------------- -bool Pak_ZStdStreamDecode(PakDecoder_t* const decoder, const PakRingBufferFrame_t& outFrame, const PakRingBufferFrame_t& inFrame) +bool Pak_ZStdStreamDecode(PakDecoder_s* const decoder, const PakRingBufferFrame_s& outFrame, const PakRingBufferFrame_s& inFrame) { ZSTD_outBuffer outBuffer = { &decoder->outputBuf[outFrame.bufIndex], @@ -663,9 +663,9 @@ bool Pak_ZStdStreamDecode(PakDecoder_t* const decoder, const PakRingBufferFrame_ //----------------------------------------------------------------------------- // initializes the decoder //----------------------------------------------------------------------------- -size_t Pak_InitDecoder(PakDecoder_t* const decoder, const uint8_t* const inputBuf, uint8_t* const outputBuf, +size_t Pak_InitDecoder(PakDecoder_s* const decoder, const uint8_t* const inputBuf, uint8_t* const outputBuf, const uint64_t inputMask, const uint64_t outputMask, const size_t dataSize, const size_t dataOffset, - const size_t headerSize, const EPakDecodeMode decodeMode) + const size_t headerSize, const PakDecodeMode_e decodeMode) { // buffer size must be power of two as we index into buffers using a bit // mask rather than a modulo, the mask provided must be bufferSize-1 @@ -696,7 +696,7 @@ size_t Pak_InitDecoder(PakDecoder_t* const decoder, const uint8_t* const inputBu // if we use the default RTech decoder, return from here as the stuff below // is handled by the RTech decoder internally - if (decodeMode == EPakDecodeMode::MODE_RTECH) + if (decodeMode == PakDecodeMode_e::MODE_RTECH) return Pak_RTechDecoderInit(decoder, inputBuf, inputMask, dataSize, dataOffset, headerSize); // NOTE: on RTech encoded paks this data is parsed out of the frame header, @@ -721,7 +721,7 @@ size_t Pak_InitDecoder(PakDecoder_t* const decoder, const uint8_t* const inputBu // from where the base pak had ended as patch pak files are considered part of // the pak file that's currently getting loaded //----------------------------------------------------------------------------- -bool Pak_StreamToBufferDecode(PakDecoder_t* const decoder, const size_t inLen, const size_t outLen, const EPakDecodeMode decodeMode) +bool Pak_StreamToBufferDecode(PakDecoder_s* const decoder, const size_t inLen, const size_t outLen, const PakDecodeMode_e decodeMode) { if (!Pak_HasEnoughStreamedDataForDecode(decoder, inLen)) return false; @@ -729,7 +729,7 @@ bool Pak_StreamToBufferDecode(PakDecoder_t* const decoder, const size_t inLen, c if (!Pak_HasEnoughDecodeBufferAvailable(decoder, outLen)) return false; - if (decodeMode == EPakDecodeMode::MODE_RTECH) + if (decodeMode == PakDecodeMode_e::MODE_RTECH) return Pak_RTechStreamDecode(decoder, inLen, outLen); // must have a decoder at this point @@ -739,8 +739,8 @@ bool Pak_StreamToBufferDecode(PakDecoder_t* const decoder, const size_t inLen, c // this position in code assert(decoder->zstreamContext && decoder->inBufBytePos <= inLen); - const PakRingBufferFrame_t outFrame = Pak_DetermineRingBufferFrame(decoder->outputMask, decoder->outBufBytePos , outLen); - const PakRingBufferFrame_t inFrame = Pak_DetermineRingBufferFrame(decoder->inputMask, decoder->inBufBytePos, inLen); + const PakRingBufferFrame_s outFrame = Pak_DetermineRingBufferFrame(decoder->outputMask, decoder->outBufBytePos , outLen); + const PakRingBufferFrame_s inFrame = Pak_DetermineRingBufferFrame(decoder->inputMask, decoder->inBufBytePos, inLen); return Pak_ZStdStreamDecode(decoder, outFrame, inFrame); } @@ -748,14 +748,14 @@ bool Pak_StreamToBufferDecode(PakDecoder_t* const decoder, const size_t inLen, c //----------------------------------------------------------------------------- // decodes buffered input pak data //----------------------------------------------------------------------------- -bool Pak_BufferToBufferDecode(uint8_t* const inBuf, uint8_t* const outBuf, const size_t pakSize, const EPakDecodeMode decodeMode) +bool Pak_BufferToBufferDecode(uint8_t* const inBuf, uint8_t* const outBuf, const size_t pakSize, const PakDecodeMode_e decodeMode) { - assert(decodeMode != EPakDecodeMode::MODE_DISABLED); + assert(decodeMode != PakDecodeMode_e::MODE_DISABLED); - PakDecoder_t decoder{}; - const size_t decompressedSize = Pak_InitDecoder(&decoder, inBuf, outBuf, UINT64_MAX, UINT64_MAX, pakSize, NULL, sizeof(PakFileHeader_t), decodeMode); + PakDecoder_s decoder{}; + const size_t decompressedSize = Pak_InitDecoder(&decoder, inBuf, outBuf, UINT64_MAX, UINT64_MAX, pakSize, NULL, sizeof(PakFileHeader_s), decodeMode); - PakFileHeader_t* const inHeader = reinterpret_cast(inBuf); + PakFileHeader_s* const inHeader = reinterpret_cast(inBuf); if (decompressedSize != inHeader->decompressedSize) { @@ -774,7 +774,7 @@ bool Pak_BufferToBufferDecode(uint8_t* const inBuf, uint8_t* const outBuf, const return false; } - PakFileHeader_t* const outHeader = reinterpret_cast(outBuf); + PakFileHeader_s* const outHeader = reinterpret_cast(outBuf); // copy the header over to the decoded buffer *outHeader = *inHeader; @@ -826,7 +826,7 @@ bool Pak_DecodePakFile(const char* const inPakFile, const char* const outPakFile const size_t fileSize = inPakStream.GetSize(); - if (fileSize <= sizeof(PakFileHeader_t)) + if (fileSize <= sizeof(PakFileHeader_s)) { Error(eDLL_T::RTECH, NO_ERROR, "%s: pak '%s' appears truncated!\n", __FUNCTION__, inPakFile); @@ -840,7 +840,7 @@ bool Pak_DecodePakFile(const char* const inPakFile, const char* const outPakFile inPakStream.Read(inPakBuf, fileSize); inPakStream.Close(); - PakFileHeader_t* const inHeader = reinterpret_cast(inPakBuf); + PakFileHeader_s* const inHeader = reinterpret_cast(inPakBuf); if (inHeader->magic != PAK_HEADER_MAGIC || inHeader->version != PAK_HEADER_VERSION) { @@ -850,9 +850,9 @@ bool Pak_DecodePakFile(const char* const inPakFile, const char* const outPakFile return false; } - const EPakDecodeMode decodeMode = inHeader->GetCompressionMode(); + const PakDecodeMode_e decodeMode = inHeader->GetCompressionMode(); - if (decodeMode == EPakDecodeMode::MODE_DISABLED) + if (decodeMode == PakDecodeMode_e::MODE_DISABLED) { Error(eDLL_T::RTECH, NO_ERROR, "%s: pak '%s' is already decompressed!\n", __FUNCTION__, inPakFile); @@ -881,7 +881,7 @@ bool Pak_DecodePakFile(const char* const inPakFile, const char* const outPakFile return false; } - const PakFileHeader_t* const outHeader = reinterpret_cast(outPakBuf); + const PakFileHeader_s* const outHeader = reinterpret_cast(outPakBuf); // NOTE: if the paks this particular pak patches have different sizes than // current sizes in the patch header, the runtime will crash! diff --git a/r5dev/rtech/pak/pakdecode.h b/r5dev/rtech/pak/pakdecode.h index 2008b012..40e6782b 100644 --- a/r5dev/rtech/pak/pakdecode.h +++ b/r5dev/rtech/pak/pakdecode.h @@ -2,12 +2,12 @@ #define RTECH_PAKDECODE_H #include "rtech/ipakfile.h" -extern size_t Pak_InitDecoder(PakDecoder_t* const decoder, const uint8_t* const inputBuf, uint8_t* const outputBuf, +extern size_t Pak_InitDecoder(PakDecoder_s* const decoder, const uint8_t* const inputBuf, uint8_t* const outputBuf, const uint64_t inputMask, const uint64_t outputMask, const size_t dataSize, const size_t dataOffset, - const size_t headerSize, const EPakDecodeMode decodeMode); + const size_t headerSize, const PakDecodeMode_e decodeMode); -extern bool Pak_StreamToBufferDecode(PakDecoder_t* const decoder, const size_t inLen, const size_t outLen, const EPakDecodeMode decodeMode); -extern bool Pak_BufferToBufferDecode(uint8_t* const inBuf, uint8_t* const outBuf, const size_t pakSize, const EPakDecodeMode decodeMode); +extern bool Pak_StreamToBufferDecode(PakDecoder_s* const decoder, const size_t inLen, const size_t outLen, const PakDecodeMode_e decodeMode); +extern bool Pak_BufferToBufferDecode(uint8_t* const inBuf, uint8_t* const outBuf, const size_t pakSize, const PakDecodeMode_e decodeMode); extern bool Pak_DecodePakFile(const char* const inPakFile, const char* const outPakFile); diff --git a/r5dev/rtech/pak/pakencode.cpp b/r5dev/rtech/pak/pakencode.cpp index 99df0017..8f9fb70c 100644 --- a/r5dev/rtech/pak/pakencode.cpp +++ b/r5dev/rtech/pak/pakencode.cpp @@ -35,7 +35,7 @@ bool Pak_BufferToBufferEncode(const uint8_t* const inBuf, const uint64_t inLen, { // offset to the actual pak data, the main file header shouldn't be // compressed - const size_t dataOffset = sizeof(PakFileHeader_t); + const size_t dataOffset = sizeof(PakFileHeader_s); uint8_t* const dstBuf = outBuf + dataOffset; const size_t dstLen = outLen - dataOffset; @@ -55,7 +55,7 @@ bool Pak_BufferToBufferEncode(const uint8_t* const inBuf, const uint64_t inLen, return false; } - PakFileHeader_t* const outHeader = reinterpret_cast(outBuf); + PakFileHeader_s* const outHeader = reinterpret_cast(outBuf); // the compressed size includes the entire buffer, even the data we didn't // compress like the file header @@ -105,7 +105,7 @@ bool Pak_EncodePakFile(const char* const inPakFile, const char* const outPakFile const size_t fileSize = inPakStream.GetSize(); // file appears truncated - if (fileSize <= sizeof(PakFileHeader_t)) + if (fileSize <= sizeof(PakFileHeader_s)) { Error(eDLL_T::RTECH, NO_ERROR, "%s: pak '%s' appears truncated!\n", __FUNCTION__, inPakFile); @@ -119,7 +119,7 @@ bool Pak_EncodePakFile(const char* const inPakFile, const char* const outPakFile inPakStream.Read(inPakBuf, fileSize); inPakStream.Close(); - const PakFileHeader_t* const inHeader = reinterpret_cast(inPakBuf); + const PakFileHeader_s* const inHeader = reinterpret_cast(inPakBuf); if (inHeader->magic != PAK_HEADER_MAGIC || inHeader->version != PAK_HEADER_VERSION) { @@ -129,7 +129,7 @@ bool Pak_EncodePakFile(const char* const inPakFile, const char* const outPakFile return false; } - if (inHeader->GetCompressionMode() != EPakDecodeMode::MODE_DISABLED) + if (inHeader->GetCompressionMode() != PakDecodeMode_e::MODE_DISABLED) { Error(eDLL_T::RTECH, NO_ERROR, "%s: pak '%s' is already compressed!\n", __FUNCTION__, inPakFile); @@ -158,7 +158,7 @@ bool Pak_EncodePakFile(const char* const inPakFile, const char* const outPakFile std::unique_ptr outPakBufContainer(new uint8_t[outBufSize]); uint8_t* const outPakBuf = outPakBufContainer.get(); - PakFileHeader_t* const outHeader = reinterpret_cast(outPakBuf); + PakFileHeader_s* const outHeader = reinterpret_cast(outPakBuf); // copy the header over *outHeader = *inHeader; @@ -172,7 +172,7 @@ bool Pak_EncodePakFile(const char* const inPakFile, const char* const outPakFile return false; } - const PakFileHeader_t* const outPakHeader = reinterpret_cast(outPakBuf); + const PakFileHeader_s* const outPakHeader = reinterpret_cast(outPakBuf); Pak_ShowHeaderDetails(outPakHeader); diff --git a/r5dev/rtech/pak/pakparse.cpp b/r5dev/rtech/pak/pakparse.cpp index 6caef4e3..b95bebeb 100644 --- a/r5dev/rtech/pak/pakparse.cpp +++ b/r5dev/rtech/pak/pakparse.cpp @@ -19,7 +19,7 @@ static ConVar pak_debugrelations("pak_debugrelations", "0", FCVAR_DEVELOPMENTONL //----------------------------------------------------------------------------- // resolve the target guid from lookuo table //----------------------------------------------------------------------------- -static bool Pak_ResolveAssetDependency(const PakFile_t* const pak, PakGuid_t currentGuid, +static bool Pak_ResolveAssetDependency(const PakFile_s* const pak, PakGuid_t currentGuid, const PakGuid_t targetGuid, int& currentIndex, const bool shouldCheckTwo) { while (true) @@ -48,9 +48,9 @@ static bool Pak_ResolveAssetDependency(const PakFile_t* const pak, PakGuid_t cur //----------------------------------------------------------------------------- // resolve guid relations for asset //----------------------------------------------------------------------------- -void Pak_ResolveAssetRelations(PakFile_t* const pak, const PakAsset_t* const asset) +void Pak_ResolveAssetRelations(PakFile_s* const pak, const PakAsset_s* const asset) { - PakPage_t* const pGuidDescriptors = &pak->memoryData.guidDescriptors[asset->dependenciesIndex]; + PakPage_u* const pGuidDescriptors = &pak->memoryData.guidDescriptors[asset->dependenciesIndex]; uint32_t* const v5 = (uint32_t*)g_pakGlobals->loadedPaks[pak->memoryData.pakId & PAK_MAX_LOADED_PAKS_MASK].qword50; if (pak_debugrelations.GetBool()) @@ -77,7 +77,7 @@ void Pak_ResolveAssetRelations(PakFile_t* const pak, const PakAsset_t* const ass // are we some special asset with the guid 2? if (!Pak_ResolveAssetDependency(pak, currentGuid, targetGuid, currentIndex, true)) { - PakAsset_t* assetEntries = pak->memoryData.assetEntries; + PakAsset_s* assetEntries = pak->memoryData.assetEntries; uint64_t a = 0; for (; assetEntries->guid != targetGuid; a++, assetEntries++) @@ -111,13 +111,13 @@ void Pak_ResolveAssetRelations(PakFile_t* const pak, const PakAsset_t* const ass } } -uint32_t Pak_ProcessRemainingPagePointers(PakFile_t* const pak) +uint32_t Pak_ProcessRemainingPagePointers(PakFile_s* const pak) { uint32_t processedPointers = 0; for (processedPointers = pak->numProcessedPointers; processedPointers < pak->GetPointerCount(); ++processedPointers) { - PakPage_t* const curPage = &pak->memoryData.virtualPointers[processedPointers]; + PakPage_u* const curPage = &pak->memoryData.virtualPointers[processedPointers]; int curCount = curPage->index - pak->firstPageIdx; if (curCount < 0) @@ -126,14 +126,14 @@ uint32_t Pak_ProcessRemainingPagePointers(PakFile_t* const pak) if (curCount >= pak->processedPageCount) break; - PakPage_t* const ptr = reinterpret_cast(pak->GetPointerForPageOffset(curPage)); + PakPage_u* const ptr = reinterpret_cast(pak->GetPointerForPageOffset(curPage)); ptr->ptr = pak->memoryData.memPageBuffers[ptr->index] + ptr->offset; } return processedPointers; } -void Pak_RunAssetLoadingJobs(PakFile_t* const pak) +void Pak_RunAssetLoadingJobs(PakFile_s* const pak) { pak->numProcessedPointers = Pak_ProcessRemainingPagePointers(pak); @@ -142,7 +142,7 @@ void Pak_RunAssetLoadingJobs(PakFile_t* const pak) if (numAssets == pak->memoryData.pakHeader.assetCount) return; - PakAsset_t* pakAsset = &pak->memoryData.assetEntries[numAssets]; + PakAsset_s* pakAsset = &pak->memoryData.assetEntries[numAssets]; if (pakAsset->pageEnd > pak->processedPageCount) return; @@ -215,7 +215,7 @@ PakHandle_t Pak_LoadAsync(const char* const fileName, CAlignedMemAlloc* const al //----------------------------------------------------------------------------- void Pak_UnloadAsync(PakHandle_t handle) { - const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(handle); + const PakLoadedInfo_s* const pakInfo = Pak_GetPakInfo(handle); if (pakInfo->fileName) Msg(eDLL_T::RTECH, "Unloading pak file: '%s'\n", pakInfo->fileName); @@ -232,13 +232,13 @@ static const int s_patchCmdToBytesToProcess[] = { CMD_INVALID, CMD_INVALID, CMD_ // loads and processes a pak file (handles decompression and patching) // TODO: !!! FINISH REBUILD !!! //---------------------------------------------------------------------------------- -bool Pak_ProcessPakFile(PakFile_t* const pak) +bool Pak_ProcessPakFile(PakFile_s* const pak) { - PakFileStream_t* const fileStream = &pak->fileStream; - PakMemoryData_t* const memoryData = &pak->memoryData; + PakFileStream_s* const fileStream = &pak->fileStream; + PakMemoryData_s* const memoryData = &pak->memoryData; // first request is always just the header? - size_t readStart = sizeof(PakFileHeader_t); + size_t readStart = sizeof(PakFileHeader_s); if (fileStream->numDataChunks > 0) readStart = fileStream->numDataChunks * PAK_READ_DATA_CHUNK_SIZE; @@ -261,19 +261,19 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) fileStream->bytesStreamed += bytesProcessed; if (v8) { - const PakFileHeader_t* pakHeader = &pak->memoryData.pakHeader; + const PakFileHeader_s* pakHeader = &pak->memoryData.pakHeader; const uint64_t v16 = fileStream->numDataChunksProcessed * PAK_READ_DATA_CHUNK_SIZE; if (v8 == 2) { fileStream->bytesStreamed = bytesProcessed + v16; - pakHeader = (PakFileHeader_t*)&fileStream->buffer[v16 & fileStream->bufferMask]; + pakHeader = (PakFileHeader_s*)&fileStream->buffer[v16 & fileStream->bufferMask]; } const uint8_t fileIndex = fileStream->numLoadedFiles++ & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK; //printf("v16: %lld\n", v16); - fileStream->descriptors[fileIndex].dataOffset = v16 + sizeof(PakFileHeader_t); + fileStream->descriptors[fileIndex].dataOffset = v16 + sizeof(PakFileHeader_s); fileStream->descriptors[fileIndex].compressedSize = v16 + pakHeader->compressedSize; fileStream->descriptors[fileIndex].decompressedSize = pakHeader->decompressedSize; fileStream->descriptors[fileIndex].compressionMode = pakHeader->GetCompressionMode(); @@ -285,18 +285,18 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) for (; pak->byte1F8 != fileStream->numLoadedFiles; pak->byte1F8++) { - PakFileStream_t::Descriptor* v22 = &fileStream->descriptors[pak->byte1F8 & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK]; + PakFileStream_s::Descriptor* v22 = &fileStream->descriptors[pak->byte1F8 & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK]; if (pak->byte1FD) { pak->byte1FD = false; pak->inputBytePos = v22->dataOffset; - if (v22->compressionMode != EPakDecodeMode::MODE_DISABLED) + if (v22->compressionMode != PakDecodeMode_e::MODE_DISABLED) { pak->isOffsetted_MAYBE = false; pak->isCompressed = true; - memoryData->processedPatchedDataSize = sizeof(PakFileHeader_t); + memoryData->processedPatchedDataSize = sizeof(PakFileHeader_s); } else { @@ -311,8 +311,8 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) const size_t decompressedSize = Pak_InitDecoder(&pak->pakDecoder, fileStream->buffer, pak->decompBuffer, PAK_DECODE_IN_RING_BUFFER_MASK, PAK_DECODE_OUT_RING_BUFFER_MASK, - v22->compressedSize - (v22->dataOffset - sizeof(PakFileHeader_t)), - v22->dataOffset - sizeof(PakFileHeader_t), sizeof(PakFileHeader_t), v22->compressionMode); + v22->compressedSize - (v22->dataOffset - sizeof(PakFileHeader_s)), + v22->dataOffset - sizeof(PakFileHeader_s), sizeof(PakFileHeader_s), v22->compressionMode); if (decompressedSize != v22->decompressedSize) Error(eDLL_T::RTECH, EXIT_FAILURE, @@ -520,7 +520,7 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) // sets patch variables for copying the next unprocessed page into the relevant segment buffer // if this is a header page, fetch info from the next unprocessed asset and copy over the asset's header -bool SetupNextPageForPatching(PakLoadedInfo_t* a1, PakFile_t* pak) +bool SetupNextPageForPatching(PakLoadedInfo_s* a1, PakFile_s* pak) { Pak_RunAssetLoadingJobs(pak); @@ -538,7 +538,7 @@ bool SetupNextPageForPatching(PakLoadedInfo_t* a1, PakFile_t* pak) if (highestProcessedPageIdx < pak->GetPageCount()) v26 = highestProcessedPageIdx; - const PakPageHeader_t* const nextMemPageHeader = &pak->memoryData.pageHeaders[v26]; + const PakPageHeader_s* const nextMemPageHeader = &pak->memoryData.pageHeaders[v26]; if ((pak->memoryData.segmentHeaders[nextMemPageHeader->segmentIdx].typeFlags & (SF_TEMP | SF_CPU)) != 0) { pak->memoryData.patchSrcSize = nextMemPageHeader->dataSize; @@ -549,7 +549,7 @@ bool SetupNextPageForPatching(PakLoadedInfo_t* a1, PakFile_t* pak) } // headers - PakAsset_t* pakAsset = pak->memoryData.ppAssetEntries[pak->memoryData.someAssetCount]; + PakAsset_s* pakAsset = pak->memoryData.ppAssetEntries[pak->memoryData.someAssetCount]; pak->memoryData.patchSrcSize = pakAsset->headerSize; int assetTypeIdx = pakAsset->HashTableIndexForAssetType(); @@ -560,9 +560,9 @@ bool SetupNextPageForPatching(PakLoadedInfo_t* a1, PakFile_t* pak) return true; } -bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) +bool Pak_ProcessAssets(PakLoadedInfo_s* const a1) { - PakFile_t* const pak = a1->pakFile; + PakFile_s* const pak = a1->pakFile; while (pak->processedAssetCount != pak->GetAssetCount()) { // TODO: invert condition and make the branch encompass the whole loop @@ -603,7 +603,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) break; } - PakAsset_t* asset = pak->memoryData.ppAssetEntries[pak->memoryData.someAssetCount]; + PakAsset_s* asset = pak->memoryData.ppAssetEntries[pak->memoryData.someAssetCount]; const uint32_t headPageOffset = asset->headPtr.offset; char* v8 = pak->memoryData.patchDstPtr - asset->headerSize; @@ -616,7 +616,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) for (uint32_t i = pak->memoryData.numShiftedPointers; i < pak->GetPointerCount(); pak->memoryData.numShiftedPointers = i) { - PakPage_t* ptr = &pak->memoryData.virtualPointers[i]; + PakPage_u* ptr = &pak->memoryData.virtualPointers[i]; ASSERT_PAKPTR_VALID(pak, ptr); @@ -627,7 +627,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) if (offsetToPointer >= asset->headerSize) break; - PakPage_t* pagePtr = reinterpret_cast(v8 + offsetToPointer); + PakPage_u* pagePtr = reinterpret_cast(v8 + offsetToPointer); ASSERT_PAKPTR_VALID(pak, ptr); @@ -641,7 +641,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) for (uint32_t j = 0; j < asset->dependenciesCount; ++j) { - PakPage_t* descriptor = &pak->memoryData.guidDescriptors[asset->dependenciesIndex + j]; + PakPage_u* descriptor = &pak->memoryData.guidDescriptors[asset->dependenciesIndex + j]; if (descriptor->index == shiftedPageIndex) descriptor->offset += offsetSize; @@ -649,7 +649,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) const uint32_t v16 = ++pak->memoryData.someAssetCount; - PakAsset_t* v17 = nullptr; + PakAsset_s* v17 = nullptr; if (v16 < pak->GetAssetCount() && (v17 = pak->memoryData.ppAssetEntries[v16], v17->headPtr.index == shiftedPageIndex)) { pak->memoryData.field_2A8 = v17->headPtr.offset - headPageOffset - asset->headerSize; @@ -675,7 +675,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) return false; uint32_t i = 0; - PakAsset_t* pAsset = nullptr; + PakAsset_s* pAsset = nullptr; for (int j = pak->memoryData.pakId & PAK_MAX_LOADED_PAKS_MASK; i < pak->GetHeader().assetCount; a1->assetGuids[i - 1] = pAsset->guid) { @@ -686,7 +686,7 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) Pak_ResolveAssetRelations(pak, pAsset); const int assetIndex = pak->memoryData.loadedAssetIndices[i]; - const PakAssetShort_t& loadedAsset = g_pakGlobals->loadedAssets[assetIndex]; + const PakAssetShort_s& loadedAsset = g_pakGlobals->loadedAssets[assetIndex]; if (g_pakGlobals->trackedAssets[loadedAsset.trackerIndex].loadedPakIndex == j) { @@ -733,24 +733,24 @@ bool Pak_ProcessAssets(PakLoadedInfo_t* const a1) if (g_pakGlobals->pakTracker) sub_14043D870(a1, 0); - a1->status = EPakStatus::PAK_STATUS_LOADED; + a1->status = PakStatus_e::PAK_STATUS_LOADED; return true; } -void Pak_StubInvalidAssetBinds(PakFile_t* const pak, PakSegmentDescriptor_t* const desc) +void Pak_StubInvalidAssetBinds(PakFile_s* const pak, PakSegmentDescriptor_s* const desc) { for (uint32_t i = 0; i < pak->GetAssetCount(); ++i) { - PakAsset_t* const asset = &pak->memoryData.assetEntries[i]; + PakAsset_s* const asset = &pak->memoryData.assetEntries[i]; pak->memoryData.ppAssetEntries[i] = asset; const uint8_t assetTypeIndex = asset->HashTableIndexForAssetType(); desc->assetTypeCount[assetTypeIndex]++; - PakAssetBinding_t* const assetBinding = &g_pakGlobals->assetBindings[assetTypeIndex]; + PakAssetBinding_s* const assetBinding = &g_pakGlobals->assetBindings[assetTypeIndex]; - if (assetBinding->type == PakAssetBinding_t::NONE) + if (assetBinding->type == PakAssetBinding_s::NONE) { assetBinding->extension = asset->magic; assetBinding->version = asset->version; @@ -762,7 +762,7 @@ void Pak_StubInvalidAssetBinds(PakFile_t* const pak, PakSegmentDescriptor_t* con assetBinding->headerSize = asset->headerSize; assetBinding->nativeClassSize = asset->headerSize; assetBinding->headerAlignment = pak->memoryData.pageHeaders[asset->headPtr.index].pageAlignment; - assetBinding->type = PakAssetBinding_t::STUB; + assetBinding->type = PakAssetBinding_s::STUB; } // this is dev only because it could spam a lot on older paks @@ -784,14 +784,14 @@ void Pak_StubInvalidAssetBinds(PakFile_t* const pak, PakSegmentDescriptor_t* con } } -bool Pak_StartLoadingPak(PakLoadedInfo_t* const loadedInfo) +bool Pak_StartLoadingPak(PakLoadedInfo_s* const loadedInfo) { - PakFile_t* const pakFile = loadedInfo->pakFile; + PakFile_s* const pakFile = loadedInfo->pakFile; if (pakFile->memoryData.patchSrcSize && !Pak_ProcessPakFile(pakFile)) return false; - PakSegmentDescriptor_t pakDescriptor = {}; + PakSegmentDescriptor_s pakDescriptor = {}; Pak_StubInvalidAssetBinds(pakFile, &pakDescriptor); @@ -823,7 +823,7 @@ bool Pak_StartLoadingPak(PakLoadedInfo_t* const loadedInfo) Pak_CopyPagesToSegments(pakFile, loadedInfo, &pakDescriptor); - const PakFileHeader_t& pakHdr = pakFile->GetHeader(); + const PakFileHeader_s& pakHdr = pakFile->GetHeader(); if (Pak_StreamingEnabled()) Pak_LoadStreamingData(loadedInfo); @@ -833,12 +833,12 @@ bool Pak_StartLoadingPak(PakLoadedInfo_t* const loadedInfo) pakFile->dword14 = 1; - PakMemoryData_t& memoryData = pakFile->memoryData; + PakMemoryData_s& memoryData = pakFile->memoryData; memoryData.patchSrcSize = pakFile->memoryData.qword2D0 - patchDestOffset; memoryData.patchDstPtr = (char*)&pakHdr + patchDestOffset; - loadedInfo->status = EPakStatus::PAK_STATUS_LOAD_PAKHDR; + loadedInfo->status = PakStatus_e::PAK_STATUS_LOAD_PAKHDR; return true; } diff --git a/r5dev/rtech/pak/pakparse.h b/r5dev/rtech/pak/pakparse.h index 30a176fe..dc05407c 100644 --- a/r5dev/rtech/pak/pakparse.h +++ b/r5dev/rtech/pak/pakparse.h @@ -11,22 +11,22 @@ inline PakHandle_t(*v_Pak_Initialize)(int mode); inline PakHandle_t(*v_Pak_LoadAsync)(const char* fileName, CAlignedMemAlloc* allocator, int nIdx, bool bUnk); -inline EPakStatus(*v_Pak_WaitAsync)(PakHandle_t handle, void* finishCallback); +inline PakStatus_e(*v_Pak_WaitAsync)(PakHandle_t handle, void* finishCallback); inline void(*v_Pak_UnloadAsync)(PakHandle_t handle); inline void(*v_Pak_RegisterAsset)(int, int, const char*, void*, void*, void*, void*, int, int, uint32_t, int, int); -inline bool(*v_Pak_StartLoadingPak)(PakLoadedInfo_t* loadedInfo); -inline bool(*v_Pak_ProcessPakFile)(PakFile_t* const pak); -inline bool(*v_Pak_ProcessAssets)(PakLoadedInfo_t* pakInfo); -inline void(*v_Pak_ResolveAssetRelations)(PakFile_t* const pak, const PakAsset_t* const asset); +inline bool(*v_Pak_StartLoadingPak)(PakLoadedInfo_s* loadedInfo); +inline bool(*v_Pak_ProcessPakFile)(PakFile_s* const pak); +inline bool(*v_Pak_ProcessAssets)(PakLoadedInfo_s* pakInfo); +inline void(*v_Pak_ResolveAssetRelations)(PakFile_s* const pak, const PakAsset_s* const asset); -inline void (*v_Pak_RunAssetLoadingJobs)(PakFile_t* pak); -inline void (*Pak_ProcessAssetRelationsAndResolveDependencies)(PakFile_t* pak_arg, PakAsset_t* asset_arg, unsigned int asset_idx_arg, unsigned int a4); +inline void (*v_Pak_RunAssetLoadingJobs)(PakFile_s* pak); +inline void (*Pak_ProcessAssetRelationsAndResolveDependencies)(PakFile_s* pak_arg, PakAsset_s* asset_arg, unsigned int asset_idx_arg, unsigned int a4); -inline int (*Pak_TrackAsset)(PakFile_t* const a1, PakAsset_t* a2); +inline int (*Pak_TrackAsset)(PakFile_s* const a1, PakAsset_s* a2); // TODO: name these! -inline void (*sub_14043D870)(PakLoadedInfo_t* a1, int a2); +inline void (*sub_14043D870)(PakLoadedInfo_s* a1, int a2); /////////////////////////////////////////////////////////////////////////////// class V_PakParse : public IDetour diff --git a/r5dev/rtech/pak/pakpatch.cpp b/r5dev/rtech/pak/pakpatch.cpp index 75075a14..55259520 100644 --- a/r5dev/rtech/pak/pakpatch.cpp +++ b/r5dev/rtech/pak/pakpatch.cpp @@ -6,7 +6,7 @@ #include "rtech/ipakfile.h" #include "pakpatch.h" -bool PATCH_CMD_0(PakFile_t* const pak, size_t* const numAvailableBytes) +bool PATCH_CMD_0(PakFile_s* const pak, size_t* const numAvailableBytes) { unsigned __int64 m_numBytesToProcess_maybe; // r9 unsigned __int64 v4; // rdi @@ -83,7 +83,7 @@ bool PATCH_CMD_0(PakFile_t* const pak, size_t* const numAvailableBytes) return pak->memoryData.numBytesToProcess_maybe == 0; } -bool PATCH_CMD_1(PakFile_t* const pak, size_t* const numAvailableBytes) +bool PATCH_CMD_1(PakFile_s* const pak, size_t* const numAvailableBytes) { unsigned __int64 m_numBytesToProcess_maybe; // r8 size_t v3; // r9 @@ -111,7 +111,7 @@ bool PATCH_CMD_1(PakFile_t* const pak, size_t* const numAvailableBytes) } } -bool PATCH_CMD_2(PakFile_t* const pak, size_t* const numAvailableBytes) +bool PATCH_CMD_2(PakFile_s* const pak, size_t* const numAvailableBytes) { NOTE_UNUSED(numAvailableBytes); @@ -153,7 +153,7 @@ bool PATCH_CMD_2(PakFile_t* const pak, size_t* const numAvailableBytes) return pak->memoryData.numBytesToProcess_maybe == 0; } -bool PATCH_CMD_3(PakFile_t* const pak, size_t* const numAvailableBytes) +bool PATCH_CMD_3(PakFile_s* const pak, size_t* const numAvailableBytes) { size_t patchSrcSize = pak->memoryData.patchSrcSize; @@ -172,7 +172,7 @@ bool PATCH_CMD_3(PakFile_t* const pak, size_t* const numAvailableBytes) return pak->memoryData.numBytesToProcess_maybe == 0; } -bool PATCH_CMD_4_5(PakFile_t* const pak, size_t* const numAvailableBytes) +bool PATCH_CMD_4_5(PakFile_s* const pak, size_t* const numAvailableBytes) { const size_t v2 = *numAvailableBytes; if (!v2) @@ -188,7 +188,7 @@ bool PATCH_CMD_4_5(PakFile_t* const pak, size_t* const numAvailableBytes) return PATCH_CMD_0(pak, numAvailableBytes); } -bool PATCH_CMD_6(PakFile_t* const pak, size_t* const numAvailableBytes) +bool PATCH_CMD_6(PakFile_s* const pak, size_t* const numAvailableBytes) { const size_t v2 = *numAvailableBytes; size_t v3 = 2; @@ -238,7 +238,7 @@ bool PATCH_CMD_6(PakFile_t* const pak, size_t* const numAvailableBytes) return false; } -const PakPatchFuncs_t g_pakPatchApi +const PakPatchFuncs_s g_pakPatchApi { PATCH_CMD_0, PATCH_CMD_1, diff --git a/r5dev/rtech/pak/pakpatch.h b/r5dev/rtech/pak/pakpatch.h index 287416f0..7b85f9b4 100644 --- a/r5dev/rtech/pak/pakpatch.h +++ b/r5dev/rtech/pak/pakpatch.h @@ -2,6 +2,6 @@ #define RTECH_PATCHAPI_H #include "rtech/ipakfile.h" -extern const PakPatchFuncs_t g_pakPatchApi; +extern const PakPatchFuncs_s g_pakPatchApi; #endif // RTECH_PATCHAPI_H diff --git a/r5dev/rtech/pak/pakstate.cpp b/r5dev/rtech/pak/pakstate.cpp index 927683b3..a79653c3 100644 --- a/r5dev/rtech/pak/pakstate.cpp +++ b/r5dev/rtech/pak/pakstate.cpp @@ -24,9 +24,9 @@ static void Pak_ListPaks_f() for (int16_t i = 0, n = g_pakGlobals->loadedPakCount; i < n; ++i) { - const PakLoadedInfo_t& info = g_pakGlobals->loadedPaks[i]; + const PakLoadedInfo_s& info = g_pakGlobals->loadedPaks[i]; - if (info.status == EPakStatus::PAK_STATUS_FREED) + if (info.status == PakStatus_e::PAK_STATUS_FREED) continue; const char* szRpakStatus = Pak_StatusToString(info.status); @@ -54,7 +54,7 @@ static void Pak_ListTypes_f() for (int8_t i = 0; i < PAK_MAX_TRACKED_TYPES; ++i) { - PakAssetBinding_t* type = &g_pakGlobals->assetBindings[i]; + PakAssetBinding_s* type = &g_pakGlobals->assetBindings[i]; if (!type->description) continue; @@ -85,7 +85,7 @@ static void Pak_RequestUnload_f(const CCommand& args) if (args.HasOnlyDigits(1)) { const PakHandle_t pakHandle = atoi(args.Arg(1)); - const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(pakHandle); + const PakLoadedInfo_s* const pakInfo = Pak_GetPakInfo(pakHandle); if (!pakInfo) { @@ -98,7 +98,7 @@ static void Pak_RequestUnload_f(const CCommand& args) } else { - const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(args.Arg(1)); + const PakLoadedInfo_s* const pakInfo = Pak_GetPakInfo(args.Arg(1)); if (!pakInfo) { Warning(eDLL_T::RTECH, "Found no pak entry for specified name.\n"); @@ -136,7 +136,7 @@ static void Pak_Swap_f(const CCommand& args) const char* pakName = nullptr; PakHandle_t pakHandle = PAK_INVALID_HANDLE; - const PakLoadedInfo_t* pakInfo = nullptr; + const PakLoadedInfo_s* pakInfo = nullptr; if (args.HasOnlyDigits(1)) { @@ -168,7 +168,7 @@ static void Pak_Swap_f(const CCommand& args) Msg(eDLL_T::RTECH, "Requested pak swap for handle '%d'\n", pakHandle); g_pakLoadApi->UnloadAsync(pakHandle); - while (pakInfo->status != EPakStatus::PAK_STATUS_FREED) // Wait till this slot gets free'd. + while (pakInfo->status != PakStatus_e::PAK_STATUS_FREED) // Wait till this slot gets free'd. std::this_thread::sleep_for(std::chrono::seconds(1)); g_pakLoadApi->LoadAsync(pakName, AlignedMemAlloc(), NULL, 0); diff --git a/r5dev/rtech/pak/pakstate.h b/r5dev/rtech/pak/pakstate.h index c2c08f28..09cc4e17 100644 --- a/r5dev/rtech/pak/pakstate.h +++ b/r5dev/rtech/pak/pakstate.h @@ -18,7 +18,7 @@ struct PakLoadFuncs_s char unknown2[16]; void* Func7; void* Func8; - EPakStatus(*WaitAsync)(PakHandle_t handle, void* finishCallback); + PakStatus_e(*WaitAsync)(PakHandle_t handle, void* finishCallback); void* Func10; void* Func11; void* FindByGUID; @@ -47,7 +47,7 @@ struct PakLoadFuncs_s void* Func33; }; -inline PakGlobals_s* g_pakGlobals; +inline PakGlobalState_s* g_pakGlobals; extern PakLoadFuncs_s* g_pakLoadApi; inline JobHelpCallback_t g_pPakFifoLockWrapper; // Pointer to functor that takes the global pak fifolock as argument. @@ -72,7 +72,7 @@ class V_PakState : public IDetour virtual void GetFun(void) const { } virtual void GetVar(void) const { - g_pakGlobals = g_GameDll.FindPatternSIMD("48 8D 1D ?? ?? ?? ?? 45 8D 5A 0E").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_pakGlobals = g_GameDll.FindPatternSIMD("48 8D 1D ?? ?? ?? ?? 45 8D 5A 0E").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); g_pakLoadApi = CMemory(v_LauncherMain).Offset(0x820).FindPatternSelf("48 89").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); const CMemory jtBase(JT_HelpWithAnything); diff --git a/r5dev/rtech/pak/pakstream.cpp b/r5dev/rtech/pak/pakstream.cpp index f530c722..b9f9e948 100644 --- a/r5dev/rtech/pak/pakstream.cpp +++ b/r5dev/rtech/pak/pakstream.cpp @@ -45,12 +45,12 @@ static bool Pak_OptionalStreamingDataDownloaded() //----------------------------------------------------------------------------- // opens all associated streaming assets for this pak //----------------------------------------------------------------------------- -void Pak_OpenAssociatedStreamingFiles(PakLoadedInfo_t* const loadedInfo, PakLoadedInfo_t::StreamingInfo_t& streamInfo, - const uint16_t fileNamesBufSize, const EPakStreamSet set) +void Pak_OpenAssociatedStreamingFiles(PakLoadedInfo_s* const loadedInfo, PakLoadedInfo_s::StreamingInfo_t& streamInfo, + const uint16_t fileNamesBufSize, const PakStreamSet_e set) { assert(set < STREAMING_SET_COUNT); - const PakMemoryData_t& memoryData = loadedInfo->pakFile->memoryData; + const PakMemoryData_s& memoryData = loadedInfo->pakFile->memoryData; uint16_t numStreamFiles = 0; // load all streaming sets @@ -83,7 +83,7 @@ void Pak_OpenAssociatedStreamingFiles(PakLoadedInfo_t* const loadedInfo, PakLoad //----------------------------------------------------------------------------- // allocates the pak string to be used for embedded streaming data //----------------------------------------------------------------------------- -void Pak_EnableEmbeddedStreamingData(PakLoadedInfo_t* const loadedInfo, PakLoadedInfo_t::StreamingInfo_t& streamInfo) +void Pak_EnableEmbeddedStreamingData(PakLoadedInfo_s* const loadedInfo, PakLoadedInfo_s::StreamingInfo_t& streamInfo) { const char* const baseName = V_UnqualifiedFileName(loadedInfo->fileName); const size_t baseNameLen = strlen(baseName); @@ -113,13 +113,13 @@ void Pak_EnableEmbeddedStreamingData(PakLoadedInfo_t* const loadedInfo, PakLoade //----------------------------------------------------------------------------- // parse and open all streaming files //----------------------------------------------------------------------------- -void Pak_LoadStreamingData(PakLoadedInfo_t* const loadedInfo) +void Pak_LoadStreamingData(PakLoadedInfo_s* const loadedInfo) { - const PakFileHeader_t& pakHeader = loadedInfo->pakFile->GetHeader(); + const PakFileHeader_s& pakHeader = loadedInfo->pakFile->GetHeader(); for (int i = 0; i < STREAMING_SET_COUNT; i++) { - PakLoadedInfo_t::StreamingInfo_t& streamInfo = loadedInfo->streamInfo[i]; + PakLoadedInfo_s::StreamingInfo_t& streamInfo = loadedInfo->streamInfo[i]; streamInfo.Reset(); const bool optional = (i == STREAMING_SET_OPTIONAL); @@ -141,7 +141,7 @@ void Pak_LoadStreamingData(PakLoadedInfo_t* const loadedInfo) // external streaming files; mistake while building the pak? assert(!embeddedStreamingDataSize); - Pak_OpenAssociatedStreamingFiles(loadedInfo, streamInfo, filesBufLen, EPakStreamSet(i)); + Pak_OpenAssociatedStreamingFiles(loadedInfo, streamInfo, filesBufLen, PakStreamSet_e(i)); } else if (embeddedStreamingDataSize > 0) { diff --git a/r5dev/rtech/pak/pakstream.h b/r5dev/rtech/pak/pakstream.h index 7667acd2..5b3e2bc4 100644 --- a/r5dev/rtech/pak/pakstream.h +++ b/r5dev/rtech/pak/pakstream.h @@ -3,11 +3,11 @@ #include "rtech/ipakfile.h" #include "pakstate.h" -extern void Pak_OpenAssociatedStreamingFiles(PakLoadedInfo_t* const loadedInfo, PakLoadedInfo_t::StreamingInfo_t& streamInfo, - const uint16_t fileNamesBufSize, const EPakStreamSet set); +extern void Pak_OpenAssociatedStreamingFiles(PakLoadedInfo_s* const loadedInfo, PakLoadedInfo_s::StreamingInfo_t& streamInfo, + const uint16_t fileNamesBufSize, const PakStreamSet_e set); -extern void Pak_EnableEmbeddedStreamingData(PakLoadedInfo_t* const loadedInfo, PakLoadedInfo_t::StreamingInfo_t& streamInfo); -extern void Pak_LoadStreamingData(PakLoadedInfo_t* const loadedInfo); +extern void Pak_EnableEmbeddedStreamingData(PakLoadedInfo_s* const loadedInfo, PakLoadedInfo_s::StreamingInfo_t& streamInfo); +extern void Pak_LoadStreamingData(PakLoadedInfo_s* const loadedInfo); // the current download progress of optional streaming assets inline float* g_pStreamingDownloadProgress = nullptr; diff --git a/r5dev/rtech/pak/paktools.cpp b/r5dev/rtech/pak/paktools.cpp index 0f850314..7ed1e409 100644 --- a/r5dev/rtech/pak/paktools.cpp +++ b/r5dev/rtech/pak/paktools.cpp @@ -77,26 +77,26 @@ int Pak_FileExists(const char* const pakFilePath) //----------------------------------------------------------------------------- // returns pak status as string //----------------------------------------------------------------------------- -const char* Pak_StatusToString(const EPakStatus status) +const char* Pak_StatusToString(const PakStatus_e status) { switch (status) { - case EPakStatus::PAK_STATUS_FREED: return "PAK_STATUS_FREED"; - case EPakStatus::PAK_STATUS_LOAD_PENDING: return "PAK_STATUS_LOAD_PENDING"; - case EPakStatus::PAK_STATUS_REPAK_RUNNING: return "PAK_STATUS_REPAK_RUNNING"; - case EPakStatus::PAK_STATUS_REPAK_DONE: return "PAK_STATUS_REPAK_DONE"; - case EPakStatus::PAK_STATUS_LOAD_STARTING: return "PAK_STATUS_LOAD_STARTING"; - case EPakStatus::PAK_STATUS_LOAD_PAKHDR: return "PAK_STATUS_LOAD_PAKHDR"; - case EPakStatus::PAK_STATUS_LOAD_PATCH_INIT: return "PAK_STATUS_LOAD_PATCH_INIT"; - case EPakStatus::PAK_STATUS_LOAD_PATCH_EDIT_STREAM: return "PAK_STATUS_LOAD_PATCH_EDIT_STREAM"; - case EPakStatus::PAK_STATUS_LOAD_ASSETS: return "PAK_STATUS_LOAD_ASSETS"; - case EPakStatus::PAK_STATUS_LOADED: return "PAK_STATUS_LOADED"; - case EPakStatus::PAK_STATUS_UNLOAD_PENDING: return "PAK_STATUS_UNLOAD_PENDING"; - case EPakStatus::PAK_STATUS_FREE_PENDING: return "PAK_STATUS_FREE_PENDING"; - case EPakStatus::PAK_STATUS_CANCELING: return "PAK_STATUS_CANCELING"; - case EPakStatus::PAK_STATUS_ERROR: return "PAK_STATUS_ERROR"; - case EPakStatus::PAK_STATUS_INVALID_PAKHANDLE: return "PAK_STATUS_INVALID_PAKHANDLE"; - case EPakStatus::PAK_STATUS_BUSY: return "PAK_STATUS_BUSY"; + case PakStatus_e::PAK_STATUS_FREED: return "PAK_STATUS_FREED"; + case PakStatus_e::PAK_STATUS_LOAD_PENDING: return "PAK_STATUS_LOAD_PENDING"; + case PakStatus_e::PAK_STATUS_REPAK_RUNNING: return "PAK_STATUS_REPAK_RUNNING"; + case PakStatus_e::PAK_STATUS_REPAK_DONE: return "PAK_STATUS_REPAK_DONE"; + case PakStatus_e::PAK_STATUS_LOAD_STARTING: return "PAK_STATUS_LOAD_STARTING"; + case PakStatus_e::PAK_STATUS_LOAD_PAKHDR: return "PAK_STATUS_LOAD_PAKHDR"; + case PakStatus_e::PAK_STATUS_LOAD_PATCH_INIT: return "PAK_STATUS_LOAD_PATCH_INIT"; + case PakStatus_e::PAK_STATUS_LOAD_PATCH_EDIT_STREAM: return "PAK_STATUS_LOAD_PATCH_EDIT_STREAM"; + case PakStatus_e::PAK_STATUS_LOAD_ASSETS: return "PAK_STATUS_LOAD_ASSETS"; + case PakStatus_e::PAK_STATUS_LOADED: return "PAK_STATUS_LOADED"; + case PakStatus_e::PAK_STATUS_UNLOAD_PENDING: return "PAK_STATUS_UNLOAD_PENDING"; + case PakStatus_e::PAK_STATUS_FREE_PENDING: return "PAK_STATUS_FREE_PENDING"; + case PakStatus_e::PAK_STATUS_CANCELING: return "PAK_STATUS_CANCELING"; + case PakStatus_e::PAK_STATUS_ERROR: return "PAK_STATUS_ERROR"; + case PakStatus_e::PAK_STATUS_INVALID_PAKHANDLE: return "PAK_STATUS_INVALID_PAKHANDLE"; + case PakStatus_e::PAK_STATUS_BUSY: return "PAK_STATUS_BUSY"; default: return "PAK_STATUS_UNKNOWN"; } } @@ -104,12 +104,12 @@ const char* Pak_StatusToString(const EPakStatus status) //----------------------------------------------------------------------------- // returns pak decoder as string //----------------------------------------------------------------------------- -const char* Pak_DecoderToString(const EPakDecodeMode mode) +const char* Pak_DecoderToString(const PakDecodeMode_e mode) { switch (mode) { - case EPakDecodeMode::MODE_RTECH: return "RTech"; - case EPakDecodeMode::MODE_ZSTD: return "ZStd"; + case PakDecodeMode_e::MODE_RTECH: return "RTech"; + case PakDecodeMode_e::MODE_ZSTD: return "ZStd"; } UNREACHABLE(); @@ -253,7 +253,7 @@ PakGuid_t Pak_StringToGuid(const char* const string) //----------------------------------------------------------------------------- // gets information about loaded pak file via pak id //----------------------------------------------------------------------------- -PakLoadedInfo_t* Pak_GetPakInfo(const PakHandle_t pakId) +PakLoadedInfo_s* Pak_GetPakInfo(const PakHandle_t pakId) { return &g_pakGlobals->loadedPaks[pakId & PAK_MAX_LOADED_PAKS_MASK]; } @@ -261,11 +261,11 @@ PakLoadedInfo_t* Pak_GetPakInfo(const PakHandle_t pakId) //----------------------------------------------------------------------------- // gets information about loaded pak file via pak name //----------------------------------------------------------------------------- -const PakLoadedInfo_t* Pak_GetPakInfo(const char* const pakName) +const PakLoadedInfo_s* Pak_GetPakInfo(const char* const pakName) { for (int16_t i = 0; i < g_pakGlobals->loadedPakCount; ++i) { - const PakLoadedInfo_t* const info = &g_pakGlobals->loadedPaks[i]; + const PakLoadedInfo_s* const info = &g_pakGlobals->loadedPaks[i]; if (!info) continue; @@ -285,27 +285,27 @@ const PakLoadedInfo_t* Pak_GetPakInfo(const char* const pakName) //----------------------------------------------------------------------------- // returns a pointer to the patch data header //----------------------------------------------------------------------------- -PakPatchDataHeader_t* Pak_GetPatchDataHeader(PakFileHeader_t* const pakHeader) +PakPatchDataHeader_s* Pak_GetPatchDataHeader(PakFileHeader_s* const pakHeader) { // shouldn't be called if the pak doesn1't have patches! assert(pakHeader->patchIndex > 0); - return reinterpret_cast(reinterpret_cast(pakHeader) + sizeof(PakFileHeader_t)); + return reinterpret_cast(reinterpret_cast(pakHeader) + sizeof(PakFileHeader_s)); } //----------------------------------------------------------------------------- // returns a pointer to the patch file header //----------------------------------------------------------------------------- -PakPatchFileHeader_t* Pak_GetPatchFileHeader(PakFileHeader_t* const pakHeader, const int index) +PakPatchFileHeader_s* Pak_GetPatchFileHeader(PakFileHeader_s* const pakHeader, const int index) { assert(pakHeader->patchIndex > 0 && index < pakHeader->patchIndex); uint8_t* address = reinterpret_cast(pakHeader); // skip the file header - address += sizeof(PakFileHeader_t); + address += sizeof(PakFileHeader_s); // skip the patch data header, the patch file headers start from there - address += sizeof(PakPatchDataHeader_t); - PakPatchFileHeader_t* const patchHeaders = reinterpret_cast(address); + address += sizeof(PakPatchDataHeader_s); + PakPatchFileHeader_s* const patchHeaders = reinterpret_cast(address); return &patchHeaders[index]; } @@ -313,13 +313,13 @@ PakPatchFileHeader_t* Pak_GetPatchFileHeader(PakFileHeader_t* const pakHeader, c //----------------------------------------------------------------------------- // returns the patch number belonging to the index provided //----------------------------------------------------------------------------- -short Pak_GetPatchNumberForIndex(PakFileHeader_t* const pakHeader, const int index) +short Pak_GetPatchNumberForIndex(PakFileHeader_s* const pakHeader, const int index) { assert(pakHeader->patchIndex > 0 && index < pakHeader->patchIndex); const uint8_t* patchHeader = reinterpret_cast(Pak_GetPatchFileHeader(pakHeader, pakHeader->patchIndex - 1)); // skip the last patch file header, the patch number start from there - patchHeader += sizeof(PakPatchFileHeader_t); + patchHeader += sizeof(PakPatchFileHeader_s); const short* patchNumber = reinterpret_cast(patchHeader); return patchNumber[index]; @@ -347,7 +347,7 @@ bool Pak_UpdatePatchHeaders(uint8_t* const inBuf, const char* const outPakFile) // NOTE: we modify the in buffer as the patch headers belong to the // compressed section - PakFileHeader_t* const inHeader = reinterpret_cast(inBuf); + PakFileHeader_s* const inHeader = reinterpret_cast(inBuf); // update each patch header for (uint16_t i = 0; i < inHeader->patchIndex; i++) @@ -371,13 +371,13 @@ bool Pak_UpdatePatchHeaders(uint8_t* const inBuf, const char* const outPakFile) const size_t fileSize = inPatch.GetSize(); // pak appears truncated - if (fileSize <= sizeof(PakFileHeader_t)) + if (fileSize <= sizeof(PakFileHeader_s)) return false; DevMsg(eDLL_T::RTECH, "%s: updating patch header for pak '%s', new size = %zu\n", __FUNCTION__, patchFile, fileSize); - PakPatchFileHeader_t* const patchHeader = Pak_GetPatchFileHeader(inHeader, i); + PakPatchFileHeader_s* const patchHeader = Pak_GetPatchFileHeader(inHeader, i); patchHeader->compressedSize = fileSize; } @@ -387,7 +387,7 @@ bool Pak_UpdatePatchHeaders(uint8_t* const inBuf, const char* const outPakFile) //----------------------------------------------------------------------------- // prints the pak header details to the console //----------------------------------------------------------------------------- -void Pak_ShowHeaderDetails(const PakFileHeader_t* const pakHeader) +void Pak_ShowHeaderDetails(const PakFileHeader_s* const pakHeader) { SYSTEMTIME systemTime; FileTimeToSystemTime(&pakHeader->fileTime, &systemTime); diff --git a/r5dev/rtech/pak/paktools.h b/r5dev/rtech/pak/paktools.h index cd9e5780..becc39a2 100644 --- a/r5dev/rtech/pak/paktools.h +++ b/r5dev/rtech/pak/paktools.h @@ -12,20 +12,20 @@ extern bool Pak_FileOverrideExists(const char* const pakFilePath, char* const ou extern int Pak_FileExists(const char* const pakFilePath); -extern const char* Pak_StatusToString(const EPakStatus status); -const char* Pak_DecoderToString(const EPakDecodeMode mode); +extern const char* Pak_StatusToString(const PakStatus_e status); +const char* Pak_DecoderToString(const PakDecodeMode_e mode); extern PakGuid_t Pak_StringToGuid(const char* const string); -extern PakLoadedInfo_t* Pak_GetPakInfo(const PakHandle_t pakId); -extern const PakLoadedInfo_t* Pak_GetPakInfo(const char* const pakName); +extern PakLoadedInfo_s* Pak_GetPakInfo(const PakHandle_t pakId); +extern const PakLoadedInfo_s* Pak_GetPakInfo(const char* const pakName); -extern PakPatchDataHeader_t* Pak_GetPatchDataHeader(PakFileHeader_t* const pakHeader); -extern PakPatchFileHeader_t* Pak_GetPatchFileHeader(PakFileHeader_t* const pakHeader, const int index); -extern short Pak_GetPatchNumberForIndex(PakFileHeader_t* const pakHeader, const int index); +extern PakPatchDataHeader_s* Pak_GetPatchDataHeader(PakFileHeader_s* const pakHeader); +extern PakPatchFileHeader_s* Pak_GetPatchFileHeader(PakFileHeader_s* const pakHeader, const int index); +extern short Pak_GetPatchNumberForIndex(PakFileHeader_s* const pakHeader, const int index); extern bool Pak_UpdatePatchHeaders(uint8_t* const inBuf, const char* const outPakFile); -extern void Pak_ShowHeaderDetails(const PakFileHeader_t* const pakHeader); +extern void Pak_ShowHeaderDetails(const PakFileHeader_s* const pakHeader); #endif // !RTECH_PAKTOOLS_H From 99cabd2ac8614456d431d37213b7046a180da4d6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 00:44:19 +0200 Subject: [PATCH 015/113] UserCmd: cleanup variable names and comments Reversed some extra field names + adjusted comment for clamping ucmd->camerapos (this was tested and works, this field should be clamped). --- r5dev/game/shared/usercmd.cpp | 3 +-- r5dev/game/shared/usercmd.h | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/r5dev/game/shared/usercmd.cpp b/r5dev/game/shared/usercmd.cpp index ef1403ea..4d5ee354 100644 --- a/r5dev/game/shared/usercmd.cpp +++ b/r5dev/game/shared/usercmd.cpp @@ -27,8 +27,7 @@ int ReadUserCmd(bf_read* buf, CUserCmd* move, CUserCmd* from) const int seed = v_ReadUserCmd(buf, move, from); // Initialize the camera position as <0,0,0>, this should at least avoid - // crash and meme behaviors. Has not been tested yet unlike all the - // patches performed below. + // crash and meme behaviors. if (!move->camerapos.IsValid()) move->camerapos.Init(); diff --git a/r5dev/game/shared/usercmd.h b/r5dev/game/shared/usercmd.h index ae357700..e964c45b 100644 --- a/r5dev/game/shared/usercmd.h +++ b/r5dev/game/shared/usercmd.h @@ -48,12 +48,15 @@ public: int32_t command_number; int32_t tick_count; float_t command_time; + QAngle viewangles; QAngle pitchangles; // Pitch angles? See [r5apex_ds+705D80]. + float_t forwardmove; float_t sidemove; float_t upmove; int32_t buttons; + byte impulse; byte cycleslot; byte weaponindex; @@ -64,12 +67,18 @@ public: bool controllermode; bool fixangles; bool setlastcycleslot; - char pad_0x0034[157]; - QAngle renderangles; // IDK what this is used for. - QAngle renderangles_copy; // IDK what this is used for. + char pad_0x0034[149]; + + // Zipline vars (see [r5apex_ds+8A6573] for read). + bool placedZiplineStation; + char unk[3]; + int nUnkDC; + Vector3D beginStationOrigin; + Vector3D stationWorldRelative; float fUnkF8; - QAngle another_renderangles_copy; // IDK what this is used for. - QAngle yet_another_renderangles_copy; // IDK what this is used for. + Vector3D endStationOrigin; + QAngle stationWorldAngles; + char pad_0x00114[112]; int32_t randomseed; byte bUnk188; From 33564c7351246b4fc8a610af615d8461a2b11cce Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 00:45:10 +0200 Subject: [PATCH 016/113] Tier2: use utlvector for cylinder points and initialize buffer --- r5dev/tier2/renderutils.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/r5dev/tier2/renderutils.cpp b/r5dev/tier2/renderutils.cpp index 67e5addc..05cabcec 100644 --- a/r5dev/tier2/renderutils.cpp +++ b/r5dev/tier2/renderutils.cpp @@ -69,7 +69,7 @@ void DebugDrawCylinder(const Vector3D& vOrigin, const QAngle& vAngles, float flR float flDegrees = 360.f / float(nSides); QAngle vComposed; Vector3D vForward; - vector vvPoints; + CUtlVector vecPoints(0, nSides); AngleVectors(vAngles, &vForward); @@ -79,13 +79,13 @@ void DebugDrawCylinder(const Vector3D& vOrigin, const QAngle& vAngles, float flR AngleCompose(vAngles, { 0.f, 0.f, flDegrees * i }, vComposed); AngleVectors(vComposed, nullptr, &right, nullptr); - vvPoints.push_back(vOrigin + (right * flRadius)); + vecPoints.AddToTail(vOrigin + (right * flRadius)); } for (int i = 0; i < nSides; i++) { - Vector3D vStart = vvPoints[i]; - Vector3D vEnd = i == 0 ? vvPoints[nSides - 1] : vvPoints[i - 1]; + Vector3D vStart = vecPoints[i]; + Vector3D vEnd = i == 0 ? vecPoints[nSides - 1] : vecPoints[i - 1]; v_RenderLine(vStart, vEnd, color, bZBuffer); v_RenderLine(vStart + (vForward * flHeight), vEnd + (vForward * flHeight), color, bZBuffer); From cdaf4f1b76b70de915ccc797e75e5403aab8e4a3 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:20:06 +0200 Subject: [PATCH 017/113] Game: fixup types in CPlayerState --- r5dev/public/playerstate.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/r5dev/public/playerstate.h b/r5dev/public/playerstate.h index 6d5a24ef..7b71c1e3 100644 --- a/r5dev/public/playerstate.h +++ b/r5dev/public/playerstate.h @@ -25,20 +25,20 @@ public: __int64 requestedClass; __int64 onDeathClass; __int64 oldClass; - __int64 netname; + string_t netname; int fixangle; - Vector3D anglechange; + QAngle anglechange; int index; - Vector3D forceWorldViewAngle; + QAngle forceWorldViewAngle; int forceWorldViewAngleUntilTick; bool replay; char gap_5d[3]; int lastPlayerView_tickcount; Vector3D lastPlayerView_origin; - Vector3D lastPlayerView_angle; + QAngle lastPlayerView_angle; bool deadflag; char gap_7d[3]; - Vector3D m_localViewAngles; + QAngle m_localViewAngles; }; #endif // PLAYERSTATE_H \ No newline at end of file From 824b5098b3e829dbe336a536f566e163162ad664 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:20:48 +0200 Subject: [PATCH 018/113] Game: add CBaseEntity::GetFlags() and FL_FAKECLIENT constant --- r5dev/game/server/baseentity.h | 2 ++ r5dev/public/const.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/r5dev/game/server/baseentity.h b/r5dev/game/server/baseentity.h index 88cd720e..950e8748 100644 --- a/r5dev/game/server/baseentity.h +++ b/r5dev/game/server/baseentity.h @@ -56,6 +56,8 @@ public: inline edict_t GetEdict(void) { return NetworkProp()->GetEdict(); } inline string_t GetEntityName(void) const { return m_iName; } + inline int GetFlags(void) const { return m_fFlags; } + protected: CBaseHandle m_RefEHandle; char gap_c[4]; diff --git a/r5dev/public/const.h b/r5dev/public/const.h index 5709c447..ebca76a7 100644 --- a/r5dev/public/const.h +++ b/r5dev/public/const.h @@ -26,6 +26,8 @@ #define FIXANGLE_ABSOLUTE 1 #define FIXANGLE_RELATIVE 2 +#define FL_FAKECLIENT (1<<7) // Fake client, simulated server side; don't send network messages to them + enum RenderMode_t { kRenderNormal = 0, // src From 42e02b456926d7cd600e7dfa8d8e2aa253c41996 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:29:29 +0200 Subject: [PATCH 019/113] UserCmd: limit command backlog to prevent exploitation Implement UserCmd command backlog limiting (the new convar 'sv_maxUserCmdProcessTicks' dictates how many ticks can be processed per second). Defaulted to 10, which is (default tick interval (0.05) * default cvar val (10) = 0.5ms window), which is equal to the default of cvar 'sv_maxunlag'. Before this patch, you could stuff several seconds worth of usercmd's in one second and achieve speed hacking. --- r5dev/common/global.cpp | 13 ++++++ r5dev/common/global.h | 6 +++ r5dev/core/init.cpp | 3 ++ r5dev/engine/client/client.cpp | 42 +++++++++++++++++ r5dev/engine/client/client.h | 10 +++++ r5dev/game/CMakeLists.txt | 2 + r5dev/game/server/gameinterface.cpp | 4 +- r5dev/game/server/gameinterface.h | 10 ++++- r5dev/game/server/player.cpp | 29 +++++++++++- r5dev/game/server/player.h | 8 +++- r5dev/game/server/player_command.cpp | 60 +++++++++++++++++++++++++ r5dev/game/server/player_command.h | 67 ++++++++++++++++++++++++++++ 12 files changed, 249 insertions(+), 5 deletions(-) create mode 100644 r5dev/game/server/player_command.cpp create mode 100644 r5dev/game/server/player_command.h diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index d18725d6..5c232085 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -85,7 +85,13 @@ ConVar* sv_voiceEcho = nullptr; ConVar* sv_voiceenable = nullptr; ConVar* sv_alltalk = nullptr; +ConVar* sv_clampPlayerFrameTime = nullptr; + +ConVar* playerframetimekick_margin = nullptr; +ConVar* playerframetimekick_decayrate = nullptr; + ConVar* player_userCmdsQueueWarning = nullptr; +ConVar* player_disallow_negative_frametime = nullptr; #endif // !CLIENT_DLL ConVar* sv_cheats = nullptr; @@ -208,7 +214,14 @@ void ConVar_InitShipped(void) sv_voiceenable = g_pCVar->FindVar("sv_voiceenable"); sv_voiceEcho = g_pCVar->FindVar("sv_voiceEcho"); sv_alltalk = g_pCVar->FindVar("sv_alltalk"); + + sv_clampPlayerFrameTime = g_pCVar->FindVar("sv_clampPlayerFrameTime"); + + playerframetimekick_margin = g_pCVar->FindVar("playerframetimekick_margin"); + playerframetimekick_decayrate = g_pCVar->FindVar("playerframetimekick_decayrate"); + player_userCmdsQueueWarning = g_pCVar->FindVar("player_userCmdsQueueWarning"); + player_disallow_negative_frametime = g_pCVar->FindVar("player_disallow_negative_frametime"); sv_updaterate_sp->RemoveFlags(FCVAR_DEVELOPMENTONLY); sv_updaterate_mp->RemoveFlags(FCVAR_DEVELOPMENTONLY); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index e958199b..746afbd3 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -72,7 +72,13 @@ extern ConVar* sv_voiceEcho; extern ConVar* sv_voiceenable; extern ConVar* sv_alltalk; +extern ConVar* sv_clampPlayerFrameTime; + +extern ConVar* playerframetimekick_margin; +extern ConVar* playerframetimekick_decayrate; + extern ConVar* player_userCmdsQueueWarning; +extern ConVar* player_disallow_negative_frametime; #endif // CLIENT_DLL extern ConVar* sv_cheats; diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 3677676d..0aec44c8 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -135,6 +135,8 @@ #include "game/server/detour_impl.h" #include "game/server/gameinterface.h" #include "game/server/movehelper_server.h" +#include "game/server/player.h" +#include "game/server/player_command.h" #include "game/server/physics_main.h" #include "game/server/vscript_server.h" #endif // !CLIENT_DLL @@ -663,6 +665,7 @@ void DetourRegister() // Register detour classes to be searched and hooked. REGISTER(VBaseEntity); REGISTER(VBaseAnimating); REGISTER(VPlayer); + REGISTER(VPlayerMove); #endif // !CLIENT_DLL diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index 496e7afe..9f3edd85 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -524,6 +524,48 @@ bool CClient::VProcessSetConVar(CClient* pClient, NET_SetConVar* pMsg) return true; } +//--------------------------------------------------------------------------------- +// Purpose: set UserCmd time buffer +// Input : numUserCmdProcessTicksMax - +// tickInterval - +//--------------------------------------------------------------------------------- +void CClientExtended::InitializeMovementTimeForUserCmdProcessing(const int numUserCmdProcessTicksMax, const float tickInterval) +{ + // Grant the client some time buffer to execute user commands + m_flMovementTimeForUserCmdProcessingRemaining += tickInterval; + + // but never accumulate more than N ticks + if (m_flMovementTimeForUserCmdProcessingRemaining > numUserCmdProcessTicksMax * tickInterval) + m_flMovementTimeForUserCmdProcessingRemaining = numUserCmdProcessTicksMax * tickInterval; +} + +//--------------------------------------------------------------------------------- +// Purpose: consume UserCmd time buffer +// Input : flTimeNeeded - +// Output : max time allowed for processing +//--------------------------------------------------------------------------------- +float CClientExtended::ConsumeMovementTimeForUserCmdProcessing(const float flTimeNeeded) +{ + if (m_flMovementTimeForUserCmdProcessingRemaining <= 0.0f) + return 0.0f; + else if (flTimeNeeded > m_flMovementTimeForUserCmdProcessingRemaining + FLT_EPSILON) + { + const float flResult = m_flMovementTimeForUserCmdProcessingRemaining; + m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; + + return flResult; + } + else + { + m_flMovementTimeForUserCmdProcessingRemaining -= flTimeNeeded; + + if (m_flMovementTimeForUserCmdProcessingRemaining < 0.0f) + m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; + + return flTimeNeeded; + } +} + void VClient::Detour(const bool bAttach) const { #ifndef CLIENT_DLL diff --git a/r5dev/engine/client/client.h b/r5dev/engine/client/client.h index a40456af..d3f9baf5 100644 --- a/r5dev/engine/client/client.h +++ b/r5dev/engine/client/client.h @@ -230,6 +230,7 @@ public: m_flNetProcessTimeBase = 0.0; m_flStringCommandQuotaTimeStart = 0.0; m_nStringCommandQuotaCount = NULL; + m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; m_bInitialConVarsSet = false; } @@ -247,6 +248,12 @@ public: // Inlines: inline void SetStringCommandQuotaCount(const int iCount) { m_nStringCommandQuotaCount = iCount; } inline int GetStringCommandQuotaCount(void) const { return m_nStringCommandQuotaCount; } + inline void SetRemainingMovementTimeForUserCmdProcessing(const float flValue) { m_flMovementTimeForUserCmdProcessingRemaining = flValue; } + inline float GetRemainingMovementTimeForUserCmdProcessing() const { return m_flMovementTimeForUserCmdProcessingRemaining; } + + void InitializeMovementTimeForUserCmdProcessing(const int numUserCmdProcessTicksMax, const float tickInterval); + float ConsumeMovementTimeForUserCmdProcessing(const float flTimeNeeded); + private: // Measure how long this client's packets took to process. double m_flNetProcessingTimeMsecs; @@ -256,6 +263,9 @@ private: double m_flStringCommandQuotaTimeStart; int m_nStringCommandQuotaCount; + // How much of a movement time buffer can we process from this user? + float m_flMovementTimeForUserCmdProcessingRemaining; + bool m_bInitialConVarsSet; // Whether or not the initial ConVar KV's are set }; diff --git a/r5dev/game/CMakeLists.txt b/r5dev/game/CMakeLists.txt index b24557d3..6a734004 100644 --- a/r5dev/game/CMakeLists.txt +++ b/r5dev/game/CMakeLists.txt @@ -73,6 +73,8 @@ add_sources( SOURCE_GROUP "Network" add_sources( SOURCE_GROUP "Player" "server/player.cpp" "server/player.h" + "server/player_command.cpp" + "server/player_command.h" "server/playerlocaldata.h" ) diff --git a/r5dev/game/server/gameinterface.cpp b/r5dev/game/server/gameinterface.cpp index 8b16f760..52992b0a 100644 --- a/r5dev/game/server/gameinterface.cpp +++ b/r5dev/game/server/gameinterface.cpp @@ -22,10 +22,10 @@ //----------------------------------------------------------------------------- // This is called when a new game is started. (restart, map) //----------------------------------------------------------------------------- -void CServerGameDLL::GameInit(void) +bool CServerGameDLL::GameInit(void) { const static int index = 1; - CallVFunc(index, this); + return CallVFunc(index, this); } //----------------------------------------------------------------------------- diff --git a/r5dev/game/server/gameinterface.h b/r5dev/game/server/gameinterface.h index 8b92c280..e89084bd 100644 --- a/r5dev/game/server/gameinterface.h +++ b/r5dev/game/server/gameinterface.h @@ -19,7 +19,7 @@ class ServerClass; class CServerGameDLL { public: - void GameInit(void); + bool GameInit(void); void PrecompileScriptsJob(void); void LevelShutdown(void); void GameShutdown(void); @@ -48,11 +48,15 @@ class CServerGameEnts : public IServerGameEnts }; inline void(*CServerGameDLL__OnReceivedSayTextMessage)(void* thisptr, int senderId, const char* text, bool isTeamChat); +inline bool(*CServerGameDLL__GameInit)(void); + inline void(*CServerGameClients__ProcessUserCmds)(CServerGameClients* thisp, edict_t edict, bf_read* buf, int numCmds, int totalCmds, int droppedPackets, bool ignore, bool paused); inline void(*v_RunFrameServer)(double flFrameTime, bool bRunOverlays, bool bUniformUpdate); +inline float* g_pflServerFrameTimeBase = nullptr; + extern CServerGameDLL* g_pServerGameDLL; extern CServerGameClients* g_pServerGameClients; extern CServerGameEnts* g_pServerGameEntities; @@ -65,8 +69,10 @@ class VServerGameDLL : public IDetour virtual void GetAdr(void) const { LogFunAdr("CServerGameDLL::OnReceivedSayTextMessage", CServerGameDLL__OnReceivedSayTextMessage); + LogFunAdr("CServerGameDLL::GameInit", CServerGameDLL__GameInit); LogFunAdr("CServerGameClients::ProcessUserCmds", CServerGameClients__ProcessUserCmds); LogFunAdr("RunFrameServer", v_RunFrameServer); + LogVarAdr("g_flServerFrameTimeBase", g_pflServerFrameTimeBase); LogVarAdr("g_pServerGameDLL", g_pServerGameDLL); LogVarAdr("g_pServerGameClients", g_pServerGameClients); LogVarAdr("g_pServerGameEntities", g_pServerGameEntities); @@ -75,12 +81,14 @@ class VServerGameDLL : public IDetour virtual void GetFun(void) const { g_GameDll.FindPatternSIMD("85 D2 0F 8E ?? ?? ?? ?? 4C 8B DC").GetPtr(CServerGameDLL__OnReceivedSayTextMessage); + g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01").GetPtr(CServerGameDLL__GameInit); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 55 41 57").GetPtr(CServerGameClients__ProcessUserCmds); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8D 0D ?? ?? ?? ??").GetPtr(v_RunFrameServer); } virtual void GetVar(void) const { g_pGlobals = g_GameDll.FindPatternSIMD("4C 8B 0D ?? ?? ?? ?? 48 8B D1").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_pflServerFrameTimeBase = CMemory(CServerGameDLL__GameInit).FindPatternSelf("F3 0F 11 0D").ResolveRelativeAddressSelf(0x4, 0x8).RCast(); } virtual void GetCon(void) const { } virtual void Detour(const bool bAttach) const; diff --git a/r5dev/game/server/player.cpp b/r5dev/game/server/player.cpp index 8bb00679..122f6b98 100644 --- a/r5dev/game/server/player.cpp +++ b/r5dev/game/server/player.cpp @@ -13,6 +13,9 @@ #include "engine/server/server.h" +// NOTE[ AMOS ]: default tick interval (0.05) * default cvar value (10) = total time buffer of 0.5, which is the default of cvar 'sv_maxunlag'. +static ConVar sv_maxUserCmdProcessTicks("sv_maxUserCmdProcessTicks", "10", FCVAR_NONE, "Maximum number of client-issued UserCmd ticks that can be replayed in packet loss conditions, 0 to allow no restrictions."); + //------------------------------------------------------------------------------ // Purpose: executes a null command for this player //------------------------------------------------------------------------------ @@ -64,7 +67,7 @@ inline void CPlayer::SetTimeBase(float flTimeBase) SetLastUCmdSimulationRemainderTime(flTime); - float flSimulationTime = flTimeBase - m_lastUCmdSimulationRemainderTime * (*g_pGlobals)->m_flTickInterval; + float flSimulationTime = flTimeBase - m_lastUCmdSimulationRemainderTime * TICK_INTERVAL; if (flSimulationTime >= 0.0f) { flTime = flSimulationTime; @@ -241,6 +244,25 @@ void CPlayer::SetLastUserCommand(CUserCmd* pUserCmd) m_LastCmd.Copy(pUserCmd); } +//------------------------------------------------------------------------------ +// Purpose: run physics simulation for player +// Input : *player (this) - +// numPerIteration - +// adjustTimeBase - +//------------------------------------------------------------------------------ +bool Player_PhysicsSimulate(CPlayer* player, int numPerIteration, bool adjustTimeBase) +{ + CClientExtended* const cle = g_pServer->GetClientExtended(player->GetEdict() - 1); + const int numUserCmdProcessTicksMax = sv_maxUserCmdProcessTicks.GetInt(); + + if (numUserCmdProcessTicksMax && (*g_pGlobals)->m_nGameMode != GameMode_t::SP_MODE) // don't apply this filter in SP games + cle->InitializeMovementTimeForUserCmdProcessing(numUserCmdProcessTicksMax, TICK_INTERVAL); + else // Otherwise we don't care to track time + cle->SetRemainingMovementTimeForUserCmdProcessing(FLT_MAX); + + return CPlayer__PhysicsSimulate(player, numPerIteration, adjustTimeBase); +} + /* ===================== CC_CreateFakePlayer_f @@ -286,3 +308,8 @@ static void CC_CreateFakePlayer_f(const CCommand& args) } static ConCommand sv_addbot("sv_addbot", CC_CreateFakePlayer_f, "Creates a bot on the server", FCVAR_RELEASE); + +void VPlayer::Detour(const bool bAttach) const +{ + DetourSetup(&CPlayer__PhysicsSimulate, &Player_PhysicsSimulate, bAttach); +} diff --git a/r5dev/game/server/player.h b/r5dev/game/server/player.h index 1b6d05bf..546064fe 100644 --- a/r5dev/game/server/player.h +++ b/r5dev/game/server/player.h @@ -241,6 +241,7 @@ struct SpeedChangeHistoryEntry class CPlayer : public CBaseCombatCharacter { + friend class CPlayerMove; public: void RunNullCommand(void); QAngle* EyeAngles(QAngle* pAngles); @@ -260,6 +261,8 @@ public: inline bool IsConnected() const { return m_iConnected != PlayerDisconnected; } inline bool IsDisconnecting() const { return m_iConnected == PlayerDisconnecting; } + inline bool IsBot() const { return (GetFlags() & FL_FAKECLIENT) != 0; } + private: int m_StuckLast; char gap_5a8c[4]; @@ -796,6 +799,7 @@ static_assert(sizeof(CPlayer) == 0x7EF0); // !TODO: backwards compatibility. inline QAngle*(*CPlayer__EyeAngles)(CPlayer* pPlayer, QAngle* pAngles); inline void(*CPlayer__PlayerRunCommand)(CPlayer* pPlayer, CUserCmd* pUserCmd, IMoveHelper* pMover); +inline bool(*CPlayer__PhysicsSimulate)(CPlayer* pPlayer, int numPerIteration, bool adjustTimeBase); /////////////////////////////////////////////////////////////////////////////// class VPlayer : public IDetour @@ -804,15 +808,17 @@ class VPlayer : public IDetour { LogFunAdr("CPlayer::EyeAngles", CPlayer__EyeAngles); LogFunAdr("CPlayer::PlayerRunCommand", CPlayer__PlayerRunCommand); + LogFunAdr("CPlayer::PhysicsSimulate", CPlayer__PhysicsSimulate); } virtual void GetFun(void) const { g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 F2 0F 10 05 ?? ?? ?? ??").GetPtr(CPlayer__EyeAngles); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 8B 03 49 81 C6 ?? ?? ?? ??").FollowNearCallSelf().GetPtr(CPlayer__PlayerRunCommand); + g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 74 06").FollowNearCallSelf().GetPtr(CPlayer__PhysicsSimulate); } virtual void GetVar(void) const { } virtual void GetCon(void) const { } - virtual void Detour(const bool bAttach) const { } + virtual void Detour(const bool bAttach) const; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/game/server/player_command.cpp b/r5dev/game/server/player_command.cpp new file mode 100644 index 00000000..b91c34c5 --- /dev/null +++ b/r5dev/game/server/player_command.cpp @@ -0,0 +1,60 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "engine/server/server.h" +#include "engine/client/client.h" + +#include "player_command.h" + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPlayerMove::CPlayerMove(void) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Runs movement commands for the player +// Input : *player - +// *ucmd - +// *moveHelper - +//----------------------------------------------------------------------------- +void CPlayerMove::StaticRunCommand(CPlayerMove* thisp, CPlayer* player, CUserCmd* ucmd, IMoveHelper* moveHelper) +{ + CClientExtended* const cle = g_pServer->GetClientExtended(player->GetEdict() - 1); + + const float playerCurTime = (player->m_lastUCmdSimulationRemainderTime * TICK_INTERVAL) + player->m_totalExtraClientCmdTimeAttempted; + float playerFrameTime; + + // Always default to clamped UserCmd frame time if this cvar is set + if (player_disallow_negative_frametime->GetBool()) + playerFrameTime = fmaxf(ucmd->frametime, 0.0f); + else + { + if (player->m_bGamePaused) + playerFrameTime = 0.0f; + else + playerFrameTime = TICK_INTERVAL; + + if (ucmd->frametime) + playerFrameTime = ucmd->frametime; + } + + if (sv_clampPlayerFrameTime->GetBool() && player->m_joinFrameTime > ((*g_pflServerFrameTimeBase) + playerframetimekick_margin->GetFloat())) + playerFrameTime = 0.0f; + + const float timeAllowedForProcessing = cle->ConsumeMovementTimeForUserCmdProcessing(playerFrameTime); + + if (!player->IsBot() && (timeAllowedForProcessing < playerFrameTime)) + return; // Don't process this command + + CPlayerMove__RunCommand(thisp, player, ucmd, moveHelper); +} + +void VPlayerMove::Detour(const bool bAttach) const +{ + DetourSetup(&CPlayerMove__RunCommand, &CPlayerMove::StaticRunCommand, bAttach); +} diff --git a/r5dev/game/server/player_command.h b/r5dev/game/server/player_command.h new file mode 100644 index 00000000..2c397243 --- /dev/null +++ b/r5dev/game/server/player_command.h @@ -0,0 +1,67 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#ifndef PLAYER_COMMAND_H +#define PLAYER_COMMAND_H + +#include "edict.h" +#include "game/shared/usercmd.h" +#include "game/server/player.h" + +class IMoveHelper; +class CMoveData; +class CBasePlayer; + +//----------------------------------------------------------------------------- +// Purpose: Server side player movement +//----------------------------------------------------------------------------- +class CPlayerMove +{ +public: + //DECLARE_CLASS_NOBASE(CPlayerMove); + + // Construction/destruction + CPlayerMove(void); + virtual ~CPlayerMove(void) {} + + // Hook statics: + static void StaticRunCommand(CPlayerMove* thisp, CPlayer* player, CUserCmd* ucmd, IMoveHelper* moveHelper); + + // Public interfaces: + // Run a movement command from the player + virtual void RunCommand(CPlayer* player, CUserCmd* ucmd, IMoveHelper* moveHelper) = 0; + +protected: + // Prepare for running movement + virtual void SetupMove(CPlayer* player, CUserCmd* ucmd, CMoveData* move) = 0; + + // Finish movement + virtual void FinishMove(CPlayer* player, CUserCmd* ucmd, CMoveData* move) = 0; + + // Called before and after any movement processing + virtual void StartCommand(CPlayer* player, IMoveHelper* pHelper, CUserCmd* cmd) = 0; +}; + +inline void (*CPlayerMove__RunCommand)(CPlayerMove* thisp, CPlayer* player, CUserCmd* ucmd, IMoveHelper* moveHelper); + +/////////////////////////////////////////////////////////////////////////////// +class VPlayerMove : public IDetour +{ + virtual void GetAdr(void) const + { + LogFunAdr("CPlayerMove::RunCommand", CPlayerMove__RunCommand); + } + virtual void GetFun(void) const + { + g_GameDll.FindPatternSIMD("48 8B C4 55 53 56 57 41 57 48 8D A8 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 44 0F 29 50 ??").GetPtr(CPlayerMove__RunCommand); + } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Detour(const bool bAttach) const; +}; +/////////////////////////////////////////////////////////////////////////////// + +#endif // PLAYER_COMMAND_H From 9236008159b55192c5ebea0ca0380931f1dbeb3f Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:33:36 +0200 Subject: [PATCH 020/113] Engine: light cleanup to CL_MoveEx() Make *chan and commandTick const. --- r5dev/engine/client/cl_main.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/r5dev/engine/client/cl_main.cpp b/r5dev/engine/client/cl_main.cpp index 49e013a6..d3424289 100644 --- a/r5dev/engine/client/cl_main.cpp +++ b/r5dev/engine/client/cl_main.cpp @@ -29,13 +29,12 @@ void CL_MoveEx() if (!v_Host_ShouldRun()) return; - int commandTick = -1; - - if (cl->m_CurrFrameSnapshot) - commandTick = cl->m_CurrFrameSnapshot->m_TickUpdate.m_nCommandTick; + const int commandTick = cl->m_CurrFrameSnapshot + ? cl->m_CurrFrameSnapshot->m_TickUpdate.m_nCommandTick + : -1; bool sendPacket = true; - CNetChan* chan = cl->m_NetChannel; + CNetChan* const chan = cl->m_NetChannel; // Only perform clamping and packeting if the timescale value is default, // else the timescale change won't be handled in the player's movement. From 14e851cc64c9265a4036f5483bf647784b0e1129 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:34:46 +0200 Subject: [PATCH 021/113] Engine: add newly reversed fields to CClient class --- r5dev/engine/client/client.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/r5dev/engine/client/client.h b/r5dev/engine/client/client.h index d3f9baf5..ea9823fb 100644 --- a/r5dev/engine/client/client.h +++ b/r5dev/engine/client/client.h @@ -79,7 +79,11 @@ public: CClientExtended* GetClientExtended(void) const; #endif // !CLIENT_DLL + inline int GetDeltaTick(void) const { return m_nDeltaTick; } inline int GetCommandTick(void) const { return m_nCommandTick; } + inline int GetLastMovementTick() const { return m_LastMovementTick; } + inline int GetSnapshotTick() const { return m_nSnapshotTick; } + inline const char* GetServerName(void) const { return m_szServerName; } inline const char* GetClientName(void) const { return m_szClientName; } @@ -197,14 +201,23 @@ private: bool m_bReceivedPacket; bool m_bLowViolence; bool m_bFullyAuthenticated; - char pad_05A4[24]; + int unk_5A4; + int unknownTick; + float m_fNextMessageTime; + int unk_5B0; + char pad_5B8[8]; PERSISTENCE m_nPersistenceState; char pad_05C0[48]; ServerDataBlock m_DataBlock; char pad_4A3D8[60]; int m_LastMovementTick; char pad_4A418[86]; - char pad_4A46E[80]; + char pad_4A46E[58]; + int unkInt_4A4A8; + int m_nSnapshotTick; + int unkTick_4A4B0; + int unkTick_4A4B4; + int unkInt_4A4B8; }; static_assert(sizeof(CClient) == 0x4A4C0); From e0ee5d9a05d94c1507e49b0665bf0f2492488000 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:35:19 +0200 Subject: [PATCH 022/113] Engine: fix typo in CClientState member variable name Renamed from m_nProcesseedDeltaTick to m_nProcessedDeltaTick. --- r5dev/engine/client/clientstate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/engine/client/clientstate.h b/r5dev/engine/client/clientstate.h index 106272ac..41f879ee 100644 --- a/r5dev/engine/client/clientstate.h +++ b/r5dev/engine/client/clientstate.h @@ -100,7 +100,7 @@ public: _BYTE field_149; int m_nDeltaTick; int m_nStringTableAckTick; - int m_nProcesseedDeltaTick; + int m_nProcessedDeltaTick; int m_nProcessedStringTableAckTick; bool m_bPendingTicksAvailable; _BYTE field_15D; From bc7a26b17090fe50cc5bbc5c0b139d223386a2d5 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:36:13 +0200 Subject: [PATCH 023/113] Game: make GameMode_t an enum class Used as enum class throughout code base, avoids potential name clashes in the future. --- r5dev/public/globalvars_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/public/globalvars_base.h b/r5dev/public/globalvars_base.h index 8f234264..5bfc5e17 100644 --- a/r5dev/public/globalvars_base.h +++ b/r5dev/public/globalvars_base.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -enum GameMode_t +enum class GameMode_t { NO_MODE = 0, MP_MODE, From aba53d7bed2f5a89da7ec4963160f9e7fd1ba70b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:37:13 +0200 Subject: [PATCH 024/113] Engine: add cvar 'sv_lagpushticks' to SDK Will be used for reworking some parts of the lag compensation system in the future. --- r5dev/common/global.cpp | 6 ++++-- r5dev/common/global.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 5c232085..309c853c 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -72,8 +72,9 @@ ConVar* sv_forceChatToTeamOnly = nullptr; ConVar* sv_single_core_dedi = nullptr; -ConVar* sv_maxunlag = nullptr; -ConVar* sv_clockcorrection_msecs = nullptr; +ConVar* sv_maxunlag = nullptr; +ConVar* sv_lagpushticks = nullptr; +ConVar* sv_clockcorrection_msecs = nullptr; ConVar* sv_updaterate_sp = nullptr; ConVar* sv_updaterate_mp = nullptr; @@ -201,6 +202,7 @@ void ConVar_InitShipped(void) sv_stats = g_pCVar->FindVar("sv_stats"); sv_maxunlag = g_pCVar->FindVar("sv_maxunlag"); + sv_lagpushticks = g_pCVar->FindVar("sv_lagpushticks"); sv_clockcorrection_msecs = g_pCVar->FindVar("sv_clockcorrection_msecs"); sv_updaterate_sp = g_pCVar->FindVar("sv_updaterate_sp"); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 746afbd3..5361c41c 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -60,6 +60,7 @@ extern ConVar* sv_forceChatToTeamOnly; extern ConVar* sv_single_core_dedi; extern ConVar* sv_maxunlag; +extern ConVar* sv_lagpushticks; extern ConVar* sv_clockcorrection_msecs; extern ConVar* sv_updaterate_sp; From 19069f039be052cfe7d52f2d37836f63bd0fd4fc Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:53:19 +0200 Subject: [PATCH 025/113] Engine: exec liveapi.cfg on start Allow configuration of the LiveAPI system --- r5dev/engine/host_state.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index 6704a7ff..8b1cc15a 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -407,6 +407,9 @@ void CHostState::LoadConfig(void) const Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec tools/rcon_client_dev.cfg\n", cmd_source_t::kCommandSrcCode); #endif // !DEDICATED } +#ifndef CLIENT_DLL + Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec liveapi.cfg\n", cmd_source_t::kCommandSrcCode); +#endif //!CLIENT_DLL #ifndef DEDICATED Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec bind.cfg\n", cmd_source_t::kCommandSrcCode); #endif // !DEDICATED From 9e0c375a7b06f94651e62a3bcca606ae55e9737a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 21:21:49 +0200 Subject: [PATCH 026/113] Game: group game source files --- r5dev/game/CMakeLists.txt | 77 +++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/r5dev/game/CMakeLists.txt b/r5dev/game/CMakeLists.txt index 6a734004..68105c4f 100644 --- a/r5dev/game/CMakeLists.txt +++ b/r5dev/game/CMakeLists.txt @@ -7,32 +7,56 @@ start_sources() if( ${PROJECT_NAME} STREQUAL "game_shared_static" ) -add_sources( SOURCE_GROUP "Shared" +add_sources( SOURCE_GROUP "AI" "shared/ai_utility_shared.cpp" "shared/ai_utility_shared.h" - "shared/animation.cpp" - "shared/animation.h" - "shared/collisionproperty.cpp" - "shared/collisionproperty.h" +) + +add_sources( SOURCE_GROUP "Entity" "shared/ehandle.h" "shared/entitylist_base.cpp" "shared/entitylist_base.h" - "shared/imovehelper.h" - "shared/playernet_vars.h" +) + +add_sources( SOURCE_GROUP "Prediction" "shared/predictioncopy.h" - "shared/shared_classnames.h" - "shared/shareddefs.h" - "shared/takedamageinfo.h" +) + +add_sources( SOURCE_GROUP "Animation" + "shared/animation.cpp" + "shared/animation.h" +) + +add_sources( SOURCE_GROUP "Collision" + "shared/collisionproperty.cpp" + "shared/collisionproperty.h" +) + +add_sources( SOURCE_GROUP "Network" + "shared/playernet_vars.h" "shared/usercmd.cpp" "shared/usercmd.h" "shared/usermessages.h" +) + +add_sources( SOURCE_GROUP "Utility" + "shared/imovehelper.h" "shared/util_shared.cpp" "shared/util_shared.h" +) + +add_sources( SOURCE_GROUP "Shared" + "shared/shared_classnames.h" + "shared/shareddefs.h" + "shared/takedamageinfo.h" +) + +add_sources( SOURCE_GROUP "Script" "shared/vscript_shared.cpp" "shared/vscript_shared.h" ) -add_sources( SOURCE_GROUP "Shared/Weapon" +add_sources( SOURCE_GROUP "Weapon" "shared/r1/weapon_bolt.cpp" "shared/r1/weapon_bolt.h" ) @@ -116,22 +140,37 @@ endif() if( ${PROJECT_NAME} STREQUAL "client_static" ) -add_sources( SOURCE_GROUP "Client" +add_sources( SOURCE_GROUP "Entity" "client/c_baseentity.cpp" "client/c_baseentity.h" - "client/c_baseplayer.h" "client/cliententitylist.h" - "client/enginesprite.h" - "client/hud.h" +) + +add_sources( SOURCE_GROUP "Player" + "client/c_baseplayer.h" +) + +add_sources( SOURCE_GROUP "Input" "client/input.cpp" "client/input.h" - "client/movehelper_client.cpp" - "client/movehelper_client.h" +) + +add_sources( SOURCE_GROUP "Rendering" + "client/enginesprite.h" + "client/hud.h" "client/spritemodel.cpp" - "client/util_client.cpp" - "client/util_client.h" "client/viewrender.cpp" "client/viewrender.h" +) + +add_sources( SOURCE_GROUP "Utility" + "client/movehelper_client.cpp" + "client/movehelper_client.h" + "client/util_client.cpp" + "client/util_client.h" +) + +add_sources( SOURCE_GROUP "Script" "client/vscript_client.cpp" "client/vscript_client.h" ) From 5a2dfaf03ad5aa71cbb715103ccab5ca3ca3107b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:06:31 +0200 Subject: [PATCH 027/113] Server: add option to respect game state when performing auto reload Can be toggled with the new cvar 'host_autoReloadRespectGameState', and used in combination with the new server script func 'SetAutoReloadState( bool state )'. This makes sure that even when the timer reaches 'host_autoReloadRate', it would wait with the reload until the game itself is finished (which is when SetAutoReloadState( true ) is being called from scripts). --- r5dev/engine/host_state.cpp | 40 ++++++++++++++++++++-------- r5dev/engine/host_state.h | 3 +++ r5dev/engine/server/server.cpp | 6 +++-- r5dev/engine/server/server.h | 9 ++++--- r5dev/game/server/vscript_server.cpp | 18 +++++++++++++ r5dev/game/server/vscript_server.h | 2 ++ 6 files changed, 61 insertions(+), 17 deletions(-) diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index 8b1cc15a..9871e075 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -57,10 +57,10 @@ #include "game/shared/vscript_shared.h" #ifndef CLIENT_DLL -static ConVar sv_pylonVisibility("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", "0 = Offline, 1 = Hidden, 2 = Public."); -static ConVar sv_pylonRefreshRate("sv_pylonRefreshRate", "5.0", FCVAR_DEVELOPMENTONLY, "Pylon host refresh rate (seconds)."); +static ConVar host_statusRefreshRate("host_statusRefreshRate", "0.5", FCVAR_RELEASE, "Host status refresh rate (seconds).", true, 0.f, false, 0.f); -static ConVar sv_autoReloadRate("sv_autoReloadRate", "0", FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null)."); +static ConVar host_autoReloadRate("host_autoReloadRate", "0", FCVAR_RELEASE, "Time in seconds between each auto-reload (disabled if null)."); +static ConVar host_autoReloadRespectGameState("host_autoReloadRespectGameState", "0", FCVAR_RELEASE, "Check the game state before proceeding to auto-reload (don't reload in the middle of a match)."); #endif // !CLIENT_DLL #ifdef DEDICATED @@ -136,6 +136,24 @@ static void HostState_KeepAlive() } #endif // DEDICATED +#ifndef CLIENT_DLL +void HostState_HandleAutoReload() +{ + if (host_autoReloadRate.GetBool()) + { + if (g_ServerGlobalVariables->m_flCurTime > host_autoReloadRate.GetFloat()) + { + // We should respect the game state, and the game isn't finished yet so + // don't reload the server now. + if (host_autoReloadRespectGameState.GetBool() && !g_hostReloadState) + return; + + Cbuf_AddText(Cbuf_GetCurrentPlayer(), "reload\n", cmd_source_t::kCommandSrcCode); + } + } +} +#endif // !CLIENT_DLL + //----------------------------------------------------------------------------- // Purpose: state machine's main processing loop //----------------------------------------------------------------------------- @@ -343,14 +361,10 @@ void CHostState::Think(void) const #endif // DEDICATED bInitialized = true; } - if (sv_autoReloadRate.GetBool()) - { - if (g_ServerGlobalVariables->m_flCurTime > sv_autoReloadRate.GetFloat()) - { - Cbuf_AddText(Cbuf_GetCurrentPlayer(), "reload\n", cmd_source_t::kCommandSrcCode); - } - } - if (statsTimer.GetDurationInProgress().GetSeconds() > sv_statusRefreshRate.GetFloat()) + + HostState_HandleAutoReload(); + + if (statsTimer.GetDurationInProgress().GetSeconds() > host_statusRefreshRate.GetFloat()) { SetConsoleTitleA(Format("%s - %d/%d Players (%s on %s) - %d%% Server CPU (%.3f msec on frame %d)", hostname->GetString(), g_pServer->GetNumClients(), @@ -547,3 +561,7 @@ void VHostState::Detour(const bool bAttach) const /////////////////////////////////////////////////////////////////////////////// CHostState* g_pHostState = nullptr; + +#ifndef CLIENT_DLL +bool g_hostReloadState = false; +#endif // !CLIENT_DLL diff --git a/r5dev/engine/host_state.h b/r5dev/engine/host_state.h index be1dbc0f..77ced4c7 100644 --- a/r5dev/engine/host_state.h +++ b/r5dev/engine/host_state.h @@ -58,6 +58,9 @@ inline void(*v_HostState_ChangeLevelMP)(char const* pNewLevel, char const* pLand /////////////////////////////////////////////////////////////////////////////// extern CHostState* g_pHostState; +#ifndef CLIENT_DLL +extern bool g_hostReloadState; +#endif // !CLIENT_DLL /////////////////////////////////////////////////////////////////////////////// class VHostState : public IDetour diff --git a/r5dev/engine/server/server.cpp b/r5dev/engine/server/server.cpp index b5efc531..2645da8d 100644 --- a/r5dev/engine/server/server.cpp +++ b/r5dev/engine/server/server.cpp @@ -25,10 +25,12 @@ // Console variables //--------------------------------------------------------------------------------- ConVar sv_showconnecting("sv_showconnecting", "1", FCVAR_RELEASE, "Logs information about the connecting client to the console"); -ConVar sv_globalBanlist("sv_globalBanlist", "1", FCVAR_RELEASE, "Determines whether or not to use the global banned list.", false, 0.f, false, 0.f, "0 = Disable, 1 = Enable."); +ConVar sv_pylonVisibility("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", "0 = Offline, 1 = Hidden, 2 = Public."); +ConVar sv_pylonRefreshRate("sv_pylonRefreshRate", "5.0", FCVAR_DEVELOPMENTONLY, "Pylon host refresh rate (seconds)."); + +ConVar sv_globalBanlist("sv_globalBanlist", "1", FCVAR_RELEASE, "Determines whether or not to use the global banned list.", false, 0.f, false, 0.f, "0 = Disable, 1 = Enable."); ConVar sv_banlistRefreshRate("sv_banlistRefreshRate", "30.0", FCVAR_DEVELOPMENTONLY, "Banned list refresh rate (seconds).", true, 1.f, false, 0.f); -ConVar sv_statusRefreshRate("sv_statusRefreshRate", "0.5", FCVAR_RELEASE, "Server status refresh rate (seconds).", true, 0.f, false, 0.f); static ConVar sv_validatePersonaName("sv_validatePersonaName", "1", FCVAR_RELEASE, "Validate the client's textual persona name on connect."); static ConVar sv_minPersonaNameLength("sv_minPersonaNameLength", "4", FCVAR_RELEASE, "The minimum length of the client's textual persona name.", true, 0.f, false, 0.f); diff --git a/r5dev/engine/server/server.h b/r5dev/engine/server/server.h index cc05ac46..3f976c6d 100644 --- a/r5dev/engine/server/server.h +++ b/r5dev/engine/server/server.h @@ -111,13 +111,14 @@ static_assert(sizeof(CServer) == 0x25264C0); extern CServer* g_pServer; +extern ConVar sv_showconnecting; + +extern ConVar sv_pylonVisibility; +extern ConVar sv_pylonRefreshRate; + extern ConVar sv_globalBanlist; extern ConVar sv_banlistRefreshRate; -extern ConVar sv_statusRefreshRate; - -extern ConVar sv_showconnecting; - /* ==== CSERVER ========================================================================================================================================================= */ inline void(*CServer__FrameJob)(double flFrameTime, bool bRunOverlays, bool bUpdateFrame); inline void(*CServer__RunFrame)(CServer* pServer); diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 2123d4d7..9120f395 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -83,6 +83,7 @@ namespace VScriptCode SCRIPT_CHECK_AND_RETURN(v, SQ_OK); } + //----------------------------------------------------------------------------- // Purpose: shuts the server down and disconnects all clients //----------------------------------------------------------------------------- @@ -94,6 +95,21 @@ namespace VScriptCode SCRIPT_CHECK_AND_RETURN(v, SQ_OK); } + //----------------------------------------------------------------------------- + // Purpose: sets whether the server could auto reload at this time (e.g. if + // server admin has host_autoReloadRate AND host_autoReloadRespectGameState + // set, and its time to auto reload, but the match hasn't finished yet, wait + // until this is set to proceed the reload of the server + //----------------------------------------------------------------------------- + SQRESULT SetAutoReloadState(HSQUIRRELVM v) + { + SQBool state = false; + sq_getbool(v, 2, &state); + + g_hostReloadState = state; + SCRIPT_CHECK_AND_RETURN(v, SQ_OK); + } + //----------------------------------------------------------------------------- // Purpose: kicks a player by given name //----------------------------------------------------------------------------- @@ -282,6 +298,8 @@ void Script_RegisterCoreServerFunctions(CSquirrelVM* s) DEFINE_SERVER_SCRIPTFUNC_NAMED(s, CreateServer, "Starts server with the specified settings", "void", "string, string, string, string, int"); DEFINE_SERVER_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local server down", "void", ""); + + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, SetAutoReloadState, "Set whether we can auto-reload the server", "void", "bool"); } //--------------------------------------------------------------------------------- diff --git a/r5dev/game/server/vscript_server.h b/r5dev/game/server/vscript_server.h index d75cd394..4bc7a82f 100644 --- a/r5dev/game/server/vscript_server.h +++ b/r5dev/game/server/vscript_server.h @@ -9,6 +9,8 @@ namespace VScriptCode SQRESULT CreateServer(HSQUIRRELVM v); SQRESULT DestroyServer(HSQUIRRELVM v); + SQRESULT SetAutoReloadState(HSQUIRRELVM v); + SQRESULT KickPlayerByName(HSQUIRRELVM v); SQRESULT KickPlayerById(HSQUIRRELVM v); SQRESULT BanPlayerByName(HSQUIRRELVM v); From 2c5e272c305d73c65b5332d84ac82f0c0cda41fb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:09:20 +0200 Subject: [PATCH 028/113] Tier0: bump sigcache version to force full rebuild Many signatures have changed, force a full rebuild for the next patch to significantly speed up startup times. --- r5dev/public/tier0/sigcache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/public/tier0/sigcache.h b/r5dev/public/tier0/sigcache.h index 67ff711a..13086c31 100644 --- a/r5dev/public/tier0/sigcache.h +++ b/r5dev/public/tier0/sigcache.h @@ -7,7 +7,7 @@ #define SIGDB_DICT_SIZE 20 #define SIGDB_MAJOR_VERSION 0x2 // Increment when library changes are made. -#define SIGDB_MINOR_VERSION 0xA // Increment when SDK updates are released. +#define SIGDB_MINOR_VERSION 0xB // Increment when SDK updates are released. class CSigCache { From 890ffa923e511c5cb30f40541341a29924e6dc50 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:35:07 +0200 Subject: [PATCH 029/113] Launcher: light overhaul and use KeyValues class Reworked some of the code to make globals static and used KeyValues class to parse VDF files instead. --- license/thirdpartylegalnotices.txt | 76 +- r5dev/public/utility/vdf_parser.h | 711 ------------------ r5dev/sdklauncher/CMakeLists.txt | 3 + r5dev/sdklauncher/basepanel.cpp | 271 +++---- r5dev/sdklauncher/basepanel.h | 6 +- r5dev/sdklauncher/sdklauncher.cpp | 36 +- r5dev/sdklauncher/sdklauncher.h | 20 +- r5dev/sdklauncher/sdklauncher_const.h | 2 +- .../thirdparty/cppnet/cppkore/Application.cpp | 4 +- r5dev/thirdparty/cppnet/cppkore/Application.h | 2 +- 10 files changed, 191 insertions(+), 940 deletions(-) delete mode 100644 r5dev/public/utility/vdf_parser.h diff --git a/license/thirdpartylegalnotices.txt b/license/thirdpartylegalnotices.txt index 3f00d2c7..f4cd422e 100644 --- a/license/thirdpartylegalnotices.txt +++ b/license/thirdpartylegalnotices.txt @@ -70,29 +70,6 @@ NVIDIA NvAPI // the above Disclaimer (as applicable) and U.S. Government End Users Notice. //////////////////////////////////////////////////////////////////////////// -************************************************************************************ -Recast & Detour -************************************************************************************ - - // Copyright (c) 2009 Mikko Mononen memon@inside.org - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - //////////////////////////////////////////////////////////////////////////// - ************************************************************************************ Google protocol buffers ************************************************************************************ @@ -131,6 +108,29 @@ Google protocol buffers // support library is itself covered by the above license. //////////////////////////////////////////////////////////////////////////// +************************************************************************************ +Recast & Detour +************************************************************************************ + + // Copyright (c) 2009 Mikko Mononen memon@inside.org + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + //////////////////////////////////////////////////////////////////////////// + ************************************************************************************ Dear ImGui ************************************************************************************ @@ -299,33 +299,6 @@ Format {fmt} // without including the above copyright and permission notices. //////////////////////////////////////////////////////////////////////////// -************************************************************************************ -VDF Parser -************************************************************************************ - - // The MIT License (MIT) - // - // Copyright (c) Matthias Moeller 2016 m_moeller@live.de - // - // Permission is hereby granted, free of charge, to any person obtaining a copy - // of this software and associated documentation files (the "Software"), to deal - // in the Software without restriction, including without limitation the rights - // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - // copies of the Software, and to permit persons to whom the Software is - // furnished to do so, subject to the following conditions: - // - // The above copyright notice and this permission notice shall be included in all - // copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - // SOFTWARE. - //////////////////////////////////////////////////////////////////////////// - ************************************************************************************ RapidJSON ************************************************************************************ @@ -642,7 +615,7 @@ EAThread (EA WebKit) // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //-------------------------------------------------------------------------- - // + // // Additional licenses also apply to this software package as detailed below. // //-------------------------------------------------------------------------- @@ -788,6 +761,7 @@ LZHAM // THE SOFTWARE. //////////////////////////////////////////////////////////////////////////// + ************************************************************************************ CRC32 ************************************************************************************ diff --git a/r5dev/public/utility/vdf_parser.h b/r5dev/public/utility/vdf_parser.h deleted file mode 100644 index 13d6f7ad..00000000 --- a/r5dev/public/utility/vdf_parser.h +++ /dev/null @@ -1,711 +0,0 @@ -//MIT License -// -//Copyright(c) 2016 Matthias Moeller -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files(the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions : -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#ifndef __TYTI_STEAM_VDF_PARSER_H__ -#define __TYTI_STEAM_VDF_PARSER_H__ -#pragma warning( disable : 4996 ) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -//for wstring support -#include -#include - -// internal -#include - -//VS < 2015 has only partial C++11 support -#if defined(_MSC_VER) && _MSC_VER < 1900 -#ifndef CONSTEXPR -#define CONSTEXPR -#endif - -#ifndef NOEXCEPT -#define NOEXCEPT -#endif -#else -#ifndef CONSTEXPR -#define CONSTEXPR constexpr -#define TYTI_UNDEF_CONSTEXPR -#endif - -#ifndef NOEXCEPT -#define NOEXCEPT noexcept -#define TYTI_UNDEF_NOEXCEPT -#endif - -#endif -namespace vdf -{ - namespace detail - { - /////////////////////////////////////////////////////////////////////////// - // Helper functions selecting the right encoding (char/wchar_T) - /////////////////////////////////////////////////////////////////////////// - - template - struct literal_macro_help - { - static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT - { - return c; - } - static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT - { - return c; - } - }; - - template <> - struct literal_macro_help - { - static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT - { - return wc; - } - static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT - { - return wc; - } - }; -#define TYTI_L(type, text) vdf::detail::literal_macro_help::result(text, L##text) - - inline std::string string_converter(const std::string& w) NOEXCEPT - { - return w; - } - - // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert - // from cppreference - template - struct deletable_facet : Facet - { - template - deletable_facet(Args &&... args) : Facet(std::forward(args)...) {} - ~deletable_facet() {} - }; - - inline std::string string_converter(const std::wstring& w) //todo: use us-locale - { - std::wstring_convert>> conv1; - return conv1.to_bytes(w); - } - - /////////////////////////////////////////////////////////////////////////// - // Writer helper functions - /////////////////////////////////////////////////////////////////////////// - - template - class tabs - { - const size_t t; - - public: - explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} - std::basic_string print() const { return std::basic_string(t, TYTI_L(charT, '\t')); } - inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT - { - return tabs(t + i); - } - }; - - template - oStreamT& operator<<(oStreamT& s, const tabs t) - { - s << t.print(); - return s; - } - } // end namespace detail - - /////////////////////////////////////////////////////////////////////////// - // Interface - /////////////////////////////////////////////////////////////////////////// - - /// custom objects and their corresponding write functions - - /// basic object node. Every object has a name and can contains attributes saved as key_value pairs or childrens - template - struct basic_object - { - typedef CharT char_type; - std::basic_string name; - std::unordered_map, std::basic_string> attribs; - std::unordered_map, std::shared_ptr>> childs; - - void add_attribute(std::basic_string key, std::basic_string value) - { - attribs.emplace(std::move(key), std::move(value)); - } - void add_child(std::unique_ptr> child) - { - std::shared_ptr> obj{ child.release() }; - childs.emplace(obj->name, obj); - } - void set_name(std::basic_string n) - { - name = std::move(n); - } - }; - - template - struct basic_multikey_object - { - typedef CharT char_type; - std::basic_string name; - std::unordered_multimap, std::basic_string> attribs; - std::unordered_multimap, std::shared_ptr>> childs; - - void add_attribute(std::basic_string key, std::basic_string value) - { - attribs.emplace(std::move(key), std::move(value)); - } - void add_child(std::unique_ptr> child) - { - std::shared_ptr> obj{ child.release() }; - childs.emplace(obj->name, obj); - } - void set_name(std::basic_string n) - { - name = std::move(n); - } - }; - - typedef basic_object object; - typedef basic_object wobject; - typedef basic_multikey_object multikey_object; - typedef basic_multikey_object wmultikey_object; - - struct Options - { - bool strip_escape_symbols; - bool ignore_all_platform_conditionals; - bool ignore_includes; - - Options() : strip_escape_symbols(true), ignore_all_platform_conditionals(false), ignore_includes(false) {} - }; - - //forward decls - template - OutputT read(iStreamT& inStream, const Options& opt = Options{}); - - /** \brief writes given object tree in vdf format to given stream. - Output is prettyfied, using tabs - */ - template - void write(oStreamT& s, const T& r, - const detail::tabs tab = detail::tabs(0)) - { - typedef typename oStreamT::char_type charT; - using namespace detail; - s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab << TYTI_L(charT, "{\n"); - for (const auto& i : r.attribs) - s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") << i.second << TYTI_L(charT, "\"\n"); - for (const auto& i : r.childs) - if (i.second) - write(s, *i.second, tab + 1); - s << tab << TYTI_L(charT, "}\n"); - } - - namespace detail - { - template - std::basic_string read_file(iStreamT& inStream) - { - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str; - inStream.seekg(0, std::ios::end); - str.resize(static_cast(inStream.tellg())); - if (str.empty()) - return str; - - inStream.seekg(0, std::ios::beg); - inStream.read(&str[0], str.size()); - return str; - } - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is malformed, parser will read the file until no longer possible. - @param first begin iterator - @param end end iterator - @param exclude_files list of files which cant be included anymore. - prevents circular includes - - can throw: - - "std::runtime_error" if a parsing error occured - - "std::bad_alloc" if not enough memory could be allocated - */ - template - std::vector> read_internal(IterT first, const IterT last, - std::unordered_set::value_type>>& exclude_files, - const Options& opt) - { - static_assert(std::is_default_constructible::value, - "Output Type must be default constructible (provide constructor without arguments)"); - static_assert(std::is_move_constructible::value, - "Output Type must be move constructible"); - - typedef typename std::iterator_traits::value_type charT; - - const std::basic_string comment_end_str = TYTI_L(charT, "*/"); - const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); - -#ifdef WIN32 - std::function&)> is_platform_str = [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); - }; -#elif __APPLE__ - // WIN32 stands for pc in general - std::function&)> is_platform_str = [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$OSX"); - }; - -#elif __linux__ - // WIN32 stands for pc in general - std::function&)> is_platform_str = [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$LINUX"); - }; -#else - std::function&)> is_platform_str = [](const std::basic_string& in) { - return false; - }; -#endif - - if (opt.ignore_all_platform_conditionals) - is_platform_str = [](const std::basic_string&) { - return false; - }; - - // function for skipping a comment block - // iter: itterate position past a '/' character - auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { - ++iter; - if (iter != last) - { - if (*iter == TYTI_L(charT, '/')) - { - // line comment, skip whole line - iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); - } - - if (*iter == '*') - { - // block comment, skip until next occurance of "*\" - iter = std::search(iter + 1, last, std::begin(comment_end_str), std::end(comment_end_str)); - iter += 2; - } - } - return iter; - }; - - auto end_quote = [](IterT iter, const IterT& last) -> IterT { - const auto begin = iter; - auto last_esc = iter; - do - { - ++iter; - iter = std::find(iter, last, TYTI_L(charT, '\"')); - if (iter == last) - break; - - last_esc = std::prev(iter); - while (last_esc != begin && *last_esc == '\\') - --last_esc; - } while (!(std::distance(last_esc, iter) % 2)); - if (iter == last) - throw std::runtime_error{ "Quote was opened but never closed" }; - return iter; - }; - - auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { - const auto begin = iter; - auto last_esc = iter; - do - { - ++iter; - iter = std::find_first_of(iter, last, std::begin(whitespaces), std::end(whitespaces)); - if (iter == last) - break; - - last_esc = std::prev(iter); - while (last_esc != begin && *last_esc == '\\') - --last_esc; - } while (!(std::distance(last_esc, iter) % 2)); - //if (iter == last) - // throw std::runtime_error{ "Word wasn't properly ended" }; - return iter; - }; - - auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { - iter = std::find_if_not(iter, last, [&whitespaces](charT c) { - // return true if whitespace - return std::any_of(std::begin(whitespaces), std::end(whitespaces), [c](charT pc) { return pc == c; }); - }); - return iter; - }; - - std::function&)> strip_escape_symbols = [](std::basic_string& s) { - auto quote_searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\""), pos); }; - auto p = quote_searcher(0); - while (p != s.npos) - { - s.replace(p, 2, TYTI_L(charT, "\"")); - p = quote_searcher(p); - } - auto searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\\"), pos); }; - p = searcher(0); - while (p != s.npos) - { - s.replace(p, 2, TYTI_L(charT, "\\")); - p = searcher(p); - } - }; - - if (!opt.strip_escape_symbols) - strip_escape_symbols = [](std::basic_string&) {}; - - auto conditional_fullfilled = [&skip_whitespaces, &is_platform_str](IterT& iter, const IterT& last) { - iter = skip_whitespaces(iter, last); - if (*iter == '[') - { - ++iter; - const auto end = std::find(iter, last, ']'); - const bool negate = *iter == '!'; - if (negate) - ++iter; - auto conditional = std::basic_string(iter, end); - - const bool is_platform = is_platform_str(conditional); - iter = end + 1; - - return static_cast(is_platform ^ negate); - } - return true; - }; - - //read header - // first, quoted name - std::unique_ptr curObj = nullptr; - std::vector> roots; - std::stack> lvls; - auto curIter = first; - - while (curIter != last && *curIter != '\0') - { - //find first starting attrib/child, or ending - curIter = skip_whitespaces(curIter, last); - if (curIter == last || *curIter == '\0') - break; - if (*curIter == TYTI_L(charT, '/')) - { - curIter = skip_comments(curIter, last); - } - else if (*curIter != TYTI_L(charT, '}')) - { - - // get key - const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); - if (*curIter == TYTI_L(charT, '\"')) - ++curIter; - std::basic_string key(curIter, keyEnd); - strip_escape_symbols(key); - curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); - - curIter = skip_whitespaces(curIter, last); - - auto conditional_key = conditional_fullfilled(curIter, last); - if (!conditional_key) - continue; - - while (*curIter == TYTI_L(charT, '/')) - { - - curIter = skip_comments(curIter, last); - if (curIter == last || *curIter == '}') - throw std::runtime_error{ "Key declared without value" }; - curIter = skip_whitespaces(curIter, last); - if (curIter == last || *curIter == '}') - throw std::runtime_error{ "Key declared without value" }; - } - // get value - if (*curIter != '{') - { - const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); - if (*curIter == TYTI_L(charT, '\"')) - ++curIter; - - auto value = std::basic_string(curIter, valueEnd); - strip_escape_symbols(value); - curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); - - auto conditional_value = conditional_fullfilled(curIter, last); - if (!conditional_value) - continue; - - // process value - if (curObj && key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) - { - curObj->add_attribute(std::move(key), std::move(value)); - } - else - { - if (!opt.ignore_includes && exclude_files.find(value) == exclude_files.end()) - { - exclude_files.insert(value); - std::basic_ifstream i(detail::string_converter(value)); - auto str = read_file(i); - auto file_objs = read_internal(str.begin(), str.end(), exclude_files, opt); - for (auto& n : file_objs) - { - if (curObj) - curObj->add_child(std::move(n)); - else - roots.push_back(std::move(n)); - } - exclude_files.erase(value); - } - } - } - else if (*curIter == '{') - { - if (curObj) - lvls.push(std::move(curObj)); - curObj = std::make_unique(); - curObj->set_name(std::move(key)); - ++curIter; - } - } - //end of new object - else if (*curIter == TYTI_L(charT, '}')) - { - if (!lvls.empty()) - { - //get object before - std::unique_ptr prev{ std::move(lvls.top()) }; - lvls.pop(); - - // add finished obj to obj before and release it from processing - prev->add_child(std::move(curObj)); - curObj = std::move(prev); - } - else - { - roots.push_back(std::move(curObj)); - curObj.reset(); - } - ++curIter; - } - } - return roots; - } - - } // namespace detail - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is malformed, parser will read the file until no longer possible. - @param first begin iterator - @param end end iterator - - can thow: - - "std::runtime_error" if a parsing error occurred - - "std::bad_alloc" if not enough memory coup be allocated - */ - template - OutputT read(IterT first, const IterT last, const Options& opt = Options{}) - { - auto exclude_files = std::unordered_set::value_type>>{}; - auto roots = detail::read_internal(first, last, exclude_files, opt); - - OutputT result; - if (roots.size() > 1) - { - for (auto& i : roots) - result.add_child(std::move(i)); - } - else if (roots.size() == 1) - result = std::move(*roots[0]); - - return result; - } - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is malformed, parser will read the file until no longer possible. - @param first begin iterator - @param end end iterator - @param ec output bool. 0 if ok, otherwise, holds an system error code - - Possible error codes: - std::errc::protocol_error: file is malformed - std::errc::not_enough_memory: not enough space - std::errc::invalid_argument: iterators throws e.g. out of range - */ - template - OutputT read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT - - { - ec.clear(); - OutputT r{}; - try - { - r = read(first, last, opt); - } - catch (std::runtime_error&) - { - ec = std::make_error_code(std::errc::protocol_error); - } - catch (std::bad_alloc&) - { - ec = std::make_error_code(std::errc::not_enough_memory); - } - catch (...) - { - ec = std::make_error_code(std::errc::invalid_argument); - } - return r; - } - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is malformed, parser will read the file until no longer possible. - @param first begin iterator - @param end end iterator - @param ok output bool. true, if parser successed, false, if parser failed - */ - template - OutputT read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT - { - std::error_code ec; - auto r = read(first, last, ec, opt); - if (ok) - *ok = !ec; - return r; - } - - template - inline auto read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT -> basic_object::value_type> - { - return read::value_type>>(first, last, ok, opt); - } - - template - inline auto read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT - -> basic_object::value_type> - { - return read::value_type>>(first, last, ec, opt); - } - - template - inline auto read(IterT first, const IterT last, const Options& opt = Options{}) - -> basic_object::value_type> - { - return read::value_type>>(first, last, opt); - } - - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. - throws "std::bad_alloc" if file buffer could not be allocated - */ - template - OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) - { - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str = detail::read_file(inStream); - - // parse it - return read(str.begin(), str.end(), ec, opt); - } - - template - inline basic_object read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) - { - return read>(inStream, ec, opt); - } - - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. - throws "std::bad_alloc" if file buffer could not be allocated - ok == false, if a parsing error occured - */ - template - OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) - { - std::error_code ec; - const auto r = read(inStream, ec, opt); - if (ok) - *ok = !ec; - return r; - } - - template - inline basic_object read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) - { - return read>(inStream, ok, opt); - } - - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. - throws "std::bad_alloc" if file buffer could not be allocated - throws "std::runtime_error" if a parsing error occured - */ - template - OutputT read(iStreamT& inStream, const Options& opt) - { - - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str = detail::read_file(inStream); - // parse it - return read(str.begin(), str.end(), opt); - } - - template - inline basic_object read(iStreamT& inStream, const Options& opt = Options{}) - { - return read>(inStream, opt); - } - -} // namespace vdf - -#ifndef TYTI_NO_L_UNDEF -#undef TYTI_L -#endif - -#ifdef TYTI_UNDEF_CONSTEXPR -#undef CONSTEXPR -#undef TYTI_NO_L_UNDEF -#endif - -#ifdef TYTI_UNDEF_NOTHROW -#undef NOTHROW -#undef TYTI_UNDEF_NOTHROW -#endif - -#endif //__TYTI_STEAM_VDF_PARSER_H__ diff --git a/r5dev/sdklauncher/CMakeLists.txt b/r5dev/sdklauncher/CMakeLists.txt index f5701928..be513530 100644 --- a/r5dev/sdklauncher/CMakeLists.txt +++ b/r5dev/sdklauncher/CMakeLists.txt @@ -38,6 +38,9 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "tier0" "tier1" + "filesystem_std" + "vstdlib" + "libdetours" "libcppkore" "libspdlog" diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index 4c3ae735..e99abdcd 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -6,7 +6,10 @@ #include "basepanel.h" #include "sdklauncher.h" #include "mathlib/bits.h" -#include "utility/vdf_parser.h" +#include "vstdlib/keyvaluessystem.h" +#include "filesystem/filesystem_std.h" + +extern CFileSystem_Stdio* FileSystem(); //----------------------------------------------------------------------------- // Purpose: creates the surface layout @@ -494,6 +497,8 @@ void CSurface::Init() this->PerformLayout(); // END DESIGNER CODE + + this->Setup(); } //----------------------------------------------------------------------------- @@ -522,97 +527,60 @@ void CSurface::Setup() //----------------------------------------------------------------------------- void CSurface::LoadSettings() { - const fs::path settingsPath(Format("platform/%s/%s", SDK_SYSTEM_CFG_PATH, LAUNCHER_SETTING_FILE)); - if (!fs::exists(settingsPath)) + CUtlString settingsPath; + settingsPath.Format("platform/" SDK_SYSTEM_CFG_PATH "%s", LAUNCHER_SETTING_FILE); + + const char* pSettingsPath = settingsPath.String(); + + if (!FileSystem()->FileExists(pSettingsPath)) + return; + + KeyValues kv("LauncherSettings"); + + if (!kv.LoadFromFile(FileSystem(), pSettingsPath, nullptr)) { + printf("%s: Failed to parse VDF file: '%s'\n", __FUNCTION__, pSettingsPath); return; } - bool success{ }; - std::ifstream fileStream(settingsPath, fstream::in); - vdf::object vRoot = vdf::read(fileStream, &success); + const int settingsVersion = kv.GetInt("version", -1); - if (!success) - { - printf("%s: Failed to parse VDF file: '%s'\n", __FUNCTION__, - settingsPath.u8string().c_str()); + if (settingsVersion != SDK_LAUNCHER_VERSION) return; - } - try + KeyValues* sv = kv.FindKey("vars"); + + if (!sv) { - string& attributeView = vRoot.attribs["version"]; - - int settingsVersion = atoi(attributeView.c_str()); - if (settingsVersion != SDK_LAUNCHER_VERSION) - return; - - vdf::object* pSubKey = vRoot.childs["vars"].get(); - if (!pSubKey) - return; - - // Game. - attributeView = pSubKey->attribs["playlistsFile"]; - this->m_PlaylistFileTextBox->SetText(attributeView.data()); - - attributeView = pSubKey->attribs["enableCheats"]; - this->m_CheatsToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["enableDeveloper"]; - this->m_DeveloperToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["enableConsole"]; - this->m_ConsoleToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["colorConsole"]; - this->m_ColorConsoleToggle->SetChecked(attributeView != "0"); - - // Engine. - attributeView = pSubKey->attribs["reservedCoreCount"]; - this->m_ReservedCoresTextBox->SetText(attributeView.data()); - - attributeView = pSubKey->attribs["workerThreadCount"]; - this->m_WorkerThreadsTextBox->SetText(attributeView.data()); - - attributeView = pSubKey->attribs["processorAffinity"]; - this->m_ProcessorAffinityTextBox->SetText(attributeView.data()); - - attributeView = pSubKey->attribs["noAsync"]; // No-async - this->m_NoAsyncJobsToggle->SetChecked(attributeView != "0"); - - // Network. - attributeView = pSubKey->attribs["encryptPackets"]; - this->m_NetEncryptionToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["randomNetKey"]; - this->m_NetRandomKeyToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["queuedPackets"]; - this->m_QueuedPacketThread->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["noTimeOut"]; - this->m_NoTimeOutToggle->SetChecked(attributeView != "0"); - - // Video. - attributeView = pSubKey->attribs["windowed"]; - this->m_WindowedToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["borderless"]; - this->m_NoBorderToggle->SetChecked(attributeView != "0"); - - attributeView = pSubKey->attribs["maxFPS"]; - this->m_FpsTextBox->SetText(attributeView.data()); - - attributeView = pSubKey->attribs["width"]; - this->m_WidthTextBox->SetText(attributeView.data()); - - attributeView = pSubKey->attribs["height"]; - this->m_HeightTextBox->SetText(attributeView.data()); - } - catch (const std::exception& e) - { - printf("%s: Exception while parsing VDF file: %s\n", __FUNCTION__, e.what()); + printf("%s: VDF file '%s' lacks subkey: '%s'\n", __FUNCTION__, pSettingsPath, "vars"); + return; // No settings to apply } + + // Game. + this->m_PlaylistFileTextBox->SetText(sv->GetString("playlistsFile")); + this->m_CheatsToggle->SetChecked(sv->GetBool("enableCheats")); + this->m_DeveloperToggle->SetChecked(sv->GetBool("enableDeveloper")); + this->m_ConsoleToggle->SetChecked(sv->GetBool("enableConsole")); + this->m_ColorConsoleToggle->SetChecked(sv->GetBool("colorConsole")); + + // Engine. + this->m_ReservedCoresTextBox->SetText(sv->GetString("reservedCoreCount", "-1")); + this->m_WorkerThreadsTextBox->SetText(sv->GetString("workerThreadCount", "-1")); + this->m_ProcessorAffinityTextBox->SetText(sv->GetString("processorAffinity", "0")); + this->m_NoAsyncJobsToggle->SetChecked(sv->GetBool("noAsync")); + + // Network. + this->m_NetEncryptionToggle->SetChecked(sv->GetBool("encryptPackets", true)); + this->m_NetRandomKeyToggle->SetChecked(sv->GetBool("randomNetKey", true)); + this->m_QueuedPacketThread->SetChecked(sv->GetBool("queuedPackets", true)); + this->m_NoTimeOutToggle->SetChecked(sv->GetBool("noTimeOut")); + + // Video. + this->m_WindowedToggle->SetChecked(sv->GetBool("windowed")); + this->m_NoBorderToggle->SetChecked(sv->GetBool("borderless")); + this->m_FpsTextBox->SetText(sv->GetString("maxFPS", "-1")); + this->m_WidthTextBox->SetText(sv->GetString("width")); + this->m_HeightTextBox->SetText(sv->GetString("height")); } //----------------------------------------------------------------------------- @@ -620,60 +588,69 @@ void CSurface::LoadSettings() //----------------------------------------------------------------------------- void CSurface::SaveSettings() { - const fs::path settingsPath(Format("platform/%s/%s", SDK_SYSTEM_CFG_PATH, LAUNCHER_SETTING_FILE)); - const fs::path parentPath = settingsPath.parent_path(); + CUtlString settingsPath; + settingsPath.Format("platform/" SDK_SYSTEM_CFG_PATH "%s", LAUNCHER_SETTING_FILE); - if (!fs::exists(parentPath) && !fs::create_directories(parentPath)) + CUtlString settingsDir = settingsPath.DirName(); + + const char* pSettingsPath = settingsPath.String(); + const char* pSettingsDir = settingsDir.String(); + + FileSystem()->CreateDirHierarchy(pSettingsDir); + + if (!FileSystem()->IsDirectory(pSettingsDir)) { - printf("%s: Failed to create directory: '%s'\n", __FUNCTION__, - parentPath.relative_path().u8string().c_str()); + printf("%s: Failed to create directory: '%s'\n", __FUNCTION__, pSettingsPath); return; } - std::ofstream fileStream(settingsPath, fstream::out); - if (!fileStream) + KeyValues kv("LauncherSettings"); + kv.SetInt("version", SDK_LAUNCHER_VERSION); + + KeyValues* sv = new KeyValues("vars"); + + if (!sv) { - printf("%s: Failed to create VDF file: '%s'\n", __FUNCTION__, - settingsPath.u8string().c_str()); - return; + printf("%s: Failed to allocate subkey: '%s'\n", __FUNCTION__, "vars"); + return; // No settings to apply } - vdf::object vRoot; - vRoot.set_name("LauncherSettings"); - vRoot.add_attribute("version", std::to_string(SDK_LAUNCHER_VERSION)); - - vdf::object* vVars = new vdf::object(); - vVars->set_name("vars"); + kv.AddSubKey(sv); // Game. - vVars->add_attribute("playlistsFile", GetControlValue(this->m_PlaylistFileTextBox)); - vVars->add_attribute("enableCheats", GetControlValue(this->m_CheatsToggle)); - vVars->add_attribute("enableDeveloper", GetControlValue(this->m_DeveloperToggle)); - vVars->add_attribute("enableConsole", GetControlValue(this->m_ConsoleToggle)); - vVars->add_attribute("colorConsole", GetControlValue(this->m_ColorConsoleToggle)); + sv->SetString("playlistsFile", GetControlValue(this->m_PlaylistFileTextBox)); + sv->SetBool("enableCheats", this->m_CheatsToggle->Checked()); + sv->SetBool("enableDeveloper", this->m_DeveloperToggle->Checked()); + sv->SetBool("enableConsole", this->m_ConsoleToggle->Checked()); + sv->SetBool("colorConsole", this->m_ColorConsoleToggle->Checked()); // Engine. - vVars->add_attribute("reservedCoreCount", GetControlValue(this->m_ReservedCoresTextBox)); - vVars->add_attribute("workerThreadCount", GetControlValue(this->m_WorkerThreadsTextBox)); - vVars->add_attribute("processorAffinity", GetControlValue(this->m_ProcessorAffinityTextBox)); - vVars->add_attribute("noAsync", GetControlValue(this->m_NoAsyncJobsToggle)); + sv->SetString("reservedCoreCount", GetControlValue(this->m_ReservedCoresTextBox)); + sv->SetString("workerThreadCount", GetControlValue(this->m_WorkerThreadsTextBox)); + sv->SetString("processorAffinity", GetControlValue(this->m_ProcessorAffinityTextBox)); + sv->SetBool("noAsync", this->m_NoAsyncJobsToggle->Checked()); // Network. - vVars->add_attribute("encryptPackets", GetControlValue(this->m_NetEncryptionToggle)); - vVars->add_attribute("randomNetKey", GetControlValue(this->m_NetRandomKeyToggle)); - vVars->add_attribute("queuedPackets", GetControlValue(this->m_QueuedPacketThread)); - vVars->add_attribute("noTimeOut", GetControlValue(this->m_NoTimeOutToggle)); + sv->SetBool("encryptPackets", this->m_NetEncryptionToggle->Checked()); + sv->SetBool("randomNetKey", this->m_NetRandomKeyToggle->Checked()); + sv->SetBool("queuedPackets", this->m_QueuedPacketThread->Checked()); + sv->SetBool("noTimeOut", this->m_NoTimeOutToggle->Checked()); // Video. - vVars->add_attribute("windowed", GetControlValue(this->m_WindowedToggle)); - vVars->add_attribute("borderless", GetControlValue(this->m_NoBorderToggle)); - vVars->add_attribute("maxFPS", GetControlValue(this->m_FpsTextBox)); - vVars->add_attribute("width", GetControlValue(this->m_WidthTextBox)); - vVars->add_attribute("height", GetControlValue(this->m_HeightTextBox)); + sv->SetBool("windowed", this->m_WindowedToggle->Checked()); + sv->SetBool("borderless", this->m_NoBorderToggle->Checked()); + sv->SetString("maxFPS", GetControlValue(this->m_FpsTextBox)); + sv->SetString("width", GetControlValue(this->m_WidthTextBox)); + sv->SetString("height", GetControlValue(this->m_HeightTextBox)); - vRoot.add_child(std::unique_ptr(vVars)); + CUtlBuffer outBuf(ssize_t(0), 0, CUtlBuffer::TEXT_BUFFER); + kv.RecursiveSaveToFile(outBuf, 0); - vdf::write(fileStream, vRoot); + if (!FileSystem()->WriteFile(pSettingsPath, "PLATFORM", outBuf)) + { + printf("%s: Failed to create VDF file: '%s'\n", __FUNCTION__, pSettingsPath); + return; + } } //----------------------------------------------------------------------------- @@ -735,11 +712,11 @@ void CSurface::LaunchGame(Forms::Control* pSender) string svParameter; pSurface->AppendParameterInternal(svParameter, "-launcher"); - eLaunchMode launchMode = g_pLauncher->GetMainSurface()->BuildParameter(svParameter); + eLaunchMode launchMode = g_Launcher.BuildParameter(svParameter); uint64_t nProcessorAffinity = pSurface->GetProcessorAffinity(svParameter); - if (g_pLauncher->CreateLaunchContext(launchMode, nProcessorAffinity, svParameter.c_str(), "startup_launcher.cfg")) - g_pLauncher->LaunchProcess(); + if (g_Launcher.CreateLaunchContext(launchMode, nProcessorAffinity, svParameter.c_str(), "startup_launcher.cfg")) + g_Launcher.LaunchProcess(); } //----------------------------------------------------------------------------- @@ -790,41 +767,39 @@ void CSurface::ParseMaps() //----------------------------------------------------------------------------- void CSurface::ParsePlaylists() { - fs::path playlistPath(Format("platform\\%s", this->m_PlaylistFileTextBox->Text().ToCString())); - m_PlaylistCombo->Items.Add(""); + CUtlString playlistPath; + playlistPath.Format("platform\\%s", this->m_PlaylistFileTextBox->Text().ToCString()); - if (!fs::exists(playlistPath)) + const char* pPlaylistPath = playlistPath.String(); + + if (!m_PlaylistCombo->Items.Contains("")) + m_PlaylistCombo->Items.Add(""); + + if (!FileSystem()->FileExists(pPlaylistPath)) + return; + + KeyValues kv("playlists"); + + if (!kv.LoadFromFile(FileSystem(), pPlaylistPath, nullptr)) { + printf("%s: Failed to parse playlists file: '%s'\n", __FUNCTION__, pPlaylistPath); return; } - bool success{ }; - std::ifstream iFile(playlistPath); - vdf::object vRoot = vdf::read(iFile, &success); + KeyValues* playlists = kv.FindKey("Playlists"); - if (!success) - { - printf("%s: Failed to parse VDF file: '%s'\n", __FUNCTION__, - playlistPath.u8string().c_str()); - return; - } + if (!playlists) + return; // Empty playlists - try + for (KeyValues* pSubKey = playlists->GetFirstTrueSubKey(); pSubKey != nullptr; pSubKey = pSubKey->GetNextTrueSubKey()) { - const auto& vcPlaylists = vRoot.childs.at("Playlists"); - for (auto [id, it] = std::tuplechilds.begin())> - { 1, vcPlaylists->childs.begin() }; it != vcPlaylists->childs.end(); id++, it++) + const char* keyName = pSubKey->GetName(); + + if (!this->m_PlaylistCombo->Items.Contains(keyName)) { - if (!this->m_PlaylistCombo->Items.Contains(it->first.c_str())) - { - this->m_PlaylistCombo->Items.Add(it->first.c_str()); - } + this->m_PlaylistCombo->Items.Add(keyName); } } - catch (const std::exception& e) - { - printf("%s: Exception while parsing VDF file: %s\n", __FUNCTION__, e.what()); - } } //----------------------------------------------------------------------------- @@ -1300,8 +1275,4 @@ const char* CSurface::GetControlValue(Forms::Control* pControl) //----------------------------------------------------------------------------- CSurface::CSurface() : Forms::Form() { - this->Init(); - this->Setup(); } - -CSurface* g_pMainUI; \ No newline at end of file diff --git a/r5dev/sdklauncher/basepanel.h b/r5dev/sdklauncher/basepanel.h index f50eac05..d1705e33 100644 --- a/r5dev/sdklauncher/basepanel.h +++ b/r5dev/sdklauncher/basepanel.h @@ -22,8 +22,10 @@ public: UIX::UIXListView* ConsoleListView() const { return m_ConsoleListView; }; std::vector m_LogList; -private: void Init(); + eLaunchMode BuildParameter(string& svParameter); + +private: void Setup(); void LoadSettings(); void SaveSettings(); @@ -44,8 +46,6 @@ private: const char* GetControlValue(Forms::Control* pControl); uint64_t GetProcessorAffinity(string& szParameter); - eLaunchMode BuildParameter(string& svParameter); - void AppendParameterInternal(string& svParameterList, const char* szParameter, const char* szArgument = nullptr); void AppendProcessorParameters(string& svParameter); void AppendConsoleParameters(string& svParameter); diff --git a/r5dev/sdklauncher/sdklauncher.cpp b/r5dev/sdklauncher/sdklauncher.cpp index 4191e50b..23b09dc7 100644 --- a/r5dev/sdklauncher/sdklauncher.cpp +++ b/r5dev/sdklauncher/sdklauncher.cpp @@ -8,6 +8,28 @@ #include "basepanel.h" #include "sdklauncher.h" +#include "vstdlib/keyvaluessystem.h" +#include "filesystem/filesystem_std.h" + +static CKeyValuesSystem s_KeyValuesSystem; +static CFileSystem_Stdio g_FullFileSystem; + +/////////////////////////////////////////////////////////////////////////////// +// Purpose: keyvalues singleton accessor +/////////////////////////////////////////////////////////////////////////////// +IKeyValuesSystem* KeyValuesSystem() +{ + return &s_KeyValuesSystem; +} + +/////////////////////////////////////////////////////////////////////////////// +// Purpose: filesystem singleton accessor +/////////////////////////////////////////////////////////////////////////////// +CFileSystem_Stdio* FileSystem() +{ + return &g_FullFileSystem; +} + /////////////////////////////////////////////////////////////////////////////// // Purpose: initializes and runs the user interface /////////////////////////////////////////////////////////////////////////////// @@ -16,8 +38,8 @@ void CLauncher::RunSurface() Forms::Application::EnableVisualStyles(); UIX::UIXTheme::InitializeRenderer(new Themes::KoreTheme()); - m_pSurface = new CSurface(); - Forms::Application::Run(g_pLauncher->m_pSurface); + m_Surface.Init(); + Forms::Application::Run(&g_Launcher.m_Surface, false); UIX::UIXTheme::ShutdownRenderer(); } @@ -366,21 +388,21 @@ BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) /////////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]/*, char* envp[]*/) { - g_pLauncher->InitLogger(); + g_Launcher.InitLogger(); if (argc < 2) { #ifdef NDEBUG FreeConsole(); #endif // NDEBUG - g_pLauncher->RunSurface(); + g_Launcher.RunSurface(); } else { - int results = g_pLauncher->HandleCommandLine(argc, argv); + int results = g_Launcher.HandleCommandLine(argc, argv); if (results != -1) return results; - return g_pLauncher->HandleInput(); + return g_Launcher.HandleInput(); } return EXIT_SUCCESS; } @@ -388,4 +410,4 @@ int main(int argc, char* argv[]/*, char* envp[]*/) /////////////////////////////////////////////////////////////////////////////// // Singleton Launcher. /////////////////////////////////////////////////////////////////////////////// -CLauncher* g_pLauncher(new CLauncher("win_console")); +CLauncher g_Launcher("win_console"); diff --git a/r5dev/sdklauncher/sdklauncher.h b/r5dev/sdklauncher/sdklauncher.h index 627d4de5..b2533855 100644 --- a/r5dev/sdklauncher/sdklauncher.h +++ b/r5dev/sdklauncher/sdklauncher.h @@ -6,17 +6,12 @@ class CLauncher public: CLauncher(const char* pszLoggerName) { - m_pSurface = nullptr; m_pLogger = spdlog::stdout_color_mt(pszLoggerName); m_ProcessorAffinity = NULL; m_svCurrentDir = fs::current_path().u8string(); } ~CLauncher() { - if (m_pSurface) - { - delete m_pSurface; - } } void AddLog(spdlog::level::level_enum nLevel, const char* szFormat, ...) @@ -30,12 +25,9 @@ public: m_pLogger->log(nLevel, svBuffer); m_pLogger->flush(); - if (m_pSurface) - { - m_pSurface->m_LogList.push_back(LogList_t(nLevel, svBuffer)); - m_pSurface->ConsoleListView()->SetVirtualListSize(static_cast(m_pSurface->m_LogList.size())); - m_pSurface->ConsoleListView()->Refresh(); - } + m_Surface.m_LogList.push_back(LogList_t(nLevel, svBuffer)); + m_Surface.ConsoleListView()->SetVirtualListSize(static_cast(m_Surface.m_LogList.size())); + m_Surface.ConsoleListView()->Refresh(); } void RunSurface(); @@ -49,10 +41,10 @@ public: void SetupLaunchContext(const char* szConfig, const char* szGameDll, const char* szCommandLine); bool LaunchProcess() const; - CSurface* GetMainSurface() const { return m_pSurface; } + eLaunchMode BuildParameter(string& parameterList) { return m_Surface.BuildParameter(parameterList); } private: - CSurface* m_pSurface; + CSurface m_Surface; std::shared_ptr m_pLogger; uint64_t m_ProcessorAffinity; @@ -64,4 +56,4 @@ private: BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam); -extern CLauncher* g_pLauncher; +extern CLauncher g_Launcher; diff --git a/r5dev/sdklauncher/sdklauncher_const.h b/r5dev/sdklauncher/sdklauncher_const.h index 6be7d829..0df95c77 100644 --- a/r5dev/sdklauncher/sdklauncher_const.h +++ b/r5dev/sdklauncher/sdklauncher_const.h @@ -1,7 +1,7 @@ #pragma once // Change this each time the settings format has changed. -#define SDK_LAUNCHER_VERSION 1 +#define SDK_LAUNCHER_VERSION 2 // Uncomment this line to compile the launcher for dedicated server builds. //#define DEDI_LAUNCHER diff --git a/r5dev/thirdparty/cppnet/cppkore/Application.cpp b/r5dev/thirdparty/cppnet/cppkore/Application.cpp index b69886eb..d01b8801 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Application.cpp +++ b/r5dev/thirdparty/cppnet/cppkore/Application.cpp @@ -11,7 +11,7 @@ namespace Forms std::atomic Application::IsGdipInitialized = false; ULONG_PTR Application::GdipToken = NULL; - void Application::Run(Form* MainWindow) + void Application::Run(Form* MainWindow, bool DeleteWindow) { if (MainWindow == nullptr) return; @@ -27,7 +27,7 @@ namespace Forms // Execute on the main loop Application::RunMainLoop(MainWindow); - if (MainWindow) + if (MainWindow && DeleteWindow) delete MainWindow; // Shutdown COM diff --git a/r5dev/thirdparty/cppnet/cppkore/Application.h b/r5dev/thirdparty/cppnet/cppkore/Application.h index 8ab073fb..df1e32d7 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Application.h +++ b/r5dev/thirdparty/cppnet/cppkore/Application.h @@ -12,7 +12,7 @@ namespace Forms public: // Begins running a standard application message loop on the current // thread, and makes the specified form visible. - static void Run(Form* MainWindow); + static void Run(Form* MainWindow, bool DeleteWindow); // Begins running a dialog application loop on the // current thread, you MUST clean up the dialog after use. From b52a5cce4811ae32c9c4ac5dadc7c386908c7470 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:49:29 +0200 Subject: [PATCH 030/113] NavMesh: rename editor program to 'recast' Renamed to original tool name --- r5dev/naveditor/CMakeLists.txt | 2 +- r5dev/resource/batch/nav_build.bat | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/r5dev/naveditor/CMakeLists.txt b/r5dev/naveditor/CMakeLists.txt index 1ca19d37..91d6b638 100644 --- a/r5dev/naveditor/CMakeLists.txt +++ b/r5dev/naveditor/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required( VERSION 3.16 ) -add_module( "exe" "naveditor" "" ${FOLDER_CONTEXT} TRUE TRUE ) +add_module( "exe" "recast" "" ${FOLDER_CONTEXT} TRUE TRUE ) start_sources() diff --git a/r5dev/resource/batch/nav_build.bat b/r5dev/resource/batch/nav_build.bat index 4774e8fc..c0901f5d 100644 --- a/r5dev/resource/batch/nav_build.bat +++ b/r5dev/resource/batch/nav_build.bat @@ -1,16 +1,16 @@ REM Build NavMesh for all levels. -naveditor -console levels\mp_lobby.obj 1 -naveditor -console levels\mp_rr_aqueduct.obj 1 -naveditor -console levels\mp_rr_arena_composite.obj 1 -naveditor -console levels\mp_rr_arena_skygarden.obj 1 -naveditor -console levels\mp_rr_ashs_redemption.obj 1 -naveditor -console levels\mp_rr_canyonlands_64k_x_64k.obj 1 -naveditor -console levels\mp_rr_canyonlands_mu1.obj 1 -naveditor -console levels\mp_rr_canyonlands_mu1_night.obj 1 -naveditor -console levels\mp_rr_canyonlands_staging.obj 1 -naveditor -console levels\mp_rr_desertlands_64k_x_64k.obj 1 -naveditor -console levels\mp_rr_desertlands_64k_x_64k_tt.obj 1 -naveditor -console levels\mp_rr_party_crasher.obj 1 +recast -console levels\mp_lobby.obj 1 +recast -console levels\mp_rr_aqueduct.obj 1 +recast -console levels\mp_rr_arena_composite.obj 1 +recast -console levels\mp_rr_arena_skygarden.obj 1 +recast -console levels\mp_rr_ashs_redemption.obj 1 +recast -console levels\mp_rr_canyonlands_64k_x_64k.obj 1 +recast -console levels\mp_rr_canyonlands_mu1.obj 1 +recast -console levels\mp_rr_canyonlands_mu1_night.obj 1 +recast -console levels\mp_rr_canyonlands_staging.obj 1 +recast -console levels\mp_rr_desertlands_64k_x_64k.obj 1 +recast -console levels\mp_rr_desertlands_64k_x_64k_tt.obj 1 +recast -console levels\mp_rr_party_crasher.obj 1 REM Copy NavMesh for identical levels. copy /y /v %~dp0..\maps\navmesh\mp_rr_aqueduct_small.nm %~dp0..\maps\navmesh\mp_rr_aqueduct_night_small.nm From 84831f53b6385ade65279a4d7b24d9ce45806a2b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:50:21 +0200 Subject: [PATCH 031/113] Engine: remove extraneous trailing semi-colon --- r5dev/engine/client/cl_splitscreen.h | 2 +- r5dev/engine/client/client.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/r5dev/engine/client/cl_splitscreen.h b/r5dev/engine/client/cl_splitscreen.h index eb3e8d02..9ad5f89d 100644 --- a/r5dev/engine/client/cl_splitscreen.h +++ b/r5dev/engine/client/cl_splitscreen.h @@ -133,7 +133,7 @@ class VSplitScreen : public IDetour virtual void GetFun(void) const { } virtual void GetVar(void) const { - const char* const pszPattern = "40 53 48 83 EC 20 48 8D 1D ?? ?? ?? ?? 83 FA FF 75 12 48 8B 05 ?? ?? ?? ?? 48 8B CB FF 50 28 48 63 C8 EB 03 48 63 CA 48 69 C1 ?? ?? ?? ?? 66 C7 84 18 ?? ?? ?? ?? ?? ??";; + const char* const pszPattern = "40 53 48 83 EC 20 48 8D 1D ?? ?? ?? ?? 83 FA FF 75 12 48 8B 05 ?? ?? ?? ?? 48 8B CB FF 50 28 48 63 C8 EB 03 48 63 CA 48 69 C1 ?? ?? ?? ?? 66 C7 84 18 ?? ?? ?? ?? ?? ??"; const char* const pszInstruction = "48 8D"; g_pSplitScreenMgr = g_GameDll.FindPatternSIMD(pszPattern).FindPatternSelf(pszInstruction).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index 9f3edd85..c628d1ad 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -259,7 +259,7 @@ bool CClient::Connect(const char* szName, CNetChan* pNetChan, bool bFakePlayer, bool CClient::VConnect(CClient* pClient, const char* szName, CNetChan* pNetChan, bool bFakePlayer, CUtlVector* conVars, char* szMessage, int nMessageSize) { - return pClient->Connect(szName, pNetChan, bFakePlayer, conVars, szMessage, nMessageSize);; + return pClient->Connect(szName, pNetChan, bFakePlayer, conVars, szMessage, nMessageSize); } //--------------------------------------------------------------------------------- From a26e692b37a909dfce75515d74eca69dad40223f Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:50:30 +0200 Subject: [PATCH 032/113] RTech: remove extraneous trailing semi-colon --- r5dev/rtech/pak/pakdecode.cpp | 2 +- r5dev/rtech/pak/pakparse.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/r5dev/rtech/pak/pakdecode.cpp b/r5dev/rtech/pak/pakdecode.cpp index 936e6893..7037c264 100644 --- a/r5dev/rtech/pak/pakdecode.cpp +++ b/r5dev/rtech/pak/pakdecode.cpp @@ -218,7 +218,7 @@ size_t Pak_RTechDecoderInit(PakDecoder_s* const decoder, const uint8_t* const fi const uint64_t finalPos = inputMask & decoder->inBufBytePos; decoder->headerOffset = (currbits >> 3) + 1; decoder->inBufBytePos += (currbits >> 3) + 1; - decoder->bufferSizeNeeded = *(_QWORD*)(finalPos + fileBuffer) & ((1i64 << (8 * ((uint8_t)(currbits >> 3) + 1))) - 1);; + decoder->bufferSizeNeeded = *(_QWORD*)(finalPos + fileBuffer) & ((1i64 << (8 * ((uint8_t)(currbits >> 3) + 1))) - 1); } decoder->bufferSizeNeeded += dataOffset; diff --git a/r5dev/rtech/pak/pakparse.cpp b/r5dev/rtech/pak/pakparse.cpp index b95bebeb..9b45d991 100644 --- a/r5dev/rtech/pak/pakparse.cpp +++ b/r5dev/rtech/pak/pakparse.cpp @@ -1089,7 +1089,7 @@ bool Pak_StartLoadingPak(PakLoadedInfo_s* const loadedInfo) // virtualSegmentCount = pakHdr.virtualSegmentCount; // v32 = *(unsigned int*)&pakHdr.unk2[4]; // -// loadedInfo->assetGuids = (PakGuid_t*)loadedInfo->allocator->Alloc(sizeof(PakGuid_t) * asset_entry_count_var, 8);; +// loadedInfo->assetGuids = (PakGuid_t*)loadedInfo->allocator->Alloc(sizeof(PakGuid_t) * asset_entry_count_var, 8); // // size_t streamingFilesBuifSize = pakHdr.streamingFilesBufSize[STREAMING_SET_OPTIONAL] + pakHdr.streamingFilesBufSize[STREAMING_SET_MANDATORY]; // From aee8447320c8ddee92530100032125eef5a8a4c6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:52:33 +0200 Subject: [PATCH 033/113] Resource: update configuration files Slightly adjusted RCON configuration files, recent changes implemented RCON encryption (users can specify their own AES keys). --- r5dev/resource/cfg/tools/rcon_client.cfg | 1 + r5dev/resource/cfg/tools/rcon_client_dev.cfg | 3 ++- r5dev/resource/cfg/tools/rcon_server.cfg | 1 + r5dev/resource/cfg/tools/rcon_server_dev.cfg | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/r5dev/resource/cfg/tools/rcon_client.cfg b/r5dev/resource/cfg/tools/rcon_client.cfg index 6d088d92..25c439e2 100644 --- a/r5dev/resource/cfg/tools/rcon_client.cfg +++ b/r5dev/resource/cfg/tools/rcon_client.cfg @@ -4,3 +4,4 @@ // NOTE: This implementation is custom and differs slightly from Valve's implementation. cl_rcon_address "" // The RCON system will attempt to connect to this address when 'rcon' command is issued. Example [::FFFF:127.0.0.1]:37015 (counts for IPv4 and IPv6). +rcon_key "" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. diff --git a/r5dev/resource/cfg/tools/rcon_client_dev.cfg b/r5dev/resource/cfg/tools/rcon_client_dev.cfg index cf95e3e9..6118c755 100644 --- a/r5dev/resource/cfg/tools/rcon_client_dev.cfg +++ b/r5dev/resource/cfg/tools/rcon_client_dev.cfg @@ -3,4 +3,5 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -cl_rcon_address "" // The RCON system will attempt to connect to this address when 'rcon' command is issued. Example [::FFFF:127.0.0.1]:37015 (counts for IPv4 and IPv6). +cl_rcon_address "" // The RCON system will attempt to connect to this address when 'rcon' command is issued. Example [::FFFF:127.0.0.1]:37015 (counts for IPv4 and IPv6). +rcon_key "WDNWLmJYQ2ZlM0VoTid3Yg==" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. diff --git a/r5dev/resource/cfg/tools/rcon_server.cfg b/r5dev/resource/cfg/tools/rcon_server.cfg index c38db08a..3f902e5f 100644 --- a/r5dev/resource/cfg/tools/rcon_server.cfg +++ b/r5dev/resource/cfg/tools/rcon_server.cfg @@ -5,3 +5,4 @@ sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). +rcon_key "" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. diff --git a/r5dev/resource/cfg/tools/rcon_server_dev.cfg b/r5dev/resource/cfg/tools/rcon_server_dev.cfg index d605c4eb..b93cea0a 100644 --- a/r5dev/resource/cfg/tools/rcon_server_dev.cfg +++ b/r5dev/resource/cfg/tools/rcon_server_dev.cfg @@ -11,3 +11,4 @@ sv_rcon_maxsockets "2" // Max number of accepted sockets b sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). rcon_debug "1" // Show RCON debug information ( ! slower! ). +rcon_key "WDNWLmJYQ2ZlM0VoTid3Yg==" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. From caafe60cf272fa5a65203fa67a12b67070e97afd Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:53:11 +0200 Subject: [PATCH 034/113] Resource: update cleaner script Added new LiveAPI log directory, and several files that were renamed. --- r5dev/resource/batch/clean_sdk.bat | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/r5dev/resource/batch/clean_sdk.bat b/r5dev/resource/batch/clean_sdk.bat index 4da73a6c..2c1f1592 100644 --- a/r5dev/resource/batch/clean_sdk.bat +++ b/r5dev/resource/batch/clean_sdk.bat @@ -3,6 +3,7 @@ rd /S /Q "%~dp0..\platform\depot" REM Remove log files ('log' is no longer used. 'logs' contains current logs, these get automatically cleaned if they exceed 10mb). rd /S /Q "%~dp0..\platform\log" rd /S /Q "%~dp0..\platform\logs" +rd /S /Q "%~dp0..\platform\liveapi\logs" REM Remove old NavMesh files which where included as an attempt to debug/suppress warnings. rd /S /Q "%~dp0..\maps" rd /S /Q "%~dp0..\platform\maps\graphs" @@ -15,6 +16,11 @@ del /Q "%~dp0..\r5reloaded.exe" del /Q "%~dp0..\r5apexsdkd64.dll" del /Q "%~dp0..\r5detours.dll" del /Q "%~dp0..\r5dev.dll" +del /Q "%~dp0..\bin\naveditor.exe" +del /Q "%~dp0..\platform\cfg\englishclient_build_vpk.cfg" +del /Q "%~dp0..\platform\cfg\englishclient_extract_vpk.cfg" +del /Q "%~dp0..\platform\cfg\englishserver_build_vpk.cfg" +del /Q "%~dp0..\platform\cfg\englishserver_extract_vpk.cfg" REM Remove deprecated pak files (these are no longer used). del /Q "%~dp0..\paks\Win32\common_empty.rpak" del /Q "%~dp0..\paks\Win32\common_sdk2.rpak" From 39191f445fb9378e02039f748bdcd7eca6dbad73 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:40:46 +0200 Subject: [PATCH 035/113] Resource: add new parallel VPK build script Build script to build VPK files in parallel with use of the new tool 'ReVPK'. --- r5dev/resource/batch/vpk_build.bat | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 r5dev/resource/batch/vpk_build.bat diff --git a/r5dev/resource/batch/vpk_build.bat b/r5dev/resource/batch/vpk_build.bat new file mode 100644 index 00000000..6ad096ef --- /dev/null +++ b/r5dev/resource/batch/vpk_build.bat @@ -0,0 +1,29 @@ +start /ABOVENORMAL revpk "pack" "english" "server" "mp_common" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_aqueduct" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_aqueduct_night" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_arena_composite" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_arena_skygarden" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_ashs_redemption" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_64k_x_64k" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_mu1" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_mu1_night" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_staging" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_desertlands_64k_x_64k" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_desertlands_64k_x_64k_nx" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_desertlands_64k_x_64k_tt" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_party_crasher" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "frontend" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_common" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_aqueduct" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_aqueduct_night" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_arena_composite" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_arena_skygarden" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_ashs_redemption" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_64k_x_64k" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_mu1" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_mu1_night" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_staging" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_desertlands_64k_x_64k" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_desertlands_64k_x_64k_nx" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_desertlands_64k_x_64k_tt" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_party_crasher" "../ship/" "../vpk/" From 51e4a11bdb8487d2651e3ced7c5a68943c441509 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:41:28 +0200 Subject: [PATCH 036/113] Resource: add new LiveAPI configuration file Executed on server launch. --- r5dev/resource/cfg/liveapi.cfg | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 r5dev/resource/cfg/liveapi.cfg diff --git a/r5dev/resource/cfg/liveapi.cfg b/r5dev/resource/cfg/liveapi.cfg new file mode 100644 index 00000000..f1a76873 --- /dev/null +++ b/r5dev/resource/cfg/liveapi.cfg @@ -0,0 +1,18 @@ +///////////////// LiveAPI system configuration file. +// This file is executed automatically on startup. + +liveapi_enabled "0" // Enable LiveAPI functionality. +liveapi_session_name "" // LiveAPI session name to identify this connection. + +liveapi_websocket_enabled "0" // Whether to use WebSocket to transmit LiveAPI events. +liveapi_servers "" // Comma separated list of addresses to connect to; format: ws://domain.suffix:port. +liveapi_retry_count "5" // Amount of times to retry connecting before marking the connection as unavailable. +liveapi_retry_time "30" // Amount of time between each retry. + +liveapi_timeout "300" // WebSocket connection timeout in seconds. +liveapi_keepalive "30" // Interval of time to send Pong to any connected server. +liveapi_lax_ssl "1" // Skip SSL certificate validation for all WSS connections (allows the use of self-signed certificates). + +liveapi_print_enabled "0" // Whether to enable the printing of all events to a LiveAPI JSON file. +liveapi_print_pretty "0" // Whether to print events in a formatted manner to the LiveAPI JSON file. +liveapi_print_primitive "0" // Whether to print primitive event fields to the LiveAPI JSON file. From 6a99c1bd5c3efa36ab945239716f1a98903c23c8 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:21:03 +0200 Subject: [PATCH 037/113] Launcher: untoggle windowed mode by default and rename field Untoggled by default due to popular demand (most wanted to launch full screen). Also renamed maxFPS field to fpsMax to remain consistency with the actual cvar name. --- r5dev/sdklauncher/basepanel.cpp | 5 ++--- r5dev/sdklauncher/sdklauncher_const.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index e99abdcd..dae046c5 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -382,7 +382,6 @@ void CSurface::Init() this->m_WindowedToggle->SetSize({ 105, 18 }); this->m_WindowedToggle->SetLocation({ 15, 7 }); this->m_WindowedToggle->SetTabIndex(0); - this->m_WindowedToggle->SetChecked(true); this->m_WindowedToggle->SetText("Windowed"); this->m_WindowedToggle->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_EngineVideoGroup->AddControl(this->m_WindowedToggle); @@ -578,7 +577,7 @@ void CSurface::LoadSettings() // Video. this->m_WindowedToggle->SetChecked(sv->GetBool("windowed")); this->m_NoBorderToggle->SetChecked(sv->GetBool("borderless")); - this->m_FpsTextBox->SetText(sv->GetString("maxFPS", "-1")); + this->m_FpsTextBox->SetText(sv->GetString("fpsMax", "-1")); this->m_WidthTextBox->SetText(sv->GetString("width")); this->m_HeightTextBox->SetText(sv->GetString("height")); } @@ -639,7 +638,7 @@ void CSurface::SaveSettings() // Video. sv->SetBool("windowed", this->m_WindowedToggle->Checked()); sv->SetBool("borderless", this->m_NoBorderToggle->Checked()); - sv->SetString("maxFPS", GetControlValue(this->m_FpsTextBox)); + sv->SetString("fpsMax", GetControlValue(this->m_FpsTextBox)); sv->SetString("width", GetControlValue(this->m_WidthTextBox)); sv->SetString("height", GetControlValue(this->m_HeightTextBox)); diff --git a/r5dev/sdklauncher/sdklauncher_const.h b/r5dev/sdklauncher/sdklauncher_const.h index 0df95c77..508734d9 100644 --- a/r5dev/sdklauncher/sdklauncher_const.h +++ b/r5dev/sdklauncher/sdklauncher_const.h @@ -1,7 +1,7 @@ #pragma once // Change this each time the settings format has changed. -#define SDK_LAUNCHER_VERSION 2 +#define SDK_LAUNCHER_VERSION 3 // Uncomment this line to compile the launcher for dedicated server builds. //#define DEDI_LAUNCHER From c3f66e748ffa8358775ed9be88251f8b629f5299 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:22:32 +0200 Subject: [PATCH 038/113] Server: add script function 'GetServerID()' Allows one to get the current session uuid (will be used for LiveAPI's Init event for session identification). --- r5dev/game/server/vscript_server.cpp | 11 +++++++++++ r5dev/game/server/vscript_server.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 9120f395..0ca711d9 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -247,6 +247,15 @@ namespace VScriptCode SCRIPT_CHECK_AND_RETURN(v, SQ_OK); } + //----------------------------------------------------------------------------- + // Purpose: gets the current server id + //----------------------------------------------------------------------------- + SQRESULT GetServerID(HSQUIRRELVM v) + { + sq_pushstring(v, g_LogSessionUUID.c_str(), (SQInteger)g_LogSessionUUID.length()); + SCRIPT_CHECK_AND_RETURN(v, SQ_OK); + } + //----------------------------------------------------------------------------- // Purpose: checks whether the server is active //----------------------------------------------------------------------------- @@ -300,6 +309,8 @@ void Script_RegisterCoreServerFunctions(CSquirrelVM* s) DEFINE_SERVER_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local server down", "void", ""); DEFINE_SERVER_SCRIPTFUNC_NAMED(s, SetAutoReloadState, "Set whether we can auto-reload the server", "void", "bool"); + + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetServerID, "Gets the current server ID", "string", ""); } //--------------------------------------------------------------------------------- diff --git a/r5dev/game/server/vscript_server.h b/r5dev/game/server/vscript_server.h index 4bc7a82f..8d811524 100644 --- a/r5dev/game/server/vscript_server.h +++ b/r5dev/game/server/vscript_server.h @@ -20,6 +20,8 @@ namespace VScriptCode SQRESULT GetNumHumanPlayers(HSQUIRRELVM v); SQRESULT GetNumFakeClients(HSQUIRRELVM v); + SQRESULT GetServerID(HSQUIRRELVM v); + SQRESULT IsServerActive(HSQUIRRELVM v); SQRESULT IsDedicated(HSQUIRRELVM v); } From 1fe74fe7277e2b98b7f400aeaa10a095c6a5e005 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:23:14 +0200 Subject: [PATCH 039/113] Server: simplify lagcomp clamping code and add technical notes Clamp to +- sv_maxunlag delta from server time base. Also added notes to possibly rework the system in the future. --- r5dev/game/server/player.cpp | 80 +++++++++--------------------------- 1 file changed, 19 insertions(+), 61 deletions(-) diff --git a/r5dev/game/server/player.cpp b/r5dev/game/server/player.cpp index 122f6b98..9032bb4c 100644 --- a/r5dev/game/server/player.cpp +++ b/r5dev/game/server/player.cpp @@ -112,65 +112,6 @@ void CPlayer::SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime) } } -//------------------------------------------------------------------------------ -// Purpose: clamps the unlag amount to sv_unlag + clockdrift -// Input : *cmd - -//------------------------------------------------------------------------------ -void CPlayer::ClampUnlag(CUserCmd* cmd) -{ - const CClient* client = g_pServer->GetClient(GetEdict() - 1); - const CNetChan* chan = client->GetNetChan(); - - const float clockDriftMsecs = sv_clockcorrection_msecs->GetFloat() / 1000.0f; - const float maxUnlag = sv_maxunlag->GetFloat(); - const float latencyAmount = Clamp(chan->GetLatency(FLOW_OUTGOING), 0.0f, maxUnlag); - const float serverTime = (*g_pGlobals)->m_flCurTime; - - // Command issue time from client, note that this value can be altered - // from the client, and therefore be used to exploit lag compensation. - const float commandTime = cmd->command_time; - const float lastCommandTime = m_LastCmd.command_time; - const float commandDelta = fabs(commandTime - serverTime); - - bool recomputeUnlag = false; - - // Check delta first, otherwise player could set commandTime to a fixed - // time and circumvent the system, as commandTime < lastCommandTime or - // commandTime > localCurTime will always fail. - if (commandDelta > maxUnlag) - { - // Too much to unlag, clamp to max !!! - recomputeUnlag = true; - DevWarning(eDLL_T::SERVER, "%s: commandDelta( %f ) > maxUnlag( %f ) !!!\n", - __FUNCTION__, commandDelta, maxUnlag); - } - else if (commandTime < (lastCommandTime - clockDriftMsecs)) - { - // Can never be lower than last !!! - recomputeUnlag = true; - DevWarning(eDLL_T::SERVER, "%s: cmd->command_time( %f ) < (m_LastCmd.command_time( %f ) - clockDriftMsecs( %f )) !!!\n", - __FUNCTION__, commandTime, lastCommandTime, clockDriftMsecs); - } - else if (commandTime > (serverTime + clockDriftMsecs)) - { - // Too far in the future, clamp to max !!! - recomputeUnlag = true; - DevWarning(eDLL_T::SERVER, "%s: cmd->command_time( %f ) > (g_pGlobals->m_flCurTime( %f ) + clockDriftMsecs( %f )) !!!\n", - __FUNCTION__, commandTime, serverTime, clockDriftMsecs); - } - - if (recomputeUnlag) - { - // Clamp it to server time minus latency. Note that it could still - // be lower than previous, hence the clamp on the recomputation. - float newCommandTime = Clamp(serverTime - latencyAmount, lastCommandTime, serverTime); - cmd->command_time = newCommandTime; - - DevWarning(eDLL_T::SERVER, "%s: Clamped cmd->command_time( %f ) to %f !!!\n", - __FUNCTION__, commandTime, newCommandTime); - } -} - //------------------------------------------------------------------------------ // Purpose: processes user cmd's for this player // Input : *cmds - @@ -182,7 +123,7 @@ void CPlayer::ClampUnlag(CUserCmd* cmd) // TODO: this code is experimental and has reported problems from players with // high latency, needs to be debugged or a different approach needs to be taken! // Defaulted to OFF for now -static ConVar sv_unlag_clamp("sv_unlag_clamp", "0", FCVAR_RELEASE, "Clamp the difference between the current time and received command time to sv_maxunlag + sv_clockcorrection_msecs."); +static ConVar sv_unlag_clamp("sv_unlag_clamp", "0", FCVAR_RELEASE, "Clamp the difference between the current time and received command time to sv_maxunlag."); void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, int droppedPackets, bool paused) @@ -192,6 +133,9 @@ void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, CUserCmd* lastCmd = &m_Commands[MAX_QUEUED_COMMANDS_PROCESS]; + const float maxUnlag = sv_maxunlag->GetFloat(); + const float currTime = (*g_pGlobals)->m_flCurTime; + for (int i = totalCmds - 1; i >= 0; i--) { CUserCmd* cmd = &cmds[i]; @@ -206,8 +150,22 @@ void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, if (lastCommandNumber == MAX_QUEUED_COMMANDS_PROCESS) return; + // TODO: why are grenades not clamped to sv_maxunlag ??? + // TODO: the command_time is set from the client itself in CInput::CreateMove + // to gpGlobals->curtime in the ucmd packet, perhaps just calculate it from + // the server based on ucmd ticks ??? + // + // Possible solutions that need to be explored and worked out further: + // + // cmd->command_time = TICKS_TO_TIME(cmd->command_number + cmd->tick_count) // seems to be the closest, but also still manipulatable from the client. + // cmd->command_time = TICKS_TO_TIME(client->GetDeltaTick() + cmd->command_number) // delta tick is not necessarily the same as actual ucmd tick, and will be -1 on baseline request. + // cmd->command_time = TICKS_TO_TIME(m_lastUCmdSimulationRemainderTime) + m_totalExtraClientCmdTimeAttempted; // player timebase; also up to 100ms difference between orig sent value. + // + // ... reverse more ticks and floats in CClient since there seem to be a + // bunch still in the padded bytes, possibly one of them is what we could + // and should actually use to get the remote client time since ucmd was sent. if (sv_unlag_clamp.GetBool()) - ClampUnlag(cmd); + cmd->command_time = Min(Max(cmd->command_time, Max(currTime - maxUnlag, 0.0f)), currTime + maxUnlag); CUserCmd* queuedCmd = &m_Commands[lastCommandNumber]; queuedCmd->Copy(cmd); From 6eee25a4e90ad3ac2796b4000cadd01b7d40dcbf Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 16:11:58 +0200 Subject: [PATCH 040/113] Engine: use dedicated convar to determine rcon server socket bind Decoupled from net_usesocketforloopback since we actually don't want this to be tied with that of the game. Now it by default does not bind to the loopback socket unlike the game. --- r5dev/common/callback.cpp | 22 ---------------------- r5dev/common/callback.h | 1 - r5dev/common/global.cpp | 1 - r5dev/engine/server/sv_rcon.cpp | 22 +++++++++++++++++++++- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp index e932710c..f98f42ed 100644 --- a/r5dev/common/callback.cpp +++ b/r5dev/common/callback.cpp @@ -228,28 +228,6 @@ void VPK_Unmount_f(const CCommand& args) FileSystem()->UnmountVPKFile(args.Arg(1)); } -/* -===================== -NET_UseSocketsForLoopbackChanged_f - - Use random AES encryption - key for game packets -===================== -*/ -void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString) -{ - if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) - { - if (strcmp(pOldString, pConVarRef->GetString()) == NULL) - return; // Same value. - -#ifndef CLIENT_DLL - // Reboot the RCON server to switch address type. - RCONServer()->Reboot(); -#endif // !CLIENT_DLL - } -} - void LanguageChanged_f(IConVar* pConVar, const char* pOldString) { if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) diff --git a/r5dev/common/callback.h b/r5dev/common/callback.h index 07426375..47a48858 100644 --- a/r5dev/common/callback.h +++ b/r5dev/common/callback.h @@ -14,7 +14,6 @@ void VPK_Pack_f(const CCommand& args); void VPK_Unpack_f(const CCommand& args); void VPK_Mount_f(const CCommand& args); void VPK_Unmount_f(const CCommand& args); -void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString); #ifndef DEDICATED void GFX_NVN_Changed_f(IConVar* pConVar, const char* pOldString); diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 309c853c..16e2e518 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -256,7 +256,6 @@ void ConVar_InitShipped(void) mp_gamemode->RemoveChangeCallback(mp_gamemode->m_fnChangeCallbacks[0]); mp_gamemode->InstallChangeCallback(MP_GameMode_Changed_f, false); net_usesocketsforloopback->RemoveFlags(FCVAR_DEVELOPMENTONLY); - net_usesocketsforloopback->InstallChangeCallback(NET_UseSocketsForLoopbackChanged_f, false); #ifndef DEDICATED language_cvar->InstallChangeCallback(LanguageChanged_f, false); #endif // !DEDICATED diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index ae71061e..4c8cb635 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -32,6 +32,7 @@ static const char s_BannedMessage[] = "Go away.\n"; static void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString); +static void RCON_UseLoopbackSocketChanged_f(IConVar* pConVar, const char* pOldString); static ConVar sv_rcon_password("sv_rcon_password", "", FCVAR_RELEASE, "Remote server access password (rcon server is disabled if empty)", &RCON_PasswordChanged_f); static ConVar sv_rcon_sendlogs("sv_rcon_sendlogs", "0", FCVAR_RELEASE, "Network console logs to connected and authenticated sockets"); @@ -45,6 +46,8 @@ static ConVar sv_rcon_maxconnections("sv_rcon_maxconnections", "1", FCVAR_RELEAS static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, false, 0.f); static ConVar sv_rcon_whitelist_address("sv_rcon_whitelist_address", "", FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts", &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); +static ConVar sv_rcon_useloopbacksocket("sv_rcon_useloopbacksocket", "0", FCVAR_RELEASE, "Whether to bind rcon server to the loopback socket", &RCON_UseLoopbackSocketChanged_f); + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -86,7 +89,7 @@ void CRConServer::Init(const char* pPassword, const char* pNetKey) return; } - const char* pszAddress = net_usesocketsforloopback->GetBool() ? NET_IPV6_UNSPEC : NET_IPV6_LOOPBACK; + const char* pszAddress = sv_rcon_useloopbacksocket.GetBool() ? NET_IPV6_UNSPEC : NET_IPV6_LOOPBACK; m_Address.SetFromString(Format("[%s]:%i", pszAddress, hostport->GetInt()).c_str(), true); m_Socket.CreateListenSocket(m_Address); @@ -797,6 +800,23 @@ static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldStri } } +//----------------------------------------------------------------------------- +// Purpose: change whether to bind on loopback socket +//----------------------------------------------------------------------------- +static void RCON_UseLoopbackSocketChanged_f(IConVar* pConVar, const char* pOldString) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { + if (strcmp(pOldString, pConVarRef->GetString()) == NULL) + return; // Same value. + +#ifndef CLIENT_DLL + // Reboot the RCON server to switch address type. + RCONServer()->Reboot(); +#endif // !CLIENT_DLL + } +} + /////////////////////////////////////////////////////////////////////////////// static CRConServer s_RCONServer; CRConServer* RCONServer() // Singleton RCON Server. From 5d38b3762bbc2ea01ade24f3cd159e00811a68bc Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 16:14:19 +0200 Subject: [PATCH 041/113] Engine: enforce rcon convar name consistency Removed extra '_' from sv_rcon_whitelist_address, its now sv_rcon_whitelistaddress. --- r5dev/engine/server/sv_rcon.cpp | 4 ++-- r5dev/resource/cfg/tools/rcon_server.cfg | 6 +++--- r5dev/resource/cfg/tools/rcon_server_dev.cfg | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index 4c8cb635..0c759b88 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -44,7 +44,7 @@ static ConVar sv_rcon_maxsockets("sv_rcon_maxsockets", "32", FCVAR_RELEASE, "Max static ConVar sv_rcon_maxconnections("sv_rcon_maxconnections", "1", FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket", true, 1.f, true, MAX_PLAYERS, &RCON_ConnectionCountChanged_f); static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, false, 0.f); -static ConVar sv_rcon_whitelist_address("sv_rcon_whitelist_address", "", FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts", &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); +static ConVar sv_rcon_whitelistaddress("sv_rcon_whitelistaddress", "", FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts", &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); static ConVar sv_rcon_useloopbacksocket("sv_rcon_useloopbacksocket", "0", FCVAR_RELEASE, "Whether to bind rcon server to the loopback socket", &RCON_UseLoopbackSocketChanged_f); @@ -583,7 +583,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) if (m_BannedList.size() >= RCON_MAX_BANNEDLIST_SIZE) { - const char* pszWhiteListAddress = sv_rcon_whitelist_address.GetString(); + const char* pszWhiteListAddress = sv_rcon_whitelistaddress.GetString(); if (!pszWhiteListAddress[0]) { Warning(eDLL_T::SERVER, "Banned list overflowed, please use a whitelist address; remote server access shutting down...\n"); diff --git a/r5dev/resource/cfg/tools/rcon_server.cfg b/r5dev/resource/cfg/tools/rcon_server.cfg index 3f902e5f..1c62f561 100644 --- a/r5dev/resource/cfg/tools/rcon_server.cfg +++ b/r5dev/resource/cfg/tools/rcon_server.cfg @@ -3,6 +3,6 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. -sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). -rcon_key "" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. +sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. +sv_rcon_whitelistaddress "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). +rcon_key "" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. diff --git a/r5dev/resource/cfg/tools/rcon_server_dev.cfg b/r5dev/resource/cfg/tools/rcon_server_dev.cfg index b93cea0a..eecc34db 100644 --- a/r5dev/resource/cfg/tools/rcon_server_dev.cfg +++ b/r5dev/resource/cfg/tools/rcon_server_dev.cfg @@ -3,12 +3,12 @@ // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for more information regarding RCON. // NOTE: This implementation is custom and differs slightly from Valve's implementation. -sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. -sv_rcon_banpenalty "1" // Number of minutes to ban IP before removing from ban vector. -sv_rcon_maxfailures "5" // Max number of tomes a user can ignore RCON authentication before being banned. -sv_rcon_maxignores "5" // Max number of times a user can ignore the no-auth message before being banned. -sv_rcon_maxsockets "2" // Max number of accepted sockets before the server starts closing redundant sockets. -sv_rcon_whitelist_address "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). +sv_rcon_password "" // !! WARNING !! Keep empty to disable RCON. Only enable this if you plan on using RCON. +sv_rcon_banpenalty "1" // Number of minutes to ban IP before removing from ban vector. +sv_rcon_maxfailures "5" // Max number of tomes a user can ignore RCON authentication before being banned. +sv_rcon_maxignores "5" // Max number of times a user can ignore the no-auth message before being banned. +sv_rcon_maxsockets "2" // Max number of accepted sockets before the server starts closing redundant sockets. +sv_rcon_whitelistaddress "" // This IP will never get disconnected or banned. Example [::FFFF:127.0.0.1]:37005 (counts for IPv4 and IPv6). -rcon_debug "1" // Show RCON debug information ( ! slower! ). -rcon_key "WDNWLmJYQ2ZlM0VoTid3Yg==" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. +rcon_debug "1" // Show RCON debug information ( ! slower! ). +rcon_key "WDNWLmJYQ2ZlM0VoTid3Yg==" // Base64 encoded AES-128 key that will be used to encrypt rcon traffic, leave this empty for a random key that gets printed to the console. From cb72778a258afa48ad53080c0fe88e00fb31cc6a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 19:39:52 +0200 Subject: [PATCH 042/113] Core: allow launching dedicated server without terminal window The terminal window isn't always necessary, especially on Linux systems. In fact, it causes issues on some Wine environments. Allow user to disable it with -noconsole. This option only exists on the dedicated server. The client builds have the console disabled by default, and can enable them with -wconsole. --- r5dev/core/dllmain.cpp | 12 ++++++++---- r5dev/sdklauncher/basepanel.cpp | 7 +++++++ r5dev/windows/console.cpp | 14 ++++++++++---- r5dev/windows/console.h | 4 ++-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/r5dev/core/dllmain.cpp b/r5dev/core/dllmain.cpp index 5415390a..819030ac 100644 --- a/r5dev/core/dllmain.cpp +++ b/r5dev/core/dllmain.cpp @@ -30,7 +30,9 @@ bool g_bSdkInitCallInitiated = false; bool g_bSdkShutdownCallInitiated = false; bool g_bSdkShutdownInitiatedFromConsoleHandler = false; -HMODULE s_hModuleHandle = NULL; + +static bool s_bConsoleInitialized = false; +static HMODULE s_hModuleHandle = NULL; //############################################################################# // UTILITY @@ -116,9 +118,11 @@ void SDK_Init() #ifndef DEDICATED if (CommandLine()->CheckParm("-wconsole")) -#endif // !DEDICATED +#else + if (!CommandLine()->CheckParm("-noconsole")) +#endif // !DEDICATED { - Console_Init(bAnsiColor); + s_bConsoleInitialized = Console_Init(bAnsiColor); } SpdLog_Init(bAnsiColor); @@ -186,7 +190,7 @@ void SDK_Shutdown() // If the shutdown was initiated from the console window itself, don't // shutdown the console as it would otherwise deadlock in FreeConsole! - if (!g_bSdkShutdownInitiatedFromConsoleHandler) + if (s_bConsoleInitialized && !g_bSdkShutdownInitiatedFromConsoleHandler) Console_Shutdown(); g_bSdkInitialized = false; diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index dae046c5..e145a917 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -109,6 +109,11 @@ void CSurface::Init() this->m_ConsoleToggle->SetSize({ 110, 18 }); this->m_ConsoleToggle->SetLocation({ 290, 7 }); this->m_ConsoleToggle->SetTabIndex(0); +#ifdef DEDI_LAUNCHER + this->m_ConsoleToggle->SetChecked(true); +#else // For client builds, don't show the console by default + this->m_ConsoleToggle->SetChecked(false); +#endif // DEDI_LAUNCHER this->m_ConsoleToggle->SetText("Show console"); this->m_ConsoleToggle->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_GameGroupExt->AddControl(this->m_ConsoleToggle); @@ -968,6 +973,8 @@ void CSurface::AppendConsoleParameters(string& svParameters) { if (this->m_ConsoleToggle->Checked()) AppendParameterInternal(svParameters, "-wconsole"); + else + AppendParameterInternal(svParameters, "-noconsole"); if (this->m_ColorConsoleToggle->Checked()) AppendParameterInternal(svParameters, "-ansicolor"); diff --git a/r5dev/windows/console.cpp b/r5dev/windows/console.cpp index a0008c46..3324fd0c 100644 --- a/r5dev/windows/console.cpp +++ b/r5dev/windows/console.cpp @@ -77,8 +77,9 @@ void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color) //----------------------------------------------------------------------------- // Purpose: terminal window setup // Input : bAnsiColor - +// Output : true on success, false otherwise //----------------------------------------------------------------------------- -void Console_Init(const bool bAnsiColor) +bool Console_Init(const bool bAnsiColor) { #ifndef _TOOLS /////////////////////////////////////////////////////////////////////////// @@ -89,7 +90,7 @@ void Console_Init(const bool bAnsiColor) snprintf(szBuf, sizeof(szBuf), "Failed to create console window! [%s]\n", std::system_category().message(static_cast(::GetLastError())).c_str()); OutputDebugStringA(szBuf); - return; + return false; } //-- Set the window title @@ -133,12 +134,15 @@ void Console_Init(const bool bAnsiColor) #ifndef _TOOLS SetConsoleCtrlHandler(ConsoleHandlerRoutine, true); #endif // !_TOOLS + + return true; } //----------------------------------------------------------------------------- // Purpose: terminal window shutdown +// Output : true on success, false otherwise //----------------------------------------------------------------------------- -void Console_Shutdown() +bool Console_Shutdown() { /////////////////////////////////////////////////////////////////////////// // Destroy the console window @@ -148,8 +152,10 @@ void Console_Shutdown() snprintf(szBuf, sizeof(szBuf), "Failed to destroy console window! [%s]\n", std::system_category().message(static_cast(::GetLastError())).c_str()); OutputDebugStringA(szBuf); - return; + return false; } + + return true; } #ifndef _TOOLS diff --git a/r5dev/windows/console.h b/r5dev/windows/console.h index 6a0e4d41..bd7c6559 100644 --- a/r5dev/windows/console.h +++ b/r5dev/windows/console.h @@ -3,5 +3,5 @@ void SetConsoleBackgroundColor(COLORREF color); void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color); -void Console_Init(const bool bAnsiColor); -void Console_Shutdown(); +bool Console_Init(const bool bAnsiColor); +bool Console_Shutdown(); From 88bb1307bea80b7813a526eb42558a0e5d34c45b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 14 Apr 2024 23:25:36 +0200 Subject: [PATCH 043/113] Engine: move unrestricted command exec code to separate function --- r5dev/engine/cmd.cpp | 73 +++++++++++++++++++++++++++++++++ r5dev/engine/cmd.h | 4 ++ r5dev/engine/server/sv_rcon.cpp | 52 +---------------------- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/r5dev/engine/cmd.cpp b/r5dev/engine/cmd.cpp index 6b78bc74..fb52a7f8 100644 --- a/r5dev/engine/cmd.cpp +++ b/r5dev/engine/cmd.cpp @@ -110,6 +110,79 @@ bool Cmd_ForwardToServer(const CCommand* args) #endif // DEDICATED } +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: execute commands directly (ignores all protection flags) +// Input : *pCommandString - +// *pValueString - +// Output : true on success, false otherwise +// +// NOTE : this function is dangerous, as it allows execution of any command +// without restrictions. Currently, this is only enabled on the +// dedicated server for the local console input and RCON, as they both +// are considered secure (local console needs physical access to the +// terminal application, RCON requires authentication and its protocol +// is secure. Do not use this anywhere else without a valid reason !!! +// +// NOTE : if client support is ever considered (unlikely), then the convar +// flag 'FCVAR_MATERIAL_THREAD_MASK' probably needs to be taken into +// account as well, also, change the DLL context of the warning to +// ENGINE if the client ever utilizes this. +//----------------------------------------------------------------------------- +bool Cmd_ExecuteUnrestricted(const char* const pCommandString, const char* const pValueString) +{ + ConCommandBase* const pCommandBase = g_pCVar->FindCommandBase(pCommandString); + + if (!pCommandBase) + { + // Found nothing. + Warning(eDLL_T::SERVER, "Command '%s' doesn't exist; request '%s' ignored\n", pCommandString, pValueString); + return false; + } + + if (pCommandBase->IsFlagSet(FCVAR_SERVER_FRAME_THREAD)) + ThreadJoinServerJob(); + + if (!pCommandBase->IsCommand()) + { + // Here we want to skip over the command string in the value buffer. + // So if we got 'sv_cheats 1' in our value buffer, we want to skip + // over 'sv_cheats ', so that we are pointing directly to the value. + const char* pFound = V_strstr(pValueString, pCommandString); + const char* pValue = nullptr; + + if (pFound) + { + pValue = pFound + V_strlen(pCommandString); + + // Skip any leading space characters. + while (*pValue == ' ') + { + ++pValue; + } + } + + ConVar* const pConVar = reinterpret_cast(pCommandBase); + pConVar->SetValue(pValue ? pValue : pValueString); + } + else // Invoke command callback directly. + { + CCommand cmd; + + // Only tokenize if we actually have strings in the value buffer, some + // commands (like 'status') don't need any additional parameters. + if (VALID_CHARSTAR(pValueString)) + { + cmd.Tokenize(pValueString, cmd_source_t::kCommandSrcCode); + } + + v_Cmd_Dispatch(ECommandTarget_t::CBUF_SERVER, pCommandBase, &cmd, false); + } + + return true; +} +#endif // !CLIENT_DLL + /////////////////////////////////////////////////////////////////////////////// void VCmd::Detour(const bool bAttach) const { diff --git a/r5dev/engine/cmd.h b/r5dev/engine/cmd.h index da1caa37..915d218e 100644 --- a/r5dev/engine/cmd.h +++ b/r5dev/engine/cmd.h @@ -26,6 +26,10 @@ FORCEINLINE ECommandTarget_t Cbuf_GetCurrentPlayer(void) extern bool Cbuf_HasRoomForExecutionMarkers(const int cExecutionMarkers); extern bool Cbuf_AddTextWithMarkers(const char* text, const ECmdExecutionMarker markerLeft, const ECmdExecutionMarker markerRight); +#ifndef CLIENT_DLL +extern bool Cmd_ExecuteUnrestricted(const char* const pCommandString, const char* const pValueString); +#endif // CLIENT_DLL + /* ==== COMMAND_BUFFER ================================================================================================================================================== */ inline void(*Cbuf_AddText)(ECommandTarget_t eTarget, const char* pText, cmd_source_t cmdSource); inline void(*Cbuf_AddExecutionMarker)(ECommandTarget_t target, ECmdExecutionMarker marker); diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index 0c759b88..92c74b1b 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -514,57 +514,7 @@ bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen) //----------------------------------------------------------------------------- void CRConServer::Execute(const netcon::request& request) const { - const string& commandString = request.requestmsg(); - const char* const pCommandString = commandString.c_str(); - - ConCommandBase* pCommandBase = g_pCVar->FindCommandBase(pCommandString); - - if (!pCommandBase) - { - // Found nothing. - return; - } - - const char* const pValueString = request.requestval().c_str(); - - if (pCommandBase->IsFlagSet(FCVAR_SERVER_FRAME_THREAD)) - ThreadJoinServerJob(); - - if (!pCommandBase->IsCommand()) - { - // Here we want to skip over the command string in the value buffer. - // So if we got 'sv_cheats 1' in our value buffer, we want to skip - // over 'sv_cheats ', so that we are pointing directly to the value. - const char* pFound = V_strstr(pValueString, pCommandString); - const char* pValue = nullptr; - - if (pFound) - { - pValue = pFound + commandString.length(); - - // Skip any leading space characters. - while (*pValue == ' ') - { - ++pValue; - } - } - - ConVar* pConVar = reinterpret_cast(pCommandBase); - pConVar->SetValue(pValue ? pValue : pValueString); - } - else // Invoke command callback directly. - { - CCommand cmd; - - // Only tokenize if we actually have strings in the value buffer, some - // commands (like 'status') don't need any additional parameters. - if (VALID_CHARSTAR(pValueString)) - { - cmd.Tokenize(pValueString, cmd_source_t::kCommandSrcCode); - } - - v_Cmd_Dispatch(ECommandTarget_t::CBUF_SERVER, pCommandBase, &cmd, false); - } + Cmd_ExecuteUnrestricted(request.requestmsg().c_str(), request.requestval().c_str()); } //----------------------------------------------------------------------------- From b201ca7a5b9f4424eb108ea0a38891f7cf6c5e47 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 15 Apr 2024 23:58:16 +0200 Subject: [PATCH 044/113] Engine: fix incorrect assignment on rcon socket bind The assignment on the ternary operator should be flipped, bug was spotted during beta testing. --- r5dev/engine/server/sv_rcon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index 92c74b1b..b9fb9e71 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -89,7 +89,7 @@ void CRConServer::Init(const char* pPassword, const char* pNetKey) return; } - const char* pszAddress = sv_rcon_useloopbacksocket.GetBool() ? NET_IPV6_UNSPEC : NET_IPV6_LOOPBACK; + const char* pszAddress = sv_rcon_useloopbacksocket.GetBool() ? NET_IPV6_LOOPBACK : NET_IPV6_UNSPEC; m_Address.SetFromString(Format("[%s]:%i", pszAddress, hostport->GetInt()).c_str(), true); m_Socket.CreateListenSocket(m_Address); From 59d4affebe9c7ddb5e883c737c08fa78eb4b6f6b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 16 Apr 2024 02:10:08 +0200 Subject: [PATCH 045/113] Server: removed unreferenced local variable Unused variable as current time calculation ended up being unnecessary, removed to suppress compiler warning. --- r5dev/game/server/player_command.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/r5dev/game/server/player_command.cpp b/r5dev/game/server/player_command.cpp index b91c34c5..cf40bc61 100644 --- a/r5dev/game/server/player_command.cpp +++ b/r5dev/game/server/player_command.cpp @@ -25,8 +25,6 @@ CPlayerMove::CPlayerMove(void) void CPlayerMove::StaticRunCommand(CPlayerMove* thisp, CPlayer* player, CUserCmd* ucmd, IMoveHelper* moveHelper) { CClientExtended* const cle = g_pServer->GetClientExtended(player->GetEdict() - 1); - - const float playerCurTime = (player->m_lastUCmdSimulationRemainderTime * TICK_INTERVAL) + player->m_totalExtraClientCmdTimeAttempted; float playerFrameTime; // Always default to clamped UserCmd frame time if this cvar is set From 9de5f4988fbdcf59e0b8da75ebc043c8ef4718fd Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 16 Apr 2024 02:17:41 +0200 Subject: [PATCH 046/113] RTech: fixed streamed pak decoding progression bug During beta tests on a Linux system, we encountered an issue where the I/O could be slower and thus result in not enough bytes being streamed by the time we invoke the decoder (lenStreamed == bufSizeNeeded at this point), after 16 calls with lenStreamed == bufSizeNeeded, the engine errors as ZSTD_NO_FORWARD_PROGRESS_MAX would be reached. Added value of 'ZSTD_nextSrcSizeToDecompress()' to 'PakDecoder_s::bufferSizeNeeded' to make sure we never call the decoder without any new streamed bytes. Also increased the value of ZSTD_NO_FORWARD_PROGRESS_MAX to 1024 since this fixed the issue without applying the aforementioned patch, this was increased as a hardening measure. --- r5dev/rtech/pak/pakdecode.cpp | 7 ++++--- r5dev/thirdparty/zstd/CMakeLists.txt | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/r5dev/rtech/pak/pakdecode.cpp b/r5dev/rtech/pak/pakdecode.cpp index 7037c264..c9075521 100644 --- a/r5dev/rtech/pak/pakdecode.cpp +++ b/r5dev/rtech/pak/pakdecode.cpp @@ -620,7 +620,8 @@ bool Pak_ZStdStreamDecode(PakDecoder_s* const decoder, const PakRingBufferFrame_ inFrame.frameLen, NULL }; - const size_t ret = ZSTD_decompressStream(decoder->zstreamContext, &outBuffer, &inBuffer); + ZSTD_DStream* const dctx = decoder->zstreamContext; + const size_t ret = ZSTD_decompressStream(dctx, &outBuffer, &inBuffer); if (ZSTD_isError(ret)) { @@ -646,14 +647,14 @@ bool Pak_ZStdStreamDecode(PakDecoder_s* const decoder, const PakRingBufferFrame_ // // if the input stream has fully decoded, this should equal the size of the // encoded pak file - decoder->bufferSizeNeeded = decoder->inBufBytePos; + decoder->bufferSizeNeeded = decoder->inBufBytePos + ZSTD_nextSrcSizeToDecompress(dctx); const bool decoded = ret == NULL; // zstd decoder no longer necessary at this point, deallocate if (decoded) { - ZSTD_freeDStream(decoder->zstreamContext); + ZSTD_freeDStream(dctx); decoder->zstreamContext = nullptr; } diff --git a/r5dev/thirdparty/zstd/CMakeLists.txt b/r5dev/thirdparty/zstd/CMakeLists.txt index 9f500816..36e490ee 100644 --- a/r5dev/thirdparty/zstd/CMakeLists.txt +++ b/r5dev/thirdparty/zstd/CMakeLists.txt @@ -94,5 +94,6 @@ thirdparty_suppress_warnings() target_compile_definitions( ${PROJECT_NAME} PRIVATE "ZSTD_MULTITHREAD" + "ZSTD_NO_FORWARD_PROGRESS_MAX=1024" "DEBUGLEVEL=0" ) From 8ffb647686770a2a030b6228c7b85d37375c0cb9 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:47:58 +0200 Subject: [PATCH 047/113] Server: use correct type for hull data used for AI Network System uses a CVarBitVec for this hull block data. --- r5dev/game/server/ai_network.cpp | 6 ++++-- r5dev/game/server/ai_network.h | 9 ++------- r5dev/game/server/ai_networkmanager.cpp | 19 +++++++++---------- r5dev/game/server/ai_node.h | 13 ++++++++----- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/r5dev/game/server/ai_network.cpp b/r5dev/game/server/ai_network.cpp index 3604cbd5..2e5591b5 100644 --- a/r5dev/game/server/ai_network.cpp +++ b/r5dev/game/server/ai_network.cpp @@ -63,11 +63,13 @@ int CAI_Network::NumLinks(void) const //----------------------------------------------------------------------------- // Purpose: gets the number of zones +// input : idx - // Output : int //----------------------------------------------------------------------------- -int CAI_Network::NumZones(void) const +int CAI_Network::NumZones(const int idx) const { - return m_iNumZones; + Assert(idx >= 0 && idx < sizeof(m_iNumZones)); + return m_iNumZones[idx]; } //----------------------------------------------------------------------------- diff --git a/r5dev/game/server/ai_network.h b/r5dev/game/server/ai_network.h index ee71feb4..0d81cbfb 100644 --- a/r5dev/game/server/ai_network.h +++ b/r5dev/game/server/ai_network.h @@ -12,7 +12,7 @@ public: static void DebugConnectMsg(int node1, int node2, const char* pszFormat, ...); void* GetVTable(void) const; int NumLinks(void) const; - int NumZones(void) const; + int NumZones(const int idx) const; int NumHints(void) const; int NumScriptNodes(void) const; int NumPathNodes(void) const; @@ -32,12 +32,7 @@ public: int m_nUnk0; CAI_HullData m_HullData[MAX_HULLS]; - - int m_iNumZones; // +0x0088 - int m_iUnkCount0; - int m_iUnkCount1; - int m_iUnkCount2; - int m_iUnkCount4; + int m_iNumZones[MAX_HULLS]; // +0x0088 // unk8 on disk int unk5; // +0x009C diff --git a/r5dev/game/server/ai_networkmanager.cpp b/r5dev/game/server/ai_networkmanager.cpp index 4b8f6abc..f8d8c015 100644 --- a/r5dev/game/server/ai_networkmanager.cpp +++ b/r5dev/game/server/ai_networkmanager.cpp @@ -225,19 +225,18 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork) // Dump the hull data blocks // ------------------------------- - // Pointer to numZones counter, incremented up and until - // the last counter field for the hull data block. - int* countPtr = &pNetwork->m_iNumZones; - - for (int i = 0; i < MAX_HULLS; i++, countPtr++) + for (int i = 0; i < MAX_HULLS; i++) { const CAI_HullData& hullData = pNetwork->m_HullData[i]; - const int bufferSize = sizeof(int) * hullData.unk1; + const int numHullZones = pNetwork->m_iNumZones[i]; - buf.PutInt(*countPtr); - buf.PutShort(hullData.m_Count); - buf.PutShort(hullData.unk1); - buf.Put(hullData.pBuffer, bufferSize); + const unsigned short numHullBits = (unsigned short)hullData.m_bitVec.GetNumBits(); + const unsigned short numHullInts = (unsigned short)hullData.m_bitVec.GetNumDWords(); + + buf.PutInt(numHullZones); + buf.PutUnsignedShort(numHullBits); + buf.PutUnsignedShort(numHullInts); + buf.Put(hullData.m_bitVec.Base(), numHullInts * sizeof(int)); } timer.End(); diff --git a/r5dev/game/server/ai_node.h b/r5dev/game/server/ai_node.h index 96a455ea..a315375d 100644 --- a/r5dev/game/server/ai_node.h +++ b/r5dev/game/server/ai_node.h @@ -5,6 +5,7 @@ //=============================================================================// #pragma once #include "mathlib/vector.h" +#include "mathlib/bitvec.h" constexpr int MAX_HULLS = 5; constexpr int NOT_CACHED = -2; // Returned if data not in cache @@ -153,13 +154,15 @@ struct CAI_ScriptNode }; //============================================================================= -// >> CAI_ScriptNode +// >> CAI_HullData //============================================================================= struct CAI_HullData { - short m_Count; // Multiplied by 4; probably total buffer size. - short unk1; - int unk2; - void* pBuffer; // Hull data buffer. + CVarBitVec m_bitVec; + + // Unknown, possible part of CVarBitVec ??? see [r5apex_ds + 1A52B0] if, + // this is part of CVarBitVec, it seems to be unused in any of the + // compiled CVarBitVec and CLargeVarBitVec methods so i think it should be + // just part of this struct. char unk3[8]; }; From d80268492a3a741bcd60f4760dd530192f026863 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:48:17 +0200 Subject: [PATCH 048/113] Tier1: fix typo in byteswap.h --- r5dev/public/tier1/byteswap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/public/tier1/byteswap.h b/r5dev/public/tier1/byteswap.h index d6290acb..e342fc6e 100644 --- a/r5dev/public/tier1/byteswap.h +++ b/r5dev/public/tier1/byteswap.h @@ -183,7 +183,7 @@ public: inputBuffer = outputBuffer; } - // Are we already the correct endienness? ( or are we swapping 1 byte items? ) + // Are we already the correct endianness? ( or are we swapping 1 byte items? ) if (!m_bSwapBytes || (sizeof(T) == 1)) { // If we were just going to swap in place then return. From 29ff073ae3bb21f37d28d9373fc255c3ad2ebf10 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:51:51 +0200 Subject: [PATCH 049/113] NetConsole: fix command line bug Recently, encryption was implemented in the RCON system, but the command line initialization code wasn't adapted to this new logic. Code has now been adapted. --- r5dev/netconsole/netconsole.cpp | 97 +++++++++++++++++++++++---------- r5dev/netconsole/netconsole.h | 7 ++- 2 files changed, 72 insertions(+), 32 deletions(-) diff --git a/r5dev/netconsole/netconsole.cpp b/r5dev/netconsole/netconsole.cpp index 0543388a..4503e22b 100644 --- a/r5dev/netconsole/netconsole.cpp +++ b/r5dev/netconsole/netconsole.cpp @@ -24,7 +24,7 @@ CNetCon::CNetCon(void) : m_bInitialized(false) , m_bQuitting(false) , m_bPromptConnect(true) - , m_bEncryptFrames(true) + , m_bEncryptFrames(false) , m_flTickInterval(0.05f) { // Empty character set used for ip addresses if we still need to initiate a @@ -44,7 +44,7 @@ CNetCon::~CNetCon(void) // Purpose: WSA and NETCON systems init // Output : true on success, false otherwise //----------------------------------------------------------------------------- -bool CNetCon::Init(const bool bAnsiColor, const char* pHostName, const int nPort) +bool CNetCon::Init(const bool bAnsiColor, const char* pAdr, const char* pKey) { std::lock_guard l(m_Mutex); @@ -60,12 +60,20 @@ bool CNetCon::Init(const bool bAnsiColor, const char* pHostName, const int nPort return false; } - // Try to connect from given parameters, these are passed in from the - // command line. If we fail, return out as this allows the user to - // quickly retry again. - if (pHostName && nPort != SOCKET_ERROR) + // Install the encryption key and enable encryption if this has been passed + // in by the user. + if (pKey) { - if (!Connect(pHostName, nPort)) + SetKey(pKey, true); + m_bEncryptFrames = true; + } + + // Try and connect to the giver remote address if this has been passed in + // by the user. If we fail, return out as this allows the user to quickly + // try again. + if (pAdr) + { + if (!Connect(pAdr)) { return false; } @@ -176,6 +184,24 @@ void CNetCon::TermSetup(const bool bAnsiColor) SpdLog_InstallSupplementalLogger("supplemental_logger_mt", "netconsole.log"); } +//----------------------------------------------------------------------------- +// Purpose: tries to set the passed in netkey, falls back to default on failure +//----------------------------------------------------------------------------- +void CNetCon::TrySetKey(const char* const pKey) +{ + if (!*pKey) + { + Warning(eDLL_T::CLIENT, "No key provided; using default %s'%s%s%s'\n", + g_svReset, g_svGreyB, DEFAULT_NET_ENCRYPTION_KEY, g_svReset); + + SetKey(DEFAULT_NET_ENCRYPTION_KEY, true); + } + else + { + SetKey(pKey, true); + } +} + //----------------------------------------------------------------------------- // Purpose: gets input IP and port for initialization //----------------------------------------------------------------------------- @@ -254,23 +280,9 @@ void CNetCon::RunInput(const string& lineInput) return; } - if (!*inKey) - { - Warning(eDLL_T::CLIENT, "No key provided; using default %s'%s%s%s'\n", - g_svReset, g_svGreyB, DEFAULT_NET_ENCRYPTION_KEY, g_svReset); - - SetKey(DEFAULT_NET_ENCRYPTION_KEY, true); - } - else - { - SetKey(inKey, true); - } - + TrySetKey(inKey); m_bEncryptFrames = true; - Msg(eDLL_T::CLIENT, "Attempting connection to '%s' with key %s'%s%s%s'\n", - inAdr, g_svReset, g_svGreyB, GetKey(), g_svReset); - if (!Connect(inAdr)) { SetPrompting(true); @@ -282,8 +294,6 @@ void CNetCon::RunInput(const string& lineInput) const char* inAdr = cmd.GetCommandString(); m_bEncryptFrames = false; - Msg(eDLL_T::CLIENT, "Attempting connection to '%s'\n", inAdr); - if (!Connect(inAdr)) { SetPrompting(true); @@ -354,6 +364,28 @@ void CNetCon::SetPrompting(const bool bPrompt) m_bPromptConnect = bPrompt; } +//----------------------------------------------------------------------------- +// Purpose: connect to remote +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool CNetCon::Connect(const char* pHostName, const int nPort) +{ + Assert(nPort == SOCKET_ERROR, "Port should be part of the address on the CNetCon implementation!"); + NOTE_UNUSED(nPort); + + if (m_bEncryptFrames) + { + Msg(eDLL_T::CLIENT, "Attempting connection to '%s' with key %s'%s%s%s'\n", + pHostName, g_svReset, g_svGreyB, GetKey(), g_svReset); + } + else + { + Msg(eDLL_T::CLIENT, "Attempting connection to '%s'\n", pHostName); + } + + return CL_NetConConnect(this, pHostName, SOCKET_ERROR); +} + //----------------------------------------------------------------------------- // Purpose: disconnect from current session // Input : *szReason - @@ -487,16 +519,21 @@ int main(int argc, char* argv[]) } } - const char* pHostName = nullptr; - int nPort = SOCKET_ERROR; + // The address and key from command line if passed in. + const char* pAdr = nullptr; + const char* pKey = nullptr; - if (argc >= 3) // Get IP and Port from command line. + if (argc >= 2) { - pHostName = argv[1]; - nPort = atoi(argv[2]); + pAdr = argv[1]; } - if (!NetConsole()->Init(bEnableColor, pHostName, nPort)) + if (argc >= 3) + { + pKey = argv[2]; + } + + if (!NetConsole()->Init(bEnableColor, pAdr, pKey)) { return EXIT_FAILURE; } diff --git a/r5dev/netconsole/netconsole.h b/r5dev/netconsole/netconsole.h index 6a9f8b73..ef2f5f91 100644 --- a/r5dev/netconsole/netconsole.h +++ b/r5dev/netconsole/netconsole.h @@ -16,7 +16,7 @@ public: CNetCon(void); ~CNetCon(void); - bool Init(const bool bAnsiColor, const char* pHostName = nullptr, const int nPort = SOCKET_ERROR); + bool Init(const bool bAnsiColor, const char* pAdr = nullptr, const char* pKey = nullptr); bool Shutdown(void); void TermSetup(const bool bAnsiColor); @@ -32,9 +32,12 @@ public: inline float GetTickInterval() const { return m_flTickInterval; } static BOOL WINAPI CloseHandler(DWORD eventCode); - virtual void Disconnect(const char* szReason = nullptr); + virtual bool Connect(const char* pHostName, const int nHostPort = SOCKET_ERROR) override; + virtual void Disconnect(const char* szReason = nullptr) override; + virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override; + void TrySetKey(const char* const pKey); bool Serialize(vector& vecBuf, const char* szReqBuf, const char* szReqVal, const netcon::request_e requestType) const; From 4c99efa88948fa17785d0a14062b871ea3c57e66 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:26:03 +0200 Subject: [PATCH 050/113] CppKore: try parent font if current is absent This allows for setting uniform fonts on all controls, by only assigning the font once to the parent control. Else each control needs to have its own set. --- r5dev/thirdparty/cppnet/cppkore/Control.cpp | 7 ++++++- r5dev/thirdparty/cppnet/cppkore/Control.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/r5dev/thirdparty/cppnet/cppkore/Control.cpp b/r5dev/thirdparty/cppnet/cppkore/Control.cpp index e52fa063..cb977402 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Control.cpp +++ b/r5dev/thirdparty/cppnet/cppkore/Control.cpp @@ -231,8 +231,13 @@ namespace Forms SetWindowLongPtrA(this->_Handle, GWLP_USERDATA, (intptr_t)this); // Setup the default font if none was previously set + if (this->_Font == nullptr) - this->_Font = std::make_unique(this->_Handle, (HFONT)GetStockObject(DEFAULT_GUI_FONT)); + if (this->_Parent && this->_Parent->_Font) + this->_Font = std::make_unique(this->_Handle, this->_Parent->_Font.get()->GetFontHandle()); + else + this->_Font = std::make_unique(this->_Handle, (HFONT)GetStockObject(DEFAULT_GUI_FONT)); + // Notify the window of the font selection SendMessageA(this->_Handle, WM_SETFONT, (WPARAM)this->_Font->GetFontHandle(), NULL); diff --git a/r5dev/thirdparty/cppnet/cppkore/Control.h b/r5dev/thirdparty/cppnet/cppkore/Control.h index 15a19e50..87ffbda7 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Control.h +++ b/r5dev/thirdparty/cppnet/cppkore/Control.h @@ -146,7 +146,7 @@ namespace Forms // Retrieves the current font for this control. Drawing::Font* GetFont(); - // Retrieves the current font for this control. + // Sets the current font for this control. void SetFont(Drawing::Font* Font); // The parent of this control. From d5db4674a46a4070b12427bff3ca9936eef0d8aa Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:26:42 +0200 Subject: [PATCH 051/113] CppKore: add getter for child control count --- r5dev/thirdparty/cppnet/cppkore/Control.cpp | 5 +++++ r5dev/thirdparty/cppnet/cppkore/Control.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/r5dev/thirdparty/cppnet/cppkore/Control.cpp b/r5dev/thirdparty/cppnet/cppkore/Control.cpp index cb977402..d3ce62e5 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Control.cpp +++ b/r5dev/thirdparty/cppnet/cppkore/Control.cpp @@ -725,6 +725,11 @@ namespace Forms return this->_RTTI; } + uint32_t Control::GetControlCount() + { + return this->_Controls->Count(); + } + Control* Control::FindForm() { auto Cur = this; diff --git a/r5dev/thirdparty/cppnet/cppkore/Control.h b/r5dev/thirdparty/cppnet/cppkore/Control.h index 87ffbda7..978b70c2 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Control.h +++ b/r5dev/thirdparty/cppnet/cppkore/Control.h @@ -209,6 +209,8 @@ namespace Forms HWND GetHandle(); // Returns the type of this control ControlTypes GetType(); + // Returns the number of child controls + uint32_t GetControlCount(); // Retrieves the form that the control is on. Control* FindForm(); From 8e81d99585d11386546c83c61f3b7eaa486eb92a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:29:33 +0200 Subject: [PATCH 052/113] CppKore: fix potential font resource leak As of commit 168ad9aabd624510045d56aabcbfeff6f4aaad6f, we can assign uniform fonts to all child controls, but only 1 control can own the font resource. This is by default false since we do not want to free the resource when destroying the child controls, but we do want to free it once the parent window gets destroyed. --- r5dev/thirdparty/cppnet/cppkore/Font.cpp | 4 ++-- r5dev/thirdparty/cppnet/cppkore/Font.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/r5dev/thirdparty/cppnet/cppkore/Font.cpp b/r5dev/thirdparty/cppnet/cppkore/Font.cpp index c3739fb7..0b5a7aa2 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Font.cpp +++ b/r5dev/thirdparty/cppnet/cppkore/Font.cpp @@ -3,8 +3,8 @@ namespace Drawing { - Font::Font(HWND Handle, const HFONT hFont) - : _Handle(Handle), _NativeFont(hFont), _OwnsFont(false) + Font::Font(HWND Handle, const HFONT hFont, const bool OwnsFont) + : _Handle(Handle), _NativeFont(hFont), _OwnsFont(OwnsFont) { } diff --git a/r5dev/thirdparty/cppnet/cppkore/Font.h b/r5dev/thirdparty/cppnet/cppkore/Font.h index c8fdaf23..e616ab5c 100644 --- a/r5dev/thirdparty/cppnet/cppkore/Font.h +++ b/r5dev/thirdparty/cppnet/cppkore/Font.h @@ -10,7 +10,7 @@ namespace Drawing { public: Font() = default; - Font(HWND Handle, const HFONT hFont); + Font(HWND Handle, const HFONT hFont, const bool OwnsFont = false); Font(HWND Handle, const Gdiplus::Font& FontObject); virtual ~Font(); From dc8a22c05e92f5f93926cc849170eaa9709e06af Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:44:54 +0200 Subject: [PATCH 053/113] Windows: move console color init code to separate function Reserve Console_Init() for actual console init, if code only needs colors (e.g. a console application that already has a console), then they should call Console_ColorInit(). --- r5dev/revpk/revpk.cpp | 11 +++++--- r5dev/windows/console.cpp | 54 +++++++++++++++++++++++++++------------ r5dev/windows/console.h | 3 ++- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/r5dev/revpk/revpk.cpp b/r5dev/revpk/revpk.cpp index 240d0aa9..b6fc6842 100644 --- a/r5dev/revpk/revpk.cpp +++ b/r5dev/revpk/revpk.cpp @@ -25,7 +25,7 @@ #define FRONTEND_ENABLE_FILE "enable.txt" static CKeyValuesSystem s_KeyValuesSystem; -static CFileSystem_Stdio g_FullFileSystem; +static CFileSystem_Stdio s_FullFileSystem; static bool s_bUseAnsiColors = true; //----------------------------------------------------------------------------- @@ -41,7 +41,7 @@ IKeyValuesSystem* KeyValuesSystem() //----------------------------------------------------------------------------- CFileSystem_Stdio* FileSystem() { - return &g_FullFileSystem; + return &s_FullFileSystem; } //----------------------------------------------------------------------------- @@ -51,10 +51,15 @@ static void ReVPK_Init() { CheckSystemCPUForSSE2(); + // Init time. + Plat_FloatTime(); + g_CoreMsgVCallback = EngineLoggerSink; lzham_enable_fail_exceptions(true); - Console_Init(s_bUseAnsiColors); + if (s_bUseAnsiColors) + Console_ColorInit(); + SpdLog_Init(s_bUseAnsiColors); } diff --git a/r5dev/windows/console.cpp b/r5dev/windows/console.cpp index 3324fd0c..4752ae99 100644 --- a/r5dev/windows/console.cpp +++ b/r5dev/windows/console.cpp @@ -81,20 +81,23 @@ void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color) //----------------------------------------------------------------------------- bool Console_Init(const bool bAnsiColor) { -#ifndef _TOOLS + char msgBuf[2048]; + /////////////////////////////////////////////////////////////////////////// // Create the console window if (AllocConsole() == FALSE) { - char szBuf[2048]; - snprintf(szBuf, sizeof(szBuf), "Failed to create console window! [%s]\n", std::system_category().message(static_cast(::GetLastError())).c_str()); + snprintf(msgBuf, sizeof(msgBuf), "Failed to create console window! [%s]\n", + std::system_category().message(static_cast(::GetLastError())).c_str()); - OutputDebugStringA(szBuf); + OutputDebugStringA(msgBuf); return false; } +#ifndef _TOOLS //-- Set the window title SetConsoleTitleA("R5"); +#endif // !_TOOLS //-- Open input/output streams FILE* fDummy; @@ -102,6 +105,7 @@ bool Console_Init(const bool bAnsiColor) freopen_s(&fDummy, "CONOUT$", "w", stdout); freopen_s(&fDummy, "CONOUT$", "w", stderr); +#ifndef _TOOLS //-- Create a worker thread to process console commands DWORD dwThreadId = NULL; DWORD __stdcall ProcessConsoleWorker(LPVOID); @@ -113,22 +117,16 @@ bool Console_Init(const bool bAnsiColor) } #endif // !_TOOLS - HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD dwMode = NULL; - if (bAnsiColor) { - GetConsoleMode(hOutput, &dwMode); - dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; - - if (!SetConsoleMode(hOutput, dwMode)) // Some editions of Windows have 'VirtualTerminalLevel' disabled by default. + if (!Console_ColorInit()) { - // Warn the user if 'VirtualTerminalLevel' could not be set on users environment. - MessageBoxA(NULL, "Failed to set console mode 'VirtualTerminalLevel'; please disable ansi-colors and restart the program if output logging appears distorted.", "SDK Warning", MB_ICONEXCLAMATION | MB_OK); - } + Assert(0); + //snprintf(msgBuf, sizeof(msgBuf), "Failed to set color console mode! [%s]\n", + // std::system_category().message(static_cast(::GetLastError())).c_str()); - SetConsoleBackgroundColor(0x00000000); - AnsiColors_Init(); + //MessageBoxA(NULL, msgBuf, "SDK Warning", MB_ICONEXCLAMATION | MB_OK); + } } #ifndef _TOOLS @@ -138,6 +136,27 @@ bool Console_Init(const bool bAnsiColor) return true; } +//----------------------------------------------------------------------------- +// Purpose: terminal color setup +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool Console_ColorInit() +{ + HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = NULL; + + GetConsoleMode(hOutput, &dwMode); // Some editions of Windows have 'VirtualTerminalLevel' disabled by default. + dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; + + if (!SetConsoleMode(hOutput, dwMode)) + return false; // Failure. + + SetConsoleBackgroundColor(0x00000000); + AnsiColors_Init(); + + return true; +} + //----------------------------------------------------------------------------- // Purpose: terminal window shutdown // Output : true on success, false otherwise @@ -149,7 +168,8 @@ bool Console_Shutdown() if (FreeConsole() == FALSE) { char szBuf[2048]; - snprintf(szBuf, sizeof(szBuf), "Failed to destroy console window! [%s]\n", std::system_category().message(static_cast(::GetLastError())).c_str()); + snprintf(szBuf, sizeof(szBuf), "Failed to destroy console window! [%s]\n", + std::system_category().message(static_cast(::GetLastError())).c_str()); OutputDebugStringA(szBuf); return false; diff --git a/r5dev/windows/console.h b/r5dev/windows/console.h index bd7c6559..32e89915 100644 --- a/r5dev/windows/console.h +++ b/r5dev/windows/console.h @@ -3,5 +3,6 @@ void SetConsoleBackgroundColor(COLORREF color); void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color); -bool Console_Init(const bool bAnsiColor); +bool Console_Init(const bool bAnsiColor, const bool bWarn = true); +bool Console_ColorInit(); bool Console_Shutdown(); From 5d680c89d98c72d43fb45169604f6f780c60a39c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:47:02 +0200 Subject: [PATCH 054/113] Windows: fix prototype mismatch Mismatched since commit acaf3fdfad319cea142ba58ce9214aec14715ff0. --- r5dev/windows/console.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/windows/console.h b/r5dev/windows/console.h index 32e89915..609f9bb3 100644 --- a/r5dev/windows/console.h +++ b/r5dev/windows/console.h @@ -3,6 +3,6 @@ void SetConsoleBackgroundColor(COLORREF color); void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color); -bool Console_Init(const bool bAnsiColor, const bool bWarn = true); +bool Console_Init(const bool bAnsiColor); bool Console_ColorInit(); bool Console_Shutdown(); From 861b4b6b2bdbf581321c2a19981acbcd22150c26 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:49:22 +0200 Subject: [PATCH 055/113] Launcher: surface and launcher code overhaul - SDK Launcher is now a proper GUI app (no longer defaults to terminal, but can of course still be used in the terminal). - Set uniform font on all controls (GetStockObject sometimes returns fonts that isn't currently supported on the UI layout causing text to clip; we don't show in other languages or character encodings so we should just default to Microsoft Sans Serif). - Make anchors uniform for all controls (resize not yet supported). - Don't attempt to send commands to game instances if command string is null or empty. - Clamp surface console list size to window size. - Remove surface console logger boilerplate (surface logging is now a dedicated function). - Use actual SDK logging system for console prints/warnings/errors. - Fixed bug where the use of a shared stack buffer caused truncated parts of the file name to end up in the command line text. --- r5dev/sdklauncher/CMakeLists.txt | 21 ++++ r5dev/sdklauncher/basepanel.cpp | 120 ++++++++++++++------- r5dev/sdklauncher/basepanel.h | 6 +- r5dev/sdklauncher/sdklauncher.cpp | 166 ++++++++++++++++++++---------- r5dev/sdklauncher/sdklauncher.h | 34 ++---- 5 files changed, 226 insertions(+), 121 deletions(-) diff --git a/r5dev/sdklauncher/CMakeLists.txt b/r5dev/sdklauncher/CMakeLists.txt index be513530..624779da 100644 --- a/r5dev/sdklauncher/CMakeLists.txt +++ b/r5dev/sdklauncher/CMakeLists.txt @@ -3,7 +3,26 @@ add_module( "exe" "sdklauncher" "" ${FOLDER_CONTEXT} TRUE TRUE ) start_sources() +add_sources( SOURCE_GROUP "Foundation" + "${ENGINE_SOURCE_DIR}/tier0/plat_time.cpp" + "${ENGINE_SOURCE_DIR}/public/tier0/platform.h" +) + add_sources( SOURCE_GROUP "Core" + "${ENGINE_SOURCE_DIR}/core/logger.cpp" + "${ENGINE_SOURCE_DIR}/core/logger.h" + "${ENGINE_SOURCE_DIR}/core/logdef.cpp" + "${ENGINE_SOURCE_DIR}/core/logdef.h" + "${ENGINE_SOURCE_DIR}/core/termutil.cpp" + "${ENGINE_SOURCE_DIR}/core/termutil.h" +) + +add_sources( SOURCE_GROUP "Windows" + "${ENGINE_SOURCE_DIR}/windows/console.cpp" + "${ENGINE_SOURCE_DIR}/windows/console.h" +) + +add_sources( SOURCE_GROUP "App" "sdklauncher.cpp" "sdklauncher.h" "sdklauncher_const.h" @@ -29,11 +48,13 @@ set_target_properties( ${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "$(ProjectDir)../../../${BUILD_OUTPUT_DIR}/" ) target_compile_definitions( ${PROJECT_NAME} PRIVATE + "_TOOLS" "SDKLAUNCHER" ) target_precompile_headers( ${PROJECT_NAME} PRIVATE "sdklauncher_pch.h" ) +target_link_options( ${PROJECT_NAME} PRIVATE "/SUBSYSTEM:WINDOWS" ) target_link_libraries( ${PROJECT_NAME} PRIVATE "tier0" "tier1" diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index e145a917..60498406 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -11,6 +11,29 @@ extern CFileSystem_Stdio* FileSystem(); +//----------------------------------------------------------------------------- +// Purpose: creates a font by name +//----------------------------------------------------------------------------- +HFONT CreateFontByName(const char* const name, const int size) +{ + return CreateFont( + size, // Height of font + 0, // Width of font + 0, // Angle of escapement + 0, // Orientation angle + FW_NORMAL, // Font weight + FALSE, // Italic + FALSE, // Underline + FALSE, // Strikeout + DEFAULT_CHARSET, // Character set identifier + OUT_DEFAULT_PRECIS, // Output precision + CLIP_DEFAULT_PRECIS, // Clipping precision + DEFAULT_QUALITY, // Output quality + DEFAULT_PITCH | FF_DONTCARE, // Pitch and family + TEXT(name) // Font name + ); +} + //----------------------------------------------------------------------------- // Purpose: creates the surface layout //----------------------------------------------------------------------------- @@ -20,6 +43,9 @@ void CSurface::Init() const INT WindowX = 800; const INT WindowY = 353; + const HFONT font = (HFONT)CreateFontByName("Microsoft Sans Serif", -11); + this->SetFont(new Drawing::Font(this->_Handle, font, true)); + this->SuspendLayout(); this->SetAutoScaleDimensions({ 6, 13 }); this->SetAutoScaleMode(Forms::AutoScaleMode::Font); @@ -141,7 +167,7 @@ void CSurface::Init() this->m_PlaylistFileLabel->SetLocation({ 311, 32 }); this->m_PlaylistFileLabel->SetTabIndex(0); this->m_PlaylistFileLabel->SetText("Playlists file"); - this->m_PlaylistFileLabel->SetAnchor(Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Left); + this->m_PlaylistFileLabel->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_GameGroupExt->AddControl(this->m_PlaylistFileLabel); // ######################################################################## @@ -423,7 +449,7 @@ void CSurface::Init() this->m_WidthTextBox->SetTabIndex(0); this->m_WidthTextBox->SetReadOnly(false); this->m_WidthTextBox->SetText(""); - this->m_WidthTextBox->SetAnchor(Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Right); + this->m_WidthTextBox->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_EngineVideoGroup->AddControl(this->m_WidthTextBox); this->m_HeightTextBox = new UIX::UIXTextBox(); @@ -432,7 +458,7 @@ void CSurface::Init() this->m_HeightTextBox->SetTabIndex(0); this->m_HeightTextBox->SetReadOnly(false); this->m_HeightTextBox->SetText(""); - this->m_HeightTextBox->SetAnchor(Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Right); + this->m_HeightTextBox->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_EngineVideoGroup->AddControl(this->m_HeightTextBox); this->m_ResolutionLabel = new UIX::UIXLabel(); @@ -452,7 +478,7 @@ void CSurface::Init() this->m_ConsoleGroup->SetLocation({ 359, 160 }); this->m_ConsoleGroup->SetTabIndex(0); this->m_ConsoleGroup->SetText("Console"); - this->m_ConsoleGroup->SetAnchor(Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Left | Forms::AnchorStyles::Right); + this->m_ConsoleGroup->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->AddControl(this->m_ConsoleGroup); this->m_ConsoleGroupExt = new UIX::UIXGroupBox(); @@ -460,7 +486,7 @@ void CSurface::Init() this->m_ConsoleGroupExt->SetLocation({ 359, 174 }); this->m_ConsoleGroupExt->SetTabIndex(0); this->m_ConsoleGroupExt->SetText(""); - this->m_ConsoleGroupExt->SetAnchor(Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Left | Forms::AnchorStyles::Right); + this->m_ConsoleGroupExt->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->AddControl(this->m_ConsoleGroupExt); this->m_ConsoleListView = new UIX::UIXListView(); @@ -468,7 +494,7 @@ void CSurface::Init() this->m_ConsoleListView->SetLocation({ 1, -23 }); // HACK: hide columns this->m_ConsoleListView->SetTabIndex(0); this->m_ConsoleListView->SetBackColor(Drawing::Color(29, 33, 37)); - this->m_ConsoleListView->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Left | Forms::AnchorStyles::Right); + this->m_ConsoleListView->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_ConsoleListView->SetView(Forms::View::Details); this->m_ConsoleListView->SetVirtualMode(true); this->m_ConsoleListView->SetFullRowSelect(true); @@ -484,7 +510,7 @@ void CSurface::Init() this->m_ConsoleCommandTextBox->SetTabIndex(0); this->m_ConsoleCommandTextBox->SetReadOnly(false); this->m_ConsoleCommandTextBox->SetText(""); - this->m_ConsoleCommandTextBox->SetAnchor(Forms::AnchorStyles::Bottom | Forms::AnchorStyles::Left); + this->m_ConsoleCommandTextBox->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_ConsoleGroupExt->AddControl(this->m_ConsoleCommandTextBox); this->m_ConsoleSendCommand = new UIX::UIXButton(); @@ -493,7 +519,7 @@ void CSurface::Init() this->m_ConsoleSendCommand->SetTabIndex(0); this->m_ConsoleSendCommand->SetText("Send"); this->m_ConsoleSendCommand->SetBackColor(Drawing::Color(3, 102, 214)); - this->m_ConsoleSendCommand->SetAnchor(Forms::AnchorStyles::None); + this->m_ConsoleSendCommand->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_ConsoleSendCommand->Click += &ForwardCommandToGame; this->m_ConsoleGroupExt->AddControl(this->m_ConsoleSendCommand); @@ -681,10 +707,7 @@ void CSurface::OnClose(const std::unique_ptr& /*pEventArgs //----------------------------------------------------------------------------- void CSurface::CleanSDK(Forms::Control* pSender) { - CSurface* pSurface = reinterpret_cast(pSender->FindForm()); - pSurface->m_LogList.push_back(LogList_t(spdlog::level::info, "Running cleaner for SDK installation\n")); - pSurface->m_ConsoleListView->SetVirtualListSize(static_cast(pSurface->m_LogList.size())); - + Msg(eDLL_T::COMMON, "Running cleaner for SDK installation\n"); std::system("bin\\clean_sdk.bat"); } @@ -694,10 +717,7 @@ void CSurface::CleanSDK(Forms::Control* pSender) //----------------------------------------------------------------------------- void CSurface::UpdateSDK(Forms::Control* pSender) { - CSurface* pSurface = reinterpret_cast(pSender->FindForm()); - pSurface->m_LogList.push_back(LogList_t(spdlog::level::info, "Running updater for SDK installation\n")); - pSurface->m_ConsoleListView->SetVirtualListSize(static_cast(pSurface->m_LogList.size())); - + Msg(eDLL_T::COMMON, "Running updater for SDK installation\n"); std::system("bin\\update_sdk.bat"); } @@ -708,19 +728,15 @@ void CSurface::UpdateSDK(Forms::Control* pSender) void CSurface::LaunchGame(Forms::Control* pSender) { CSurface* pSurface = reinterpret_cast(pSender->FindForm()); - - pSurface->m_LogList.clear(); // Clear console. - pSurface->m_ConsoleListView->SetVirtualListSize(0); - pSurface->m_ConsoleListView->Refresh(); - string svParameter; + pSurface->AppendParameterInternal(svParameter, "-launcher"); - eLaunchMode launchMode = g_Launcher.BuildParameter(svParameter); + eLaunchMode launchMode = SDKLauncher()->BuildParameter(svParameter); uint64_t nProcessorAffinity = pSurface->GetProcessorAffinity(svParameter); - if (g_Launcher.CreateLaunchContext(launchMode, nProcessorAffinity, svParameter.c_str(), "startup_launcher.cfg")) - g_Launcher.LaunchProcess(); + if (SDKLauncher()->CreateLaunchContext(launchMode, nProcessorAffinity, svParameter.c_str(), "startup_launcher.cfg")) + SDKLauncher()->LaunchProcess(); } //----------------------------------------------------------------------------- @@ -819,6 +835,26 @@ void CSurface::ReloadPlaylists(Forms::Control* pSender) pSurface->ParsePlaylists(); } +//----------------------------------------------------------------------------- +// Purpose: adds a log to the surface console +// Input : type - +// Input : *pszText - +//----------------------------------------------------------------------------- +void CSurface::AddLog(const LogType_t type, const char* const pszText) +{ + m_LogList.push_back(LogList_t(type, pszText)); + + // Clamp the log list size, as we cannot fit more elements than + // 8 in the console window. + while (m_LogList.size() > 8) + { + m_LogList.erase(m_LogList.begin()); + } + + m_ConsoleListView->SetVirtualListSize(static_cast(m_LogList.size())); + m_ConsoleListView->Refresh(); +} + //----------------------------------------------------------------------------- // Purpose: copies selected virtual items to clipboard // Input : &pEventArgs - @@ -859,30 +895,34 @@ void CSurface::GetVirtualItem(const std::unique_ptrSubItemIndex) { case 0: - pEventArgs->Style.ForeColor = cColor[pSurface->m_LogList[pEventArgs->ItemIndex].m_nLevel]; - pEventArgs->Text = svLevel[pSurface->m_LogList[pEventArgs->ItemIndex].m_nLevel]; + pEventArgs->Style.ForeColor = cColor[(int)pSurface->m_LogList[pEventArgs->ItemIndex].m_nLevel]; + pEventArgs->Text = svLevel[(int)pSurface->m_LogList[pEventArgs->ItemIndex].m_nLevel]; break; case 1: pEventArgs->Text = pSurface->m_LogList[pEventArgs->ItemIndex].m_svText; @@ -905,7 +945,11 @@ void CSurface::ForwardCommandToGame(Forms::Control* pSender) if (vecHandles.empty()) return; - const string kzCommand = pSurface->m_ConsoleCommandTextBox->Text().ToCString(); + const String kzCommand = pSurface->m_ConsoleCommandTextBox->Text(); + + if (String::IsNullOrEmpty(kzCommand)) + return; + bool bSuccess = false; for (const HWND hWindow : vecHandles) @@ -913,7 +957,7 @@ void CSurface::ForwardCommandToGame(Forms::Control* pSender) char szWindowName[256]; GetWindowTextA(hWindow, szWindowName, 256); - COPYDATASTRUCT cData = { 0, (DWORD)(std::min)(kzCommand.size(), (size_t)259) + 1, (void*)kzCommand.c_str() }; + COPYDATASTRUCT cData = { 0, (DWORD)(std::min)(kzCommand.Length(), (uint32_t)259) + 1, (void*)kzCommand.ToCString() }; bool bProcessingMessage = SendMessageA(hWindow, WM_COPYDATA, NULL, (LPARAM)&cData); // WM_COPYDATA will only return 0 or 1, that's why we use a boolean. if (bProcessingMessage && !bSuccess) { @@ -923,9 +967,7 @@ void CSurface::ForwardCommandToGame(Forms::Control* pSender) if (bSuccess) // At least one game instance received the command. { - pSurface->m_LogList.push_back(LogList_t((spdlog::level::level_enum)2, kzCommand)); - pSurface->m_ConsoleListView->SetVirtualListSize(static_cast(pSurface->m_LogList.size())); - pSurface->m_ConsoleListView->Refresh(); + pSurface->AddLog(LogType_t::LOG_INFO, Format("Sent command: %s\n", kzCommand.ToCString()).c_str()); pSurface->m_ConsoleCommandTextBox->SetText(""); } } diff --git a/r5dev/sdklauncher/basepanel.h b/r5dev/sdklauncher/basepanel.h index d1705e33..cc3036c6 100644 --- a/r5dev/sdklauncher/basepanel.h +++ b/r5dev/sdklauncher/basepanel.h @@ -2,13 +2,13 @@ struct LogList_t { - LogList_t(const spdlog::level::level_enum nLevel, const string& svText) + LogList_t(const LogType_t nLevel, const string& svText) { m_nLevel = nLevel; m_svText = svText; } - spdlog::level::level_enum m_nLevel; + LogType_t m_nLevel; string m_svText; }; @@ -23,6 +23,8 @@ public: std::vector m_LogList; void Init(); + void AddLog(const LogType_t type, const char* const pszText); + eLaunchMode BuildParameter(string& svParameter); private: diff --git a/r5dev/sdklauncher/sdklauncher.cpp b/r5dev/sdklauncher/sdklauncher.cpp index 23b09dc7..13b07962 100644 --- a/r5dev/sdklauncher/sdklauncher.cpp +++ b/r5dev/sdklauncher/sdklauncher.cpp @@ -3,16 +3,21 @@ // Purpose: SDK launcher implementation. // //=============================================================================// +#include "core/logger.h" +#include "core/logdef.h" +#include "tier0/cpu.h" #include "tier0/binstream.h" #include "tier1/fmtstr.h" #include "basepanel.h" #include "sdklauncher.h" +#include "windows/console.h" #include "vstdlib/keyvaluessystem.h" #include "filesystem/filesystem_std.h" static CKeyValuesSystem s_KeyValuesSystem; -static CFileSystem_Stdio g_FullFileSystem; +static CFileSystem_Stdio s_FullFileSystem; +static CLauncher s_Launcher; /////////////////////////////////////////////////////////////////////////////// // Purpose: keyvalues singleton accessor @@ -27,7 +32,28 @@ IKeyValuesSystem* KeyValuesSystem() /////////////////////////////////////////////////////////////////////////////// CFileSystem_Stdio* FileSystem() { - return &g_FullFileSystem; + return &s_FullFileSystem; +} + +/////////////////////////////////////////////////////////////////////////////// +// Purpose: launcher singleton accessor. +/////////////////////////////////////////////////////////////////////////////// +CLauncher* SDKLauncher() +{ + return &s_Launcher; +} + +/////////////////////////////////////////////////////////////////////////////// +// Purpose: launcher logger sink +/////////////////////////////////////////////////////////////////////////////// +void LauncherLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context, + const char* pszLogger, const char* pszFormat, va_list args, + const UINT exitCode /*= NO_ERROR*/, const char* pszUptimeOverride /*= nullptr*/) +{ + const string buffer = FormatV(pszFormat, args); + + SDKLauncher()->AddLog(logType, buffer.c_str()); + EngineLoggerSink(logType, logLevel, context, pszLogger, pszFormat, args, exitCode, pszUptimeOverride); } /////////////////////////////////////////////////////////////////////////////// @@ -38,30 +64,42 @@ void CLauncher::RunSurface() Forms::Application::EnableVisualStyles(); UIX::UIXTheme::InitializeRenderer(new Themes::KoreTheme()); - m_Surface.Init(); - Forms::Application::Run(&g_Launcher.m_Surface, false); + m_pSurface = new CSurface(); + m_pSurface->Init(); + + Forms::Application::Run(m_pSurface, true); UIX::UIXTheme::ShutdownRenderer(); } /////////////////////////////////////////////////////////////////////////////// -// Purpose: initializes the console (development only) +// Purpose: initializes the launcher /////////////////////////////////////////////////////////////////////////////// -void CLauncher::InitConsole() +void CLauncher::Init() { - AllocConsole(); - freopen("conin$", "r", stdin); - freopen("conout$", "w", stdout); - freopen("conout$", "w", stderr); + g_CoreMsgVCallback = &LauncherLoggerSink; // Setup logger callback sink. + + // Init time. + Plat_FloatTime(); + SpdLog_Init(true); } /////////////////////////////////////////////////////////////////////////////// -// Purpose: initializes the logger +// Purpose: de-initializes the launcher /////////////////////////////////////////////////////////////////////////////// -void CLauncher::InitLogger() +void CLauncher::Shutdown() { - m_pLogger->set_pattern("[%^%l%$] %v"); - m_pLogger->set_level(spdlog::level::trace); - spdlog::set_default_logger(m_pLogger); // Set as default. + SpdLog_Shutdown(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Purpose: adds a log to the surface console +/////////////////////////////////////////////////////////////////////////////// +void CLauncher::AddLog(const LogType_t level, const char* szText) +{ + if (m_pSurface) + { + m_pSurface->AddLog(level, szText); + } } /////////////////////////////////////////////////////////////////////////////// @@ -120,13 +158,13 @@ int CLauncher::HandleCommandLine(int argc, char* argv[]) /////////////////////////////////////////////////////////////////////////////// int CLauncher::HandleInput() { - std::cout << "----------------------------------------------------------------------------------------------------------------------" << std::endl; - AddLog(spdlog::level::level_enum::warn, "The '%s' options are for development purposes; use the '%s' options for default usage.\n", "DEV", "PROD"); - std::cout << "----------------------------------------------------------------------------------------------------------------------" << std::endl; - AddLog(spdlog::level::level_enum::info, "%-6s ('0' = %s | '1' = %s).\n", "GAME", "DEV", "PROD"); - AddLog(spdlog::level::level_enum::info, "%-6s ('2' = %s | '3' = %s).\n", "SERVER", "DEV", "PROD"); - AddLog(spdlog::level::level_enum::info, "%-6s ('4' = %s | '5' = %s).\n", "CLIENT", "DEV", "PROD"); - std::cout << "----------------------------------------------------------------------------------------------------------------------" << std::endl; + Msg(eDLL_T::NONE, "--------------------------------------------------------------------------------------------------------------\n"); + Warning(eDLL_T::COMMON, "The '%s' options are for development purposes; use the '%s' options for default usage.\n", "DEV", "PROD"); + Msg(eDLL_T::NONE, "--------------------------------------------------------------------------------------------------------------\n"); + Msg(eDLL_T::COMMON, "%-6s ('0' = %s | '1' = %s).\n", "GAME", "DEV", "PROD"); + Msg(eDLL_T::COMMON, "%-6s ('2' = %s | '3' = %s).\n", "SERVER", "DEV", "PROD"); + Msg(eDLL_T::COMMON, "%-6s ('4' = %s | '5' = %s).\n", "CLIENT", "DEV", "PROD"); + Msg(eDLL_T::NONE, "--------------------------------------------------------------------------------------------------------------\n"); std::cout << "User input: "; std::string input; @@ -142,17 +180,24 @@ int CLauncher::HandleInput() } else { - AddLog(spdlog::level::level_enum::err, "Invalid mode (range 0-5).\n"); + Error(eDLL_T::COMMON, 0, "Invalid mode (range 0-5).\n"); + Sleep(2500); + return EXIT_FAILURE; } } catch (const std::exception& e) { - AddLog(spdlog::level::level_enum::err, "SDK Launcher only takes numerical input (error = %s).\n", e.what()); + Error(eDLL_T::COMMON, 0, "SDK Launcher only takes numerical input (error = %s).\n", e.what()); + Sleep(2500); + return EXIT_FAILURE; } } - AddLog(spdlog::level::level_enum::err, "SDK Launcher requires numerical input.\n"); + + Error(eDLL_T::COMMON, 0, "SDK Launcher requires numerical input.\n"); + Sleep(2500); + return EXIT_FAILURE; } @@ -229,14 +274,13 @@ bool CLauncher::CreateLaunchContext(eLaunchMode lMode, uint64_t nProcessorAffini } default: { - AddLog(spdlog::level::level_enum::err, "No launch mode specified.\n"); + Error(eDLL_T::COMMON, 0, "No launch mode specified.\n"); return false; } } SetupLaunchContext(szConfig, szGameDLL, szCommandLine); - AddLog(spdlog::level::level_enum::info, "*** LAUNCHING %s [%s] ***\n", - szContext, szLevel); + Msg(eDLL_T::COMMON, "*** LAUNCHING %s [%s] ***\n", szContext, szLevel); return true; } @@ -251,20 +295,19 @@ bool CLauncher::CreateLaunchContext(eLaunchMode lMode, uint64_t nProcessorAffini void CLauncher::SetupLaunchContext(const char* szConfig, const char* szGameDll, const char* szCommandLine) { CIOStream cfgFile; + + CFmtStrN<1024> cfgFileName; CFmtStrMax commandLine; if (szConfig && szConfig[0]) { - commandLine.Format(GAME_CFG_PATH"%s", szConfig); + cfgFileName.Format(GAME_CFG_PATH"%s", szConfig); - if (cfgFile.Open(commandLine.String(), CIOStream::READ)) + if (cfgFile.Open(cfgFileName.String(), CIOStream::READ)) { - // Reuse the stack string for the actual command line buffer. - commandLine.Clear(); - if (!cfgFile.ReadString(commandLine.Access(), commandLine.GetMaxLength())) { - AddLog(spdlog::level::level_enum::err, "Failed to read file '%s'!\n", szConfig); + Error(eDLL_T::COMMON, 0, "Failed to read file '%s'!\n", szConfig); } else { @@ -273,7 +316,7 @@ void CLauncher::SetupLaunchContext(const char* szConfig, const char* szGameDll, } else // Failed to open config file. { - AddLog(spdlog::level::level_enum::err, "Failed to open file '%s'!\n", szConfig); + Error(eDLL_T::COMMON, 0, "Failed to open file '%s'!\n", szConfig); } } @@ -287,11 +330,11 @@ void CLauncher::SetupLaunchContext(const char* szConfig, const char* szGameDll, /////////////////////////////////////////////////////////////////////////// // Print the file paths and arguments. - std::cout << "----------------------------------------------------------------------------------------------------------------------" << std::endl; - AddLog(spdlog::level::level_enum::debug, "- CWD: %s\n", m_svCurrentDir.c_str()); - AddLog(spdlog::level::level_enum::debug, "- EXE: %s\n", m_svGameDll.c_str()); - AddLog(spdlog::level::level_enum::debug, "- CLI: %s\n", commandLine.String()); - std::cout << "----------------------------------------------------------------------------------------------------------------------" << std::endl; + Msg(eDLL_T::NONE, "--------------------------------------------------------------------------------------------------------------\n"); + Msg(eDLL_T::COMMON, "- CWD: %s\n", m_svCurrentDir.c_str()); + Msg(eDLL_T::COMMON, "- EXE: %s\n", m_svGameDll.c_str()); + Msg(eDLL_T::COMMON, "- CLI: %s\n", commandLine.String()); + Msg(eDLL_T::NONE, "--------------------------------------------------------------------------------------------------------------\n"); } /////////////////////////////////////////////////////////////////////////////// @@ -386,28 +429,39 @@ BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) /////////////////////////////////////////////////////////////////////////////// // EntryPoint. /////////////////////////////////////////////////////////////////////////////// -int main(int argc, char* argv[]/*, char* envp[]*/) +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) { - g_Launcher.InitLogger(); - if (argc < 2) + CheckSystemCPUForSSE2(); + if (__argc < 2) { -#ifdef NDEBUG - FreeConsole(); -#endif // NDEBUG - g_Launcher.RunSurface(); +#ifdef _DEBUG + Console_Init(true, true); +#endif // _DEBUG + SDKLauncher()->Init(); + SDKLauncher()->RunSurface(); + SDKLauncher()->Shutdown(); +#ifdef _DEBUG + Console_Shutdown(); +#endif // _DEBUG } else { - int results = g_Launcher.HandleCommandLine(argc, argv); - if (results != -1) - return results; + if (!Console_Init(true)) + return EXIT_FAILURE; - return g_Launcher.HandleInput(); + SDKLauncher()->Init(); + + int cmdRet = SDKLauncher()->HandleCommandLine(__argc, __argv); + + if (cmdRet == -1) + cmdRet = SDKLauncher()->HandleInput(); + + SDKLauncher()->Shutdown(); + + if (!Console_Shutdown()) + return EXIT_FAILURE; + + return cmdRet; } return EXIT_SUCCESS; } - -/////////////////////////////////////////////////////////////////////////////// -// Singleton Launcher. -/////////////////////////////////////////////////////////////////////////////// -CLauncher g_Launcher("win_console"); diff --git a/r5dev/sdklauncher/sdklauncher.h b/r5dev/sdklauncher/sdklauncher.h index b2533855..b27eb700 100644 --- a/r5dev/sdklauncher/sdklauncher.h +++ b/r5dev/sdklauncher/sdklauncher.h @@ -4,9 +4,9 @@ class CLauncher { public: - CLauncher(const char* pszLoggerName) + CLauncher() { - m_pLogger = spdlog::stdout_color_mt(pszLoggerName); + m_pSurface = nullptr; m_ProcessorAffinity = NULL; m_svCurrentDir = fs::current_path().u8string(); } @@ -14,25 +14,12 @@ public: { } - void AddLog(spdlog::level::level_enum nLevel, const char* szFormat, ...) - { - string svBuffer; - va_list args; - va_start(args, szFormat); - svBuffer = FormatV(szFormat, args); - va_end(args); - - m_pLogger->log(nLevel, svBuffer); - m_pLogger->flush(); - - m_Surface.m_LogList.push_back(LogList_t(nLevel, svBuffer)); - m_Surface.ConsoleListView()->SetVirtualListSize(static_cast(m_Surface.m_LogList.size())); - m_Surface.ConsoleListView()->Refresh(); - } - void RunSurface(); - void InitConsole(); - void InitLogger(); + + void Init(); + void Shutdown(); + + void AddLog(const LogType_t level, const char* szText); int HandleCommandLine(int argc, char* argv[]); int HandleInput(); @@ -41,11 +28,10 @@ public: void SetupLaunchContext(const char* szConfig, const char* szGameDll, const char* szCommandLine); bool LaunchProcess() const; - eLaunchMode BuildParameter(string& parameterList) { return m_Surface.BuildParameter(parameterList); } + eLaunchMode BuildParameter(string& parameterList) { return m_pSurface->BuildParameter(parameterList); } private: - CSurface m_Surface; - std::shared_ptr m_pLogger; + CSurface* m_pSurface; uint64_t m_ProcessorAffinity; @@ -56,4 +42,4 @@ private: BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam); -extern CLauncher g_Launcher; +extern CLauncher* SDKLauncher(); From 9a3ea6b53a0314cb93b1e90346ef69fdd44fa2e9 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:51:04 +0200 Subject: [PATCH 056/113] Resource: add missing command line parameter client configs Since the implementation of the loader system, client's need '-noserverdll' to work properly when launched from the SDK launcher. --- r5dev/resource/cfg/system/startup_client_dev.cfg | 1 + r5dev/resource/cfg/system/startup_client_retail.cfg | 1 + 2 files changed, 2 insertions(+) diff --git a/r5dev/resource/cfg/system/startup_client_dev.cfg b/r5dev/resource/cfg/system/startup_client_dev.cfg index 805a07b5..0c121a99 100644 --- a/r5dev/resource/cfg/system/startup_client_dev.cfg +++ b/r5dev/resource/cfg/system/startup_client_dev.cfg @@ -1,3 +1,4 @@ +-noserverdll -ansicolor -dev -devsdk diff --git a/r5dev/resource/cfg/system/startup_client_retail.cfg b/r5dev/resource/cfg/system/startup_client_retail.cfg index c72584ea..43871141 100644 --- a/r5dev/resource/cfg/system/startup_client_retail.cfg +++ b/r5dev/resource/cfg/system/startup_client_retail.cfg @@ -1,3 +1,4 @@ +-noserverdll -fnf -showdevmenu -playlistfile "playlists_r5_patch.txt" From e7d3e8d23d4a63d7c2e2e2fafbee25ebfc5a4d95 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:52:06 +0200 Subject: [PATCH 057/113] NetConsole: log header/version as soon as possible Logged right after console and terminal is initialized. --- r5dev/netconsole/netconsole.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/r5dev/netconsole/netconsole.cpp b/r5dev/netconsole/netconsole.cpp index 4503e22b..95d7a943 100644 --- a/r5dev/netconsole/netconsole.cpp +++ b/r5dev/netconsole/netconsole.cpp @@ -51,6 +51,8 @@ bool CNetCon::Init(const bool bAnsiColor, const char* pAdr, const char* pKey) g_CoreMsgVCallback = &EngineLoggerSink; TermSetup(bAnsiColor); + Msg(eDLL_T::NONE, "R5 TCP net console [Version %s]\n", NETCON_VERSION); + WSAData wsaData; const int nError = ::WSAStartup(MAKEWORD(2, 2), &wsaData); @@ -80,7 +82,6 @@ bool CNetCon::Init(const bool bAnsiColor, const char* pAdr, const char* pKey) } m_bInitialized = true; - Msg(eDLL_T::NONE, "R5 TCP net console [Version %s]\n", NETCON_VERSION); static std::thread frame([this]() { From afb53b899c9a3ce71f788a49584069657fb0dbdb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:53:50 +0200 Subject: [PATCH 058/113] ImGui: update default server browser width As of the recent layout changes, buttons and widgets looks the sharpest on this width; default to this width instead. --- r5dev/gameui/IBrowser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp index b68b43a3..7115f2d5 100644 --- a/r5dev/gameui/IBrowser.cpp +++ b/r5dev/gameui/IBrowser.cpp @@ -71,7 +71,7 @@ CBrowser::~CBrowser(void) //----------------------------------------------------------------------------- bool CBrowser::Init(void) { - SetStyleVar(928.f, 524.f, -500.f, 50.f); + SetStyleVar(927.f, 524.f, -500.f, 50.f); bool ret = LoadTextureBuffer(reinterpret_cast(m_lockedIconDataResource.m_pData), int(m_lockedIconDataResource.m_nSize), &m_lockedIconShaderResource, &m_lockedIconDataResource.m_nWidth, &m_lockedIconDataResource.m_nHeight); From 535d2cdfba72d82d1e5f81bc4014bc705652ef77 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:18:51 +0200 Subject: [PATCH 059/113] ImGui: fix server modal token input bug The string buffer was moved to the stack on a recent refactor, but the data must persist even outside the function scope. Moved back to class in form of a buffer. --- r5dev/gameui/IBrowser.cpp | 13 +++++++------ r5dev/gameui/IBrowser.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp index 7115f2d5..a5b3761c 100644 --- a/r5dev/gameui/IBrowser.cpp +++ b/r5dev/gameui/IBrowser.cpp @@ -52,6 +52,7 @@ CBrowser::CBrowser(void) { m_surfaceLabel = "Server Browser"; + memset(m_serverTokenTextBuf, '\0', sizeof(m_serverTokenTextBuf)); memset(m_serverAddressTextBuf, '\0', sizeof(m_serverAddressTextBuf)); memset(m_serverNetKeyTextBuf, '\0', sizeof(m_serverNetKeyTextBuf)); @@ -343,10 +344,10 @@ void CBrowser::DrawBrowserPanel(void) ImGui::PushItemWidth(itemWidth); { - ImGui::InputTextWithHint("##ServerBrowser_ServerCon", "Server address and port", m_serverAddressTextBuf, IM_ARRAYSIZE(m_serverAddressTextBuf)); + ImGui::InputTextWithHint("##ServerBrowser_ServerCon", "Server address and port", m_serverAddressTextBuf, sizeof(m_serverAddressTextBuf)); ImGui::SameLine(); - ImGui::InputTextWithHint("##ServerBrowser_ServerKey", "Encryption key", m_serverNetKeyTextBuf, IM_ARRAYSIZE(m_serverNetKeyTextBuf)); + ImGui::InputTextWithHint("##ServerBrowser_ServerKey", "Encryption key", m_serverNetKeyTextBuf, sizeof(m_serverNetKeyTextBuf)); ImGui::SameLine(); if (ImGui::Button("Connect", ImVec2(itemWidth, ImGui::GetFrameHeight()))) @@ -437,8 +438,8 @@ void CBrowser::HiddenServersModal(void) const ImVec2 contentRegionMax = ImGui::GetContentRegionAvail(); ImGui::PushItemWidth(contentRegionMax.x); // Override item width. - string hiddenServerToken; - ImGui::InputTextWithHint("##HiddenServersConnectModal_TokenInput", "Token (required)", &hiddenServerToken); + ImGui::InputTextWithHint("##HiddenServersConnectModal_TokenInput", "Token (required)", + m_serverTokenTextBuf, sizeof(m_serverTokenTextBuf)); ImGui::PopItemWidth(); @@ -458,10 +459,10 @@ void CBrowser::HiddenServersModal(void) m_hiddenServerRequestMessage.clear(); m_reclaimFocusOnTokenField = true; - if (!hiddenServerToken.empty()) + if (m_serverTokenTextBuf[0]) { NetGameServer_t server; - const bool result = g_MasterServer.GetServerByToken(server, m_hiddenServerRequestMessage, hiddenServerToken); // Send token connect request. + const bool result = g_MasterServer.GetServerByToken(server, m_hiddenServerRequestMessage, m_serverTokenTextBuf); // Send token connect request. if (result && !server.name.empty()) { diff --git a/r5dev/gameui/IBrowser.h b/r5dev/gameui/IBrowser.h index 9591892d..b758b3ca 100644 --- a/r5dev/gameui/IBrowser.h +++ b/r5dev/gameui/IBrowser.h @@ -47,6 +47,7 @@ private: bool m_reclaimFocusOnTokenField; bool m_queryNewListNonRecursive; // When set, refreshes the server list once the next frame. bool m_queryGlobalBanList; + char m_serverTokenTextBuf[128]; char m_serverAddressTextBuf[128]; char m_serverNetKeyTextBuf[30]; From 8ac582ee821aa102e349dfe0b38b8bf43d663428 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:19:53 +0200 Subject: [PATCH 060/113] ImGui: improve browser modal QOL Hitting enter will now also submit the request. --- r5dev/gameui/IBrowser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp index a5b3761c..41223dbc 100644 --- a/r5dev/gameui/IBrowser.cpp +++ b/r5dev/gameui/IBrowser.cpp @@ -438,8 +438,8 @@ void CBrowser::HiddenServersModal(void) const ImVec2 contentRegionMax = ImGui::GetContentRegionAvail(); ImGui::PushItemWidth(contentRegionMax.x); // Override item width. - ImGui::InputTextWithHint("##HiddenServersConnectModal_TokenInput", "Token (required)", - m_serverTokenTextBuf, sizeof(m_serverTokenTextBuf)); + const bool hitEnter = ImGui::InputTextWithHint("##HiddenServersConnectModal_TokenInput", "Token (required)", + m_serverTokenTextBuf, sizeof(m_serverTokenTextBuf), ImGuiInputTextFlags_EnterReturnsTrue); ImGui::PopItemWidth(); @@ -454,7 +454,7 @@ void CBrowser::HiddenServersModal(void) ImGui::TextColored(m_hiddenServerMessageColor, "%s", m_hiddenServerRequestMessage.c_str()); ImGui::Separator(); - if (ImGui::Button("Connect", ImVec2(contentRegionMax.x, 24))) + if (ImGui::Button("Connect", ImVec2(contentRegionMax.x, 24)) || hitEnter) { m_hiddenServerRequestMessage.clear(); m_reclaimFocusOnTokenField = true; From a54fec9e18c994085d534b4401d265bc560d5fcd Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:22:13 +0200 Subject: [PATCH 061/113] ImGui: increase base64 key buf size Make buffer size as large as that of the engine itself (used to represent the string in class CNetKey). --- r5dev/gameui/IBrowser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/gameui/IBrowser.h b/r5dev/gameui/IBrowser.h index b758b3ca..123ba6fe 100644 --- a/r5dev/gameui/IBrowser.h +++ b/r5dev/gameui/IBrowser.h @@ -49,7 +49,7 @@ private: bool m_queryGlobalBanList; char m_serverTokenTextBuf[128]; char m_serverAddressTextBuf[128]; - char m_serverNetKeyTextBuf[30]; + char m_serverNetKeyTextBuf[45]; ID3D11ShaderResourceView* m_lockedIconShaderResource; MODULERESOURCE m_lockedIconDataResource; From cfc2deada4c78c3f8b9429a9cad3f3f82c6545f4 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:45:25 +0200 Subject: [PATCH 062/113] Resource: add LiveAPI documentation --- r5dev/resource/docs/liveapi_readme.txt | 96 ++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 r5dev/resource/docs/liveapi_readme.txt diff --git a/r5dev/resource/docs/liveapi_readme.txt b/r5dev/resource/docs/liveapi_readme.txt new file mode 100644 index 00000000..db17343c --- /dev/null +++ b/r5dev/resource/docs/liveapi_readme.txt @@ -0,0 +1,96 @@ +# Quick Start + +This API is built on top of WebSockets and Google's Protocol Buffer (protobuf) technology. All gameplay events and +requests supported by the LiveAPI are documented in the `events.proto` protobuf file that lives in this directory. +If you're not familiar with protobuf, visit https://developers.google.com/protocol-buffers to learn more. + +Protobuf bindings can be easily generated for your language of choice after you obtain the Protobuf Compiler `protoc`. +For example, to generate bindings for Python, use: +`protoc.exe --proto_path= --python_out= events.proto` + +The bindings can then be included into your app code. In order to consume the events, your app will have to open a +WebSocket server that the running game server can connect and send events to. + +# Configuration + +The game server must also be running with additional configurations to activate the LiveAPI and connect to the app. +The configuration file is located in `platform/cfg/liveapi.cfg` (relative from the game executable `r5apex_ds.exe`). + +For example, if the app has a websocket server in port 7777 of the same machine the game server is running on, the +following settings can be applied in the aforementioned configuration file to connect the game server to the app: + +liveapi_enabled "1" +liveapi_websocket_enabled "1" +liveapi_servers "ws://127.0.0.1:7777" + +Upon launching with these parameters, the game server will connect to the WebSocket server at 127.0.0.1 in port 7777. +Gameplay events are sent to the WebSocket server app once the game server has started. + +The game can also be configured to write events to a local JSON file on the disk. The event logs will be located in +`platform/liveapi/logs//match_.json` (relative from the game executable `r5apex_ds.exe`). + +The following settings can be applied in the aforementioned configuration file to log events to a local JSON file: + +liveapi_enabled "1" +liveapi_print_enabled "1" +liveapi_print_pretty "1" + +- You can run the WebSocket and local JSON logging simultaneously. + +# Scripting + +The Squirrel scripting API of the LiveAPI is quite simple, there are 5 main functions: + +LiveAPI_IsValidToRun() +- Whether the LiveAPI system was initialized and is currently able to run, check on this before calling the functions + `LiveAPI_WriteLogUsingDefinedFields()` and `LiveAPI_WriteLogUsingCustomFields()`to save unnecessary load on the game + server. + +LiveAPI_StartLogging() +- This is used to start the logging of LiveAPI events to a local JSON file, if a log session is already active by the + time this function is called, the previous log session will be closed and a new one will be started. The new session + will be written to a new json file. +- Needs ConVar `liveapi_enabled` and `liveapi_print_enabled` set to 1, else this function will not do anything. + +LiveAPI_StopLogging() +- This is used to stop the logging of LiveAPI events to a local JSON file. Calling this will finish off the file and + stop the logging of new events. + +LiveAPI_WriteLogUsingDefinedFields() +- This function takes 3 parameters, an event type (must be one registered in the 'eLiveAPI_EventTypes' enum, see + the file `src/game/server/liveapi/liveapi.cpp` for available event types, or alternatively, see the events.proto + file, event names must start with a lower case !!!), an array of data, and an array of field indices. The order of + the 2 arrays are important, as the entries in the data array map directly to the data in the field indices array; if + event type is eLiveAPI_EventTypes.playerKilled, and if the first entry of the data array is "someString", and the + first entry in the field indices array is '3', then "someString" will be set to the third field index of the + PlayerKilled event message. Make sure to study the event messages, and their respective field numbers in the + `events.proto` file before assigning new events! + +NOTE: Since there was a high demand for custom events, we added an event named `CustomEvent` which can be used to send +game data in any structure from the game's scripting API. This is useful if you wish to log your own data from the +game (e.g. a custom gamemode that has something the current protocol doesn't support). The following function utilizes +this special event message: + +LiveAPI_WriteLogUsingCustomFields() +- This function takes 3 parameters, an event name (can be any string, the purpose of this is to identify your custom + event!), an array of data, and an array of field names. You can entirely define the structure of the data yourself; + if entry 6 in data array is "world!", and entry 6 in the field names array is "hello", then message variable "hello" + becomes "world!". The data array can take any of the following types: bool|int|float|string|vector|array|table. + NOTE: with tables, the key must be a string as this will be used to determine the custom field names, the values can + be any of the aforementioned types. +- Tables and arrays cannot be nested into them selfs as this would cause infinite recursion, and the maximum nesting + depth of a table or array is 64. + +For more technical information about the scripting API of the system, see the file +`platform/scripts/vscripts/_live_api.gnut` (relative from the game executable `r5apex_ds.exe`). + +# Technical Information + +By popular demand, we tried our best to keep the protocol and documentation the same as that of the retail version of +the game to maintain compatibility with existing apps. As of the release of this build, the file `events.proto` is +synced with the retail build `R5pc_r5-201_J29_CL6350311_EX6402312_6403685_2024_03_22`. + +# Contact & Feedback + +If you have a question, suggestion, or encountered an issue in the system, you can send me (Kawe Mazidjatari) an email +at `amos@r5reloaded.com`. From 33f926da74392df2f4898d73eee126e3e10e4fde Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 17 Apr 2024 22:07:00 +0200 Subject: [PATCH 063/113] Launcher: fix compiler error Prototype changed in commit c261db243e7de0a57445ed9bb036238a7171e572. --- r5dev/sdklauncher/sdklauncher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/sdklauncher/sdklauncher.cpp b/r5dev/sdklauncher/sdklauncher.cpp index 13b07962..3cb83551 100644 --- a/r5dev/sdklauncher/sdklauncher.cpp +++ b/r5dev/sdklauncher/sdklauncher.cpp @@ -435,7 +435,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) if (__argc < 2) { #ifdef _DEBUG - Console_Init(true, true); + Console_Init(true); #endif // _DEBUG SDKLauncher()->Init(); SDKLauncher()->RunSurface(); From 639f4741b19dc7909919155d11d2768041e90c2a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:18:09 +0200 Subject: [PATCH 064/113] VScript: add ScriptStatus_t enum Enum values are correct based on 'CSquirrelVM::ExecuteFunction()'. --- r5dev/public/vscript/ivscript.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/r5dev/public/vscript/ivscript.h b/r5dev/public/vscript/ivscript.h index 2d9960b8..4cf0ee93 100644 --- a/r5dev/public/vscript/ivscript.h +++ b/r5dev/public/vscript/ivscript.h @@ -17,6 +17,15 @@ typedef void* ScriptFunctionBindingStorageType_t; //--------------------------------------------------------- +enum ScriptStatus_t +{ + SCRIPT_ERROR = -1, + SCRIPT_DONE, + SCRIPT_RUNNING, +}; + +//--------------------------------------------------------- + enum ExtendedFieldType { FIELD_TYPEUNKNOWN = FIELD_TYPECOUNT, From fb9ba0e454e4177581e790d712414cc1994efd4c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:47:45 +0200 Subject: [PATCH 065/113] Squirrel: add multiple SQ API functions Added: - sq_getstackobj - sq_pop - sq_addref - sq_release - SQVM::Pop - RefTable::Get - RefTable::AddRef - RefTable::Release --- r5dev/vscript/CMakeLists.txt | 1 + .../languages/squirrel_re/include/sqstate.h | 4 +++ .../languages/squirrel_re/include/squirrel.h | 19 ++++++++++++ .../languages/squirrel_re/include/sqvm.h | 4 +++ .../languages/squirrel_re/squirrel/sqapi.cpp | 30 +++++++++++++++++++ .../squirrel_re/squirrel/sqstate.cpp | 22 ++++++++++++++ .../languages/squirrel_re/squirrel/sqvm.cpp | 10 +++++++ 7 files changed, 90 insertions(+) create mode 100644 r5dev/vscript/languages/squirrel_re/squirrel/sqstate.cpp diff --git a/r5dev/vscript/CMakeLists.txt b/r5dev/vscript/CMakeLists.txt index f7c28ec1..ff13f9a6 100644 --- a/r5dev/vscript/CMakeLists.txt +++ b/r5dev/vscript/CMakeLists.txt @@ -23,6 +23,7 @@ add_sources( SOURCE_GROUP "Squirrel_RE/squirrel" "languages/squirrel_re/squirrel/sqstring.cpp" "languages/squirrel_re/squirrel/sqtable.cpp" "languages/squirrel_re/squirrel/sqmem.cpp" + "languages/squirrel_re/squirrel/sqstate.cpp" "languages/squirrel_re/squirrel/sqvm.cpp" ) diff --git a/r5dev/vscript/languages/squirrel_re/include/sqstate.h b/r5dev/vscript/languages/squirrel_re/include/sqstate.h index 1adbf85a..01aefb85 100644 --- a/r5dev/vscript/languages/squirrel_re/include/sqstate.h +++ b/r5dev/vscript/languages/squirrel_re/include/sqstate.h @@ -13,6 +13,10 @@ struct RefTable { SQUnsignedInteger refs; struct RefNode* next; }; + void AddRef(SQObject& obj); + SQBool Release(SQObject& obj); + + RefTable::RefNode* Get(SQObject& obj, SQHash& mainpos, RefNode** prev, bool add); private: SQUnsignedInteger _numofslots; SQUnsignedInteger _slotused; diff --git a/r5dev/vscript/languages/squirrel_re/include/squirrel.h b/r5dev/vscript/languages/squirrel_re/include/squirrel.h index 6b5c5b64..1244ed98 100644 --- a/r5dev/vscript/languages/squirrel_re/include/squirrel.h +++ b/r5dev/vscript/languages/squirrel_re/include/squirrel.h @@ -47,6 +47,9 @@ to the following restrictions: #define _SC(a) a +#define SQTrue (1) +#define SQFalse (0) + typedef long SQInteger; typedef unsigned long SQUnsignedInteger; typedef short SQShort; @@ -64,6 +67,8 @@ typedef SQInteger SQRESULT; typedef int ScriptDataType_t; typedef struct SQVM* HSQUIRRELVM; +//typedef SQObject HSQOBJECT; + struct SQBufState; typedef char SQChar; @@ -170,6 +175,8 @@ SQRESULT sq_getthread(HSQUIRRELVM v, SQInteger idx, HSQUIRRELVM* thread); SQRESULT sq_getstring(HSQUIRRELVM v, SQInteger idx, const SQChar** c); SQRESULT sq_get(HSQUIRRELVM v, SQInteger idx); SQInteger sq_gettop(HSQUIRRELVM v); +SQRESULT sq_getstackobj(HSQUIRRELVM v, SQInteger idx, SQObject* po); +void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop); SQRESULT sq_pushroottable(HSQUIRRELVM v); void sq_pushbool(HSQUIRRELVM v, SQBool b); void sq_pushstring(HSQUIRRELVM v, const SQChar* string, SQInteger len); @@ -186,6 +193,9 @@ SQRESULT sq_call(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBool raiseerr SQRESULT sq_startconsttable(HSQUIRRELVM v); SQRESULT sq_endconsttable(HSQUIRRELVM v); +void sq_addref(HSQUIRRELVM v, SQObject* po); +SQBool sq_release(HSQUIRRELVM v, SQObject* po); + /*UTILITY MACRO*/ #define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC) #define sq_istable(o) ((o)._type==OT_TABLE) @@ -227,6 +237,9 @@ inline SQRESULT (*v_sq_endconsttable)(HSQUIRRELVM v); inline SQString* (*v_StringTable__Add)(void* a1, const SQChar* str, SQInteger len); +inline void* /*RefTable::RefNode*/ (*v_RefTable__Get)(void* /*RefTable*/ thisp, SQObject* obj, SQHash* mainpos, void*/*RefTable::RefNode**/ prev, bool add); +inline SQBool(*v_RefTable__Release)(void* /*RefTable*/ thisp, SQObject* obj); + /////////////////////////////////////////////////////////////////////////////// class VSquirrelAPI : public IDetour { @@ -250,6 +263,9 @@ class VSquirrelAPI : public IDetour LogFunAdr("sq_endconsttable", v_sq_endconsttable); LogFunAdr("StringTable::Add", v_StringTable__Add); + + LogFunAdr("RefTable::Get", v_RefTable__Get); + LogFunAdr("RefTable::Release", v_RefTable__Release); } virtual void GetFun(void) const { @@ -271,6 +287,9 @@ class VSquirrelAPI : public IDetour g_GameDll.FindPatternSIMD("8B 41 78 45 33 C0 FF C8 8B D0 89 41 78 48 C1 E2 04 48 03 91 ?? ?? ?? ?? 8B 02 48 C7 02 ?? ?? ?? ?? 25 ?? ?? ?? ?? 74 15").GetPtr(v_sq_endconsttable); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 41 8D 4D FF").FollowNearCallSelf().GetPtr(v_StringTable__Add); + + g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? FF 40 10 FF C6").FollowNearCallSelf().GetPtr(v_RefTable__Get); + g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 40 84 7D BC").FollowNearCallSelf().GetPtr(v_RefTable__Release); } virtual void GetVar(void) const { } virtual void GetCon(void) const { } diff --git a/r5dev/vscript/languages/squirrel_re/include/sqvm.h b/r5dev/vscript/languages/squirrel_re/include/sqvm.h index 7f82b708..0bcbd025 100644 --- a/r5dev/vscript/languages/squirrel_re/include/sqvm.h +++ b/r5dev/vscript/languages/squirrel_re/include/sqvm.h @@ -20,6 +20,9 @@ struct SQVM : public CHAINABLE_OBJ { void PrintObjVal(const SQObject* oin, SQObject* oout); + void Pop(); + void Pop(SQInteger n); + // push sqobjectptr on to the stack void Push(const SQObjectPtr& o); @@ -59,6 +62,7 @@ static_assert(offsetof(SQVM, _top) == 0x78); static_assert(offsetof(SQVM, _nnativecalls) == 0x130); inline SQObjectPtr& stack_get(HSQUIRRELVM v, SQInteger idx) { return ((idx >= 0) ? (v->_stackbase[idx-1]) : (v->GetUp(idx))); } +#define _ss(_vm_) (_vm_)->_sharedstate /* ==== SQUIRREL ======================================================================================================================================================== */ inline SQRESULT(*v_SQVM_PrintFunc)(HSQUIRRELVM v, SQChar* fmt, ...); diff --git a/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp b/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp index 707df29f..b5e213af 100644 --- a/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp +++ b/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp @@ -94,6 +94,20 @@ SQInteger sq_gettop(HSQUIRRELVM v) return (v->_top - v->_bottom); } +//--------------------------------------------------------------------------------- +SQRESULT sq_getstackobj(HSQUIRRELVM v, SQInteger idx, SQObject* po) +{ + *po = stack_get(v, idx); + return SQ_OK; +} + +//--------------------------------------------------------------------------------- +void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop) +{ + Assert(v->_top >= nelemstopop); + v->Pop(nelemstopop); +} + //--------------------------------------------------------------------------------- SQRESULT sq_pushroottable(HSQUIRRELVM v) { @@ -174,16 +188,32 @@ SQRESULT sq_call(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBool raiseerr return v_sq_call(v, params, retval, raiseerror); } +//--------------------------------------------------------------------------------- SQRESULT sq_startconsttable(HSQUIRRELVM v) { return v_sq_startconsttable(v); } +//--------------------------------------------------------------------------------- SQRESULT sq_endconsttable(HSQUIRRELVM v) { return v_sq_endconsttable(v); } +//--------------------------------------------------------------------------------- +void sq_addref(HSQUIRRELVM v, SQObject* po) +{ + if (!ISREFCOUNTED(sq_type(*po))) return; + _ss(v)->_refs_table.AddRef(*po); +} + +//--------------------------------------------------------------------------------- +SQBool sq_release(HSQUIRRELVM v, SQObject* po) +{ + if (!ISREFCOUNTED(sq_type(*po))) return SQTrue; + return _ss(v)->_refs_table.Release(*po); +} + void VSquirrelAPI::Detour(const bool bAttach) const { DetourSetup(&v_sq_pushroottable, &sq_pushroottable, bAttach); diff --git a/r5dev/vscript/languages/squirrel_re/squirrel/sqstate.cpp b/r5dev/vscript/languages/squirrel_re/squirrel/sqstate.cpp new file mode 100644 index 00000000..bd7d6077 --- /dev/null +++ b/r5dev/vscript/languages/squirrel_re/squirrel/sqstate.cpp @@ -0,0 +1,22 @@ +/* + see copyright notice in squirrel.h +*/ +#include "sqstate.h" + +void RefTable::AddRef(SQObject& obj) +{ + SQHash mainpos; + RefNode* prev; + RefNode* ref = Get(obj, mainpos, &prev, true); + ref->refs++; +} + +SQBool RefTable::Release(SQObject& obj) +{ + return v_RefTable__Release(this, &obj); +} + +RefTable::RefNode* RefTable::Get(SQObject& obj, SQHash& mainpos, RefNode** prev, bool add) +{ + return (RefTable::RefNode*)v_RefTable__Get(this, &obj, &mainpos, prev, add); +} diff --git a/r5dev/vscript/languages/squirrel_re/squirrel/sqvm.cpp b/r5dev/vscript/languages/squirrel_re/squirrel/sqvm.cpp index ae478ea1..c24d234b 100644 --- a/r5dev/vscript/languages/squirrel_re/squirrel/sqvm.cpp +++ b/r5dev/vscript/languages/squirrel_re/squirrel/sqvm.cpp @@ -174,6 +174,16 @@ void SQVM_LogicError(SQBool bPrompt) v_SQVM_LogicError(bPrompt); } +void SQVM::Pop() { + _stack[--_top] = _null_; +} + +void SQVM::Pop(SQInteger n) { + for (SQInteger i = 0; i < n; i++) { + _stack[--_top] = _null_; + } +} + void SQVM::Push(const SQObjectPtr& o) { _stack[_top++] = o; } SQObjectPtr& SQVM::Top() { return _stack[_top - 1]; } SQObjectPtr& SQVM::PopGet() { return _stack[--_top]; } From 72709eeb5ee8cd132334839a1c0eb8422bd23e3a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:44:43 +0200 Subject: [PATCH 066/113] VScript: add CSquirrelVM::ExecuteFunction() Executes script code by function handle. --- .../languages/squirrel_re/vsquirrel.cpp | 19 +++++++++++++++++-- .../vscript/languages/squirrel_re/vsquirrel.h | 8 +++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp index a7b6fb3d..90e4f23a 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp @@ -106,9 +106,24 @@ SQRESULT CSquirrelVM::RegisterConstant(const SQChar* name, SQInteger value) // Input : *name - // Output : true on success, false otherwise //--------------------------------------------------------------------------------- -bool CSquirrelVM::ExecuteCodeCallback(const SQChar* const callbackName) +bool CSquirrelVM::ExecuteCodeCallback(const SQChar* const name) { - return CSquirrelVM__ExecuteCodeCallback(this, callbackName); + return CSquirrelVM__ExecuteCodeCallback(this, name); +} + +//--------------------------------------------------------------------------------- +// Purpose: executes a function by handle +// Input : hFunction - +// *pArgs - +// nArgs - +// *pReturn - +// hScope - +// Output : SCRIPT_DONE on success, SCRIPT_ERROR otherwise +//--------------------------------------------------------------------------------- +ScriptStatus_t CSquirrelVM::ExecuteFunction(HSCRIPT hFunction, void** pArgs, unsigned int nArgs, void* pReturn, HSCRIPT hScope) +{ + // NOTE: pArgs and pReturn are most likely of type 'ScriptVariant_t', needs to be reversed. + return CSquirrelVM__ExecuteFunction(this, hFunction, pArgs, nArgs, pReturn, hScope); } //--------------------------------------------------------------------------------- diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.h b/r5dev/vscript/languages/squirrel_re/vsquirrel.h index 6928195a..b9c312a9 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.h +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.h @@ -25,12 +25,14 @@ public: SQRESULT RegisterFunction(const SQChar* scriptname, const SQChar* nativename, const SQChar* helpstring, const SQChar* returntype, const SQChar* parameters, void* functor); SQRESULT RegisterConstant(const SQChar* name, SQInteger value); - bool ExecuteCodeCallback(const SQChar* const callbackName); + bool ExecuteCodeCallback(const SQChar* const name); FORCEINLINE HSQUIRRELVM GetVM() const { return m_hVM; } FORCEINLINE SQCONTEXT GetContext() const { return m_iContext; } FORCEINLINE eDLL_T GetNativeContext() const { return (eDLL_T)GetContext(); } + ScriptStatus_t ExecuteFunction(HSCRIPT hFunction, void** pArgs, unsigned int nArgs, void* pReturn, HSCRIPT hScope); + private: bool unk_00; SQChar pad0[7]; @@ -78,7 +80,9 @@ inline bool(*CSquirrelVM__PrecompileClientScripts)(CSquirrelVM* vm, SQCONTEXT co #ifndef CLIENT_DLL inline bool(*CSquirrelVM__PrecompileServerScripts)(CSquirrelVM* vm, SQCONTEXT context, char** scriptArray, int scriptCount); #endif +inline ScriptStatus_t(*CSquirrelVM__ExecuteFunction)(CSquirrelVM* s, HSCRIPT hFunction, void** pArgs, unsigned int nArgs, void* pReturn, HSCRIPT hScope); inline bool(*CSquirrelVM__ExecuteCodeCallback)(CSquirrelVM* s, const SQChar* callbackName); + inline bool(*CSquirrelVM__ThrowError)(CSquirrelVM* vm, HSQUIRRELVM v); #ifndef CLIENT_DLL @@ -136,6 +140,7 @@ class VSquirrel : public IDetour #ifndef DEDICATED LogFunAdr("CSquirrelVM::PrecompileClientScripts", CSquirrelVM__PrecompileClientScripts); #endif // !DEDICATED + LogFunAdr("CSquirrelVM::ExecuteFunction", CSquirrelVM__ExecuteFunction); LogFunAdr("CSquirrelVM::ExecuteCodeCallback", CSquirrelVM__ExecuteCodeCallback); LogFunAdr("CSquirrelVM::ThrowError", CSquirrelVM__ThrowError); } @@ -155,6 +160,7 @@ class VSquirrel : public IDetour // cl/ui scripts.rson compiling g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 44 0F B6 F0 48 85 DB").FollowNearCallSelf().GetPtr(CSquirrelVM__PrecompileClientScripts); #endif + g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 83 FB 5C").FollowNearCallSelf().GetPtr(CSquirrelVM__ExecuteFunction); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? C6 47 1C 01").FollowNearCallSelf().GetPtr(CSquirrelVM__ExecuteCodeCallback); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? BB ?? ?? ?? ?? 8B C3").FollowNearCallSelf().GetPtr(CSquirrelVM__ThrowError); } From 0cea07ab8f852cc20cf45fd34f229acd6387ee36 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:55:31 +0200 Subject: [PATCH 067/113] VScript: properly implement script command callback Previously we did sq_pushroottable() and a subsequent sq_call() after compiling the text buffer, but this didn't work for code that was threaded, or using Get/SetNetVar* functions. The second issue was that the callback for the "script" command was ran in the main thread. Server script should always run in the server frame thread, the Set/GetNetVar* functions check thread id to retrieve the correct VM context, so running server script from the main thread ended up with Set/GetNetVar* functions retrieving the client VM context rather than server's, causing undefined behavior. Script commands are now queued to the server frame thread, ultimately fixing this bug. Also fixed a small bug with function 'sq_compilebuffer()'; it takes an extra argument but this wasn't taken into account in the SDK. --- r5dev/engine/server/server.cpp | 15 ++++++++++++ r5dev/engine/server/server.h | 4 ++++ r5dev/engine/sys_dll.cpp | 6 ++++- r5dev/game/server/vscript_server.cpp | 12 ++++++++++ r5dev/public/tier0/frametask.h | 4 ++-- .../languages/squirrel_re/include/squirrel.h | 4 ++-- .../languages/squirrel_re/squirrel/sqapi.cpp | 4 ++-- r5dev/vscript/vscript.cpp | 23 +++++++++++++------ 8 files changed, 58 insertions(+), 14 deletions(-) diff --git a/r5dev/engine/server/server.cpp b/r5dev/engine/server/server.cpp index 2645da8d..d241972c 100644 --- a/r5dev/engine/server/server.cpp +++ b/r5dev/engine/server/server.cpp @@ -10,6 +10,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "core/stdafx.h" #include "common/protocol.h" +#include "tier0/frametask.h" #include "tier1/cvar.h" #include "tier1/strtools.h" #include "engine/server/sv_main.h" @@ -217,6 +218,17 @@ void CServer::BroadcastMessage(CNetMessage* const msg, const bool onlyActive, co //--------------------------------------------------------------------------------- void CServer::FrameJob(double flFrameTime, bool bRunOverlays, bool bUpdateFrame) { + for (IFrameTask* const& task : g_ServerTaskQueueList) + { + task->RunFrame(); + } + + g_ServerTaskQueueList.erase(std::remove_if(g_ServerTaskQueueList.begin(), + g_ServerTaskQueueList.end(), [](const IFrameTask* task) + { + return task->IsFinished(); + }), g_ServerTaskQueueList.end()); + CServer__FrameJob(flFrameTime, bRunOverlays, bUpdateFrame); LiveAPISystem()->RunFrame(); } @@ -242,3 +254,6 @@ void VServer::Detour(const bool bAttach) const /////////////////////////////////////////////////////////////////////////////// CServer* g_pServer = nullptr; CClientExtended CServer::sm_ClientsExtended[MAX_PLAYERS]; + +std::list g_ServerTaskQueueList; +CFrameTask g_ServerTaskQueue; diff --git a/r5dev/engine/server/server.h b/r5dev/engine/server/server.h index 3f976c6d..c549f8f7 100644 --- a/r5dev/engine/server/server.h +++ b/r5dev/engine/server/server.h @@ -1,4 +1,5 @@ #pragma once +#include "tier0/frametask.h" #include "tier1/NetAdr.h" #include "networksystem/pylon.h" #include "engine/client/client.h" @@ -111,6 +112,9 @@ static_assert(sizeof(CServer) == 0x25264C0); extern CServer* g_pServer; +extern std::list g_ServerTaskQueueList; +extern CFrameTask g_ServerTaskQueue; + extern ConVar sv_showconnecting; extern ConVar sv_pylonVisibility; diff --git a/r5dev/engine/sys_dll.cpp b/r5dev/engine/sys_dll.cpp index 5a3d21a2..5dc20100 100644 --- a/r5dev/engine/sys_dll.cpp +++ b/r5dev/engine/sys_dll.cpp @@ -20,6 +20,7 @@ #include "engine/host_cmd.h" #include "engine/enginetrace.h" #ifndef CLIENT_DLL +#include "engine/server/server.h" #include "engine/server/sv_main.h" #include "server/vengineserver_impl.h" #include "game/server/gameinterface.h" @@ -116,8 +117,11 @@ bool CModAppSystemGroup::StaticCreate(CModAppSystemGroup* pModAppSystemGroup) } g_TaskQueueList.push_back(&g_TaskQueue); - g_bAppSystemInit = true; +#ifndef CLIENT_DLL + g_ServerTaskQueueList.push_back(&g_ServerTaskQueue); +#endif // !CLIENT_DLL + g_bAppSystemInit = true; return CModAppSystemGroup__Create(pModAppSystemGroup); } diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 0ca711d9..8e6cdb63 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -31,6 +31,18 @@ static void SQVM_ServerScript_f(const CCommand& args) { if (args.ArgC() >= 2) { + const char* code = args.ArgS(); + + if (!ThreadInServerFrameThread()) + { + const string scode(code); + g_ServerTaskQueue.Dispatch([scode]() + { + Script_Execute(scode.c_str(), SQCONTEXT::SERVER); + }, 0); + return; // Only run in server frame thread. + } + Script_Execute(args.ArgS(), SQCONTEXT::SERVER); } } diff --git a/r5dev/public/tier0/frametask.h b/r5dev/public/tier0/frametask.h index 01e7c2f9..9c4601a4 100644 --- a/r5dev/public/tier0/frametask.h +++ b/r5dev/public/tier0/frametask.h @@ -4,8 +4,8 @@ #include "public/iframetask.h" //=============================================================================// -// This class is set up to run before each frame (main thread). -// Committed tasks are scheduled to execute after 'i' frames. +// This class is set up to run before each frame, committed tasks are scheduled +// to execute after 'i' frames. // ---------------------------------------------------------------------------- // A use case for scheduling tasks in the main thread would be (for example) // performing a web request in a separate thread, and apply the results (such as diff --git a/r5dev/vscript/languages/squirrel_re/include/squirrel.h b/r5dev/vscript/languages/squirrel_re/include/squirrel.h index 1244ed98..5eee0377 100644 --- a/r5dev/vscript/languages/squirrel_re/include/squirrel.h +++ b/r5dev/vscript/languages/squirrel_re/include/squirrel.h @@ -187,7 +187,7 @@ void sq_newtable(HSQUIRRELVM v); SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx); SQRESULT sq_arrayappend(HSQUIRRELVM v, SQInteger idx); SQRESULT sq_pushstructure(HSQUIRRELVM v, const SQChar* name, const SQChar* member, const SQChar* codeclass1, const SQChar* codeclass2); -SQRESULT sq_compilebuffer(HSQUIRRELVM v, SQBufState* bufferState, const SQChar* buffer, SQInteger context); +SQRESULT sq_compilebuffer(HSQUIRRELVM v, SQBufState* bufferState, const SQChar* buffer, SQInteger context, SQBool raiseerror); SQRESULT sq_call(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBool raiseerror); SQRESULT sq_startconsttable(HSQUIRRELVM v); @@ -228,7 +228,7 @@ inline void(*v_sq_newtable)(HSQUIRRELVM v); inline SQRESULT(*v_sq_newslot)(HSQUIRRELVM v, SQInteger idx); inline SQRESULT(*v_sq_arrayappend)(HSQUIRRELVM v, SQInteger idx); inline SQRESULT(*v_sq_pushstructure)(HSQUIRRELVM v, const SQChar* name, const SQChar* member, const SQChar* codeclass1, const SQChar* codeclass2); -inline SQRESULT(*v_sq_compilebuffer)(HSQUIRRELVM v, SQBufState* bufferstate, const SQChar* buffer, SQInteger level); +inline SQRESULT(*v_sq_compilebuffer)(HSQUIRRELVM v, SQBufState* bufferstate, const SQChar* buffer, SQInteger level, SQBool raiseerror); inline SQRESULT(*v_sq_call)(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBool raiseerror); inline SQRESULT(*v_sq_get)(HSQUIRRELVM v, SQInteger idx); diff --git a/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp b/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp index b5e213af..b0ce42a1 100644 --- a/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp +++ b/r5dev/vscript/languages/squirrel_re/squirrel/sqapi.cpp @@ -177,9 +177,9 @@ SQRESULT sq_pushstructure(HSQUIRRELVM v, const SQChar* name, const SQChar* membe } //--------------------------------------------------------------------------------- -SQRESULT sq_compilebuffer(HSQUIRRELVM v, SQBufState* bufferState, const SQChar* buffer, SQInteger level) +SQRESULT sq_compilebuffer(HSQUIRRELVM v, SQBufState* bufferState, const SQChar* buffer, SQInteger level, SQBool raiseerror) { - return v_sq_compilebuffer(v, bufferState, buffer, level); + return v_sq_compilebuffer(v, bufferState, buffer, level, raiseerror); } //--------------------------------------------------------------------------------- diff --git a/r5dev/vscript/vscript.cpp b/r5dev/vscript/vscript.cpp index 8fcec3b4..11c7fced 100644 --- a/r5dev/vscript/vscript.cpp +++ b/r5dev/vscript/vscript.cpp @@ -133,7 +133,11 @@ SQBool Script_PrecompileClientScripts(CSquirrelVM* vm) void Script_Execute(const SQChar* code, const SQCONTEXT context) { Assert(context != SQCONTEXT::NONE); - Assert(ThreadInMainOrServerFrameThread()); + + if (context == SQCONTEXT::CLIENT || context == SQCONTEXT::UI) + Assert(ThreadInMainThread()); + else if (context == SQCONTEXT::SERVER) + Assert(ThreadInServerFrameThread()); CSquirrelVM* s = Script_GetScriptHandle(context); const char* const contextName = s_scriptContextNames[(int)context]; @@ -145,24 +149,29 @@ void Script_Execute(const SQChar* code, const SQCONTEXT context) } HSQUIRRELVM v = s->GetVM(); + if (!v) { Error(eDLL_T::ENGINE, NO_ERROR, "Attempted to run %s script while VM isn't initialized\n", contextName); return; } - SQBufState bufState = SQBufState(code); - SQRESULT compileResult = sq_compilebuffer(v, &bufState, "console", -1); + SQBufState bufState(code); - if (SQ_SUCCEEDED(compileResult)) + if (SQ_SUCCEEDED(sq_compilebuffer(v, &bufState, "unnamed", -1, SQTrue))) { - sq_pushroottable(v); - SQRESULT callResult = sq_call(v, 1, false, false); + SQObject hScript; + sq_getstackobj(v, -1, &hScript); - if (!SQ_SUCCEEDED(callResult)) + sq_addref(v, &hScript); + sq_pop(v, 1); + + if (s->ExecuteFunction((HSCRIPT)&hScript, NULL, 0, NULL, NULL) == SCRIPT_ERROR) { Error(eDLL_T::ENGINE, NO_ERROR, "Failed to execute %s script \"%s\"\n", contextName, code); } + + sq_release(v, &hScript); } } From d4f9ac279cfff44d653299a4e397a6054c1bf0bf Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:12:35 +0200 Subject: [PATCH 068/113] VScript: move script run code to dedicated method --- .../languages/squirrel_re/vsquirrel.cpp | 29 +++++++++++++++++++ .../vscript/languages/squirrel_re/vsquirrel.h | 1 + r5dev/vscript/vscript.cpp | 18 ++---------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp index 90e4f23a..6c3f729c 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp @@ -101,6 +101,35 @@ SQRESULT CSquirrelVM::RegisterConstant(const SQChar* name, SQInteger value) return CSquirrelVM__RegisterConstant(this, name, value); } +//--------------------------------------------------------------------------------- +// Purpose: runs text as script on the VM +// Input : *script - +// Output : true on success, false otherwise +//--------------------------------------------------------------------------------- +bool CSquirrelVM::Run(const SQChar* const script) +{ + Assert(m_hVM); + + bool success = false; + SQBufState bufState(script); + + if (SQ_SUCCEEDED(sq_compilebuffer(m_hVM, &bufState, "unnamed", -1, SQTrue))) + { + SQObject hScript; + sq_getstackobj(m_hVM, -1, &hScript); + + sq_addref(m_hVM, &hScript); + sq_pop(m_hVM, 1); + + if (ExecuteFunction((HSCRIPT)&hScript, NULL, 0, NULL, NULL) == SCRIPT_DONE) + success = true; + + sq_release(m_hVM, &hScript); + } + + return success; +} + //--------------------------------------------------------------------------------- // Purpose: executes a code callback // Input : *name - diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.h b/r5dev/vscript/languages/squirrel_re/vsquirrel.h index b9c312a9..d70c0828 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.h +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.h @@ -31,6 +31,7 @@ public: FORCEINLINE SQCONTEXT GetContext() const { return m_iContext; } FORCEINLINE eDLL_T GetNativeContext() const { return (eDLL_T)GetContext(); } + bool Run(const SQChar* const script); ScriptStatus_t ExecuteFunction(HSCRIPT hFunction, void** pArgs, unsigned int nArgs, void* pReturn, HSCRIPT hScope); private: diff --git a/r5dev/vscript/vscript.cpp b/r5dev/vscript/vscript.cpp index 11c7fced..41064fc3 100644 --- a/r5dev/vscript/vscript.cpp +++ b/r5dev/vscript/vscript.cpp @@ -156,22 +156,10 @@ void Script_Execute(const SQChar* code, const SQCONTEXT context) return; } - SQBufState bufState(code); - - if (SQ_SUCCEEDED(sq_compilebuffer(v, &bufState, "unnamed", -1, SQTrue))) + if (!s->Run(code)) { - SQObject hScript; - sq_getstackobj(v, -1, &hScript); - - sq_addref(v, &hScript); - sq_pop(v, 1); - - if (s->ExecuteFunction((HSCRIPT)&hScript, NULL, 0, NULL, NULL) == SCRIPT_ERROR) - { - Error(eDLL_T::ENGINE, NO_ERROR, "Failed to execute %s script \"%s\"\n", contextName, code); - } - - sq_release(v, &hScript); + Error(eDLL_T::ENGINE, NO_ERROR, "Failed to run %s script \"%s\"\n", contextName, code); + return; } } From b622854d85852987f3f59baaa969de3c38fb0191 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:13:17 +0200 Subject: [PATCH 069/113] Squirrel: fix struct name bufCopy is actually bufPos as this indicated the current pos in the text buffer as it gets parsed out. --- r5dev/vscript/languages/squirrel_re/include/sqstate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/r5dev/vscript/languages/squirrel_re/include/sqstate.h b/r5dev/vscript/languages/squirrel_re/include/sqstate.h index 01aefb85..1d6c600f 100644 --- a/r5dev/vscript/languages/squirrel_re/include/sqstate.h +++ b/r5dev/vscript/languages/squirrel_re/include/sqstate.h @@ -75,13 +75,13 @@ struct SQBufState { const SQChar* buf; const SQChar* bufTail; - const SQChar* bufCopy; + const SQChar* bufPos; SQBufState(const SQChar* code) { buf = code; bufTail = code + strlen(code); - bufCopy = code; + bufPos = code; } }; #endif // SQSTATE_H \ No newline at end of file From 6b7e0d574d355cbd9b51f5af28b26da58fe15fba Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:14:35 +0200 Subject: [PATCH 070/113] VScript: fix method order More logical order of newly added methods. --- .../languages/squirrel_re/vsquirrel.cpp | 20 +++++++++---------- .../vscript/languages/squirrel_re/vsquirrel.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp index 6c3f729c..89452193 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp @@ -130,16 +130,6 @@ bool CSquirrelVM::Run(const SQChar* const script) return success; } -//--------------------------------------------------------------------------------- -// Purpose: executes a code callback -// Input : *name - -// Output : true on success, false otherwise -//--------------------------------------------------------------------------------- -bool CSquirrelVM::ExecuteCodeCallback(const SQChar* const name) -{ - return CSquirrelVM__ExecuteCodeCallback(this, name); -} - //--------------------------------------------------------------------------------- // Purpose: executes a function by handle // Input : hFunction - @@ -155,6 +145,16 @@ ScriptStatus_t CSquirrelVM::ExecuteFunction(HSCRIPT hFunction, void** pArgs, uns return CSquirrelVM__ExecuteFunction(this, hFunction, pArgs, nArgs, pReturn, hScope); } +//--------------------------------------------------------------------------------- +// Purpose: executes a code callback +// Input : *name - +// Output : true on success, false otherwise +//--------------------------------------------------------------------------------- +bool CSquirrelVM::ExecuteCodeCallback(const SQChar* const name) +{ + return CSquirrelVM__ExecuteCodeCallback(this, name); +} + //--------------------------------------------------------------------------------- // Purpose: registers a code function // Input : *s - diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.h b/r5dev/vscript/languages/squirrel_re/vsquirrel.h index d70c0828..212d075b 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.h +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.h @@ -25,14 +25,14 @@ public: SQRESULT RegisterFunction(const SQChar* scriptname, const SQChar* nativename, const SQChar* helpstring, const SQChar* returntype, const SQChar* parameters, void* functor); SQRESULT RegisterConstant(const SQChar* name, SQInteger value); - bool ExecuteCodeCallback(const SQChar* const name); - FORCEINLINE HSQUIRRELVM GetVM() const { return m_hVM; } FORCEINLINE SQCONTEXT GetContext() const { return m_iContext; } FORCEINLINE eDLL_T GetNativeContext() const { return (eDLL_T)GetContext(); } bool Run(const SQChar* const script); + ScriptStatus_t ExecuteFunction(HSCRIPT hFunction, void** pArgs, unsigned int nArgs, void* pReturn, HSCRIPT hScope); + bool ExecuteCodeCallback(const SQChar* const name); private: bool unk_00; From 3883597cb2a67ec96b9c040e10d468ee28750fd4 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 19 Apr 2024 17:06:11 +0200 Subject: [PATCH 071/113] RTech: fix bitwise order in define Put in parentheses. --- r5dev/public/rtech/ipakfile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/public/rtech/ipakfile.h b/r5dev/public/rtech/ipakfile.h index 7c29e02e..70a3d564 100644 --- a/r5dev/public/rtech/ipakfile.h +++ b/r5dev/public/rtech/ipakfile.h @@ -17,7 +17,7 @@ // pak header flags #define PAK_HEADER_FLAGS_HAS_MODULE (1<<0) -#define PAK_HEADER_FLAGS_HAS_MODULE_EXTENDED PAK_HEADER_FLAGS_HAS_MODULE | (1<<1) +#define PAK_HEADER_FLAGS_HAS_MODULE_EXTENDED (PAK_HEADER_FLAGS_HAS_MODULE | (1<<1)) #define PAK_HEADER_FLAGS_COMPRESSED (1<<8) From 9db094b98da4170f2d7a073af6f417d772e2e39e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 00:59:39 +0200 Subject: [PATCH 072/113] Engine: add command line statics for dedicated server and light cleanup CGameServer::SpawnServer() pointer to engine/server/server.h, and renamed it to CServer::SpawnServer(). --- r5dev/engine/server/server.h | 3 +++ r5dev/engine/server/sv_main.h | 50 ++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/r5dev/engine/server/server.h b/r5dev/engine/server/server.h index c549f8f7..e0ba76f4 100644 --- a/r5dev/engine/server/server.h +++ b/r5dev/engine/server/server.h @@ -129,6 +129,7 @@ inline void(*CServer__RunFrame)(CServer* pServer); inline CClient*(*CServer__ConnectClient)(CServer* pServer, user_creds_s* pCreds); inline void*(*CServer__RejectConnection)(CServer* pServer, int iSocket, netadr_t* pNetAdr, const char* szMessage); inline void (*CServer__BroadcastMessage)(CServer* pServer, CNetMessage* const msg, const bool onlyActive, const bool reliable); +inline bool(*CServer__SpawnServer)(CServer* pServer, const char* pszMapName, const char* pszMapGroupName); /////////////////////////////////////////////////////////////////////////////// class VServer : public IDetour @@ -141,6 +142,7 @@ class VServer : public IDetour LogFunAdr("CServer::ConnectClient", CServer__ConnectClient); LogFunAdr("CServer::RejectConnection", CServer__RejectConnection); LogFunAdr("CServer::BroadcastMessage", CServer__BroadcastMessage); + LogFunAdr("CServer::SpawnServer", CServer__SpawnServer); LogVarAdr("g_Server", g_pServer); #endif // !CLIENT_DLL } @@ -153,6 +155,7 @@ class VServer : public IDetour g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 88 05 ?? ?? ?? ??").FollowNearCallSelf().GetPtr(CServer__RunFrame); g_GameDll.FindPatternSIMD("4C 89 4C 24 ?? 53 55 56 57 48 81 EC ?? ?? ?? ?? 49 8B D9").GetPtr(CServer__RejectConnection); g_GameDll.FindPatternSIMD("4C 8B DC 45 88 43 18 56").GetPtr(CServer__BroadcastMessage); + g_GameDll.FindPatternSIMD("48 8B C4 53 55 56 57 41 54 41 55 41 57").GetPtr(CServer__SpawnServer); #endif // !CLIENT_DLL } virtual void GetVar(void) const diff --git a/r5dev/engine/server/sv_main.h b/r5dev/engine/server/sv_main.h index 1c2e75d2..b283c850 100644 --- a/r5dev/engine/server/sv_main.h +++ b/r5dev/engine/server/sv_main.h @@ -8,7 +8,6 @@ class CClient; class CClient; /* ==== SV_MAIN ======================================================================================================================================================= */ -inline bool(*CGameServer__SpawnServer)(void* thisptr, const char* pszMapName, const char* pszMapGroupName); inline void(*v_SV_InitGameDLL)(void); inline void(*v_SV_ShutdownGameDLL)(void); inline bool(*v_SV_ActivateServer)(void); @@ -17,12 +16,50 @@ inline void(*v_SV_BroadcastVoiceData)(CClient* cl, int nBytes, char* data); inline bool* s_bIsDedicated = nullptr; +inline bool* s_bPartyDediOnly = nullptr; +inline bool* s_bTrainingDedi = nullptr; +inline bool* s_bStagingDedi = nullptr; +inline bool* s_bFiringRangeDedi = nullptr; + // Returns true if this is a dedicated server. inline bool IsDedicated() { return *s_bIsDedicated; } +// If this is true, a maximum of 2 teams will be enforced. No voice data will +// be processed or broad casted to clients. +// This is set with command line option '-partyDediOnly'. +inline bool IsPartyDedi() +{ + return *s_bPartyDediOnly; +} + +// If this is true, no playlist matching checks will be performed. No voice +// data will be processed or broad casted to clients. +// This is set with command line option '-trainingDedi'. +inline bool IsTrainingDedi() +{ + return *s_bTrainingDedi; +} + +// If this is true, no playlist matching checks will be performed. +// This is set with command line option '-stagingDedi'. +inline bool IsStagingDedi() +{ + return *s_bStagingDedi; +} + +// If this is true, no playlist matching checks will be performed. +// The system expects a 'max_team_size' key in the playlists file +// that will be used to enforce the max team size, which defaults +// to '3' if key is absent. +// This is set with command line option '-firingRangeDedi'. +inline bool IsFiringRangeDedi() +{ + return *s_bFiringRangeDedi; +} + /////////////////////////////////////////////////////////////////////////////// void SV_InitGameDLL(); @@ -38,17 +75,16 @@ class HSV_Main : public IDetour { virtual void GetAdr(void) const { - LogFunAdr("CGameServer::SpawnServer", CGameServer__SpawnServer); LogFunAdr("SV_InitGameDLL", v_SV_InitGameDLL); LogFunAdr("SV_ShutdownGameDLL", v_SV_ShutdownGameDLL); LogFunAdr("SV_ActivateServer", v_SV_ActivateServer); LogFunAdr("SV_CreateBaseline", v_SV_CreateBaseline); LogFunAdr("SV_BroadcastVoiceData", v_SV_BroadcastVoiceData); + LogVarAdr("s_bIsDedicated", s_bIsDedicated); } virtual void GetFun(void) const { - g_GameDll.FindPatternSIMD("48 8B C4 53 55 56 57 41 54 41 55 41 57").GetPtr(CGameServer__SpawnServer); g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ??").GetPtr(v_SV_InitGameDLL); g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48").GetPtr(v_SV_ShutdownGameDLL); g_GameDll.FindPatternSIMD("48 8B C4 56 48 81 EC ?? ?? ?? ?? 48 89 ?? ?? 48 8D").GetPtr(v_SV_ActivateServer); @@ -59,6 +95,14 @@ class HSV_Main : public IDetour { s_bIsDedicated = g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 48 89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? 53 57 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9 48 8D BC 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 89 7C 24 ?? 48 8D 54 24 ?? 33 FF") .FindPatternSelf("40 38 3D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + + CMemory baseAdr = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 83 3D ?? ?? ?? ?? ?? 75 2A").OffsetSelf(0x100); + + // Grab the 4 globals in a row (FindPatternSelf moves the base address to found address). + baseAdr.FindPatternSelf("0F 95 05").ResolveRelativeAddress(3, 7).GetPtr(s_bPartyDediOnly); + baseAdr.FindPatternSelf("0F 95 05").ResolveRelativeAddress(3, 7).GetPtr(s_bTrainingDedi); + baseAdr.FindPatternSelf("0F 95 05").ResolveRelativeAddress(3, 7).GetPtr(s_bStagingDedi); + baseAdr.FindPatternSelf("0F 95 05").ResolveRelativeAddress(3, 7).GetPtr(s_bFiringRangeDedi); } virtual void GetCon(void) const { } /////////////////////////////////////////////////////////////////////////////// From 1b6d37725bfe403f07c67426c1f651d50752db06 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 01:00:49 +0200 Subject: [PATCH 073/113] Engine: don't broadcast voice data on training dedi Training dedi doesn't support broadcasting voice data, return out. --- r5dev/engine/server/sv_main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/r5dev/engine/server/sv_main.cpp b/r5dev/engine/server/sv_main.cpp index 9ad96112..c402ab0b 100644 --- a/r5dev/engine/server/sv_main.cpp +++ b/r5dev/engine/server/sv_main.cpp @@ -164,6 +164,9 @@ bool SV_ActivateServer() void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data) { + if (IsTrainingDedi()) + return; + if (!sv_voiceenable->GetBool()) return; @@ -174,7 +177,7 @@ void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) { - CClient* pClient = g_pServer->GetClient(i); + CClient* const pClient = g_pServer->GetClient(i); if (!pClient) continue; @@ -194,7 +197,7 @@ void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data // there's also supposed to be some xplat checks here // but since r5r is only on PC, there's no point in implementing them here - CNetChan* pNetChan = pClient->GetNetChan(); + CNetChan* const pNetChan = pClient->GetNetChan(); if (!pNetChan) continue; From 101962f5ce362fd5a31e53fce9115bad1fb8d351 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 01:33:34 +0200 Subject: [PATCH 074/113] Engine: simplify "script" command callback for server Code actually doesn't need to be ran in the server frame thread. All the code really does is preparation work. Run it in the main thread but do join the server frame thread (FCVAR_SERVER_FRAME_THREAD) as we can't do concurrent work on the server VM. --- r5dev/engine/server/server.cpp | 14 -------------- r5dev/engine/server/server.h | 3 --- r5dev/engine/sys_dll.cpp | 5 +---- r5dev/game/server/vscript_server.cpp | 12 ------------ r5dev/vscript/vscript.cpp | 6 +----- 5 files changed, 2 insertions(+), 38 deletions(-) diff --git a/r5dev/engine/server/server.cpp b/r5dev/engine/server/server.cpp index d241972c..30359c62 100644 --- a/r5dev/engine/server/server.cpp +++ b/r5dev/engine/server/server.cpp @@ -218,17 +218,6 @@ void CServer::BroadcastMessage(CNetMessage* const msg, const bool onlyActive, co //--------------------------------------------------------------------------------- void CServer::FrameJob(double flFrameTime, bool bRunOverlays, bool bUpdateFrame) { - for (IFrameTask* const& task : g_ServerTaskQueueList) - { - task->RunFrame(); - } - - g_ServerTaskQueueList.erase(std::remove_if(g_ServerTaskQueueList.begin(), - g_ServerTaskQueueList.end(), [](const IFrameTask* task) - { - return task->IsFinished(); - }), g_ServerTaskQueueList.end()); - CServer__FrameJob(flFrameTime, bRunOverlays, bUpdateFrame); LiveAPISystem()->RunFrame(); } @@ -254,6 +243,3 @@ void VServer::Detour(const bool bAttach) const /////////////////////////////////////////////////////////////////////////////// CServer* g_pServer = nullptr; CClientExtended CServer::sm_ClientsExtended[MAX_PLAYERS]; - -std::list g_ServerTaskQueueList; -CFrameTask g_ServerTaskQueue; diff --git a/r5dev/engine/server/server.h b/r5dev/engine/server/server.h index e0ba76f4..ffbb1fac 100644 --- a/r5dev/engine/server/server.h +++ b/r5dev/engine/server/server.h @@ -112,9 +112,6 @@ static_assert(sizeof(CServer) == 0x25264C0); extern CServer* g_pServer; -extern std::list g_ServerTaskQueueList; -extern CFrameTask g_ServerTaskQueue; - extern ConVar sv_showconnecting; extern ConVar sv_pylonVisibility; diff --git a/r5dev/engine/sys_dll.cpp b/r5dev/engine/sys_dll.cpp index 5dc20100..e65fa81d 100644 --- a/r5dev/engine/sys_dll.cpp +++ b/r5dev/engine/sys_dll.cpp @@ -117,11 +117,8 @@ bool CModAppSystemGroup::StaticCreate(CModAppSystemGroup* pModAppSystemGroup) } g_TaskQueueList.push_back(&g_TaskQueue); -#ifndef CLIENT_DLL - g_ServerTaskQueueList.push_back(&g_ServerTaskQueue); -#endif // !CLIENT_DLL - g_bAppSystemInit = true; + return CModAppSystemGroup__Create(pModAppSystemGroup); } diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 8e6cdb63..0ca711d9 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -31,18 +31,6 @@ static void SQVM_ServerScript_f(const CCommand& args) { if (args.ArgC() >= 2) { - const char* code = args.ArgS(); - - if (!ThreadInServerFrameThread()) - { - const string scode(code); - g_ServerTaskQueue.Dispatch([scode]() - { - Script_Execute(scode.c_str(), SQCONTEXT::SERVER); - }, 0); - return; // Only run in server frame thread. - } - Script_Execute(args.ArgS(), SQCONTEXT::SERVER); } } diff --git a/r5dev/vscript/vscript.cpp b/r5dev/vscript/vscript.cpp index 41064fc3..ab0de695 100644 --- a/r5dev/vscript/vscript.cpp +++ b/r5dev/vscript/vscript.cpp @@ -133,11 +133,7 @@ SQBool Script_PrecompileClientScripts(CSquirrelVM* vm) void Script_Execute(const SQChar* code, const SQCONTEXT context) { Assert(context != SQCONTEXT::NONE); - - if (context == SQCONTEXT::CLIENT || context == SQCONTEXT::UI) - Assert(ThreadInMainThread()); - else if (context == SQCONTEXT::SERVER) - Assert(ThreadInServerFrameThread()); + Assert(ThreadInMainOrServerFrameThread()); CSquirrelVM* s = Script_GetScriptHandle(context); const char* const contextName = s_scriptContextNames[(int)context]; From c4a2d61905a4618c9dc156a40dfe665ff0ddbd0c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:08:31 +0200 Subject: [PATCH 075/113] Launcher: fix use after free (ASAN) The launcher would regularly throw the PSA (Program Compatibility Assistance) notification upon exit. Running the program with address sanitizer revealed 'CSurface::GetControlValue()' returned a pointer to a temporary buffer, this is destroyed as 'Forms::Control::Text()' returns class String by value. 'CSurface::GetControlValue()' is no longer necessary since we moved to the official KeyValues class, so this function has been removed all together and the issue has therefore been fixed. --- r5dev/sdklauncher/basepanel.cpp | 36 ++++++++------------------------- r5dev/sdklauncher/basepanel.h | 1 - 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index 60498406..4d798e13 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -58,7 +58,7 @@ void CSurface::Init() this->SetBackColor(Drawing::Color(47, 54, 61)); this->Load += &OnLoad; - this->FormClosing += &OnClose; + this->Closing += &OnClose; // ######################################################################## // GAME @@ -648,16 +648,16 @@ void CSurface::SaveSettings() kv.AddSubKey(sv); // Game. - sv->SetString("playlistsFile", GetControlValue(this->m_PlaylistFileTextBox)); + sv->SetString("playlistsFile", this->m_PlaylistFileTextBox->Text().ToCString()); sv->SetBool("enableCheats", this->m_CheatsToggle->Checked()); sv->SetBool("enableDeveloper", this->m_DeveloperToggle->Checked()); sv->SetBool("enableConsole", this->m_ConsoleToggle->Checked()); sv->SetBool("colorConsole", this->m_ColorConsoleToggle->Checked()); // Engine. - sv->SetString("reservedCoreCount", GetControlValue(this->m_ReservedCoresTextBox)); - sv->SetString("workerThreadCount", GetControlValue(this->m_WorkerThreadsTextBox)); - sv->SetString("processorAffinity", GetControlValue(this->m_ProcessorAffinityTextBox)); + sv->SetString("reservedCoreCount", this->m_ReservedCoresTextBox->Text().ToCString()); + sv->SetString("workerThreadCount", this->m_WorkerThreadsTextBox->Text().ToCString()); + sv->SetString("processorAffinity", this->m_ProcessorAffinityTextBox->Text().ToCString()); sv->SetBool("noAsync", this->m_NoAsyncJobsToggle->Checked()); // Network. @@ -669,9 +669,9 @@ void CSurface::SaveSettings() // Video. sv->SetBool("windowed", this->m_WindowedToggle->Checked()); sv->SetBool("borderless", this->m_NoBorderToggle->Checked()); - sv->SetString("fpsMax", GetControlValue(this->m_FpsTextBox)); - sv->SetString("width", GetControlValue(this->m_WidthTextBox)); - sv->SetString("height", GetControlValue(this->m_HeightTextBox)); + sv->SetString("fpsMax", this->m_FpsTextBox->Text().ToCString()); + sv->SetString("width", this->m_WidthTextBox->Text().ToCString()); + sv->SetString("height", this->m_HeightTextBox->Text().ToCString()); CUtlBuffer outBuf(ssize_t(0), 0, CUtlBuffer::TEXT_BUFFER); kv.RecursiveSaveToFile(outBuf, 0); @@ -1298,26 +1298,6 @@ uint64_t CSurface::GetProcessorAffinity(string& svParameters) return nProcessorAffinity; } -//----------------------------------------------------------------------------- -// Purpose: gets the control item value -// Input : *pControl - -//----------------------------------------------------------------------------- -const char* CSurface::GetControlValue(Forms::Control* pControl) -{ - switch (pControl->GetType()) - { - case Forms::ControlTypes::CheckBox: - case Forms::ControlTypes::RadioButton: - { - return reinterpret_cast(pControl)->Checked() ? "1" : "0"; - } - default: - { - return pControl->Text().ToCString(); - } - } -} - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/r5dev/sdklauncher/basepanel.h b/r5dev/sdklauncher/basepanel.h index cc3036c6..2a6da82b 100644 --- a/r5dev/sdklauncher/basepanel.h +++ b/r5dev/sdklauncher/basepanel.h @@ -45,7 +45,6 @@ private: static void GetVirtualItem(const std::unique_ptr& pEventArgs, Forms::Control* pSender); static void ForwardCommandToGame(Forms::Control* pSender); - const char* GetControlValue(Forms::Control* pControl); uint64_t GetProcessorAffinity(string& szParameter); void AppendParameterInternal(string& svParameterList, const char* szParameter, const char* szArgument = nullptr); From 06a71903f598c42fba39c91539b0748e18ca9a1e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:10:45 +0200 Subject: [PATCH 076/113] Server: add getter for Nucleus ID in CPlayer --- r5dev/game/server/player.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/r5dev/game/server/player.h b/r5dev/game/server/player.h index 546064fe..f201f274 100644 --- a/r5dev/game/server/player.h +++ b/r5dev/game/server/player.h @@ -263,6 +263,8 @@ public: inline bool IsBot() const { return (GetFlags() & FL_FAKECLIENT) != 0; } + inline NucleusID_t GetPlatformUserId() const { return m_platformUserId; }; + private: int m_StuckLast; char gap_5a8c[4]; @@ -279,7 +281,7 @@ private: char m_hardwareIcon[16]; bool m_happyHourActive; char gap_5ee6[2]; - __int64 m_platformUserId; + NucleusID_t m_platformUserId; char m_hardware; char gap_5ef1[7]; __int64 m_classModsActive; From 699469f7b6e76a3f4176c252ab6523e520f74c2f Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:11:13 +0200 Subject: [PATCH 077/113] Server: add getter for net name in CBaseCombatCharacter --- r5dev/game/server/basecombatcharacter.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/r5dev/game/server/basecombatcharacter.h b/r5dev/game/server/basecombatcharacter.h index ef93c12a..c92d72da 100644 --- a/r5dev/game/server/basecombatcharacter.h +++ b/r5dev/game/server/basecombatcharacter.h @@ -44,6 +44,10 @@ struct CTether //----------------------------------------------------------------------------- class CBaseCombatCharacter : public CBaseAnimatingOverlay { +public: + inline const char* GetNetName() const { return m_szNetname; }; + +private: bool m_bPreventWeaponPickup; char gap_15b1[3]; float m_phaseShiftTimeStart; @@ -146,5 +150,4 @@ class CBaseCombatCharacter : public CBaseAnimatingOverlay int m_headAttachment; int m_chestAttachment; }; - #endif // BASECOMBATCHARACTER_H From 8cfcc00bc54c255b392f76d9eefcc08acab507ba Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:27:00 +0200 Subject: [PATCH 078/113] PluginSystem: add callback for chatroom receiver Allow plugins to block chat msg's based on their text. --- r5dev/engine/server/server.cpp | 2 +- r5dev/game/server/gameinterface.cpp | 32 +++++++++++++++++++++++++++++ r5dev/pluginsystem/ipluginsystem.h | 8 ++++++-- r5dev/pluginsystem/pluginsystem.cpp | 24 +++++++++++++++++++++- r5dev/pluginsystem/pluginsystem.h | 32 +++++++++++++++++++++++++++-- r5dev/public/tier1/strtools.h | 4 ++++ r5dev/tier1/strtools.cpp | 31 ++++++++++++++++++++++++++-- 7 files changed, 125 insertions(+), 8 deletions(-) diff --git a/r5dev/engine/server/server.cpp b/r5dev/engine/server/server.cpp index 30359c62..8e5676ab 100644 --- a/r5dev/engine/server/server.cpp +++ b/r5dev/engine/server/server.cpp @@ -177,7 +177,7 @@ CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge) for (auto& callback : !g_PluginSystem.GetConnectClientCallbacks()) { - if (!callback(pServer, pClient, pChallenge)) + if (!callback.Function()(pServer, pClient, pChallenge)) { pClient->Disconnect(REP_MARK_BAD, "#Valve_Reject_Banned"); return nullptr; diff --git a/r5dev/game/server/gameinterface.cpp b/r5dev/game/server/gameinterface.cpp index 52992b0a..7905e32a 100644 --- a/r5dev/game/server/gameinterface.cpp +++ b/r5dev/game/server/gameinterface.cpp @@ -18,6 +18,7 @@ #include "engine/server/server.h" #include "game/shared/usercmd.h" #include "game/server/util_server.h" +#include "pluginsystem/pluginsystem.h" //----------------------------------------------------------------------------- // This is called when a new game is started. (restart, map) @@ -77,8 +78,39 @@ ServerClass* CServerGameDLL::GetAllServerClasses(void) return CallVFunc(index, this); } +static ConVar chat_debug("chat_debug", "0", FCVAR_RELEASE, "Enables chat-related debug printing."); + void __fastcall CServerGameDLL::OnReceivedSayTextMessage(void* thisptr, int senderId, const char* text, bool isTeamChat) { + const CGlobalVars* globals = *g_pGlobals; + if (senderId > 0) + { + if (senderId <= globals->m_nMaxPlayers && senderId != 0xFFFF) + { + CPlayer* player = reinterpret_cast(globals->m_pEdicts[senderId + 30728]); + + if (player && player->IsConnected()) + { + for (auto& cb : !g_PluginSystem.GetChatMessageCallbacks()) + { + if (!cb.Function()(player, text, sv_forceChatToTeamOnly->GetBool())) + { + if (chat_debug.GetBool()) + { + char moduleName[MAX_PATH] = {}; + + V_UnicodeToUTF8(V_UnqualifiedFileName(cb.ModuleName()), moduleName, MAX_PATH); + + Msg(eDLL_T::SERVER, "[%s] Plugin blocked chat message from '%s' (%llu): \"%s\"\n", moduleName, player->GetNetName(), player->GetPlatformUserId(), text); + } + + return; + } + } + } + } + } + // set isTeamChat to false so that we can let the convar sv_forceChatToTeamOnly decide whether team chat should be enforced // this isn't a great way of doing it but it works so meh CServerGameDLL__OnReceivedSayTextMessage(thisptr, senderId, text, false); diff --git a/r5dev/pluginsystem/ipluginsystem.h b/r5dev/pluginsystem/ipluginsystem.h index 21479ec4..be46ed5d 100644 --- a/r5dev/pluginsystem/ipluginsystem.h +++ b/r5dev/pluginsystem/ipluginsystem.h @@ -13,8 +13,12 @@ struct PluginHelpWithAnything_t enum class ePluginCallback : int16_t { - CModAppSystemGroup_Create = 0, - CServer_ConnectClient + // !! - WARNING: if any existing values are changed, you must increment INTERFACEVERSION_PLUGINSYSTEM - !! + + CModAppSystemGroup_Create = 0, + CServer_ConnectClient = 1, + SV_RegisterScriptFunctions = 2, + OnReceivedChatMessage = 3, }; ePluginHelp m_nHelpID; diff --git a/r5dev/pluginsystem/pluginsystem.cpp b/r5dev/pluginsystem/pluginsystem.cpp index 8f5b2e0a..2596ff1d 100644 --- a/r5dev/pluginsystem/pluginsystem.cpp +++ b/r5dev/pluginsystem/pluginsystem.cpp @@ -131,7 +131,16 @@ CUtlVector& CPluginSystem::GetInstances() //----------------------------------------------------------------------------- void CPluginSystem::AddCallback(PluginHelpWithAnything_t* help) { -#define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast(function) +#define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast(function); callback.GetCallbacks().Tail().SetModuleName(moduleName) + + if (!help->m_pFunction) + return; + + // [rexx]: This fetches the path to the module that contains the requested callback function. + // The module name is fetched so that callbacks can be identified by the plugin that they came from. + // This must use the wide-char version of this func, as file paths may contain non-ASCII characters and we don't really want those to break. + wchar_t moduleName[MAX_PATH] = {}; + GetMappedFileNameW((HANDLE)-1, help->m_pFunction, moduleName, MAX_PATH); switch (help->m_nCallbackID) { @@ -145,6 +154,11 @@ void CPluginSystem::AddCallback(PluginHelpWithAnything_t* help) ADD_PLUGIN_CALLBACK(ConnectClientFn, GetConnectClientCallbacks(), help->m_pFunction); break; } + case PluginHelpWithAnything_t::ePluginCallback::OnReceivedChatMessage: + { + ADD_PLUGIN_CALLBACK(OnChatMessageFn, GetChatMessageCallbacks(), help->m_pFunction); + break; + } default: break; } @@ -160,6 +174,9 @@ void CPluginSystem::RemoveCallback(PluginHelpWithAnything_t* help) { #define REMOVE_PLUGIN_CALLBACK(fn, callback, function) callback -= reinterpret_cast(function) + if (!help->m_pFunction) + return; + switch (help->m_nCallbackID) { case PluginHelpWithAnything_t::ePluginCallback::CModAppSystemGroup_Create: @@ -172,6 +189,11 @@ void CPluginSystem::RemoveCallback(PluginHelpWithAnything_t* help) REMOVE_PLUGIN_CALLBACK(ConnectClientFn, GetConnectClientCallbacks(), help->m_pFunction); break; } + case PluginHelpWithAnything_t::ePluginCallback::OnReceivedChatMessage: + { + REMOVE_PLUGIN_CALLBACK(OnChatMessageFn, GetChatMessageCallbacks(), help->m_pFunction); + break; + } default: break; } diff --git a/r5dev/pluginsystem/pluginsystem.h b/r5dev/pluginsystem/pluginsystem.h index 6b60e848..071c11d6 100644 --- a/r5dev/pluginsystem/pluginsystem.h +++ b/r5dev/pluginsystem/pluginsystem.h @@ -6,6 +6,7 @@ class CModAppSystemGroup; class CServer; class CClient; +class CPlayer; struct user_creds_s; template @@ -82,6 +83,32 @@ private: CUtlVector m_vCallbacks; }; +template +class CPluginCallback +{ + friend class CPluginSystem; +public: + CPluginCallback(T f) : function(f) {}; + + inline const T& Function() { return function; }; + inline const wchar_t* ModuleName() { return moduleName; }; + + operator bool() const + { + return function; + } + +protected: + inline void SetModuleName(wchar_t* name) + { + wcscpy_s(moduleName, name); + }; + +private: + T function; + wchar_t moduleName[MAX_PATH]; +}; + class CPluginSystem : IPluginSystem { public: @@ -120,10 +147,11 @@ public: virtual void* HelpWithAnything(PluginHelpWithAnything_t* help); -#define CREATE_PLUGIN_CALLBACK(typeName, type, funcName, varName) public: using typeName = type; CPluginCallbackList& funcName() { return varName; } private: CPluginCallbackList varName; +#define CREATE_PLUGIN_CALLBACK(typeName, type, funcName, varName) public: using typeName = type; CPluginCallbackList>& funcName() { return varName; } private: CPluginCallbackList> varName; CREATE_PLUGIN_CALLBACK(CreateFn, bool(*)(CModAppSystemGroup*), GetCreateCallbacks, createCallbacks); CREATE_PLUGIN_CALLBACK(ConnectClientFn, bool(*)(CServer*, CClient*, user_creds_s*), GetConnectClientCallbacks, connectClientCallbacks); + CREATE_PLUGIN_CALLBACK(OnChatMessageFn, bool(*)(CPlayer*, const char*, bool), GetChatMessageCallbacks, chatMessageCallbacks); #undef CREATE_PLUGIN_CALLBACK @@ -140,4 +168,4 @@ FORCEINLINE CPluginSystem* PluginSystem() // Monitor this and performance profile this if fps drops are detected. #define CALL_PLUGIN_CALLBACKS(callback, ...) \ for (auto& cb : !callback) \ - cb(__VA_ARGS__) + cb.Function()(__VA_ARGS__) diff --git a/r5dev/public/tier1/strtools.h b/r5dev/public/tier1/strtools.h index 20508762..4ea53e5a 100644 --- a/r5dev/public/tier1/strtools.h +++ b/r5dev/public/tier1/strtools.h @@ -7,6 +7,7 @@ #define INCORRECT_PATH_SEPARATOR_S "/" #define CHARACTERS_WHICH_SEPARATE_DIRECTORY_COMPONENTS_IN_PATHNAMES ":/\\" #define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') +#define PATHSEPARATORW(c) ((c) == L'\\' || (c) == L'/') #elif POSIX || defined( _PS3 ) #define CORRECT_PATH_SEPARATOR '/' #define CORRECT_PATH_SEPARATOR_S "/" @@ -14,6 +15,7 @@ #define INCORRECT_PATH_SEPARATOR_S "\\" #define CHARACTERS_WHICH_SEPARATE_DIRECTORY_COMPONENTS_IN_PATHNAMES "/" #define PATHSEPARATOR(c) ((c) == '/') +#define PATHSEPARATORW(c) ((c) == L'/') #endif #define COPY_ALL_CHARACTERS -1 @@ -156,6 +158,8 @@ inline void V_MakeAbsolutePath(char* pOut, size_t outLen, const char* pPath, con size_t V_StripLastDir(char* dirName, size_t maxLen); // Returns a pointer to the unqualified file name (no path) of a file name const char* V_UnqualifiedFileName(const char* in); +const wchar_t* V_UnqualifiedFileName(const wchar_t* in); + // Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary void V_ComposeFileName(const char* path, const char* filename, char* dest, size_t destSize); diff --git a/r5dev/tier1/strtools.cpp b/r5dev/tier1/strtools.cpp index b7958849..454eb186 100644 --- a/r5dev/tier1/strtools.cpp +++ b/r5dev/tier1/strtools.cpp @@ -503,8 +503,15 @@ int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes cchResult = wcstombs(pUTF8, pUnicode, cubDestSizeInBytes); #endif - if (cubDestSizeInBytes > 0) - pUTF8[cubDestSizeInBytes - 1] = 0; + if (cchResult <= 0 || cchResult > cubDestSizeInBytes) + { + if (cchResult != cubDestSizeInBytes || pUTF8[cubDestSizeInBytes - 1] != '\0') + { + *pUTF8 = '\0'; + } + } + else + pUTF8[cchResult] = '\0'; return cchResult; } @@ -1248,6 +1255,26 @@ const char* V_UnqualifiedFileName(const char* in) return out; } +const wchar_t* V_UnqualifiedFileName(const wchar_t* in) +{ + Assert(in); + + const wchar_t* out = in; + + while (*in) + { + if (PATHSEPARATORW(*in)) + { + // +1 to skip the slash + out = in + 1; + } + + in++; + } + + return out; +} + //----------------------------------------------------------------------------- // Purpose: Composes a path and filename together, inserting a path separator // if need be From 9792ce69516de55da81509e4150e7686c591a117 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:28:35 +0200 Subject: [PATCH 079/113] Launcher: initialize all member vars Suppress IntelliSense warnings. --- r5dev/sdklauncher/basepanel.cpp | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index 4d798e13..73e0daf0 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -1303,4 +1303,62 @@ uint64_t CSurface::GetProcessorAffinity(string& svParameters) //----------------------------------------------------------------------------- CSurface::CSurface() : Forms::Form() { + // Game. + m_GameGroup = nullptr; + m_GameGroupExt = nullptr; + m_MapLabel = nullptr; + m_MapCombo = nullptr; + m_PlaylistLabel = nullptr; + m_PlaylistCombo = nullptr; + m_CheatsToggle = nullptr; + m_DeveloperToggle = nullptr; + m_ConsoleToggle = nullptr; + m_ColorConsoleToggle = nullptr; + m_PlaylistFileTextBox = nullptr; + m_PlaylistFileLabel = nullptr; + + // Main. + m_MainGroup = nullptr; + m_MainGroupExt = nullptr; + m_ModeCombo = nullptr; + m_ModeLabel = nullptr; + m_HostNameTextBox = nullptr; + m_HostNameLabel = nullptr; + m_VisibilityCombo = nullptr; + m_VisibilityLabel = nullptr; + m_LaunchArgsTextBox = nullptr; + m_LaunchArgsLabel = nullptr; + m_CleanSDK = nullptr; + m_UpdateSDK = nullptr; + m_LaunchSDK = nullptr; + + // Engine. + m_EngineBaseGroup = nullptr; + m_EngineNetworkGroup = nullptr; + m_EngineVideoGroup = nullptr; + m_ReservedCoresTextBox = nullptr; + m_ReservedCoresLabel = nullptr; + m_WorkerThreadsTextBox = nullptr; + m_WorkerThreadsLabel = nullptr; + m_ProcessorAffinityTextBox = nullptr; + m_ProcessorAffinityLabel = nullptr; + m_NoAsyncJobsToggle = nullptr; + m_NetEncryptionToggle = nullptr; + m_NetRandomKeyToggle = nullptr; + m_QueuedPacketThread = nullptr; + m_NoTimeOutToggle = nullptr; + m_WindowedToggle = nullptr; + m_NoBorderToggle = nullptr; + m_FpsTextBox = nullptr; + m_FpsLabel = nullptr; + m_WidthTextBox = nullptr; + m_HeightTextBox = nullptr; + m_ResolutionLabel = nullptr; + + // Console. + m_ConsoleGroup = nullptr; + m_ConsoleGroupExt = nullptr; + m_ConsoleListView = nullptr; + m_ConsoleCommandTextBox = nullptr; + m_ConsoleSendCommand = nullptr; } From fa04053de79f066a61b1bd602bbdb7dee89a92e3 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 21 Apr 2024 01:50:32 +0200 Subject: [PATCH 080/113] Resource: use default protoc instead of custom one No need to use the custom one. --- r5dev/resource/protobuf/generate.bat | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/r5dev/resource/protobuf/generate.bat b/r5dev/resource/protobuf/generate.bat index ebc05ef4..428f2219 100644 --- a/r5dev/resource/protobuf/generate.bat +++ b/r5dev/resource/protobuf/generate.bat @@ -1,3 +1,3 @@ -protoc64 --cpp_out=. sig_map.proto -protoc64 --cpp_out=. netcon.proto -protoc64 --cpp_out=. events.proto +protoc --cpp_out=. sig_map.proto +protoc --cpp_out=. netcon.proto +protoc --cpp_out=. events.proto From aa6a5dcb6eb537ea847c3812a99b5320e183913a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 21 Apr 2024 01:54:58 +0200 Subject: [PATCH 081/113] NetCon: rename to 'netcon'; remove platform suffix Netcon is no longer 32bits. Previously it was made 32bits to maximize system compatibility, but this was unfortunately too hard to maintain after the migration to CMake, it was also no longer worth it as the tool never got used on 32bit platforms. Renamed to avoid confusion. --- r5dev/netconsole/CMakeLists.txt | 7 ++----- r5dev/resource/batch/clean_sdk.bat | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/r5dev/netconsole/CMakeLists.txt b/r5dev/netconsole/CMakeLists.txt index 7b6727ea..e978455b 100644 --- a/r5dev/netconsole/CMakeLists.txt +++ b/r5dev/netconsole/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required( VERSION 3.16 ) -add_module( "exe" "netconsole" "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) +add_module( "exe" "netcon" "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) start_sources() @@ -31,11 +31,8 @@ add_sources( SOURCE_GROUP "Windows" end_sources( "${BUILD_OUTPUT_DIR}/bin/" ) -set_target_properties( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME - "netcon32" -) set_target_properties( ${PROJECT_NAME} PROPERTIES - VS_DEBUGGER_COMMAND "netcon32.exe" + VS_DEBUGGER_COMMAND "${PROJECT_NAME}.exe" VS_DEBUGGER_COMMAND_ARGUMENTS "-ansicolor" VS_DEBUGGER_WORKING_DIRECTORY "$(ProjectDir)../../../${BUILD_OUTPUT_DIR}/bin/" ) diff --git a/r5dev/resource/batch/clean_sdk.bat b/r5dev/resource/batch/clean_sdk.bat index 2c1f1592..a3fe7ee4 100644 --- a/r5dev/resource/batch/clean_sdk.bat +++ b/r5dev/resource/batch/clean_sdk.bat @@ -17,6 +17,7 @@ del /Q "%~dp0..\r5apexsdkd64.dll" del /Q "%~dp0..\r5detours.dll" del /Q "%~dp0..\r5dev.dll" del /Q "%~dp0..\bin\naveditor.exe" +del /Q "%~dp0..\bin\netcon32.exe" del /Q "%~dp0..\platform\cfg\englishclient_build_vpk.cfg" del /Q "%~dp0..\platform\cfg\englishclient_extract_vpk.cfg" del /Q "%~dp0..\platform\cfg\englishserver_build_vpk.cfg" From 299ab763e4f74a05e6a2bb34eb922bc23b743583 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:38:48 +0200 Subject: [PATCH 082/113] VpkLib: light cleanup Improve global names, initialize VPKDirHeader_t structure, make inlines for checking if language or target exists. --- r5dev/public/const.h | 18 ++++++++++++++ r5dev/public/localize/ilocalize.h | 13 ++++++++++ r5dev/revpk/revpk.cpp | 19 +++++++++------ r5dev/vpklib/packedstore.cpp | 40 ++++++++++--------------------- r5dev/vpklib/packedstore.h | 25 +++++++++++-------- 5 files changed, 70 insertions(+), 45 deletions(-) diff --git a/r5dev/public/const.h b/r5dev/public/const.h index ebca76a7..63535f79 100644 --- a/r5dev/public/const.h +++ b/r5dev/public/const.h @@ -66,4 +66,22 @@ enum MoveType_t MOVETYPE_ZEROG // ? }; +inline const char* const g_GameDllTargets[] = { + "server", + "client" +}; + +inline bool V_GameTargetExists(const char* const pTarget) +{ + for (size_t i = 0; i < V_ARRAYSIZE(g_GameDllTargets); i++) + { + if (V_strcmp(pTarget, g_GameDllTargets[i]) == NULL) + { + return true; + } + } + + return false; +} + #endif // CONST_H \ No newline at end of file diff --git a/r5dev/public/localize/ilocalize.h b/r5dev/public/localize/ilocalize.h index 2c145557..a696c69a 100644 --- a/r5dev/public/localize/ilocalize.h +++ b/r5dev/public/localize/ilocalize.h @@ -73,4 +73,17 @@ inline const char* const g_LanguageNames[] = { "polish", }; +inline bool V_LocaleExists(const char* const pLocale) +{ + for (size_t i = 0; i < V_ARRAYSIZE(g_LanguageNames); i++) + { + if (V_strcmp(pLocale, g_LanguageNames[i]) == NULL) + { + return true; + } + } + + return false; +} + #endif // LOCALIZE_H diff --git a/r5dev/revpk/revpk.cpp b/r5dev/revpk/revpk.cpp index b6fc6842..5434d36d 100644 --- a/r5dev/revpk/revpk.cpp +++ b/r5dev/revpk/revpk.cpp @@ -13,6 +13,8 @@ #include "windows/console.h" #include "vpklib/packedstore.h" +#include "public/const.h" +#include "localize/ilocalize.h" #include "vstdlib/keyvaluessystem.h" #include "filesystem/filesystem_std.h" @@ -83,8 +85,8 @@ static void ReVPK_Usage() usage.Format( "ReVPK instructions and options:\n" "For packing; run 'revpk %s' with the following parameters:\n" - "\t<%s>\t- locale prefix for the directory tree file\n" - "\t<%s>\t- context scope for the VPK files [\"server\", \"client\"]\n" + "\t<%s>\t- locale prefix for the directory file ( defaults to \"%s\" )\n" + "\t<%s>\t- context scope for the VPK files [\"%s\", \"%s\"]\n" "\t<%s>\t- level name for the VPK files\n" "\t<%s>\t- ( optional ) path to the workspace containing the manifest file\n" "\t<%s>\t- ( optional ) path in which the VPK files will be built\n" @@ -92,12 +94,15 @@ static void ReVPK_Usage() "\t<%s>\t- ( optional ) the level of compression [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"]\n\n" "For unpacking; run 'revpk %s' with the following parameters:\n" - "\t<%s>\t- path and name of the target directory tree or data block file\n" + "\t<%s>\t- path and name of the target VPK files\n" "\t<%s>\t- ( optional ) path in which the VPK files will be unpacked\n" - "\t<%s>\t- ( optional ) whether to parse the directory tree file name from the data block file name\n", + "\t<%s>\t- ( optional ) whether to parse the directory file name from the pack file name\n", PACK_COMMAND, // Pack parameters: - "locale", "context", "levelName", "workspacePath", "buildPath", + "locale", g_LanguageNames[0], + "context", g_GameDllTargets[0], g_GameDllTargets[1], + + "levelName", "workspacePath", "buildPath", "numThreads", // Num helper threads. -1, LZHAM_MAX_HELPER_THREADS, -1, @@ -106,7 +111,7 @@ static void ReVPK_Usage() "fastest", "faster", "default", "better", "uber", UNPACK_COMMAND,// Unpack parameters: - "fileName", "inputDir", "sanitize" + "fileName", "outPath", "sanitize" ); Warning(eDLL_T::FS, "%s", usage.Get()); @@ -173,7 +178,7 @@ static void ReVPK_Pack(const CCommand& args) // For clients, we need an enable file which the engine uses to determine // whether or not to mount the front-end VPK file. - if (V_strcmp(contextName, DIR_TARGET[EPackedStoreTargets::STORE_TARGET_CLIENT]) == NULL) + if (V_strcmp(contextName, g_GameDllTargets[EPackedStoreTargets::STORE_TARGET_CLIENT]) == NULL) { ReVPK_WriteEnableFile(buildPath); } diff --git a/r5dev/vpklib/packedstore.cpp b/r5dev/vpklib/packedstore.cpp index 29a402cf..3acd2162 100644 --- a/r5dev/vpklib/packedstore.cpp +++ b/r5dev/vpklib/packedstore.cpp @@ -463,7 +463,7 @@ void CPackedStoreBuilder::PackStore(const VPKPair_t& vpkPair, const char* worksp return; } - std::unique_ptr pEntryBuffer(new uint8_t[ENTRY_MAX_LEN]); + std::unique_ptr pEntryBuffer(new uint8_t[VPK_ENTRY_MAX_LEN]); if (!pEntryBuffer) { @@ -587,8 +587,8 @@ void CPackedStoreBuilder::UnpackStore(const VPKDir_t& vpkDir, const char* worksp workspacePath.AppendSlash(); workspacePath.FixSlashes('/'); - std::unique_ptr pDestBuffer(new uint8_t[ENTRY_MAX_LEN]); - std::unique_ptr pSourceBuffer(new uint8_t[ENTRY_MAX_LEN]); + std::unique_ptr pDestBuffer(new uint8_t[VPK_ENTRY_MAX_LEN]); + std::unique_ptr pSourceBuffer(new uint8_t[VPK_ENTRY_MAX_LEN]); if (!pDestBuffer || !pSourceBuffer) { @@ -652,7 +652,7 @@ void CPackedStoreBuilder::UnpackStore(const VPKDir_t& vpkDir, const char* worksp continue; } - size_t nDstLen = ENTRY_MAX_LEN; + size_t nDstLen = VPK_ENTRY_MAX_LEN; assert(fragment.m_nCompressedSize <= nDstLen); if (fragment.m_nCompressedSize > nDstLen) @@ -747,13 +747,13 @@ VPKEntryBlock_t::VPKEntryBlock_t(const uint8_t* pData, size_t nLen, int64_t nOff m_EntryPath.FixSlashes('/'); - size_t nFragmentCount = (nLen + ENTRY_MAX_LEN - 1) / ENTRY_MAX_LEN; + size_t nFragmentCount = (nLen + VPK_ENTRY_MAX_LEN - 1) / VPK_ENTRY_MAX_LEN; size_t nFileSize = nLen; int64_t nCurrentOffset = nOffset; for (size_t i = 0; i < nFragmentCount; i++) // Fragment data into 1 MiB chunks. { - size_t nSize = std::min(ENTRY_MAX_LEN, nFileSize); + size_t nSize = std::min(VPK_ENTRY_MAX_LEN, nFileSize); nFileSize -= nSize; m_Fragments.AddToTail(VPKChunkDescriptor_t(nLoadFlags, nTextureFlags, nCurrentOffset, nSize, nSize)); nCurrentOffset += nSize; @@ -802,15 +802,7 @@ VPKChunkDescriptor_t::VPKChunkDescriptor_t(uint32_t nLoadFlags, uint16_t nTextur //----------------------------------------------------------------------------- VPKPair_t::VPKPair_t(const char* pLocale, const char* pTarget, const char* pLevel, int nPatch) { - bool bFoundLocale = false; - - for (size_t i = 0; i < SDK_ARRAYSIZE(g_LanguageNames); i++) - { - if (V_strcmp(pLocale, g_LanguageNames[i]) == NULL) - { - bFoundLocale = true; - } - } + const bool bFoundLocale = V_LocaleExists(pLocale); if (!bFoundLocale) { @@ -818,20 +810,12 @@ VPKPair_t::VPKPair_t(const char* pLocale, const char* pTarget, const char* pLeve pLocale = g_LanguageNames[0]; } - bool bFoundTarget = false; - - for (size_t i = 0; i < SDK_ARRAYSIZE(DIR_TARGET); i++) - { - if (V_strcmp(pTarget, DIR_TARGET[i]) == NULL) - { - bFoundTarget = true; - } - } + const bool bFoundTarget = V_GameTargetExists(pTarget); if (!bFoundTarget) { - Warning(eDLL_T::FS, "Target '%s' not supported; using default '%s'\n", pTarget, DIR_TARGET[STORE_TARGET_SERVER]); - pTarget = DIR_TARGET[STORE_TARGET_SERVER]; + Warning(eDLL_T::FS, "Target '%s' not supported; using default '%s'\n", pTarget, g_GameDllTargets[STORE_TARGET_SERVER]); + pTarget = g_GameDllTargets[STORE_TARGET_SERVER]; } m_PackName.Format("%s_%s.bsp.pak000_%03d.vpk", pTarget, pLevel, nPatch); @@ -902,9 +886,9 @@ VPKDir_t::VPKDir_t(const CUtlString& dirFilePath, bool bSanitizeName) CUtlString packDirToSearch; packDirToSearch.Append(g_LanguageNames[i]); - for (size_t j = 0; j < SDK_ARRAYSIZE(DIR_TARGET); j++) + for (size_t j = 0; j < SDK_ARRAYSIZE(g_GameDllTargets); j++) { - const char* targetName = DIR_TARGET[j]; + const char* targetName = g_GameDllTargets[j]; if (sanitizedName.Find(targetName) != -1) { diff --git a/r5dev/vpklib/packedstore.h b/r5dev/vpklib/packedstore.h index d065f24a..88e2bcaf 100644 --- a/r5dev/vpklib/packedstore.h +++ b/r5dev/vpklib/packedstore.h @@ -1,6 +1,4 @@ -#ifndef PACKEDSTORE_H -#define PACKEDSTORE_H -/******************************************************************* +/******************************************************************* * ██████╗ ██╗ ██╗ ██╗██████╗ ██╗ ██╗ ██╗ ██╗██████╗ * * ██╔â•â•â–ˆâ–ˆâ•—███║ ██║ ██║██╔â•â•â–ˆâ–ˆâ•—██║ ██╔╠██║ ██║██╔â•â•â–ˆâ–ˆâ•— * * ██████╔â•â•šâ–ˆâ–ˆâ•‘ ██║ ██║██████╔â•â–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ•”╠██║ ██║██████╔╠* @@ -8,6 +6,10 @@ * ██║ ██║ ██║ ╚████╔╠██║ ██║ ██╗ ███████╗██║██████╔╠* * â•šâ•â• â•šâ•â• â•šâ•â• â•šâ•â•â•â• â•šâ•â• â•šâ•â• â•šâ•â• â•šâ•â•â•â•â•â•â•â•šâ•â•â•šâ•â•â•â•â•â• * *******************************************************************/ +#ifndef PACKEDSTORE_H +#define PACKEDSTORE_H + +#include "public/const.h" #include "public/ipackedstore.h" #include "public/ifilesystem.h" #include "public/tier1/strtools.h" @@ -19,18 +21,12 @@ constexpr unsigned int VPK_HEADER_MARKER = 0x55AA1234; constexpr unsigned int VPK_MAJOR_VERSION = 2; constexpr unsigned int VPK_MINOR_VERSION = 3; constexpr unsigned int VPK_DICT_SIZE = 20; -constexpr int ENTRY_MAX_LEN = 1024 * 1024; +constexpr unsigned int VPK_ENTRY_MAX_LEN = 1024 * 1024; constexpr int PACKFILEPATCH_MAX = 512; constexpr int PACKFILEINDEX_SEP = 0x0; constexpr int PACKFILEINDEX_END = 0xffff; constexpr const char VPK_IGNORE_FILE[] = ".vpkignore"; -static const char* const DIR_TARGET[] -{ - "server", - "client" -}; - //----------------------------------------------------------------------------- // KeyValues structure for the VPK manifest file. This struct gets populated by // the VPK's corresponding manifest file, which ultimately determines how each @@ -131,6 +127,15 @@ struct VPKDirHeader_t uint16_t m_nMinorVersion; // Vpk minor version. uint32_t m_nDirectorySize; // Directory tree size. uint32_t m_nSignatureSize; // Directory signature. + + VPKDirHeader_t() + { + m_nHeaderMarker = 0; + m_nMajorVersion = 0; + m_nMinorVersion = 0; + m_nDirectorySize = 0; + m_nSignatureSize = 0; + } }; //----------------------------------------------------------------------------- From da09d8b631d3be2a25ea313ec1cd26898f39ed0e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:01:50 +0200 Subject: [PATCH 083/113] CppKore: add callback for drop down opened event --- r5dev/thirdparty/cppnet/cppkore/ComboBox.cpp | 7 +++++++ r5dev/thirdparty/cppnet/cppkore/ComboBox.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/r5dev/thirdparty/cppnet/cppkore/ComboBox.cpp b/r5dev/thirdparty/cppnet/cppkore/ComboBox.cpp index a9b1dcfe..a0e7669d 100644 --- a/r5dev/thirdparty/cppnet/cppkore/ComboBox.cpp +++ b/r5dev/thirdparty/cppnet/cppkore/ComboBox.cpp @@ -283,6 +283,11 @@ namespace Forms SelectedIndexChanged.RaiseEvent(this); } + void ComboBox::OnDropDownOpened() + { + DropDownOpened.RaiseEvent(this); + } + void ComboBox::OnDropDownClosed() { DropDownClosed.RaiseEvent(this); @@ -412,6 +417,8 @@ namespace Forms OnSelectedIndexChanged(); OnSelectedItemChanged(); break; + case CBN_DROPDOWN: + OnDropDownOpened(); case CBN_CLOSEUP: OnDropDownClosed(); break; diff --git a/r5dev/thirdparty/cppnet/cppkore/ComboBox.h b/r5dev/thirdparty/cppnet/cppkore/ComboBox.h index d5632b50..538a168d 100644 --- a/r5dev/thirdparty/cppnet/cppkore/ComboBox.h +++ b/r5dev/thirdparty/cppnet/cppkore/ComboBox.h @@ -134,11 +134,13 @@ namespace Forms virtual void OnHandleCreated(); virtual void OnSelectedItemChanged(); virtual void OnSelectedIndexChanged(); + virtual void OnDropDownOpened(); virtual void OnDropDownClosed(); // We must define event handlers here EventBase SelectedItemChanged; EventBase SelectedIndexChanged; + EventBase DropDownOpened; EventBase DropDownClosed; // Override WndProc for specific combo box messages. From 84abfced6ab5848f07217e073e220e8a397e95bb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:03:31 +0200 Subject: [PATCH 084/113] VpkLib: make regex available to other code and utilize those instead Prevent copies or similar patterns that might not work as good. --- r5dev/engine/cmodel_bsp.cpp | 10 +++++----- r5dev/vpklib/packedstore.cpp | 9 +++------ r5dev/vpklib/packedstore.h | 3 +++ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/r5dev/engine/cmodel_bsp.cpp b/r5dev/engine/cmodel_bsp.cpp index b5511af7..7daa8cf5 100644 --- a/r5dev/engine/cmodel_bsp.cpp +++ b/r5dev/engine/cmodel_bsp.cpp @@ -9,6 +9,7 @@ #include "tier0/memstd.h" #include "tier0/jobthread.h" #include "tier1/fmtstr.h" +#include "tier1/keyvalues.h" #include "tier2/fileutils.h" #include "engine/sys_dll2.h" #include "engine/host_cmd.h" @@ -19,7 +20,7 @@ #include "rtech/pak/paktools.h" #include "rtech/pak/pakstream.h" -#include "tier1/keyvalues.h" +#include "vpklib/packedstore.h" #include "datacache/mdlcache.h" #include "filesystem/filesystem.h" #ifndef DEDICATED @@ -29,8 +30,6 @@ CUtlVector g_InstalledMaps; CFmtStrN s_CurrentLevelName; -static std::regex s_ArchiveRegex{ R"([^_]*_(.*)(.bsp.pak000_dir).*)" }; - static CustomPakData_t s_customPakData; static KeyValues* s_pLevelSetKV = nullptr; @@ -136,11 +135,11 @@ void Mod_GetAllInstalledMaps() // slash, as the files are loaded from 'vpk/'. Assert(pFileName); - std::regex_search(pFileName, regexMatches, s_ArchiveRegex); + std::regex_search(pFileName, regexMatches, g_VpkDirFileRegex); if (!regexMatches.empty()) { - const std::sub_match& match = regexMatches[1]; + const std::sub_match& match = regexMatches[2]; if (match.compare("frontend") == 0) continue; // Frontend contains no BSP's. @@ -155,6 +154,7 @@ void Mod_GetAllInstalledMaps() else { const string mapName = match.str(); + if (!g_InstalledMaps.HasElement(mapName.c_str())) g_InstalledMaps.AddToTail(mapName.c_str()); } diff --git a/r5dev/vpklib/packedstore.cpp b/r5dev/vpklib/packedstore.cpp index 3acd2162..cbe48e3b 100644 --- a/r5dev/vpklib/packedstore.cpp +++ b/r5dev/vpklib/packedstore.cpp @@ -35,9 +35,6 @@ extern CFileSystem_Stdio* FileSystem(); -static const std::regex s_DirFileRegex{ R"((?:.*\/)?([^_]*)(?:_)(.*)(.bsp.pak000_dir).*)" }; -static const std::regex s_BlockFileRegex{ R"(pak000_([0-9]{3}))" }; - //----------------------------------------------------------------------------- // Purpose: gets the LZHAM compression level // output : lzham_compress_level @@ -98,7 +95,7 @@ CUtlString PackedStore_GetDirBaseName(const CUtlString& dirFileName) const char* baseFileName = V_UnqualifiedFileName(dirFileName.String()); std::cmatch regexMatches; - std::regex_search(baseFileName, regexMatches, s_DirFileRegex); + std::regex_search(baseFileName, regexMatches, g_VpkDirFileRegex); CUtlString result; result.Format("%s_%s", regexMatches[1].str().c_str(), regexMatches[2].str().c_str()); @@ -117,7 +114,7 @@ CUtlString PackedStore_GetDirNameParts(const CUtlString& dirFileName, const int const char* baseFileName = V_UnqualifiedFileName(dirFileName.String()); std::cmatch regexMatches; - std::regex_search(baseFileName, regexMatches, s_DirFileRegex); + std::regex_search(baseFileName, regexMatches, g_VpkDirFileRegex); return regexMatches[nCaptureGroup].str().c_str(); } @@ -846,7 +843,7 @@ VPKDir_t::VPKDir_t(const CUtlString& dirFilePath, bool bSanitizeName) } std::cmatch regexMatches; - std::regex_search(dirFilePath.String(), regexMatches, s_BlockFileRegex); + std::regex_search(dirFilePath.String(), regexMatches, g_VpkPackFileRegex); if (regexMatches.empty()) // Not a block file, or not following the naming scheme. { diff --git a/r5dev/vpklib/packedstore.h b/r5dev/vpklib/packedstore.h index 88e2bcaf..aa79feea 100644 --- a/r5dev/vpklib/packedstore.h +++ b/r5dev/vpklib/packedstore.h @@ -27,6 +27,9 @@ constexpr int PACKFILEINDEX_SEP = 0x0; constexpr int PACKFILEINDEX_END = 0xffff; constexpr const char VPK_IGNORE_FILE[] = ".vpkignore"; +static const std::regex g_VpkDirFileRegex{ R"((?:.*\/)?([^_]*)(?:_)(.*)(.bsp.pak000_dir).*)" }; +static const std::regex g_VpkPackFileRegex{ R"(pak000_([0-9]{3}))" }; + //----------------------------------------------------------------------------- // KeyValues structure for the VPK manifest file. This struct gets populated by // the VPK's corresponding manifest file, which ultimately determines how each From bdc7929286d4c84200b980032cf46993054b362f Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:06:11 +0200 Subject: [PATCH 085/113] Launcher: several fixes and improvements - Reload map list each time the combo box is opened (needs to refresh if user installed a new map while launcher is still open). - Reload playlists each time the combo box is opened (makes sure that the list is up-to-date if user modified it in any way). - Use global VPK dir regex to parse out map names. --- r5dev/sdklauncher/basepanel.cpp | 54 ++++++++++++++++++++++++--------- r5dev/sdklauncher/basepanel.h | 3 ++ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index 73e0daf0..31d6ac8b 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -6,8 +6,10 @@ #include "basepanel.h" #include "sdklauncher.h" #include "mathlib/bits.h" +#include "vpklib/packedstore.h" #include "vstdlib/keyvaluessystem.h" #include "filesystem/filesystem_std.h" +#include "tier2/fileutils.h" extern CFileSystem_Stdio* FileSystem(); @@ -93,6 +95,7 @@ void CSurface::Init() this->m_MapCombo->SetLocation({ 15, 25 }); this->m_MapCombo->SetTabIndex(0); this->m_MapCombo->SetSelectedIndex(0); + this->m_MapCombo->DropDownOpened += ReloadMaplists; this->m_MapCombo->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_MapCombo->SetDropDownStyle(Forms::ComboBoxStyle::DropDownList); this->m_GameGroup->AddControl(this->m_MapCombo); @@ -111,6 +114,7 @@ void CSurface::Init() this->m_PlaylistCombo->SetLocation({ 15, 50 }); this->m_PlaylistCombo->SetTabIndex(0); this->m_PlaylistCombo->SetSelectedIndex(0); + this->m_PlaylistCombo->DropDownOpened += ReloadPlaylists; this->m_PlaylistCombo->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); this->m_PlaylistCombo->SetDropDownStyle(Forms::ComboBoxStyle::DropDownList); this->m_GameGroup->AddControl(this->m_PlaylistCombo); @@ -159,7 +163,6 @@ void CSurface::Init() this->m_PlaylistFileTextBox->SetTabIndex(0); this->m_PlaylistFileTextBox->SetText("playlists_r5_patch.txt"); this->m_PlaylistFileTextBox->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left); - this->m_PlaylistFileTextBox->LostFocus += &ReloadPlaylists; this->m_GameGroupExt->AddControl(this->m_PlaylistFileTextBox); this->m_PlaylistFileLabel = new UIX::UIXLabel(); @@ -536,9 +539,6 @@ void CSurface::Init() //----------------------------------------------------------------------------- void CSurface::Setup() { - this->ParseMaps(); - this->ParsePlaylists(); - this->m_ModeCombo->Items.Add("Host"); this->m_ModeCombo->Items.Add("Server"); this->m_ModeCombo->Items.Add("Client"); @@ -744,29 +744,33 @@ void CSurface::LaunchGame(Forms::Control* pSender) //----------------------------------------------------------------------------- void CSurface::ParseMaps() { + if (!m_MapCombo->Items.Contains("")) + m_MapCombo->Items.Add(""); + const fs::path vpkPath("vpk"); + if (!fs::exists(vpkPath)) { return; } fs::directory_iterator directoryIterator(vpkPath); - std::regex archiveRegex{ R"([^_]*_(.*)(.bsp.pak000_dir).*)" }; - std::smatch regexMatches; + std::cmatch regexMatches; - m_MapCombo->Items.Add(""); for (const fs::directory_entry& directoryEntry : directoryIterator) { std::string fileName = directoryEntry.path().u8string(); - std::regex_search(fileName, regexMatches, archiveRegex); + std::regex_search(fileName.c_str(), regexMatches, g_VpkDirFileRegex); if (!regexMatches.empty()) { - if (regexMatches[1].str().compare("frontend") == 0) + const std::sub_match& match = regexMatches[2]; + + if (match.compare("frontend") == 0) { continue; } - else if (regexMatches[1].str().compare("mp_common") == 0) + else if (match.compare("mp_common") == 0) { if (!this->m_MapCombo->Items.Contains("mp_lobby")) { @@ -774,9 +778,14 @@ void CSurface::ParseMaps() } continue; } - else if (!this->m_MapCombo->Items.Contains(regexMatches[1].str().c_str())) + else { - this->m_MapCombo->Items.Add(regexMatches[1].str().c_str()); + const string mapName = match.str(); + + if (!this->m_MapCombo->Items.Contains(match.str().c_str())) + { + this->m_MapCombo->Items.Add(match.str().c_str()); + } } } } @@ -787,14 +796,14 @@ void CSurface::ParseMaps() //----------------------------------------------------------------------------- void CSurface::ParsePlaylists() { + if (!m_PlaylistCombo->Items.Contains("")) + m_PlaylistCombo->Items.Add(""); + CUtlString playlistPath; playlistPath.Format("platform\\%s", this->m_PlaylistFileTextBox->Text().ToCString()); const char* pPlaylistPath = playlistPath.String(); - if (!m_PlaylistCombo->Items.Contains("")) - m_PlaylistCombo->Items.Add(""); - if (!FileSystem()->FileExists(pPlaylistPath)) return; @@ -822,6 +831,20 @@ void CSurface::ParsePlaylists() } } +//----------------------------------------------------------------------------- +// Purpose: clears the form and reloads the map list +// Input : *pSender - +//----------------------------------------------------------------------------- +void CSurface::ReloadMaplists(Forms::Control* pSender) +{ + CSurface* pSurface = reinterpret_cast(pSender->FindForm()); + + pSurface->m_MapCombo->Items.Clear(); + pSurface->m_MapCombo->OnSizeChanged(); + + pSurface->ParseMaps(); +} + //----------------------------------------------------------------------------- // Purpose: clears the form and reloads the playlist // Input : *pSender - @@ -832,6 +855,7 @@ void CSurface::ReloadPlaylists(Forms::Control* pSender) pSurface->m_PlaylistCombo->Items.Clear(); pSurface->m_PlaylistCombo->OnSizeChanged(); + pSurface->ParsePlaylists(); } diff --git a/r5dev/sdklauncher/basepanel.h b/r5dev/sdklauncher/basepanel.h index 2a6da82b..2c21ffaf 100644 --- a/r5dev/sdklauncher/basepanel.h +++ b/r5dev/sdklauncher/basepanel.h @@ -40,7 +40,10 @@ private: static void LaunchGame(Forms::Control* pSender); static void CleanSDK(Forms::Control* pSender); static void UpdateSDK(Forms::Control* pSender); + + static void ReloadMaplists(Forms::Control* pSender); static void ReloadPlaylists(Forms::Control* pSender); + static void VirtualItemToClipboard(const std::unique_ptr& pEventArgs, Forms::Control* pSender); static void GetVirtualItem(const std::unique_ptr& pEventArgs, Forms::Control* pSender); static void ForwardCommandToGame(Forms::Control* pSender); From 126591cb1f51f57c7b6854fc30ac3a064d82178d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:15:02 +0200 Subject: [PATCH 086/113] Miles: put event queue warnings behind a cvar These warnings can get verbose, especially if events from the map itself are missing. Put behind a cvar and enabled it by default in development configurations. --- r5dev/codecs/Miles/miles_impl.cpp | 15 ++++++++++----- r5dev/resource/cfg/system/autoexec_client_dev.cfg | 6 ++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/r5dev/codecs/Miles/miles_impl.cpp b/r5dev/codecs/Miles/miles_impl.cpp index 9de48fa9..3ee18c3c 100644 --- a/r5dev/codecs/Miles/miles_impl.cpp +++ b/r5dev/codecs/Miles/miles_impl.cpp @@ -6,6 +6,7 @@ #include "filesystem/filesystem.h" static ConVar miles_debug("miles_debug", "0", FCVAR_RELEASE, "Enables debug prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); +static ConVar miles_warnings("miles_warnings", "0", FCVAR_RELEASE, "Enables warning prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); //----------------------------------------------------------------------------- // Purpose: logs debug output emitted from the Miles Sound System @@ -40,7 +41,8 @@ bool Miles_Initialize() // if we are loading english and the file is still not found, we can let it hit the regular engine error, since that is not recoverable if (!FileSystem()->FileExists(baseStreamFilePath.c_str())) { - Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to english...\n", __FUNCTION__, pszLanguage, baseStreamFilePath.c_str()); + Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to '%s'...\n", + __FUNCTION__, pszLanguage, baseStreamFilePath.c_str(), MILES_DEFAULT_LANGUAGE); pszLanguage = MILES_DEFAULT_LANGUAGE; miles_language->SetValue(pszLanguage); @@ -99,11 +101,14 @@ void CSOM_AddEventToQueue(const char* eventName) v_CSOM_AddEventToQueue(eventName); - if (g_milesGlobals->queuedEventHash == 1) - Warning(eDLL_T::AUDIO, "%s: failed to add event to queue; invalid event name '%s'\n", __FUNCTION__, eventName); + if (miles_warnings.GetBool()) + { + if (g_milesGlobals->queuedEventHash == 1) + Warning(eDLL_T::AUDIO, "%s: failed to add event to queue; invalid event name '%s'\n", __FUNCTION__, eventName); - if (g_milesGlobals->queuedEventHash == 2) - Warning(eDLL_T::AUDIO, "%s: failed to add event to queue; event '%s' not found.\n", __FUNCTION__, eventName); + if (g_milesGlobals->queuedEventHash == 2) + Warning(eDLL_T::AUDIO, "%s: failed to add event to queue; event '%s' not found.\n", __FUNCTION__, eventName); + } }; diff --git a/r5dev/resource/cfg/system/autoexec_client_dev.cfg b/r5dev/resource/cfg/system/autoexec_client_dev.cfg index 652de307..978e9f1d 100644 --- a/r5dev/resource/cfg/system/autoexec_client_dev.cfg +++ b/r5dev/resource/cfg/system/autoexec_client_dev.cfg @@ -72,3 +72,9 @@ cl_ent_absbox "1" // Display entity abs bo gl_clear_color_buffer "1" // Enable or disable the clearing of the main color buffer. //mat_sync_rt "1" // Enable to debug render threads more easily ( !slower! ). //mat_sync_rt_flushes_gpu "1" // Enable to debug render threads more easily ( !slower! ). + +////////////////////////// +//// SOUND //// +////////////////////////// +//miles_debug "1" // Enable miles debug ( !slower! ). +miles_warnings "1" // Enable miles warnings. From a07069f8f8ec7adfc0c50dc492809bfb3a13f729 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:27:01 +0200 Subject: [PATCH 087/113] Miles: refer to 'MILES_DEFAULT_LANGUAGE' instead of 'english' Enforce 'MILES_DEFAULT_LANGUAGE' as the default rather than "english", even though "english" will always be the default. Also marked cvar 'miles_debug' as FCVAR_DEVELOPMENTONLY. --- r5dev/codecs/Miles/miles_impl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/r5dev/codecs/Miles/miles_impl.cpp b/r5dev/codecs/Miles/miles_impl.cpp index 3ee18c3c..147b34cf 100644 --- a/r5dev/codecs/Miles/miles_impl.cpp +++ b/r5dev/codecs/Miles/miles_impl.cpp @@ -5,7 +5,7 @@ #include "tier1/cvar.h" #include "filesystem/filesystem.h" -static ConVar miles_debug("miles_debug", "0", FCVAR_RELEASE, "Enables debug prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); +static ConVar miles_debug("miles_debug", "0", FCVAR_DEVELOPMENTONLY, "Enables debug prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); static ConVar miles_warnings("miles_warnings", "0", FCVAR_RELEASE, "Enables warning prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); //----------------------------------------------------------------------------- @@ -29,16 +29,16 @@ bool Miles_Initialize() if (!pszLanguage[0]) pszLanguage = MILES_DEFAULT_LANGUAGE; - const bool isEnglishLanguage = _stricmp(pszLanguage, "english") == 0; + const bool isDefaultLanguage = _stricmp(pszLanguage, MILES_DEFAULT_LANGUAGE) == 0; - if (!isEnglishLanguage) + if (!isDefaultLanguage) { const bool useShipSound = !CommandLine()->FindParm("-devsound") || CommandLine()->FindParm("-shipsound"); const std::string baseStreamFilePath = Format("%s/general_%s.mstr", useShipSound ? "audio/ship" : "audio/dev", pszLanguage); - // if the requested language for miles does not have a MSTR file present, throw a non-fatal error and force english as a fallback - // if we are loading english and the file is still not found, we can let it hit the regular engine error, since that is not recoverable + // if the requested language for miles does not have a MSTR file present, throw a non-fatal error and force MILES_DEFAULT_LANGUAGE as a fallback + // if we are loading MILES_DEFAULT_LANGUAGE and the file is still not found, we can let it hit the regular engine error, since that is not recoverable if (!FileSystem()->FileExists(baseStreamFilePath.c_str())) { Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to '%s'...\n", @@ -84,7 +84,7 @@ void MilesBankPatch(Miles::Bank* bank, char* streamPatch, char* localizedStreamP if (header->bankIndex >= header->project->bankCount) Error(eDLL_T::AUDIO, EXIT_FAILURE, - "%s: Attempted to patch bank '%s' that identified itself as bank idx %i.\nProject expects a highest index of %i\n", + "%s: attempted to patch bank \"%s\" that identified itself as bank #%i, project expects a highest index of #%i\n", __FUNCTION__, bank->GetBankName(), header->bankIndex, From 900df8bc6f3dfd190554251327ff8c05fa640cdc Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:51:32 +0200 Subject: [PATCH 088/113] Resource: update vpk build list and remove old build scripts 2 new maps added, which will be includes in the next release. The dedi could still be used to build the vpk's, but ReVPK is prefered. Removed old build scripts. --- r5dev/resource/batch/vpk_build.bat | 4 ++++ r5dev/resource/cfg/tools/build_all_vpk.cfg | 2 -- .../resource/cfg/tools/englishclient_pack_vpk.cfg | 15 --------------- .../cfg/tools/englishclient_unpack_vpk.cfg | 15 --------------- .../resource/cfg/tools/englishserver_pack_vpk.cfg | 14 -------------- .../cfg/tools/englishserver_unpack_vpk.cfg | 14 -------------- 6 files changed, 4 insertions(+), 60 deletions(-) delete mode 100644 r5dev/resource/cfg/tools/build_all_vpk.cfg delete mode 100644 r5dev/resource/cfg/tools/englishclient_pack_vpk.cfg delete mode 100644 r5dev/resource/cfg/tools/englishclient_unpack_vpk.cfg delete mode 100644 r5dev/resource/cfg/tools/englishserver_pack_vpk.cfg delete mode 100644 r5dev/resource/cfg/tools/englishserver_unpack_vpk.cfg diff --git a/r5dev/resource/batch/vpk_build.bat b/r5dev/resource/batch/vpk_build.bat index 6ad096ef..ae691fb4 100644 --- a/r5dev/resource/batch/vpk_build.bat +++ b/r5dev/resource/batch/vpk_build.bat @@ -2,11 +2,13 @@ start /ABOVENORMAL revpk "pack" "english" "server" "mp_common" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_aqueduct" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_aqueduct_night" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_arena_composite" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_arena_phase_runner" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_arena_skygarden" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_ashs_redemption" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_64k_x_64k" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_mu1" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_mu1_night" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_mu2" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_canyonlands_staging" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_desertlands_64k_x_64k" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "server" "mp_rr_desertlands_64k_x_64k_nx" "../ship/" "../vpk/" @@ -17,11 +19,13 @@ start /ABOVENORMAL revpk "pack" "english" "client" "mp_common" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_aqueduct" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_aqueduct_night" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_arena_composite" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_arena_phase_runner" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_arena_skygarden" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_ashs_redemption" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_64k_x_64k" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_mu1" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_mu1_night" "../ship/" "../vpk/" +start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_mu2" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_canyonlands_staging" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_desertlands_64k_x_64k" "../ship/" "../vpk/" start /ABOVENORMAL revpk "pack" "english" "client" "mp_rr_desertlands_64k_x_64k_nx" "../ship/" "../vpk/" diff --git a/r5dev/resource/cfg/tools/build_all_vpk.cfg b/r5dev/resource/cfg/tools/build_all_vpk.cfg deleted file mode 100644 index 7f0f56e4..00000000 --- a/r5dev/resource/cfg/tools/build_all_vpk.cfg +++ /dev/null @@ -1,2 +0,0 @@ -exec "tools/englishserver_pack_vpk.cfg" -exec "tools/englishclient_pack_vpk.cfg" diff --git a/r5dev/resource/cfg/tools/englishclient_pack_vpk.cfg b/r5dev/resource/cfg/tools/englishclient_pack_vpk.cfg deleted file mode 100644 index 2c448176..00000000 --- a/r5dev/resource/cfg/tools/englishclient_pack_vpk.cfg +++ /dev/null @@ -1,15 +0,0 @@ -fs_vpk_pack "english" "client" "frontend" -fs_vpk_pack "english" "client" "mp_common" -fs_vpk_pack "english" "client" "mp_rr_aqueduct" -fs_vpk_pack "english" "client" "mp_rr_aqueduct_night" -fs_vpk_pack "english" "client" "mp_rr_arena_composite" -fs_vpk_pack "english" "client" "mp_rr_arena_skygarden" -fs_vpk_pack "english" "client" "mp_rr_ashs_redemption" -fs_vpk_pack "english" "client" "mp_rr_canyonlands_64k_x_64k" -fs_vpk_pack "english" "client" "mp_rr_canyonlands_mu1" -fs_vpk_pack "english" "client" "mp_rr_canyonlands_mu1_night" -fs_vpk_pack "english" "client" "mp_rr_canyonlands_staging" -fs_vpk_pack "english" "client" "mp_rr_desertlands_64k_x_64k" -fs_vpk_pack "english" "client" "mp_rr_desertlands_64k_x_64k_nx" -fs_vpk_pack "english" "client" "mp_rr_desertlands_64k_x_64k_tt" -fs_vpk_pack "english" "client" "mp_rr_party_crasher" diff --git a/r5dev/resource/cfg/tools/englishclient_unpack_vpk.cfg b/r5dev/resource/cfg/tools/englishclient_unpack_vpk.cfg deleted file mode 100644 index e4e533bc..00000000 --- a/r5dev/resource/cfg/tools/englishclient_unpack_vpk.cfg +++ /dev/null @@ -1,15 +0,0 @@ -fs_vpk_unpack "vpk/englishclient_frontend.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_common.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_aqueduct.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_aqueduct_night.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_arena_composite.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_arena_skygarden.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_ashs_redemption.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_canyonlands_64k_x_64k.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_canyonlands_mu1.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_canyonlands_mu1_night.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_canyonlands_staging.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_desertlands_64k_x_64k.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_desertlands_64k_x_64k_nx.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_desertlands_64k_x_64k_tt.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishclient_mp_rr_party_crasher.bsp.pak000_dir.vpk" diff --git a/r5dev/resource/cfg/tools/englishserver_pack_vpk.cfg b/r5dev/resource/cfg/tools/englishserver_pack_vpk.cfg deleted file mode 100644 index f275d5b5..00000000 --- a/r5dev/resource/cfg/tools/englishserver_pack_vpk.cfg +++ /dev/null @@ -1,14 +0,0 @@ -fs_vpk_pack "english" "server" "mp_common" -fs_vpk_pack "english" "server" "mp_rr_aqueduct" -fs_vpk_pack "english" "server" "mp_rr_aqueduct_night" -fs_vpk_pack "english" "server" "mp_rr_arena_composite" -fs_vpk_pack "english" "server" "mp_rr_arena_skygarden" -fs_vpk_pack "english" "server" "mp_rr_ashs_redemption" -fs_vpk_pack "english" "server" "mp_rr_canyonlands_64k_x_64k" -fs_vpk_pack "english" "server" "mp_rr_canyonlands_mu1" -fs_vpk_pack "english" "server" "mp_rr_canyonlands_mu1_night" -fs_vpk_pack "english" "server" "mp_rr_canyonlands_staging" -fs_vpk_pack "english" "server" "mp_rr_desertlands_64k_x_64k" -fs_vpk_pack "english" "server" "mp_rr_desertlands_64k_x_64k_nx" -fs_vpk_pack "english" "server" "mp_rr_desertlands_64k_x_64k_tt" -fs_vpk_pack "english" "server" "mp_rr_party_crasher" diff --git a/r5dev/resource/cfg/tools/englishserver_unpack_vpk.cfg b/r5dev/resource/cfg/tools/englishserver_unpack_vpk.cfg deleted file mode 100644 index 1962fb42..00000000 --- a/r5dev/resource/cfg/tools/englishserver_unpack_vpk.cfg +++ /dev/null @@ -1,14 +0,0 @@ -fs_vpk_unpack "vpk/englishserver_mp_common.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_aqueduct.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_aqueduct_night.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_arena_composite.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_arena_skygarden.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_ashs_redemption.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_canyonlands_64k_x_64k.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_canyonlands_mu1.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_canyonlands_mu1_night.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_canyonlands_staging.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_desertlands_64k_x_64k.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_desertlands_64k_x_64k_nx.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_desertlands_64k_x_64k_tt.bsp.pak000_dir.vpk" -fs_vpk_unpack "vpk/englishserver_mp_rr_party_crasher.bsp.pak000_dir.vpk" From bdc4112c551c6c6ad9a761553073baf739d81932 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 24 Apr 2024 22:32:50 +0200 Subject: [PATCH 089/113] Game: remove game dll flag from "script" cmd Prevent remote execution, should be done through RCON instead for security. --- r5dev/game/client/vscript_client.cpp | 4 ++-- r5dev/game/server/vscript_server.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index 81e451b8..85a99ea6 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -54,8 +54,8 @@ static void SQVM_UIScript_f(const CCommand& args) } } -static ConCommand script_client("script_client", SQVM_ClientScript_f, "Run input code as CLIENT script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT); -static ConCommand script_ui("script_ui", SQVM_UIScript_f, "Run input code as UI script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT); +static ConCommand script_client("script_client", SQVM_ClientScript_f, "Run input code as CLIENT script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); +static ConCommand script_ui("script_ui", SQVM_UIScript_f, "Run input code as UI script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); //----------------------------------------------------------------------------- // Purpose: checks if the server index is valid, raises an error if not diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 0ca711d9..b700c6b0 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -34,7 +34,7 @@ static void SQVM_ServerScript_f(const CCommand& args) Script_Execute(args.ArgS(), SQCONTEXT::SERVER); } } -static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT | FCVAR_SERVER_FRAME_THREAD); +static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT | FCVAR_SERVER_FRAME_THREAD); namespace VScriptCode { From bbd80e4416180e4199c2175238d7460137415e25 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 5 May 2024 11:31:03 +0200 Subject: [PATCH 090/113] Common: unmark "set" command from FCVAR_DEVELOPMENTONLY from dedicated "set" is already marked as FCVAR_CHEATS, and typically used when sv_cheats 1; remove FCVAR_DEVELOPMENTONLY from dedi builds as well. --- r5dev/common/global.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 16e2e518..231db91a 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -391,7 +391,6 @@ void ConCommand_InitShipped(void) "connectAsSpectator", "connectWithKey", "silentconnect", - "set", "ping", #endif // !DEDICATED "launchplaylist", @@ -399,6 +398,7 @@ void ConCommand_InitShipped(void) "exit", "reload", "restart", + "set", "status", "version", }; From 569ee78df757c2011cc390f72ffc78312055287c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 5 May 2024 11:32:32 +0200 Subject: [PATCH 091/113] Launcher: parse maps and playlists on surface setup This allows you to scroll through the combo list with the scroll wheel without uncollapsing it. --- r5dev/sdklauncher/basepanel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index 31d6ac8b..c24e4e1b 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -539,6 +539,11 @@ void CSurface::Init() //----------------------------------------------------------------------------- void CSurface::Setup() { + // Already parse these out since you can scroll select in a combo box + // without uncollapsing it. + this->ParseMaps(); + this->ParsePlaylists(); + this->m_ModeCombo->Items.Add("Host"); this->m_ModeCombo->Items.Add("Server"); this->m_ModeCombo->Items.Add("Client"); From df363414df98ccac4b2cfc5447099286b64b8523 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 14:05:11 +0200 Subject: [PATCH 092/113] Engine: fix numerous exploitable bugs in voice protocol - Fixed stack smash in CClient:ProcessVoiceData (oob read on bitbuf). - Fixed stack smash in CClient:ProcessDurangoVoiceData (oob read on bitbuf). - Fixed ability to bypass team check on Durango voice packets if forced as reliable from the sender (client). - Incorporated the following missing checks in the durango version of voice broadcasting: - Enforce chat between multiple teams using cvar 'sv_alltalk'. - Ability to also disable Durango voice data with cvar 'sv_voiceenable'. - Ability to echo voice with Durango voice data using cvar 'sv_voiceEcho'. --- r5dev/common/global.cpp | 5 +- r5dev/common/global.h | 2 + r5dev/common/netmessages.h | 89 ++++++++++++++++++++++++ r5dev/engine/client/client.cpp | 38 ++++++++++ r5dev/engine/client/client.h | 12 ++++ r5dev/engine/net_chan.h | 10 +-- r5dev/engine/server/datablock_sender.h | 1 - r5dev/engine/server/sv_main.cpp | 96 ++++++++++++++++++++++++-- r5dev/engine/server/sv_main.h | 1 + r5dev/public/tier1/bitbuf.h | 18 +++++ 10 files changed, 261 insertions(+), 11 deletions(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 231db91a..d12ae85e 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -63,6 +63,8 @@ ConVar* eula_version_accepted = nullptr; ConVar* language_cvar = nullptr; +ConVar* voice_noxplat = nullptr; + //----------------------------------------------------------------------------- // SERVER | #ifndef CLIENT_DLL @@ -152,7 +154,8 @@ void ConVar_InitShipped(void) eula_version = g_pCVar->FindVar("eula_version"); eula_version_accepted = g_pCVar->FindVar("eula_version_accepted"); - language_cvar = g_pCVar->FindVar("language"); + language_cvar = g_pCVar->FindVar("language"); + voice_noxplat = g_pCVar->FindVar("voice_noxplat"); #ifndef DEDICATED cl_updaterate_mp = g_pCVar->FindVar("cl_updaterate_mp"); cl_threaded_bone_setup = g_pCVar->FindVar("cl_threaded_bone_setup"); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 5361c41c..139ad327 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -50,6 +50,8 @@ extern ConVar* eula_version_accepted; extern ConVar* language_cvar; +extern ConVar* voice_noxplat; + //------------------------------------------------------------------------- // SERVER | #ifndef CLIENT_DLL diff --git a/r5dev/common/netmessages.h b/r5dev/common/netmessages.h index e94ed440..c60c3992 100644 --- a/r5dev/common/netmessages.h +++ b/r5dev/common/netmessages.h @@ -372,6 +372,70 @@ public: void* m_DataOut; }; +struct SVC_DurangoVoiceData : public CNetMessage +{ +public: + SVC_DurangoVoiceData() = default; + SVC_DurangoVoiceData(int senderClient, int nBytes, char* data, int unknown, bool useUnreliableStream) + { + void** pVFTable = reinterpret_cast(this); + *pVFTable = g_pSVC_VoiceData_VFTable; + + m_bReliable = false; + m_NetChannel = nullptr; + + m_nFromClient = senderClient; + m_nLength = nBytes; // length in bits + + m_unknown = unknown; + m_useVoiceStream = useUnreliableStream; + + m_DataOut = data; + + m_nGroup = 2; // must be set to 2 to avoid being copied into replay buffer + }; + + virtual ~SVC_DurangoVoiceData() {}; + + virtual void SetNetChannel(CNetChan* netchan) { m_NetChannel = netchan; } + virtual void SetReliable(bool state) { m_bReliable = state; }; + + virtual bool Process(void) + { + return CallVFunc(NetMessageVtbl::Process, this); + }; + virtual bool ReadFromBuffer(bf_read* buffer) + { + return CallVFunc(NetMessageVtbl::ReadFromBuffer, this, buffer); + } + virtual bool WriteToBuffer(bf_write* buffer) + { + return CallVFunc(NetMessageVtbl::WriteToBuffer, this, buffer); + } + + virtual bool IsReliable(void) const { return m_bReliable; }; + + virtual int GetGroup(void) const { return m_nGroup; }; + virtual int GetType(void) const { return NetMessageType::svc_DurangoVoiceData; }; + virtual const char* GetName(void) const { return "svc_DurangoVoiceData"; }; + virtual CNetChan* GetNetChannel(void) const { return m_NetChannel; }; + virtual const char* ToString(void) const + { + static char szBuf[4096]; + V_snprintf(szBuf, sizeof(szBuf), "%s: client %i, bytes %i", this->GetName(), m_nFromClient, ((m_nLength + 7) >> 3)); + + return szBuf; + }; + virtual size_t GetSize(void) const { return sizeof(SVC_DurangoVoiceData); }; + + int m_nFromClient; + int m_nLength; + int m_unknown; + bool m_useVoiceStream; + bf_read m_DataIn; + void* m_DataOut; +}; + class SVC_PlaylistOverrides : public CNetMessage { private: @@ -385,6 +449,31 @@ private: // Client messages: /////////////////////////////////////////////////////////////////////////////////////// +class CLC_VoiceData : public CNetMessage +{ +public: + void* unk0; + int m_nLength; + bf_read m_DataIn; + bf_write m_DataOut; + int unk1; + int unk2; +}; + +class CLC_DurangoVoiceData : public CNetMessage +{ +public: + void* unk0; + int m_nLength; + bf_read m_DataIn; + bf_write m_DataOut; + bool m_skipXidCheck; + bool m_useVoiceStream; + int m_xid; + int m_unknown; +}; + + class CLC_ClientTick : public CNetMessage { public: diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index c628d1ad..61d4260c 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -9,6 +9,7 @@ // /////////////////////////////////////////////////////////////////////////////////// #include "core/stdafx.h" +#include "mathlib/bitvec.h" #include "tier1/cvar.h" #include "tier1/strtools.h" #include "engine/server/server.h" @@ -524,6 +525,41 @@ bool CClient::VProcessSetConVar(CClient* pClient, NET_SetConVar* pMsg) return true; } +//--------------------------------------------------------------------------------- +// Purpose: process voice data +// Input : *pClient - (ADJ) +// *pMsg - +// Output : +//--------------------------------------------------------------------------------- +bool CClient::VProcessVoiceData(CClient* pClient, CLC_VoiceData* pMsg) +{ + char voiceDataBuffer[4096]; + const int bitsRead = pMsg->m_DataIn.ReadBitsClamped(voiceDataBuffer, pMsg->m_nLength); + + CClient* const pAdj = AdjustShiftedThisPointer(pClient); + SV_BroadcastVoiceData(pAdj, Bits2Bytes(bitsRead), voiceDataBuffer); + + return true; +} + +//--------------------------------------------------------------------------------- +// Purpose: process durango voice data +// Input : *pClient - (ADJ) +// *pMsg - +// Output : +//--------------------------------------------------------------------------------- +bool CClient::VProcessDurangoVoiceData(CClient* pClient, CLC_DurangoVoiceData* pMsg) +{ + char voiceDataBuffer[4096]; + const int bitsRead = pMsg->m_DataIn.ReadBitsClamped(voiceDataBuffer, pMsg->m_nLength); + + CClient* const pAdj = AdjustShiftedThisPointer(pClient); + SV_BroadcastDurangoVoiceData(pAdj, Bits2Bytes(bitsRead), voiceDataBuffer, + pMsg->m_xid, pMsg->m_unknown, pMsg->m_useVoiceStream, pMsg->m_skipXidCheck); + + return true; +} + //--------------------------------------------------------------------------------- // Purpose: set UserCmd time buffer // Input : numUserCmdProcessTicksMax - @@ -578,5 +614,7 @@ void VClient::Detour(const bool bAttach) const DetourSetup(&CClient__ProcessStringCmd, &CClient::VProcessStringCmd, bAttach); DetourSetup(&CClient__ProcessSetConVar, &CClient::VProcessSetConVar, bAttach); + DetourSetup(&CClient__ProcessVoiceData, &CClient::VProcessVoiceData, bAttach); + DetourSetup(&CClient__ProcessDurangoVoiceData, &CClient::VProcessDurangoVoiceData, bAttach); #endif // !CLIENT_DLL } diff --git a/r5dev/engine/client/client.h b/r5dev/engine/client/client.h index ea9823fb..9a273b36 100644 --- a/r5dev/engine/client/client.h +++ b/r5dev/engine/client/client.h @@ -69,6 +69,7 @@ public: inline edict_t GetHandle(void) const { return m_nHandle; } inline int GetUserID(void) const { return m_nUserID; } inline NucleusID_t GetNucleusID(void) const { return m_nNucleusID; } + inline int GetXPlatID(void) const { return m_XPlatID; } inline SIGNONSTATE GetSignonState(void) const { return m_nSignonState; } inline PERSISTENCE GetPersistenceState(void) const { return m_nPersistenceState; } @@ -124,6 +125,8 @@ public: // Hook statics: static bool VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg); static bool VProcessSetConVar(CClient* pClient, NET_SetConVar* pMsg); + static bool VProcessVoiceData(CClient* pClient, CLC_VoiceData* pMsg); + static bool VProcessDurangoVoiceData(CClient* pClient, CLC_DurangoVoiceData* pMsg); private: // Stub reimplementation to avoid the 'no overrider' compiler errors in the @@ -208,6 +211,9 @@ private: char pad_5B8[8]; PERSISTENCE m_nPersistenceState; char pad_05C0[48]; + char SnapshotBuffer_AndSomeUnknowns[98344]; // TODO: needs to be reversed further. + int m_XPlatID; + char pad_30758[196964]; ServerDataBlock m_DataBlock; char pad_4A3D8[60]; int m_LastMovementTick; @@ -293,6 +299,8 @@ inline void*(*CClient__SendSnapshot)(CClient* pClient, CClientFrame* pFrame, int inline void(*CClient__WriteDataBlock)(CClient* pClient, bf_write& buf); inline bool(*CClient__ProcessStringCmd)(CClient* pClient, NET_StringCmd* pMsg); inline bool(*CClient__ProcessSetConVar)(CClient* pClient, NET_SetConVar* pMsg); +inline bool(*CClient__ProcessVoiceData)(CClient* pClient, CLC_VoiceData* pMsg); +inline bool(*CClient__ProcessDurangoVoiceData)(CClient* pClient, CLC_DurangoVoiceData* pMsg); /////////////////////////////////////////////////////////////////////////////// class VClient : public IDetour @@ -309,6 +317,8 @@ class VClient : public IDetour LogFunAdr("CClient::WriteDataBlock", CClient__WriteDataBlock); LogFunAdr("CClient::ProcessStringCmd", CClient__ProcessStringCmd); LogFunAdr("CClient::ProcessSetConVar", CClient__ProcessSetConVar); + LogFunAdr("CClient::ProcessVoiceData", CClient__ProcessVoiceData); + LogFunAdr("CClient::ProcessDurangoVoiceData", CClient__ProcessDurangoVoiceData); } virtual void GetFun(void) const { @@ -323,6 +333,8 @@ class VClient : public IDetour g_GameDll.FindPatternSIMD("48 83 EC 28 48 83 C2 20").GetPtr(CClient__ProcessSetConVar); g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 10 48 89 70 18 57 48 81 EC ?? ?? ?? ?? 0F 29 70 E8 8B F2").GetPtr(CClient__SetSignonState); + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 44 8B 42 20").GetPtr(CClient__ProcessVoiceData); + g_GameDll.FindPatternSIMD("40 53 57 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 44 8B 42 20").GetPtr(CClient__ProcessDurangoVoiceData); } virtual void GetVar(void) const { } virtual void GetCon(void) const { } diff --git a/r5dev/engine/net_chan.h b/r5dev/engine/net_chan.h index 1a032bbe..88414cd0 100644 --- a/r5dev/engine/net_chan.h +++ b/r5dev/engine/net_chan.h @@ -124,10 +124,12 @@ public: int GetSequenceNr(int flow) const; double GetTimeConnected(void) const; - inline float GetTimeoutSeconds(void) const { return m_Timeout; } - inline int GetSocket(void) const { return m_Socket; } - inline const bf_write& GetStreamVoice(void) const { return m_StreamVoice; } - inline const netadr_t& GetRemoteAddress(void) const { return remote_address; } + inline float GetTimeoutSeconds(void) const { return m_Timeout; } + inline int GetSocket(void) const { return m_Socket; } + inline const bf_write& GetStreamVoice(void) const { return m_StreamVoice; } + inline const bf_write& GetStreamReliable(void) const { return m_StreamReliable; } + inline const bf_write& GetStreamUnreliable(void) const { return m_StreamUnreliable; } + inline const netadr_t& GetRemoteAddress(void) const { return remote_address; } int GetNumBitsWritten(const bool bReliable); int GetNumBitsLeft(const bool bReliable); diff --git a/r5dev/engine/server/datablock_sender.h b/r5dev/engine/server/datablock_sender.h index 29f505a9..3f48995e 100644 --- a/r5dev/engine/server/datablock_sender.h +++ b/r5dev/engine/server/datablock_sender.h @@ -23,7 +23,6 @@ public: struct ServerDataBlock { - char blockBuffer[295312]; // this might be wrong !!! void* userData; char gapC0008[56]; ServerDataBlockSender sender; diff --git a/r5dev/engine/server/sv_main.cpp b/r5dev/engine/server/sv_main.cpp index c402ab0b..144448a9 100644 --- a/r5dev/engine/server/sv_main.cpp +++ b/r5dev/engine/server/sv_main.cpp @@ -162,15 +162,32 @@ bool SV_ActivateServer() return v_SV_ActivateServer(); } -void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data) +//----------------------------------------------------------------------------- +// Purpose: returns whether voice data can be broadcasted from the server +//----------------------------------------------------------------------------- +bool SV_CanBroadcastVoice() { + if (IsPartyDedi()) + return false; + if (IsTrainingDedi()) - return; + return false; if (!sv_voiceenable->GetBool()) - return; + return false; if (g_ServerGlobalVariables->m_nMaxClients <= 0) + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: relays voice data to other clients +//----------------------------------------------------------------------------- +void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data) +{ + if (!SV_CanBroadcastVoice()) return; SVC_VoiceData voiceData(cl->GetUserID(), nBytes, data); @@ -194,8 +211,11 @@ void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data if (pClient->GetTeamNum() != cl->GetTeamNum() && !sv_alltalk->GetBool()) continue; - // there's also supposed to be some xplat checks here - // but since r5r is only on PC, there's no point in implementing them here + //if (voice_noxplat->GetBool() && cl->GetXPlatID() != pClient->GetXPlatID()) + //{ + // if ((cl->GetXPlatID() -1) > 1 || (pClient->GetXPlatID() -1) > 1) + // continue; + //} CNetChan* const pNetChan = pClient->GetNetChan(); @@ -207,3 +227,69 @@ void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data pClient->SendNetMsgEx(&voiceData, false, false, true); } } + +//----------------------------------------------------------------------------- +// Purpose: relays durango voice data to other clients +//----------------------------------------------------------------------------- +void SV_BroadcastDurangoVoiceData(CClient* const cl, const int nBytes, char* const data, + const int nXid, const int unknown, const bool useVoiceStream, const bool skipXidCheck) +{ + if (!SV_CanBroadcastVoice()) + return; + + SVC_DurangoVoiceData voiceData(cl->GetUserID(), nBytes, data, unknown, useVoiceStream); + + for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + { + CClient* const pClient = g_pServer->GetClient(i); + + if (!pClient) + continue; + + // is this client fully connected + if (pClient->GetSignonState() != SIGNONSTATE::SIGNONSTATE_FULL) + continue; + + // is this client the sender + if (pClient == cl && !sv_voiceEcho->GetBool()) + continue; + + if (!skipXidCheck && i != nXid) + continue; + + // is this client on the sender's team + if (pClient->GetTeamNum() != cl->GetTeamNum() && !sv_alltalk->GetBool()) + { + // NOTE: on Durango packets, the game appears to bypass the team + // check if 'useVoiceStream' is false, thus forcing the usage + // of the reliable stream. Omitted the check as it appears that + // could be exploited to transmit voice to other teams while cvar + // 'sv_alltalk' is unset. + continue; + } + + // NOTE: xplat code checks disabled; CClient::GetXPlatID() seems to be + // an enumeration of platforms, but the enum hasn't been reversed yet. + //if (voice_noxplat->GetBool() && cl->GetXPlatID() != pClient->GetXPlatID()) + //{ + // if ((cl->GetXPlatID() - 1) > 1 || (pClient->GetXPlatID() - 1) > 1) + // continue; + //} + + CNetChan* const pNetChan = pClient->GetNetChan(); + + if (!pNetChan) + continue; + + // NOTE: the game appears to have the ability to use the unreliable + // stream as well, but the condition to hit that code path can never + // evaluate to true - appears to be a compile time option that hasn't + // been fully optimized away? For now only switch between voice and + // reliable streams as that is what the original code does. + const bf_write& stream = useVoiceStream ? pNetChan->GetStreamVoice() : pNetChan->GetStreamReliable(); + + // if stream has enough space for new data + if (stream.GetNumBitsLeft() >= 8 * nBytes + 34) + pClient->SendNetMsgEx(&voiceData, false, !useVoiceStream, useVoiceStream); + } +} diff --git a/r5dev/engine/server/sv_main.h b/r5dev/engine/server/sv_main.h index b283c850..8f861709 100644 --- a/r5dev/engine/server/sv_main.h +++ b/r5dev/engine/server/sv_main.h @@ -66,6 +66,7 @@ void SV_InitGameDLL(); void SV_ShutdownGameDLL(); bool SV_ActivateServer(); void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data); +void SV_BroadcastDurangoVoiceData(CClient* const cl, const int nBytes, char* const data, const int nXid, const int unknown, const bool useVoiceStream, const bool skipXidCheck); void SV_CheckForBanAndDisconnect(CClient* const pClient, const string& svIPAddr, const NucleusID_t nNucleusID, const string& svPersonaName, const int nPort); void SV_CheckClientsForBan(const CBanSystem::BannedList_t* const pBannedVec = nullptr); /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/public/tier1/bitbuf.h b/r5dev/public/tier1/bitbuf.h index 8581da14..b8baacb2 100644 --- a/r5dev/public/tier1/bitbuf.h +++ b/r5dev/public/tier1/bitbuf.h @@ -212,6 +212,24 @@ public: int64 ReadSignedVarInt64() { return bitbuf::ZigZagDecode64(ReadVarInt64()); } void ReadBits(void* pOutData, int nBits); + + // Helper 'safe' template function that infers the size of the destination + // array. This version of the function should be preferred. + // Usage: char databuffer[100]; + // ReadBitsClamped( dataBuffer, msg->m_nLength ); + template + FORCEINLINE int ReadBitsClamped(T (&pOut)[N], int nBits) + { + const int outSizeBytes = N * sizeof(T); + const int outSizeBits = outSizeBytes * 8; + + if (nBits > outSizeBits) + nBits = outSizeBits; + + ReadBits(pOut, nBits); + return nBits; + } + bool ReadBytes(void* pOut, int nBytes); From 30c514110f3b1dfe0f7e5ff6e89586acf2591fb8 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 14:36:05 +0200 Subject: [PATCH 093/113] Tier1: fix ctor bug in class bf_read Parameter 'nBytes' was unused while it should've been, causing invalid buffer sizes being set. Bug was found after careful inspection of generation assembly code. --- r5dev/public/tier1/bitbuf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/public/tier1/bitbuf.h b/r5dev/public/tier1/bitbuf.h index b8baacb2..9d1ffa75 100644 --- a/r5dev/public/tier1/bitbuf.h +++ b/r5dev/public/tier1/bitbuf.h @@ -380,7 +380,7 @@ public: : CBitRead(pData, nBytes, nBits) {} bf_read(const char* pDebugName, void* pData, int nBytes, int nMaxBits = -1) - : CBitRead(pDebugName, pData, nMaxBits) {} + : CBitRead(pDebugName, pData, nBytes, nMaxBits) {} bf_read(void) : CBitRead() {} From eaaa32eb6461622b8c40d28c0f6e1e7990a33fd9 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 14:44:12 +0200 Subject: [PATCH 094/113] Engine: fix stack smash in client side UserMessage processor Unclamped CBitRead::ReadBits() call on stack buffer of MAX_USER_MSG_DATA bytes. Function has been rebuilt with additional clamping to mitigate the problem. --- r5dev/engine/client/cdll_engine_int.h | 6 +++++ r5dev/engine/client/clientstate.cpp | 32 +++++++++++++++++++++++++++ r5dev/engine/client/clientstate.h | 4 ++++ 3 files changed, 42 insertions(+) diff --git a/r5dev/engine/client/cdll_engine_int.h b/r5dev/engine/client/cdll_engine_int.h index 7952fb9c..ce2972e0 100644 --- a/r5dev/engine/client/cdll_engine_int.h +++ b/r5dev/engine/client/cdll_engine_int.h @@ -47,6 +47,12 @@ public: const static int index = 28; return CallVFunc(index, this, sequenceNumber); /*48 83 EC 28 48 8B 05 ? ? ? ? 48 8D 0D ? ? ? ? 44 8B C2*/ } + + bool DispatchUserMessage(int msgType, bf_read* msgData) + { + const static int index = 59; + return CallVFunc(index, this, msgType, msgData); + } }; /* ==== CHLCLIENT ======================================================================================================================================================= */ diff --git a/r5dev/engine/client/clientstate.cpp b/r5dev/engine/client/clientstate.cpp index f7c42b5a..2a2a57c0 100644 --- a/r5dev/engine/client/clientstate.cpp +++ b/r5dev/engine/client/clientstate.cpp @@ -9,6 +9,7 @@ // ///////////////////////////////////////////////////////////////////////////////// #include "core/stdafx.h" +#include "mathlib/bitvec.h" #include "tier0/frametask.h" #include "engine/common.h" #include "engine/host.h" @@ -307,6 +308,36 @@ bool CClientState::_ProcessCreateStringTable(CClientState* thisptr, SVC_CreateSt return (endbit - startbit) == msg->m_nLength; } +//------------------------------------------------------------------------------ +// Purpose: processes user message data +// Input : *thisptr - +// *msg - +// Output : true on success, false otherwise +//------------------------------------------------------------------------------ +bool CClientState::_ProcessUserMessage(CClientState* thisptr, SVC_UserMessage* msg) +{ + CClientState* const cl = thisptr->GetShiftedBasePointer(); + + if (!cl->IsConnected()) + return false; + + // buffer for incoming user message + ALIGN4 byte userdata[MAX_USER_MSG_DATA] ALIGN4_POST = { 0 }; + bf_read userMsg("UserMessage(read)", userdata, sizeof(userdata)); + + int bitsRead = msg->m_DataIn.ReadBitsClamped(userdata, msg->m_nLength); + userMsg.StartReading(userdata, Bits2Bytes(bitsRead)); + + // dispatch message to client.dll + if (!g_pHLClient->DispatchUserMessage(msg->m_nMsgType, &userMsg)) + { + Warning(eDLL_T::CLIENT, "Couldn't dispatch user message (%i)\n", msg->m_nMsgType); + return false; + } + + return true; +} + static ConVar cl_onlineAuthEnable("cl_onlineAuthEnable", "1", FCVAR_RELEASE, "Enables the client-side online authentication system"); static ConVar cl_onlineAuthToken("cl_onlineAuthToken", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token"); @@ -402,6 +433,7 @@ void VClientState::Detour(const bool bAttach) const DetourSetup(&CClientState__ProcessStringCmd, &CClientState::_ProcessStringCmd, bAttach); DetourSetup(&CClientState__ProcessServerTick, &CClientState::VProcessServerTick, bAttach); DetourSetup(&CClientState__ProcessCreateStringTable, &CClientState::_ProcessCreateStringTable, bAttach); + DetourSetup(&CClientState__ProcessUserMessage, &CClientState::_ProcessUserMessage, bAttach); DetourSetup(&CClientState__Connect, &CClientState::VConnect, bAttach); } diff --git a/r5dev/engine/client/clientstate.h b/r5dev/engine/client/clientstate.h index 41f879ee..8c663507 100644 --- a/r5dev/engine/client/clientstate.h +++ b/r5dev/engine/client/clientstate.h @@ -40,6 +40,7 @@ public: // Hook statics. static bool _ProcessStringCmd(CClientState* thisptr, NET_StringCmd* msg); static bool VProcessServerTick(CClientState* thisptr, SVC_ServerTick* msg); static bool _ProcessCreateStringTable(CClientState* thisptr, SVC_CreateStringTable* msg); + static bool _ProcessUserMessage(CClientState* thisptr, SVC_UserMessage* msg); static void VConnect(CClientState* thisptr, connectparams_t* connectParams); @@ -228,6 +229,7 @@ inline bool(*CClientState__HookClientStringTable)(CClientState* thisptr, const c inline bool(*CClientState__ProcessStringCmd)(CClientState* thisptr, NET_StringCmd* msg); inline bool(*CClientState__ProcessServerTick)(CClientState* thisptr, SVC_ServerTick* msg); inline bool(*CClientState__ProcessCreateStringTable)(CClientState* thisptr, SVC_CreateStringTable* msg); +inline bool(*CClientState__ProcessUserMessage)(CClientState* thisptr, SVC_UserMessage* msg); /////////////////////////////////////////////////////////////////////////////// class VClientState : public IDetour @@ -242,6 +244,7 @@ class VClientState : public IDetour LogFunAdr("CClientState::ProcessStringCmd", CClientState__ProcessStringCmd); LogFunAdr("CClientState::ProcessServerTick", CClientState__ProcessServerTick); LogFunAdr("CClientState::ProcessCreateStringTable", CClientState__ProcessCreateStringTable); + LogFunAdr("CClientState::ProcessUserMessage", CClientState__ProcessUserMessage); LogVarAdr("g_ClientState", g_pClientState); LogVarAdr("g_ClientState_Shifted", g_pClientState_Shifted); } @@ -255,6 +258,7 @@ class VClientState : public IDetour g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 80 B9 ?? ?? ?? ?? ?? 48 8B DA").GetPtr(CClientState__ProcessStringCmd); g_GameDll.FindPatternSIMD("40 57 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B F9 7C 66").GetPtr(CClientState__ProcessServerTick); g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 53 56 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ??").GetPtr(CClientState__ProcessCreateStringTable); + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ??").GetPtr(CClientState__ProcessUserMessage); } virtual void GetVar(void) const { From 47ffee00437354a5c9d96968ca51ce830913f897 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 14:47:09 +0200 Subject: [PATCH 095/113] Resource: additional dedicated build patches to improve runtime performance Disabled additional unnecessary DX code from patched dedicated server executable, this allows the dedicated server to run RPaks containing models without any material or texture data. This also allows us to fully rebuild all RPaks for dedicated while also omitting material/texture data to further reduce memory usage during the parsing thereof, and overall disk size. --- r5dev/resource/patch/r5apex_ds.patch | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/r5dev/resource/patch/r5apex_ds.patch b/r5dev/resource/patch/r5apex_ds.patch index 43b5a3dc..ce2e5cdb 100644 --- a/r5dev/resource/patch/r5apex_ds.patch +++ b/r5dev/resource/patch/r5apex_ds.patch @@ -27,3 +27,10 @@ // since the dedicated server doesn't use model or texture streaming, and as a // result the files aren't shipped. 0x44BE87: "mov ecx, 0x1" --> "mov ecx, 0x0" + +// Prevent this global bool from being set, as setting this enables CMaterialRenderContext code which shouldn't run on the dedicated server. +0x1E4CE0: "mov cs:byte_165C4D15B, al" --> "mov cs:byte_165C4D15B, 0x0" + +// Prevent VFTable global pointer from being initialized to HardwareConfigDX11, which disables additional DX/Render code. +0x44A460: "lea rax, ds:off_141F03730" --> "nop" +0x44A467: "mov ds:off_141F03730, rax" --> "nop" \ No newline at end of file From 02b5d77d2f9ecf423cd0ab5fabae4029f9222804 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 15:02:36 +0200 Subject: [PATCH 096/113] Engine: fix client dll compile error This code should not compile for client.dll. --- r5dev/engine/client/client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index 61d4260c..e85b9805 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -533,11 +533,13 @@ bool CClient::VProcessSetConVar(CClient* pClient, NET_SetConVar* pMsg) //--------------------------------------------------------------------------------- bool CClient::VProcessVoiceData(CClient* pClient, CLC_VoiceData* pMsg) { +#ifndef CLIENT_DLL char voiceDataBuffer[4096]; const int bitsRead = pMsg->m_DataIn.ReadBitsClamped(voiceDataBuffer, pMsg->m_nLength); CClient* const pAdj = AdjustShiftedThisPointer(pClient); SV_BroadcastVoiceData(pAdj, Bits2Bytes(bitsRead), voiceDataBuffer); +#endif // !CLIENT_DLL return true; } @@ -550,12 +552,14 @@ bool CClient::VProcessVoiceData(CClient* pClient, CLC_VoiceData* pMsg) //--------------------------------------------------------------------------------- bool CClient::VProcessDurangoVoiceData(CClient* pClient, CLC_DurangoVoiceData* pMsg) { +#ifndef CLIENT_DLL char voiceDataBuffer[4096]; const int bitsRead = pMsg->m_DataIn.ReadBitsClamped(voiceDataBuffer, pMsg->m_nLength); CClient* const pAdj = AdjustShiftedThisPointer(pClient); SV_BroadcastDurangoVoiceData(pAdj, Bits2Bytes(bitsRead), voiceDataBuffer, pMsg->m_xid, pMsg->m_unknown, pMsg->m_useVoiceStream, pMsg->m_skipXidCheck); +#endif // !CLIENT_DLL return true; } From 99edd0229d5491cbe5c07d071d41acc8f584f4f0 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 16:00:20 +0200 Subject: [PATCH 097/113] Localize: add language codes Newly added g_LanguageCodes maps directly with g_LanguageNames. --- r5dev/localize/localize.cpp | 8 +------- r5dev/public/localize/ilocalize.h | 34 +++++++++++++++++++++++++++++-- r5dev/vpklib/packedstore.cpp | 2 +- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/r5dev/localize/localize.cpp b/r5dev/localize/localize.cpp index cae020eb..eee84ab1 100644 --- a/r5dev/localize/localize.cpp +++ b/r5dev/localize/localize.cpp @@ -32,13 +32,7 @@ bool Localize_LoadLocalizationFileLists(CLocalize* thisptr) bool Localize_IsLanguageSupported(const char* pLocaleName) { - for (int i = 0; i < SDK_ARRAYSIZE(g_LanguageNames); ++i) - { - if (strcmp(pLocaleName, g_LanguageNames[i]) == NULL) - return true; - } - - return false; + return V_LocaleNameExists(pLocaleName); } void VLocalize::Detour(const bool bAttach) const diff --git a/r5dev/public/localize/ilocalize.h b/r5dev/public/localize/ilocalize.h index a696c69a..89f660fb 100644 --- a/r5dev/public/localize/ilocalize.h +++ b/r5dev/public/localize/ilocalize.h @@ -65,6 +65,7 @@ inline const char* const g_LanguageNames[] = { "italian", "korean", "spanish", + "mspanish", "schinese", "tchinese", "russian", @@ -73,11 +74,40 @@ inline const char* const g_LanguageNames[] = { "polish", }; -inline bool V_LocaleExists(const char* const pLocale) +inline const char* const g_LanguageCodes[] = { + "en_US", + "de_DE", + "fr_FR", + "it_IT", + "ko_KR", + "es_ES", + "es_MX", + "zh_CN", + "zh_TW", + "ru_RU", + "ja_JP", + "pt_BR", + "pl_PL", +}; + +inline bool V_LocaleNameExists(const char* const localeName) { for (size_t i = 0; i < V_ARRAYSIZE(g_LanguageNames); i++) { - if (V_strcmp(pLocale, g_LanguageNames[i]) == NULL) + if (V_strcmp(localeName, g_LanguageNames[i]) == NULL) + { + return true; + } + } + + return false; +} + +inline bool V_LocaleCodeExists(const char* const localeCode) +{ + for (size_t i = 0; i < V_ARRAYSIZE(g_LanguageCodes); i++) + { + if (V_strcmp(localeCode, g_LanguageCodes[i]) == NULL) { return true; } diff --git a/r5dev/vpklib/packedstore.cpp b/r5dev/vpklib/packedstore.cpp index cbe48e3b..0b86d005 100644 --- a/r5dev/vpklib/packedstore.cpp +++ b/r5dev/vpklib/packedstore.cpp @@ -799,7 +799,7 @@ VPKChunkDescriptor_t::VPKChunkDescriptor_t(uint32_t nLoadFlags, uint16_t nTextur //----------------------------------------------------------------------------- VPKPair_t::VPKPair_t(const char* pLocale, const char* pTarget, const char* pLevel, int nPatch) { - const bool bFoundLocale = V_LocaleExists(pLocale); + const bool bFoundLocale = V_LocaleNameExists(pLocale); if (!bFoundLocale) { From 8005993da0c3dae68b6b91ef38dacd688f50aa67 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 16:05:57 +0200 Subject: [PATCH 098/113] Ebisu: allow overriding global game language setting The code originally fetches available and selected languages from Origin/EADesktop. The issue however is that its hard to change the language through the Origin/EADesktop app. The second issue is that the languages returned by Origin/EADesktop isn't necvesarily supported by our version of the game, for example, the original implementation of EbisuSDK_GetLanguage() also returns ar_SA, which is supported by the retail version of the game, but our version doesn't have the code to render this language. The code has been rewritten to allow the user to easily change the language using the command line '-language' parameter. The miles code has also been slightly adjusted to fetch the language directly from HEbisuSDK_GetLanguage() instead of miles_language since otherwise we would still error out in engine code as miles_language will be out of sync. --- r5dev/codecs/Miles/miles_impl.cpp | 8 +++--- r5dev/ebisusdk/EbisuSDK.cpp | 42 +++++++++++++++++++++++++++++++ r5dev/ebisusdk/EbisuSDK.h | 7 +++++- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/r5dev/codecs/Miles/miles_impl.cpp b/r5dev/codecs/Miles/miles_impl.cpp index 147b34cf..01d90704 100644 --- a/r5dev/codecs/Miles/miles_impl.cpp +++ b/r5dev/codecs/Miles/miles_impl.cpp @@ -1,9 +1,10 @@ #include "core/stdafx.h" -#include "miles_impl.h" #include "tier0/fasttimer.h" #include "tier0/commandline.h" #include "tier1/cvar.h" #include "filesystem/filesystem.h" +#include "ebisusdk/EbisuSDK.h" +#include "miles_impl.h" static ConVar miles_debug("miles_debug", "0", FCVAR_DEVELOPMENTONLY, "Enables debug prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); static ConVar miles_warnings("miles_warnings", "0", FCVAR_RELEASE, "Enables warning prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); @@ -25,10 +26,7 @@ void AIL_LogFunc(int64_t nLogLevel, const char* pszMessage) //----------------------------------------------------------------------------- bool Miles_Initialize() { - const char* pszLanguage = miles_language->GetString(); - if (!pszLanguage[0]) - pszLanguage = MILES_DEFAULT_LANGUAGE; - + const char* pszLanguage = HEbisuSDK_GetLanguage(); const bool isDefaultLanguage = _stricmp(pszLanguage, MILES_DEFAULT_LANGUAGE) == 0; if (!isDefaultLanguage) diff --git a/r5dev/ebisusdk/EbisuSDK.cpp b/r5dev/ebisusdk/EbisuSDK.cpp index a87115a5..a082356f 100644 --- a/r5dev/ebisusdk/EbisuSDK.cpp +++ b/r5dev/ebisusdk/EbisuSDK.cpp @@ -1,4 +1,5 @@ #include "core/stdafx.h" +#include "tier0/commandline.h" #include "ebisusdk/EbisuSDK.h" #include "engine/server/sv_main.h" @@ -15,6 +16,42 @@ void HEbisuSDK_Init() } } +//----------------------------------------------------------------------------- +// Purpose: returns the currently set language +//----------------------------------------------------------------------------- +const char* HEbisuSDK_GetLanguage() +{ + static bool initialized = false; + static char languageName[32]; + + if (initialized) + { + return languageName; + } + + const char* value = nullptr; + bool useDefault = true; + + if (CommandLine()->CheckParm("-language", &value)) + { + if (V_LocaleNameExists(value)) + { + strncpy(languageName, value, sizeof(languageName)); + useDefault = false; + } + } + + if (useDefault) + { + strncpy(languageName, g_LanguageNames[0], sizeof(languageName)); + } + + languageName[sizeof(languageName) - 1] = '\0'; + initialized = true; + + return languageName; +} + //----------------------------------------------------------------------------- // Purpose: checks if the EbisuSDK is initialized // Output : true on success, false on failure @@ -57,3 +94,8 @@ bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen) size_t pos = strspn(pszName, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"); return pszName[pos] == '\0'; } + +void VEbisuSDK::Detour(const bool bAttach) const +{ + DetourSetup(&EbisuSDK_GetLanguage, &HEbisuSDK_GetLanguage, bAttach); +} diff --git a/r5dev/ebisusdk/EbisuSDK.h b/r5dev/ebisusdk/EbisuSDK.h index 894f8bac..caf1f16c 100644 --- a/r5dev/ebisusdk/EbisuSDK.h +++ b/r5dev/ebisusdk/EbisuSDK.h @@ -3,6 +3,7 @@ inline void(*EbisuSDK_Tier0_Init)(void); inline void(*EbisuSDK_CVar_Init)(void); inline void(*EbisuSDK_SetState)(void); +inline const char*(*EbisuSDK_GetLanguage)(void); inline uint64_t* g_NucleusID = nullptr; inline char* g_NucleusToken = nullptr; /*SIZE = 1024*/ @@ -13,6 +14,8 @@ inline bool* g_EbisuProfileInit = nullptr; /////////////////////////////////////////////////////////////////////////////// void HEbisuSDK_Init(); +const char* HEbisuSDK_GetLanguage(); + bool IsOriginInitialized(); bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen); @@ -24,6 +27,7 @@ class VEbisuSDK : public IDetour LogFunAdr("EbisuSDK_Tier0_Init", EbisuSDK_Tier0_Init); LogFunAdr("EbisuSDK_CVar_Init", EbisuSDK_CVar_Init); LogFunAdr("EbisuSDK_SetState", EbisuSDK_SetState); + LogFunAdr("EbisuSDK_SetState", EbisuSDK_GetLanguage); LogVarAdr("g_NucleusID", g_NucleusID); LogVarAdr("g_NucleusToken", g_NucleusToken); LogVarAdr("g_OriginAuthCode", g_OriginAuthCode); @@ -36,6 +40,7 @@ class VEbisuSDK : public IDetour g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 85 ?? 02 ?? ?? 48 89 5C 24 20").GetPtr(EbisuSDK_Tier0_Init); g_GameDll.FindPatternSIMD("40 57 48 83 EC 40 83 3D").GetPtr(EbisuSDK_CVar_Init); g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B").GetPtr(EbisuSDK_SetState); + g_GameDll.FindPatternSIMD("48 8B C4 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ??").GetPtr(EbisuSDK_GetLanguage); } virtual void GetVar(void) const { @@ -47,6 +52,6 @@ class VEbisuSDK : public IDetour g_EbisuSDKInit = CMemory(EbisuSDK_Tier0_Init).Offset(0x0).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); } virtual void GetCon(void) const { } - virtual void Detour(const bool bAttach) const { } + virtual void Detour(const bool bAttach) const; }; /////////////////////////////////////////////////////////////////////////////// From 12aa0f8ded92691311d45e77800308daf522bf79 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 15 May 2024 19:03:24 +0200 Subject: [PATCH 099/113] Game: add game dll flags to "script(_*)" command The flags were originally removed in commit 1bdc3b893e59f208dbeadd78b978096dcdd8e8f9, but this caused a regression in the dev menu. Restored flags (this also doesn't cause security issues as these commands are flagged devonly and cheats anyways). --- r5dev/game/client/vscript_client.cpp | 4 ++-- r5dev/game/server/vscript_server.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index 85a99ea6..81e451b8 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -54,8 +54,8 @@ static void SQVM_UIScript_f(const CCommand& args) } } -static ConCommand script_client("script_client", SQVM_ClientScript_f, "Run input code as CLIENT script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); -static ConCommand script_ui("script_ui", SQVM_UIScript_f, "Run input code as UI script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); +static ConCommand script_client("script_client", SQVM_ClientScript_f, "Run input code as CLIENT script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT); +static ConCommand script_ui("script_ui", SQVM_UIScript_f, "Run input code as UI script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT); //----------------------------------------------------------------------------- // Purpose: checks if the server index is valid, raises an error if not diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index b700c6b0..0ca711d9 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -34,7 +34,7 @@ static void SQVM_ServerScript_f(const CCommand& args) Script_Execute(args.ArgS(), SQCONTEXT::SERVER); } } -static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT | FCVAR_SERVER_FRAME_THREAD); +static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT | FCVAR_SERVER_FRAME_THREAD); namespace VScriptCode { From 661874025f53e42982606076311e71a794bf30c8 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 17 May 2024 11:12:57 +0200 Subject: [PATCH 100/113] Engine: add functionality to run game without the platform system Unbind the game from the platform system, which is useful when developing for or debugging the game. This was supposed to make it into the SDK back in 2021, but wasn't due to the ability to spoof usernames. This is no longer possible on servers requiring authentication as the player's name is actually checked along with the Nucleus ID. --- r5dev/common/global.cpp | 8 +++++ r5dev/common/global.h | 6 ++++ r5dev/ebisusdk/EbisuSDK.cpp | 50 ++++++++++++++++++++++++++--- r5dev/ebisusdk/EbisuSDK.h | 22 +++++++++---- r5dev/engine/client/clientstate.cpp | 30 +++++++++++++++++ 5 files changed, 104 insertions(+), 12 deletions(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index d12ae85e..fe73e35e 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -65,6 +65,12 @@ ConVar* language_cvar = nullptr; ConVar* voice_noxplat = nullptr; +ConVar* platform_user_id = nullptr; + +#ifndef DEDICATED +ConVar* name_cvar = nullptr; +#endif // !DEDICATED + //----------------------------------------------------------------------------- // SERVER | #ifndef CLIENT_DLL @@ -156,7 +162,9 @@ void ConVar_InitShipped(void) language_cvar = g_pCVar->FindVar("language"); voice_noxplat = g_pCVar->FindVar("voice_noxplat"); + platform_user_id = g_pCVar->FindVar("platform_user_id"); #ifndef DEDICATED + name_cvar = g_pCVar->FindVar("name"); cl_updaterate_mp = g_pCVar->FindVar("cl_updaterate_mp"); cl_threaded_bone_setup = g_pCVar->FindVar("cl_threaded_bone_setup"); #endif // !DEDICATED diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 139ad327..5df2c062 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -52,6 +52,12 @@ extern ConVar* language_cvar; extern ConVar* voice_noxplat; +extern ConVar* platform_user_id; + +#ifndef DEDICATED +extern ConVar* name_cvar; +#endif // !DEDICATED + //------------------------------------------------------------------------- // SERVER | #ifndef CLIENT_DLL diff --git a/r5dev/ebisusdk/EbisuSDK.cpp b/r5dev/ebisusdk/EbisuSDK.cpp index a082356f..1487a250 100644 --- a/r5dev/ebisusdk/EbisuSDK.cpp +++ b/r5dev/ebisusdk/EbisuSDK.cpp @@ -4,18 +4,47 @@ #include "engine/server/sv_main.h" //----------------------------------------------------------------------------- -// Purpose: sets the EbisuSDK globals for dedicated to satisfy command callbacks +// Purpose: initialize the EbisuSDK //----------------------------------------------------------------------------- void HEbisuSDK_Init() { - if (IsDedicated()) + const bool isDedicated = IsDedicated(); + const bool noOrigin = IsOriginDisabled(); + + // Fill with default data if this is a dedicated server, or if the game was + // launched with the platform system disabled. Engine code requires these + // to be set for the game to function, else stuff like the "map" command + // won't run as 'IsOriginInitialized()' returns false (which got inlined in + // every place this was called in the game's executable). + if (isDedicated || noOrigin) { - *g_EbisuSDKInit = true; // <- 1st EbisuSDK - *g_EbisuProfileInit = true; // <- 2nd EbisuSDK - *g_NucleusID = 9990000; // <- 3rd EbisuSDK + *g_EbisuSDKInit = true; + *g_EbisuProfileInit = true; + *g_NucleusID = FAKE_BASE_NUCLEUD_ID; + + Q_snprintf(g_OriginAuthCode, 256, "%s", "INVALID_OAUTH_CODE"); + Q_snprintf(g_NucleusToken, 1024, "%s", "INVALID_NUCLEUS_TOKEN"); + + if (!isDedicated) + { + platform_user_id->SetValue(FAKE_BASE_NUCLEUD_ID); + } } } +//----------------------------------------------------------------------------- +// Purpose: runs the EbisuSDK state machine +//----------------------------------------------------------------------------- +void HEbisuSDK_RunFrame() +{ + if (IsOriginDisabled()) + { + return; + } + + EbisuSDK_RunFrame(); +} + //----------------------------------------------------------------------------- // Purpose: returns the currently set language //----------------------------------------------------------------------------- @@ -52,6 +81,16 @@ const char* HEbisuSDK_GetLanguage() return languageName; } +//----------------------------------------------------------------------------- +// Purpose: checks if the EbisuSDK is disabled +// Output : true on success, false on failure +//----------------------------------------------------------------------------- +bool IsOriginDisabled() +{ + const static bool isDisabled = CommandLine()->CheckParm("-noorigin"); + return isDisabled; +} + //----------------------------------------------------------------------------- // Purpose: checks if the EbisuSDK is initialized // Output : true on success, false on failure @@ -97,5 +136,6 @@ bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen) void VEbisuSDK::Detour(const bool bAttach) const { + DetourSetup(&EbisuSDK_RunFrame, &HEbisuSDK_RunFrame, bAttach); DetourSetup(&EbisuSDK_GetLanguage, &HEbisuSDK_GetLanguage, bAttach); } diff --git a/r5dev/ebisusdk/EbisuSDK.h b/r5dev/ebisusdk/EbisuSDK.h index caf1f16c..79dbaaa7 100644 --- a/r5dev/ebisusdk/EbisuSDK.h +++ b/r5dev/ebisusdk/EbisuSDK.h @@ -1,13 +1,17 @@ #pragma once +#define MAX_PERSONA_NAME_LEN 64 // sizeof( g_PersonaName ) +#define FAKE_BASE_NUCLEUD_ID 9990000 + inline void(*EbisuSDK_Tier0_Init)(void); inline void(*EbisuSDK_CVar_Init)(void); -inline void(*EbisuSDK_SetState)(void); +inline void(*EbisuSDK_RunFrame)(void); inline const char*(*EbisuSDK_GetLanguage)(void); inline uint64_t* g_NucleusID = nullptr; inline char* g_NucleusToken = nullptr; /*SIZE = 1024*/ inline char* g_OriginAuthCode = nullptr; /*SIZE = 256*/ +inline char* g_PersonaName = nullptr; /*SIZE = 64*/ inline int* g_OriginErrorLevel = nullptr; inline bool* g_EbisuSDKInit = nullptr; inline bool* g_EbisuProfileInit = nullptr; @@ -16,7 +20,9 @@ inline bool* g_EbisuProfileInit = nullptr; void HEbisuSDK_Init(); const char* HEbisuSDK_GetLanguage(); +bool IsOriginDisabled(); bool IsOriginInitialized(); + bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen); /////////////////////////////////////////////////////////////////////////////// @@ -26,11 +32,12 @@ class VEbisuSDK : public IDetour { LogFunAdr("EbisuSDK_Tier0_Init", EbisuSDK_Tier0_Init); LogFunAdr("EbisuSDK_CVar_Init", EbisuSDK_CVar_Init); - LogFunAdr("EbisuSDK_SetState", EbisuSDK_SetState); - LogFunAdr("EbisuSDK_SetState", EbisuSDK_GetLanguage); + LogFunAdr("EbisuSDK_RunFrame", EbisuSDK_RunFrame); + LogFunAdr("EbisuSDK_GetLanguage", EbisuSDK_GetLanguage); LogVarAdr("g_NucleusID", g_NucleusID); LogVarAdr("g_NucleusToken", g_NucleusToken); LogVarAdr("g_OriginAuthCode", g_OriginAuthCode); + LogVarAdr("g_PersonaName", g_PersonaName); LogVarAdr("g_OriginErrorLevel", g_OriginErrorLevel); LogVarAdr("g_EbisuProfileInit", g_EbisuProfileInit); LogVarAdr("g_EbisuSDKInit", g_EbisuSDKInit); @@ -39,15 +46,16 @@ class VEbisuSDK : public IDetour { g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 85 ?? 02 ?? ?? 48 89 5C 24 20").GetPtr(EbisuSDK_Tier0_Init); g_GameDll.FindPatternSIMD("40 57 48 83 EC 40 83 3D").GetPtr(EbisuSDK_CVar_Init); - g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B").GetPtr(EbisuSDK_SetState); + g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B").GetPtr(EbisuSDK_RunFrame); g_GameDll.FindPatternSIMD("48 8B C4 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ??").GetPtr(EbisuSDK_GetLanguage); } virtual void GetVar(void) const { g_NucleusID = CMemory(EbisuSDK_CVar_Init).Offset(0x20).FindPatternSelf("4C 89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - g_NucleusToken = CMemory(EbisuSDK_SetState).Offset(0x1EF).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); - g_OriginAuthCode = CMemory(EbisuSDK_SetState).Offset(0x1BF).FindPatternSelf("0F B6", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - g_OriginErrorLevel = CMemory(EbisuSDK_SetState).Offset(0x20).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast(); + g_NucleusToken = CMemory(EbisuSDK_RunFrame).Offset(0x1EF).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); + g_OriginAuthCode = CMemory(EbisuSDK_RunFrame).Offset(0x1BF).FindPatternSelf("0F B6", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_PersonaName = CMemory(EbisuSDK_CVar_Init).Offset(0x120).FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_OriginErrorLevel = CMemory(EbisuSDK_RunFrame).Offset(0x20).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast(); g_EbisuProfileInit = CMemory(EbisuSDK_CVar_Init).Offset(0x12A).FindPatternSelf("C6 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); g_EbisuSDKInit = CMemory(EbisuSDK_Tier0_Init).Offset(0x0).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); } diff --git a/r5dev/engine/client/clientstate.cpp b/r5dev/engine/client/clientstate.cpp index 2a2a57c0..f8064e02 100644 --- a/r5dev/engine/client/clientstate.cpp +++ b/r5dev/engine/client/clientstate.cpp @@ -25,6 +25,36 @@ #include #include +//------------------------------------------------------------------------------ +// Purpose: console command callbacks +//------------------------------------------------------------------------------ +static void SetName_f(const CCommand& args) +{ + if (args.ArgC() < 2) + return; + + if (!IsOriginDisabled()) + return; + + const char* pszName = args.Arg(1); + + if (!pszName[0]) + pszName = "unnamed"; + + const size_t nLen = strlen(pszName); + + if (nLen > MAX_PERSONA_NAME_LEN) + return; + + // Update nucleus name. + memset(g_PersonaName, '\0', MAX_PERSONA_NAME_LEN); + strncpy(g_PersonaName, pszName, nLen); +} + +//------------------------------------------------------------------------------ +// Purpose: console commands +//------------------------------------------------------------------------------ +static ConCommand cl_setname("cl_setname", SetName_f, "Sets the client's persona name", FCVAR_RELEASE); //------------------------------------------------------------------------------ // Purpose: returns true if client simulation is paused From 06e995f17bbdee7ad43d7bcce06a5b572934d7d3 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 23 May 2024 19:53:54 +0200 Subject: [PATCH 101/113] Server: fix incorrect calculation of player timebase on bot instances - Member CPlayer::m_lastUCmdSimulationRemainderTime is set and checked as an int in compiled code, change type from float to int. - Simulation time was calculated incorrectly; brough expression 'CPlayer::m_lastUCmdSimulationRemainderTime * TICK_INTERVAL' into parentheses. - Call to CPlayer::SetTotalExtraClientCmdTimeAttempted() took incorrect parameter value if flSimulationTime < 0.0f, it was supposed to be clamped to 0.0f, but instead, took the value of 'TIME_TO_TICKS( flTimeBase )'. --- r5dev/game/server/player.cpp | 31 ++++++++++++------------------- r5dev/game/server/player.h | 6 ++---- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/r5dev/game/server/player.cpp b/r5dev/game/server/player.cpp index 9032bb4c..6ebf10f6 100644 --- a/r5dev/game/server/player.cpp +++ b/r5dev/game/server/player.cpp @@ -60,37 +60,29 @@ QAngle* CPlayer::EyeAngles(QAngle* pAngles) //------------------------------------------------------------------------------ inline void CPlayer::SetTimeBase(float flTimeBase) { - float flTime = float(TIME_TO_TICKS(flTimeBase)); + const int nRemainderTime = Max(TIME_TO_TICKS(flTimeBase), 0); + SetLastUCmdSimulationRemainderTime(nRemainderTime); - if (flTime < 0.0f) - flTime = 0.0f; - - SetLastUCmdSimulationRemainderTime(flTime); - - float flSimulationTime = flTimeBase - m_lastUCmdSimulationRemainderTime * TICK_INTERVAL; - if (flSimulationTime >= 0.0f) - { - flTime = flSimulationTime; - } - - SetTotalExtraClientCmdTimeAttempted(flTime); + const float flAttemptedTime = Max(flTimeBase - (m_lastUCmdSimulationRemainderTime * TICK_INTERVAL), 0.0f); + SetTotalExtraClientCmdTimeAttempted(flAttemptedTime); } //------------------------------------------------------------------------------ // Purpose: sets the last user cmd simulation remainder time -// Input : flRemainderTime - +// Input : nRemainderTime - //------------------------------------------------------------------------------ -void CPlayer::SetLastUCmdSimulationRemainderTime(float flRemainderTime) +void CPlayer::SetLastUCmdSimulationRemainderTime(int nRemainderTime) { - if (m_lastUCmdSimulationRemainderTime != flRemainderTime) + if (m_lastUCmdSimulationRemainderTime != nRemainderTime) { - edict_t nEdict = NetworkProp()->GetEdict(); + const edict_t nEdict = NetworkProp()->GetEdict(); + if (nEdict != FL_EDICT_INVALID) { _InterlockedOr16((SHORT*)(*g_pGlobals)->m_pEdicts + nEdict + 32, 0x200u); } - m_lastUCmdSimulationRemainderTime = flRemainderTime; + m_lastUCmdSimulationRemainderTime = nRemainderTime; } } @@ -102,7 +94,8 @@ void CPlayer::SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime) { if (m_totalExtraClientCmdTimeAttempted != flAttemptedTime) { - edict_t nEdict = NetworkProp()->GetEdict(); + const edict_t nEdict = NetworkProp()->GetEdict(); + if (nEdict != FL_EDICT_INVALID) { _InterlockedOr16((SHORT*)(*g_pGlobals)->m_pEdicts + nEdict + 32, 0x200u); diff --git a/r5dev/game/server/player.h b/r5dev/game/server/player.h index f201f274..a71752ea 100644 --- a/r5dev/game/server/player.h +++ b/r5dev/game/server/player.h @@ -247,14 +247,12 @@ public: QAngle* EyeAngles(QAngle* pAngles); void SetTimeBase(float flTimeBase); - void SetLastUCmdSimulationRemainderTime(float flRemainderTime); + void SetLastUCmdSimulationRemainderTime(int nRemainderTime); void SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime); void ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, int droppedPackets, bool paused); - void ClampUnlag(CUserCmd* cmd); - void PlayerRunCommand(CUserCmd* pUserCmd, IMoveHelper* pMover); void SetLastUserCommand(CUserCmd* pUserCmd); @@ -576,7 +574,7 @@ private: float m_totalFrameTime; float m_joinFrameTime; int m_lastUCmdSimulationTicks; - float m_lastUCmdSimulationRemainderTime; + int m_lastUCmdSimulationRemainderTime; // Originally float??? float m_totalExtraClientCmdTimeAttempted; int m_hPlayerViewEntity; bool m_atLeastOneCommandRunThisServerFrame; From d1c80ad6fdd20edf8ff4653515f2fe7d2e60da9e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 26 May 2024 13:13:33 +0200 Subject: [PATCH 102/113] Engine: make debug statement a warning --- r5dev/engine/server/sv_rcon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index b9fb9e71..a283f83a 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -547,7 +547,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) { if (rcon_debug.GetBool()) { - Msg(eDLL_T::SERVER, "Banned list is full, dropping '%s'\n", szNetAdr); + Warning(eDLL_T::SERVER, "Banned list is full, dropping '%s'\n", szNetAdr); } return true; From 3f36deb8705505d0f3858f2fc9884e7f34a4ecf4 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 26 May 2024 13:31:46 +0200 Subject: [PATCH 103/113] Merge pull request #120 from Mauler125/bot_timebase_fix Bot player timebase fix From 6db088749f9b94fc61acb22e040f833a9995d6ba Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 26 May 2024 22:21:02 +0200 Subject: [PATCH 104/113] RTech: improve concommand strings Improve readability. --- r5dev/rtech/pak/pakstate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/rtech/pak/pakstate.cpp b/r5dev/rtech/pak/pakstate.cpp index a79653c3..16d7aa23 100644 --- a/r5dev/rtech/pak/pakstate.cpp +++ b/r5dev/rtech/pak/pakstate.cpp @@ -246,7 +246,7 @@ static void Pak_Compress_f(const CCommand& args) } } -static ConCommand pak_strtoguid("pak_strtoguid", Pak_StringToGUID_f, "Calculates the GUID from input data", FCVAR_DEVELOPMENTONLY); +static ConCommand pak_stringtoguid("pak_stringtoguid", Pak_StringToGUID_f, "Calculates the GUID from input text", FCVAR_DEVELOPMENTONLY); static ConCommand pak_compress("pak_compress", Pak_Compress_f, "Compresses specified RPAK file", FCVAR_DEVELOPMENTONLY, RTech_PakCompress_f_CompletionFunc); static ConCommand pak_decompress("pak_decompress", Pak_Decompress_f, "Decompresses specified RPAK file", FCVAR_DEVELOPMENTONLY, RTech_PakDecompress_f_CompletionFunc); From adb3b66fa4e6986259b540e9abf036230d1022f7 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 26 May 2024 22:22:46 +0200 Subject: [PATCH 105/113] ImGui: use cached value for clamped window width Remove extraneous indirection. --- r5dev/gameui/IConsole.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/gameui/IConsole.cpp b/r5dev/gameui/IConsole.cpp index 1da1103f..b6c0f27b 100644 --- a/r5dev/gameui/IConsole.cpp +++ b/r5dev/gameui/IConsole.cpp @@ -768,7 +768,7 @@ void CConsole::DetermineAutoCompleteWindowRect(void) const float maxWindowWidth = con_autocomplete_window_width.GetFloat(); const float flWindowWidth = maxWindowWidth > 0 - ? ImMin(con_autocomplete_window_width.GetFloat(), lastItemRectSize.x) + ? ImMin(maxWindowWidth, lastItemRectSize.x) : lastItemRectSize.x; // NOTE: minimum vertical size of the window, going below this will From 6b0f3a2fdd0c43f70ea7ca24516c565656f17ff7 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 27 May 2024 14:26:39 +0200 Subject: [PATCH 106/113] RTech: enforce naming consistency in define names renamed PLATFORM_PAK_PATH and PLATFORM_PAK_OVERRIDE_PATH. --- r5dev/public/rtech/ipakfile.h | 6 +++--- r5dev/rtech/async/asyncio.cpp | 2 +- r5dev/rtech/pak/pakparse.cpp | 2 +- r5dev/rtech/pak/pakstate.cpp | 8 ++++---- r5dev/rtech/pak/paktools.cpp | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/r5dev/public/rtech/ipakfile.h b/r5dev/public/rtech/ipakfile.h index 70a3d564..aedbbb72 100644 --- a/r5dev/public/rtech/ipakfile.h +++ b/r5dev/public/rtech/ipakfile.h @@ -80,11 +80,11 @@ // base pak directory containing paks sorted in platform specific subdirectories #define PAK_BASE_PATH "paks\\" -#define PLATFORM_PAK_PATH PAK_BASE_PATH"Win64\\" +#define PAK_PLATFORM_PATH PAK_BASE_PATH"Win64\\" // pak override directory; the system will looks for pak files in this directory -// first before falling back to PLATFORM_PAK_PATH -#define PLATFORM_PAK_OVERRIDE_PATH PAK_BASE_PATH"Win64_override\\" +// first before falling back to PAK_PLATFORM_PATH +#define PAK_PLATFORM_OVERRIDE_PATH PAK_BASE_PATH"Win64_override\\" // the handle that should be returned when a pak failed to load or process #define PAK_INVALID_HANDLE -1 diff --git a/r5dev/rtech/async/asyncio.cpp b/r5dev/rtech/async/asyncio.cpp index 0c945233..05cc7cb8 100644 --- a/r5dev/rtech/async/asyncio.cpp +++ b/r5dev/rtech/async/asyncio.cpp @@ -23,7 +23,7 @@ int FS_OpenAsyncFile(const char* const filePath, const int logLevel, size_t* con if (fileToLoad && *fileToLoad) { // is this a pak file and do we have an override - if (strstr(fileToLoad, PLATFORM_PAK_PATH) && + if (strstr(fileToLoad, PAK_PLATFORM_PATH) && Pak_FileOverrideExists(fileToLoad, overridePath, sizeof(overridePath))) { fileToLoad = overridePath; diff --git a/r5dev/rtech/pak/pakparse.cpp b/r5dev/rtech/pak/pakparse.cpp index 9b45d991..bc81c767 100644 --- a/r5dev/rtech/pak/pakparse.cpp +++ b/r5dev/rtech/pak/pakparse.cpp @@ -461,7 +461,7 @@ bool Pak_ProcessPakFile(PakFile_s* const pak) return memoryData->patchSrcSize == 0; char pakPatchPath[MAX_PATH] = {}; - sprintf(pakPatchPath, PLATFORM_PAK_PATH"%s", pak->memoryData.fileName); + sprintf(pakPatchPath, PAK_PLATFORM_PATH"%s", pak->memoryData.fileName); // get path of next patch rpak to load if (pak->memoryData.patchIndices[pak->patchCount]) diff --git a/r5dev/rtech/pak/pakstate.cpp b/r5dev/rtech/pak/pakstate.cpp index 16d7aa23..0a51cd5b 100644 --- a/r5dev/rtech/pak/pakstate.cpp +++ b/r5dev/rtech/pak/pakstate.cpp @@ -208,8 +208,8 @@ static void Pak_Decompress_f(const CCommand& args) return; } - CFmtStr1024 inPakFile(PLATFORM_PAK_PATH "%s", args.Arg(1)); - CFmtStr1024 outPakFile(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1)); + CFmtStr1024 inPakFile(PAK_PLATFORM_PATH "%s", args.Arg(1)); + CFmtStr1024 outPakFile(PAK_PLATFORM_OVERRIDE_PATH "%s", args.Arg(1)); if (!Pak_DecodePakFile(inPakFile.String(), outPakFile.String())) { @@ -233,8 +233,8 @@ static void Pak_Compress_f(const CCommand& args) return; } - CFmtStr1024 inPakFile(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1)); - CFmtStr1024 outPakFile(PLATFORM_PAK_PATH "%s", args.Arg(1)); + CFmtStr1024 inPakFile(PAK_PLATFORM_OVERRIDE_PATH "%s", args.Arg(1)); + CFmtStr1024 outPakFile(PAK_PLATFORM_PATH "%s", args.Arg(1)); // NULL means default compress level const int compressLevel = args.ArgC() > 2 ? atoi(args.Arg(2)) : NULL; diff --git a/r5dev/rtech/pak/paktools.cpp b/r5dev/rtech/pak/paktools.cpp index 7ed1e409..5283597d 100644 --- a/r5dev/rtech/pak/paktools.cpp +++ b/r5dev/rtech/pak/paktools.cpp @@ -14,7 +14,7 @@ //---------------------------------------------------------------------------------- bool Pak_BasePathExists() { - return IsDirectory(PLATFORM_PAK_PATH); + return IsDirectory(PAK_PLATFORM_PATH); } //---------------------------------------------------------------------------------- @@ -26,7 +26,7 @@ bool Pak_CreateBasePath() if (Pak_BasePathExists()) return true; - return CreateDirHierarchy(PLATFORM_PAK_PATH) == 0; + return CreateDirHierarchy(PAK_PLATFORM_PATH) == 0; } //---------------------------------------------------------------------------------- @@ -34,7 +34,7 @@ bool Pak_CreateBasePath() //---------------------------------------------------------------------------------- bool Pak_OverridePathExists() { - return IsDirectory(PLATFORM_PAK_OVERRIDE_PATH); + return IsDirectory(PAK_PLATFORM_OVERRIDE_PATH); } //---------------------------------------------------------------------------------- @@ -46,7 +46,7 @@ bool Pak_CreateOverridePath() if (Pak_OverridePathExists()) return true; - return CreateDirHierarchy(PLATFORM_PAK_OVERRIDE_PATH) == 0; + return CreateDirHierarchy(PAK_PLATFORM_OVERRIDE_PATH) == 0; } //---------------------------------------------------------------------------------- @@ -55,7 +55,7 @@ bool Pak_CreateOverridePath() bool Pak_FileOverrideExists(const char* const pakFilePath, char* const outPath, const size_t outBufLen) { // check the overrides path - snprintf(outPath, outBufLen, PLATFORM_PAK_OVERRIDE_PATH"%s", V_UnqualifiedFileName(pakFilePath)); + snprintf(outPath, outBufLen, PAK_PLATFORM_OVERRIDE_PATH"%s", V_UnqualifiedFileName(pakFilePath)); return FileExists(outPath); } @@ -69,7 +69,7 @@ int Pak_FileExists(const char* const pakFilePath) return true; // check the platform's default path - snprintf(fullPath, sizeof(fullPath), PLATFORM_PAK_PATH"%s", pakFilePath); + snprintf(fullPath, sizeof(fullPath), PAK_PLATFORM_PATH"%s", pakFilePath); return FileExists(fullPath); } From ecf6cbcef0e53b2b367f2cf4258d80811d071d2d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 29 May 2024 17:56:55 +0200 Subject: [PATCH 107/113] Miles: upgrade sound engine to v10.0.47.7 Internal structure 'IntProjectData_t' has changed, padding size adjusted to accommodate changes. Sound engine taken from retail build R5pc_r5-61_J318_CL651503_2020_10_14_18_51. --- r5dev/codecs/Miles/miles_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/codecs/Miles/miles_types.h b/r5dev/codecs/Miles/miles_types.h index 3ac735e1..ade5ee64 100644 --- a/r5dev/codecs/Miles/miles_types.h +++ b/r5dev/codecs/Miles/miles_types.h @@ -31,7 +31,7 @@ namespace Miles // internal project data structure struct IntProjectData_t { - char gap0[0xCF0]; + char gap0[0xE28]; int bankCount; BankHeader_t** loadedBanks; }; From a839433e46f85e700489b691c9105f65845a1c70 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 31 May 2024 13:43:47 +0200 Subject: [PATCH 108/113] Engine: fix CLC voice data netmessage structures The field 'void* unk0' is actually 'CNetMessage::m_pMessageHandler'. Since this type was taken from the IDB (in which this field is actually part of the netmessage implementation itself, since SVC messages use a different vtable and its the only way to have it show correctly in the output), an extra 8 bytes shift occurred rendering the system defective. Removed the field and the structure now matches that of the game executable. --- r5dev/common/netmessages.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/r5dev/common/netmessages.h b/r5dev/common/netmessages.h index c60c3992..9bfa31d0 100644 --- a/r5dev/common/netmessages.h +++ b/r5dev/common/netmessages.h @@ -452,7 +452,6 @@ private: class CLC_VoiceData : public CNetMessage { public: - void* unk0; int m_nLength; bf_read m_DataIn; bf_write m_DataOut; @@ -463,7 +462,6 @@ public: class CLC_DurangoVoiceData : public CNetMessage { public: - void* unk0; int m_nLength; bf_read m_DataIn; bf_write m_DataOut; From 45508847e3d755ac3cb1c8efbf08e2915335a061 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 31 May 2024 13:44:27 +0200 Subject: [PATCH 109/113] Engine: check for bitbuf overflow after reading voice data --- r5dev/engine/client/client.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index e85b9805..4c380ce6 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -537,6 +537,9 @@ bool CClient::VProcessVoiceData(CClient* pClient, CLC_VoiceData* pMsg) char voiceDataBuffer[4096]; const int bitsRead = pMsg->m_DataIn.ReadBitsClamped(voiceDataBuffer, pMsg->m_nLength); + if (pMsg->m_DataIn.IsOverflowed()) + return false; + CClient* const pAdj = AdjustShiftedThisPointer(pClient); SV_BroadcastVoiceData(pAdj, Bits2Bytes(bitsRead), voiceDataBuffer); #endif // !CLIENT_DLL @@ -556,6 +559,9 @@ bool CClient::VProcessDurangoVoiceData(CClient* pClient, CLC_DurangoVoiceData* p char voiceDataBuffer[4096]; const int bitsRead = pMsg->m_DataIn.ReadBitsClamped(voiceDataBuffer, pMsg->m_nLength); + if (pMsg->m_DataIn.IsOverflowed()) + return false; + CClient* const pAdj = AdjustShiftedThisPointer(pClient); SV_BroadcastDurangoVoiceData(pAdj, Bits2Bytes(bitsRead), voiceDataBuffer, pMsg->m_xid, pMsg->m_unknown, pMsg->m_useVoiceStream, pMsg->m_skipXidCheck); From d796ed495d5e61b2846b9151a782d2c5f64b17e7 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 31 May 2024 14:01:11 +0200 Subject: [PATCH 110/113] VScript: fix compiler error on VS2017 Compiler error only happens on VS2017's compiler "*\ found outside comment". Fixed error while also making the comment more clear. --- r5dev/vscript/languages/squirrel_re/include/squirrel.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/r5dev/vscript/languages/squirrel_re/include/squirrel.h b/r5dev/vscript/languages/squirrel_re/include/squirrel.h index 5eee0377..74a268cb 100644 --- a/r5dev/vscript/languages/squirrel_re/include/squirrel.h +++ b/r5dev/vscript/languages/squirrel_re/include/squirrel.h @@ -237,8 +237,11 @@ inline SQRESULT (*v_sq_endconsttable)(HSQUIRRELVM v); inline SQString* (*v_StringTable__Add)(void* a1, const SQChar* str, SQInteger len); -inline void* /*RefTable::RefNode*/ (*v_RefTable__Get)(void* /*RefTable*/ thisp, SQObject* obj, SQHash* mainpos, void*/*RefTable::RefNode**/ prev, bool add); -inline SQBool(*v_RefTable__Release)(void* /*RefTable*/ thisp, SQObject* obj); +// returns: RefTable::RefNode* +// thisp = RefTable* +// prev = RefTable::RefNode* +inline void* (*v_RefTable__Get)(void* thisp, SQObject* obj, SQHash* mainpos, void* prev, bool add); +inline SQBool(*v_RefTable__Release)(void* thisp, SQObject* obj); /////////////////////////////////////////////////////////////////////////////// class VSquirrelAPI : public IDetour From e461dfc2d6077bb5396c124add785a18a8d209b0 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 31 May 2024 14:03:04 +0200 Subject: [PATCH 111/113] Engine: mark cvar 'fps_max' as FCVAR_ARCHIVE The new scripts now show a dedicated FPS limit option in the video settings, there is also a demand for having this cvar to persist its value. Marked as FCVAR_ARCHIVE so it gets saved to user profile settings. --- r5dev/common/global.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index fe73e35e..0323a17d 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -258,6 +258,7 @@ void ConVar_InitShipped(void) origin_disconnectWhenOffline->RemoveFlags(FCVAR_DEVELOPMENTONLY); discord_updatePresence->RemoveFlags(FCVAR_DEVELOPMENTONLY); #endif // !DEDICATED + fps_max->AddFlags(FCVAR_ARCHIVE); fps_max_vsync->RemoveFlags(FCVAR_DEVELOPMENTONLY); base_tickinterval_sp->RemoveFlags(FCVAR_DEVELOPMENTONLY); From 6f2d271ce1a47294c0bce4a8da172f5c3423da36 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 31 May 2024 14:55:47 +0200 Subject: [PATCH 112/113] Tier1: only set overflow flag if it hasn't been set already Only set overflow flag in 'CBitRead::GrabNextDWord()' if it hasn't been set already, code now matches the assembly of the game executable. --- r5dev/public/tier1/bitbuf.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/r5dev/public/tier1/bitbuf.h b/r5dev/public/tier1/bitbuf.h index 9d1ffa75..02ce2868 100644 --- a/r5dev/public/tier1/bitbuf.h +++ b/r5dev/public/tier1/bitbuf.h @@ -441,7 +441,9 @@ FORCEINLINE void CBitRead::GrabNextDWord(bool bOverFlowImmediately) { if (m_pDataIn > m_pBufferEnd) { - SetOverflowFlag(); + if (!IsOverflowed()) + SetOverflowFlag(); + m_nInBufWord = 0; } else From dd9dd1be67b2dbb434e9a80fc38715eed44b796d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:54:35 +0200 Subject: [PATCH 113/113] Miles: fix voice comm bus regression Regression was caused in commit 3bb4ee625863c1dd503f07e0d480f4b3fd302c48. The new sound engine has breaking changes in its exports. Added shim layer to fix incompatibilities on the export 'MilesSampleSetSourceRaw'. --- r5dev/codecs/CMakeLists.txt | 2 ++ r5dev/codecs/Miles/miles_impl.h | 3 +++ r5dev/codecs/miles/miles_shim.cpp | 27 +++++++++++++++++++++++++++ r5dev/codecs/miles/miles_shim.h | 13 +++++++++++++ r5dev/core/init.cpp | 2 ++ 5 files changed, 47 insertions(+) create mode 100644 r5dev/codecs/miles/miles_shim.cpp create mode 100644 r5dev/codecs/miles/miles_shim.h diff --git a/r5dev/codecs/CMakeLists.txt b/r5dev/codecs/CMakeLists.txt index 6cbfc8ca..11824776 100644 --- a/r5dev/codecs/CMakeLists.txt +++ b/r5dev/codecs/CMakeLists.txt @@ -11,6 +11,8 @@ add_sources( SOURCE_GROUP "Bink" add_sources( SOURCE_GROUP "Miles" "miles/miles_impl.cpp" "miles/miles_impl.h" + "miles/miles_shim.cpp" + "miles/miles_shim.h" "miles/miles_types.h" # TODO[ AMOS ]: move to public! "miles/radshal_wasapi.h" ) diff --git a/r5dev/codecs/Miles/miles_impl.h b/r5dev/codecs/Miles/miles_impl.h index 74c4483c..e3ff048b 100644 --- a/r5dev/codecs/Miles/miles_impl.h +++ b/r5dev/codecs/Miles/miles_impl.h @@ -6,6 +6,7 @@ inline void(*v_AIL_LogFunc)(int64_t nLogLevel, const char* pszMessage); inline bool(*v_Miles_Initialize)(); inline void(*v_MilesQueueEventRun)(Miles::Queue*, const char*); inline void(*v_MilesBankPatch)(Miles::Bank*, char*, char*); +inline unsigned int (*v_MilesSampleSetSourceRaw)(__int64 a1, __int64 a2, unsigned int a3, int a4, unsigned __int16 a5, bool a6); inline void(*v_CSOM_AddEventToQueue)(const char* eventName); struct MilesBankList_t @@ -54,6 +55,7 @@ class MilesCore : public IDetour LogFunAdr("Miles_Initialize", v_Miles_Initialize); LogFunAdr("MilesQueueEventRun", v_MilesQueueEventRun); LogFunAdr("MilesBankPatch", v_MilesBankPatch); + LogFunAdr("MilesSampleSetSourceRaw", v_MilesSampleSetSourceRaw); LogFunAdr("CSOM_AddEventToQueue", v_CSOM_AddEventToQueue); LogVarAdr("g_milesGlobals", g_milesGlobals); } @@ -69,6 +71,7 @@ class MilesCore : public IDetour g_RadAudioSystemDll.GetExportedSymbol("MilesQueueEventRun").GetPtr(v_MilesQueueEventRun); g_RadAudioSystemDll.GetExportedSymbol("MilesBankPatch").GetPtr(v_MilesBankPatch); + g_RadAudioSystemDll.GetExportedSymbol("MilesSampleSetSourceRaw").GetPtr(v_MilesSampleSetSourceRaw); } virtual void GetVar(void) const { } virtual void GetCon(void) const { } diff --git a/r5dev/codecs/miles/miles_shim.cpp b/r5dev/codecs/miles/miles_shim.cpp new file mode 100644 index 00000000..8f794f77 --- /dev/null +++ b/r5dev/codecs/miles/miles_shim.cpp @@ -0,0 +1,27 @@ +//=============================================================================// +// +// Purpose: Miles Sound System interface shim +// +//----------------------------------------------------------------------------- +// The engine is compiled with version 10.0.42, this shim layer fixes any +// incompatibilities between upgrades. On more recent versions of the Miles +// Sound System, some exports have been renamed and/or thoroughly changed. +// If we upgrade to these versions, we need to convert this into an actual +// DLL shim layer instead of linking it statically with the SDK module. +//=============================================================================// +#include "miles_impl.h" +#include "miles_shim.h" + +unsigned int MilesSampleSetSourceRaw(__int64 a1, __int64 a2, unsigned int a3, int a4, unsigned __int16 a5, bool a6) +{ + // interface fix from 10.0.42 --> 10.0.47. As of version (10.0.43 ?) the + // export 'MilesSampleSetSourceRaw' has a newly added bool parameter. The + // purpose of this is unknown, but we need to set it to false as they + // otherwise would distort the voice comm bus. + return v_MilesSampleSetSourceRaw(a1, a2, a3, a4, a5, false); +} + +void MilesShim::Detour(const bool bAttach) const +{ + DetourSetup(&v_MilesSampleSetSourceRaw, &MilesSampleSetSourceRaw, bAttach); +} diff --git a/r5dev/codecs/miles/miles_shim.h b/r5dev/codecs/miles/miles_shim.h new file mode 100644 index 00000000..1e475895 --- /dev/null +++ b/r5dev/codecs/miles/miles_shim.h @@ -0,0 +1,13 @@ +#ifndef MILES_SHIM_H +#define MILES_SHIM_H + +class MilesShim : public IDetour +{ + virtual void GetAdr(void) const { } + virtual void GetFun(void) const { } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Detour(const bool bAttach) const; +}; + +#endif // MILES_SHIM_H diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 0aec44c8..1c7fbb50 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -35,6 +35,7 @@ #ifndef DEDICATED #include "codecs/bink/bink_impl.h" #include "codecs/miles/miles_impl.h" +#include "codecs/miles/miles_shim.h" #include "codecs/miles/radshal_wasapi.h" #endif // !DEDICATED #include "vphysics/physics_collide.h" @@ -525,6 +526,7 @@ void DetourRegister() // Register detour classes to be searched and hooked. // Codecs REGISTER(BinkCore); // REGISTER CLIENT ONLY! REGISTER(MilesCore); // REGISTER CLIENT ONLY! + REGISTER(MilesShim); REGISTER(VRadShal); #endif // !DEDICATED