Merge branch 'indev' into launcher_rework

This commit is contained in:
Kawe Mazidjatari 2024-06-01 12:02:06 +02:00
commit 02303d0ffc
174 changed files with 6235 additions and 4252 deletions

View File

@ -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
************************************************************************************
@ -788,6 +761,7 @@ LZHAM
// THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
CRC32
************************************************************************************

View File

@ -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"
)

View File

@ -1,11 +1,13 @@
#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_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");
//-----------------------------------------------------------------------------
// Purpose: logs debug output emitted from the Miles Sound System
@ -24,23 +26,21 @@ 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;
const bool isEnglishLanguage = _stricmp(pszLanguage, "english") == 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 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);
@ -82,7 +82,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,
@ -99,11 +99,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);
}
};

View File

@ -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 { }

View File

@ -31,7 +31,7 @@ namespace Miles
// internal project data structure
struct IntProjectData_t
{
char gap0[0xCF0];
char gap0[0xE28];
int bankCount;
BankHeader_t** loadedBanks;
};

View File

@ -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);
}

View File

@ -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

View File

@ -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
@ -227,33 +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.
if (RCONServer()->IsInitialized())
{
Msg(eDLL_T::SERVER, "Rebooting RCON server...\n");
RCONServer()->Shutdown();
RCONServer()->Init();
}
#endif // !CLIENT_DLL
}
}
void LanguageChanged_f(IConVar* pConVar, const char* pOldString)
{
if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName()))

View File

@ -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);

View File

@ -63,6 +63,14 @@ ConVar* eula_version_accepted = nullptr;
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
@ -72,8 +80,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;
@ -85,7 +94,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;
@ -145,8 +160,11 @@ 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");
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
@ -195,6 +213,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");
@ -208,7 +227,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);
@ -232,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);
@ -241,7 +268,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
@ -377,7 +403,6 @@ void ConCommand_InitShipped(void)
"connectAsSpectator",
"connectWithKey",
"silentconnect",
"set",
"ping",
#endif // !DEDICATED
"launchplaylist",
@ -385,6 +410,7 @@ void ConCommand_InitShipped(void)
"exit",
"reload",
"restart",
"set",
"status",
"version",
};

View File

@ -50,6 +50,14 @@ extern ConVar* eula_version_accepted;
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
@ -60,6 +68,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;
@ -72,7 +81,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;

View File

@ -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<void**>(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<bool>(NetMessageVtbl::Process, this);
};
virtual bool ReadFromBuffer(bf_read* buffer)
{
return CallVFunc<bool>(NetMessageVtbl::ReadFromBuffer, this, buffer);
}
virtual bool WriteToBuffer(bf_write* buffer)
{
return CallVFunc<bool>(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,29 @@ private:
// Client messages:
///////////////////////////////////////////////////////////////////////////////////////
class CLC_VoiceData : public CNetMessage
{
public:
int m_nLength;
bf_read m_DataIn;
bf_write m_DataOut;
int unk1;
int unk2;
};
class CLC_DurangoVoiceData : public CNetMessage
{
public:
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:

View File

@ -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()

View File

@ -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;

View File

@ -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"
@ -135,6 +136,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
@ -523,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
@ -663,6 +667,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
REGISTER(VBaseEntity);
REGISTER(VBaseAnimating);
REGISTER(VPlayer);
REGISTER(VPlayerMove);
#endif // !CLIENT_DLL

View File

@ -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

View File

@ -176,7 +176,7 @@ struct studioanimcache_t
const char* rigName;
int unk0;
int numSequences;
PakPage_t sequences;
PakPage_u sequences;
int unk1;
int unk2;
};

View File

@ -1,20 +1,96 @@
#include "core/stdafx.h"
#include "tier0/commandline.h"
#include "ebisusdk/EbisuSDK.h"
#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
//-----------------------------------------------------------------------------
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 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
@ -57,3 +133,9 @@ 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_RunFrame, &HEbisuSDK_RunFrame, bAttach);
DetourSetup(&EbisuSDK_GetLanguage, &HEbisuSDK_GetLanguage, bAttach);
}

View File

@ -1,19 +1,28 @@
#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;
///////////////////////////////////////////////////////////////////////////////
void HEbisuSDK_Init();
const char* HEbisuSDK_GetLanguage();
bool IsOriginDisabled();
bool IsOriginInitialized();
bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen);
///////////////////////////////////////////////////////////////////////////////
@ -23,10 +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_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);
@ -35,18 +46,20 @@ 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<uint64_t*>();
g_NucleusToken = CMemory(EbisuSDK_SetState).Offset(0x1EF).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<char*>();
g_OriginAuthCode = CMemory(EbisuSDK_SetState).Offset(0x1BF).FindPatternSelf("0F B6", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
g_OriginErrorLevel = CMemory(EbisuSDK_SetState).Offset(0x20).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_NucleusToken = CMemory(EbisuSDK_RunFrame).Offset(0x1EF).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<char*>();
g_OriginAuthCode = CMemory(EbisuSDK_RunFrame).Offset(0x1BF).FindPatternSelf("0F B6", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
g_PersonaName = CMemory(EbisuSDK_CVar_Init).Offset(0x120).FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
g_OriginErrorLevel = CMemory(EbisuSDK_RunFrame).Offset(0x20).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_EbisuProfileInit = CMemory(EbisuSDK_CVar_Init).Offset(0x12A).FindPatternSelf("C6 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
g_EbisuSDKInit = CMemory(EbisuSDK_Tier0_Init).Offset(0x0).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
}
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const { }
virtual void Detour(const bool bAttach) const;
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -47,6 +47,12 @@ public:
const static int index = 28;
return CallVFunc<CUserCmd*>(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<bool>(index, this, msgType, msgData);
}
};
/* ==== CHLCLIENT ======================================================================================================================================================= */

View File

@ -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.

View File

@ -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 \"<query>\"");
static ConCommand rcon_disconnect("rcon_disconnect", RCON_Disconnect_f, "Disconnect from RCON server", FCVAR_CLIENTDLL | FCVAR_RELEASE);
static ConCommand rcon("rcon", RCON_CmdQuery_f, "Forward RCON message to remote server", FCVAR_CLIENTDLL | FCVAR_RELEASE, nullptr, "rcon \"<message>\"");
//-----------------------------------------------------------------------------
// 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<LogType_t>(response.messagetype()),
static_cast<eDLL_T>(response.messageid()),
@ -165,7 +166,7 @@ void CRConClient::RequestConsoleLog(const bool bWantLog)
const SocketHandle_t hSocket = GetSocket();
vector<char> 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<char>& 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,56 @@ CRConClient* RCONClient() // Singleton RCON Client.
return &s_RCONClient;
}
/*
=====================
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)
{
if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName()))
{
const char* pNewString = pConVarRef->GetString();
if (!*pNewString) // Empty address means nothing to network to; shutdown client...
{
RCONClient()->Shutdown();
}
else
{
RCON_InitClientAndTrySyncKeys();
if (RCONClient()->IsInitialized() && !RCONClient()->IsConnected())
{
if (RCONClient()->IsConnected())
{
RCONClient()->Disconnect("address change requested");
}
RCONClient()->Connect(pNewString);
}
}
}
}
/*
=====================
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,14 +309,8 @@ static void RCON_CmdQuery_f(const CCommand& args)
if (argCount < 2)
{
const char* pszAddress = 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
{
@ -290,15 +325,15 @@ 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 // Need at least 3 arguments for a password in PASS command (rcon PASS <password>)
{
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;
}
@ -311,11 +346,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 +364,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");
}
}

View File

@ -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<char>& 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);

View File

@ -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<CSplitScreen*>();

View File

@ -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"
@ -259,7 +260,7 @@ bool CClient::Connect(const char* szName, CNetChan* pNetChan, bool bFakePlayer,
bool CClient::VConnect(CClient* pClient, const char* szName, CNetChan* pNetChan, bool bFakePlayer,
CUtlVector<NET_SetConVar::cvar_t>* conVars, char* szMessage, int nMessageSize)
{
return pClient->Connect(szName, pNetChan, bFakePlayer, conVars, szMessage, nMessageSize);;
return pClient->Connect(szName, pNetChan, bFakePlayer, conVars, szMessage, nMessageSize);
}
//---------------------------------------------------------------------------------
@ -524,6 +525,93 @@ 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)
{
#ifndef CLIENT_DLL
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
return true;
}
//---------------------------------------------------------------------------------
// Purpose: process durango voice data
// Input : *pClient - (ADJ)
// *pMsg -
// Output :
//---------------------------------------------------------------------------------
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);
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);
#endif // !CLIENT_DLL
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
@ -536,5 +624,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
}

View File

@ -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; }
@ -79,7 +80,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; }
@ -120,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
@ -197,14 +204,26 @@ 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];
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;
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);
@ -230,6 +249,7 @@ public:
m_flNetProcessTimeBase = 0.0;
m_flStringCommandQuotaTimeStart = 0.0;
m_nStringCommandQuotaCount = NULL;
m_flMovementTimeForUserCmdProcessingRemaining = 0.0f;
m_bInitialConVarsSet = false;
}
@ -247,6 +267,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 +282,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
};
@ -270,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
@ -286,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
{
@ -300,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 { }

View File

@ -9,6 +9,7 @@
//
/////////////////////////////////////////////////////////////////////////////////
#include "core/stdafx.h"
#include "mathlib/bitvec.h"
#include "tier0/frametask.h"
#include "engine/common.h"
#include "engine/host.h"
@ -24,6 +25,36 @@
#include <ebisusdk/EbisuSDK.h>
#include <engine/cmd.h>
//------------------------------------------------------------------------------
// 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
@ -307,6 +338,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 +463,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);
}

View File

@ -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);
@ -100,7 +101,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;
@ -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
{

View File

@ -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<ConVar*>(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
{

View File

@ -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);

View File

@ -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<CUtlString> g_InstalledMaps;
CFmtStrN<MAX_MAP_NAME> s_CurrentLevelName;
static std::regex s_ArchiveRegex{ R"([^_]*_(.*)(.bsp.pak000_dir).*)" };
static CustomPakData_t s_customPakData;
static KeyValues* s_pLevelSetKV = nullptr;
@ -42,13 +41,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 +63,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 +82,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 +96,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;
}
}
@ -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<const char*>& match = regexMatches[1];
const std::sub_match<const char*>& 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());
}
@ -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
@ -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,9 +421,9 @@ 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);
const PakLoadedInfo_s* const pli = Pak_GetPakInfo(commonData->pakId);
if (pli->handle != commonData->pakId || ((pli->status - 9) & 0xFFFFFFFB) != 0)
{
@ -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);
}
}

View File

@ -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

View File

@ -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
//-----------------------------------------------------------------------------
@ -299,13 +317,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
@ -350,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(),
@ -414,6 +421,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
@ -551,3 +561,7 @@ void VHostState::Detour(const bool bAttach) const
///////////////////////////////////////////////////////////////////////////////
CHostState* g_pHostState = nullptr;
#ifndef CLIENT_DLL
bool g_hostReloadState = false;
#endif // !CLIENT_DLL

View File

@ -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

View File

@ -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<char*>(&pBuffer), AES_128_KEY_SIZE)));
NET_SetKey(Base64Encode(string(reinterpret_cast<char*>(&keyBuf), AES_128_KEY_SIZE)));
}
//-----------------------------------------------------------------------------

View File

@ -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);

View File

@ -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);

View File

@ -23,7 +23,6 @@ public:
struct ServerDataBlock
{
char blockBuffer[295312]; // this might be wrong !!!
void* userData;
char gapC0008[56];
ServerDataBlockSender sender;

View File

@ -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"
@ -25,10 +26,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);
@ -174,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;

View File

@ -1,4 +1,5 @@
#pragma once
#include "tier0/frametask.h"
#include "tier1/NetAdr.h"
#include "networksystem/pylon.h"
#include "engine/client/client.h"
@ -111,19 +112,21 @@ 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);
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
@ -136,6 +139,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
}
@ -148,6 +152,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

View File

@ -162,19 +162,39 @@ 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 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);
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;
@ -191,10 +211,13 @@ 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* pNetChan = pClient->GetNetChan();
CNetChan* const pNetChan = pClient->GetNetChan();
if (!pNetChan)
continue;
@ -204,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);
}
}

View File

@ -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,18 +16,57 @@ 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();
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);
///////////////////////////////////////////////////////////////////////////////
@ -38,17 +76,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 +96,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<bool*>();
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 { }
///////////////////////////////////////////////////////////////////////////////

View File

@ -10,11 +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/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 "mbedtls/aes.h"
#include "mbedtls/ctr_drbg.h"
//-----------------------------------------------------------------------------
// Purpose: constants
@ -27,15 +29,13 @@ 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 void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString);
static void RCON_UseLoopbackSocketChanged_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_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");
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,8 +43,10 @@ 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_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_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_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);
//-----------------------------------------------------------------------------
// Purpose:
@ -54,6 +56,7 @@ CRConServer::CRConServer(void)
, m_nAuthConnections(0)
, m_bInitialized(false)
{
memset(m_PasswordHash, 0, sizeof(m_PasswordHash));
}
//-----------------------------------------------------------------------------
@ -62,18 +65,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;
}
@ -84,12 +89,14 @@ void CRConServer::Init(void)
return;
}
const char* pszAddress = net_usesocketsforloopback->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);
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;
}
@ -120,6 +127,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
//-----------------------------------------------------------------------------
@ -232,14 +252,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 +312,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<char> vecMsg;
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
@ -320,8 +340,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<char> vecMsg;
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
@ -349,26 +369,10 @@ bool CRConServer::SendEncode(const SocketHandle_t hSocket, const char* pResponse
// Output : serialized results as string
//-----------------------------------------------------------------------------
bool CRConServer::Serialize(vector<char>& 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 +380,7 @@ bool CRConServer::Serialize(vector<char>& 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 +399,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<int>(eDLL_T::NETCON));
SendEncoded(data.m_hSocket, s_AuthMessage, pSendLogs,
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(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<int>(eDLL_T::NETCON));
SendEncoded(data.m_hSocket, s_WrongPwMessage, "",
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
data.m_bAuthorized = false;
data.m_bValidated = false;
@ -442,21 +446,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<int>(eDLL_T::NETCON));
SendEncoded(data.m_hSocket, s_NoAuthMessage, "",
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
data.m_bValidated = false;
data.m_nIgnoredMessage++;
@ -464,12 +469,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 +482,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,59 +512,9 @@ 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();
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<ConVar*>(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());
}
//-----------------------------------------------------------------------------
@ -578,10 +533,10 @@ 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. 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;
@ -590,9 +545,9 @@ 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);
Warning(eDLL_T::SERVER, "Banned list is full, dropping '%s'\n", szNetAdr);
}
return true;
@ -680,7 +635,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 +643,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())
{
@ -716,6 +671,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
//-----------------------------------------------------------------------------
@ -773,19 +751,19 @@ static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldStri
}
//-----------------------------------------------------------------------------
// Purpose: change RCON password on server and drop all connections
// Purpose: change whether to bind on loopback socket
//-----------------------------------------------------------------------------
void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString)
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 password.
return; // Same value.
if (RCONServer()->IsInitialized())
RCONServer()->SetPassword(pConVarRef->GetString());
else
RCONServer()->Init(); // Initialize first.
#ifndef CLIENT_DLL
// Reboot the RCON server to switch address type.
RCONServer()->Reboot();
#endif // !CLIENT_DLL
}
}

View File

@ -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,45 +14,48 @@ public:
CRConServer(void);
~CRConServer(void);
void Init(void);
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);
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<int>(eDLL_T::NETCON),
const int nMessageType = static_cast<int>(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<int>(eDLL_T::NETCON),
const int nMessageType = static_cast<int>(LogType_t::LOG_NET)) const;
bool SendToAll(const char* pMsgBuf, const int nMsgLen) const;
bool Serialize(vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal, const sv_rcon::response_t responseType,
bool Serialize(vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal, const netcon::response_e responseType,
const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(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;

View File

@ -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<const unsigned char*>(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 (!Plat_GenerateRandom(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<unsigned char*>(&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 != AES_128_B64_ENCODED_SIZE)
{
Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: write error (%zu != %zu)\n", numBytesEncoded, AES_128_B64_ENCODED_SIZE);
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<const unsigned char*>(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<const unsigned char*>(pInBuf), nDataLen))
return Crypto_CTREncrypt(ctx, reinterpret_cast<const unsigned char*>(pInBuf),
reinterpret_cast<unsigned char*>(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<const unsigned char*>(pInBuf),
reinterpret_cast<unsigned char*>(pOutBuf), m_NetKey, nDataLen);
}
//-----------------------------------------------------------------------------
// Purpose: encode message to buffer
// Input : *pMsg -

View File

@ -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

View File

@ -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<char>& 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<char>& 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;
}
@ -50,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)))
@ -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<char>& outMsgBuf, const size_t nMsgLen,
google::protobuf::MessageLite* inMsg, const bool bEncrypt, const bool bDebug)
{
char* encodeBuf = new char[nMsgLen];
std::unique_ptr<char[]> 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<char[]> 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<char[]> 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,92 @@ 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);
//-----------------------------------------------------------------------------
// 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
}
}
#ifndef 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()
{
#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

View File

@ -1,13 +1,31 @@
#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;
#ifndef CLIENT_DLL
extern void RCON_InitServerAndTrySyncKeys(const char* pPassword);
#endif // !CLIENT_DLL
#ifndef DEDICATED
extern void RCON_InitClientAndTrySyncKeys();
#endif // !DEDICATED
#endif // _TOOLS
bool SV_NetConSerialize(const CNetConBase* pBase, vector<char>& 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<char>& 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<char>& 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);

View File

@ -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"

View File

@ -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"
)
@ -73,6 +97,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"
)
@ -114,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"
)

View File

@ -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];
}
//-----------------------------------------------------------------------------

View File

@ -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

View File

@ -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();

View File

@ -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];
};

View File

@ -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

View File

@ -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];

View File

@ -18,14 +18,15 @@
#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)
//-----------------------------------------------------------------------------
void CServerGameDLL::GameInit(void)
bool CServerGameDLL::GameInit(void)
{
const static int index = 1;
CallVFunc<void>(index, this);
return CallVFunc<bool>(index, this);
}
//-----------------------------------------------------------------------------
@ -77,8 +78,39 @@ ServerClass* CServerGameDLL::GetAllServerClasses(void)
return CallVFunc<ServerClass*>(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<CPlayer*>(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);

View File

@ -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<CGlobalVars**>();
g_pflServerFrameTimeBase = CMemory(CServerGameDLL__GameInit).FindPatternSelf("F3 0F 11 0D").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>();
}
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const;

View File

@ -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
//------------------------------------------------------------------------------
@ -57,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 * (*g_pGlobals)->m_flTickInterval;
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;
}
}
@ -99,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);
@ -109,65 +105,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 -
@ -179,7 +116,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)
@ -189,6 +126,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];
@ -203,8 +143,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);
@ -241,6 +195,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 +259,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);
}

View File

@ -241,25 +241,28 @@ struct SpeedChangeHistoryEntry
class CPlayer : public CBaseCombatCharacter
{
friend class CPlayerMove;
public:
void RunNullCommand(void);
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);
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; }
inline NucleusID_t GetPlatformUserId() const { return m_platformUserId; };
private:
int m_StuckLast;
char gap_5a8c[4];
@ -276,7 +279,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;
@ -571,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;
@ -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;
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,58 @@
//====== 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);
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);
}

View File

@ -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

View File

@ -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
//-----------------------------------------------------------------------------
@ -231,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
//-----------------------------------------------------------------------------
@ -282,6 +307,10 @@ 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");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetServerID, "Gets the current server ID", "string", "");
}
//---------------------------------------------------------------------------------

View File

@ -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);
@ -18,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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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));
@ -71,7 +72,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<unsigned char*>(m_lockedIconDataResource.m_pData), int(m_lockedIconDataResource.m_nSize),
&m_lockedIconShaderResource, &m_lockedIconDataResource.m_nWidth, &m_lockedIconDataResource.m_nHeight);
@ -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);
const bool hitEnter = ImGui::InputTextWithHint("##HiddenServersConnectModal_TokenInput", "Token (required)",
m_serverTokenTextBuf, sizeof(m_serverTokenTextBuf), ImGuiInputTextFlags_EnterReturnsTrue);
ImGui::PopItemWidth();
@ -453,15 +454,15 @@ 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;
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())
{

View File

@ -47,8 +47,9 @@ 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];
char m_serverNetKeyTextBuf[45];
ID3D11ShaderResourceView* m_lockedIconShaderResource;
MODULERESOURCE m_lockedIconDataResource;

View File

@ -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.
@ -767,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

View File

@ -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

View File

@ -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()

View File

@ -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/"
)
@ -48,8 +45,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"
)

View File

@ -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(false)
, m_flTickInterval(0.05f)
{
// Empty character set used for ip addresses if we still need to initiate a
@ -44,13 +44,15 @@ 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<std::mutex> l(m_Mutex);
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);
@ -60,19 +62,26 @@ 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;
}
}
m_bInitialized = true;
Msg(eDLL_T::NONE, "R5 TCP net console [Version %s]\n", NETCON_VERSION);
static std::thread frame([this]()
{
@ -176,6 +185,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
//-----------------------------------------------------------------------------
@ -216,17 +243,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 +271,31 @@ 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)))
TrySetKey(inKey);
m_bEncryptFrames = true;
if (!Connect(inAdr))
{
SetPrompting(true);
return;
}
}
else
else // No encryption
{
if (!Connect(cmd.GetCommandString()))
const char* inAdr = cmd.GetCommandString();
m_bEncryptFrames = false;
if (!Connect(inAdr))
{
SetPrompting(true);
return;
@ -287,7 +320,7 @@ bool CNetCon::RunFrame(void)
}
else if (GetPrompting())
{
Msg(eDLL_T::NONE, "Enter [<IP>]:<PORT> or <IP> <PORT>: ");
Msg(eDLL_T::NONE, "Enter [<address>]:<port> and <key>: ");
SetPrompting(false);
}
}
@ -332,6 +365,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 -
@ -360,18 +415,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 +433,7 @@ bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
if (!i) // Means we are marked 'input only' on the rcon server.
{
vector<char> 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 +445,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<LogType_t>(response.messagetype()),
static_cast<eDLL_T>(response.messageid()),
@ -416,9 +470,9 @@ bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetCon::Serialize(vector<char>& 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);
}
//-----------------------------------------------------------------------------
@ -453,7 +507,7 @@ bool CNetCon::IsConnected(void)
//-----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
CheckCPUforSSE2();
CheckSystemCPUForSSE2();
bool bEnableColor = false;
@ -466,16 +520,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;
}

View File

@ -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";
@ -17,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);
@ -33,11 +32,14 @@ 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<char>& 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 +49,7 @@ private:
bool m_bInitialized;
bool m_bQuitting;
bool m_bPromptConnect;
bool m_bEncryptFrames;
float m_flTickInterval;
characterset_t m_CharacterSet;

View File

@ -23,8 +23,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"libspdlog"
"SigCache_Pb"
"SV_RCon_Pb"
"CL_RCon_Pb"
"NetCon_Pb"
"Rpcrt4.lib"
)

View File

@ -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;

View File

@ -131,7 +131,16 @@ CUtlVector<CPluginSystem::PluginInstance_t>& CPluginSystem::GetInstances()
//-----------------------------------------------------------------------------
void CPluginSystem::AddCallback(PluginHelpWithAnything_t* help)
{
#define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast<fn>(function)
#define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast<fn>(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<fn>(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;
}

View File

@ -6,6 +6,7 @@
class CModAppSystemGroup;
class CServer;
class CClient;
class CPlayer;
struct user_creds_s;
template<typename T>
@ -82,6 +83,32 @@ private:
CUtlVector<T> m_vCallbacks;
};
template<typename T>
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<typeName>& funcName() { return varName; } private: CPluginCallbackList<typeName> varName;
#define CREATE_PLUGIN_CALLBACK(typeName, type, funcName, varName) public: using typeName = type; CPluginCallbackList<CPluginCallback<typeName>>& funcName() { return varName; } private: CPluginCallbackList<CPluginCallback<typeName>> 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__)

View File

@ -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()

View File

@ -1,489 +0,0 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: cl_rcon.proto
#include "cl_rcon.pb.h"
#include <algorithm>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/extension_set.h>
#include <thirdparty/protobuf/wire_format_lite.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl_lite.h>
// @@protoc_insertion_point(includes)
#include <thirdparty/protobuf/port_def.inc>
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<std::string> 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<request_t>(int_value);
}
return success;
}
// ===================================================================
class request::_Internal {
public:
using HasBits = decltype(std::declval<request>()._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<std::string>(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<size_t>(reinterpret_cast<char*>(&_impl_.requesttype_) -
reinterpret_cast<char*>(&_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<std::string>()) {
(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<size_t>(
reinterpret_cast<char*>(&_impl_.requesttype_) -
reinterpret_cast<char*>(&_impl_.messageid_)) + sizeof(_impl_.requesttype_));
}
_impl_._has_bits_.Clear();
_internal_metadata_.Clear<std::string>();
}
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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<std::string>(),
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<int>(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<int>(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<std::string>(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(),
static_cast<int>(_internal_metadata_.unknown_fields<std::string>(::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<std::string>(::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<const request*>(
&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<std::string>(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<char*>(&_impl_.messageid_),
reinterpret_cast<char*>(&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 <thirdparty/protobuf/port_undef.inc>

View File

@ -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 <limits>
#include <string>
#include <thirdparty/protobuf/port_def.inc>
#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 <thirdparty/protobuf/port_undef.inc>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/arena.h>
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/generated_message_util.h>
#include <thirdparty/protobuf/metadata_lite.h>
#include <thirdparty/protobuf/message_lite.h>
#include <thirdparty/protobuf/repeated_field.h> // IWYU pragma: export
#include <thirdparty/protobuf/extension_set.h> // IWYU pragma: export
#include <thirdparty/protobuf/generated_enum_util.h>
// @@protoc_insertion_point(includes)
#include <thirdparty/protobuf/port_def.inc>
#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<int32_t>::min(),
request_t_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::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<typename T>
inline const std::string& request_t_Name(T enum_t_value) {
static_assert(::std::is_same<T, request_t>::value ||
::std::is_integral<T>::value,
"Incorrect type passed to function request_t_Name.");
return request_t_Name(static_cast<request_t>(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<const request*>(
&_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<request>(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 <typename ArgT0 = const std::string&, typename... ArgT>
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 <typename ArgT0 = const std::string&, typename... ArgT>
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 <typename T> 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 <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void request::set_requestmsg(ArgT0&& arg0, ArgT... args) {
_impl_._has_bits_[0] |= 0x00000001u;
_impl_.requestmsg_.Set(static_cast<ArgT0 &&>(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 <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void request::set_requestval(ArgT0&& arg0, ArgT... args) {
_impl_._has_bits_[0] |= 0x00000002u;
_impl_.requestval_.Set(static_cast<ArgT0 &&>(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 <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto

1235
r5dev/protoc/netcon.pb.cc Normal file

File diff suppressed because it is too large Load Diff

1279
r5dev/protoc/netcon.pb.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,485 +0,0 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: sv_rcon.proto
#include "sv_rcon.pb.h"
#include <algorithm>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/extension_set.h>
#include <thirdparty/protobuf/wire_format_lite.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl_lite.h>
// @@protoc_insertion_point(includes)
#include <thirdparty/protobuf/port_def.inc>
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<std::string> 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<response_t>(int_value);
}
return success;
}
// ===================================================================
class response::_Internal {
public:
using HasBits = decltype(std::declval<response>()._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<std::string>(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<size_t>(reinterpret_cast<char*>(&_impl_.responsetype_) -
reinterpret_cast<char*>(&_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<std::string>()) {
(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<size_t>(
reinterpret_cast<char*>(&_impl_.responsetype_) -
reinterpret_cast<char*>(&_impl_.messageid_)) + sizeof(_impl_.responsetype_));
}
_impl_._has_bits_.Clear();
_internal_metadata_.Clear<std::string>();
}
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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<std::string>(),
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<int>(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<int>(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<std::string>(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(),
static_cast<int>(_internal_metadata_.unknown_fields<std::string>(::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<std::string>(::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<const response*>(
&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<std::string>(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<char*>(&_impl_.messageid_),
reinterpret_cast<char*>(&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 <thirdparty/protobuf/port_undef.inc>

View File

@ -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 <limits>
#include <string>
#include <thirdparty/protobuf/port_def.inc>
#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 <thirdparty/protobuf/port_undef.inc>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/arena.h>
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/generated_message_util.h>
#include <thirdparty/protobuf/metadata_lite.h>
#include <thirdparty/protobuf/message_lite.h>
#include <thirdparty/protobuf/repeated_field.h> // IWYU pragma: export
#include <thirdparty/protobuf/extension_set.h> // IWYU pragma: export
#include <thirdparty/protobuf/generated_enum_util.h>
// @@protoc_insertion_point(includes)
#include <thirdparty/protobuf/port_def.inc>
#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<int32_t>::min(),
response_t_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::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<typename T>
inline const std::string& response_t_Name(T enum_t_value) {
static_assert(::std::is_same<T, response_t>::value ||
::std::is_integral<T>::value,
"Incorrect type passed to function response_t_Name.");
return response_t_Name(static_cast<response_t>(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<const response*>(
&_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<response>(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 <typename ArgT0 = const std::string&, typename... ArgT>
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 <typename ArgT0 = const std::string&, typename... ArgT>
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 <typename T> 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 <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void response::set_responsemsg(ArgT0&& arg0, ArgT... args) {
_impl_._has_bits_[0] |= 0x00000001u;
_impl_.responsemsg_.Set(static_cast<ArgT0 &&>(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 <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void response::set_responseval(ArgT0&& arg0, ArgT... args) {
_impl_._has_bits_[0] |= 0x00000002u;
_impl_.responseval_.Set(static_cast<ArgT0 &&>(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 <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_sv_5frcon_2eproto

View File

@ -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
@ -64,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

View File

@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
enum GameMode_t
enum class GameMode_t
{
NO_MODE = 0,
MP_MODE,

View File

@ -65,6 +65,7 @@ inline const char* const g_LanguageNames[] = {
"italian",
"korean",
"spanish",
"mspanish",
"schinese",
"tchinese",
"russian",
@ -73,4 +74,46 @@ inline const char* const g_LanguageNames[] = {
"polish",
};
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(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;
}
}
return false;
}
#endif // LOCALIZE_H

View File

@ -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

View File

@ -1,3 +1,8 @@
//=============================================================================//
//
// Purpose: pak file constants and types
//
//=============================================================================//
#ifndef RTECH_IPACKFILE_H
#define RTECH_IPACKFILE_H
#include "tier0/jobthread.h"
@ -12,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)
@ -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
@ -75,14 +80,14 @@
// 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 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
@ -90,7 +95,7 @@
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct PakFile_t;
struct PakFile_s;
//-----------------------------------------------------------------------------
// Handle types
@ -101,7 +106,7 @@ typedef uint64_t PakGuid_t;
//-----------------------------------------------------------------------------
// Page handle types
//-----------------------------------------------------------------------------
struct PakPageHeader_t
struct PakPageHeader_s
{
uint32_t segmentIdx;
uint32_t pageAlignment;
@ -115,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
{
@ -128,7 +133,7 @@ union PakPage_t
//-----------------------------------------------------------------------------
// Enumerations
//-----------------------------------------------------------------------------
enum EPakDecodeMode : int32_t
enum PakDecodeMode_e
{
MODE_DISABLED = -1,
@ -137,7 +142,7 @@ enum EPakDecodeMode : int32_t
MODE_ZSTD
};
enum EPakStreamSet
enum PakStreamSet_e
{
STREAMING_SET_MANDATORY = 0,
STREAMING_SET_OPTIONAL,
@ -146,7 +151,7 @@ enum EPakStreamSet
STREAMING_SET_COUNT
};
enum EPakStatus : int32_t
enum PakStatus_e
{
PAK_STATUS_FREED = 0,
PAK_STATUS_LOAD_PENDING = 1,
@ -166,7 +171,7 @@ enum EPakStatus : int32_t
PAK_STATUS_BUSY = 15
};
struct PakAssetBinding_t
struct PakAssetBinding_s
{
enum EType
{
@ -205,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];
@ -235,11 +240,11 @@ 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);
}
};
struct PakAssetShort_t
struct PakAssetShort_s
{
PakGuid_t guid;
uint32_t trackerIndex;
@ -264,11 +269,11 @@ 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];
};
class PakLoadedInfo_t
class PakLoadedInfo_s
{
public:
struct StreamingInfo_t
@ -292,7 +297,7 @@ public:
};
PakHandle_t handle;
EPakStatus status;
PakStatus_e status;
JobID_t loadJobId;
uint32_t padding_maybe;
@ -307,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;
@ -315,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_TYPES];
PakAssetShort_t loadedAssets[PAK_MAX_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];
@ -328,11 +333,11 @@ struct PakGlobals_s
RHashMap loadedPakMap; // links to 'loadedPaks'
// all currently loaded pak handles
PakLoadedInfo_t loadedPaks[PAK_MAX_HANDLES];
PakLoadedInfo_s 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
@ -390,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
{
@ -420,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
@ -496,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)
@ -504,23 +509,23 @@ 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_TYPES];
size_t assetTypeCount[PAK_MAX_TRACKED_TYPES];
int64_t segmentSizes[PAK_MAX_SEGMENTS];
size_t segmentSizeForType[PAK_SEGMENT_BUFFER_TYPES];
int segmentAlignmentForType[PAK_SEGMENT_BUFFER_TYPES];
};
struct PakDecoder_t
struct PakDecoder_s
{
const uint8_t* inputBuf;
uint8_t* outputBuf;
@ -537,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!!!
@ -574,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
{
@ -590,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;
@ -610,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,
@ -636,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
@ -670,37 +675,37 @@ 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;
// 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;
PakPatchFileHeader_t patchHeader;
PakFileHeader_s pakHeader;
PakPatchFileHeader_s patchHeader;
};
struct PakFile_t
struct PakFile_s
{
int numProcessedPointers;
uint32_t processedAssetCount;
@ -710,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;
}
@ -766,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());
@ -786,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));
@ -806,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());
@ -816,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

View File

@ -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

View File

@ -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
{

View File

@ -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 <typename T, int N>
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);
@ -362,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()
{}
@ -423,7 +441,9 @@ FORCEINLINE void CBitRead::GrabNextDWord(bool bOverFlowImmediately)
{
if (m_pDataIn > m_pBufferEnd)
{
SetOverflowFlag();
if (!IsOverflowed())
SetOverflowFlag();
m_nInBufWord = 0;
}
else

View File

@ -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.

View File

@ -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);

View File

@ -0,0 +1,28 @@
#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];
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

View File

@ -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 <map>
#include <vector>
#include <unordered_map>
#include <utility>
#include <fstream>
#include <memory>
#include <unordered_set>
#include <algorithm>
#include <iterator>
#include <functional>
#include <system_error>
#include <exception>
//for wstring support
#include <locale>
#include <string>
// internal
#include <stack>
//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 <typename T>
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<wchar_t>
{
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<type>::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 <class Facet>
struct deletable_facet : Facet
{
template <class... Args>
deletable_facet(Args &&... args) : Facet(std::forward<Args>(args)...) {}
~deletable_facet() {}
};
inline std::string string_converter(const std::wstring& w) //todo: use us-locale
{
std::wstring_convert<deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>> conv1;
return conv1.to_bytes(w);
}
///////////////////////////////////////////////////////////////////////////
// Writer helper functions
///////////////////////////////////////////////////////////////////////////
template <typename charT>
class tabs
{
const size_t t;
public:
explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {}
std::basic_string<charT> print() const { return std::basic_string<charT>(t, TYTI_L(charT, '\t')); }
inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT
{
return tabs(t + i);
}
};
template <typename oStreamT>
oStreamT& operator<<(oStreamT& s, const tabs<typename oStreamT::char_type> 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 <typename CharT>
struct basic_object
{
typedef CharT char_type;
std::basic_string<char_type> name;
std::unordered_map<std::basic_string<char_type>, std::basic_string<char_type>> attribs;
std::unordered_map<std::basic_string<char_type>, std::shared_ptr<basic_object<char_type>>> childs;
void add_attribute(std::basic_string<char_type> key, std::basic_string<char_type> value)
{
attribs.emplace(std::move(key), std::move(value));
}
void add_child(std::unique_ptr<basic_object<char_type>> child)
{
std::shared_ptr<basic_object<char_type>> obj{ child.release() };
childs.emplace(obj->name, obj);
}
void set_name(std::basic_string<char_type> n)
{
name = std::move(n);
}
};
template <typename CharT>
struct basic_multikey_object
{
typedef CharT char_type;
std::basic_string<char_type> name;
std::unordered_multimap<std::basic_string<char_type>, std::basic_string<char_type>> attribs;
std::unordered_multimap<std::basic_string<char_type>, std::shared_ptr<basic_multikey_object<char_type>>> childs;
void add_attribute(std::basic_string<char_type> key, std::basic_string<char_type> value)
{
attribs.emplace(std::move(key), std::move(value));
}
void add_child(std::unique_ptr<basic_multikey_object<char_type>> child)
{
std::shared_ptr<basic_multikey_object<char_type>> obj{ child.release() };
childs.emplace(obj->name, obj);
}
void set_name(std::basic_string<char_type> n)
{
name = std::move(n);
}
};
typedef basic_object<char> object;
typedef basic_object<wchar_t> wobject;
typedef basic_multikey_object<char> multikey_object;
typedef basic_multikey_object<wchar_t> 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 <typename OutputT, typename iStreamT>
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 <typename oStreamT, typename T>
void write(oStreamT& s, const T& r,
const detail::tabs<typename oStreamT::char_type> tab = detail::tabs<typename oStreamT::char_type>(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 <typename iStreamT>
std::basic_string<typename iStreamT::char_type> read_file(iStreamT& inStream)
{
// cache the file
typedef typename iStreamT::char_type charT;
std::basic_string<charT> str;
inStream.seekg(0, std::ios::end);
str.resize(static_cast<size_t>(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 <typename OutputT, typename IterT>
std::vector<std::unique_ptr<OutputT>> read_internal(IterT first, const IterT last,
std::unordered_set<std::basic_string<typename std::iterator_traits<IterT>::value_type>>& exclude_files,
const Options& opt)
{
static_assert(std::is_default_constructible<OutputT>::value,
"Output Type must be default constructible (provide constructor without arguments)");
static_assert(std::is_move_constructible<OutputT>::value,
"Output Type must be move constructible");
typedef typename std::iterator_traits<IterT>::value_type charT;
const std::basic_string<charT> comment_end_str = TYTI_L(charT, "*/");
const std::basic_string<charT> whitespaces = TYTI_L(charT, " \n\v\f\r\t");
#ifdef WIN32
std::function<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& in) {
return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS");
};
#elif __APPLE__
// WIN32 stands for pc in general
std::function<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& 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<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& in) {
return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$LINUX");
};
#else
std::function<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& in) {
return false;
};
#endif
if (opt.ignore_all_platform_conditionals)
is_platform_str = [](const std::basic_string<charT>&) {
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<void(std::basic_string<charT>&)> strip_escape_symbols = [](std::basic_string<charT>& 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<charT>&) {};
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<charT>(iter, end);
const bool is_platform = is_platform_str(conditional);
iter = end + 1;
return static_cast<bool>(is_platform ^ negate);
}
return true;
};
//read header
// first, quoted name
std::unique_ptr<OutputT> curObj = nullptr;
std::vector<std::unique_ptr<OutputT>> roots;
std::stack<std::unique_ptr<OutputT>> 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<charT> 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<charT>(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<charT> i(detail::string_converter(value));
auto str = read_file(i);
auto file_objs = read_internal<OutputT>(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<OutputT>();
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<OutputT> 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 <typename OutputT, typename IterT>
OutputT read(IterT first, const IterT last, const Options& opt = Options{})
{
auto exclude_files = std::unordered_set<std::basic_string<typename std::iterator_traits<IterT>::value_type>>{};
auto roots = detail::read_internal<OutputT>(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 <typename OutputT, typename IterT>
OutputT read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT
{
ec.clear();
OutputT r{};
try
{
r = read<OutputT>(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 <typename OutputT, typename IterT>
OutputT read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT
{
std::error_code ec;
auto r = read<OutputT>(first, last, ec, opt);
if (ok)
*ok = !ec;
return r;
}
template <typename IterT>
inline auto read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT -> basic_object<typename std::iterator_traits<IterT>::value_type>
{
return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(first, last, ok, opt);
}
template <typename IterT>
inline auto read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT
-> basic_object<typename std::iterator_traits<IterT>::value_type>
{
return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(first, last, ec, opt);
}
template <typename IterT>
inline auto read(IterT first, const IterT last, const Options& opt = Options{})
-> basic_object<typename std::iterator_traits<IterT>::value_type>
{
return read<basic_object<typename std::iterator_traits<IterT>::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 <typename OutputT, typename iStreamT>
OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{})
{
// cache the file
typedef typename iStreamT::char_type charT;
std::basic_string<charT> str = detail::read_file(inStream);
// parse it
return read<OutputT>(str.begin(), str.end(), ec, opt);
}
template <typename iStreamT>
inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{})
{
return read<basic_object<typename iStreamT::char_type>>(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 <typename OutputT, typename iStreamT>
OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{})
{
std::error_code ec;
const auto r = read<OutputT>(inStream, ec, opt);
if (ok)
*ok = !ec;
return r;
}
template <typename iStreamT>
inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, bool* ok, const Options& opt = Options{})
{
return read<basic_object<typename iStreamT::char_type>>(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 <typename OutputT, typename iStreamT>
OutputT read(iStreamT& inStream, const Options& opt)
{
// cache the file
typedef typename iStreamT::char_type charT;
std::basic_string<charT> str = detail::read_file(inStream);
// parse it
return read<OutputT>(str.begin(), str.end(), opt);
}
template <typename iStreamT>
inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, const Options& opt = Options{})
{
return read<basic_object<typename iStreamT::char_type>>(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__

View File

@ -17,6 +17,15 @@ typedef void* ScriptFunctionBindingStorageType_t;
//---------------------------------------------------------
enum ScriptStatus_t
{
SCRIPT_ERROR = -1,
SCRIPT_DONE,
SCRIPT_RUNNING,
};
//---------------------------------------------------------
enum ExtendedFieldType
{
FIELD_TYPEUNKNOWN = FIELD_TYPECOUNT,

View File

@ -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,12 @@ 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..\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"
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"

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More