Compare commits

..

No commits in common. "p4sync" and "v2.5_r3" have entirely different histories.

196 changed files with 2714 additions and 5143 deletions

View File

@ -12,6 +12,7 @@ set( FOLDER_CONTEXT "Libraries" )
add_subdirectory( mathlib )
add_subdirectory( vpklib )
add_subdirectory( vstdlib )
add_subdirectory( vphysics )
add_subdirectory( ebisusdk )
add_subdirectory( codecs )
add_subdirectory( geforce )
@ -67,9 +68,7 @@ add_subdirectory( inputsystem )
add_subdirectory( filesystem )
add_subdirectory( datacache )
add_subdirectory( studiorender )
add_subdirectory( particles )
add_subdirectory( localize )
add_subdirectory( vphysics )
add_subdirectory( engine )
add_subdirectory( vguimatsurface )
add_subdirectory( vgui )

View File

@ -100,13 +100,6 @@ macro( define_compiler_variables )
else()
message( FATAL_ERROR "Unsupported compiler: ${CMAKE_CXX_COMPILER_ID}" )
endif()
# Win64 is currently the only target we plan to support. If we support more,
# we need to adjust the extension from here as _DLL_EXT is used for the macro
# DLL_EXT_STRING, which is used for constructing AppSystemInfo_t objects. The
# method IAppSystem::GetDependencies() returns these objects which the caller
# could use to figure out which modules to load in order to use the interface.
add_definitions( -D_DLL_EXT=\".dll\" )
endmacro()
# -----------------------------------------------------------------------------
@ -120,7 +113,7 @@ macro( whole_program_optimization )
endmacro()
# -----------------------------------------------------------------------------
# Toggles whether or not to treat warnings as errors
# Toggles wether or not to treat warnings as errors
# -----------------------------------------------------------------------------
macro( warnings_as_errors TARGET FLAG )
if( ${FLAG} )

View File

@ -32,16 +32,15 @@ bool Miles_Initialize()
if (!isDefaultLanguage)
{
const bool useShipSound = !CommandLine()->FindParm("-devsound") || CommandLine()->FindParm("-shipsound");
char baseStreamFilePath[MAX_PATH];
V_snprintf(baseStreamFilePath, sizeof(baseStreamFilePath), "%s/general_%s.mstr", useShipSound ? "audio/ship" : "audio/dev", pszLanguage);
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 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))
if (!FileSystem()->FileExists(baseStreamFilePath.c_str()))
{
Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to '%s'...\n",
__FUNCTION__, pszLanguage, baseStreamFilePath, MILES_DEFAULT_LANGUAGE);
__FUNCTION__, pszLanguage, baseStreamFilePath.c_str(), MILES_DEFAULT_LANGUAGE);
pszLanguage = MILES_DEFAULT_LANGUAGE;
miles_language->SetValue(pszLanguage);
@ -52,7 +51,7 @@ bool Miles_Initialize()
CFastTimer initTimer;
initTimer.Start();
const bool bResult = v_Miles_Initialize();
bool bResult = v_Miles_Initialize();
initTimer.End();
Msg(eDLL_T::AUDIO, "%s: %s ('%f' seconds)\n", __FUNCTION__, bResult ? "success" : "failure", initTimer.GetDuration().GetSeconds());
@ -117,6 +116,6 @@ void MilesCore::Detour(const bool bAttach) const
DetourSetup(&v_AIL_LogFunc, &AIL_LogFunc, bAttach);
DetourSetup(&v_Miles_Initialize, &Miles_Initialize, bAttach);
DetourSetup(&v_MilesQueueEventRun, &MilesQueueEventRun, bAttach);
//DetourSetup(&v_MilesBankPatch, &MilesBankPatch, bAttach);
DetourSetup(&v_MilesBankPatch, &MilesBankPatch, bAttach);
DetourSetup(&v_CSOM_AddEventToQueue, &CSOM_AddEventToQueue, bAttach);
}

View File

@ -231,24 +231,28 @@ void VPK_Unmount_f(const CCommand& args)
void LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue, ChangeUserData_t pUserData)
{
const char* pNewString = language_cvar->GetString();
if (strcmp(pOldString, pNewString) == NULL)
return; // Same language.
if (!Localize_IsLanguageSupported(pNewString))
if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName()))
{
// if new text isn't valid but the old value is, reset the value
if (Localize_IsLanguageSupported(pOldString))
pNewString = pOldString;
else
const char* pNewString = pConVarRef->GetString();
if (strcmp(pOldString, pConVarRef->GetString()) == NULL)
return; // Same language.
if (!Localize_IsLanguageSupported(pNewString))
{
// this shouldn't really happen, but if neither the old nor new values are valid, set to english
Assert(0);
pNewString = g_LanguageNames[0];
// if new text isn't valid but the old value is, reset the value
if (Localize_IsLanguageSupported(pOldString))
pNewString = pOldString;
else
{
// this shouldn't really happen, but if neither the old nor new values are valid, set to english
Assert(0);
pNewString = g_LanguageNames[0];
}
}
language_cvar->SetValue(pNewString);
pConVarRef->SetValue(pNewString);
g_MasterServer.SetLanguage(pNewString);
}
}
@ -287,59 +291,61 @@ Mat_CrossHair_f
Print the material under the crosshair.
=====================
*/
static void PrintChildMat(const CMaterialGlue* const materialGlue, const char* const text)
{
Msg(eDLL_T::MS, " |-+\n");
Msg(eDLL_T::MS, " | |-+ Child material ----------------------------------------\n");
Msg(eDLL_T::MS, text, materialGlue);
if (materialGlue)
{
const MaterialGlue_s* const material = materialGlue->Get();
Msg(eDLL_T::MS, " | |-- Pak GUID: '%llX'\n", material->guid);
Msg(eDLL_T::MS, " | |-- Material name: '%s'\n", material->name);
}
}
void Mat_CrossHair_f(const CCommand& args)
{
const CMaterialGlue* const materialGlue = v_GetMaterialAtCrossHair();
CMaterialGlue* material = v_GetMaterialAtCrossHair();
if (material)
{
Msg(eDLL_T::MS, "______________________________________________________________\n");
Msg(eDLL_T::MS, "-+ Material --------------------------------------------------\n");
Msg(eDLL_T::MS, " |-- ADDR: '%llX'\n", material);
Msg(eDLL_T::MS, " |-- GUID: '%llX'\n", material->assetGuid);
Msg(eDLL_T::MS, " |-- Num Streaming Textures: '%d'\n", material->numStreamingTextureHandles);
Msg(eDLL_T::MS, " |-- Material width: '%d'\n", material->width);
Msg(eDLL_T::MS, " |-- Material height: '%d'\n", material->height);
Msg(eDLL_T::MS, " |-- Samplers: '%08X'\n", material->samplers);
if (!materialGlue)
std::function<void(CMaterialGlue*, const char*)> fnPrintChild = [](CMaterialGlue* material, const char* print)
{
Msg(eDLL_T::MS, " |-+\n");
Msg(eDLL_T::MS, " | |-+ Child material ----------------------------------------\n");
Msg(eDLL_T::MS, print, material);
Msg(eDLL_T::MS, " | |-- GUID: '%llX'\n", material->assetGuid);
Msg(eDLL_T::MS, " | |-- Material name: '%s'\n", material->name);
};
Msg(eDLL_T::MS, " |-- Material name: '%s'\n", material->name);
Msg(eDLL_T::MS, " |-- Material surface name 1: '%s'\n", material->surfaceProp);
Msg(eDLL_T::MS, " |-- Material surface name 2: '%s'\n", material->surfaceProp2);
Msg(eDLL_T::MS, " |-- DX buffer: '%llX'\n", material->dxBuffer);
Msg(eDLL_T::MS, " |-- DX buffer VFTable: '%llX'\n", material->unkD3DPointer);
material->depthShadowMaterial
? fnPrintChild(material->depthShadowMaterial, " | |-+ DepthShadow: '%llX'\n")
: Msg(eDLL_T::MS, " | |-+ DepthShadow: 'NULL'\n");
material->depthPrepassMaterial
? fnPrintChild(material->depthPrepassMaterial, " | |-+ DepthPrepass: '%llX'\n")
: Msg(eDLL_T::MS, " | |-+ DepthPrepass: 'NULL'\n");
material->depthVSMMaterial
? fnPrintChild(material->depthVSMMaterial, " | |-+ DepthVSM: '%llX'\n")
: Msg(eDLL_T::MS, " | |-+ DepthVSM: 'NULL'\n");
material->depthShadowTightMaterial
? fnPrintChild(material->depthShadowTightMaterial, " | |-+ DepthShadowTight: '%llX'\n")
: Msg(eDLL_T::MS, " | |-+ DepthShadowTight: 'NULL'\n");
material->colpassMaterial
? fnPrintChild(material->colpassMaterial, " | |-+ ColPass: '%llX'\n")
: Msg(eDLL_T::MS, " | |-+ ColPass: 'NULL'\n");
Msg(eDLL_T::MS, "-+ Texture GUID map ------------------------------------------\n");
Msg(eDLL_T::MS, " |-- Texture handles: '%llX'\n", material->textureHandles);
Msg(eDLL_T::MS, " |-- Streaming texture handles: '%llX'\n", material->streamingTextureHandles);
Msg(eDLL_T::MS, "--------------------------------------------------------------\n");
}
else
{
Msg(eDLL_T::MS, "%s: No material found >:(\n", __FUNCTION__);
return;
}
const MaterialGlue_s* const material = materialGlue->Get();
Msg(eDLL_T::MS, "______________________________________________________________\n");
Msg(eDLL_T::MS, "-+ Material --------------------------------------------------\n");
Msg(eDLL_T::MS, " |-- Address: '%llX'\n", material);
Msg(eDLL_T::MS, " |-- Pak GUID: '%llX'\n", material->guid);
Msg(eDLL_T::MS, " |-- Samplers: '%08X'\n", *(uint32*)material->samplers);
Msg(eDLL_T::MS, " |-- Streaming handles: '%hu'\n", material->streamingTextureHandleCount);
Msg(eDLL_T::MS, " |-- Material width: '%hu'\n", material->width);
Msg(eDLL_T::MS, " |-- Material height: '%hu'\n", material->height);
Msg(eDLL_T::MS, " |-- Material name: '%s'\n", material->name);
Msg(eDLL_T::MS, " |-- Material surface name 1: '%s'\n", material->surfaceProp);
Msg(eDLL_T::MS, " |-- Material surface name 2: '%s'\n", material->surfaceProp2);
Msg(eDLL_T::MS, " |-- Uber buffer: '%llX'\n", material->uberBuffer);
Msg(eDLL_T::MS, " |-- View buffer: '%llX'\n", material->viewBuffer);
PrintChildMat(material->depthMaterials[DEPTH_SHADOW], " | |-+ Depth shadow: '%llX'\n");
PrintChildMat(material->depthMaterials[DEPTH_PREPASS], " | |-+ Depth prepass: '%llX'\n");
PrintChildMat(material->depthMaterials[DEPTH_VSM], " | |-+ Depth VSM: '%llX'\n");
PrintChildMat(material->depthMaterials[DEPTH_SHADOW_TIGHT], " | |-+ Depth shadow tight: '%llX'\n");
PrintChildMat(material->colpassMaterial, " | |-+ Color pass: '%llX'\n");
Msg(eDLL_T::MS, "-+ Texture GUID map ------------------------------------------\n");
Msg(eDLL_T::MS, " |-- Texture handles: '%llX'\n", material->textureHandles);
Msg(eDLL_T::MS, " |-- Streaming texture handles: '%llX'\n", material->streamingTextureHandles);
Msg(eDLL_T::MS, "--------------------------------------------------------------\n");
}
/*

View File

@ -170,18 +170,6 @@ int RTech_PakUnload_f_CompletionFunc(char const* partial, char commands[COMMAND_
return _Host_Pak_f_CompletionFunc(&s_PakUnloadAutoFileList, partial, commands);
}
static CBaseAutoCompleteFileList s_PakSwapAutoFileList("pak_requestswap", "paks/Win64", "rpak");
//-----------------------------------------------------------------------------
// Purpose:
// Input : *partial -
// **commands -
// Output : int
//-----------------------------------------------------------------------------
int RTech_PakSwap_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
{
return _Host_Pak_f_CompletionFunc(&s_PakSwapAutoFileList, partial, commands);
}
static CBaseAutoCompleteFileList s_PakCompress("pak_compress", "paks/Win64_override", "rpak");
//-----------------------------------------------------------------------------
// Purpose:

View File

@ -11,7 +11,6 @@ int Game_Give_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLE
int RTech_PakLoad_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakUnload_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakSwap_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakCompress_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakDecompress_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);

View File

@ -57,7 +57,6 @@ ConVar* r_visualizetraces_duration = nullptr;
ConVar* stream_overlay = nullptr;
ConVar* stream_overlay_mode = nullptr;
ConVar* gpu_driven_tex_stream = nullptr;
ConVar* eula_version = nullptr;
ConVar* eula_version_accepted = nullptr;
@ -187,11 +186,8 @@ void ConVar_InitShipped(void)
#endif // !DEDICATED
staticProp_no_fade_scalar = g_pCVar->FindVar("staticProp_no_fade_scalar");
staticProp_gather_size_weight = g_pCVar->FindVar("staticProp_gather_size_weight");
#ifndef DEDICATED
stream_overlay = g_pCVar->FindVar("stream_overlay");
stream_overlay_mode = g_pCVar->FindVar("stream_overlay_mode");
gpu_driven_tex_stream = g_pCVar->FindVar("gpu_driven_tex_stream");
#endif // !DEDICATED
sv_cheats = g_pCVar->FindVar("sv_cheats");
sv_visualizetraces = g_pCVar->FindVar("sv_visualizetraces");
sv_visualizetraces_duration = g_pCVar->FindVar("sv_visualizetraces_duration");
@ -278,14 +274,12 @@ void ConVar_InitShipped(void)
mp_gamemode->RemoveFlags(FCVAR_DEVELOPMENTONLY);
// The base callback is for client builds only, must be replaced with the
// dedicated server variant as the original one runs this through
// CEngineClient::SetupGamemode(). The callback is effectively the same
// with the exception that it calls SetupGamemode directly, and not
// through an interface like CEngineClient.
#ifdef DEDICATED
// The base callback is for client builds only, must be removed from the
// dedicated server as it features client globals.
mp_gamemode->RemoveChangeCallback(mp_gamemode->GetChangeCallback(0), 0);
#endif // DEDICATED
mp_gamemode->InstallChangeCallback(MP_GameMode_Changed_f, nullptr, false);
net_usesocketsforloopback->RemoveFlags(FCVAR_DEVELOPMENTONLY);
#ifndef DEDICATED
language_cvar->InstallChangeCallback(LanguageChanged_f, nullptr, false);

View File

@ -39,11 +39,10 @@ extern ConVar* mp_gamemode;
#ifndef DEDICATED
extern ConVar* r_visualizetraces;
extern ConVar* r_visualizetraces_duration;
#endif // !DEDICATED
extern ConVar* stream_overlay;
extern ConVar* stream_overlay_mode;
extern ConVar* gpu_driven_tex_stream;
#endif // !DEDICATED
//-------------------------------------------------------------------------
// SHARED |
extern ConVar* eula_version;

View File

@ -4,11 +4,10 @@
//
//===========================================================================//
#pragma once
#include "netcon/INetCon.h"
typedef int SocketHandle_t;
enum class ServerDataRequestType_e : int
enum class ServerDataRequestType_t : int
{
SERVERDATA_REQUEST_VALUE = 0,
SERVERDATA_REQUEST_SETVALUE,
@ -18,7 +17,7 @@ enum class ServerDataRequestType_e : int
SERVERDATA_REQUEST_SEND_REMOTEBUG,
};
enum class ServerDataResponseType_e : int
enum class ServerDataResponseType_t : int
{
SERVERDATA_RESPONSE_VALUE = 0,
SERVERDATA_RESPONSE_UPDATE,
@ -28,20 +27,20 @@ enum class ServerDataResponseType_e : int
SERVERDATA_RESPONSE_REMOTEBUG,
};
struct ConnectedNetConsoleData_s
class CConnectedNetConsoleData
{
public:
SocketHandle_t m_hSocket;
u32 m_nPayloadLen; // Num bytes for this message.
u32 m_nPayloadRead; // Num read bytes from input buffer.
u32 m_nFailedAttempts; // Num failed authentication attempts.
u32 m_nIgnoredMessage; // Count how many times client ignored the no-auth message.
int m_nPayloadLen; // Num bytes for this message.
int m_nPayloadRead; // Num read bytes from input buffer.
int m_nFailedAttempts; // Num failed authentication attempts.
int m_nIgnoredMessage; // Count how many times client ignored the no-auth message.
bool m_bValidated; // Revalidates netconsole if false.
bool m_bAuthorized; // Set to true after successful netconsole auth.
bool m_bInputOnly; // If set, don't send spew to this netconsole.
NetConFrameHeader_s m_FrameHeader; // Current frame header.
vector<byte> m_RecvBuffer;
vector<uint8_t> m_RecvBuffer;
ConnectedNetConsoleData_s(SocketHandle_t hSocket = -1)
CConnectedNetConsoleData(SocketHandle_t hSocket = -1)
{
m_hSocket = hSocket;
m_nPayloadLen = 0;
@ -51,19 +50,22 @@ struct ConnectedNetConsoleData_s
m_bValidated = false;
m_bAuthorized = false;
m_bInputOnly = true;
m_FrameHeader.magic = 0;
m_FrameHeader.length = 0;
m_RecvBuffer.resize(sizeof(u_long)); // Reserve enough for length-prefix.
}
};
/* PACKET FORMAT **********************************
REQUEST:
NetConFrameHeader_s header;
byte* data;
int requestID;
int ServerDataRequestType_t;
NullTerminatedString (variable or command)
NullTerminatedString (value)
RESPONSE:
NetConFrameHeader_s header;
byte* data;
int requestID;
int ServerDataResponseType_t;
NullTerminatedString (variable)
NullTerminatedString (value)
***************************************************/

View File

@ -70,24 +70,24 @@ bool SVC_UserMessage::ProcessImpl()
///////////////////////////////////////////////////////////////////////////////////
bool SVC_SetClassVar::ReadFromBuffer(bf_read* buffer)
{
const bool key = buffer->ReadString(m_szKey, sizeof(m_szKey));
const bool val = buffer->ReadString(m_szValue, sizeof(m_szValue));
const bool set = buffer->ReadString(m_szSetting, sizeof(m_szSetting));
const bool var = buffer->ReadString(m_szVariable, sizeof(m_szVariable));
return key && val;
return set && var;
}
bool SVC_SetClassVar::WriteToBuffer(bf_write* buffer)
{
const bool key = buffer->WriteString(m_szKey);
const bool val = buffer->WriteString(m_szValue);
const bool set = buffer->WriteString(m_szSetting);
const bool var = buffer->WriteString(m_szVariable);
return key && val;
return set && var;
}
bool SVC_SetClassVar::Process(void)
{
const char* pArgs[3] = {
"_setClassVarClient",
m_szKey,
m_szValue
m_szSetting,
m_szVariable
};
CCommand command((int)V_ARRAYSIZE(pArgs), pArgs, cmd_source_t::kCommandSrcCode);

View File

@ -464,13 +464,13 @@ class SVC_SetClassVar : public CNetMessage
{
public:
SVC_SetClassVar() = default;
SVC_SetClassVar(const char* key, const char* value)
SVC_SetClassVar(const char* setting, const char* var)
{
V_strncpy(m_szKey, key, sizeof(m_szKey));
V_strncpy(m_szValue, value, sizeof(m_szValue));
V_strncpy(m_szSetting, setting, sizeof(m_szSetting));
V_strncpy(m_szVariable, var, sizeof(m_szVariable));
m_szKey[sizeof(m_szKey) - 1] = '\0';
m_szValue[sizeof(m_szValue) - 1] = '\0';
m_szSetting[sizeof(m_szSetting) - 1] = '\0';
m_szVariable[sizeof(m_szVariable) - 1] = '\0';
m_nGroup = 2; // must be set to 2 to avoid being copied into replay buffer
}
@ -486,15 +486,15 @@ public:
virtual const char* ToString(void) const
{
static char szBuf[4096];
V_snprintf(szBuf, sizeof(szBuf), "%s: key \"%s\", value \"%s\"", this->GetName(), m_szKey, m_szValue);
V_snprintf(szBuf, sizeof(szBuf), "%s: setting \"%s\", variable \"%s\"", this->GetName(), m_szSetting, m_szVariable);
return szBuf;
};
virtual size_t GetSize(void) const { return sizeof(SVC_SetClassVar); }
char m_szKey[128];
char m_szValue[128];
char m_szSetting[128];
char m_szVariable[128];
};
///////////////////////////////////////////////////////////////////////////////////////

View File

@ -113,8 +113,6 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"vgui"
"rui"
"particles"
"d3d11.lib"
"${THIRDPARTY_SOURCE_DIR}/nvapi/amd64/nvapi64.lib"
)

View File

@ -18,9 +18,6 @@
#include "mathlib/mathlib.h"
#include "launcher/launcher.h"
#include "protobuf/stubs/common.h"
#ifndef DEDICATED
#include "gameui/imgui_system.h"
#endif // !DEDICATED
#ifndef DEDICATED
#define SDK_DEFAULT_CFG "cfg/system/startup_default.cfg"
@ -58,8 +55,8 @@ void Show_Emblem()
// Log the SDK's 'build_id' under the emblem.
Msg(eDLL_T::SYSTEM_ERROR,
"+------------------------------------------------[%s%010u%s]-+\n",
g_svYellowF.c_str(), g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svRedF.c_str());
"+------------------------------------------------[%s%010d%s]-+\n",
g_svYellowF, g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svRedF);
Msg(eDLL_T::SYSTEM_ERROR, "\n");
}
@ -127,10 +124,6 @@ void SDK_Init()
s_bConsoleInitialized = Console_Init(bAnsiColor);
}
#ifndef DEDICATED
ImguiSystem()->SetEnabled(!CommandLine()->CheckParm("-noimgui"));
#endif // !DEDICATED
SpdLog_Init(bAnsiColor);
Show_Emblem();

View File

@ -44,13 +44,11 @@
#include "materialsystem/cmaterialsystem.h"
#ifndef DEDICATED
#include "materialsystem/cmaterialglue.h"
#include "materialsystem/texturestreaming.h"
#include "vgui/vgui_baseui_interface.h"
#include "vgui/vgui_debugpanel.h"
#include "vgui/vgui_fpspanel.h"
#include "vgui/vgui_controls/RichText.h"
#include "vguimatsurface/MatSystemSurface.h"
#include "particles/particles.h"
#include "engine/client/vengineclient_impl.h"
#include "engine/client/cdll_engine_int.h"
#include "engine/client/datablock_receiver.h"
@ -269,17 +267,15 @@ void Systems_Init()
#ifndef CLIENT_DLL
ServerScriptRegister_Callback = Script_RegisterServerFunctions;
CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions;
AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions;
ServerScriptRegisterEnum_Callback = Script_RegisterServerEnums;
#endif// !CLIENT_DLL
#ifndef SERVER_DLL
ClientScriptRegister_Callback = Script_RegisterClientFunctions;
UiScriptRegister_Callback = Script_RegisterUIFunctions;
#ifndef CLIENT_DLL
UiServerScriptRegister_Callback = Script_RegisterUIServerFunctions;
UiAdminPanelScriptRegister_Callback = Script_RegisterAdminServerFunctions;
#endif // !CLIENT_DLL
#endif // !SERVER_DLL
#ifdef CLIENT_DLL
@ -563,7 +559,6 @@ void DetourRegister() // Register detour classes to be searched and hooked.
#ifndef DEDICATED
REGISTER(VMaterialGlue);
REGISTER(VShaderGlue);
REGISTER(VTextureStreaming);
// Studio
REGISTER(VStudioRenderContext);
@ -574,9 +569,6 @@ void DetourRegister() // Register detour classes to be searched and hooked.
REGISTER(VVGUIRichText); // REGISTER CLIENT ONLY!
REGISTER(VMatSystemSurface);
// Particles
REGISTER(VParticles);
// Client
REGISTER(HVEngineClient);
REGISTER(VDll_Engine_Int);

View File

@ -2,8 +2,13 @@
#include "core/logdef.h"
std::shared_ptr<spdlog::logger> g_TermLogger;
std::shared_ptr<spdlog::logger> g_ImGuiLogger;
std::shared_ptr<spdlog::logger> g_SuppementalToolsLogger;
std::ostringstream g_LogStream;
std::shared_ptr<spdlog::sinks::ostream_sink_st> g_LogSink;
#ifndef _TOOLS
static void SpdLog_CreateRotatingLoggers()
{
@ -55,14 +60,17 @@ void SpdLog_Init(const bool bAnsiColor)
#ifndef _TOOLS
g_LogSessionUUID = CreateUUID();
if (g_LogSessionUUID.empty())
{
// Fall-back directory in case of a failure.
g_LogSessionUUID = "00000000-0000-0000-0000-000000000000";
}
g_LogSessionDirectory = fmt::format("platform/logs/{:s}", g_LogSessionUUID);
/************************
* IMGUI LOGGER SETUP *
************************/
{
g_LogSink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_LogStream);
g_ImGuiLogger = std::make_shared<spdlog::logger>("game_console", g_LogSink);
spdlog::register_logger(g_ImGuiLogger); // in-game console logger.
g_ImGuiLogger->set_pattern("%v");
g_ImGuiLogger->set_level(spdlog::level::trace);
}
#endif // !_TOOLS
/************************
* WINDOWS LOGGER SETUP *
@ -84,6 +92,7 @@ void SpdLog_Init(const bool bAnsiColor)
{
g_TermLogger->set_pattern("%v");
}
//g_TermLogger->set_level(spdlog::level::trace);
}
#ifndef _TOOLS

View File

@ -22,6 +22,11 @@ extern std::shared_ptr<spdlog::logger> g_ImGuiLogger;
extern std::shared_ptr<spdlog::logger> g_SuppementalToolsLogger;
#endif // _TOOLS
//-------------------------------------------------------------------------
// IMGUI CONSOLE SINK |
extern std::ostringstream g_LogStream;
extern std::shared_ptr<spdlog::sinks::ostream_sink_st> g_LogSink;
void SpdLog_Init(const bool bAnsiColor);
void SpdLog_Shutdown(void);

View File

@ -72,24 +72,21 @@ ImVec4 GetColorForContext(LogType_t type, eDLL_T context)
}
#endif // !DEDICATED && !_TOOLS
static const char* GetContextNameByIndex(eDLL_T context, size_t& numTotalChars, size_t& numAnsiChars, const bool ansiColor)
const char* GetContextNameByIndex(eDLL_T context, const bool ansiColor = false)
{
const int index = static_cast<int>(context);
const char* contextName;
int index = static_cast<int>(context);
const char* contextName = s_DefaultAnsiColor;
switch (context)
{
case eDLL_T::SCRIPT_SERVER:
contextName = s_ScriptAnsiColor[0];
numTotalChars = s_FullAnsiContextPrefixTextSize;
break;
case eDLL_T::SCRIPT_CLIENT:
contextName = s_ScriptAnsiColor[1];
numTotalChars = s_FullAnsiContextPrefixTextSize;
break;
case eDLL_T::SCRIPT_UI:
contextName = s_ScriptAnsiColor[2];
numTotalChars = s_FullAnsiContextPrefixTextSize;
break;
case eDLL_T::SERVER:
case eDLL_T::CLIENT:
@ -105,22 +102,17 @@ static const char* GetContextNameByIndex(eDLL_T context, size_t& numTotalChars,
case eDLL_T::SYSTEM_WARNING:
case eDLL_T::SYSTEM_ERROR:
contextName = s_DllAnsiColor[index];
numTotalChars = context >= eDLL_T::COMMON ? s_AnsiColorTextSize : s_FullAnsiContextPrefixTextSize;
break;
case eDLL_T::NONE:
default:
contextName = s_DefaultAnsiColor;
numTotalChars = s_AnsiColorTextSize;
break;
}
if (!ansiColor)
{
// Shift # chars to skip ANSI row.
contextName += s_AnsiColorTextSize;
numTotalChars -= s_AnsiColorTextSize;
contextName += sizeof(s_DefaultAnsiColor) - 1;
}
else
numAnsiChars = s_AnsiColorTextSize;
return contextName;
}
@ -155,16 +147,11 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
const char* pszUpTime = pszUptimeOverride ? pszUptimeOverride : Plat_GetProcessUpTime();
string message(pszUpTime);
const size_t contextTextStartIndex = message.length();
const bool bToConsole = (logLevel >= LogLevel_t::LEVEL_CONSOLE);
const bool bUseColor = (bToConsole && g_bSpdLog_UseAnsiClr);
size_t numTotalContextTextChars = 0;
size_t numAnsiContextChars = 0;
const char* pszContext = GetContextNameByIndex(context, numTotalContextTextChars, numAnsiContextChars, bUseColor);
message.append(pszContext, numTotalContextTextChars);
const char* pszContext = GetContextNameByIndex(context, bUseColor);
message.append(pszContext);
#if !defined (DEDICATED) && !defined (_TOOLS)
ImVec4 overlayColor = GetColorForContext(logType, context);
@ -179,9 +166,6 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
NOTE_UNUSED(pszLogger);
#endif // !_TOOLS
const size_t messageTextStartIndex = message.length();
size_t numMessageAnsiChars = 0;
//-------------------------------------------------------------------------
// Setup logger and context
//-------------------------------------------------------------------------
@ -194,7 +178,6 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
if (bUseColor)
{
message.append(g_svYellowF);
numMessageAnsiChars = g_svYellowF.length();
}
break;
case LogType_t::LOG_ERROR:
@ -204,7 +187,6 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
if (bUseColor)
{
message.append(g_svRedF);
numMessageAnsiChars = g_svRedF.length();
}
break;
#ifndef _TOOLS
@ -266,28 +248,12 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
if (bUseColor)
{
if (logType != LogType_t::LOG_ERROR)
{
if (numMessageAnsiChars > 0)
message.replace(messageTextStartIndex, numMessageAnsiChars, g_svRedF);
else
message.append(g_svRedF);
numMessageAnsiChars = g_svRedF.length();
}
message.append(g_svRedF);
}
}
else if (bUseColor && bWarning)
{
if (logType != LogType_t::LOG_ERROR)
{
if (numMessageAnsiChars > 0)
message.replace(messageTextStartIndex, numMessageAnsiChars, g_svYellowF);
else
message.append(g_svYellowF);
numMessageAnsiChars = g_svYellowF.length();
}
message.append(g_svYellowF);
}
}
#endif // !_TOOLS
@ -301,24 +267,9 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
{
g_TermLogger->debug(message);
// Remove ANSI rows if we have them, before emitting to file or over wire.
if (bUseColor)
{
// Start with the message first because else the indices will shift.
// The message colors comes after the context colors.
if (numMessageAnsiChars > 0)
{
message.erase(messageTextStartIndex, numMessageAnsiChars);
numMessageAnsiChars = 0;
}
if (numAnsiContextChars > 0)
{
message.erase(contextTextStartIndex, numAnsiContextChars);
numAnsiContextChars = 0;
}
// Remove anything else that was passed in as a format argument.
// Remove ANSI rows before emitting to file or over wire.
message = std::regex_replace(message, s_AnsiRowRegex, "");
}
}
@ -331,32 +282,38 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
// Output is always logged to the file.
std::shared_ptr<spdlog::logger> ntlogger = spdlog::get(pszLogger); // <-- Obtain by 'pszLogger'.
assert(ntlogger.get() != nullptr);
if (ntlogger)
ntlogger->debug(message);
ntlogger->debug(message);
if (bToConsole)
{
#ifndef CLIENT_DLL
if (!LoggedFromClient(context) && RCONServer()->ShouldSend(netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG))
{
RCONServer()->SendEncoded(formatted.c_str(), formatted.length(), pszUpTime, contextTextStartIndex, netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG,
RCONServer()->SendEncoded(formatted.c_str(), pszUpTime, netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG,
int(context), int(logType));
}
#endif // !CLIENT_DLL
#ifndef DEDICATED
g_Console.AddLog(message.c_str(), ImGui::ColorConvertFloat4ToU32(overlayColor));
g_ImGuiLogger->debug(message);
const string logStreamBuf = g_LogStream.str();
g_Console.AddLog(logStreamBuf.c_str(), ImGui::ColorConvertFloat4ToU32(overlayColor));
// We can only log to the in-game overlay console when the SDK has
// been fully initialized, due to the use of ConVar's.
if (g_bSdkInitialized && logLevel >= LogLevel_t::LEVEL_NOTIFY)
{
// Draw to mini console.
g_TextOverlay.AddLog(overlayContext, message.c_str(), (ssize_t)message.length());
g_TextOverlay.AddLog(overlayContext, logStreamBuf.c_str());
}
#endif // !DEDICATED
}
#ifndef DEDICATED
g_LogStream.str(string());
g_LogStream.clear();
#endif // !DEDICATED
#else
if (g_SuppementalToolsLogger)
{

View File

@ -47,7 +47,6 @@
#include <set>
#include <unordered_set>
#include <functional>
#include <charconv>
#include <smmintrin.h>

View File

@ -25,24 +25,6 @@
#include "thirdparty/curl/include/curl/curl.h"
// RapidJSON uses 32 bit size types. Size types are
// 64 bit wide on our target. Override it with ours.
// this must be done before the rapidjson.h include.
#define RAPIDJSON_NO_SIZETYPEDEFINE
namespace rapidjson { typedef ::std::size_t SizeType; }
#include "rapidjson/rapidjson.h"
#ifdef RAPIDJSON_USE_CUSTOM_ALLOCATOR
// Must be included before the RapidJSON includes
// as this replaces the default allocator. The new
// allocator takes SIMD alignment into account, but
// isn't strictly necessary when using RAPIDJSON_SIMD.
#include "tier2/jsonalloc.h"
#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<JSONAllocator>
#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<JSONAllocator>
#endif // RAPIDJSON_USE_CUSTOM_ALLOCATOR
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

View File

@ -1,19 +1,19 @@
#include "core/stdafx.h"
#include "core/termutil.h"
std::string g_svGreyF;
std::string g_svRedF;
std::string g_svGreenF;
std::string g_svBlueF;
std::string g_svYellowF;
const char* g_svGreyF = "";
const char* g_svRedF = "";
const char* g_svGreenF = "";
const char* g_svBlueF = "";
const char* g_svYellowF = "";
std::string g_svGreyB;
std::string g_svRedB;
std::string g_svGreenB;
std::string g_svBlueB;
std::string g_svYellowB;
const char* g_svGreyB = "";
const char* g_svRedB = "";
const char* g_svGreenB = "";
const char* g_svBlueB = "";
const char* g_svYellowB = "";
std::string g_svReset;
const char* g_svReset = "";
//-----------------------------------------------------------------------------
// Purpose: sets the global ansi escape sequences.

View File

@ -1,16 +1,16 @@
#pragma once
extern std::string g_svGreyF;
extern std::string g_svRedF;
extern std::string g_svGreenF;
extern std::string g_svBlueF;
extern std::string g_svYellowF;
extern const char* g_svGreyF;
extern const char* g_svRedF;
extern const char* g_svGreenF;
extern const char* g_svBlueF;
extern const char* g_svYellowF;
extern std::string g_svGreyB;
extern std::string g_svRedB;
extern std::string g_svGreenB;
extern std::string g_svBlueB;
extern std::string g_svYellowB;
extern const char* g_svGreyB;
extern const char* g_svRedB;
extern const char* g_svGreenB;
extern const char* g_svBlueB;
extern const char* g_svYellowB;
extern std::string g_svReset;
extern const char* g_svReset;
void AnsiColors_Init();

View File

@ -16,6 +16,7 @@
#include "public/studio.h"
CStudioFallbackHandler g_StudioMdlFallbackHandler;
#define IS_VALID_DATACACHE_HANDLE(cacheHandle) (cacheHandle && cacheHandle != DC_INVALID_HANDLE)
//-----------------------------------------------------------------------------
// Purpose: finds an MDL
@ -46,7 +47,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle
studiomodelcache_t* modelCache = studioData->GetModelCache();
// Store error and empty fallback models.
if (IsValidDataCacheHandle(modelCache))
if (IS_VALID_DATACACHE_HANDLE(modelCache))
{
studiohdr_t* const studioHdr = studioData->GetModelCache()->GetStudioHdr();
@ -66,7 +67,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle
if ((studioData->flags & nFlags))
{
if (IsValidDataCacheHandle(modelCache))
if (IS_VALID_DATACACHE_HANDLE(modelCache))
{
if (a3)
{
@ -84,7 +85,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle
studioanimcache_t* const animCache = studioData->GetAnimCache();
if (IsValidDataCacheHandle(animCache))
if (IS_VALID_DATACACHE_HANDLE(animCache))
{
studiohdr_t* const pStudioHdr = animCache->GetStudioHdr();
@ -157,7 +158,7 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* const cache, const MDLHandle_
studiomodelcache_t* const modelCache = pStudioData->GetModelCache();
if (IsValidDataCacheHandle(modelCache))
if (IS_VALID_DATACACHE_HANDLE(modelCache))
{
FindCachedMDL(cache, pStudioData, a4);
studioHdr = modelCache->GetStudioHdr();
@ -167,7 +168,7 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* const cache, const MDLHandle_
// Attempt to get studio header from anim cache.
studioanimcache_t* const animCache = pStudioData->GetAnimCache();
if (IsValidDataCacheHandle(animCache))
if (IS_VALID_DATACACHE_HANDLE(animCache))
{
studioHdr = animCache->GetStudioHdr();
}
@ -218,7 +219,7 @@ vcollide_t* CMDLCache::GetVCollide(CMDLCache* const cache, const MDLHandle_t han
{
studiomodelcache_t* const modelCache = cache->GetModelCache(handle);
if (!IsValidDataCacheHandle(modelCache))
if (!IS_VALID_DATACACHE_HANDLE(modelCache))
{
Warning(eDLL_T::ENGINE, "Attempted to load collision data on model \"%s\" with invalid studio data!\n", cache->GetModelName(handle));
return nullptr;
@ -247,7 +248,7 @@ void* CMDLCache::GetPhysicsGeometry(CMDLCache* const cache, const MDLHandle_t ha
{
studiomodelcache_t* const modelCache = cache->GetModelCache(handle);
if (!IsValidDataCacheHandle(modelCache))
if (!IS_VALID_DATACACHE_HANDLE(modelCache))
{
Warning(eDLL_T::ENGINE, "Attempted to load physics geometry on model \"%s\" with invalid studio data!\n", cache->GetModelName(handle));
return nullptr;
@ -277,7 +278,7 @@ studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* const cache, const MDLHand
const studiodata_t* studioData = nullptr; cache->GetStudioData(handle);
const studiomodelcache_t* modelCache = cache->GetModelCache(handle);
if (!IsValidDataCacheHandle(modelCache))
if (!IS_VALID_DATACACHE_HANDLE(modelCache))
{
if (!HasErrorModel())
{

View File

@ -138,7 +138,6 @@ add_sources( SOURCE_GROUP "Shared"
"shared/shared_rcon.h"
"shared/datablock.cpp"
"shared/datablock.h"
"shared/ents_shared.h"
)
if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" )
@ -162,8 +161,6 @@ add_sources( SOURCE_GROUP "GameUI"
"${ENGINE_SOURCE_DIR}/gameui/IBrowser.h"
"${ENGINE_SOURCE_DIR}/gameui/IConsole.cpp"
"${ENGINE_SOURCE_DIR}/gameui/IConsole.h"
"${ENGINE_SOURCE_DIR}/gameui/IStreamOverlay.cpp"
"${ENGINE_SOURCE_DIR}/gameui/IStreamOverlay.h"
"${ENGINE_SOURCE_DIR}/gameui/imgui_system.cpp"
"${ENGINE_SOURCE_DIR}/gameui/imgui_system.h"
@ -229,8 +226,6 @@ add_sources( SOURCE_GROUP "Public"
"${ENGINE_SOURCE_DIR}/public/networkvar.h"
"${ENGINE_SOURCE_DIR}/public/playerstate.h"
"${ENGINE_SOURCE_DIR}/public/netcon/INetCon.h"
# These probably need to go to 'bsplib' if we ever create that project.
"${ENGINE_SOURCE_DIR}/public/bspflags.h"
"${ENGINE_SOURCE_DIR}/public/bspfile.h"

View File

@ -6,27 +6,12 @@
//=============================================================================//
#include "core/stdafx.h"
#include "public/const.h"
#include "engine/host.h"
#include "engine/client/cl_ents_parse.h"
bool CL_CopyNewEntity(CEntityReadInfo* const u, unsigned int* const iClass, const int iSerialNum, bool* const pbError)
bool CL_CopyExistingEntity(__int64 a1, unsigned int* a2, char* a3)
{
// Similar to the issue in CL_CopyExistingEntity,
// except, only the lower bounds check was missing.
if (u->m_nNewEntity < NULL || u->m_nNewEntity >= MAX_EDICTS)
{
Host_Error("CL_CopyNewEntity: u.m_nNewEntity < 0 || u.m_nNewEntity >= MAX_EDICTS");
*pbError = true;
return false;
}
return v_CL_CopyNewEntity(u, iClass, iSerialNum, pbError);
}
bool CL_CopyExistingEntity(CEntityReadInfo* const u, unsigned int* const iClass, bool* const pbError)
{
if (u->m_nNewEntity < NULL || u->m_nNewEntity >= MAX_EDICTS)
int nNewEntity = *reinterpret_cast<int*>(a1 + 40);
if (nNewEntity >= MAX_EDICTS || nNewEntity < NULL)
{
// Value isn't sanitized in release builds for
// every game powered by the Source Engine 1
@ -35,11 +20,7 @@ bool CL_CopyExistingEntity(CEntityReadInfo* const u, unsigned int* const iClass,
// full-chain RCE exploit. We hook and perform
// sanity checks for the value of m_nNewEntity
// here to prevent this behavior from happening.
Host_Error("CL_CopyExistingEntity: u.m_nNewEntity < 0 || u.m_nNewEntity >= MAX_EDICTS");
*pbError = true;
return false;
}
return v_CL_CopyExistingEntity(u, iClass, pbError);
return v_CL_CopyExistingEntity(a1, a2, a3);
}

View File

@ -1,30 +1,24 @@
#ifndef CL_ENTS_PARSE_H
#define CL_ENTS_PARSE_H
#include "engine/shared/ents_shared.h"
inline bool(*v_CL_CopyNewEntity)(CEntityReadInfo* const u, unsigned int* const iClass, const int iSerialNum, bool* const pbError);
inline bool(*v_CL_CopyExistingEntity)(CEntityReadInfo* const u, unsigned int* const iClass, bool* const pbError);
inline bool(*v_CL_CopyExistingEntity)(__int64 a1, unsigned int* a2, char* a3);
bool CL_CopyNewEntity(CEntityReadInfo* const u, unsigned int* const iClass, const int iSerialNum, bool* const pbError);
bool CL_CopyExistingEntity(CEntityReadInfo* const u, unsigned int* const iClass, bool* const pbError);
bool CL_CopyExistingEntity(__int64 a1, unsigned int* a2, char* a3);
///////////////////////////////////////////////////////////////////////////////
class V_CL_Ents_Parse : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("CL_CopyNewEntity", v_CL_CopyNewEntity);
LogFunAdr("CL_CopyExistingEntity", v_CL_CopyExistingEntity);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("40 55 53 41 54 41 55 41 57 48 8D AC 24").GetPtr(v_CL_CopyNewEntity);
g_GameDll.FindPatternSIMD("40 53 48 83 EC 70 4C 63 51 28").GetPtr(v_CL_CopyExistingEntity);
}
virtual void GetVar(void) const { }
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const
{
DetourSetup(&v_CL_CopyNewEntity, &CL_CopyNewEntity, bAttach);
DetourSetup(&v_CL_CopyExistingEntity, &CL_CopyExistingEntity, bAttach);
}
};

View File

@ -73,7 +73,7 @@ void CRConClient::RunFrame(void)
{
if (IsInitialized() && IsConnected())
{
ConnectedNetConsoleData_s* pData = GetData();
CConnectedNetConsoleData* pData = GetData();
Assert(pData != nullptr);
if (pData)
@ -105,7 +105,7 @@ void CRConClient::Disconnect(const char* szReason)
// Input : *pMsgBug -
// nMsgLen -
//-----------------------------------------------------------------------------
bool CRConClient::ProcessMessage(const byte* const pMsgBuf, const u32 nMsgLen)
bool CRConClient::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
{
netcon::response response;
@ -162,13 +162,13 @@ void CRConClient::RequestConsoleLog(const bool bWantLog)
// sending logs will cause the print func to get called recursively forever.
Assert(!(bWantLog && IsRemoteLocal()));
const char* const szEnable = bWantLog ? "1" : "0";
const char* szEnable = bWantLog ? "1" : "0";
const SocketHandle_t hSocket = GetSocket();
vector<byte> vecMsg;
const bool ret = Serialize(vecMsg, "", 0, szEnable, 1, netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
vector<char> vecMsg;
bool ret = Serialize(vecMsg, "", szEnable, netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
if (ret && !Send(hSocket, vecMsg.data(), (u32)vecMsg.size()))
if (ret && !Send(hSocket, vecMsg.data(), int(vecMsg.size())))
{
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
}
@ -177,16 +177,14 @@ void CRConClient::RequestConsoleLog(const bool bWantLog)
//-----------------------------------------------------------------------------
// Purpose: serializes input
// Input : *svReqBuf -
// nReqMsgLen -
// *svReqVal -
// nReqValLen -
// request_t -
// Output : serialized results as string
//-----------------------------------------------------------------------------
bool CRConClient::Serialize(vector<byte>& vecBuf, const char* szReqBuf, const size_t nReqMsgLen,
const char* szReqVal, const size_t nReqValLen, const netcon::request_e requestType) const
bool CRConClient::Serialize(vector<char>& vecBuf, const char* szReqBuf,
const char* szReqVal, const netcon::request_e requestType) const
{
return NetconClient_Serialize(this, vecBuf, szReqBuf, nReqMsgLen, szReqVal, nReqValLen, requestType,
return NetconClient_Serialize(this, vecBuf, szReqBuf, szReqVal, requestType,
rcon_encryptframes.GetBool(), rcon_debug.GetBool());
}
@ -194,7 +192,7 @@ bool CRConClient::Serialize(vector<byte>& vecBuf, const char* szReqBuf, const si
// Purpose: retrieves the remote socket
// Output : SOCKET_ERROR (-1) on failure
//-----------------------------------------------------------------------------
ConnectedNetConsoleData_s* CRConClient::GetData(void)
CConnectedNetConsoleData* CRConClient::GetData(void)
{
return NetconShared_GetConnData(this, 0);
}
@ -323,7 +321,7 @@ static void RCON_CmdQuery_f(const CCommand& args)
}
else if (RCONClient()->IsConnected())
{
vector<byte> vecMsg;
vector<char> vecMsg;
bool bSuccess = false;
const SocketHandle_t hSocket = RCONClient()->GetSocket();
@ -331,10 +329,7 @@ static void RCON_CmdQuery_f(const CCommand& args)
{
if (argCount > 2)
{
const char* const pass = args.Arg(2);
const size_t passLen = strlen(pass);
bSuccess = RCONClient()->Serialize(vecMsg, pass, passLen, "", 0, netcon::request_e::SERVERDATA_REQUEST_AUTH);
bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", netcon::request_e::SERVERDATA_REQUEST_AUTH);
}
else // Need at least 3 arguments for a password in PASS command (rcon PASS <password>)
{
@ -344,7 +339,7 @@ static void RCON_CmdQuery_f(const CCommand& args)
if (bSuccess)
{
RCONClient()->Send(hSocket, vecMsg.data(), (u32)vecMsg.size());
RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size()));
}
return;
@ -355,16 +350,10 @@ static void RCON_CmdQuery_f(const CCommand& args)
return;
}
const char* const request = args.Arg(1);
const size_t requestLen = strlen(request);
const char* const value = args.ArgS();
const size_t valueLen = strlen(value);
bSuccess = RCONClient()->Serialize(vecMsg, request, requestLen, value, valueLen, netcon::request_e::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(), (u32)vecMsg.size());
RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size()));
}
return;
}

View File

@ -15,10 +15,10 @@ public:
void RunFrame(void);
virtual void Disconnect(const char* szReason = nullptr) override;
virtual bool ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen) override;
virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override;
bool Serialize(vector<byte>& vecBuf, const char* szReqBuf, const size_t nReqMsgLen,
const char* szReqVal, const size_t nReqValLen, const netcon::request_e requestType) const;
bool Serialize(vector<char>& vecBuf, const char* szReqBuf,
const char* szReqVal, const netcon::request_e requestType) const;
void RequestConsoleLog(const bool bWantLog);
bool ShouldReceive(void);
@ -27,7 +27,7 @@ public:
bool IsInitialized(void) const;
bool IsConnected(void);
ConnectedNetConsoleData_s* GetData(void);
CConnectedNetConsoleData* GetData(void);
SocketHandle_t GetSocket(void);
private:

View File

@ -43,12 +43,12 @@ static void SetName_f(const CCommand& args)
const size_t nLen = strlen(pszName);
if (nLen >= MAX_PERSONA_NAME_LEN)
if (nLen > MAX_PERSONA_NAME_LEN)
return;
// Update nucleus name.
strncpy(g_PersonaName, pszName, nLen+1);
name_cvar->SetValue(pszName);
memset(g_PersonaName, '\0', MAX_PERSONA_NAME_LEN);
strncpy(g_PersonaName, pszName, nLen);
}
static void Reconnect_f(const CCommand& args)
{
@ -234,7 +234,6 @@ bool CClientState::_ProcessStringCmd(CClientState* thisptr, NET_StringCmd* msg)
if (thisptr_ADJ->m_bRestrictServerCommands
#ifndef CLIENT_DLL
// Don't restrict commands if we are on our own listen server
&& !g_pServer->IsActive()
#endif // !CLIENT_DLL
)

View File

@ -158,5 +158,5 @@ static bool HK_ProcessDataBlock(ClientDataBlockReceiver* receiver, const double
void VClientDataBlockReceiver::Detour(const bool bAttach) const
{
DetourSetup(&ClientDataBlockReceiver__ProcessDataBlock, HK_ProcessDataBlock, bAttach);
DetourAttach(&ClientDataBlockReceiver__ProcessDataBlock, HK_ProcessDataBlock);
}

View File

@ -15,7 +15,6 @@
#include "engine/host_cmd.h"
#include "engine/cmodel_bsp.h"
#include "rtech/rson.h"
#include "rtech/pak/pakstate.h"
#include "rtech/pak/pakparse.h"
#include "rtech/pak/paktools.h"
@ -31,23 +30,23 @@
CUtlVector<CUtlString> g_InstalledMaps;
CFmtStrN<MAX_MAP_NAME> s_CurrentLevelName;
static CustomPakData_s s_customPakData;
static CustomPakData_t s_customPakData;
static KeyValues* s_pLevelSetKV = nullptr;
//-----------------------------------------------------------------------------
// Purpose: load a custom pak and add it to the list
//-----------------------------------------------------------------------------
PakHandle_t CustomPakData_s::LoadAndAddPak(const char* const pakFile)
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 limit of %d!\n", pakFile, 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 PAK_INVALID_HANDLE;
}
const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0);
// failure, don't add; return the invalid handle.
// failure, don't add and return the invalid handle.
if (pakId == PAK_INVALID_HANDLE)
return pakId;
@ -56,72 +55,30 @@ PakHandle_t CustomPakData_s::LoadAndAddPak(const char* const pakFile)
}
//-----------------------------------------------------------------------------
// Purpose: unload a custom pak
// NOTE : the array must be kept contiguous; this means that the last pak in
// the array should always be unloaded fist!
// Purpose: unloads all active custom pak handles
//-----------------------------------------------------------------------------
void CustomPakData_s::UnloadAndRemovePak(const int index)
void CustomPakData_t::UnloadAndRemoveAll()
{
const PakHandle_t pakId = handles[index];
assert(pakId != PAK_INVALID_HANDLE); // invalid handles should not be inserted
g_pakLoadApi->UnloadAsync(pakId);
handles[index] = PAK_INVALID_HANDLE;
numHandles--;
}
//-----------------------------------------------------------------------------
// Purpose: preload a custom pak; this keeps it available throughout the
// duration of the process, unless manually removed by user.
//-----------------------------------------------------------------------------
PakHandle_t CustomPakData_s::PreloadAndAddPak(const char* const pakFile)
{
// this must never be called after a non-preloaded pak has been added!
// preloaded paks must always appear before custom user requested paks
// due to the unload order: user-requested -> preloaded -> sdk -> core.
assert(handles[CustomPakData_s::PAK_TYPE_COUNT+numPreload] == PAK_INVALID_HANDLE);
const PakHandle_t pakId = LoadAndAddPak(pakFile);
if (pakId != PAK_INVALID_HANDLE)
numPreload++;
return pakId;
}
//-----------------------------------------------------------------------------
// Purpose: unloads all non-preloaded custom pak handles
//-----------------------------------------------------------------------------
void CustomPakData_s::UnloadAndRemoveNonPreloaded()
{
// Preloaded paks should not be unloaded here, but only right before sdk /
// Base SDK paks should not be unloaded here, but only right before base
// engine paks are unloaded. Only unload user requested and level settings
// paks from here. Unload them in reverse order, the last pak loaded should
// be the first one to be unloaded.
for (int n = numHandles-1; n >= CustomPakData_s::PAK_TYPE_COUNT + numPreload; n--)
// paks from here. Also, ideally this loop runs in reverse, but the engine
// does not support that as it would crash when paks are unloaded that way.
for (size_t i = CustomPakData_t::PAK_TYPE_COUNT, n = numHandles; i < n; i++)
{
UnloadAndRemovePak(n);
}
}
const PakHandle_t pakId = handles[i];
assert(pakId != PAK_INVALID_HANDLE); // invalid handles should not be inserted
//-----------------------------------------------------------------------------
// Purpose: unloads all preloaded custom pak handles
//-----------------------------------------------------------------------------
void CustomPakData_s::UnloadAndRemovePreloaded()
{
// Unload them in reverse order, the last pak loaded should be the first
// one to be unloaded.
for (; numPreload > 0; numPreload--)
{
UnloadAndRemovePak(CustomPakData_s::PAK_TYPE_COUNT + (numPreload-1));
g_pakLoadApi->UnloadAsync(pakId);
handles[i] = PAK_INVALID_HANDLE;
numHandles--;
}
}
//-----------------------------------------------------------------------------
// Purpose: loads the base SDK pak file by type
//-----------------------------------------------------------------------------
PakHandle_t CustomPakData_s::LoadBasePak(const char* const pakFile, const PakType_e type)
PakHandle_t CustomPakData_t::LoadBasePak(const char* const pakFile, const EPakType type)
{
const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0);
@ -135,7 +92,7 @@ PakHandle_t CustomPakData_s::LoadBasePak(const char* const pakFile, const PakTyp
//-----------------------------------------------------------------------------
// Purpose: unload the SDK base pak file by type
//-----------------------------------------------------------------------------
void CustomPakData_s::UnloadBasePak(const PakType_e type)
void CustomPakData_t::UnloadBasePak(const EPakType type)
{
const PakHandle_t pakId = handles[type];
@ -206,71 +163,10 @@ void Mod_GetAllInstalledMaps()
}
}
//-----------------------------------------------------------------------------
// Purpose: returns whether the load job for given pak id is finished
//-----------------------------------------------------------------------------
static bool Mod_IsPakLoadFinished(const PakHandle_t pakId)
{
if (pakId == PAK_INVALID_HANDLE)
return true;
const PakLoadedInfo_s* const pli = Pak_GetPakInfo(pakId);
if (pli->handle != pakId)
return false;
const PakStatus_e stat = pli->status;
if (stat != PakStatus_e::PAK_STATUS_LOADED &&
stat != PakStatus_e::PAK_STATUS_ERROR)
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: returns whether the load job for custom pak batch for given common
// pak is finished
//-----------------------------------------------------------------------------
static bool CustomPakData_IsPakLoadFinished(const CommonPakData_s::PakType_e commonType)
{
switch (commonType)
{
case CommonPakData_s::PakType_e::PAK_TYPE_UI_GM:
#ifndef DEDICATED
return Mod_IsPakLoadFinished(s_customPakData.handles[CustomPakData_s::PakType_e::PAK_TYPE_UI_SDK]);
#else // Dedicated doesn't load UI paks.
return true;
#endif // DEDICATED
case CommonPakData_s::PakType_e::PAK_TYPE_COMMON:
return true;
case CommonPakData_s::PakType_e::PAK_TYPE_COMMON_GM:
return Mod_IsPakLoadFinished(s_customPakData.handles[CustomPakData_s::PakType_e::PAK_TYPE_COMMON_SDK]);
case CommonPakData_s::PakType_e::PAK_TYPE_LOBBY:
// Check for preloaded paks at this stage (loaded from preload.rson).
for (int i = 0, n = s_customPakData.numPreload; i < n; i++)
{
if (!Mod_IsPakLoadFinished(s_customPakData.handles[CustomPakData_s::PAK_TYPE_COUNT + i]))
return false;
}
break;
case CommonPakData_s::PakType_e::PAK_TYPE_LEVEL:
// Check for extra level paks at this stage (loaded from <levelname>.kv).
for (int i = CustomPakData_s::PAK_TYPE_COUNT + s_customPakData.numPreload, n = s_customPakData.numHandles; i < n; i++)
{
if (!Mod_IsPakLoadFinished(s_customPakData.handles[i]))
return false;
}
break;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: processes queued pak files
//-----------------------------------------------------------------------------
static void Mod_QueuedPakCacheFrame()
void Mod_QueuedPakCacheFrame()
{
#ifndef DEDICATED
bool bUnconnected = !(*g_pClientState_Shifted)->IsConnected();
@ -332,11 +228,11 @@ static void Mod_QueuedPakCacheFrame()
const int numToProcess = startIndex;
if (startIndex < CommonPakData_s::PAK_TYPE_COUNT)
if (startIndex <= CommonPakData_t::PAK_TYPE_LEVEL)
{
bool keepLoaded = false;
int numLeftToProcess = 4;
CommonPakData_s* data = &g_commonPakData[4];
CommonPakData_t* data = &g_commonPakData[4];
do
{
@ -365,26 +261,32 @@ static void Mod_QueuedPakCacheFrame()
switch (numLeftToProcess)
{
#ifndef DEDICATED
case CommonPakData_s::PakType_e::PAK_TYPE_UI_GM:
s_customPakData.UnloadBasePak(CustomPakData_s::PakType_e::PAK_TYPE_UI_SDK);
case CommonPakData_t::PAK_TYPE_UI_GM:
s_customPakData.UnloadBasePak(CustomPakData_t::PAK_TYPE_UI_SDK);
break;
#endif // !DEDICATED
case CommonPakData_s::PakType_e::PAK_TYPE_COMMON:
case CommonPakData_t::PAK_TYPE_COMMON:
g_StudioMdlFallbackHandler.Clear();
break;
case CommonPakData_s::PakType_e::PAK_TYPE_COMMON_GM:
s_customPakData.UnloadBasePak(CustomPakData_s::PakType_e::PAK_TYPE_COMMON_SDK);
case CommonPakData_t::PAK_TYPE_COMMON_GM:
s_customPakData.UnloadBasePak(CustomPakData_t::PAK_TYPE_COMMON_SDK);
break;
case CommonPakData_t::PAK_TYPE_LOBBY:
s_customPakData.basePaksLoaded = false;
break;
default:
break;
}
if (numLeftToProcess == CommonPakData_s::PakType_e::PAK_TYPE_LEVEL)
g_pakLoadApi->UnloadAsync(data->pakId);
if (numLeftToProcess == CommonPakData_t::PAK_TYPE_LEVEL)
{
Mod_UnloadLevelPaks(); // Unload mod pak files.
Mod_UnloadPakFile(); // Unload mod pak files.
if (s_pLevelSetKV)
{
@ -393,14 +295,6 @@ static void Mod_QueuedPakCacheFrame()
s_pLevelSetKV = nullptr;
}
}
g_pakLoadApi->UnloadAsync(data->pakId);
if (numLeftToProcess == CommonPakData_s::PakType_e::PAK_TYPE_LOBBY)
{
Mod_UnloadPreloadedPaks();
s_customPakData.basePaksLoaded = false;
}
}
if (status && (unsigned int)(status - 13) > 1)
@ -417,7 +311,7 @@ static void Mod_QueuedPakCacheFrame()
}
*g_pPakPrecacheJobFinished = true;
CommonPakData_s* commonData = g_commonPakData;
CommonPakData_t* commonData = g_commonPakData;
int it = 0;
@ -441,7 +335,7 @@ static void Mod_QueuedPakCacheFrame()
} while (c);
if (!v20)
goto CHECK_LOAD_STATUS;
goto CHECK_FOR_FAILURE;
V_strncpy(name, commonData->basePakName, MAX_PATH);
@ -476,9 +370,9 @@ static void Mod_QueuedPakCacheFrame()
if (ThreadInMainThread())
{
if (*g_bPakFifoLockAcquiredInMainThread)
if (*g_bPakFifoLockAcquired)
{
*g_bPakFifoLockAcquiredInMainThread = false;
*g_bPakFifoLockAcquired = 0;
JT_ReleaseFifoLock(pakFifoLock);
}
}
@ -497,85 +391,38 @@ static void Mod_QueuedPakCacheFrame()
}
}
if (it == CommonPakData_s::PakType_e::PAK_TYPE_LOBBY)
{
Mod_PreloadPaks();
if (it == CommonPakData_t::PAK_TYPE_LOBBY)
s_customPakData.basePaksLoaded = true;
if (s_customPakData.basePaksLoaded && !s_customPakData.levelResourcesLoaded)
{
Mod_PreloadLevelPaks(s_CurrentLevelName.String());
s_customPakData.levelResourcesLoaded = true;
}
commonData->pakId = g_pakLoadApi->LoadAsync(name, AlignedMemAlloc(), 4, 0);
if (it == CommonPakData_s::PakType_e::PAK_TYPE_LEVEL)
{
Mod_LoadLevelPaks(s_CurrentLevelName.String());
s_customPakData.levelResourcesLoaded = true;
}
#ifndef DEDICATED
if (it == CommonPakData_s::PakType_e::PAK_TYPE_UI_GM)
s_customPakData.LoadBasePak("ui_sdk.rpak", CustomPakData_s::PakType_e::PAK_TYPE_UI_SDK);
else
if (it == CommonPakData_t::PAK_TYPE_UI_GM)
s_customPakData.LoadBasePak("ui_sdk.rpak", CustomPakData_t::PAK_TYPE_UI_SDK);
#endif // !DEDICATED
if (it == CommonPakData_s::PakType_e::PAK_TYPE_COMMON_GM)
s_customPakData.LoadBasePak("common_sdk.rpak", CustomPakData_s::PakType_e::PAK_TYPE_COMMON_SDK);
if (it == CommonPakData_t::PAK_TYPE_COMMON_GM)
s_customPakData.LoadBasePak("common_sdk.rpak", CustomPakData_t::PAK_TYPE_COMMON_SDK);
CHECK_LOAD_STATUS:
CHECK_FOR_FAILURE:
if (!Mod_IsPakLoadFinished(commonData->pakId) || !CustomPakData_IsPakLoadFinished(CommonPakData_s::PakType_e(it)))
*g_pPakPrecacheJobFinished = false;
goto LOOP_AGAIN_OR_FINISH;
}
//-----------------------------------------------------------------------------
// Purpose: preload paks in list and keeps them active throughout level changes
//-----------------------------------------------------------------------------
void Mod_PreloadPaks()
{
static const char* const preloadFile = "paks/preload.rson";
bool parseFailure = false;
RSON::Node_t* const rson = RSON::LoadFromFile(preloadFile, "GAME", &parseFailure);
if (!rson)
if (commonData->pakId != PAK_INVALID_HANDLE)
{
if (parseFailure)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "%s: failure parsing file '%s'\n", __FUNCTION__, preloadFile);
else
const PakLoadedInfo_s* const pli = Pak_GetPakInfo(commonData->pakId);
if (pli->handle != commonData->pakId || ((pli->status - 9) & 0xFFFFFFFB) != 0)
{
Warning(eDLL_T::ENGINE, "%s: could not load file '%s'\n", __FUNCTION__, preloadFile);
return; // No preload file, thus no error. Warn and return out.
*g_pPakPrecacheJobFinished = false;
return;
}
}
static const char* const arrayName = "Paks";
const RSON::Field_t* const key = rson->FindKey(arrayName);
if (!key)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "%s: missing array key \"%s\" in file '%s'\n", __FUNCTION__, arrayName, preloadFile);
if ((key->m_Node.m_Type != (RSON::eFieldType::RSON_ARRAY | RSON::eFieldType::RSON_STRING)) &&
(key->m_Node.m_Type != (RSON::eFieldType::RSON_ARRAY | RSON::eFieldType::RSON_VALUE)))
{
Error(eDLL_T::ENGINE, EXIT_FAILURE, "%s: expected an array of strings in file '%s'\n", __FUNCTION__, preloadFile);
}
for (int i = 0; i < key->m_Node.m_nValueCount; i++)
{
const RSON::Value_t* const value = key->m_Node.GetArrayValue(i);
s_customPakData.PreloadAndAddPak(value->pszString);
}
RSON_Free(rson, AlignedMemAlloc());
AlignedMemAlloc()->Free(rson);
}
//-----------------------------------------------------------------------------
// Purpose: unloads all preloaded paks
//-----------------------------------------------------------------------------
void Mod_UnloadPreloadedPaks()
{
s_customPakData.UnloadAndRemovePreloaded();
goto LOOP_AGAIN_OR_FINISH;
}
//-----------------------------------------------------------------------------
@ -620,10 +467,10 @@ KeyValues* Mod_GetLevelSettings(const char* const pszLevelName)
}
//-----------------------------------------------------------------------------
// Purpose: loads paks specified inside the level settings file
// Input : *pszLevelName -
// Purpose: loads required pakfile assets for specified BSP level
// Input : &svSetFile -
//-----------------------------------------------------------------------------
void Mod_LoadLevelPaks(const char* const pszLevelName)
void Mod_PreloadLevelPaks(const char* const pszLevelName)
{
KeyValues* const pSettingsKV = Mod_GetLevelSettings(pszLevelName);
@ -651,11 +498,11 @@ void Mod_LoadLevelPaks(const char* const pszLevelName)
}
//-----------------------------------------------------------------------------
// Purpose: unloads all paks loaded by the level settings file
// Purpose: unloads all pakfiles loaded by the SDK
//-----------------------------------------------------------------------------
void Mod_UnloadLevelPaks()
void Mod_UnloadPakFile(void)
{
s_customPakData.UnloadAndRemoveNonPreloaded();
s_customPakData.UnloadAndRemoveAll();
g_StudioMdlFallbackHandler.ClearBadModelHandleCache();
g_StudioMdlFallbackHandler.ClearSuppresionList();

View File

@ -12,9 +12,9 @@ class KeyValues;
// loads for a level, this is used for load/unload management during level
// changes or engine shutdown
//-----------------------------------------------------------------------------
struct CommonPakData_s
struct CommonPakData_t
{
enum PakType_e
enum EPakType
{
// the UI pak assigned to the current gamemode (range in GameMode_t)
PAK_TYPE_UI_GM = 0,
@ -32,7 +32,7 @@ struct CommonPakData_s
PAK_TYPE_COUNT
};
CommonPakData_s()
CommonPakData_t()
{
Reset();
}
@ -62,9 +62,9 @@ struct CommonPakData_s
// loaded with the settings KV for that level, these paks are loaded after the
// common paks are loaded, but unloaded before the common paks are unloaded
//-----------------------------------------------------------------------------
struct CustomPakData_s
struct CustomPakData_t
{
enum PakType_e
enum EPakType
{
// the pak that loads after CommonPakData_t::PAK_TYPE_UI_GM has loaded, and
// unloads before CommonPakData_t::PAK_TYPE_UI_GM gets unloaded
@ -83,10 +83,10 @@ struct CustomPakData_s
// 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_LOADED_PAKS - CommonPakData_s::PAK_TYPE_COUNT)
MAX_CUSTOM_PAKS = (PAK_MAX_LOADED_PAKS - CommonPakData_t::PAK_TYPE_COUNT)
};
CustomPakData_s()
CustomPakData_t()
{
for (size_t i = 0; i < V_ARRAYSIZE(handles); i++)
{
@ -95,40 +95,30 @@ struct CustomPakData_s
// the first # handles are reserved for base SDK paks
numHandles = PAK_TYPE_COUNT;
numPreload = 0;
levelResourcesLoaded = false;
basePaksLoaded = false;
}
PakHandle_t LoadAndAddPak(const char* const pakFile);
PakHandle_t PreloadAndAddPak(const char* const pakFile);
void UnloadAndRemoveAll();
void UnloadAndRemoveNonPreloaded();
void UnloadAndRemovePreloaded();
PakHandle_t LoadBasePak(const char* const pakFile, const EPakType type);
void UnloadBasePak(const EPakType type);
PakHandle_t LoadBasePak(const char* const pakFile, const PakType_e type);
void UnloadBasePak(const PakType_e type);
private:
void UnloadAndRemovePak(const int index);
public:
// Pak handles that have been loaded with the level
// from within the level settings KV (located in
// scripts/levels/settings/*.kv). On level unload,
// each pak listed in this vector gets unloaded.
PakHandle_t handles[MAX_CUSTOM_PAKS];
int numHandles;
int numPreload;
size_t numHandles;
bool levelResourcesLoaded;
bool basePaksLoaded;
};
// array size = CommonPakData_t::PAK_TYPE_COUNT
inline CommonPakData_s* g_commonPakData;
inline CommonPakData_t* g_commonPakData;
inline void(*v_Mod_LoadPakForMap)(const char* szLevelName);
inline void(*v_Mod_QueuedPakCacheFrame)(void);
@ -141,14 +131,11 @@ inline void(*Mod_UnloadPendingAndPrecacheRequestedPaks)(void);
extern CUtlVector<CUtlString> g_InstalledMaps;
extern CThreadMutex g_InstalledMapsMutex;
void Mod_PreloadPaks();
void Mod_UnloadPreloadedPaks();
bool Mod_LevelHasChanged(const char* pszLevelName);
void Mod_GetAllInstalledMaps();
KeyValues* Mod_GetLevelSettings(const char* pszLevelName);
void Mod_LoadLevelPaks(const char* pszLevelName);
void Mod_UnloadLevelPaks(void);
void Mod_PreloadLevelPaks(const char* pszLevelName);
void Mod_UnloadPakFile(void);
///////////////////////////////////////////////////////////////////////////////

View File

@ -78,7 +78,7 @@ void _Host_RunFrame(void* unused, float time)
return v_Host_RunFrame(unused, time);
}
void Host_Error(const char* const error, ...)
void _Host_Error(const char* error, ...)
{
char buf[1024];
{/////////////////////////////
@ -102,6 +102,6 @@ void VHost::Detour(const bool bAttach) const
DetourSetup(&v_Host_CountRealTimePackets, &Host_CountRealTimePackets, bAttach);
#ifndef DEDICATED // Dedicated already logs this!
DetourSetup(&v_Host_Error, &Host_Error, bAttach);
DetourSetup(&v_Host_Error, &_Host_Error, bAttach);
#endif // !DEDICATED
}

View File

@ -15,8 +15,6 @@ inline bool* host_initialized = nullptr;
inline float* host_frametime_unbounded = nullptr;
inline float* host_frametime_stddeviation = nullptr;
void Host_Error(const char* const error, ...);
class CCommonHostState
{
public:

View File

@ -1,6 +1,5 @@
#include "core/stdafx.h"
#include "tier0/commandline.h"
#include "rtech/pak/pakstate.h"
#include "host_cmd.h"
#include "common.h"
#include "client/client.h"
@ -8,60 +7,6 @@
#include "windows/id3dx.h"
#endif // !DEDICATED
static void DoNothing(){};
static const char* const s_paksToLoad[] =
{
// Used to store assets that must be loaded after common_early.rpak, but
// before common.rpak is being loaded. One use case is to preserve the
// fixed linked list structure for the player settings layouts, we must
// load SDK layouts before common.rpak as the Game DLL expects the linked
// list to be ordered in a specific manner that is determined by bakery.
"common_roots.rpak",
#ifndef DEDICATED
// Used to load UI assets associated with the main menu.
"ui_mainmenu.rpak"
#endif // !DEDICATED
};
/*
==================
Host_SetupUIMaterials
setup and initialize
UI materials
==================
*/
static void Host_SetupUIMaterials()
{
// Don't sync during video init as this is where this function is called
// from. We restore the function pointer after we loaded the pak file.
void* const oldSyncFn = g_pakGlobals->threadSyncFunc;
g_pakGlobals->threadSyncFunc = DoNothing;
for (size_t i = 0; i < V_ARRAYSIZE(s_paksToLoad); i++)
{
const char* const pakFileName = s_paksToLoad[i];
// NOTE: make sure to wait for the async load request, as these paks
// must be loaded before we continue processing anything else.
const PakHandle_t pakHandle = g_pakLoadApi->LoadAsyncAndWait(pakFileName, AlignedMemAlloc(), 3, DoNothing);
if (pakHandle == PAK_INVALID_HANDLE)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Failed to load pak file '%s'\n", pakFileName);
}
g_pakGlobals->threadSyncFunc = oldSyncFn;
// For dedicated, we shouldn't continue with setting up ui materials.
// Return out here. This is the only place we can reliably load core
// paks directly after common_early.rpak and ui.rpak without having
// the engine do anything in between.
#ifndef DEDICATED
v_Host_SetupUIMaterials();
#endif // !DEDICATED
}
/*
==================
Host_Shutdown
@ -70,7 +15,7 @@ Host_Shutdown
systems
==================
*/
static void Host_Shutdown()
void Host_Shutdown()
{
#ifndef DEDICATED
DirectX_Shutdown();
@ -86,7 +31,7 @@ Host_Status_PrintClient
to console
==================
*/
static void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (const char* fmt, ...))
void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (const char* fmt, ...))
{
CNetChan* nci = client->GetNetChan();
const char* state = "challenging";
@ -100,7 +45,7 @@ static void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*p
if (nci != NULL)
{
print("# %hu \"%s\" %llu %s %i %i %s %d\n",
print("# %i \"%s\" %llu %s %i %i %s %d\n",
client->GetHandle(), client->GetServerName(), client->GetNucleusID(), COM_FormatSeconds(static_cast<int>(nci->GetTimeConnected())),
static_cast<int>(1000.0f * nci->GetAvgLatency(FLOW_OUTGOING)), static_cast<int>(100.0f * nci->GetAvgLoss(FLOW_INCOMING)), state, nci->GetDataRate());
@ -111,7 +56,7 @@ static void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*p
}
else
{
print("#%2hu \"%s\" %llu %s\n", client->GetHandle(), client->GetServerName(), client->GetNucleusID(), state);
print("#%2i \"%s\" %llu %s\n", client->GetHandle(), client->GetServerName(), client->GetNucleusID(), state);
}
//print("\n");
@ -125,7 +70,7 @@ DFS_InitializeFeatureFlagDefinitions
flag definitions
==================
*/
static bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags)
bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags)
{
if (CommandLine()->CheckParm("-nodfs"))
return false;
@ -136,7 +81,6 @@ static bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags)
///////////////////////////////////////////////////////////////////////////////
void VHostCmd::Detour(const bool bAttach) const
{
DetourSetup(&v_Host_SetupUIMaterials, &Host_SetupUIMaterials, bAttach);
DetourSetup(&v_Host_Shutdown, &Host_Shutdown, bAttach);
DetourSetup(&v_Host_Status_PrintClient, &Host_Status_PrintClient, bAttach);
DetourSetup(&v_DFS_InitializeFeatureFlagDefinitions, &DFS_InitializeFeatureFlagDefinitions, bAttach);

View File

@ -19,11 +19,8 @@ extern EngineParms_t* g_pEngineParms;
/* ==== HOST ============================================================================================================================================================ */
inline void(*v_Host_Init)();
#ifndef DEDICATED
inline void(*v_Host_Init_DuringVideo)(bool* bDedicated);
inline void(*v_Host_Init_PostVideo)(bool* bDedicated);
#endif // !DEDICATED
inline void(*v_Host_SetupUIMaterials)();
inline void(*v_Host_Shutdown)();
inline bool(*v_Host_NewGame)(char* pszMapName, char* pszMapGroup, bool bLoadGame, char bBackground, LARGE_INTEGER PerformanceCount);
inline void(*v_Host_Disconnect)(bool bShowMainMenu);
@ -41,11 +38,8 @@ class VHostCmd : public IDetour
virtual void GetAdr(void) const
{
LogFunAdr("Host_Init", v_Host_Init);
#ifndef DEDICATED
LogFunAdr("Host_Init_DuringVideo", v_Host_Init_DuringVideo);
LogFunAdr("Host_Init_PostVideo", v_Host_Init_PostVideo);
#endif // !DEDICATED
LogFunAdr("Host_SetupUIMaterials", v_Host_SetupUIMaterials);
LogFunAdr("Host_Shutdown", v_Host_Shutdown);
LogFunAdr("Host_Disconnect", v_Host_Disconnect);
LogFunAdr("Host_NewGame", v_Host_NewGame);
@ -59,14 +53,11 @@ class VHostCmd : public IDetour
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("88 4C 24 08 53 55 56 57 48 83 EC 68").GetPtr(v_Host_Init);
#ifndef DEDICATED
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9").GetPtr(v_Host_Init_DuringVideo);
g_GameDll.FindPatternSIMD("48 8B C4 41 56 48 81 EC ?? ?? ?? ?? 45 33 F6").GetPtr(v_Host_Init_PostVideo);
#endif // !DEDICATED
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 8D 3D").GetPtr(v_Host_SetupUIMaterials);
g_GameDll.FindPatternSIMD("48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 ?? ?? F2 0F 10 05 ?? ?? ?? 0B").GetPtr(v_Host_NewGame);
g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 0F B6 D9").GetPtr(v_Host_Disconnect);
g_GameDll.FindPatternSIMD("40 56 57 41 56 48 81 EC ?? ?? ?? ??").GetPtr(v_Host_ChangeLevel);
g_GameDll.FindPatternSIMD("48 8B C4 41 56 48 81 EC ?? ?? ?? ?? 45 33 F6").GetPtr(v_Host_Init_PostVideo);
g_GameDll.FindPatternSIMD("48 8B C4 48 83 EC ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 8B 15 ?? ?? ?? ??").GetPtr(v_Host_Shutdown);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 60 48 8B A9 ?? ?? ?? ??").GetPtr(v_Host_Status_PrintClient);

View File

@ -63,9 +63,8 @@ static ConVar host_autoReloadRate("host_autoReloadRate", "0", FCVAR_RELEASE, "Ti
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
ConVar hostdesc("hostdesc", "", FCVAR_RELEASE, "Host game server description.");
#ifdef DEDICATED
static ConVar hostdesc("hostdesc", "", FCVAR_RELEASE, "Host game server description.");
//-----------------------------------------------------------------------------
// Purpose: Send keep alive request to Pylon Master Server.
// Output : Returns true on success, false otherwise.
@ -121,8 +120,8 @@ static void HostState_KeepAlive()
{
g_ServerHostManager.SetCurrentToken(hostToken);
Msg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
g_svReset.c_str(), g_svGreyB.c_str(),
hostToken.c_str(), g_svReset.c_str());
g_svReset, g_svGreyB,
hostToken.c_str(), g_svReset);
}
}
@ -424,12 +423,7 @@ void CHostState::LoadConfig(void) const
}
if (CommandLine()->CheckParm("-offline"))
{
#ifndef CLIENT_DLL
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec system/offline_server.cfg\n", cmd_source_t::kCommandSrcCode);
#endif //!CLIENT_DLL
#ifndef DEDICATED
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec system/offline_client.cfg\n", cmd_source_t::kCommandSrcCode);
#endif // !DEDICATED
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec system/autoexec_offline.cfg\n", cmd_source_t::kCommandSrcCode);
}
#ifndef CLIENT_DLL
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec liveapi.cfg\n", cmd_source_t::kCommandSrcCode);

View File

@ -1,8 +1,6 @@
#pragma once
#include "mathlib/vector.h"
extern ConVar hostdesc;
enum class HostStates_t : int
{
HS_NEW_GAME = 0x0,

View File

@ -181,7 +181,7 @@ void NET_Config()
void NET_PrintKey()
{
Msg(eDLL_T::ENGINE, "Installed NetKey: %s'%s%s%s'\n",
g_svReset.c_str(), g_svGreyB.c_str(), g_pNetKey->GetBase64NetKey(), g_svReset.c_str());
g_svReset, g_svGreyB, g_pNetKey->GetBase64NetKey(), g_svReset);
}
//-----------------------------------------------------------------------------
@ -247,7 +247,12 @@ void NET_PrintFunc(const char* fmt, ...)
result = FormatV(fmt, args);
va_end(args);
Msg(context, result.back() == '\n' ? "%s" : "%s\n", result.c_str());
if (result.back() != '\n')
{
result.push_back('\n');
}
Msg(context, "%s", result.c_str());
}
//-----------------------------------------------------------------------------
@ -383,7 +388,7 @@ const char* NET_ErrorString(int iCode)
case WSA_QOS_EFILTERCOUNT : return "WSA_QOS_EFILTERCOUNT";
case WSA_QOS_EOBJLENGTH : return "WSA_QOS_EOBJLENGTH";
case WSA_QOS_EFLOWCOUNT : return "WSA_QOS_EFLOWCOUNT";
case WSA_QOS_EUNKOWNPSOBJ : return "WSA_QOS_EUNKNOWNPSOBJ";
case WSA_QOS_EUNKOWNPSOBJ : return "WSA_QOS_EUNKOWNPSOBJ";
case WSA_QOS_EPOLICYOBJ : return "WSA_QOS_EPOLICYOBJ";
case WSA_QOS_EFLOWDESC : return "WSA_QOS_EFLOWDESC";
case WSA_QOS_EPSFLOWSPEC : return "WSA_QOS_EPSFLOWSPEC";

View File

@ -116,7 +116,7 @@ CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge)
return nullptr;
char* pszPersonaName = pChallenge->personaName;
NucleusID_t nNucleusID = pChallenge->personaId;
uint64_t nNucleusID = pChallenge->personaId;
char pszAddresBuffer[128]; // Render the client's address.
pChallenge->netAdr.ToString(pszAddresBuffer, sizeof(pszAddresBuffer), true);

View File

@ -23,7 +23,7 @@ struct user_creds_s
int32_t protocolVer;
int32_t challenge;
uint32_t reservation;
NucleusID_t personaId;
uint64_t personaId;
char* personaName;
};

View File

@ -39,7 +39,7 @@ void SV_CheckForBanAndDisconnect(CClient* const pClient, const string& svIPAddr,
{
const int nUserID = pClient->GetUserID();
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "%s", svError.c_str());
pClient->Disconnect(Reputation_t::REP_MARK_BAD, svError.c_str());
Warning(eDLL_T::SERVER, "Removed client '[%s]:%i' from slot #%i ('%llu' is banned globally!)\n",
svIPAddr.c_str(), nPort, nUserID, nNucleusID);
}

View File

@ -43,7 +43,7 @@ static ConVar sv_rcon_maxignores("sv_rcon_maxignores", "15", FCVAR_RELEASE, "Max
static ConVar sv_rcon_maxsockets("sv_rcon_maxsockets", "32", FCVAR_RELEASE, "Max number of accepted sockets before the server starts closing redundant sockets", true, 1.f, true, MAX_PLAYERS);
static ConVar sv_rcon_maxconnections("sv_rcon_maxconnections", "1", FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket", true, 1.f, true, MAX_PLAYERS, &RCON_ConnectionCountChanged_f);
static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, true, 4096.f);
static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, false, 0.f);
static ConVar sv_rcon_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);
@ -95,7 +95,7 @@ void CRConServer::Init(const char* pPassword, const char* pNetKey)
m_Socket.CreateListenSocket(m_Address);
Msg(eDLL_T::SERVER, "Remote server access initialized ('%s') with key %s'%s%s%s'\n",
m_Address.ToString(), g_svReset.c_str(), g_svGreyB.c_str(), GetKey(), g_svReset.c_str());
m_Address.ToString(), g_svReset, g_svGreyB, GetKey(), g_svReset);
m_bInitialized = true;
}
@ -155,7 +155,7 @@ void CRConServer::Think(void)
const netadr_t& netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex);
if (!m_WhiteListAddress.CompareAdr(netAdr))
{
const ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
const CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
if (!data.m_bAuthorized)
{
Disconnect("redundant");
@ -248,11 +248,11 @@ void CRConServer::RunFrame(void)
const int nCount = m_Socket.GetAcceptedSocketCount();
for (m_nConnIndex = nCount - 1; m_nConnIndex >= 0; m_nConnIndex--)
{
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
if (CheckForBan(data))
{
SendEncoded(data.m_hSocket, s_BannedMessage, sizeof(s_BannedMessage)-1, "", 0,
SendEncoded(data.m_hSocket, s_BannedMessage, "",
netcon::response_e::SERVERDATA_RESPONSE_AUTH, int(eDLL_T::NETCON));
Disconnect("banned");
@ -270,18 +270,25 @@ void CRConServer::RunFrame(void)
// nMsgLen -
// Output: true on success, false otherwise
//-----------------------------------------------------------------------------
bool CRConServer::SendToAll(const byte* pMsgBuf, const u32 nMsgLen) const
bool CRConServer::SendToAll(const char* pMsgBuf, const int nMsgLen) const
{
const int nCount = m_Socket.GetAcceptedSocketCount();
ostringstream sendbuf;
const u_long nLen = htonl(u_long(nMsgLen));
bool bSuccess = true;
sendbuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
sendbuf.write(pMsgBuf, nMsgLen);
const int nCount = m_Socket.GetAcceptedSocketCount();
for (int i = nCount - 1; i >= 0; i--)
{
const ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(i);
const CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(i);
if (data.m_bAuthorized && !data.m_bInputOnly)
{
const int ret = ::send(data.m_hSocket, (const char*)pMsgBuf, (i32)nMsgLen, MSG_NOSIGNAL);
int ret = ::send(data.m_hSocket, sendbuf.str().data(),
int(sendbuf.str().size()), MSG_NOSIGNAL);
if (ret == SOCKET_ERROR)
{
@ -299,19 +306,17 @@ bool CRConServer::SendToAll(const byte* pMsgBuf, const u32 nMsgLen) const
//-----------------------------------------------------------------------------
// Purpose: encode and send message to all connected sockets
// Input : *pResponseMsg -
// nResponseMsgLen -
// *pResponseVal -
// nResponseValLen -
// responseType -
// nMessageId -
// nMessageType -
// Output: true on success, false otherwise
//-----------------------------------------------------------------------------
bool CRConServer::SendEncoded(const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
bool CRConServer::SendEncoded(const char* pResponseMsg, const char* pResponseVal,
const netcon::response_e responseType, const int nMessageId, const int nMessageType) const
{
vector<byte> vecMsg;
if (!Serialize(vecMsg, pResponseMsg, nResponseMsgLen, pResponseVal, nResponseValLen,
vector<char> vecMsg;
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
responseType, nMessageId, nMessageType))
{
return false;
@ -329,20 +334,17 @@ bool CRConServer::SendEncoded(const char* pResponseMsg, const size_t nResponseMs
// Purpose: encode and send message to specific socket
// Input : hSocket -
// *pResponseMsg -
// nResponseMsgLen -
// *pResponseVal -
// nResponseValLen -
// responseType -
// nMessageId -
// nMessageType -
// Output: true on success, false otherwise
//-----------------------------------------------------------------------------
bool CRConServer::SendEncoded(const SocketHandle_t hSocket,
const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
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<byte> vecMsg;
if (!Serialize(vecMsg, pResponseMsg, nResponseMsgLen, pResponseVal, nResponseValLen,
vector<char> vecMsg;
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
responseType, nMessageId, nMessageType))
{
return false;
@ -360,19 +362,16 @@ bool CRConServer::SendEncoded(const SocketHandle_t hSocket,
// Purpose: serializes input
// Input : &vecBuf -
// *responseMsg -
// nResponseMsgLen -
// *responseVal -
// nResponseValLen -
// responseType -
// nMessageId -
// nMessageType -
// Output : serialized results as string
//-----------------------------------------------------------------------------
bool CRConServer::Serialize(vector<byte>& vecBuf,
const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
bool CRConServer::Serialize(vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal,
const netcon::response_e responseType, const int nMessageId, const int nMessageType) const
{
return NetconServer_Serialize(this, vecBuf, pResponseMsg, nResponseMsgLen, pResponseVal, nResponseValLen, responseType, nMessageId, nMessageType,
return NetconServer_Serialize(this, vecBuf, pResponseMsg, pResponseVal, responseType, nMessageId, nMessageType,
rcon_encryptframes.GetBool(), rcon_debug.GetBool());
}
@ -381,7 +380,7 @@ bool CRConServer::Serialize(vector<byte>& vecBuf,
// Input : &request -
// &data -
//-----------------------------------------------------------------------------
void CRConServer::Authenticate(const netcon::request& request, ConnectedNetConsoleData_s& data)
void CRConServer::Authenticate(const netcon::request& request, CConnectedNetConsoleData& data)
{
if (data.m_bAuthorized)
{
@ -400,7 +399,7 @@ void CRConServer::Authenticate(const netcon::request& request, ConnectedNetConso
const char* pSendLogs = (!sv_rcon_sendlogs.GetBool() || data.m_bInputOnly) ? "0" : "1";
SendEncoded(data.m_hSocket, s_AuthMessage, sizeof(s_AuthMessage)-1, pSendLogs, 1,
SendEncoded(data.m_hSocket, s_AuthMessage, pSendLogs,
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
}
else // Bad password.
@ -411,7 +410,7 @@ void CRConServer::Authenticate(const netcon::request& request, ConnectedNetConso
Msg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString());
}
SendEncoded(data.m_hSocket, s_WrongPwMessage, sizeof(s_WrongPwMessage)-1, "", 0,
SendEncoded(data.m_hSocket, s_WrongPwMessage, "",
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
data.m_bAuthorized = false;
@ -445,7 +444,7 @@ bool CRConServer::Comparator(const string& svPassword) const
// nMsgLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CRConServer::ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen)
bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
{
netcon::request request;
@ -455,13 +454,13 @@ bool CRConServer::ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen)
return false;
}
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
if (!data.m_bAuthorized &&
request.requesttype() != netcon::request_e::SERVERDATA_REQUEST_AUTH)
{
// Notify netconsole that authentication is required.
SendEncoded(data.m_hSocket, s_NoAuthMessage, sizeof(s_NoAuthMessage)-1, "", 0,
SendEncoded(data.m_hSocket, s_NoAuthMessage, "",
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
data.m_bValidated = false;
@ -522,7 +521,7 @@ void CRConServer::Execute(const netcon::request& request) const
// Purpose: checks for amount of failed attempts and bans netconsole accordingly
// Input : &data -
//-----------------------------------------------------------------------------
bool CRConServer::CheckForBan(ConnectedNetConsoleData_s& data)
bool CRConServer::CheckForBan(CConnectedNetConsoleData& data)
{
if (data.m_bValidated)
{
@ -597,7 +596,7 @@ void CRConServer::Disconnect(const char* szReason) // NETMGR
//-----------------------------------------------------------------------------
void CRConServer::Disconnect(const int nIndex, const char* szReason) // NETMGR
{
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(nIndex);
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(nIndex);
if (data.m_bAuthorized)
{
// Inform server owner when authenticated connection has been closed.
@ -622,7 +621,7 @@ void CRConServer::CloseNonAuthConnection(void)
int nCount = m_Socket.GetAcceptedSocketCount();
for (int i = nCount - 1; i >= 0; i--)
{
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(i);
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(i);
if (!data.m_bAuthorized)
{

View File

@ -25,27 +25,27 @@ public:
void Think(void);
void RunFrame(void);
bool SendEncoded(const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
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 SendEncoded(const SocketHandle_t hSocket, const char* pResponseMsg, const size_t nResponseMsgLen,
const char* pResponseVal, const size_t nResponseValLen, const netcon::response_e 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 byte* pMsgBuf, const u32 nMsgLen) const;
bool Serialize(vector<byte>& vecBuf, const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
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 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 netcon::request& request, ConnectedNetConsoleData_s& data);
void Authenticate(const netcon::request& request, CConnectedNetConsoleData& data);
bool Comparator(const string& svPassword) const;
virtual bool ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen) override;
virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override;
void Execute(const netcon::request& request) const;
bool CheckForBan(ConnectedNetConsoleData_s& data);
bool CheckForBan(CConnectedNetConsoleData& data);
virtual void Disconnect(const char* szReason = nullptr) override;
void Disconnect(const int nIndex, const char* szReason = nullptr);

View File

@ -9,10 +9,10 @@
//-----------------------------------------------------------------------------
// Purpose: sets the persistence var in the CClient instance to 'ready'
//-----------------------------------------------------------------------------
bool CVEngineServer::PersistenceAvailable(CVEngineServer* const thisptr, const int clientidx)
bool CVEngineServer::PersistenceAvailable(void* entidx, int clientidx)
{
///////////////////////////////////////////////////////////////////////////
return CVEngineServer__PersistenceAvailable(thisptr, clientidx);
return CVEngineServer__PersistenceAvailable(entidx, clientidx);
}
void HVEngineServer::Detour(const bool bAttach) const

View File

@ -2,21 +2,22 @@
#include "public/edict.h"
#include "public/eiface.h"
/* ==== CVENGINESERVER ================================================================================================================================================== */
inline bool(*CVEngineServer__PersistenceAvailable)(void* entidx, int clientidx);
inline bool* m_bIsDedicated = nullptr;
///////////////////////////////////////////////////////////////////////////////
class CVEngineServer : public IVEngineServer
{
public:
static bool PersistenceAvailable(CVEngineServer* const thisptr, const int clientidx);
static bool PersistenceAvailable(void* entidx, int clientidx);
// Implementation in GameDLL.
};
extern CVEngineServer* g_pEngineServer;
extern IVEngineServer* g_pEngineServerVFTable;
/* ==== CVENGINESERVER ================================================================================================================================================== */
inline bool(*CVEngineServer__PersistenceAvailable)(CVEngineServer* const thisptr, const int clientidx);
///////////////////////////////////////////////////////////////////////////////
inline bool* m_bIsDedicated = nullptr;
///////////////////////////////////////////////////////////////////////////////
class HVEngineServer : public IDetour
{

View File

@ -144,88 +144,72 @@ bool CNetConBase::Connect(const char* pHostName, const int nPort)
// nMaxLen -
// Output: true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetConBase::ProcessBuffer(ConnectedNetConsoleData_s& data, const byte* pRecvBuf, u32 nRecvLen, const int nMaxLen)
bool CNetConBase::ProcessBuffer(CConnectedNetConsoleData& data,
const char* pRecvBuf, int nRecvLen, const int nMaxLen)
{
bool bSuccess = true;
while (nRecvLen > 0)
{
// Read payload if it's already in progress.
if (data.m_nPayloadLen)
{
const u32 bytesToCopy = Min(nRecvLen, data.m_nPayloadLen - data.m_nPayloadRead);
memcpy(&data.m_RecvBuffer[data.m_nPayloadRead], pRecvBuf, bytesToCopy);
data.m_nPayloadRead += bytesToCopy;
pRecvBuf += bytesToCopy;
nRecvLen -= bytesToCopy;
if (data.m_nPayloadRead < data.m_nPayloadLen)
{
data.m_RecvBuffer[data.m_nPayloadRead++] = *pRecvBuf;
pRecvBuf++;
nRecvLen--;
}
if (data.m_nPayloadRead == data.m_nPayloadLen)
{
if (!ProcessMessage(data.m_RecvBuffer.data(), data.m_nPayloadLen))
return false;
if (!ProcessMessage(
reinterpret_cast<const char*>(data.m_RecvBuffer.data()), data.m_nPayloadLen)
&& bSuccess)
{
bSuccess = false;
}
// Reset state.
data.m_nPayloadLen = 0;
data.m_nPayloadRead = 0;
}
}
else if (data.m_nPayloadRead < sizeof(NetConFrameHeader_s)) // Read the header if we haven't fully recv'd it.
else if (data.m_nPayloadRead < sizeof(int)) // Read size field.
{
const u32 bytesToCopy = Min(nRecvLen, int(sizeof(NetConFrameHeader_s)) - data.m_nPayloadRead);
memcpy(reinterpret_cast<char*>(&data.m_FrameHeader) + data.m_nPayloadRead, pRecvBuf, bytesToCopy);
data.m_RecvBuffer[data.m_nPayloadRead++] = *pRecvBuf;
data.m_nPayloadRead += bytesToCopy;
pRecvBuf++;
nRecvLen--;
}
else // Build prefix.
{
data.m_nPayloadLen = int(ntohl(*reinterpret_cast<u_long*>(&data.m_RecvBuffer[0])));
data.m_nPayloadRead = 0;
pRecvBuf += bytesToCopy;
nRecvLen -= bytesToCopy;
if (data.m_nPayloadRead == sizeof(NetConFrameHeader_s))
if (!data.m_bAuthorized && nMaxLen > -1)
{
NetConFrameHeader_s& header = data.m_FrameHeader;
// Convert byte order and check for desync.
header.magic = ntohl(header.magic);
const char* desyncReason = nullptr;
if (header.magic != RCON_FRAME_MAGIC)
if (data.m_nPayloadLen > nMaxLen)
{
desyncReason = "invalid magic";
}
if (!desyncReason)
{
header.length = ntohl(header.length);
if (header.length == 0)
{
desyncReason = "empty frame";
}
}
if (desyncReason)
{
Error(eDLL_T::ENGINE, NO_ERROR, "RCON Cmd: sync error (%s)\n", desyncReason);
Disconnect("desync");
Disconnect("overflow"); // Sending large messages while not authenticated.
return false;
}
}
if ((!data.m_bAuthorized && nMaxLen > -1 && header.length > (u32)nMaxLen) ||
header.length > RCON_FRAME_MAX_SIZE)
{
Disconnect("overflow");
return false;
}
if (data.m_nPayloadLen < 0 ||
data.m_nPayloadLen > data.m_RecvBuffer.max_size())
{
Error(eDLL_T::ENGINE, NO_ERROR, "RCON Cmd: sync error (%d)\n", data.m_nPayloadLen);
Disconnect("desync"); // Out of sync (irrecoverable).
data.m_nPayloadLen = header.length;
data.m_nPayloadRead = 0;
data.m_RecvBuffer.resize(header.length);
return false;
}
else
{
data.m_RecvBuffer.resize(data.m_nPayloadLen);
}
}
}
return true;
return bSuccess;
}
//-----------------------------------------------------------------------------
@ -236,12 +220,13 @@ bool CNetConBase::ProcessBuffer(ConnectedNetConsoleData_s& data, const byte* pRe
// nDataLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetConBase::Encrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBuf, const u32 nDataLen) const
bool CNetConBase::Encrypt(CryptoContext_s& ctx, const char* pInBuf,
char* pOutBuf, const size_t nDataLen) const
{
if (Crypto_GenerateIV(ctx, pInBuf, nDataLen))
return Crypto_CTREncrypt(ctx, pInBuf, pOutBuf, m_NetKey, nDataLen);
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);
Assert(0);
return false; // failure
}
@ -253,9 +238,11 @@ bool CNetConBase::Encrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBu
// nDataLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetConBase::Decrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBuf, const u32 nDataLen) const
bool CNetConBase::Decrypt(CryptoContext_s& ctx, const char* pInBuf,
char* pOutBuf, const size_t nDataLen) const
{
return Crypto_CTRDecrypt(ctx, pInBuf, pOutBuf, m_NetKey, nDataLen);
return Crypto_CTRDecrypt(ctx, reinterpret_cast<const unsigned char*>(pInBuf),
reinterpret_cast<unsigned char*>(pOutBuf), m_NetKey, nDataLen);
}
//-----------------------------------------------------------------------------
@ -265,9 +252,10 @@ bool CNetConBase::Decrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBu
// nMsgLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg, byte* pMsgBuf, const u32 nMsgLen) const
bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg,
char* pMsgBuf, const size_t nMsgLen) const
{
return pMsg->SerializeToArray(pMsgBuf, (i32)nMsgLen);
return pMsg->SerializeToArray(pMsgBuf, int(nMsgLen));
}
//-----------------------------------------------------------------------------
@ -277,9 +265,10 @@ bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg, byte* pMsgBuf, con
// nMsgLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg, const byte* pMsgBuf, const u32 nMsgLen) const
bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg,
const char* pMsgBuf, const size_t nMsgLen) const
{
return pMsg->ParseFromArray(pMsgBuf, (i32)nMsgLen);
return pMsg->ParseFromArray(pMsgBuf, int(nMsgLen));
}
//-----------------------------------------------------------------------------
@ -289,9 +278,18 @@ bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg, const byte* pMsgBu
// nMsgLen -
// Output: true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetConBase::Send(const SocketHandle_t hSocket, const byte* pMsgBuf, const u32 nMsgLen) const
bool CNetConBase::Send(const SocketHandle_t hSocket, const char* pMsgBuf,
const int nMsgLen) const
{
const int ret = ::send(hSocket, (char*)pMsgBuf, (i32)nMsgLen, MSG_NOSIGNAL);
std::ostringstream sendbuf;
const u_long nLen = htonl(u_long(nMsgLen));
sendbuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
sendbuf.write(pMsgBuf, nMsgLen);
int ret = ::send(hSocket, sendbuf.str().data(), int(sendbuf.str().size()),
MSG_NOSIGNAL);
return (ret != SOCKET_ERROR);
}
@ -301,19 +299,19 @@ bool CNetConBase::Send(const SocketHandle_t hSocket, const byte* pMsgBuf, const
// nMaxLen -
// Output: true on success, false otherwise
//-----------------------------------------------------------------------------
void CNetConBase::Recv(ConnectedNetConsoleData_s& data, const int nMaxLen)
void CNetConBase::Recv(CConnectedNetConsoleData& data, const int nMaxLen)
{
static char szRecvBuf[1024];
{//////////////////////////////////////////////
const int nPendingLen = ::recv(data.m_hSocket, szRecvBuf, sizeof(szRecvBuf), MSG_PEEK);
const int nPendingLen = ::recv(data.m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
if (nPendingLen == SOCKET_ERROR && m_Socket.IsSocketBlocking())
{
return;
}
else if (nPendingLen == 0) // Socket was closed.
{
Disconnect("socket closed prematurely");
Disconnect("remote closed socket");
return;
}
else if (nPendingLen < 0)
@ -323,8 +321,8 @@ void CNetConBase::Recv(ConnectedNetConsoleData_s& data, const int nMaxLen)
}
}//////////////////////////////////////////////
u_long nReadLen = 0; // Find out how much we have to read.
const int iResult = ::ioctlsocket(data.m_hSocket, FIONREAD, &nReadLen);
int nReadLen = 0; // Find out how much we have to read.
int iResult = ::ioctlsocket(data.m_hSocket, FIONREAD, reinterpret_cast<u_long*>(&nReadLen));
if (iResult == SOCKET_ERROR)
{
@ -346,10 +344,8 @@ void CNetConBase::Recv(ConnectedNetConsoleData_s& data, const int nMaxLen)
break;
}
nReadLen -= static_cast<u_long>(nRecvLen); // Process what we've got.
if (!ProcessBuffer(data, reinterpret_cast<byte*>(&szRecvBuf), static_cast<u32>(nRecvLen), nMaxLen))
break;
nReadLen -= nRecvLen; // Process what we've got.
ProcessBuffer(data, szRecvBuf, nRecvLen, nMaxLen);
}
return;

View File

@ -1,12 +1,14 @@
#ifndef BASE_RCON_H
#define BASE_RCON_H
#include "netcon/INetCon.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:
@ -21,17 +23,17 @@ public:
virtual bool Connect(const char* pHostName, const int nHostPort = SOCKET_ERROR);
virtual void Disconnect(const char* szReason = nullptr) { NOTE_UNUSED(szReason); };
virtual bool ProcessBuffer(ConnectedNetConsoleData_s& data, const byte* pRecvBuf, u32 nRecvLen, const int nMaxLen = SOCKET_ERROR);
virtual bool ProcessMessage(const byte* /*pMsgBuf*/, const u32 /*nMsgLen*/) { return true; };
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 byte* pInBuf, byte* pOutBuf, const u32 nDataLen) const;
virtual bool Decrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBuf, const u32 nDataLen) const;
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, byte* pMsgBuf, const u32 nMsgLen) const;
virtual bool Decode(google::protobuf::MessageLite* pMsg, const byte* pMsgBuf, const u32 nMsgLen) 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;
virtual bool Send(const SocketHandle_t hSocket, const byte* pMsgBuf, const u32 nMsgLen) const;
virtual void Recv(ConnectedNetConsoleData_s& data, const int nMaxLen = SOCKET_ERROR);
virtual bool Send(const SocketHandle_t hSocket, const char* pMsgBuf, const int nMsgLen) const;
virtual void Recv(CConnectedNetConsoleData& data, const int nMaxLen = SOCKET_ERROR);
CSocketCreator* GetSocketCreator(void) { return &m_Socket; }
netadr_t* GetNetAddress(void) { return &m_Address; }

View File

@ -1,66 +0,0 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef ENTS_SHARED_H
#define ENTS_SHARED_H
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CClientFrame;
class bf_read;
// Used to classify entity update types in DeltaPacketEntities.
enum EntityUpdateType_e
{
EnterPVS = 0, // Entity came back into pvs, create new entity if one doesn't exist
LeavePVS, // Entity left pvs
DeltaEnt, // There is a delta for this entity.
PreserveEnt, // Entity stays alive but no delta ( could be LOD, or just unchanged )
Finished, // finished parsing entities successfully
Failed, // parsing error occured while reading entities
};
// Base entity info class.
struct CEntityInfo
{
virtual ~CEntityInfo() {};
bool m_bAsDelta;
CClientFrame* m_pFrom;
CClientFrame* m_pTo;
EntityUpdateType_e m_UpdateType;
int m_nOldEntity; // current entity index in m_pFrom
int m_nNewEntity; // current entity index in m_pTo
int m_nHeaderBase;
int m_nHeaderCount;
};
// Flags for delta encoding header
enum EntityUpdateFlags_e
{
FHDR_ZERO = 0x0,
FHDR_LEAVEPVS = 0x1,
FHDR_DELETE = 0x2,
FHDR_ENTERPVS = 0x4,
};
// Passed around the read functions.
class CEntityReadInfo : public CEntityInfo
{
bf_read* m_pBuf;
EntityUpdateFlags_e m_UpdateFlags; // from the subheader
bool m_bIsEntity;
};
#endif // ENTS_SHARED_H

View File

@ -13,9 +13,7 @@
// Input : *pBase -
// &vecBuf -
// *pResponseMsg -
// nResponseMsgLen -
// *pResponseVal -
// nResponseValLen -
// responseType -
// nMessageId -
// nMessageType -
@ -23,8 +21,7 @@
// bDebug -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool NetconServer_Serialize(const CNetConBase* pBase, vector<byte>& vecBuf,
const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
bool NetconServer_Serialize(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;
@ -32,10 +29,10 @@ bool NetconServer_Serialize(const CNetConBase* pBase, vector<byte>& vecBuf,
response.set_messageid(nMessageId);
response.set_messagetype(nMessageType);
response.set_responsetype(responseType);
response.set_responsemsg(pResponseMsg, nResponseMsgLen);
response.set_responseval(pResponseVal, nResponseValLen);
response.set_responsemsg(pResponseMsg);
response.set_responseval(pResponseVal);
if (!NetconShared_PackEnvelope(pBase, vecBuf, (u32)response.ByteSizeLong(), &response, bEncrypt, bDebug))
if (!NetconShared_PackEnvelope(pBase, vecBuf, response.ByteSizeLong(), &response, bEncrypt, bDebug))
{
return false;
}
@ -48,25 +45,23 @@ bool NetconServer_Serialize(const CNetConBase* pBase, vector<byte>& vecBuf,
// Input : *pBase -
// &vecBuf -
// *szReqBuf -
// nReqMsgLen -
// *szReqVal -
// nReqValLen -
// *requestType -
// bEncrypt -
// bDebug -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool NetconClient_Serialize(const CNetConBase* pBase, vector<byte>& vecBuf, const char* szReqBuf, const size_t nReqMsgLen,
const char* szReqVal, const size_t nReqValLen, const netcon::request_e requestType, const bool bEncrypt, const bool bDebug)
bool NetconClient_Serialize(const CNetConBase* pBase, vector<char>& vecBuf, const char* szReqBuf,
const char* szReqVal, const netcon::request_e requestType, const bool bEncrypt, const bool bDebug)
{
netcon::request request;
request.set_messageid(-1);
request.set_requesttype(requestType);
request.set_requestmsg(szReqBuf, nReqMsgLen);
request.set_requestval(szReqVal, nReqValLen);
request.set_requestmsg(szReqBuf);
request.set_requestval(szReqVal);
if (!NetconShared_PackEnvelope(pBase, vecBuf, (u32)request.ByteSizeLong(), &request, bEncrypt, bDebug))
if (!NetconShared_PackEnvelope(pBase, vecBuf, request.ByteSizeLong(), &request, bEncrypt, bDebug))
{
return false;
}
@ -129,11 +124,11 @@ bool NetconClient_Connect(CNetConBase* pBase, const char* pHostAdr, const int nH
// bDebug -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf, const u32 nMsgLen,
google::protobuf::MessageLite* const inMsg, const bool bEncrypt, const bool bDebug)
bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<char>& outMsgBuf, const size_t nMsgLen,
google::protobuf::MessageLite* inMsg, const bool bEncrypt, const bool bDebug)
{
byte* const encodeBuf = new byte[nMsgLen];
std::unique_ptr<byte[]> encodedContainer(encodeBuf);
char* encodeBuf = new char[nMsgLen];
std::unique_ptr<char[]> encodedContainer(encodeBuf);
if (!pBase->Encode(inMsg, encodeBuf, nMsgLen))
{
@ -148,12 +143,12 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf
netcon::envelope envelope;
envelope.set_encrypted(bEncrypt);
const byte* dataBuf = encodeBuf;
std::unique_ptr<byte[]> container;
const char* dataBuf = encodeBuf;
std::unique_ptr<char[]> container;
if (bEncrypt)
{
byte* encryptBuf = new byte[nMsgLen];
char* encryptBuf = new char[nMsgLen];
container.reset(encryptBuf);
CryptoContext_s ctx;
@ -172,12 +167,11 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf
}
envelope.set_data(dataBuf, nMsgLen);
const u32 envelopeSize = (u32)envelope.ByteSizeLong();
const size_t envelopeSize = envelope.ByteSizeLong();
outMsgBuf.resize(sizeof(NetConFrameHeader_s) + envelopeSize);
byte* const scratch = outMsgBuf.data();
outMsgBuf.resize(envelopeSize);
if (!pBase->Encode(&envelope, &scratch[sizeof(NetConFrameHeader_s)], envelopeSize))
if (!pBase->Encode(&envelope, &outMsgBuf[0], envelopeSize))
{
if (bDebug)
{
@ -187,12 +181,6 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf
return false;
}
NetConFrameHeader_s* const header = reinterpret_cast<NetConFrameHeader_s*>(scratch);
// Write out magic and frame size in network byte order.
header->magic = htonl(RCON_FRAME_MAGIC);
header->length = htonl(u32(envelopeSize));
return true;
}
@ -206,8 +194,8 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf
// bDebug -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const byte* pMsgBuf, const u32 nMsgLen,
google::protobuf::MessageLite* const outMsg, const bool bDebug)
bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf, const size_t nMsgLen,
google::protobuf::MessageLite* outMsg, const bool bDebug)
{
netcon::envelope envelope;
@ -221,33 +209,33 @@ bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const byte* pMsgBuf,
return false;
}
const u32 msgLen = (u32)envelope.data().size();
const size_t msgLen = envelope.data().size();
if (msgLen > RCON_FRAME_MAX_SIZE)
if (msgLen > RCON_MAX_PAYLOAD_SIZE)
{
Error(eDLL_T::ENGINE, NO_ERROR, "Data in RCON message envelope is too large (%u > %u)\n",
msgLen, RCON_FRAME_MAX_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 byte* netMsg = reinterpret_cast<const byte*>(envelope.data().c_str());
const byte* dataBuf = netMsg;
const char* netMsg = envelope.data().c_str();
const char* dataBuf = netMsg;
std::unique_ptr<byte[]> container;
std::unique_ptr<char[]> container;
if (envelope.encrypted())
{
byte* decryptBuf = new byte[msgLen];
char* decryptBuf = new char[msgLen];
container.reset(decryptBuf);
const u32 ivLen = (u32)envelope.nonce().size();
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 (%u != %u)\n",
Error(eDLL_T::ENGINE, NO_ERROR, "Nonce in RCON message envelope is invalid (%zu != %zu)\n",
ivLen, sizeof(CryptoIV_t));
}
@ -291,7 +279,7 @@ bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const byte* pMsgBuf,
// iSocket -
// Output : nullptr on failure
//-----------------------------------------------------------------------------
ConnectedNetConsoleData_s* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket)
CConnectedNetConsoleData* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket)
{
CSocketCreator* pCreator = pBase->GetSocketCreator();
Assert(iSocket >= 0 && (pCreator->GetAcceptedSocketCount() == 0
@ -313,7 +301,7 @@ ConnectedNetConsoleData_s* NetconShared_GetConnData(CNetConBase* pBase, const in
//-----------------------------------------------------------------------------
SocketHandle_t NetconShared_GetSocketHandle(CNetConBase* pBase, const int iSocket)
{
const ConnectedNetConsoleData_s* pData = NetconShared_GetConnData(pBase, iSocket);
const CConnectedNetConsoleData* pData = NetconShared_GetConnData(pBase, iSocket);
if (!pData)
{
return SOCKET_ERROR;
@ -356,19 +344,19 @@ void RCON_KeyChanged_f(IConVar* pConVar, const char* pOldString, float flOldValu
RCONClient()->SetKey(RCONServer()->GetKey()); // Sync server & client keys
Msg(eDLL_T::ENGINE, "Installed RCON Key: %s'%s%s%s'\n",
g_svReset.c_str(), g_svGreyB.c_str(), RCONClient()->GetKey(), g_svReset.c_str());
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.c_str(), g_svGreyB.c_str(), RCONServer()->GetKey(), g_svReset.c_str());
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.c_str(), g_svGreyB.c_str(), RCONClient()->GetKey(), g_svReset.c_str());
g_svReset, g_svGreyB, RCONClient()->GetKey(), g_svReset);
#endif // CLIENT_DLL
#endif // !DEDICATED && !CLIENT_DLL

View File

@ -16,18 +16,17 @@ extern void RCON_InitClientAndTrySyncKeys();
#endif // !DEDICATED
#endif // _TOOLS
bool NetconServer_Serialize(const CNetConBase* pBase, vector<byte>& vecBuf,
const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
bool NetconServer_Serialize(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 NetconClient_Serialize(const CNetConBase* pBase, vector<byte>& vecBuf, const char* szReqBuf, const size_t nReqMsgLen,
const char* szReqVal, const size_t nReqValLen, const netcon::request_e requestType, const bool bEncrypt, const bool bDebug);
bool NetconClient_Serialize(const CNetConBase* pBase, vector<char>& vecBuf, const char* szReqBuf,
const char* szReqVal, const netcon::request_e requestType, const bool bEncrypt, const bool bDebug);
bool NetconClient_Connect(CNetConBase* pBase, const char* pHostAdr, const int nHostPort);
bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf, const u32 nMsgLen, google::protobuf::MessageLite* const inMsg, const bool bEncrypt, const bool bDebug);
bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const byte* pMsgBuf, const u32 nMsgLen, google::protobuf::MessageLite* const outMsg, const bool bDebug);
bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<char>& outMsgBuf, const size_t nMsgLen, google::protobuf::MessageLite* inMsg, const bool bEncrypt, const bool bDebug);
bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf, const size_t nMsgLen, google::protobuf::MessageLite* outMsg, const bool bDebug);
ConnectedNetConsoleData_s* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket);
CConnectedNetConsoleData* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket);
SocketHandle_t NetconShared_GetSocketHandle(CNetConBase* pBase, const int iSocket);
#endif // SHARED_RCON_H

View File

@ -97,7 +97,7 @@ bool CEngineAPI::VModInit(CEngineAPI* pEngineAPI, const char* pModName, const ch
// Register new Pak Assets here!
//RTech_RegisterAsset(0, 1, "", nullptr, nullptr, nullptr, CMemory(0x1660AD0A8).RCast<void**>(), 8, 8, 8, 0, 0xFFFFFFC);
const bool results = CEngineAPI__ModInit(pEngineAPI, pModName, pGameDir);
bool results = CEngineAPI__ModInit(pEngineAPI, pModName, pGameDir);
if (!IsValveMod(pModName) && !IsRespawnMod(pModName))
{
#ifndef DEDICATED
@ -109,15 +109,6 @@ bool CEngineAPI::VModInit(CEngineAPI* pEngineAPI, const char* pModName, const ch
return results;
}
//-----------------------------------------------------------------------------
// One-time setup, based on the initially selected mod
//-----------------------------------------------------------------------------
bool CEngineAPI::OnStartup(CEngineAPI* pEngineAPI, void* pInstance, const char* pStartupModName)
{
const bool results = CEngineAPI__OnStartup(pEngineAPI, pInstance, pStartupModName);
return results;
}
//-----------------------------------------------------------------------------
// Sets startup info
//-----------------------------------------------------------------------------
@ -306,7 +297,6 @@ void VSys_Dll2::Detour(const bool bAttach) const
{
DetourSetup(&CEngineAPI__Init, &CEngineAPI::VInit, bAttach);
DetourSetup(&CEngineAPI__ModInit, &CEngineAPI::VModInit, bAttach);
DetourSetup(&CEngineAPI__OnStartup, &CEngineAPI::OnStartup, bAttach);
DetourSetup(&CEngineAPI__PumpMessages, &CEngineAPI::PumpMessages, bAttach);
DetourSetup(&CEngineAPI__MainLoop, &CEngineAPI::MainLoop, bAttach);
DetourSetup(&CEngineAPI__SetStartupInfo, &CEngineAPI::VSetStartupInfo, bAttach);

View File

@ -2,9 +2,17 @@
#include "vpc/interfaces.h"
#include "common/engine_launcher_api.h"
class CEngineAPI : public CTier1AppSystem<IEngineAPI>
class CEngineAPI : public IEngineAPI
{
public:
virtual bool Connect(const CreateInterfaceFn factory) = 0;
virtual void Disconnect() = 0;
virtual void* QueryInterface(const char* const pInterfaceName) = 0;
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
virtual AppSystemTier_t GetTier() = 0;
virtual void Reconnect(const CreateInterfaceFn factory, const char* const pInterfaceName) = 0;
// This function must be called before init
virtual bool SetStartupInfo(StartupInfo_t& info) = 0;
@ -24,7 +32,6 @@ public:
static InitReturnVal_t VInit(CEngineAPI* thisp);
static bool VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir);
static bool OnStartup(CEngineAPI* pEngineAPI, void* pInstance, const char* pStartupModName);
static void VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo);
static void PumpMessages();
@ -42,7 +49,6 @@ inline InitReturnVal_t(*CEngineAPI__Init)(CEngineAPI* thisp);
inline void(*CEngineAPI__Shutdown)(void);
inline bool(*CEngineAPI__Connect)(CEngineAPI* thisptr, CreateInterfaceFn factory);
inline bool(*CEngineAPI__ModInit)(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir);
inline bool(*CEngineAPI__OnStartup)(CEngineAPI* pEngineAPI, void* pInstance, const char* pStartupModName);
inline bool(*CEngineAPI__MainLoop)(void);
inline void(*CEngineAPI__PumpMessages)(void);
inline void(*CEngineAPI__SetStartupInfo)(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo);
@ -63,7 +69,6 @@ class VSys_Dll2 : public IDetour
LogFunAdr("CEngineAPI::Shutdown", CEngineAPI__Shutdown);
LogFunAdr("CEngineAPI::Connect", CEngineAPI__Connect);
LogFunAdr("CEngineAPI::ModInit", CEngineAPI__ModInit);
LogFunAdr("CEngineAPI::OnStartup", CEngineAPI__OnStartup);
LogFunAdr("CEngineAPI::MainLoop", CEngineAPI__MainLoop);
LogFunAdr("CEngineAPI::PumpMessages", CEngineAPI__PumpMessages);
LogFunAdr("CEngineAPI::SetStartupInfo", CEngineAPI__SetStartupInfo);
@ -80,7 +85,6 @@ class VSys_Dll2 : public IDetour
g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 89 15").GetPtr(CEngineAPI__Connect);
g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 33 D2 48 8B 01 FF 90 ?? ?? ?? ?? B1 01").GetPtr(CEngineAPI__Shutdown);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 4D 8B F8").GetPtr(CEngineAPI__ModInit);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 49 8B F8 48 8B DA").GetPtr(CEngineAPI__OnStartup);
g_GameDll.FindPatternSIMD("4C 8B DC 49 89 4B 08 48 81 EC ?? ?? ?? ?? 8B 05 ?? ?? ?? ??").GetPtr(CEngineAPI__MainLoop);
g_GameDll.FindPatternSIMD("44 88 44 24 ?? 53 55 56 57").GetPtr(v_PakFile_Init);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 81 EC ?? ?? ?? ?? 45 33 C9").GetPtr(CEngineAPI__PumpMessages);

View File

@ -4,6 +4,7 @@
//
//===========================================================================//
#include "core/stdafx.h"
#include "windows/id3dx.h"
#include "engine/sys_getmodes.h"
#include "gameui/imgui_system.h"
@ -12,6 +13,9 @@
//-----------------------------------------------------------------------------
bool HCVideoMode_Common__CreateGameWindow(int* pnRect)
{
g_nWindowRect[0] = pnRect[0];
g_nWindowRect[1] = pnRect[1];
const bool ret = CVideoMode_Common__CreateGameWindow(pnRect);
return ret;
}

View File

@ -30,18 +30,10 @@ void CGame::PlayStartupVideos(void)
//-----------------------------------------------------------------------------
LRESULT CGame::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (ImguiSystem()->IsInitialized())
ImguiWindowProc(hWnd, uMsg, wParam, lParam);
if (!ImguiSystem()->IsInitialized())
return CGame__WindowProc(hWnd, uMsg, wParam, lParam);
return CGame__WindowProc(hWnd, uMsg, wParam, lParam);
}
//-----------------------------------------------------------------------------
// Purpose: imgui windows procedure
//-----------------------------------------------------------------------------
LRESULT CGame::ImguiWindowProc(HWND hWnd, UINT& uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT hr = NULL;
ImguiSystem()->MessageHandler(hWnd, uMsg, wParam, lParam);
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)
{
@ -60,40 +52,42 @@ LRESULT CGame::ImguiWindowProc(HWND hWnd, UINT& uMsg, WPARAM wParam, LPARAM lPar
}
}
if (ImguiSystem()->IsSurfaceActive())
if (g_Console.IsActivated() || g_Browser.IsActivated())
{//////////////////////////////////////////////////////////////////////////////
hr = ImguiSystem()->MessageHandler(hWnd, uMsg, wParam, lParam);
g_bBlockInput = true;
switch (uMsg)
{
// This is required as the game calls CInputStackSystem::SetCursorPosition(),
// which hides the cursor. It keeps calling it as the game window is the top
// most window, even when the ImGui window is enabled. We could in the future
// create a new input context for the imgui system, then push it to the stack
// after the game's context and call CInputStackSystem::EnableInputContext()
// on the new imgui context.
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_KEYDOWN:
case WM_KEYUP:
case WM_MOUSEACTIVATE:
case WM_MOUSEHOVER:
case WM_MOUSEHWHEEL:
case WM_MOUSELEAVE:
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
case WM_SETCURSOR:
uMsg = WM_NULL;
break;
default:
break;
}
g_bBlockInput = true;
}//////////////////////////////////////////////////////////////////////////////
else
{
if (g_bBlockInput.exchange(false))
{
// Dry run with kill focus msg to clear the keydown state, we have to do
// this as the menu's can be closed while still holding down a key. That
// key will remain pressed down so the next time a window is opened that
// key will be spammed, until that particular key msg is sent here again.
hr = ImguiSystem()->MessageHandler(hWnd, WM_KILLFOCUS, wParam, lParam);
}
g_bBlockInput = false;
}
return hr;
return CGame__WindowProc(hWnd, uMsg, wParam, lParam);
}
//-----------------------------------------------------------------------------
@ -119,24 +113,6 @@ void CGame::GetWindowRect(int* const x, int* const y, int* const w, int* const h
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the window position
//-----------------------------------------------------------------------------
void CGame::SetWindowPosition(const int x, const int y)
{
m_x = x;
m_y = y;
}
//-----------------------------------------------------------------------------
// Purpose: sets the window size
//-----------------------------------------------------------------------------
void CGame::SetWindowSize(const int w, const int h)
{
m_width = w;
m_height = h;
}
//-----------------------------------------------------------------------------
// Purpose: dispatch key event
//-----------------------------------------------------------------------------

View File

@ -6,7 +6,6 @@
#ifndef SYS_MAINWIND_H
#define SYS_MAINWIND_H
#include "inputsystem/iinputsystem.h"
#include "inputsystem/iinputstacksystem.h"
inline void (*CGame__AttachToWindow)(void);
inline void(*CGame__PlayStartupVideos)(void);
@ -18,16 +17,12 @@ class CGame
{
public:
static void PlayStartupVideos(void);
static LRESULT WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static LRESULT ImguiWindowProc(HWND hWnd, UINT& uMsg, WPARAM wParam, LPARAM lParam);
inline HWND GetWindow() const { return m_hWindow; }
void GetWindowRect(int* const x, int* const y, int* const w, int* const h) const;
void SetWindowPosition(const int x, const int y);
void SetWindowSize(const int w, const int h);
inline int GetDesktopWidth() const { return m_iDesktopWidth; }
inline int GetDesktopHeight() const { return m_iDesktopHeight; }
inline int GetDesktopRefreshRate() const { return m_iDesktopRefreshRate; }
@ -51,7 +46,7 @@ private:
int m_iDesktopWidth;
int m_iDesktopHeight;
int m_iDesktopRefreshRate;
InputContextHandle_t m_hInputContext;
void* m_pInputContext_Maybe;
}; static_assert(sizeof(CGame) == 64);
inline CGame* g_pGame = nullptr;

View File

@ -6,6 +6,17 @@
class CBaseFileSystem : public CTier1AppSystem<IFileSystem>
{
public:
// Stub implementation of IAppSystem.
//virtual ~CBaseFileSystem() {};
virtual bool Connect(const CreateInterfaceFn factory) { return false; };
virtual void Disconnect() {};
virtual void* QueryInterface(const char* const pInterfaceName) { return nullptr; };
virtual InitReturnVal_t Init() { return InitReturnVal_t::INIT_FAILED; };
virtual void Shutdown() {};
virtual AppSystemTier_t GetTier() { return AppSystemTier_t::APP_SYSTEM_TIER_OTHER; };
virtual void Reconnect(const CreateInterfaceFn factory, const char* const pInterfaceName) {};
//--------------------------------------------------------
virtual bool IsSteam() const { return false; };
virtual FilesystemMountRetval_t MountSteamContent(int nExtraAppId = -1) { return FilesystemMountRetval_t::FILESYSTEM_MOUNT_FAILED; };

View File

@ -1,52 +1,5 @@
#include "cliententitylist.h"
// Note: 'entList' points directly at the vtable member
// of CClientEntityList; sub classed data is truncated.
static IClientNetworkable* ClientEntityList_GetClientNetworkable(IClientEntityList* const entList, const int entNum)
{
// entNum is used to index into m_EntPtrArray, which is of size
// NUM_ENT_ENTRIES. However, both the lower and upper bounds
// checks were missing; check it here.
if (entNum < 0 || entNum >= NUM_ENT_ENTRIES)
{
Assert(0);
return nullptr;
}
return v_ClientEntityList_GetClientNetworkable(entList, entNum);
}
// Note: 'entList' points directly at the vtable member
// of CClientEntityList; sub classed data is truncated.
static IClientEntity* ClientEntityList_GetClientEntity(IClientEntityList* const entList, const int entNum)
{
// Numbers < -2 will be used to index into the array as follows:
// m_EntPtrArray[ (MAX_EDICTS-2) - entNum ]. However, the code
// doesn't have a clamp for underflows; check it here. -1 cases
// are ignored here as they already are handled correctly.
if (entNum < -(MAX_EDICTS - 2))
{
Assert(0);
return nullptr;
}
// m_EntPtrArray is as large as NUM_ENT_ENTRIES, but there is no
// overflow clamp; check it here.
if (entNum >= NUM_ENT_ENTRIES)
{
Assert(0);
return nullptr;
}
return v_ClientEntityList_GetClientEntity(entList, entNum);
}
void VClientEntityList::Detour(const bool bAttach) const
{
DetourSetup(&v_ClientEntityList_GetClientNetworkable, &ClientEntityList_GetClientNetworkable, bAttach);
DetourSetup(&v_ClientEntityList_GetClientEntity, &ClientEntityList_GetClientEntity, bAttach);
}
//-----------------------------------------------------------------------------
// Purpose: a global list of all the entities in the game. All iteration through
// entities is done through this object.

View File

@ -59,10 +59,8 @@ private:
};
COMPILE_TIME_ASSERT(sizeof(CClientEntityList) == 0x3800C0);
inline IClientNetworkable* (*v_ClientEntityList_GetClientNetworkable)(IClientEntityList* const entList, const int entNum);
inline IClientEntity* (*v_ClientEntityList_GetClientEntity)(IClientEntityList* const entList, const int entNum);
inline IClientEntityList* g_pClientEntityList = nullptr;
extern CClientEntityList* g_clientEntityList;
///////////////////////////////////////////////////////////////////////////////
@ -75,18 +73,14 @@ class VClientEntityList : public IDetour
{
LogVarAdr("g_clientEntityList", g_clientEntityList);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("48 63 C2 48 03 C0 48 8B 44 C1").GetPtr(v_ClientEntityList_GetClientNetworkable);
g_GameDll.FindPatternSIMD("83 FA ?? 7F ?? B8 ?? ?? ?? ?? 2B C2 48 63 D0 48 C1 E2 ?? 48 8B 8C 0A ?? ?? ?? ?? EB ?? 85 D2 78 ?? 48 63 C2 48 C1 E0 ?? 48 8B 8C 08 ?? ?? ?? ?? 48 85 C9 74 ?? 48 8B 01 48 FF 60 ?? 33 C0 C3 CC 80 FA").GetPtr(v_ClientEntityList_GetClientEntity);
}
virtual void GetFun(void) const { }
virtual void GetVar(void) const
{
g_GameDll.FindPatternSIMD("48 8D 0D ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 44 89 0D").
ResolveRelativeAddressSelf(3, 7).ResolveRelativeAddressSelf(3, 7).GetPtr(g_clientEntityList);
}
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const;
virtual void Detour(const bool bAttach) const { };
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -15,7 +15,6 @@
#include "engine/client/cl_main.h"
#include "networksystem/pylon.h"
#include "networksystem/listmanager.h"
#include "networksystem/hostmanager.h"
#include "game/shared/vscript_shared.h"
#include "vscript/vscript.h"
@ -82,17 +81,6 @@ static SQBool Script_CheckServerIndexAndFailure(HSQUIRRELVM v, SQInteger iServer
namespace VScriptCode
{
namespace Client
{
//-----------------------------------------------------------------------------
// Purpose: checks whether this SDK build is a client dll
//-----------------------------------------------------------------------------
SQRESULT IsClientDLL(HSQUIRRELVM v)
{
sq_pushbool(v, ::IsClientDLL());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
}
namespace Ui
{
//-----------------------------------------------------------------------------
// Purpose: refreshes the server list
@ -144,7 +132,7 @@ namespace VScriptCode
else
{
hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), (SQInteger)hiddenServerRequestMessage.length());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
}
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
@ -157,12 +145,12 @@ namespace VScriptCode
else
hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), (SQInteger)hiddenServerRequestMessage.length());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
}
else
{
hiddenServerRequestMessage = Format("Found server: %s", serverListing.name.c_str());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), (SQInteger)hiddenServerRequestMessage.length());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
}
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
@ -182,7 +170,7 @@ namespace VScriptCode
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverName = g_ServerListManager.m_vServerList[iServer].name;
sq_pushstring(v, serverName.c_str(), (SQInteger)serverName.length());
sq_pushstring(v, serverName.c_str(), -1);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
@ -201,7 +189,7 @@ namespace VScriptCode
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverDescription = g_ServerListManager.m_vServerList[iServer].description;
sq_pushstring(v, serverDescription.c_str(), (SQInteger)serverDescription.length());
sq_pushstring(v, serverDescription.c_str(), -1);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
@ -219,8 +207,8 @@ namespace VScriptCode
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverMapName = g_ServerListManager.m_vServerList[iServer].map;
sq_pushstring(v, serverMapName.c_str(), (SQInteger)serverMapName.length());
const string& svServerMapName = g_ServerListManager.m_vServerList[iServer].map;
sq_pushstring(v, svServerMapName.c_str(), -1);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
@ -239,7 +227,7 @@ namespace VScriptCode
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverPlaylist = g_ServerListManager.m_vServerList[iServer].playlist;
sq_pushstring(v, serverPlaylist.c_str(), (SQInteger)serverPlaylist.length());
sq_pushstring(v, serverPlaylist.c_str(), -1);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
@ -356,14 +344,14 @@ namespace VScriptCode
// set EULA version cvar to the newly fetched EULA version
eula_version->SetValue(eulaData.version);
sq_pushstring(v, eulaData.contents.c_str(), (SQInteger)eulaData.contents.length());
sq_pushstring(v, eulaData.contents.c_str(), -1);
}
else
{
const string error = Format("Failed to load EULA Data: %s", eulaRequestMessage.c_str());
string error = Format("Failed to load EULA Data: %s", eulaRequestMessage.c_str());
Warning(eDLL_T::UI, "%s\n", error.c_str());
sq_pushstring(v, error.c_str(), (SQInteger)error.length());
sq_pushstring(v, error.c_str(), -1);
}
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
@ -448,52 +436,11 @@ namespace VScriptCode
}
//-----------------------------------------------------------------------------
// Purpose: create server via native serverbrowser entries
// TODO: return a boolean on failure instead of raising an error, so we could
// determine from scripts whether or not to spin a local server, or connect
// to a dedicated server (for disconnecting and loading the lobby, for example)
// Purpose: checks whether this SDK build is a client dll
//-----------------------------------------------------------------------------
SQRESULT CreateServer(HSQUIRRELVM v)
SQRESULT IsClientDLL(HSQUIRRELVM v)
{
const SQChar* serverName = nullptr;
const SQChar* serverDescription = nullptr;
const SQChar* serverMapName = nullptr;
const SQChar* serverPlaylist = nullptr;
sq_getstring(v, 2, &serverName);
sq_getstring(v, 3, &serverDescription);
sq_getstring(v, 4, &serverMapName);
sq_getstring(v, 5, &serverPlaylist);
SQInteger serverVisibility = 0;
sq_getinteger(v, 6, &serverVisibility);
if (!VALID_CHARSTAR(serverName) ||
!VALID_CHARSTAR(serverMapName) ||
!VALID_CHARSTAR(serverPlaylist))
{
v_SQVM_ScriptError("Empty or null server criteria");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
hostname->SetValue(serverName);
hostdesc.SetValue(serverDescription);
// Launch server.
g_ServerHostManager.SetVisibility(ServerVisibility_e(serverVisibility));
g_ServerHostManager.LaunchServer(serverMapName, serverPlaylist);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: shuts the server down and disconnects all clients
//-----------------------------------------------------------------------------
SQRESULT DestroyServer(HSQUIRRELVM v)
{
if (g_pHostState->m_bActiveGame)
g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN;
sq_pushbool(v, ::IsClientDLL());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
}
@ -509,15 +456,6 @@ void Script_RegisterClientFunctions(CSquirrelVM* s)
Script_RegisterCoreClientFunctions(s);
}
//---------------------------------------------------------------------------------
// Purpose: core client script functions
// Input : *s -
//---------------------------------------------------------------------------------
void Script_RegisterCoreClientFunctions(CSquirrelVM* s)
{
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, IsClientDLL, "Returns whether this build is client only", "bool", "");
}
//---------------------------------------------------------------------------------
// Purpose: registers script functions in UI context
// Input : *s -
@ -527,34 +465,37 @@ void Script_RegisterUIFunctions(CSquirrelVM* s)
Script_RegisterCommonAbstractions(s);
Script_RegisterCoreClientFunctions(s);
DEFINE_UI_SCRIPTFUNC_NAMED(s, RefreshServerList, "Refreshes the public server list and returns the count", "int", "");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerCount, "Gets the number of public servers", "int", "");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, RefreshServerList, "Refreshes the public server list and returns the count", "int", "");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerCount, "Gets the number of public servers", "int", "");
// Functions for retrieving server browser data
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetHiddenServerName, "Gets hidden server name by token", "string", "string");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerName, "Gets the name of the server at the specified index of the server list", "string", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerDescription, "Gets the description of the server at the specified index of the server list", "string", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetHiddenServerName, "Gets hidden server name by token", "string", "string");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerName, "Gets the name of the server at the specified index of the server list", "string", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerDescription, "Gets the description of the server at the specified index of the server list", "string", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerMap, "Gets the map of the server at the specified index of the server list", "string", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerPlaylist, "Gets the playlist of the server at the specified index of the server list", "string", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerCurrentPlayers, "Gets the current player count of the server at the specified index of the server list", "int", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerMap, "Gets the map of the server at the specified index of the server list", "string", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerPlaylist, "Gets the playlist of the server at the specified index of the server list", "string", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerCurrentPlayers, "Gets the current player count of the server at the specified index of the server list", "int", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetServerMaxPlayers, "Gets the max player count of the server at the specified index of the server list", "int", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerMaxPlayers, "Gets the max player count of the server at the specified index of the server list", "int", "int");
// Misc main menu functions
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetPromoData, "Gets promo data for specified slot type", "string", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, GetEULAContents, "Gets EULA contents from masterserver", "string", "");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetPromoData, "Gets promo data for specified slot type", "string", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetEULAContents, "Gets EULA contents from masterserver", "string", "");
// Functions for connecting to servers
DEFINE_UI_SCRIPTFUNC_NAMED(s, ConnectToServer, "Joins server by ip address and encryption key", "void", "string, string");
DEFINE_UI_SCRIPTFUNC_NAMED(s, ConnectToListedServer, "Joins listed server by index", "void", "int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, ConnectToHiddenServer, "Joins hidden server by token", "void", "string");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToServer, "Joins server by ip address and encryption key", "void", "string, string");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToListedServer, "Joins listed server by index", "void", "int");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToHiddenServer, "Joins hidden server by token", "void", "string");
}
void Script_RegisterUIServerFunctions(CSquirrelVM* s)
//---------------------------------------------------------------------------------
// Purpose: core client script functions
// Input : *s -
//---------------------------------------------------------------------------------
void Script_RegisterCoreClientFunctions(CSquirrelVM* s)
{
DEFINE_UI_SCRIPTFUNC_NAMED(s, CreateServer, "Starts server with the specified settings", "void", "string, string, string, string, int");
DEFINE_UI_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local server down", "void", "");
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, IsClientDLL, "Returns whether this build is client only", "bool", "");
}
//---------------------------------------------------------------------------------

View File

@ -4,11 +4,6 @@
namespace VScriptCode
{
namespace Client
{
SQRESULT IsClientDLL(HSQUIRRELVM v);
}
namespace Ui
{
SQRESULT RefreshServerList(HSQUIRRELVM v);
SQRESULT GetServerCount(HSQUIRRELVM v);
@ -28,12 +23,13 @@ namespace VScriptCode
SQRESULT ConnectToListedServer(HSQUIRRELVM v);
SQRESULT ConnectToHiddenServer(HSQUIRRELVM v);
SQRESULT ConnectToServer(HSQUIRRELVM v);
SQRESULT IsClientDLL(HSQUIRRELVM v);
}
}
void Script_RegisterClientFunctions(CSquirrelVM* s);
void Script_RegisterUIFunctions(CSquirrelVM* s);
void Script_RegisterUIServerFunctions(CSquirrelVM* s);
void Script_RegisterCoreClientFunctions(CSquirrelVM* s);
#define DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, functionName, helpString, \
@ -41,11 +37,6 @@ void Script_RegisterCoreClientFunctions(CSquirrelVM* s);
s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \
helpString, returnType, parameters, VScriptCode::Client::##functionName); \
#define DEFINE_UI_SCRIPTFUNC_NAMED(s, functionName, helpString, \
returnType, parameters) \
s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \
helpString, returnType, parameters, VScriptCode::Ui::##functionName); \
inline void (*v_Script_RegisterClientEntityClassFuncs)();
inline void (*v_Script_RegisterClientPlayerClassFuncs)();
inline void (*v_Script_RegisterClientAIClassFuncs)();

View File

@ -18,7 +18,7 @@
#include "ai_basenpc.h"
static ConVar navmesh_always_reachable("navmesh_always_reachable", "0", FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable by ignoring static pathing ( !slower! )");
static ConVar navmesh_always_reachable("navmesh_always_reachable", "0", FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable regardless of table data ( !slower! )");
//-----------------------------------------------------------------------------
// Purpose: gets the navmesh by type from global array [small, med_short, medium, large, extra_large]

View File

@ -120,7 +120,7 @@ private:
CTether m_tethers[2];
EHANDLE m_titanSoul;
Vector3D m_lastFootstepDamagePos;
bool m_lastFootstepDamageOnGround;
bool m_lastFoostepDamageOnGround;
char gap_1781[3];
int m_muzzleAttachment[2];
int m_weaponHandAttachment;

View File

@ -330,7 +330,7 @@ static bool LiveAPI_CheckSwitchType(HSQUIRRELVM const v, const SQObjectPtr& obj)
#define LIVEAPI_EMPTY_TABLE_ERROR(v, eventMsg) { v_SQVM_RaiseError(v, "Empty iterable on message \"%s\".", eventMsg->GetTypeName().c_str()); return false; }
#define LIVEAPI_FIELD_ERROR(v, fieldNum, eventMsg) { v_SQVM_RaiseError(v, "Field #%d doesn't exist in message \"%s\".", fieldNum, eventMsg->GetTypeName().c_str()); return false; }
#define LIVEAPI_ONEOF_FIELD_ERROR(v, fieldNum, eventMsg) { v_SQVM_RaiseError(v, "Tried to set member #%d of oneof field in message \"%s\" while another has already been set.", fieldNum, eventMsg->GetTypeName().c_str()); return false; }
#define LIVEAPI_UNSUPPORTED_TYPE_ERROR(v, gotType, eventMsg) {v_SQVM_RaiseError(v, "Value type \"%s\" is not supported for message \"%s\".", IdType2Name(gotType), eventMsg->GetTypeName().c_str()); return false; }
#define LIVEAPI_UNSUPPORTED_TYPE_ERROR(v, gotType, eventMsg) {v_SQVM_RaiseError(v, "Value type \"%s\" is not supported for message \"%s\".\n", IdType2Name(gotType), eventMsg->GetTypeName().c_str()); return false; }
#define LIVEAPI_CHECK_RECURSION_DEPTH(v, currDepth) { if (currDepth > LIVEAPI_MAX_ITEM_DEPTH) { v_SQVM_RaiseError(v, "Exceeded nesting depth limit of %i.", LIVEAPI_MAX_ITEM_DEPTH); return false; }}
@ -406,7 +406,8 @@ static bool LiveAPI_SetPlayerIdentityFields(HSQUIRRELVM const v, const SQTable*
if (sq_isnull(node.key))
continue;
ranLoop = true;
if (!ranLoop)
ranLoop = true;
if (!LiveAPI_CheckSwitchType(v, node.key))
return false;
@ -536,7 +537,8 @@ static bool LiveAPI_SetInventoryItem(HSQUIRRELVM const v, const SQTable* const t
if (sq_isnull(node.key))
continue;
ranLoop = true;
if (!ranLoop)
ranLoop = true;
if (!LiveAPI_CheckSwitchType(v, node.key))
return false;
@ -1790,7 +1792,8 @@ static bool LiveAPI_SetCustomArrayFields(HSQUIRRELVM const v, google::protobuf::
if (sq_isnull(valueObj))
continue;
ranLoop = true;
if (!ranLoop)
ranLoop = true;
const SQObjectType valueType = sq_type(valueObj);
@ -1854,7 +1857,8 @@ static bool LiveAPI_SetCustomTableFields(HSQUIRRELVM const v, google::protobuf::
if (sq_isnull(node.key))
continue;
ranLoop = true;
if (!ranLoop)
ranLoop = true;
const SQObjectType keyType = sq_type(node.key);

View File

@ -258,19 +258,23 @@ static void CC_CreateFakePlayer_f(const CCommand& args)
if (numPlayers >= g_ServerGlobalVariables->maxClients)
return;
const char* const playerName = args.Arg(1);
const int teamNum = atoi(args.Arg(2));
const char* playerName = args.Arg(1);
// The following code must either run inside the server frame thread, or
// after it has finished. Lock here and help with other jobs until the
// server has finished running the frame.
ThreadJoinServerJob();
int teamNum = atoi(args.Arg(2));
const int maxTeams = int(g_pServer->GetMaxTeams()) + 1;
// Clamp team count, going above the limit will
// cause a crash. Going below 0 means that the
// engine will assign the bot to the last team.
if (teamNum > maxTeams)
teamNum = maxTeams;
g_pEngineServer->LockNetworkStringTables(true);
// note(amos): if you call CServer::CreateFakeClient() directly, you also
// need to lock the string tables with LockNetworkStringTables. The
// CVEngineServer method automatically locks and unlocks the string tables.
const edict_t nHandle = g_pEngineServer->CreateFakeClient(playerName, teamNum);
g_pServerGameClients->ClientFullyConnect(nHandle, false);
g_pEngineServer->LockNetworkStringTables(false);
}
static ConCommand sv_addbot("sv_addbot", CC_CreateFakePlayer_f, "Creates a bot on the server", FCVAR_RELEASE);

View File

@ -17,6 +17,7 @@
#include "liveapi/liveapi.h"
#include "vscript_server.h"
#include <engine/host_state.h>
#include <networksystem/hostmanager.h>
#include "player.h"
#include <common/callback.h>
@ -41,6 +42,61 @@ namespace VScriptCode
{
namespace Server
{
//-----------------------------------------------------------------------------
// Purpose: create server via native serverbrowser entries
// TODO: return a boolean on failure instead of raising an error, so we could
// determine from scripts whether or not to spin a local server, or connect
// to a dedicated server (for disconnecting and loading the lobby, for example)
//-----------------------------------------------------------------------------
SQRESULT CreateServer(HSQUIRRELVM v)
{
const SQChar* serverName = nullptr;
const SQChar* serverDescription = nullptr;
const SQChar* serverMapName = nullptr;
const SQChar* serverPlaylist = nullptr;
sq_getstring(v, 2, &serverName);
sq_getstring(v, 3, &serverDescription);
sq_getstring(v, 4, &serverMapName);
sq_getstring(v, 5, &serverPlaylist);
SQInteger serverVisibility = 0;
sq_getinteger(v, 6, &serverVisibility);
if (!VALID_CHARSTAR(serverName) ||
!VALID_CHARSTAR(serverMapName) ||
!VALID_CHARSTAR(serverPlaylist))
{
v_SQVM_ScriptError("Empty or null server criteria");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Adjust browser settings.
NetGameServer_t& details = g_ServerHostManager.GetDetails();
details.name = serverName;
details.description = serverDescription;
details.map = serverMapName;
details.playlist = serverPlaylist;
// Launch server.
g_ServerHostManager.SetVisibility(ServerVisibility_e(serverVisibility));
g_ServerHostManager.LaunchServer(g_pServer->IsActive());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: shuts the server down and disconnects all clients
//-----------------------------------------------------------------------------
SQRESULT DestroyServer(HSQUIRRELVM v)
{
if (g_pHostState->m_bActiveGame)
g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN;
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
@ -212,6 +268,75 @@ namespace VScriptCode
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: checks whether this SDK build is a dedicated server
//-----------------------------------------------------------------------------
SQRESULT IsDedicated(HSQUIRRELVM v)
{
sq_pushbool(v, ::IsDedicated());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: sets a class var on the server and each client
// TODO: it might also be good to research potential ways to track class var
// changes and sync them back to clients connecting after this has been called.
//-----------------------------------------------------------------------------
SQRESULT SetClassVarSynced(HSQUIRRELVM v)
{
const SQChar* key = nullptr;
sq_getstring(v, 2, &key);
if (!VALID_CHARSTAR(key))
{
v_SQVM_ScriptError("Empty or null class key");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
const SQChar* val = nullptr;
sq_getstring(v, 3, &val);
if (!VALID_CHARSTAR(val))
{
v_SQVM_ScriptError("Empty or null class var");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
const char* pArgs[3] = {
"_setClassVarServer",
key,
val
};
SVC_SetClassVar msg(key, val);
const CCommand cmd((int)V_ARRAYSIZE(pArgs), pArgs, cmd_source_t::kCommandSrcCode);
bool failure = false;
const int oldIdx = *g_nCommandClientIndex;
for (int i = 0; i < gpGlobals->maxClients; i++)
{
CClient* const client = g_pServer->GetClient(i);
// is this client fully connected
if (client->GetSignonState() != SIGNONSTATE::SIGNONSTATE_FULL)
continue;
if (client->SendNetMsgEx(&msg, false, true, false))
{
*g_nCommandClientIndex = client->GetUserID();
v__setClassVarServer_f(cmd);
}
else // Not all clients have their class var set.
failure = true;
}
*g_nCommandClientIndex = oldIdx;
sq_pushbool(v, !failure);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
}
namespace PlayerEntity
@ -240,7 +365,7 @@ namespace VScriptCode
if (!VALID_CHARSTAR(val))
{
v_SQVM_ScriptError("Empty or null class value");
v_SQVM_ScriptError("Empty or null class var");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
@ -280,7 +405,7 @@ void Script_RegisterServerFunctions(CSquirrelVM* s)
{
Script_RegisterCommonAbstractions(s);
Script_RegisterCoreServerFunctions(s);
Script_RegisterAdminServerFunctions(s);
Script_RegisterAdminPanelFunctions(s);
Script_RegisterLiveAPIFunctions(s);
}
@ -296,15 +421,28 @@ void Script_RegisterServerEnums(CSquirrelVM* const s)
//---------------------------------------------------------------------------------
void Script_RegisterCoreServerFunctions(CSquirrelVM* s)
{
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsServerActive, "Returns whether the server is active", "bool", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsDedicated, "Returns whether this is a dedicated server", "bool", "");
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", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, SetClassVarSynced, "Change a variable in the class settings for server and all connected clients", "bool", "string, string");
}
//---------------------------------------------------------------------------------
// Purpose: admin server script functions
// Purpose: admin panel script functions
// Input : *s -
//
// Ideally, these get dropped entirely in favor of remote functions. Currently,
// the s3 build only supports remote function calls from server to client/ui.
// Client/ui to server is all done through clientcommands.
//---------------------------------------------------------------------------------
void Script_RegisterAdminServerFunctions(CSquirrelVM* s)
void Script_RegisterAdminPanelFunctions(CSquirrelVM* s)
{
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetNumHumanPlayers, "Gets the number of human players on the server", "int", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetNumFakeClients, "Gets the number of bot players on the server", "int", "");

View File

@ -29,7 +29,7 @@ namespace VScriptCode
void Script_RegisterServerFunctions(CSquirrelVM* s);
void Script_RegisterCoreServerFunctions(CSquirrelVM* s);
void Script_RegisterAdminServerFunctions(CSquirrelVM* s);
void Script_RegisterAdminPanelFunctions(CSquirrelVM* s);
void Script_RegisterServerEnums(CSquirrelVM* const s);

View File

@ -27,7 +27,7 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT GetSDKVersion(HSQUIRRELVM v)
{
sq_pushstring(v, SDK_VERSION, sizeof(SDK_VERSION)-1);
sq_pushstring(v, SDK_VERSION, -1);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
@ -47,7 +47,7 @@ namespace VScriptCode
{
const CUtlString& mapName = g_InstalledMaps[i];
sq_pushstring(v, mapName.String(), (SQInteger)mapName.Length());
sq_pushstring(v, mapName.String(), -1);
sq_arrayappend(v, -2);
}
@ -65,7 +65,7 @@ namespace VScriptCode
sq_newarray(v, 0);
for (const CUtlString& it : g_vecAllPlaylists)
{
sq_pushstring(v, it.String(), (SQInteger)it.Length());
sq_pushstring(v, it.String(), -1);
sq_arrayappend(v, -2);
}

View File

@ -48,7 +48,6 @@ CBrowser::CBrowser(void)
: m_reclaimFocusOnTokenField(false)
, m_queryNewListNonRecursive(false)
, m_queryGlobalBanList(true)
, m_lockedIconShaderResource(nullptr)
, m_hostMessageColor(1.00f, 1.00f, 1.00f, 1.00f)
, m_hiddenServerMessageColor(0.00f, 1.00f, 0.00f, 1.00f)
{
@ -58,8 +57,7 @@ CBrowser::CBrowser(void)
memset(m_serverAddressTextBuf, '\0', sizeof(m_serverAddressTextBuf));
memset(m_serverNetKeyTextBuf, '\0', sizeof(m_serverNetKeyTextBuf));
m_levelName = "mp_lobby";
m_gameMode = "dev_default";
m_lockedIconDataResource = GetModuleResource(IDB_PNG2);
}
//-----------------------------------------------------------------------------
@ -77,10 +75,7 @@ bool CBrowser::Init(void)
{
SetStyleVar(927.f, 524.f, -500.f, 50.f);
HMODULE sdkModule = reinterpret_cast<HMODULE>(g_SDKDll.GetModuleBase());
m_lockedIconDataResource = GetModuleResource(sdkModule, IDB_PNG2);
const bool ret = LoadTextureBuffer(reinterpret_cast<unsigned char*>(m_lockedIconDataResource.m_pData), int(m_lockedIconDataResource.m_nSize),
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);
IM_ASSERT(ret && m_lockedIconShaderResource);
@ -193,9 +188,6 @@ void CBrowser::RunTask()
//-----------------------------------------------------------------------------
bool CBrowser::DrawSurface(void)
{
if (!IsVisible())
return false;
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_None, &ResetInput))
{
ImGui::End();
@ -281,9 +273,9 @@ void CBrowser::DrawBrowserPanel(void)
const char* pszHostMap = server.map.c_str();
const char* pszPlaylist = server.playlist.c_str();
if (m_serverBrowserTextFilter.PassFilter(pszHostName, &pszHostName[server.name.length()])
|| m_serverBrowserTextFilter.PassFilter(pszHostMap, &pszHostMap[server.map.length()])
|| m_serverBrowserTextFilter.PassFilter(pszPlaylist, &pszPlaylist[server.playlist.length()]))
if (m_serverBrowserTextFilter.PassFilter(pszHostName)
|| m_serverBrowserTextFilter.PassFilter(pszHostMap)
|| m_serverBrowserTextFilter.PassFilter(pszPlaylist))
{
filteredServers.push_back(&server);
}
@ -297,32 +289,28 @@ void CBrowser::DrawBrowserPanel(void)
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{
const NetGameServer_t* const server = filteredServers[i];
const ImGuiTextFlags textFlags = ImGuiTextFlags_NoWidthForLargeClippedText;
const char* pszHostName = server->name.c_str();
const char* pszHostMap = server->map.c_str();
const char* pszPlaylist = server->playlist.c_str();
char pszHostPort[32];
sprintf(pszHostPort, "%d", server->port);
ImGui::TableNextColumn();
const char* const pszHostName = server->name.c_str();
ImGui::TextEx(pszHostName, &pszHostName[server->name.length()], textFlags);
ImGui::Text("%s", pszHostName);
ImGui::TableNextColumn();
const char* const pszHostMap = server->map.c_str();
ImGui::TextEx(pszHostMap, &pszHostMap[server->map.length()], textFlags);
ImGui::Text("%s", pszHostMap);
ImGui::TableNextColumn();
const char* const pszPlaylist = server->playlist.c_str();
ImGui::TextEx(pszPlaylist, &pszPlaylist[server->playlist.length()], textFlags);
ImGui::Text("%s", pszPlaylist);
ImGui::TableNextColumn();
const std::string playerNums = Format("%3d/%3d", server->numPlayers, server->maxPlayers);
const char* const pszPlayerNums = playerNums.c_str();
ImGui::TextEx(pszPlayerNums, &pszPlayerNums[playerNums.length()], textFlags);
ImGui::Text("%s", Format("%3d/%3d", server->numPlayers, server->maxPlayers).c_str());
ImGui::TableNextColumn();
ImGui::Text("%d", server->port);
ImGui::Text("%s", pszHostPort);
ImGui::TableNextColumn();
string svConnectBtn = "Connect##";
@ -529,71 +517,47 @@ void CBrowser::HiddenServersModal(void)
}
}
void CBrowser::HandleInvalidFields(const bool offline)
{
if (!offline && m_serverName.empty())
{
m_hostMessage = "Server name is required.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
else if (m_gameMode.empty())
{
m_hostMessage = "Game mode is required.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
else if (m_levelName.empty())
{
m_hostMessage = "Level name is required.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
}
//-----------------------------------------------------------------------------
// Purpose: draws the host section
//-----------------------------------------------------------------------------
void CBrowser::DrawHostPanel(void)
{
#ifndef CLIENT_DLL
if (ImGui::InputTextWithHint("##ServerHost_ServerName", "Server name (required)", &m_serverName))
{
hostname->SetValue(m_serverName.c_str());
}
if (ImGui::InputTextWithHint("##ServerHost_ServerDesc", "Server description (optional)", &m_serverDescription))
{
hostdesc.SetValue(m_serverDescription.c_str());
}
NetGameServer_t& details = g_ServerHostManager.GetDetails();
ImGui::InputTextWithHint("##ServerHost_ServerName", "Server name (required)", &details.name);
ImGui::InputTextWithHint("##ServerHost_ServerDesc", "Server description (optional)", &details.description);
ImGui::Spacing();
if (ImGui::BeginCombo("Mode", m_gameMode.c_str()))
{
for (const CUtlString& playlist : g_vecAllPlaylists)
{
const char* const cachedPlaylists = playlist.String();
const char* const selectedPlaylists = details.playlist.c_str();
if (ImGui::Selectable(cachedPlaylists,
playlist.IsEqual_CaseInsensitive(m_gameMode.c_str())))
if (ImGui::BeginCombo("Mode", selectedPlaylists))
{
for (const CUtlString& svPlaylist : g_vecAllPlaylists)
{
const char* const cachedPlaylists = svPlaylist.String();
if (ImGui::Selectable(cachedPlaylists, (strcmp(cachedPlaylists, selectedPlaylists) == 0)))
{
m_gameMode = cachedPlaylists;
details.playlist = svPlaylist;
}
}
ImGui::EndCombo();
}
if (ImGui::BeginCombo("Map", m_levelName.c_str()))
if (ImGui::BeginCombo("Map", details.map.c_str()))
{
g_InstalledMapsMutex.Lock();
for (const CUtlString& mapName : g_InstalledMaps)
FOR_EACH_VEC(g_InstalledMaps, i)
{
const char* const cachedMapName = mapName.String();
const CUtlString& mapName = g_InstalledMaps[i];
if (ImGui::Selectable(cachedMapName,
mapName.IsEqual_CaseInsensitive(m_levelName.c_str())))
if (ImGui::Selectable(mapName.String(),
mapName.IsEqual_CaseInsensitive(details.map.c_str())))
{
m_levelName = cachedMapName;
details.map = mapName.String();
}
}
@ -635,22 +599,37 @@ void CBrowser::DrawHostPanel(void)
const bool serverActive = g_pServer->IsActive();
const bool clientActive = g_pClientState->IsActive();
const bool isOffline = g_ServerHostManager.GetVisibility() == ServerVisibility_e::OFFLINE;
const bool hasName = isOffline ? true : !m_serverName.empty();
if (!g_pHostState->m_bActiveGame)
{
if (ImGui::Button("Start server", ImVec2(contentRegionMax.x, 32)))
{
m_hostMessage.clear();
if (hasName && !m_levelName.empty() && !m_gameMode.empty())
const bool enforceField = g_ServerHostManager.GetVisibility() == ServerVisibility_e::OFFLINE
? true
: !details.name.empty();
if (enforceField && !details.playlist.empty() && !details.map.empty())
{
g_ServerHostManager.LaunchServer(m_levelName.c_str(), m_gameMode.c_str()); // Launch server.
g_ServerHostManager.LaunchServer(serverActive); // Launch server.
}
else
{
HandleInvalidFields(isOffline);
if (details.name.empty())
{
m_hostMessage = "Server name is required.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
else if (details.playlist.empty())
{
m_hostMessage = "Playlist is required.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
else if (details.map.empty())
{
m_hostMessage = "Level name is required.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
}
}
@ -675,14 +654,12 @@ void CBrowser::DrawHostPanel(void)
if (ImGui::Button("Change level", ImVec2(contentRegionMax.x, 32)))
{
if (!m_levelName.empty() && !m_gameMode.empty())
if (!details.map.empty())
{
g_ServerHostManager.ChangeLevel(m_levelName.c_str(), m_gameMode.c_str());
g_ServerHostManager.LaunchServer(serverActive);
}
else
{
HandleInvalidFields(isOffline);
m_hostMessage = "Failed to change level: 'levelname' was empty.";
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
}
@ -806,23 +783,37 @@ void CBrowser::UpdateHostingStatus(void)
}
case HostStatus_e::HOSTING:
{
if (*g_nServerRemoteChecksum == NULL) // Check if script checksum is valid yet.
{
break;
}
const ServerVisibility_e serverVisibility = g_ServerHostManager.GetVisibility();
NetGameServer_t& details = g_ServerHostManager.GetDetails();
if (serverVisibility == ServerVisibility_e::OFFLINE)
{
break;
}
NetGameServer_t netGameServer
if (*g_nServerRemoteChecksum == NULL) // Check if script checksum is valid yet.
{
hostname->GetString(),
hostdesc.GetString(),
serverVisibility == ServerVisibility_e::HIDDEN,
break;
}
switch (serverVisibility)
{
case ServerVisibility_e::HIDDEN:
details.hidden = true;
break;
case ServerVisibility_e::PUBLIC:
details.hidden = false;
break;
default:
break;
}
const NetGameServer_t netGameServer
{
details.name,
details.description,
details.hidden,
g_pHostState->m_levelName,
v_Playlists_GetCurrent(),
hostip->GetString(),
@ -851,10 +842,10 @@ void CBrowser::UpdateHostingStatus(void)
// host data on the server browser
// Input : &gameServer -
//-----------------------------------------------------------------------------
void CBrowser::SendHostingPostRequest(NetGameServer_t& gameServer)
void CBrowser::SendHostingPostRequest(const NetGameServer_t& gameServer)
{
#ifndef CLIENT_DLL
std::thread request([&, gameServer = std::move(gameServer)]
std::thread request([&, gameServer]
{
string hostRequestMessage;
string hostToken;
@ -864,7 +855,7 @@ void CBrowser::SendHostingPostRequest(NetGameServer_t& gameServer)
g_TaskQueue.Dispatch([&, result, hostRequestMessage, hostToken, hostIp]
{
InstallHostingDetails(result, hostRequestMessage, hostToken, hostIp);
InstallHostingDetails(result, hostRequestMessage.c_str(), hostToken.c_str(), hostIp);
}, 0);
}
);
@ -879,7 +870,7 @@ void CBrowser::SendHostingPostRequest(NetGameServer_t& gameServer)
// *hostToken -
// &hostIp -
//-----------------------------------------------------------------------------
void CBrowser::InstallHostingDetails(const bool postFailed, const string& hostMessage, const string& hostToken, const string& hostIp)
void CBrowser::InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp)
{
#ifndef CLIENT_DLL
m_hostMessage = hostMessage;
@ -893,10 +884,14 @@ void CBrowser::InstallHostingDetails(const bool postFailed, const string& hostMe
if (postFailed)
{
m_hostMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f);
stringstream ssMessage;
ssMessage << "Broadcasting";
if (!m_hostToken.empty())
{
ssMessage << ": share the following token for clients to connect: ";
}
m_hostMessage = m_hostToken.empty()
? "Broadcasting"
: "Broadcasting: share the following token for clients to connect: ";
m_hostMessage = ssMessage.str();
}
else
{

View File

@ -26,13 +26,11 @@ public:
void RefreshServerList(void);
void HiddenServersModal(void);
void HandleInvalidFields(const bool offline);
void DrawHostPanel(void);
void UpdateHostingStatus(void);
void InstallHostingDetails(const bool postFailed, const string& hostMessage, const string& hostToken, const string& hostIp);
void SendHostingPostRequest(NetGameServer_t& gameServer);
void InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp);
void SendHostingPostRequest(const NetGameServer_t& gameServer);
void ProcessCommand(const char* pszCommand) const;
@ -74,12 +72,6 @@ private:
////////////////////
string m_hiddenServerRequestMessage;
ImVec4 m_hiddenServerMessageColor;
string m_serverName;
string m_serverDescription;
string m_levelName;
string m_gameMode;
};
extern CBrowser g_Browser;

View File

@ -22,7 +22,6 @@ History:
#include "windows/resource.h"
#include "engine/cmd.h"
#include "gameui/IConsole.h"
#include "imgui_system.h"
//-----------------------------------------------------------------------------
// Console variables
@ -129,6 +128,8 @@ void CConsole::RunFrame(void)
if (m_surfaceStyle == ImGuiStyle_t::MODERN)
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 8.f, 10.f }); baseWindowStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
minBaseWindowRect = ImVec2(621.f, 532.f);
}
else
@ -138,9 +139,9 @@ void CConsole::RunFrame(void)
: ImVec2(618.f, 524.f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 6.f, 6.f }); baseWindowStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
}
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, minBaseWindowRect); baseWindowStyleVars++;
const bool drawn = DrawSurface();
@ -186,9 +187,6 @@ void CConsole::RunFrame(void)
//-----------------------------------------------------------------------------
bool CConsole::DrawSurface(void)
{
if (!IsVisible())
return false;
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_None, &ResetInput))
{
ImGui::End();
@ -281,6 +279,20 @@ bool CConsole::DrawSurface(void)
ImGui::Text("%s", m_summaryTextBuf);
const std::function<void(void)> fnHandleInput = [&](void)
{
if (m_inputTextBuf[0])
{
ProcessCommand(m_inputTextBuf);
ResetAutoCompleteData();
m_inputTextBufModified = true;
}
BuildSummaryText("");
m_reclaimFocus = true;
};
///////////////////////////////////////////////////////////////////////
const static int inputTextFieldFlags =
ImGuiInputTextFlags_EnterReturnsTrue |
@ -298,19 +310,18 @@ bool CConsole::DrawSurface(void)
// command from that instead
if (m_suggestPos > ConAutoCompletePos_e::kPark)
{
HandleSuggest();
DetermineInputTextFromSelectedSuggestion(m_vecSuggest[m_suggestPos], m_selectedSuggestionText);
BuildSummaryText(m_selectedSuggestionText.c_str());
m_inputTextBufModified = true;
m_reclaimFocus = true;
}
else
{
HandleCommand();
fnHandleInput();
}
}
if (ImGui::IsKeyPressed(ImGuiKey_Tab))
{
HandleSuggest();
}
// Auto-focus input field on window apparition.
ImGui::SetItemDefaultFocus();
@ -326,7 +337,7 @@ bool CConsole::DrawSurface(void)
ImGui::SameLine();
if (ImGui::Button("Submit"))
{
HandleCommand();
fnHandleInput();
}
ImGui::End();
@ -341,176 +352,43 @@ void CConsole::DrawOptionsPanel(void)
ImGui::Checkbox("Auto-scroll", &m_colorTextLogger.m_bAutoScroll);
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
ImGui::PushItemWidth(100);
if (ImGui::SmallButton("Clear Text"))
ImGui::PopItemWidth();
if (ImGui::SmallButton("Clear"))
{
ClearLog();
}
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
// Copies all logged text to the clip board
if (ImGui::SmallButton("Copy Text"))
if (ImGui::SmallButton("Copy"))
{
AUTO_LOCK(m_colorTextLoggerMutex);
m_colorTextLogger.Copy(true);
}
ImGui::TextEx("Console HotKey:", nullptr, ImGuiTextFlags_NoWidthForLargeClippedText);
ImGui::Text("Console hotkey:");
ImGui::SameLine();
int selected = g_ImGuiConfig.m_ConsoleConfig.m_nBind0;
if (ImGui::Hotkey("##ToggleConsolePrimary", &selected, ImVec2(80, 80)) &&
!g_ImGuiConfig.KeyUsed(selected))
if (ImGui::Hotkey("##ToggleConsole", &g_ImGuiConfig.m_ConsoleConfig.m_nBind0, ImVec2(80, 80)))
{
g_ImGuiConfig.m_ConsoleConfig.m_nBind0 = selected;
g_ImGuiConfig.Save();
}
ImGui::SameLine();
selected = g_ImGuiConfig.m_ConsoleConfig.m_nBind1;
if (ImGui::Hotkey("##ToggleConsoleSecondary", &selected, ImVec2(80, 80)) &&
!g_ImGuiConfig.KeyUsed(selected))
{
g_ImGuiConfig.m_ConsoleConfig.m_nBind1 = selected;
g_ImGuiConfig.Save();
}
ImGui::TextEx("Browser HotKey:", nullptr, ImGuiTextFlags_NoWidthForLargeClippedText);
ImGui::Text("Browser hotkey:");
ImGui::SameLine();
selected = g_ImGuiConfig.m_BrowserConfig.m_nBind0;
if (ImGui::Hotkey("##ToggleBrowserPrimary", &selected, ImVec2(80, 80)) &&
!g_ImGuiConfig.KeyUsed(selected))
if (ImGui::Hotkey("##ToggleBrowser", &g_ImGuiConfig.m_BrowserConfig.m_nBind0, ImVec2(80, 80)))
{
g_ImGuiConfig.m_BrowserConfig.m_nBind0 = selected;
g_ImGuiConfig.Save();
}
ImGui::SameLine();
selected = g_ImGuiConfig.m_BrowserConfig.m_nBind1;
if (ImGui::Hotkey("##ToggleBrowserSecondary", &selected, ImVec2(80, 80)) &&
!g_ImGuiConfig.KeyUsed(selected))
{
g_ImGuiConfig.m_BrowserConfig.m_nBind1 = selected;
g_ImGuiConfig.Save();
}
ImGui::EndPopup();
}
//-----------------------------------------------------------------------------
// Purpose: returns flag texture index for CommandBase (must be aligned with resource.h!)
// in the future we should build the texture procedurally with use of popcnt.
// Input : nFlags -
//-----------------------------------------------------------------------------
static int GetFlagTextureIndex(const int flags)
{
switch (flags) // All indices for single/dual flag textures.
{
case FCVAR_DEVELOPMENTONLY:
return 9;
case FCVAR_GAMEDLL:
return 10;
case FCVAR_CLIENTDLL:
return 11;
case FCVAR_REPLICATED:
return 12;
case FCVAR_CHEAT:
return 13;
case FCVAR_RELEASE:
return 14;
case FCVAR_MATERIAL_SYSTEM_THREAD:
return 15;
case FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL:
return 16;
case FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL:
return 17;
case FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED:
return 18;
case FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT:
return 19;
case FCVAR_DEVELOPMENTONLY | FCVAR_MATERIAL_SYSTEM_THREAD:
return 20;
case FCVAR_REPLICATED | FCVAR_CHEAT:
return 21;
case FCVAR_REPLICATED | FCVAR_RELEASE:
return 22;
case FCVAR_GAMEDLL | FCVAR_CHEAT:
return 23;
case FCVAR_GAMEDLL | FCVAR_RELEASE:
return 24;
case FCVAR_CLIENTDLL | FCVAR_CHEAT:
return 25;
case FCVAR_CLIENTDLL | FCVAR_RELEASE:
return 26;
case FCVAR_MATERIAL_SYSTEM_THREAD | FCVAR_CHEAT:
return 27;
case FCVAR_MATERIAL_SYSTEM_THREAD | FCVAR_RELEASE:
return 28;
case COMMAND_COMPLETION_MARKER:
return 29;
default: // Hit when flag is zero/non-indexed or 3+ bits are set.
const unsigned int v = __popcnt(flags);
switch (v)
{
case 0:
return 0; // Pink checker texture (FCVAR_NONE)
case 1:
return 1; // Yellow checker texture (non-indexed).
default:
// If 3 or more bits are set, we test the flags
// and display the appropriate checker texture.
const bool mul = v > 2;
if (flags & FCVAR_DEVELOPMENTONLY)
{
return mul ? 4 : 3;
}
else if (flags & FCVAR_CHEAT)
{
return mul ? 6 : 5;
}
else if (flags & FCVAR_RELEASE && // RELEASE command but no context restriction.
!(flags & FCVAR_SERVER_CAN_EXECUTE) &&
!(flags & FCVAR_CLIENTCMD_CAN_EXECUTE))
{
return mul ? 8 : 7;
}
// Rainbow checker texture (user needs to manually check flags).
// These commands are not restricted if ran from the same context.
return 2;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: adds an icon hint to the suggest panel
// Input : &cvarInfo -
// &flagIconHandles -
//-----------------------------------------------------------------------------
static void AddHint(const ConVarFlags::FlagDesc_t& cvarInfo, const vector<MODULERESOURCE>& flagIconHandles)
{
const int hintTexIdx = GetFlagTextureIndex(cvarInfo.bit);
const MODULERESOURCE& hintRes = flagIconHandles[hintTexIdx];
ImGui::Image(hintRes.m_idIcon, ImVec2(float(hintRes.m_nWidth), float(hintRes.m_nHeight)));
ImGui::SameLine();
ImGui::TextEx(cvarInfo.shortdesc, nullptr, ImGuiTextFlags_NoWidthForLargeClippedText);
};
//-----------------------------------------------------------------------------
// Purpose: draws the autocomplete panel with results based on user input
//-----------------------------------------------------------------------------
@ -555,6 +433,16 @@ void CConsole::DrawAutoCompletePanel(void)
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly) &&
suggest.flags != COMMAND_COMPLETION_MARKER)
{
const std::function<void(const ConVarFlags::FlagDesc_t&)> fnAddHint = [&](const ConVarFlags::FlagDesc_t& cvarInfo)
{
const int hintTexIdx = GetFlagTextureIndex(cvarInfo.bit);
const MODULERESOURCE& hintRes = m_vecFlagIcons[hintTexIdx];
ImGui::Image(hintRes.m_idIcon, ImVec2(float(hintRes.m_nWidth), float(hintRes.m_nHeight)));
ImGui::SameLine();
ImGui::Text("%s", cvarInfo.shortdesc);
};
ImGui::BeginTooltip();
bool isFlagSet = false;
@ -565,12 +453,12 @@ void CConsole::DrawAutoCompletePanel(void)
if (suggest.flags & info.bit)
{
isFlagSet = true;
AddHint(info, m_vecFlagIcons);
fnAddHint(info);
}
}
if (!isFlagSet) // Display the FCVAR_NONE flag if no flags are set.
{
AddHint(g_ConVarFlags.m_FlagsToDesc[0], m_vecFlagIcons);
fnAddHint(g_ConVarFlags.m_FlagsToDesc[0]);
}
ImGui::EndTooltip();
@ -590,7 +478,7 @@ void CConsole::DrawAutoCompletePanel(void)
m_canAutoComplete = true;
m_reclaimFocus = true;
BuildSummaryText(newInputText.c_str(), newInputText.size());
BuildSummaryText(newInputText.c_str());
}
ImGui::PopID();
@ -665,7 +553,7 @@ bool CConsole::RunAutoComplete(void)
{
const char c = m_inputTextBuf[i];
if (c == '\0' || V_isspace(c))
if (c == '\0' || isspace(c))
{
break;
}
@ -688,8 +576,7 @@ bool CConsole::RunAutoComplete(void)
for (int j = 0; j < iret; ++j)
{
const CUtlString& cmdToAdd = commands[j];
m_vecSuggest.emplace_back(cmdToAdd.String(), cmdToAdd.Length(), COMMAND_COMPLETION_MARKER);
m_vecSuggest.push_back(ConAutoCompleteSuggest_s(commands[j].String(), COMMAND_COMPLETION_MARKER));
}
}
else
@ -719,40 +606,6 @@ void CConsole::ResetAutoCompleteData(void)
m_vecSuggest.clear();
}
template <size_t N1, size_t N2>
static void EncaseAppendString(string& targetString, const char* toEncase, const char(&open)[N1], const char(&close)[N2])
{
const size_t appLen = strlen(toEncase);
const size_t newLen = targetString.length() + (N1-1) + (N2-1) + appLen+1;
targetString.reserve(newLen);
targetString.append(open, N1-1);
targetString.append(toEncase, appLen);
targetString.append(close, N2-1);
}
//-----------------------------------------------------------------------------
// Purpose: format appends the value string
//-----------------------------------------------------------------------------
static void AppendValueString(string& targetString, const char* const toAppend)
{
EncaseAppendString(targetString, toAppend, " = [", "]");
}
//-----------------------------------------------------------------------------
// Purpose: format appends the doc string
//-----------------------------------------------------------------------------
static void AppendDocString(string& targetString, const char* const toAppend)
{
if (!VALID_CHARSTAR(toAppend))
{
return;
}
EncaseAppendString(targetString, toAppend, " - \"", "\"");
}
//-----------------------------------------------------------------------------
// Purpose: find ConVars/ConCommands from user input and add to vector
// - Ignores ConVars marked FCVAR_HIDDEN
@ -788,18 +641,30 @@ void CConsole::CreateSuggestionsFromPartial(void)
{
string docString;
// Assign current value to string if its a ConVar.
if (!commandBase->IsCommand())
{
const ConVar* const conVar = reinterpret_cast<const ConVar*>(commandBase);
AppendValueString(docString, conVar->GetString());
const ConVar* conVar = reinterpret_cast<const ConVar*>(commandBase);
docString = " = ["; // Assign current value to string if its a ConVar.
docString.append(conVar->GetString());
docString.append("]");
}
if (con_suggest_helptext.GetBool())
{
AppendDocString(docString, commandBase->GetHelpText());
AppendDocString(docString, commandBase->GetUsageText());
std::function<void(string& , const char*)> fnAppendDocString = [&](string& targetString, const char* toAppend)
{
if (VALID_CHARSTAR(toAppend))
{
targetString.append(" - \"");
targetString.append(toAppend);
targetString.append("\"");
}
};
fnAppendDocString(docString, commandBase->GetHelpText());
fnAppendDocString(docString, commandBase->GetUsageText());
}
m_vecSuggest.emplace_back(commandName + docString, commandBase->GetFlags());
m_vecSuggest.push_back(ConAutoCompleteSuggest_s(commandName + docString, commandBase->GetFlags()));
}
else
{
@ -839,11 +704,11 @@ void CConsole::ProcessCommand(const char* const inputText)
// formats the number of history items instead
// Input : inputText -
//-----------------------------------------------------------------------------
void CConsole::BuildSummaryText(const char* const inputText, const size_t textLen)
void CConsole::BuildSummaryText(const char* const inputText)
{
if (textLen > 0)
if (*inputText)
{
string conVarFormatted(inputText, textLen);
string conVarFormatted(inputText);
// Remove trailing space and/or semicolon before we call 'g_pCVar->FindVar(..)'.
StringRTrim(conVarFormatted, " ;", true);
@ -924,25 +789,117 @@ void CConsole::DetermineAutoCompleteWindowRect(void)
//-----------------------------------------------------------------------------
bool CConsole::LoadFlagIcons(void)
{
HMODULE sdkModule = reinterpret_cast<HMODULE>(g_SDKDll.GetModuleBase());
bool ret = false;
// Get all flag image resources for displaying flags.
for (int i = IDB_PNG3, k = NULL; i <= IDB_PNG32; i++, k++)
{
m_vecFlagIcons.emplace_back(GetModuleResource(sdkModule, i));
m_vecFlagIcons.push_back(MODULERESOURCE(GetModuleResource(i)));
MODULERESOURCE& rFlagIcon = m_vecFlagIcons[k];
ret = LoadTextureBuffer(reinterpret_cast<unsigned char*>(rFlagIcon.m_pData), // !TODO: Fall-back texture.
static_cast<int>(rFlagIcon.m_nSize), &rFlagIcon.m_idIcon, &rFlagIcon.m_nWidth, &rFlagIcon.m_nHeight);
Assert(ret, "Texture flags load failed for %i", i);
if (!ret)
{
Assert(0, "Texture flags load failed for %i", i);
break;
}
}
m_autoCompleteTexturesLoaded = ret;
return ret;
}
//-----------------------------------------------------------------------------
// Purpose: returns flag texture index for CommandBase (must be aligned with resource.h!)
// in the future we should build the texture procedurally with use of popcnt.
// Input : nFlags -
//-----------------------------------------------------------------------------
int CConsole::GetFlagTextureIndex(const int flags) const
{
switch (flags) // All indices for single/dual flag textures.
{
case FCVAR_DEVELOPMENTONLY:
return 9;
case FCVAR_GAMEDLL:
return 10;
case FCVAR_CLIENTDLL:
return 11;
case FCVAR_REPLICATED:
return 12;
case FCVAR_CHEAT:
return 13;
case FCVAR_RELEASE:
return 14;
case FCVAR_MATERIAL_SYSTEM_THREAD:
return 15;
case FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL:
return 16;
case FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL:
return 17;
case FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED:
return 18;
case FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT:
return 19;
case FCVAR_DEVELOPMENTONLY | FCVAR_MATERIAL_SYSTEM_THREAD:
return 20;
case FCVAR_REPLICATED | FCVAR_CHEAT:
return 21;
case FCVAR_REPLICATED | FCVAR_RELEASE:
return 22;
case FCVAR_GAMEDLL | FCVAR_CHEAT:
return 23;
case FCVAR_GAMEDLL | FCVAR_RELEASE:
return 24;
case FCVAR_CLIENTDLL | FCVAR_CHEAT:
return 25;
case FCVAR_CLIENTDLL | FCVAR_RELEASE:
return 26;
case FCVAR_MATERIAL_SYSTEM_THREAD | FCVAR_CHEAT:
return 27;
case FCVAR_MATERIAL_SYSTEM_THREAD | FCVAR_RELEASE:
return 28;
case COMMAND_COMPLETION_MARKER:
return 29;
default: // Hit when flag is zero/non-indexed or 3+ bits are set.
const unsigned int v = __popcnt(flags);
switch (v)
{
case 0:
return 0; // Pink checker texture (FCVAR_NONE)
case 1:
return 1; // Yellow checker texture (non-indexed).
default:
// If 3 or more bits are set, we test the flags
// and display the appropriate checker texture.
bool mul = v > 2;
if (flags & FCVAR_DEVELOPMENTONLY)
{
return mul ? 4 : 3;
}
else if (flags & FCVAR_CHEAT)
{
return mul ? 6 : 5;
}
else if (flags & FCVAR_RELEASE && // RELEASE command but no context restriction.
!(flags & FCVAR_SERVER_CAN_EXECUTE) &&
!(flags & FCVAR_CLIENTCMD_CAN_EXECUTE))
{
return mul ? 8 : 7;
}
// Rainbow checker texture (user needs to manually check flags).
// These commands are not restricted if ran from the same context.
return 2;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: console input box callback
// Input : *iData -
@ -1033,7 +990,7 @@ int CConsole::TextEditCallback(ImGuiInputTextCallbackData* iData)
}
}
BuildSummaryText(iData->Buf, iData->BufTextLen);
BuildSummaryText(iData->Buf);
break;
}
case ImGuiInputTextFlags_CallbackAlways:
@ -1098,7 +1055,7 @@ int CConsole::TextEditCallback(ImGuiInputTextCallbackData* iData)
ResetAutoCompleteData();
}
BuildSummaryText(iData->Buf, iData->BufTextLen);
BuildSummaryText(iData->Buf);
break;
}
}
@ -1117,50 +1074,6 @@ int CConsole::TextEditCallbackStub(ImGuiInputTextCallbackData* iData)
return pConsole->TextEditCallback(iData);
}
//-----------------------------------------------------------------------------
// Purpose: handle anything in the command buffer
//-----------------------------------------------------------------------------
void CConsole::HandleCommand()
{
if (m_inputTextBuf[0])
{
ProcessCommand(m_inputTextBuf);
ResetAutoCompleteData();
m_inputTextBufModified = true;
}
BuildSummaryText("", 0);
m_reclaimFocus = true;
}
//-----------------------------------------------------------------------------
// Purpose: handle the suggested item that was selected
//-----------------------------------------------------------------------------
void CConsole::HandleSuggest()
{
const bool parked = m_suggestPos == ConAutoCompletePos_e::kPark;
if (parked && m_vecSuggest.empty())
{
return;
}
// Note: we should never be able to move the suggest pos
// if the suggest list is empty. Suggest pos must always
// be cleared if the list is cleared.
Assert(!m_vecSuggest.empty());
// Use the first item if the suggest position is parked.
const int vecIndex = parked ? 0 : m_suggestPos;
DetermineInputTextFromSelectedSuggestion(m_vecSuggest[vecIndex], m_selectedSuggestionText);
BuildSummaryText(m_selectedSuggestionText.c_str(), m_selectedSuggestionText.size());
m_inputTextBufModified = true;
m_reclaimFocus = true;
}
//-----------------------------------------------------------------------------
// Purpose: adds logs to the console; this is the only place text is added to
// the vector, do not call 'm_Logger.InsertText' elsewhere as we also manage
@ -1169,11 +1082,6 @@ void CConsole::HandleSuggest()
//-----------------------------------------------------------------------------
void CConsole::AddLog(const char* const text, const ImU32 color)
{
if (!ImguiSystem()->IsEnabled())
{
return;
}
AUTO_LOCK(m_colorTextLoggerMutex);
m_colorTextLogger.InsertText(text, color);
@ -1277,7 +1185,7 @@ void CConsole::ClampLogSize(void)
//-----------------------------------------------------------------------------
// Purpose: adds a command to the history vector; this is the only place text
// is added to the vector, do not call 'm_History.emplace_back' elsewhere as we
// is added to the vector, do not call 'm_History.push_back' elsewhere as we
// also manage the size of the vector here !!!
//-----------------------------------------------------------------------------
void CConsole::AddHistory(const char* const command)
@ -1293,7 +1201,7 @@ void CConsole::AddHistory(const char* const command)
}
}
m_vecHistory.emplace_back(command);
m_vecHistory.push_back(command);
ClampHistorySize();
}
@ -1312,7 +1220,7 @@ const vector<string>& CConsole::GetHistory(void) const
void CConsole::ClearHistory(void)
{
m_vecHistory.clear();
BuildSummaryText("", 0);
BuildSummaryText("");
}
//-----------------------------------------------------------------------------

View File

@ -30,13 +30,14 @@ private:
void CreateSuggestionsFromPartial(void);
void ProcessCommand(const char* const inputText);
void BuildSummaryText(const char* const inputText, const size_t textLen);
void BuildSummaryText(const char* const inputText);
struct ConAutoCompleteSuggest_s;
void DetermineInputTextFromSelectedSuggestion(const ConAutoCompleteSuggest_s& suggest, string& svInput);
void DetermineAutoCompleteWindowRect(void);
bool LoadFlagIcons(void);
int GetFlagTextureIndex(const int flags) const;
int TextEditCallback(ImGuiInputTextCallbackData* pData);
static int TextEditCallbackStub(ImGuiInputTextCallbackData* pData);
@ -60,9 +61,6 @@ public:
static void ClearHistory_f();
private: // Internals.
void HandleCommand();
void HandleSuggest();
void AddLog(const ImU32 color, const char* fmt, ...) /*IM_FMTARGS(2)*/;
void ClampLogSize(void);
@ -71,8 +69,7 @@ private: // Internals.
private:
enum ConAutoCompletePos_e
{
// Park means the auto complete position is out of screen and not
// indexing an item.
// Park means the position is out of screen.
kPark = -1,
};
@ -83,11 +80,6 @@ private:
text = inText;
flags = inFlags;
}
ConAutoCompleteSuggest_s(const char* inText, const size_t len, const int inFlags)
{
text.assign(inText, len);
flags = inFlags;
}
bool operator==(const string& a) const
{
return text.compare(a) == 0;

View File

@ -1,218 +0,0 @@
/******************************************************************************
-------------------------------------------------------------------------------
File : IStreamOverlay.cpp
Date : 08:01:2025
Author : Kawe Mazidjatari
Purpose: Implements the in-game texture streaming debug overlay
-------------------------------------------------------------------------------
History:
- 08:01:2025 | 19:05 : Created by Kawe Mazidjatari
******************************************************************************/
#include "windows/id3dx.h"
#include "materialsystem/texturestreaming.h"
#include "IStreamOverlay.h"
//-----------------------------------------------------------------------------
// Console variables
//-----------------------------------------------------------------------------
static ConVar stream_overlay_memory("stream_overlay_memory", "524288", FCVAR_DEVELOPMENTONLY, "Total string memory to allocate for the texture streaming debug overlay.", true, 1.f, false, 0.0f);
//-----------------------------------------------------------------------------
// Console commands
//-----------------------------------------------------------------------------
static ConCommand stream_dumpinfo("stream_dumpinfo", CStreamOverlay::DumpStreamInfo_f, "Dump texture streaming debug info to the console", FCVAR_DEVELOPMENTONLY, nullptr, "tex mtl bsp short");
//-----------------------------------------------------------------------------
// Purpose: constructor/destructor
//-----------------------------------------------------------------------------
CStreamOverlay::CStreamOverlay(void)
{
m_surfaceLabel = "Stream Overlay";
m_scratchBuffer = nullptr;
m_scratchBufferSize = 0;
m_lastAvailability = false;
}
CStreamOverlay::~CStreamOverlay(void)
{
Shutdown();
}
//-----------------------------------------------------------------------------
// Purpose: stream overlay initialization
//-----------------------------------------------------------------------------
bool CStreamOverlay::Init(void)
{
SetStyleVar(1200, 524, -1000, 50);
m_initialized = true;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: stream overlay shutdown
//-----------------------------------------------------------------------------
void CStreamOverlay::Shutdown(void)
{
FreeScratchBuffer();
m_initialized = false;
}
//-----------------------------------------------------------------------------
// Purpose: check value of stream_overlay and determine availability of window
//-----------------------------------------------------------------------------
void CStreamOverlay::UpdateWindowAvailability(void)
{
const bool enabled = stream_overlay->GetBool();
if (enabled == m_lastAvailability)
return;
if (!enabled && m_activated)
{
m_activated = false;
ResetInput();
}
else if (enabled && !m_activated)
m_activated = true;
m_lastAvailability = enabled;
}
//-----------------------------------------------------------------------------
// Purpose: run stream overlay frame
//-----------------------------------------------------------------------------
void CStreamOverlay::RunFrame(void)
{
if (!m_initialized)
Init();
Animate();
int baseWindowStyleVars = 0;
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
const bool drawn = DrawSurface();
ImGui::PopStyleVar(baseWindowStyleVars);
if (!drawn)
FreeScratchBuffer();
UpdateWindowAvailability();
}
//-----------------------------------------------------------------------------
// Purpose: syncs the cvar and updates the availability of mouse/key inputs
//-----------------------------------------------------------------------------
static void StreamOverlay_HandleClose(void)
{
stream_overlay->SetValue(false);
ResetInput();
}
//-----------------------------------------------------------------------------
// Purpose: draw stream overlay
//-----------------------------------------------------------------------------
bool CStreamOverlay::DrawSurface(void)
{
if (!IsVisible())
return false;
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_None, &StreamOverlay_HandleClose))
{
ImGui::End();
return false;
}
if (ImGui::BeginChild("##StreamReport", ImVec2(-1, -1), ImGuiChildFlags_Border, ImGuiWindowFlags_None))
{
ResizeScratchBuffer(stream_overlay_memory.GetInt());
TextureStreamMgr_GetStreamOverlay(stream_overlay_mode->GetString(), m_scratchBuffer, m_scratchBufferSize);
ImGui::TextUnformatted(m_scratchBuffer);
}
ImGui::EndChild();
ImGui::End();
return true;
}
//-----------------------------------------------------------------------------
// Purpose: dynamically scale the scratch buffer if it became smaller or larger
//-----------------------------------------------------------------------------
void CStreamOverlay::ResizeScratchBuffer(const size_t newSize)
{
Assert(newSize > 0);
if (newSize == m_scratchBufferSize)
return; // Same size.
if (m_scratchBuffer)
delete[] m_scratchBuffer;
m_scratchBuffer = new char[newSize];
m_scratchBufferSize = newSize;
}
//-----------------------------------------------------------------------------
// Purpose: free the scratch buffer if we have one
//-----------------------------------------------------------------------------
void CStreamOverlay::FreeScratchBuffer(void)
{
if (m_scratchBuffer)
{
delete[] m_scratchBuffer;
m_scratchBuffer = nullptr;
m_scratchBufferSize = 0;
}
else
Assert(m_scratchBufferSize == 0);
}
//-----------------------------------------------------------------------------
// Purpose: render current streaming data to console with given or default mode
//-----------------------------------------------------------------------------
void CStreamOverlay::RenderToConsole(const char* const mode)
{
const bool isTemp = m_scratchBuffer == nullptr;
// If we have a buffer already, use that to render the overlay report into
// it. Else create a temporary buffer and free it afterwards.
if (isTemp)
{
const size_t targetBufLen = stream_overlay_memory.GetInt();
m_scratchBuffer = new char[targetBufLen];
m_scratchBufferSize = targetBufLen;
}
TextureStreamMgr_GetStreamOverlay(mode ? mode : stream_overlay_mode->GetString(), m_scratchBuffer, m_scratchBufferSize);
Msg(eDLL_T::MS, "%s\n", m_scratchBuffer);
if (isTemp)
{
delete[] m_scratchBuffer;
m_scratchBuffer = nullptr;
m_scratchBufferSize = 0;
}
}
CStreamOverlay g_streamOverlay;
/*
=====================
DumpStreamInfo_f
Dumps the stream info to the console.
=====================
*/
void CStreamOverlay::DumpStreamInfo_f(const CCommand& args)
{
const char* const mode = args.ArgC() >= 2 ? args.Arg(1) : nullptr;
g_streamOverlay.RenderToConsole(mode);
}

View File

@ -1,36 +0,0 @@
#pragma once
#include "imgui/misc/imgui_logger.h"
#include "imgui/misc/imgui_utility.h"
#include "imgui_surface.h"
class CStreamOverlay : public CImguiSurface
{
public:
CStreamOverlay(void);
~CStreamOverlay(void);
virtual bool Init(void);
virtual void Shutdown(void);
virtual void RunFrame(void);
virtual bool DrawSurface(void);
void UpdateWindowAvailability(void);
void ResizeScratchBuffer(const size_t newSize);
void FreeScratchBuffer(void);
void RenderToConsole(const char* const mode);
// Command callbacks.
static void DumpStreamInfo_f(const CCommand& args);
private:
char* m_scratchBuffer;
size_t m_scratchBufferSize;
bool m_lastAvailability;
};
extern CStreamOverlay g_streamOverlay;

View File

@ -23,8 +23,8 @@ public:
// inlines:
inline void ToggleActive() { m_activated ^= true; }
inline bool IsActivated() const { return m_activated; }
inline bool IsVisible() const { return m_fadeAlpha > 0.0f; }
inline bool IsActivated() { return m_activated; }
inline bool IsVisible() { return m_fadeAlpha > 0.0f; }
protected:
const char* m_surfaceLabel;

View File

@ -8,16 +8,17 @@
#include "engine/sys_mainwind.h"
#include "windows/id3dx.h"
#include "IBrowser.h"
#include "IConsole.h"
#include "imgui_system.h"
//-----------------------------------------------------------------------------
// Constructors/Destructors.
//-----------------------------------------------------------------------------
CImguiSystem::CImguiSystem()
: m_enabled(true)
, m_initialized(false)
, m_hasNewFrame(false)
{
m_systemInitState = ImguiSystemInitStage_e::IM_PENDING_INIT;
}
//-----------------------------------------------------------------------------
@ -27,19 +28,14 @@ CImguiSystem::CImguiSystem()
bool CImguiSystem::Init()
{
Assert(ThreadInMainThread(), "CImguiSystem::Init() should only be called from the main thread!");
Assert(!IsInitialized(), "CImguiSystem::Init() called recursively?");
Assert(IsEnabled(), "CImguiSystem::Init() called while system was disabled!");
Assert(m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT, "CImguiSystem::Init() called recursively?");
///////////////////////////////////////////////////////////////////////////
IMGUI_CHECKVERSION();
ImGuiContext* const context = ImGui::CreateContext();
if (!context)
{
m_enabled = false;
return false;
}
AUTO_LOCK(m_snapshotBufferMutex);
AUTO_LOCK(m_inputEventQueueMutex);
@ -60,13 +56,11 @@ bool CImguiSystem::Init()
{
Assert(0);
m_enabled = false;
m_systemInitState = ImguiSystemInitStage_e::IM_INIT_FAILURE;
return false;
}
m_initialized = true;
m_hasNewFrame = false;
m_systemInitState = ImguiSystemInitStage_e::IM_SYSTEM_INIT;
return true;
}
@ -76,66 +70,23 @@ bool CImguiSystem::Init()
void CImguiSystem::Shutdown()
{
Assert(ThreadInMainThread(), "CImguiSystem::Shutdown() should only be called from the main thread!");
Assert(IsInitialized(), "CImguiSystem::Shutdown() called recursively?");
Assert(m_systemInitState != ImguiSystemInitStage_e::IM_PENDING_INIT, "CImguiSystem::Shutdown() called recursively?");
Assert(IsEnabled(), "CImguiSystem::Shutdown() called while system was disabled!");
// Nothing to shutdown.
if (m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT)
return;
AUTO_LOCK(m_snapshotBufferMutex);
AUTO_LOCK(m_inputEventQueueMutex);
m_systemInitState = ImguiSystemInitStage_e::IM_PENDING_INIT;
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
m_snapshotData.Clear();
m_initialized = false;
m_hasNewFrame = false;
m_surfaceList.Purge();
}
//-----------------------------------------------------------------------------
// Add an imgui surface.
//-----------------------------------------------------------------------------
void CImguiSystem::AddSurface(CImguiSurface* const surface)
{
Assert(IsInitialized());
m_surfaceList.AddToTail(surface);
}
//-----------------------------------------------------------------------------
// Remove an imgui surface.
//-----------------------------------------------------------------------------
void CImguiSystem::RemoveSurface(CImguiSurface* const surface)
{
Assert(!IsInitialized());
m_surfaceList.FindAndRemove(surface);
}
//-----------------------------------------------------------------------------
// Draws the ImGui panels and applies all queued input events.
//-----------------------------------------------------------------------------
void CImguiSystem::SampleFrame()
{
Assert(ThreadInMainThread(), "CImguiSystem::SampleFrame() should only be called from the main thread!");
Assert(IsInitialized());
AUTO_LOCK(m_inputEventQueueMutex);
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
FOR_EACH_VEC(m_surfaceList, i)
{
CImguiSurface* const surface = m_surfaceList[i];
surface->RunFrame();
}
ImGui::EndFrame();
ImGui::Render();
}
//-----------------------------------------------------------------------------
@ -146,19 +97,48 @@ void CImguiSystem::SampleFrame()
void CImguiSystem::SwapBuffers()
{
Assert(ThreadInMainThread(), "CImguiSystem::SwapBuffers() should only be called from the main thread!");
Assert(IsInitialized());
ImDrawData* const drawData = ImGui::GetDrawData();
Assert(drawData);
// Nothing has been drawn, nothing to swap.
if (!drawData->CmdListsCount)
if (m_systemInitState < ImguiSystemInitStage_e::IM_FRAME_SAMPLED)
return;
AUTO_LOCK(m_snapshotBufferMutex);
ImDrawData* const drawData = ImGui::GetDrawData();
// Nothing has been drawn, nothing to swap
if (!drawData)
return;
m_snapshotData.SnapUsingSwap(drawData, ImGui::GetTime());
m_hasNewFrame = true;
if (m_systemInitState == ImguiSystemInitStage_e::IM_FRAME_SAMPLED)
m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_SWAPPED;
}
//-----------------------------------------------------------------------------
// Draws the ImGui panels and applies all queued input events.
//-----------------------------------------------------------------------------
void CImguiSystem::SampleFrame()
{
Assert(ThreadInMainThread(), "CImguiSystem::SampleFrame() should only be called from the main thread!");
if (m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT)
return;
AUTO_LOCK(m_inputEventQueueMutex);
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
g_Browser.RunFrame();
g_Console.RunFrame();
ImGui::EndFrame();
ImGui::Render();
if (m_systemInitState == ImguiSystemInitStage_e::IM_SYSTEM_INIT)
m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_SAMPLED;
}
//-----------------------------------------------------------------------------
@ -166,27 +146,16 @@ void CImguiSystem::SwapBuffers()
//-----------------------------------------------------------------------------
void CImguiSystem::RenderFrame()
{
Assert(IsInitialized());
if (!m_hasNewFrame.exchange(false))
if (m_systemInitState < ImguiSystemInitStage_e::IM_FRAME_SWAPPED)
return;
AUTO_LOCK(m_snapshotBufferMutex);
ImGui_ImplDX11_RenderDrawData(&m_snapshotData.DrawData);
}
//-----------------------------------------------------------------------------
// Checks whether we have an active surface.
//-----------------------------------------------------------------------------
bool CImguiSystem::IsSurfaceActive() const
{
FOR_EACH_VEC(m_surfaceList, i)
{
if (m_surfaceList[i]->IsActivated())
return true;
AUTO_LOCK(m_snapshotBufferMutex);
ImGui_ImplDX11_RenderDrawData(&m_snapshotData.DrawData);
}
return false;
if (m_systemInitState == ImguiSystemInitStage_e::IM_FRAME_SAMPLED)
m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_RENDERED;
}
//-----------------------------------------------------------------------------
@ -194,9 +163,6 @@ bool CImguiSystem::IsSurfaceActive() const
//-----------------------------------------------------------------------------
LRESULT CImguiSystem::MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (!ImguiSystem()->IsInitialized())
return NULL;
AUTO_LOCK(ImguiSystem()->m_inputEventQueueMutex);
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

View File

@ -6,7 +6,6 @@
#ifndef IMGUI_SYSTEM_H
#define IMGUI_SYSTEM_H
#include "imgui/misc/imgui_snapshot.h"
#include "imgui_surface.h"
class CImguiSystem
{
@ -16,47 +15,54 @@ public:
bool Init();
void Shutdown();
void AddSurface(CImguiSurface* const surface);
void RemoveSurface(CImguiSurface* const surface);
void SwapBuffers();
void SampleFrame();
void RenderFrame();
bool IsSurfaceActive() const;
// statics:
static LRESULT MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
// inlines:
inline bool IsEnabled() const { return m_enabled; };
inline bool IsInitialized() const { return m_initialized; };
// when explicitly disabled, surfaces such as the console could query
// whether to run code that isn't directly tied to rendering, i.e. to
// check if we should store logs for rendering.
inline void SetEnabled(const bool enable) { Assert(!m_initialized); m_enabled = enable; }
inline bool IsInitialized() const
{
return m_systemInitState >= ImguiSystemInitStage_e::IM_SYSTEM_INIT;
};
private:
enum class ImguiSystemInitStage_e
{
// When the system failed to initialize, the stage would be set to
// this.
IM_INIT_FAILURE = -1,
IM_PENDING_INIT,
IM_SYSTEM_INIT,
// State gets set to this when the first frame has been sampled.
IM_FRAME_SAMPLED,
// State gets set to this then buffers have been swapped for the first
// time.
IM_FRAME_SWAPPED,
// Rendered for the first time.
IM_FRAME_RENDERED
};
ImguiSystemInitStage_e m_systemInitState;
ImDrawDataSnapshot m_snapshotData;
CUtlVector<CImguiSurface*> m_surfaceList;
// Mutex used during swapping and rendering, we draw the windows in the
// main thread, and render it in the render thread. The only place this
// mutex is used is during snapshot swapping and during rendering
mutable CThreadMutex m_snapshotBufferMutex;
mutable CThreadFastMutex m_snapshotBufferMutex;
// Mutex used between ImGui window procedure handling and drawing, see
// https://github.com/ocornut/imgui/issues/6895. In this engine the window
// is ran in thread separate from the main thread, therefore it needs a
// lock to control access as main calls SampleFrame().
mutable CThreadMutex m_inputEventQueueMutex;
bool m_enabled;
bool m_initialized;
std::atomic_bool m_hasNewFrame;
mutable CThreadFastMutex m_inputEventQueueMutex;
};
CImguiSystem* ImguiSystem();

View File

@ -31,30 +31,16 @@ InputContextHandle_t CInputStackSystem::PushInputContext()
//-----------------------------------------------------------------------------
// Pops the provided input context off the input stack, and destroys it.
// Pops the top input context off the input stack, and destroys it.
//-----------------------------------------------------------------------------
void CInputStackSystem::PopInputContext( InputContextHandle_t& hContext )
void CInputStackSystem::PopInputContext( InputContextHandle_t hContext )
{
const int nCount = m_ContextStack.Count();
if ( nCount == 0 )
if ( m_ContextStack.Count() == 0 )
return;
int i = 0;
InputContext_t *pContext = *m_ContextStack.Base();
// Find the context.
for ( ; pContext != (InputContext_t*)hContext; pContext++ )
{
if ( ++i == nCount )
{
Assert( 0 );
return;
}
}
m_ContextStack.PopAt( i );
hContext = INPUT_CONTEXT_HANDLE_INVALID;
InputContext_t *pContext = NULL;
m_ContextStack.Pop( pContext );
delete pContext;
UpdateCursorState();
}
@ -216,35 +202,36 @@ void CInputStackSystem::UpdateCursorState()
}
}
//-----------------------------------------------------------------------------
// Shutdown
//-----------------------------------------------------------------------------
void CInputStackSystem::Shutdown()
{
// Delete any leaked contexts
while( m_ContextStack.Count() )
{
InputContext_t *pContext = NULL;
m_ContextStack.Pop( pContext );
delete pContext;
}
BaseClass::Shutdown();
}
//-----------------------------------------------------------------------------
// Get dependencies
//-----------------------------------------------------------------------------
static AppSystemInfo_t s_Dependencies[] =
{
{ "inputsystem" DLL_EXT_STRING, INPUTSYSTEM_INTERFACE_VERSION },
{ NULL, NULL }
};
//static AppSystemInfo_t s_Dependencies[] =
//{
// { "inputsystem" DLL_EXT_STRING, INPUTSYSTEM_INTERFACE_VERSION },
// { NULL, NULL }
//};
//
//const AppSystemInfo_t* CInputStackSystem::GetDependencies()
//{
// return s_Dependencies;
//}
const AppSystemInfo_t* CInputStackSystem::GetDependencies()
{
return s_Dependencies;
}
//-----------------------------------------------------------------------------
// Shutdown
//-----------------------------------------------------------------------------
//void CInputStackSystem::Shutdown()
//{
// // Delete any leaked contexts
// while( m_ContextStack.Count() )
// {
// InputContext_t *pContext = NULL;
// m_ContextStack.Pop( pContext );
// delete pContext;
// }
//
// BaseClass::Shutdown();
//}
//-----------------------------------------------------------------------------
// Singleton instance

View File

@ -30,14 +30,18 @@ class CInputStackSystem : public CTier1AppSystem< IInputStackSystem >
typedef CTier1AppSystem< IInputStackSystem > BaseClass;
// Methods of IAppSystem
// NOTE: currently, the implementation in the game engine is used. If the
// vtable ever gets swapped with the implementation in the SDK, make sure
// to implement BaseClass::Shutdown() and uncomment the functions below !!!
// The implementation in this SDK is identical to that of the engine.
public:
virtual void Shutdown();
virtual const AppSystemInfo_t* GetDependencies();
//virtual const AppSystemInfo_t* GetDependencies();
//virtual void Shutdown();
// Methods of IInputStackSystem
public:
virtual InputContextHandle_t PushInputContext();
virtual void PopInputContext( InputContextHandle_t& hContext );
virtual void PopInputContext( InputContextHandle_t hContext );
virtual void EnableInputContext( InputContextHandle_t hContext, bool bEnable );
virtual void SetCursorVisible( InputContextHandle_t hContext, bool bVisible );
virtual void SetCursorIcon( InputContextHandle_t hContext, InputCursorHandle_t hCursor );
@ -52,13 +56,6 @@ private:
CUtlStack< InputContext_t* > m_ContextStack;
};
// NOTE: we use the engine's implementation of CInputStackSystem, even though
// we have the entire class implemented in the SDK. If, for whatever reason,
// the SDK's implementation is used, make sure all methods are tested properly
// first before fully migrating to the SDK's implementation. The only method
// that appeared to have changed compared to other source game interfaces is
// CInputStackSystem::PopInputContext(), which now actually takes the context
// handle to pop it rather than pushing/popping handles in an explicit order.
extern CInputStackSystem* g_pInputStackSystem;
///////////////////////////////////////////////////////////////////////////////

View File

@ -10,8 +10,6 @@ add_sources( SOURCE_GROUP "Private"
"cmaterialsystem.h"
"cshaderglue.cpp"
"cshaderglue.h"
"texturestreaming.cpp"
"texturestreaming.h"
)
add_sources( SOURCE_GROUP "Public"

View File

@ -5,89 +5,75 @@
#include "public/materialsystem/shader_vcs_version.h"
#include "public/rendersystem/schema/texture.g.h"
#define MATERIAL_RENDER_PARAMS_COUNT 2 // the same for r2 and r5
#define MATERIAL_SAMPLER_COUNT 4
class CMaterialGlue;
enum MaterialDepthPass_e
struct MaterialDXState_t
{
DEPTH_SHADOW,
DEPTH_PREPASS,
DEPTH_VSM,
DEPTH_SHADOW_TIGHT,
MATERIAL_DEPTH_PASS_MAT_COUNT,
};
// Virtual function-less material instance.
struct MaterialGlue_s
{
PakGuid_t guid;
const char* name;
const char* surfaceProp;
const char* surfaceProp2;
CMaterialGlue* depthMaterials[MATERIAL_DEPTH_PASS_MAT_COUNT];
CMaterialGlue* colpassMaterial;
CShaderGlue* shaderset;
TextureAsset_s** textureHandles;
TextureAsset_s** streamingTextureHandles;
uint16 streamingTextureHandleCount;
uint16 width;
uint16 height;
uint16 depth;
// An array of indices into sampler states array. must be set properly to
// have accurate texture tiling. Used in CShaderGlue::SetupShader (1403B3C60)
byte samplers[MATERIAL_SAMPLER_COUNT];// example: 0x1D0300;
uint32 unk_7C;
// some features? mostly differs per material with different shader types, but
// it seems mostly unused by the runtime too.
uint32 unk_80_0x1F5A92BD;
uint32 unk_84;
uint32 materialFlags;
uint32 materialFlags2;
MaterialRenderParams_s renderParams[MATERIAL_RENDER_PARAMS_COUNT];
uint16 numAnimationFrames;
MaterialShaderType_e materialType;
uint8 uberBufferFlags;
int dwordf4;
void* textureAnim;
ID3D11Buffer* uberBuffer;
void** pID3D11BufferVTable;
void* viewBuffer;
// Last frame this material was used to shift the texture streaming histogram.
uint32 lastFrame;
uint16 m_iUnknown4;
uint16 m_iUnknown5;
uint16 m_iUnknown6;
uint32_t blendState[8];
unsigned int unkFlags;
unsigned __int16 depthStencilFlags;
unsigned __int16 rasterizerFlags;
char pad[8];
};
#pragma pack(push, 1)
class CMaterialGlue : public IMaterialInternal
{
public:
inline const MaterialGlue_s* Get() const { return &material; }
inline MaterialGlue_s* Get() { return &material; }
uint8_t pad_0008[8]; //0x0008
uint64_t assetGuid; //0x0010
const char* name; //0x0018
private:
byte reserved[8];
MaterialGlue_s material;
const char* surfaceProp; //0x0020
const char* surfaceProp2; //0x0028
CMaterialGlue* depthShadowMaterial; //0x0030
CMaterialGlue* depthPrepassMaterial; //0x0038
CMaterialGlue* depthVSMMaterial; //0x0040
CMaterialGlue* depthShadowTightMaterial; //0x0048
CMaterialGlue* colpassMaterial; //0x0050
CShaderGlue* shaderset; //0x0058
TextureHeader_t** textureHandles; //0x0060
TextureHeader_t** streamingTextureHandles; //0x0068
int16_t numStreamingTextureHandles; //0x0070
int16_t width; //0x0072
int16_t height; //0x0074
int16_t depth; //0x0076
uint32_t samplers; //0x0078
char padding_7C[4]; //0x007C
uint32_t unk_80;
uint32_t unk_84;
uint64_t flags; // 0x0088
MaterialDXState_t dxStates[2];
uint16_t numAnimationFrames; // used in CMaterialGlue::GetNumAnimationFrames (0x1403B4250), which is called from GetSpriteInfo @ 0x1402561FC
uint8_t materialType;
uint8_t bytef3;
char padding_F4[4];
void* textureAnim;
void** dxBuffer;
void** unkD3DPointer; // was m_pID3D11BufferVTable
void* viewsBuffer;
uint32_t unknown3; //0x0118
uint16_t unknown4; //0x011C
uint16_t unknown5; //0x011E
uint16_t unknown6; //0x0120
uint64_t unknown7; //0x0122
uint32_t unknown8; //0x012A
uint16_t unknown9; //0x012E
}; //Size: 0x0130 confirmed end size.
static_assert(sizeof(CMaterialGlue) == 0x130);
#pragma pack(pop)
#endif // !DEDICATED
inline void* g_pMaterialGlueVFTable = nullptr;

View File

@ -15,10 +15,8 @@
#include "geforce/reflex.h"
#include "radeon/antilag.h"
#ifndef MATERIALSYSTEM_NODX
#include "windows/id3dx.h"
#include "gameui/imgui_system.h"
#include "materialsystem/cmaterialglue.h"
#include "materialsystem/texturestreaming.h"
#endif // !MATERIALSYSTEM_NODX
#include "materialsystem/cmaterialsystem.h"
@ -47,10 +45,10 @@ static bool s_useLowLatency = false;
InitReturnVal_t CMaterialSystem::Init(CMaterialSystem* thisptr)
{
#ifdef MATERIALSYSTEM_NODX
// Only load the startup pak files, as 'common_early.rpak' has assets
// Only load the 'startup.rpak' file, as 'common_early.rpak' has assets
// that references assets in 'startup.rpak'.
g_pakLoadApi->LoadAsyncAndWait("startup.rpak", AlignedMemAlloc(), 5, 0);
g_pakLoadApi->LoadAsyncAndWait("startup_sdk.rpak", AlignedMemAlloc(), 5, 0);
PakHandle_t pakHandle = g_pakLoadApi->LoadAsync("startup.rpak", AlignedMemAlloc(), 5, 0);
g_pakLoadApi->WaitAsync(pakHandle, nullptr);
// Trick: return INIT_FAILED to disable the loading of hardware
// configuration data, since we don't need it on the dedi.
@ -71,14 +69,7 @@ InitReturnVal_t CMaterialSystem::Init(CMaterialSystem* thisptr)
g_PCLStatsAvailable = true;
}
const InitReturnVal_t result = CMaterialSystem__Init(thisptr);
// Must be loaded after the call to CMaterialSystem::Init() as we want
// to load startup_sdk.rpak after startup.rpak. This pak file can be
// used to load paks as early as startup.rpak, while still offering the
// ability to patch/update its containing assets on time.
g_pakLoadApi->LoadAsyncAndWait("startup_sdk.rpak", AlignedMemAlloc(), 5, 0);
return result;
return CMaterialSystem__Init(thisptr);
#endif
}
@ -102,6 +93,33 @@ int CMaterialSystem::Shutdown(CMaterialSystem* thisptr)
}
#ifndef MATERIALSYSTEM_NODX
//---------------------------------------------------------------------------------
// Purpose: loads and processes STBSP files
// (overrides level name if stbsp field has value in prerequisites file)
// Input : *pszLevelName -
//---------------------------------------------------------------------------------
void StreamDB_Init(const char* pszLevelName)
{
KeyValues* pSettingsKV = Mod_GetLevelSettings(pszLevelName);
if (pSettingsKV)
{
KeyValues* pStreamKV = pSettingsKV->FindKey("StreamDB");
if (pStreamKV)
{
const char* pszColumnName = pStreamKV->GetString();
Msg(eDLL_T::MS, "StreamDB_Init: Loading override STBSP file '%s.stbsp'\n", pszColumnName);
v_StreamDB_Init(pszColumnName);
return;
}
}
Msg(eDLL_T::MS, "StreamDB_Init: Loading STBSP file '%s.stbsp'\n", pszLevelName);
v_StreamDB_Init(pszLevelName);
}
//---------------------------------------------------------------------------------
// Purpose: draw frame
//---------------------------------------------------------------------------------
@ -121,10 +139,7 @@ void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64
//---------------------------------------------------------------------------------
ssize_t SpinPresent(void)
{
CImguiSystem* const imguiSystem = ImguiSystem();
if (imguiSystem->IsInitialized())
imguiSystem->RenderFrame();
ImguiSystem()->RenderFrame();
const ssize_t val = v_SpinPresent();
return val;
@ -132,16 +147,8 @@ ssize_t SpinPresent(void)
void* CMaterialSystem::SwapBuffers(CMaterialSystem* pMatSys)
{
CImguiSystem* const imguiSystem = ImguiSystem();
// See https://github.com/ocornut/imgui/issues/7615, looking for status msg
// DXGI_STATUS_OCCLUDED isn't compatible with DXGI_SWAP_EFFECT_FLIP_DISCARD.
// This engine however does not use the flip model.
if (imguiSystem->IsInitialized() && D3D11SwapChain()->Present(0, DXGI_PRESENT_TEST) != DXGI_STATUS_OCCLUDED)
{
imguiSystem->SampleFrame();
imguiSystem->SwapBuffers();
}
ImguiSystem()->SampleFrame();
ImguiSystem()->SwapBuffers();
return CMaterialSystem__SwapBuffers(pMatSys);
}
@ -181,57 +188,6 @@ Vector2D CMaterialSystem::GetScreenSize(CMaterialSystem* pMatSys)
return vecScreenSize;
}
//-----------------------------------------------------------------------------
// Purpose: same as StreamDB_CreditWorldTextures, but also takes the coverage
// of the dynamic model into account.
// Input : *pMatSys -
// *materialGlue -
// a3 -
// a4 -
// a5 -
// *pViewOrigin -
// tanOfHalfFov -
// viewWidthPixels -
// a9 -
//-----------------------------------------------------------------------------
void CMaterialSystem::CreditModelTextures(CMaterialSystem* const pMatSys, CMaterialGlue* const materialGlue, __int64 a3, __int64 a4, unsigned int a5, const Vector3D* const pViewOrigin, const float tanOfHalfFov, const float viewWidthPixels, int a9)
{
if (!materialGlue->CanCreditModelTextures())
return;
// If we use the GPU driven texture streaming system, do not run this code
// as the compute shaders deals with both static and dynamic model textures.
if (gpu_driven_tex_stream->GetBool())
return;
MaterialGlue_s* const material = materialGlue->Get();
material->lastFrame = s_textureStreamMgr->thisFrame;
v_StreamDB_CreditModelTextures(material->streamingTextureHandles, material->streamingTextureHandleCount, a3, a4, a5, pViewOrigin, tanOfHalfFov, viewWidthPixels, a9);
}
//-----------------------------------------------------------------------------
// Purpose: updates the stream camera used for getting the column from the STBSP
// Input : *pMatSys -
// *camPos -
// *camAng -
// halfFovX -
// viewWidth -
//-----------------------------------------------------------------------------
void CMaterialSystem::UpdateStreamCamera(CMaterialSystem* const pMatSys, const Vector3D* const camPos,
const QAngle* const camAng, const float halfFovX, const float viewWidth)
{
// The stream camera is only used for the STBSP. If we use the GPU feedback
// driven texture streaming system instead, do not run this code.
if (gpu_driven_tex_stream->GetBool())
return;
// NOTE: 'camAng' is set and provided to the function below, but the actual
// function that updates the global state (StreamDB_SetCameraPosition)
// isn't using it. The parameter is unused.
CMaterialSystem__UpdateStreamCamera(pMatSys, camPos, camAng, halfFovX, viewWidth);
}
#endif // !MATERIALSYSTEM_NODX
///////////////////////////////////////////////////////////////////////////////
@ -247,9 +203,7 @@ void VMaterialSystem::Detour(const bool bAttach) const
DetourSetup(&CMaterialSystem__SwapBuffers, &CMaterialSystem::SwapBuffers, bAttach);
DetourSetup(&CMaterialSystem__FindMaterialEx, &CMaterialSystem::FindMaterialEx, bAttach);
DetourSetup(&CMaterialSystem__CreditModelTextures, &CMaterialSystem::CreditModelTextures, bAttach);
DetourSetup(&CMaterialSystem__UpdateStreamCamera, &CMaterialSystem::UpdateStreamCamera, bAttach);
DetourSetup(&v_StreamDB_Init, &StreamDB_Init, bAttach);
DetourSetup(&v_DispatchDrawCall, &DispatchDrawCall, bAttach);
DetourSetup(&v_SpinPresent, &SpinPresent, bAttach);
#endif // !MATERIALSYSTEM_NODX

View File

@ -3,6 +3,8 @@
#include "cmaterialglue.h"
#include "public/imaterialsystem.h"
#define STREAM_DB_EXT "stbsp"
class CMaterialSystem
{
public:
@ -15,9 +17,6 @@ public:
static void* SwapBuffers(CMaterialSystem* pMatSys);
static CMaterialGlue* FindMaterialEx(CMaterialSystem* pMatSys, const char* pMaterialName, uint8_t nMaterialType, int nUnk, bool bComplain);
static Vector2D GetScreenSize(CMaterialSystem* pMatSys = nullptr);
static void CreditModelTextures(CMaterialSystem* const pMatSys, CMaterialGlue* const materialGlue, __int64 a3, __int64 a4, unsigned int a5, const Vector3D* const pViewOrigin, const float tanOfHalfFov, const float viewWidthPixels, int a9);
static void UpdateStreamCamera(CMaterialSystem* const pMatSys, const Vector3D* const camPos, const QAngle* const camAng, const float halfFovX, const float viewWidth);
#endif // !MATERIALSYSTEM_NODX
// TODO: reverse the vftable!
@ -76,15 +75,20 @@ inline void*(*CMaterialSystem__SwapBuffers)(CMaterialSystem* pMatSys);
inline CMaterialGlue*(*CMaterialSystem__FindMaterialEx)(CMaterialSystem* pMatSys, const char* pMaterialName, uint8_t nMaterialType, int nUnk, bool bComplain);
inline void(*CMaterialSystem__GetScreenSize)(CMaterialSystem* pMatSys, float* outX, float* outY);
inline void(*CMaterialSystem__CreditModelTextures)(CMaterialSystem* const pMatSys, CMaterialGlue* const materialGlue, __int64 a3, __int64 a4, unsigned int a5, const Vector3D* const pViewOrigin, const float tanOfHalfFov, const float viewWidthPixels, int a9);
inline void(*CMaterialSystem__UpdateStreamCamera)(CMaterialSystem* const pMatSys, const Vector3D* const camPos, const QAngle* const camAng, const float halfFovX, const float viewWidth);
inline void*(*v_DispatchDrawCall)(int64_t a1, uint64_t a2, int a3, int a4, int64_t a5, int a6, uint8_t a7, int64_t a8, uint32_t a9, uint32_t a10, int a11, __m128* a12, int a13, int64_t a14);
inline ssize_t(*v_SpinPresent)(void);
inline void(*CMaterialSystem__GetStreamOverlay)(const char* mode, char* buf, size_t bufSize);
inline const char*(*CMaterialSystem__DrawStreamOverlay)(void* thisptr, uint8_t* a2, void* unused, void* a4);
#endif // !MATERIALSYSTEM_NODX
inline void(*v_StreamDB_Init)(const char* const pszLevelName);
#ifndef MATERIALSYSTEM_NODX
inline void** s_pRenderContext; // NOTE: This is some CMaterial instance or array.
inline ssize_t* g_nTotalStreamingTextureMemory = nullptr;
inline ssize_t* g_nUnfreeStreamingTextureMemory = nullptr;
inline ssize_t* g_nUnusableStreamingTextureMemory = nullptr;
#endif // !MATERIALSYSTEM_NODX
// TODO: move to materialsystem_global.h!
@ -108,13 +112,17 @@ class VMaterialSystem : public IDetour
LogFunAdr("CMaterialSystem::SwapBuffers", CMaterialSystem__SwapBuffers);
LogFunAdr("CMaterialSystem::FindMaterialEx", CMaterialSystem__FindMaterialEx);
LogFunAdr("CMaterialSystem::GetScreenSize", CMaterialSystem__GetScreenSize);
LogFunAdr("CMaterialSystem::CreditModelTextures", CMaterialSystem__CreditModelTextures);
LogFunAdr("CMaterialSystem::UpdateStreamCamera", CMaterialSystem__UpdateStreamCamera);
LogFunAdr("CMaterialSystem::GetStreamOverlay", CMaterialSystem__GetStreamOverlay);
LogFunAdr("CMaterialSystem::DrawStreamOverlay", CMaterialSystem__DrawStreamOverlay);
LogFunAdr("DispatchDrawCall", v_DispatchDrawCall);
LogFunAdr("SpinPresent", v_SpinPresent);
#endif // !MATERIALSYSTEM_NODX
LogFunAdr("StreamDB_Init", v_StreamDB_Init);
#ifndef MATERIALSYSTEM_NODX
LogVarAdr("g_nTotalStreamingTextureMemory", g_nTotalStreamingTextureMemory);
LogVarAdr("g_nUnfreeStreamingTextureMemory", g_nUnfreeStreamingTextureMemory);
LogVarAdr("g_nUnusableStreamingTextureMemory", g_nUnusableStreamingTextureMemory);
LogVarAdr("s_pRenderContext", s_pRenderContext);
LogVarAdr("g_MaterialAdapterMgr", g_pMaterialAdapterMgr);
#endif // !MATERIALSYSTEM_NODX
@ -132,17 +140,22 @@ class VMaterialSystem : public IDetour
g_GameDll.FindPatternSIMD("44 89 4C 24 ?? 44 88 44 24 ?? 48 89 4C 24 ??").GetPtr(CMaterialSystem__FindMaterialEx);
g_GameDll.FindPatternSIMD("8B 05 ?? ?? ?? ?? 89 02 8B 05 ?? ?? ?? ?? 41 89 ?? C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC 8B 05 ?? ?? ?? ??").GetPtr(CMaterialSystem__GetScreenSize);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B 02 48 8B CA 49 8B F9").GetPtr(CMaterialSystem__CreditModelTextures);
g_GameDll.FindPatternSIMD("48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 44 0F 29 44 24").GetPtr(CMaterialSystem__UpdateStreamCamera);
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 80 7C 24 ?? ?? 0F 84 ?? ?? ?? ?? 48 89 9C 24 ?? ?? ?? ??").FollowNearCallSelf().GetPtr(CMaterialSystem__GetStreamOverlay);
g_GameDll.FindPatternSIMD("41 56 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 C6 02 ??").GetPtr(CMaterialSystem__DrawStreamOverlay);
g_GameDll.FindPatternSIMD("44 89 4C 24 ?? 44 89 44 24 ?? 48 89 4C 24 ?? 55 53 56").GetPtr(v_DispatchDrawCall);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 8B 15 ?? ?? ?? ??").GetPtr(v_SpinPresent);
#endif // !MATERIALSYSTEM_NODX
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 54 41 56 41 57 48 83 EC 40 48 8B E9").GetPtr(v_StreamDB_Init);
}
virtual void GetVar(void) const
{
#ifndef MATERIALSYSTEM_NODX
CMemory(CMaterialSystem__DrawStreamOverlay).Offset(0x1C).FindPatternSelf("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_nTotalStreamingTextureMemory);
CMemory(CMaterialSystem__DrawStreamOverlay).Offset(0x2D).FindPatternSelf("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_nUnfreeStreamingTextureMemory);
CMemory(CMaterialSystem__DrawStreamOverlay).Offset(0x50).FindPatternSelf("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_nUnusableStreamingTextureMemory);
CMemory(v_DispatchDrawCall).FindPattern("48 8B ?? ?? ?? ?? 01").ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(s_pRenderContext);
CMemory(CMaterialSystem__Disconnect).FindPattern("48 8D").ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_pMaterialAdapterMgr);
#endif // !MATERIALSYSTEM_NODX

View File

@ -1,69 +0,0 @@
#include "tier1/keyvalues.h"
#include "engine/cmodel_bsp.h"
#include "materialsystem/texturestreaming.h"
//---------------------------------------------------------------------------------
// Purpose: loads and processes STBSP files
// (overrides level name if stbsp field has value in prerequisites file)
// Input : *pszLevelName -
//---------------------------------------------------------------------------------
static void StreamDB_Init(const char* const pszLevelName)
{
KeyValues* const pSettingsKV = Mod_GetLevelSettings(pszLevelName);
const char* targetStreamDB = pszLevelName;
if (pSettingsKV)
{
KeyValues* const pStreamKV = pSettingsKV->FindKey("StreamDB");
if (pStreamKV)
targetStreamDB = pStreamKV->GetString();
}
v_StreamDB_Init(targetStreamDB);
// If the requested STBSP file doesn't exist, then enable the GPU driven
// texture streaming system.
const bool gpuDriven = s_textureStreamMgr->fileHandle == FS_ASYNC_FILE_INVALID;
gpu_driven_tex_stream->SetValue(gpuDriven);
if (!gpuDriven)
Msg(eDLL_T::MS, "StreamDB_Init: Loaded STBSP file '%s.stbsp'\n", targetStreamDB);
}
//---------------------------------------------------------------------------------
// Purpose: shift and scale the texture's histogram to accommodate varying screen
// FOV, screen resolutions and texture resolutions.
// Input : *taskList -
//---------------------------------------------------------------------------------
static void StreamDB_CreditWorldTextures(TextureStreamMgr_TaskList_s* const taskList)
{
// If we use the GPU driven texture streaming system, do not credit the textures
// based on the STBSP pages.
if (gpu_driven_tex_stream->GetBool())
return;
v_StreamDB_CreditWorldTextures(taskList);
}
//---------------------------------------------------------------------------------
// Purpose: same as above, except for older (legacy) STBSP's (v8.0).
// Input : *taskList -
//---------------------------------------------------------------------------------
static void StreamDB_CreditWorldTextures_Legacy(TextureStreamMgr_TaskList_s* const taskList)
{
// If we use the GPU driven texture streaming system, do not credit the textures
// based on the STBSP pages.
if (gpu_driven_tex_stream->GetBool())
return;
v_StreamDB_CreditWorldTextures_Legacy(taskList);
}
void VTextureStreaming::Detour(const bool bAttach) const
{
DetourSetup(&v_StreamDB_Init, &StreamDB_Init, bAttach);
DetourSetup(&v_StreamDB_CreditWorldTextures, &StreamDB_CreditWorldTextures, bAttach);
DetourSetup(&v_StreamDB_CreditWorldTextures_Legacy, &StreamDB_CreditWorldTextures_Legacy, bAttach);
}

View File

@ -1,178 +0,0 @@
//=============================================================================//
//
// Purpose: texture streaming and runtime management
//
//-----------------------------------------------------------------------------
// Some of these structs are based on the presentation held by the developer of
// the texture streaming system in Titanfall 2 and Apex Legends, see the links:
// - https://www.gdcvault.com/play/1024418/Efficient-Texture-Streaming-in-Titanfall
// - https://www.youtube.com/watch?v=q0aKNGH8WbA
//=============================================================================//
#ifndef TEXTURESTREAMING_H
#define TEXTURESTREAMING_H
#include "public/rtech/istreamdb.h"
struct MaterialGlue_s;
struct TextureAsset_s;
struct TextureStreamMgr_Task_s
{
TextureAsset_s* textureAsset;
// The mip level count to load or drop.
uint8 mipLevelCount;
char padding[3];
// The 'cost vs benefit' metric used to partially sort the task list to get
// the best and worst 16 textures.
float metric;
};
struct TextureStreamMgr_TaskList_s
{
// STBSP async file handle and index to the current page.
int fileHandle;
int pageIndex;
// Whether we should update the current page state.
bool updatePageState;
int padding;
// Offset to the page in the STBSP to read up to size bytes.
uint64 pageOffset;
uint64 pageSize;
// - loadBegin points to the first texture load task.
// - loadEnd points to the last texture load task.
// - loadLimit points to the absolute end of the load task buffer.
TextureStreamMgr_Task_s* loadBegin;
TextureStreamMgr_Task_s* loadEnd;
TextureStreamMgr_Task_s* loadLimit;
// - dropBegin points to the first texture drop task.
// - dropEnd points to the last texture drop task.
// - dropLimit points to the absolute end of the drop task buffer.
TextureStreamMgr_Task_s* dropBegin;
TextureStreamMgr_Task_s* dropEnd;
TextureStreamMgr_Task_s* dropLimit;
};
enum TextureStreamMode_e : uint8
{
TSM_OPMODE_LEGACY_PICMIP = 0,
TSM_OPMODE_DYNAMIC,
TSM_OPMODE_ALL,
TSM_OPMODE_NONE,
TSM_OPMODE_PAUSED,
};
struct TextureStreamMgr_s
{
bool initialised;
bool hasResidentPages;
char filePath[260]; // size=MAX_PATH.
char gap_105[2];
int fileHandle; // STBSP file handle.
char gap_10b[4];
char* stringBuffer;
StreamDB_Header_s header;
StreamDB_ResidentPage_s* residentPages;
MaterialGlue_s** materials;
StreamDB_Material_s* materialInfo;
int64 maxResidentPageSize;
StreamDB_PageState_s pageStates[4];
bool unk_320;
char gap_321[3];
TextureStreamMode_e texStreamMode;
int picMip;
float streamBspBucketBias;
float streamBspDistScale;
uint64 highPriorityMemoryBudget;
uint32 streamBspCellX;
uint32 streamBspCellY;
int loadedLinkedTextureCount;
int totalMipLevelCount;
int loadedMipLevelCount;
int unk_34;
int64 usedStreamingMemory;
int64 totalStreamingMemory;
int thisFrame;
int unk_50;
Vector3D streamBspCameraPos;
float streamBspHalfFovX;
float streamBspViewWidth;
TextureAsset_s* streamableTextures[4];
};
enum TextureStreamMemory_e
{
TML_TRACKER_UNFREE,
TML_TRACKER_UNKNOWN_1, // Appears unused by the retail runtime.
TML_TRACKER_UNKNOWN_2, // Appears unused by the retail runtime.
TML_TRACKER_UNUSABE,
// Not a memory tracker!
STREAMING_TEXTURES_MEMORY_LATENCY_FRAME_COUNT,
};
inline void(*v_StreamDB_Init)(const char* const pszLevelName);
inline void(*v_StreamDB_CreditWorldTextures)(TextureStreamMgr_TaskList_s* const taskList);
inline void(*v_StreamDB_CreditWorldTextures_Legacy)(TextureStreamMgr_TaskList_s* const taskList);
inline void(*v_StreamDB_CreditModelTextures)(TextureAsset_s** const textureAssets, const int textureCount, __int64 a3, __int64 a4, unsigned int a5, const Vector3D* const pViewOrigin, const float tanOfHalfFov, const float viewWidthPixels, int a9);
inline void(*TextureStreamMgr_GetStreamOverlay)(const char* const mode, char* const buf, const size_t bufSize);
inline const char* (*TextureStreamMgr_DrawStreamOverlayToInterface)(void* thisptr, uint8_t* a2, void* unused, void* debugOverlayIface);
inline ssize_t* g_textureStreamMemoryUsed = nullptr; // array size = STREAMING_TEXTURES_MEMORY_LATENCY_FRAME_COUNT.
inline ssize_t* g_textureStreamMemoryTarget = nullptr; // pointer to single size var.
inline TextureStreamMgr_s* s_textureStreamMgr;
///////////////////////////////////////////////////////////////////////////////
class VTextureStreaming : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("StreamDB_Init", v_StreamDB_Init);
LogFunAdr("StreamDB_CreditWorldTextures", v_StreamDB_CreditWorldTextures);
LogFunAdr("StreamDB_CreditWorldTextures_Legacy", v_StreamDB_CreditWorldTextures_Legacy);
LogFunAdr("StreamDB_CreditModelTextures", v_StreamDB_CreditModelTextures);
LogFunAdr("TextureStreamMgr_GetStreamOverlay", TextureStreamMgr_GetStreamOverlay);
LogFunAdr("TextureStreamMgr_DrawStreamOverlayToInterface", TextureStreamMgr_DrawStreamOverlayToInterface);
LogVarAdr("g_textureStreamMemoryUsed", g_textureStreamMemoryUsed);
LogVarAdr("g_textureStreamMemoryTarget", g_textureStreamMemoryTarget);
LogVarAdr("s_textureStreamMgr", s_textureStreamMgr);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 54 41 56 41 57 48 83 EC 40 48 8B E9").GetPtr(v_StreamDB_Init);
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? EB ?? 48 8B CF E8 ?? ?? ?? ?? 4C 8D 25").FollowNearCallSelf().GetPtr(v_StreamDB_CreditWorldTextures);
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 4C 8D 25 ?? ?? ?? ?? 4C 89 64 24").FollowNearCallSelf().GetPtr(v_StreamDB_CreditWorldTextures_Legacy);
g_GameDll.FindPatternSIMD("4C 89 44 24 ?? 89 54 24 ?? 48 89 4C 24 ?? 55 56").GetPtr(v_StreamDB_CreditModelTextures);
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 80 7C 24 ?? ?? 0F 84 ?? ?? ?? ?? 48 89 9C 24 ?? ?? ?? ??").FollowNearCallSelf().GetPtr(TextureStreamMgr_GetStreamOverlay);
g_GameDll.FindPatternSIMD("41 56 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 C6 02 ??").GetPtr(TextureStreamMgr_DrawStreamOverlayToInterface);
}
virtual void GetVar(void) const
{
CMemory(TextureStreamMgr_DrawStreamOverlayToInterface).Offset(0x2D).FindPatternSelf("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_textureStreamMemoryUsed);
CMemory(TextureStreamMgr_DrawStreamOverlayToInterface).Offset(0x1C).FindPatternSelf("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_textureStreamMemoryTarget);
CMemory(v_StreamDB_Init).FindPattern("C6 05").ResolveRelativeAddressSelf(0x2, 0x7).GetPtr(s_textureStreamMgr);
}
virtual void GetCon(void) const
{ }
virtual void Detour(const bool bAttach) const;
};
///////////////////////////////////////////////////////////////////////////////
#endif // TEXTURESTREAMING_H

View File

@ -21,8 +21,8 @@
struct BoundsItem
{
float bmin[3];
float bmax[3];
float bmin[2];
float bmax[2];
int i;
};
@ -48,56 +48,30 @@ static int compareItemY(const void* va, const void* vb)
return 0;
}
static int compareItemZ(const void* va, const void* vb)
{
const BoundsItem* a = (const BoundsItem*)va;
const BoundsItem* b = (const BoundsItem*)vb;
if (a->bmin[2] < b->bmin[2])
return -1;
if (a->bmin[2] > b->bmin[2])
return 1;
return 0;
}
static void calcExtends(const BoundsItem* items, const int /*nitems*/,
const int imin, const int imax,
float* bmin, float* bmax)
{
bmin[0] = items[imin].bmin[0];
bmin[1] = items[imin].bmin[1];
bmin[2] = items[imin].bmin[2];
bmax[0] = items[imin].bmax[0];
bmax[1] = items[imin].bmax[1];
bmax[2] = items[imin].bmax[2];
for (int i = imin+1; i < imax; ++i)
{
const BoundsItem& it = items[i];
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2];
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2];
}
}
inline int longestAxis(float x, float y, float z)
inline int longestAxis(float x, float y)
{
int axis = 0;
float maxVal = x;
if (y > maxVal)
{
axis = 1;
maxVal = y;
}
if (z > maxVal)
{
axis = 2;
}
return axis;
return y > x ? 1 : 0;
}
static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk,
@ -136,9 +110,8 @@ static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int tri
// Split
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
const int axis = longestAxis(node.bmax[0] - node.bmin[0],
node.bmax[1] - node.bmin[1],
node.bmax[2] - node.bmin[2]);
int axis = longestAxis(node.bmax[0] - node.bmin[0],
node.bmax[1] - node.bmin[1]);
if (axis == 0)
{
@ -150,11 +123,6 @@ static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int tri
// Sort along y-axis
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemY);
}
else
{
// Sort along z-axis
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemZ);
}
int isplit = imin+inum/2;
@ -194,20 +162,17 @@ bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
const int* t = &tris[i*3];
BoundsItem& it = items[i];
it.i = i;
// Calc triangle XYZ bounds.
// Calc triangle XY bounds.
it.bmin[0] = it.bmax[0] = verts[t[0]*3+0];
it.bmin[1] = it.bmax[1] = verts[t[0]*3+1];
it.bmin[2] = it.bmax[2] = verts[t[0]*3+2];
for (int j = 1; j < 3; ++j)
{
const float* v = &verts[t[j]*3];
if (v[0] < it.bmin[0]) it.bmin[0] = v[0];
if (v[1] < it.bmin[1]) it.bmin[1] = v[1];
if (v[2] < it.bmin[2]) it.bmin[2] = v[2];
if (v[0] > it.bmax[0]) it.bmax[0] = v[0];
if (v[1] > it.bmax[1]) it.bmax[1] = v[1];
if (v[2] > it.bmax[2]) it.bmax[2] = v[2];
}
}
@ -313,19 +278,18 @@ int rcGetChunksOverlappingRect(const rcChunkyTriMesh * cm, float bmin[2], float
static bool checkOverlapSegment(const float p[3], const float q[3],
const float bmin[3], const float bmax[3])
static bool checkOverlapSegment(const float p[2], const float q[2],
const float bmin[2], const float bmax[2])
{
float tmin = 0;
float tmax = 1;
float d[3];
float d[2];
d[0] = q[0] - p[0];
d[1] = q[1] - p[1];
d[2] = q[2] - p[2];
for (int i = 0; i < 3; i++)
for (int i = 0; i < 2; i++)
{
if (rdMathFabsf(d[i]) < RD_EPS)
if (fabsf(d[i]) < RD_EPS)
{
// Ray is parallel to slab. No hit if origin not within slab
if (p[i] < bmin[i] || p[i] > bmax[i])
@ -346,9 +310,8 @@ static bool checkOverlapSegment(const float p[3], const float q[3],
return true;
}
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm,
float p[3], float q[3],
float p[2], float q[2],
int* ids, const int maxIds)
{
// Traverse tree

View File

@ -80,8 +80,8 @@ static void initTraverseMasks()
s_traverseAnimTraverseFlags[ANIMTYPE_PILOT] = 0x0008013F;
s_traverseAnimTraverseFlags[ANIMTYPE_PROWLER] = 0x00033FB7;
s_traverseAnimTraverseFlags[ANIMTYPE_SUPER_SPECTRE] = 0x00033FB2;
s_traverseAnimTraverseFlags[ANIMTYPE_TITAN] = 0x00000030;
s_traverseAnimTraverseFlags[ANIMTYPE_GOLIATH] = 0x00000030; // TODO: figure out all the activities GOLIATH has.
s_traverseAnimTraverseFlags[ANIMTYPE_TITAN] = 0000000030;
s_traverseAnimTraverseFlags[ANIMTYPE_GOLIATH] = 0000000030; // TODO: figure out all the activities GOLIATH has.
}
TraverseType_s s_traverseTable[NUM_TRAVERSE_TYPES];
@ -150,7 +150,6 @@ Editor::Editor() :
m_filterWalkableLowHeightSpans(true),
m_buildTraversePortals(true),
m_traverseRayDynamicOffset(true),
m_traverseLinkSinglePortalPerPolyPair(false),
m_collapseLinkedPolyGroups(false),
m_buildBvTree(true),
m_selectedNavMeshType(NAVMESH_SMALL),
@ -472,8 +471,6 @@ void Editor::handleCommonSettings()
ImGui::Checkbox("Build Traverse Portals", &m_buildTraversePortals);
ImGui::Checkbox("Single Portal Per Poly Pair", &m_traverseLinkSinglePortalPerPolyPair);
ImGui::Checkbox("Collapse Linked Poly Groups", &m_collapseLinkedPolyGroups);
if (ImGui::Checkbox("Dynamic Traverse Ray Offset", &m_traverseRayDynamicOffset))
@ -633,11 +630,6 @@ static const int TRAVERSE_LINK_TRACE_MASK = TRACE_WORLD|TRACE_CLIP|TRACE_TRIGGER
// avoiding 2 additional ray casts will save a lot on build times.
static const float TRAVERSE_LINK_TRIPPLE_TRACE_THRESH = 100.f;
static bool raycastMesh(const InputGeom* geom, const float* src, const float* dst)
{
return geom->raycastMesh(src, dst, TRAVERSE_LINK_TRACE_MASK);
}
static bool traverseLinkOffsetIntersectsGeom(const InputGeom* geom, const float* basePos, const float* offsetPos)
{
// We need to fire a raycast from out initial
@ -660,7 +652,7 @@ static bool traverseLinkOffsetIntersectsGeom(const InputGeom* geom, const float*
// Otherwise we create links between a mesh
// inside and outside an object, causing the
// ai to traverse inside of it.
if (raycastMesh(geom, basePos, offsetPos))
if (geom->raycastMesh(basePos, offsetPos, TRAVERSE_LINK_TRACE_MASK))
return true;
return false;
@ -703,7 +695,7 @@ static bool traverseLinkIntersectsPlaneOverPlane(const InputGeom* geom, const fl
float rayMidEnd[3];
rdVset(rayMidEnd, rayMidStart[0], rayMidStart[1], rayMidStart[2]+walkableHeight);
if (raycastMesh(geom, rayMidStart, rayMidEnd))
if (geom->raycastMesh(rayMidStart, rayMidEnd, TRAVERSE_LINK_TRACE_MASK))
return true;
const float distance = rdVdist(lowPos, highPos);
@ -716,13 +708,13 @@ static bool traverseLinkIntersectsPlaneOverPlane(const InputGeom* geom, const fl
rdVsad(rayMidMidStart, rayMidStart, lowPos, 0.5f);
rdVset(rayMidEnd, rayMidMidStart[0], rayMidMidStart[1], rayMidMidStart[2]+walkableHeight);
if (raycastMesh(geom, rayMidStart, rayMidEnd))
if (geom->raycastMesh(rayMidStart, rayMidEnd, TRAVERSE_LINK_TRACE_MASK))
return true;
rdVsad(rayMidMidStart, rayMidStart, highPos, 0.5f);
rdVset(rayMidEnd, rayMidMidStart[0], rayMidMidStart[1], rayMidMidStart[2]+walkableHeight);
if (raycastMesh(geom, rayMidStart, rayMidEnd))
if (geom->raycastMesh(rayMidStart, rayMidEnd, TRAVERSE_LINK_TRACE_MASK))
return true;
return false;
@ -766,7 +758,7 @@ static bool traverseLinkIntersectsOverhangOverPoint(const InputGeom* geom, const
startPos[2] + (walkableHeight*2)
};
return raycastMesh(geom, minClearanceHeight, startPos);
return geom->raycastMesh(minClearanceHeight, startPos, TRAVERSE_LINK_TRACE_MASK);
}
static bool traverseLinkInLOS(void* userData, const float* lowPos, const float* highPos, const float* lowNorm,
@ -866,7 +858,7 @@ static bool traverseLinkInLOS(void* userData, const float* lowPos, const float*
// Check if the path between the ground position and the kink point
// is clear.
if (raycastMesh(geom, targetRayPos, lowPos))
if (geom->raycastMesh(targetRayPos, lowPos, TRAVERSE_LINK_TRACE_MASK))
return false;
const float angle = rdCalcSlopeAngle(lowPos, highPos);
@ -908,7 +900,7 @@ static int addToPolyMap(void* userData, const dtPolyRef basePolyRef, const dtPol
try
{
const auto ret = editor->getTraverseLinkPolyMap().emplace(TraverseLinkPolyPair(basePolyRef, landPolyRef), traverseTypeBit);
auto ret = editor->getTraverseLinkPolyMap().emplace(TraverseLinkPolyPair(basePolyRef, landPolyRef), traverseTypeBit);
if (!ret.second)
{
rdAssert(ret.second); // Called 'addToPolyMap' while poly link already exists.
@ -933,7 +925,6 @@ void Editor::createTraverseLinkParams(dtTraverseLinkConnectParams& params)
params.userData = this;
params.minEdgeOverlap = m_traverseEdgeMinOverlap;
params.maxPortalAlign = m_traversePortalMaxAlign;
params.singlePortalPerPair = m_traverseLinkSinglePortalPerPolyPair;
}
bool Editor::createTraverseLinks()
@ -1401,11 +1392,11 @@ void Editor::renderTraverseTableFineTuners()
// NOTE: the climb height should never equal or exceed the agent's height, see https://groups.google.com/g/recastnavigation/c/L5rBamxcOBk/m/5xGLj6YP25kJ
// Quote: "you will get into trouble in cases where there is an overhand which is low enough to step over and high enough for the agent to walk under."
const NavMeshDefaults_s g_navMeshDefaults[NAVMESH_COUNT] = {
{ g_navMeshNames[NAVMESH_SMALL] , NAI_Hull::Radius(HULL_HUMAN) , NAI_Hull::Height(HULL_HUMAN) , NAI_Hull::StepHeight(HULL_HUMAN) , 8.f, 4.f, 16 },
{ g_navMeshNames[NAVMESH_MED_SHORT] , NAI_Hull::Radius(HULL_PROWLER), NAI_Hull::Height(HULL_PROWLER), NAI_Hull::StepHeight(HULL_PROWLER), 8.f, 4.f, 8 },
{ g_navMeshNames[NAVMESH_MEDIUM] , NAI_Hull::Radius(HULL_MEDIUM) , NAI_Hull::Height(HULL_MEDIUM) , NAI_Hull::StepHeight(HULL_MEDIUM) , 8.f, 4.f, 8 },
{ g_navMeshNames[NAVMESH_LARGE] , NAI_Hull::Radius(HULL_TITAN) , NAI_Hull::Height(HULL_TITAN) , NAI_Hull::StepHeight(HULL_TITAN) , 15.f, 7.5f, 4 },
{ g_navMeshNames[NAVMESH_EXTRA_LARGE], NAI_Hull::Radius(HULL_GOLIATH), NAI_Hull::Height(HULL_GOLIATH), NAI_Hull::StepHeight(HULL_GOLIATH), 15.f, 7.5f, 4 },
{ g_navMeshNames[NAVMESH_SMALL] , NAI_Hull::Width(HULL_HUMAN) * NAI_Hull::ExtentScale(HULL_HUMAN) , NAI_Hull::Height(HULL_HUMAN) , NAI_Hull::StepHeight(HULL_HUMAN) , 8.f, 4.f, 16 },
{ g_navMeshNames[NAVMESH_MED_SHORT] , NAI_Hull::Width(HULL_PROWLER) * NAI_Hull::ExtentScale(HULL_PROWLER), NAI_Hull::Height(HULL_PROWLER), NAI_Hull::StepHeight(HULL_PROWLER), 8.f, 4.f, 8 },
{ g_navMeshNames[NAVMESH_MEDIUM] , NAI_Hull::Width(HULL_MEDIUM) * NAI_Hull::ExtentScale(HULL_MEDIUM) , NAI_Hull::Height(HULL_MEDIUM) , NAI_Hull::StepHeight(HULL_MEDIUM) , 8.f, 4.f, 8 },
{ g_navMeshNames[NAVMESH_LARGE] , NAI_Hull::Width(HULL_TITAN) * NAI_Hull::ExtentScale(HULL_TITAN) , NAI_Hull::Height(HULL_TITAN) , NAI_Hull::StepHeight(HULL_TITAN) , 15.f, 7.5f, 4 },
{ g_navMeshNames[NAVMESH_EXTRA_LARGE], NAI_Hull::Width(HULL_GOLIATH) * NAI_Hull::ExtentScale(HULL_GOLIATH), NAI_Hull::Height(HULL_GOLIATH), NAI_Hull::StepHeight(HULL_GOLIATH), 15.f, 7.5f, 4 },
};
void Editor::selectNavMeshType(const NavMeshType_e navMeshType)

View File

@ -35,7 +35,7 @@ void scanDirectoryAppend(const string& path, const string& ext, vector<string>&
do
{
filelist.emplace_back(dir.name);
filelist.push_back(dir.name);
}
while (_findnext(fh, &dir) == 0);
_findclose(fh);
@ -53,7 +53,7 @@ void scanDirectoryAppend(const string& path, const string& ext, vector<string>&
int len = strlen(current->d_name);
if (len > extLen && strncmp(current->d_name + len - extLen, ext.c_str(), extLen) == 0)
{
filelist.emplace_back(current->d_name);
filelist.push_back(current->d_name);
}
}
closedir(dp);

View File

@ -533,13 +533,11 @@ bool InputGeom::raycastMesh(const float* src, const float* dst, const unsigned i
if (!traceWorld)
return false;
float p[3], q[3];
float p[2], q[2];
p[0] = src[0] + (dst[0]-src[0]) * btmin;
p[1] = src[1] + (dst[1]-src[1]) * btmin;
p[2] = src[2] + (dst[2]-src[2]) * btmin;
q[0] = src[0] + (dst[0]-src[0]) * btmax;
q[1] = src[1] + (dst[1]-src[1]) * btmax;
q[2] = src[2] + (dst[2]-src[2]) * btmax;
const int ncid = rcGetChunksOverlappingSegment(m_chunkyMesh, p, q, s_chunkIndices, MAX_CHUNK_INDICES);
if (!ncid)

View File

@ -21,8 +21,8 @@
struct rcChunkyTriMeshNode
{
float bmin[3];
float bmax[3];
float bmin[2];
float bmax[2];
int i;
int n;
};
@ -56,7 +56,7 @@ int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm, float bmin[2], float b
int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm, float bmin[2], float bmax[2], int* ids, const int maxIds,int& currentCount,int& currentNode);
/// Returns the chunk indices which overlap the input segment.
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm, float p[3], float q[3], int* ids, const int maxIds);
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm, float p[2], float q[2], int* ids, const int maxIds);
#endif // CHUNKYTRIMESH_H

View File

@ -247,7 +247,6 @@ protected:
bool m_filterWalkableLowHeightSpans;
bool m_buildTraversePortals;
bool m_traverseRayDynamicOffset;
bool m_traverseLinkSinglePortalPerPolyPair;
bool m_collapseLinkedPolyGroups;
bool m_buildBvTree;

View File

@ -277,7 +277,7 @@ bool sdl_init(SDL_Window*& window, SDL_Renderer*& renderer, int &width, int &hei
SDL_DisplayMode displayMode;
SDL_GetCurrentDisplayMode(0, &displayMode);
Uint32 flags = SDL_WINDOW_OPENGL | SDL_RENDERER_PRESENTVSYNC | SDL_WINDOW_RESIZABLE;
Uint32 flags = SDL_WINDOW_OPENGL | SDL_RENDERER_PRESENTVSYNC;
if (presentationMode)
{
// Create a fullscreen window at the native resolution.
@ -752,24 +752,6 @@ int not_main(int argc, char** argv)
}
break;
case SDL_WINDOWEVENT:
{
if (event.window.event == SDL_WINDOWEVENT_RESIZED)
{
// Get the new window size
width = event.window.data1;
height = event.window.data2;
// Update OpenGL viewport
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.0f, (float)width / (float)height, 1.0f, camr);
}
}
break;
case SDL_QUIT:
done = true;
break;

View File

@ -24,10 +24,6 @@ add_sources( SOURCE_GROUP "Engine"
"${ENGINE_SOURCE_DIR}/engine/shared/shared_rcon.h"
)
add_sources( SOURCE_GROUP "Public"
"${ENGINE_SOURCE_DIR}/public/netcon/INetCon.h"
)
add_sources( SOURCE_GROUP "Windows"
"${ENGINE_SOURCE_DIR}/windows/console.cpp"
"${ENGINE_SOURCE_DIR}/windows/console.h"

View File

@ -172,10 +172,8 @@ BOOL WINAPI CNetCon::CloseHandler(DWORD eventCode)
//-----------------------------------------------------------------------------
void CNetCon::TermSetup(const bool bAnsiColor)
{
if (bAnsiColor)
Console_ColorInit();
SpdLog_Init(bAnsiColor);
Console_Init(bAnsiColor);
// Handle ctrl+x or X close events, give the application time to shutdown
// properly and flush all logging buffers.
@ -195,7 +193,7 @@ 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.c_str(), g_svGreyB.c_str(), DEFAULT_NET_ENCRYPTION_KEY, g_svReset.c_str());
g_svReset, g_svGreyB, DEFAULT_NET_ENCRYPTION_KEY, g_svReset);
SetKey(DEFAULT_NET_ENCRYPTION_KEY, true);
}
@ -235,7 +233,7 @@ void CNetCon::RunInput(const string& lineInput)
return;
}
vector<byte> vecMsg;
vector<char> vecMsg;
const SocketHandle_t hSocket = GetSocket();
bool bSend = false;
@ -244,27 +242,18 @@ void CNetCon::RunInput(const string& lineInput)
{
if (V_strcmp(cmd.Arg(0), "PASS") == 0) // Auth with RCON server.
{
const char* const pass = cmd.Arg(1);
const size_t passLen = strlen(pass);
bSend = Serialize(vecMsg, pass, passLen, "", 0,
bSend = Serialize(vecMsg, cmd.Arg(1), "",
netcon::request_e::SERVERDATA_REQUEST_AUTH);
}
else // Execute command query.
{
const char* const request = cmd.Arg(0);
const size_t requestLen = strlen(request);
const char* const command = cmd.GetCommandString();
const size_t commandLen = strlen(command);
bSend = Serialize(vecMsg, request, requestLen, command, commandLen,
bSend = Serialize(vecMsg, cmd.Arg(0), cmd.GetCommandString(),
netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND);
}
}
else // Single arg command query.
{
bSend = Serialize(vecMsg, lineInput.c_str(), lineInput.length(), "", 0, netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND);
bSend = Serialize(vecMsg, lineInput.c_str(), "", netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND);
}
if (bSend) // Only send if serialization process was successful.
@ -326,7 +315,7 @@ bool CNetCon::RunFrame(void)
if (IsConnected())
{
ConnectedNetConsoleData_s& pData = GetSocketCreator()->GetAcceptedSocketData(0);
CConnectedNetConsoleData& pData = GetSocketCreator()->GetAcceptedSocketData(0);
Recv(pData);
}
else if (GetPrompting())
@ -388,7 +377,7 @@ bool CNetCon::Connect(const char* pHostName, const int nPort)
if (m_bEncryptFrames)
{
Msg(eDLL_T::CLIENT, "Attempting connection to '%s' with key %s'%s%s%s'\n",
pHostName, g_svReset.c_str(), g_svGreyB.c_str(), GetKey(), g_svReset.c_str());
pHostName, g_svReset, g_svGreyB, GetKey(), g_svReset);
}
else
{
@ -424,7 +413,7 @@ void CNetCon::Disconnect(const char* szReason)
// nMsgLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetCon::ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen)
bool CNetCon::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
{
netcon::response response;
@ -443,10 +432,10 @@ bool CNetCon::ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen)
const long i = strtol(response.responseval().c_str(), NULL, NULL);
if (!i) // Means we are marked 'input only' on the rcon server.
{
vector<byte> vecMsg;
const bool ret = Serialize(vecMsg, "", 0, "1", 1, netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
vector<char> vecMsg;
bool ret = Serialize(vecMsg, "", "1", netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
if (ret && !Send(GetSocket(), vecMsg.data(), (u32)vecMsg.size()))
if (ret && !Send(GetSocket(), vecMsg.data(), int(vecMsg.size())))
{
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
}
@ -476,16 +465,14 @@ bool CNetCon::ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen)
// Purpose: serializes message to vector
// Input : &vecBuf -
// *szReqBuf -
// nReqMsgLen -
// *svReqVal -
// nReqValLen -
// requestType -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetCon::Serialize(vector<byte>& vecBuf, const char* szReqBuf, const size_t nReqMsgLen,
const char* szReqVal, const size_t nReqValLen, const netcon::request_e requestType) const
bool CNetCon::Serialize(vector<char>& vecBuf, const char* szReqBuf,
const char* szReqVal, const netcon::request_e requestType) const
{
return NetconClient_Serialize(this, vecBuf, szReqBuf, nReqMsgLen, szReqVal, nReqValLen, requestType, m_bEncryptFrames, true);
return NetconClient_Serialize(this, vecBuf, szReqBuf, szReqVal, requestType, m_bEncryptFrames, true);
}
//-----------------------------------------------------------------------------
@ -524,23 +511,27 @@ int main(int argc, char* argv[])
bool bEnableColor = false;
if (argc >= 2)
for (int i = 0; i < argc; i++)
{
bEnableColor = V_strcmp(argv[1], "-ansicolor") == NULL;
if (V_strcmp(argv[i], "-ansicolor") == NULL)
{
bEnableColor = true;
break;
}
}
// The address and key from command line if passed in.
const char* pAdr = nullptr;
const char* pKey = nullptr;
if (argc >= 2 + bEnableColor)
if (argc >= 2)
{
pAdr = argv[1 + bEnableColor];
pAdr = argv[1];
}
if (argc >= 3 + bEnableColor)
if (argc >= 3)
{
pKey = argv[2 + bEnableColor];
pKey = argv[2];
}
if (!NetConsole()->Init(bEnableColor, pAdr, pKey))

View File

@ -35,11 +35,11 @@ public:
virtual bool Connect(const char* pHostName, const int nHostPort = SOCKET_ERROR) override;
virtual void Disconnect(const char* szReason = nullptr) override;
virtual bool ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen) override;
virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override;
void TrySetKey(const char* const pKey);
bool Serialize(vector<byte>& vecBuf, const char* szReqBuf, const size_t nReqMsgLen,
const char* szReqVal, const size_t nReqValLen, const netcon::request_e requestType) const;
bool Serialize(vector<char>& vecBuf, const char* szReqBuf,
const char* szReqVal, const netcon::request_e requestType) const;
SocketHandle_t GetSocket(void);
bool IsInitialized(void) const;

View File

@ -36,7 +36,7 @@ void CBanSystem::LoadList(void)
pBuf[nRead] = '\0'; // Null terminate the string buffer containing our banned list.
rapidjson::Document document;
if (document.Parse(pBuf.get(), nRead).HasParseError())
if (document.Parse(pBuf.get()).HasParseError())
{
Warning(eDLL_T::SERVER, "%s: JSON parse error at position %zu: %s\n",
__FUNCTION__, document.GetErrorOffset(), rapidjson::GetParseError_En(document.GetParseError()));
@ -51,7 +51,7 @@ void CBanSystem::LoadList(void)
int nTotalBans = 0;
if (!JSON_GetValue(document, "totalBans", nTotalBans))
if (!JSON_GetValue(document, "totalBans", JSONFieldType_e::kSint32, nTotalBans))
{
return;
}
@ -62,15 +62,15 @@ void CBanSystem::LoadList(void)
rapidjson::Value::ConstMemberIterator entryIt;
if (JSON_GetIterator(document, rapidjson::StringRef(idx, strlen(idx)), JSONFieldType_e::kObject, entryIt))
if (JSON_GetIterator(document, idx, JSONFieldType_e::kObject, entryIt))
{
const rapidjson::Value& entry = entryIt->value;
const char* ipAddress = nullptr;
NucleusID_t nucleusId = NULL;
if (JSON_GetValue(entry, "ipAddress", ipAddress) &&
JSON_GetValue(entry, "nucleusId", nucleusId))
if (JSON_GetValue(entry, "ipAddress", JSONFieldType_e::kString, ipAddress) &&
JSON_GetValue(entry, "nucleusId", JSONFieldType_e::kUint64, nucleusId))
{
Banned_t banned;
@ -107,7 +107,7 @@ void CBanSystem::SaveList(void) const
rapidjson::Value obj(rapidjson::kObjectType);
obj.AddMember("ipAddress", rapidjson::Value(banned.m_Address.String(), banned.m_Address.Length(), allocator), allocator);
obj.AddMember("ipAddress", rapidjson::Value(banned.m_Address.String(), allocator), allocator);
obj.AddMember("nucleusId", banned.m_NucleusID, allocator);
document.AddMember(rapidjson::Value(idx, allocator), obj, allocator);
@ -324,7 +324,7 @@ void CBanSystem::AuthorPlayerByName(const char* playerName, const bool shouldBan
{
if (strcmp(playerName, pNetChan->GetName()) == NULL) // Our wanted name?
{
if (shouldBan && AddEntry(pNetChan->GetAddress(true), pClient->GetNucleusID()) && !bSave)
if (shouldBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
bSave = true;
pClient->Disconnect(REP_MARK_BAD, reason);
@ -389,7 +389,7 @@ void CBanSystem::AuthorPlayerById(const char* playerHandle, const bool shouldBan
continue;
}
if (shouldBan && AddEntry(pNetChan->GetAddress(true), pClient->GetNucleusID()) && !bSave)
if (shouldBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
bSave = true;
pClient->Disconnect(REP_MARK_BAD, reason);
@ -397,12 +397,10 @@ void CBanSystem::AuthorPlayerById(const char* playerHandle, const bool shouldBan
}
else
{
const char* const chanAddr = pNetChan->GetAddress(true);
if (strcmp(playerHandle, chanAddr) != NULL)
if (strcmp(playerHandle, pNetChan->GetAddress()) != NULL)
continue;
if (shouldBan && AddEntry(chanAddr, pClient->GetNucleusID()) && !bSave)
if (shouldBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
bSave = true;
pClient->Disconnect(REP_MARK_BAD, reason);

View File

@ -6,7 +6,6 @@
//
//=============================================================================//
#include "tier0/frametask.h"
#include "common/callback.h"
#include "rtech/playlists/playlists.h"
#include "engine/cmd.h"
#include "hostmanager.h"
@ -20,58 +19,33 @@ CServerHostManager::CServerHostManager(void)
{
}
//-----------------------------------------------------------------------------
// Purpose: internal server launch handler
//-----------------------------------------------------------------------------
static void HostManager_HandleCommandInternal(const char* const map, const char* const mode, const bool changeLevel)
{
Assert(!ThreadInServerFrameThread(), "Use server script GameRules_ChangeMap() instead!");
Msg(eDLL_T::ENGINE, "Starting server with name: \"%s\" map: \"%s\" mode: \"%s\"\n",
hostname->GetString(), map, mode);
bool hasPendingMap = *g_pPlaylistMapToLoad != '\0';
// NOTE: when the provided playlist is the same as the one we're currently
// on, and there's already a pending map load request, the game will run
// "map <mapName>" in Playlists_Parse, where the map name is dictated by
// g_pPlaylistMapToLoad. If changelevel was specified, we have to null the
// requested map here as to prevent Playlists_Parse from running the map
// command on it, as we are going to run the changelevel command anyways.
// Not doing this will result in running both map and changelevel commands.
if (changeLevel && hasPendingMap)
{
*g_pPlaylistMapToLoad = '\0';
hasPendingMap = false;
}
const bool samePlaylist = v_Playlists_Parse(mode);
char commandBuf[512];
if (!samePlaylist || !hasPendingMap)
{
snprintf(commandBuf, sizeof(commandBuf), "%s %s\n", changeLevel ? "changelevel" : "map", map);
Cbuf_AddText(Cbuf_GetCurrentPlayer(), commandBuf, cmd_source_t::kCommandSrcCode);
}
snprintf(commandBuf, sizeof(commandBuf), "mp_gamemode %s\n", mode);
Cbuf_AddText(Cbuf_GetCurrentPlayer(), commandBuf, cmd_source_t::kCommandSrcCode);
}
//-----------------------------------------------------------------------------
// Purpose: Launch server with given parameters
//-----------------------------------------------------------------------------
void CServerHostManager::LaunchServer(const char* const map, const char* const mode) const
void CServerHostManager::LaunchServer(const bool changeLevel) const
{
HostManager_HandleCommandInternal(map, mode, false);
}
if (!ThreadInMainThread())
{
g_TaskQueue.Dispatch([this, changeLevel]()
{
this->LaunchServer(changeLevel);
}, 0);
return;
}
//-----------------------------------------------------------------------------
// Purpose: Change level with given parameters
//-----------------------------------------------------------------------------
void CServerHostManager::ChangeLevel(const char* const map, const char* const mode) const
{
HostManager_HandleCommandInternal(map, mode, true);
Msg(eDLL_T::ENGINE, "Starting server with name: \"%s\" map: \"%s\" playlist: \"%s\"\n",
m_Server.name.c_str(), m_Server.map.c_str(), m_Server.playlist.c_str());
/*
* Playlist gets parsed in two instances, first in Playlists_Parse() with all the necessary
* values. Then when you would normally call launchplaylist which calls StartPlaylist it would cmd
* call mp_gamemode which parses the gamemode specific part of the playlist..
*/
v_Playlists_Parse(m_Server.playlist.c_str());
mp_gamemode->SetValue(m_Server.playlist.c_str());
const string command = Format("%s \"%s\"", changeLevel ? "changelevel" : "map", m_Server.map.c_str());
Cbuf_AddText(Cbuf_GetCurrentPlayer(), command.c_str(), cmd_source_t::kCommandSrcCode);
}
CServerHostManager g_ServerHostManager;

View File

@ -20,8 +20,7 @@ class CServerHostManager
public:
CServerHostManager();
void LaunchServer(const char* const map, const char* const mode) const;
void ChangeLevel(const char* const map, const char* const mode) const;
void LaunchServer(const bool changeLevel) const;
inline HostStatus_e GetHostStatus(void) const { return m_HostingStatus; }
inline void SetHostStatus(const HostStatus_e hostStatus) { m_HostingStatus = hostStatus; }
@ -29,6 +28,8 @@ public:
inline ServerVisibility_e GetVisibility(void) const { return m_ServerVisibility; }
inline void SetVisibility(const ServerVisibility_e visibility) { m_ServerVisibility = visibility; }
inline NetGameServer_t& GetDetails() { return m_Server; }
inline void SetCurrentToken(const string& token) { m_Token = token; }
inline const string& GetCurrentToken() const { return m_Token; }
@ -42,6 +43,8 @@ private:
HostStatus_e m_HostingStatus;
ServerVisibility_e m_ServerVisibility;
NetGameServer_t m_Server;
string m_Token;
string m_ErrorMsg;
string m_HostIP;

View File

@ -28,17 +28,17 @@ ConVar pylon_showdebuginfo("pylon_showdebuginfo", "0", FCVAR_RELEASE | FCVAR_ACC
//-----------------------------------------------------------------------------
static bool GetServerListingFromJSON(const rapidjson::Value& value, NetGameServer_t& outGameServer)
{
if (JSON_GetValue(value, "name", outGameServer.name) &&
JSON_GetValue(value, "description", outGameServer.description) &&
JSON_GetValue(value, "hidden", outGameServer.hidden) &&
JSON_GetValue(value, "map", outGameServer.map) &&
JSON_GetValue(value, "playlist", outGameServer.playlist) &&
JSON_GetValue(value, "ip", outGameServer.address) &&
JSON_GetValue(value, "port", outGameServer.port) &&
JSON_GetValue(value, "key", outGameServer.netKey) &&
JSON_GetValue(value, "checksum", outGameServer.checksum) &&
JSON_GetValue(value, "numPlayers", outGameServer.numPlayers) &&
JSON_GetValue(value, "maxPlayers", outGameServer.maxPlayers))
if (JSON_GetValue(value, "name", JSONFieldType_e::kString, outGameServer.name) &&
JSON_GetValue(value, "description", JSONFieldType_e::kString, outGameServer.description) &&
JSON_GetValue(value, "hidden", JSONFieldType_e::kBool, outGameServer.hidden) &&
JSON_GetValue(value, "map", JSONFieldType_e::kString, outGameServer.map) &&
JSON_GetValue(value, "playlist", JSONFieldType_e::kString, outGameServer.playlist) &&
JSON_GetValue(value, "ip", JSONFieldType_e::kString, outGameServer.address) &&
JSON_GetValue(value, "port", JSONFieldType_e::kSint32, outGameServer.port) &&
JSON_GetValue(value, "key", JSONFieldType_e::kString, outGameServer.netKey) &&
JSON_GetValue(value, "checksum", JSONFieldType_e::kUint32, outGameServer.checksum) &&
JSON_GetValue(value, "numPlayers", JSONFieldType_e::kSint32, outGameServer.numPlayers) &&
JSON_GetValue(value, "maxPlayers", JSONFieldType_e::kSint32, outGameServer.maxPlayers))
{
return true;
}
@ -48,8 +48,7 @@ static bool GetServerListingFromJSON(const rapidjson::Value& value, NetGameServe
//-----------------------------------------------------------------------------
// Purpose: gets a vector of hosted servers.
// Input : &outServerList -
// &outMessage -
// Input : &outMessage -
// Output : true on success, false on failure.
//-----------------------------------------------------------------------------
bool CPylon::GetServerList(vector<NetGameServer_t>& outServerList, string& outMessage) const
@ -96,7 +95,7 @@ bool CPylon::GetServerList(vector<NetGameServer_t>& outServerList, string& outMe
continue;
}
outServerList.emplace_back(std::move(gameServer));
outServerList.push_back(gameServer);
}
return true;
@ -122,8 +121,8 @@ bool CPylon::GetServerByToken(NetGameServer_t& outGameServer,
requestJson.SetObject();
rapidjson::Document::AllocatorType& allocator = requestJson.GetAllocator();
requestJson.AddMember("version", rapidjson::Value(SDK_VERSION, sizeof(SDK_VERSION)-1, requestJson.GetAllocator()), allocator);
requestJson.AddMember("token", rapidjson::Value(token.c_str(), token.length(), requestJson.GetAllocator()), allocator);
requestJson.AddMember("version", rapidjson::Value(SDK_VERSION, requestJson.GetAllocator()), allocator);
requestJson.AddMember("token", rapidjson::Value(token.c_str(), requestJson.GetAllocator()), allocator);
rapidjson::Document responseJson;
CURLINFO status;
@ -157,7 +156,6 @@ bool CPylon::GetServerByToken(NetGameServer_t& outGameServer,
// Purpose: Sends host server POST request.
// Input : &outMessage -
// &outToken -
// &outHostIp -
// &netGameServer -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
@ -174,16 +172,16 @@ bool CPylon::PostServerHost(string& outMessage, string& outToken, string& outHos
rapidjson::Document::AllocatorType& allocator = requestJson.GetAllocator();
requestJson.AddMember("name", rapidjson::Value(netGameServer.name.c_str(), netGameServer.name.length(), allocator), allocator);
requestJson.AddMember("description", rapidjson::Value(netGameServer.description.c_str(), netGameServer.description.length(), allocator), allocator);
requestJson.AddMember("name", rapidjson::Value(netGameServer.name.c_str(), allocator), allocator);
requestJson.AddMember("description", rapidjson::Value(netGameServer.description.c_str(), allocator), allocator);
requestJson.AddMember("hidden", netGameServer.hidden, allocator);
requestJson.AddMember("map", rapidjson::Value(netGameServer.map.c_str(), netGameServer.map.length(), allocator), allocator);
requestJson.AddMember("playlist", rapidjson::Value(netGameServer.playlist.c_str(), netGameServer.playlist.length(), allocator), allocator);
requestJson.AddMember("ip", rapidjson::Value(netGameServer.address.c_str(), netGameServer.address.length(), allocator), allocator);
requestJson.AddMember("map", rapidjson::Value(netGameServer.map.c_str(), allocator), allocator);
requestJson.AddMember("playlist", rapidjson::Value(netGameServer.playlist.c_str(), allocator), allocator);
requestJson.AddMember("ip", rapidjson::Value(netGameServer.address.c_str(), allocator), allocator);
requestJson.AddMember("port", netGameServer.port, allocator);
requestJson.AddMember("key", rapidjson::Value(netGameServer.netKey.c_str(), netGameServer.netKey.length(), allocator), allocator);
requestJson.AddMember("key", rapidjson::Value(netGameServer.netKey.c_str(), allocator), allocator);
requestJson.AddMember("checksum", netGameServer.checksum, allocator);
requestJson.AddMember("version", rapidjson::Value(netGameServer.versionId.c_str(), netGameServer.versionId.length(), allocator), allocator);
requestJson.AddMember("version", rapidjson::Value(netGameServer.versionId.c_str(), allocator), allocator);
requestJson.AddMember("numPlayers", netGameServer.numPlayers, allocator);
requestJson.AddMember("maxPlayers", netGameServer.maxPlayers, allocator);
requestJson.AddMember("timeStamp", netGameServer.timeStamp, allocator);
@ -200,7 +198,7 @@ bool CPylon::PostServerHost(string& outMessage, string& outToken, string& outHos
{
const char* token = nullptr;
if (!JSON_GetValue(responseJson, "token", token))
if (!JSON_GetValue(responseJson, "token", JSONFieldType_e::kString, token))
{
outMessage = Format("Invalid response with status: %d", int(status));
outToken.clear();
@ -213,8 +211,8 @@ bool CPylon::PostServerHost(string& outMessage, string& outToken, string& outHos
const char* ip = nullptr;
int port = 0;
if (JSON_GetValue(responseJson, "ip", ip) &&
JSON_GetValue(responseJson, "port", port))
if (JSON_GetValue(responseJson, "ip", JSONFieldType_e::kString, ip) &&
JSON_GetValue(responseJson, "port", JSONFieldType_e::kSint32, port))
{
outHostIp = Format("[%s]:%i", ip, port);
}
@ -246,7 +244,7 @@ bool CPylon::GetBannedList(const CBanSystem::BannedList_t& inBannedVec, CBanSyst
rapidjson::Value player(rapidjson::kObjectType);
player.AddMember("id", banned.m_NucleusID, allocator);
player.AddMember("ip", rapidjson::Value(banned.m_Address.String(), banned.m_Address.Length(), allocator), allocator);
player.AddMember("ip", rapidjson::Value(banned.m_Address.String(), allocator), allocator);
playersArray.PushBack(player, allocator);
}
@ -282,10 +280,10 @@ bool CPylon::GetBannedList(const CBanSystem::BannedList_t& inBannedVec, CBanSyst
for (const rapidjson::Value& obj : bannedPlayers)
{
const char* reason = nullptr;
JSON_GetValue(obj, "reason", reason);
JSON_GetValue(obj, "reason", JSONFieldType_e::kString, reason);
NucleusID_t nuc = NULL;
JSON_GetValue(obj, "id", nuc);
JSON_GetValue(obj, "id", JSONFieldType_e::kUint64, nuc);
CBanSystem::Banned_t banned(reason ? reason : "#DISCONNECT_BANNED", nuc);
(*outBannedVec)->AddToTail(banned);
@ -298,7 +296,6 @@ bool CPylon::GetBannedList(const CBanSystem::BannedList_t& inBannedVec, CBanSyst
// Purpose: Checks if client is banned on the comp server.
// Input : &ipAddress -
// nucleusId -
// &personaName -
// &outReason - <- contains banned reason if any.
// Output : True if banned, false if not banned.
//-----------------------------------------------------------------------------
@ -330,13 +327,13 @@ bool CPylon::CheckForBan(const string& ipAddress, const uint64_t nucleusId, cons
bool isBanned = false;
if (JSON_GetValue(responseJson, "banned", isBanned))
if (JSON_GetValue(responseJson, "banned", JSONFieldType_e::kBool, isBanned))
{
if (isBanned)
{
const char* reason = nullptr;
outReason = JSON_GetValue(responseJson, "reason", reason)
outReason = JSON_GetValue(responseJson, "reason", JSONFieldType_e::kString, reason)
? reason
: "#DISCONNECT_BANNED";
@ -385,7 +382,7 @@ bool CPylon::AuthForConnection(const uint64_t nucleusId, const char* ipAddress,
const char* token = nullptr;
if (JSON_GetValue(responseJson, "token", token))
if (JSON_GetValue(responseJson, "token", JSONFieldType_e::kString, token))
{
outToken = token;
return true;
@ -434,9 +431,9 @@ bool CPylon::GetEULA(MSEulaData_t& outData, string& outMessage) const
const char* contents = nullptr;
// check if the EULA response fields are valid.
if (!JSON_GetValue(data, "version", version) ||
!JSON_GetValue(data, "language", language) ||
!JSON_GetValue(data, "contents", contents))
if (!JSON_GetValue(data, "version", JSONFieldType_e::kSint32, version) ||
!JSON_GetValue(data, "language", JSONFieldType_e::kString, language) ||
!JSON_GetValue(data, "contents", JSONFieldType_e::kString, contents))
{
outMessage = "schema is invalid";
return false;
@ -480,7 +477,7 @@ bool CPylon::SendRequest(const char* endpoint, const rapidjson::Document& reques
if (status == 200) // STATUS_OK
{
responseJson.Parse(responseBody.c_str(), responseBody.length()+1);
responseJson.Parse(responseBody.c_str());
if (responseJson.HasParseError())
{
@ -503,7 +500,7 @@ bool CPylon::SendRequest(const char* endpoint, const rapidjson::Document& reques
bool success = false;
if (JSON_GetValue(responseJson, "success", success)
if (JSON_GetValue(responseJson, "success", JSONFieldType_e::kBool, success)
&& success)
{
return true;
@ -591,7 +588,7 @@ void CPylon::ExtractError(const rapidjson::Document& resultJson, string& outMess
const char* error = nullptr;
if (resultJson.IsObject() &&
JSON_GetValue(resultJson, "error", error))
JSON_GetValue(resultJson, "error", JSONFieldType_e::kString, error))
{
outMessage = error;
}
@ -620,7 +617,7 @@ void CPylon::ExtractError(const string& response, string& outMessage,
if (!response.empty())
{
rapidjson::Document resultBody;
resultBody.Parse(response.c_str(), response.length()+1);
resultBody.Parse(response.c_str());
ExtractError(resultBody, outMessage, status, errorText);
}

View File

@ -14,8 +14,8 @@ struct NetGameServer_t
// the level and playlist of the server, which will be display to the
// client's server browser
string map;
string playlist;
string map = "mp_lobby";
string playlist = "dev_default";
// the address and port of the server, validated and set from the
// masterserver

View File

@ -1,13 +0,0 @@
cmake_minimum_required( VERSION 3.16 )
add_module( "lib" "particles" "vpc" ${FOLDER_CONTEXT} TRUE TRUE )
start_sources()
add_sources( SOURCE_GROUP "Runtime"
"particles.cpp"
"particles.h"
)
end_sources()
target_include_directories( ${PROJECT_NAME} PRIVATE "${ENGINE_SOURCE_DIR}/tier0/" "${ENGINE_SOURCE_DIR}/tier1/" )

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