mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Compare commits
256 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d73ce9ed72 | ||
|
dea3888973 | ||
|
f2e332efa0 | ||
|
7de9196d7d | ||
|
905f496474 | ||
|
5d7c94ae2f | ||
|
def96b25a7 | ||
|
85d99364cb | ||
|
08646370c4 | ||
|
3c30d959dd | ||
|
1e1fe1beff | ||
|
0a0eeca20a | ||
|
b0423ee74b | ||
|
fdab5dea84 | ||
|
f491f3dfe3 | ||
|
b1d81e2dc5 | ||
|
e223cec9c2 | ||
|
7607ca073f | ||
|
8b0bdae883 | ||
|
f0f90e5c1b | ||
|
d36ea4d769 | ||
|
1331c3c67b | ||
|
26ec02f302 | ||
|
73b517600d | ||
|
bfe96e9ccd | ||
|
8646dfa516 | ||
|
fde639e167 | ||
|
bb566cd1fd | ||
|
e27fc72e25 | ||
|
18e71086b6 | ||
|
4188c13780 | ||
|
13301bceae | ||
|
d6cff51624 | ||
|
ff303d5de8 | ||
|
d7ebf62c38 | ||
|
27285fc087 | ||
|
eaf313ab7a | ||
|
e8fc542907 | ||
|
3ac646da64 | ||
|
e55975100e | ||
|
949b71a162 | ||
|
c4bf79376e | ||
|
72cbe5bc63 | ||
|
d810768895 | ||
|
456a68af05 | ||
|
b8550c9f32 | ||
|
24bce8ee73 | ||
|
8339c44c25 | ||
|
5a6c655196 | ||
|
56aba36b8c | ||
|
f18dd71f4b | ||
|
51931b59db | ||
|
b288d072db | ||
|
e63660b549 | ||
|
c8ee0d4333 | ||
|
b4f68d69ce | ||
|
0f17987599 | ||
|
452c226316 | ||
|
66a271d003 | ||
|
c8c321e924 | ||
|
a5bd66513a | ||
|
5584c2a87f | ||
|
5f5bbb9164 | ||
|
726b5c9fbc | ||
|
bf7f128acf | ||
|
291a99e3ae | ||
|
5742163756 | ||
|
bf3bd90dc7 | ||
|
9eeb0606e7 | ||
|
1766530af1 | ||
|
2dc28bb742 | ||
|
2083bc73fa | ||
|
aa405dc4c3 | ||
|
d3a2fd5238 | ||
|
d049b2df1c | ||
|
de4a3d294c | ||
|
9bcbf3187c | ||
|
18f2e27409 | ||
|
03dd7046a6 | ||
|
eee6aed033 | ||
|
ec9fc7d77f | ||
|
6827d1ed02 | ||
|
716a3efa0c | ||
|
c2deaaf3e8 | ||
|
74d8cdfb26 | ||
|
4d4fb66477 | ||
|
117e2d77e4 | ||
|
e9a2aea17c | ||
|
5d000db867 | ||
|
1a5a77f9c8 | ||
|
d8326575e5 | ||
|
4a2f5d2aa5 | ||
|
68271b9768 | ||
|
e1f0de0089 | ||
|
164c594486 | ||
|
37e3c8c653 | ||
|
4445edac6d | ||
|
561fc25c8e | ||
|
6d4de8c5b7 | ||
|
ca7b0d9981 | ||
|
b1ad2c19b8 | ||
|
3cbdab512d | ||
|
b617caf1d8 | ||
|
538df8e02c | ||
|
05f37cad73 | ||
|
e6c7c7d279 | ||
|
62d0dab7cd | ||
|
746660490b | ||
|
059f9fc82d | ||
|
aefebd846e | ||
|
aba1ed26b5 | ||
|
48e79faffa | ||
|
49d1f6f1fe | ||
|
3b44bbc6bc | ||
|
bd9beaa33a | ||
|
5e0c24ad84 | ||
|
36d2b3534a | ||
|
d20488c919 | ||
|
f0511a89a7 | ||
|
8720dde3cb | ||
|
6ae072386d | ||
|
6bf516f1ef | ||
|
b75655c101 | ||
|
4ffcc4ca75 | ||
|
bef61249fd | ||
|
c6d451c753 | ||
|
26f48507f4 | ||
|
2a357914da | ||
|
92842e4ac2 | ||
|
5f8afd9cf0 | ||
|
5369b21a64 | ||
|
3f12f6f203 | ||
|
551840e6a3 | ||
|
8490344d93 | ||
|
6a8eb40930 | ||
|
8c85e1ec68 | ||
|
9939d963ef | ||
|
3d8d0b37a6 | ||
|
3209af9a6c | ||
|
67b43192ef | ||
|
fbf95f64ad | ||
|
7fd33da180 | ||
|
e0c7a9b980 | ||
|
fd0521fce6 | ||
|
e38d9ab1e9 | ||
|
8237f2b1f3 | ||
|
163f38c87d | ||
|
138600a3a6 | ||
|
77851d9ad7 | ||
|
c8e8bea154 | ||
|
f7f9e9e425 | ||
|
7ec1e679fd | ||
|
7ee1626233 | ||
|
bb99cec2fe | ||
|
fd04eef1ce | ||
|
02a0088deb | ||
|
c09e6d6948 | ||
|
ec77faeb97 | ||
|
ab0ec34e80 | ||
|
2128b0ad04 | ||
|
10b466bde7 | ||
|
ffbbbfc483 | ||
|
1fd4c25cd0 | ||
|
bae7df37ae | ||
|
7febdde3d4 | ||
|
e05d137acd | ||
|
bd06ddcb74 | ||
|
8c7bb52673 | ||
|
6f534e9811 | ||
|
6ed6711426 | ||
|
a003e21f6e | ||
|
59bdc55d15 | ||
|
a6a0226481 | ||
|
2f618bbe04 | ||
|
f78a842744 | ||
|
f212e96a96 | ||
|
e4dafa240e | ||
|
745024d198 | ||
|
9b2034d897 | ||
|
e5b6e3eb6e | ||
|
eb374b4328 | ||
|
d276a8c850 | ||
|
64393f6e5f | ||
|
77637019d1 | ||
|
953bdf5d5f | ||
|
874314ee1c | ||
|
72c71fac8b | ||
|
ba83bd9ae9 | ||
|
d655ae8b4d | ||
|
d444900b9a | ||
|
f5f14c153f | ||
|
7a40db4d85 | ||
|
3eea52b199 | ||
|
35c6655e20 | ||
|
1c36dfa484 | ||
|
3d56934cc0 | ||
|
19896857e2 | ||
|
add4037504 | ||
|
1ec3df5874 | ||
|
3f3b69e2bb | ||
|
5d20256f10 | ||
|
03d19344fe | ||
|
0dde788aa7 | ||
|
e2b931d6d8 | ||
|
4d2ac77ac7 | ||
|
8de652b4c9 | ||
|
68b7c25a10 | ||
|
3dcb058774 | ||
|
440e5f7fe1 | ||
|
d4d2244b93 | ||
|
1e7bfcde2e | ||
|
f45ca75474 | ||
|
20e212b1ea | ||
|
aac8c84442 | ||
|
bc54931408 | ||
|
7114bc6a40 | ||
|
18545ec422 | ||
|
f0fcb821a8 | ||
|
36bee21784 | ||
|
fa949c8e6a | ||
|
a331d43488 | ||
|
b88ed6d5cb | ||
|
14e0c8f5e4 | ||
|
3d5ddd2bed | ||
|
e8fe12b4fd | ||
|
da6ffe9005 | ||
|
b3796c32cc | ||
|
ad741882ae | ||
|
abe5578557 | ||
|
1909ad63ab | ||
|
35f5c34190 | ||
|
93588edca5 | ||
|
c0a451f90d | ||
|
2813c0e24f | ||
|
94c296561f | ||
|
c71d7f52dc | ||
|
62f7b04f5a | ||
|
a6958dcee7 | ||
|
cb598e397d | ||
|
46e2424bb2 | ||
|
4aee1e707c | ||
|
24e731e4ee | ||
|
e5d7644d19 | ||
|
b16985ee0c | ||
|
0a0c99ba77 | ||
|
35b23915d3 | ||
|
9a9e84f974 | ||
|
a809b1f262 | ||
|
5ed734a4ff | ||
|
5e962d6eb0 | ||
|
50b4c559c6 | ||
|
c1ca886ee5 | ||
|
cce4429606 | ||
|
0806b10f79 | ||
|
427860e6e9 | ||
|
c72e34606b |
@ -12,7 +12,6 @@ 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 )
|
||||
@ -68,7 +67,9 @@ 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 )
|
||||
|
@ -100,6 +100,13 @@ 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()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@ -113,7 +120,7 @@ macro( whole_program_optimization )
|
||||
endmacro()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Toggles wether or not to treat warnings as errors
|
||||
# Toggles whether or not to treat warnings as errors
|
||||
# -----------------------------------------------------------------------------
|
||||
macro( warnings_as_errors TARGET FLAG )
|
||||
if( ${FLAG} )
|
||||
|
@ -32,15 +32,16 @@ bool Miles_Initialize()
|
||||
if (!isDefaultLanguage)
|
||||
{
|
||||
const bool useShipSound = !CommandLine()->FindParm("-devsound") || CommandLine()->FindParm("-shipsound");
|
||||
char baseStreamFilePath[MAX_PATH];
|
||||
|
||||
const std::string baseStreamFilePath = Format("%s/general_%s.mstr", useShipSound ? "audio/ship" : "audio/dev", pszLanguage);
|
||||
V_snprintf(baseStreamFilePath, sizeof(baseStreamFilePath), "%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.c_str()))
|
||||
if (!FileSystem()->FileExists(baseStreamFilePath))
|
||||
{
|
||||
Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to '%s'...\n",
|
||||
__FUNCTION__, pszLanguage, baseStreamFilePath.c_str(), MILES_DEFAULT_LANGUAGE);
|
||||
__FUNCTION__, pszLanguage, baseStreamFilePath, MILES_DEFAULT_LANGUAGE);
|
||||
|
||||
pszLanguage = MILES_DEFAULT_LANGUAGE;
|
||||
miles_language->SetValue(pszLanguage);
|
||||
@ -51,7 +52,7 @@ bool Miles_Initialize()
|
||||
CFastTimer initTimer;
|
||||
|
||||
initTimer.Start();
|
||||
bool bResult = v_Miles_Initialize();
|
||||
const bool bResult = v_Miles_Initialize();
|
||||
initTimer.End();
|
||||
|
||||
Msg(eDLL_T::AUDIO, "%s: %s ('%f' seconds)\n", __FUNCTION__, bResult ? "success" : "failure", initTimer.GetDuration().GetSeconds());
|
||||
@ -116,6 +117,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);
|
||||
}
|
||||
|
@ -231,28 +231,24 @@ void VPK_Unmount_f(const CCommand& args)
|
||||
|
||||
void LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue, ChangeUserData_t pUserData)
|
||||
{
|
||||
if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName()))
|
||||
const char* pNewString = language_cvar->GetString();
|
||||
|
||||
if (strcmp(pOldString, pNewString) == NULL)
|
||||
return; // Same language.
|
||||
|
||||
if (!Localize_IsLanguageSupported(pNewString))
|
||||
{
|
||||
const char* pNewString = pConVarRef->GetString();
|
||||
|
||||
if (strcmp(pOldString, pConVarRef->GetString()) == NULL)
|
||||
return; // Same language.
|
||||
|
||||
if (!Localize_IsLanguageSupported(pNewString))
|
||||
// if new text isn't valid but the old value is, reset the value
|
||||
if (Localize_IsLanguageSupported(pOldString))
|
||||
pNewString = pOldString;
|
||||
else
|
||||
{
|
||||
// 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];
|
||||
}
|
||||
// this shouldn't really happen, but if neither the old nor new values are valid, set to english
|
||||
Assert(0);
|
||||
pNewString = g_LanguageNames[0];
|
||||
}
|
||||
|
||||
pConVarRef->SetValue(pNewString);
|
||||
g_MasterServer.SetLanguage(pNewString);
|
||||
language_cvar->SetValue(pNewString);
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,61 +287,59 @@ 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)
|
||||
{
|
||||
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);
|
||||
const CMaterialGlue* const materialGlue = v_GetMaterialAtCrossHair();
|
||||
|
||||
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
|
||||
if (!materialGlue)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -170,6 +170,18 @@ 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:
|
||||
|
@ -11,6 +11,7 @@ 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]);
|
||||
|
||||
|
@ -57,6 +57,7 @@ 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;
|
||||
@ -186,8 +187,11 @@ 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");
|
||||
@ -274,12 +278,14 @@ void ConVar_InitShipped(void)
|
||||
|
||||
mp_gamemode->RemoveFlags(FCVAR_DEVELOPMENTONLY);
|
||||
|
||||
#ifdef DEDICATED
|
||||
// The base callback is for client builds only, must be removed from the
|
||||
// dedicated server as it features client globals.
|
||||
// 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.
|
||||
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);
|
||||
|
@ -39,10 +39,11 @@ 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;
|
||||
|
@ -4,10 +4,11 @@
|
||||
//
|
||||
//===========================================================================//
|
||||
#pragma once
|
||||
#include "netcon/INetCon.h"
|
||||
|
||||
typedef int SocketHandle_t;
|
||||
|
||||
enum class ServerDataRequestType_t : int
|
||||
enum class ServerDataRequestType_e : int
|
||||
{
|
||||
SERVERDATA_REQUEST_VALUE = 0,
|
||||
SERVERDATA_REQUEST_SETVALUE,
|
||||
@ -17,7 +18,7 @@ enum class ServerDataRequestType_t : int
|
||||
SERVERDATA_REQUEST_SEND_REMOTEBUG,
|
||||
};
|
||||
|
||||
enum class ServerDataResponseType_t : int
|
||||
enum class ServerDataResponseType_e : int
|
||||
{
|
||||
SERVERDATA_RESPONSE_VALUE = 0,
|
||||
SERVERDATA_RESPONSE_UPDATE,
|
||||
@ -27,20 +28,20 @@ enum class ServerDataResponseType_t : int
|
||||
SERVERDATA_RESPONSE_REMOTEBUG,
|
||||
};
|
||||
|
||||
class CConnectedNetConsoleData
|
||||
struct ConnectedNetConsoleData_s
|
||||
{
|
||||
public:
|
||||
SocketHandle_t m_hSocket;
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
vector<uint8_t> m_RecvBuffer;
|
||||
NetConFrameHeader_s m_FrameHeader; // Current frame header.
|
||||
vector<byte> m_RecvBuffer;
|
||||
|
||||
CConnectedNetConsoleData(SocketHandle_t hSocket = -1)
|
||||
ConnectedNetConsoleData_s(SocketHandle_t hSocket = -1)
|
||||
{
|
||||
m_hSocket = hSocket;
|
||||
m_nPayloadLen = 0;
|
||||
@ -50,22 +51,19 @@ public:
|
||||
m_bValidated = false;
|
||||
m_bAuthorized = false;
|
||||
m_bInputOnly = true;
|
||||
m_RecvBuffer.resize(sizeof(u_long)); // Reserve enough for length-prefix.
|
||||
m_FrameHeader.magic = 0;
|
||||
m_FrameHeader.length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* PACKET FORMAT **********************************
|
||||
|
||||
REQUEST:
|
||||
int requestID;
|
||||
int ServerDataRequestType_t;
|
||||
NullTerminatedString (variable or command)
|
||||
NullTerminatedString (value)
|
||||
NetConFrameHeader_s header;
|
||||
byte* data;
|
||||
|
||||
RESPONSE:
|
||||
int requestID;
|
||||
int ServerDataResponseType_t;
|
||||
NullTerminatedString (variable)
|
||||
NullTerminatedString (value)
|
||||
NetConFrameHeader_s header;
|
||||
byte* data;
|
||||
|
||||
***************************************************/
|
||||
|
@ -70,24 +70,24 @@ bool SVC_UserMessage::ProcessImpl()
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool SVC_SetClassVar::ReadFromBuffer(bf_read* buffer)
|
||||
{
|
||||
const bool set = buffer->ReadString(m_szSetting, sizeof(m_szSetting));
|
||||
const bool var = buffer->ReadString(m_szVariable, sizeof(m_szVariable));
|
||||
const bool key = buffer->ReadString(m_szKey, sizeof(m_szKey));
|
||||
const bool val = buffer->ReadString(m_szValue, sizeof(m_szValue));
|
||||
|
||||
return set && var;
|
||||
return key && val;
|
||||
}
|
||||
bool SVC_SetClassVar::WriteToBuffer(bf_write* buffer)
|
||||
{
|
||||
const bool set = buffer->WriteString(m_szSetting);
|
||||
const bool var = buffer->WriteString(m_szVariable);
|
||||
const bool key = buffer->WriteString(m_szKey);
|
||||
const bool val = buffer->WriteString(m_szValue);
|
||||
|
||||
return set && var;
|
||||
return key && val;
|
||||
}
|
||||
bool SVC_SetClassVar::Process(void)
|
||||
{
|
||||
const char* pArgs[3] = {
|
||||
"_setClassVarClient",
|
||||
m_szSetting,
|
||||
m_szVariable
|
||||
m_szKey,
|
||||
m_szValue
|
||||
};
|
||||
|
||||
CCommand command((int)V_ARRAYSIZE(pArgs), pArgs, cmd_source_t::kCommandSrcCode);
|
||||
|
@ -464,13 +464,13 @@ class SVC_SetClassVar : public CNetMessage
|
||||
{
|
||||
public:
|
||||
SVC_SetClassVar() = default;
|
||||
SVC_SetClassVar(const char* setting, const char* var)
|
||||
SVC_SetClassVar(const char* key, const char* value)
|
||||
{
|
||||
V_strncpy(m_szSetting, setting, sizeof(m_szSetting));
|
||||
V_strncpy(m_szVariable, var, sizeof(m_szVariable));
|
||||
V_strncpy(m_szKey, key, sizeof(m_szKey));
|
||||
V_strncpy(m_szValue, value, sizeof(m_szValue));
|
||||
|
||||
m_szSetting[sizeof(m_szSetting) - 1] = '\0';
|
||||
m_szVariable[sizeof(m_szVariable) - 1] = '\0';
|
||||
m_szKey[sizeof(m_szKey) - 1] = '\0';
|
||||
m_szValue[sizeof(m_szValue) - 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: setting \"%s\", variable \"%s\"", this->GetName(), m_szSetting, m_szVariable);
|
||||
V_snprintf(szBuf, sizeof(szBuf), "%s: key \"%s\", value \"%s\"", this->GetName(), m_szKey, m_szValue);
|
||||
|
||||
return szBuf;
|
||||
};
|
||||
|
||||
virtual size_t GetSize(void) const { return sizeof(SVC_SetClassVar); }
|
||||
|
||||
char m_szSetting[128];
|
||||
char m_szVariable[128];
|
||||
char m_szKey[128];
|
||||
char m_szValue[128];
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -26,14 +26,14 @@
|
||||
#define C2S_CHALLENGE 'H' // + challenge value
|
||||
#define S2C_CHALLENGE 'I' // + challenge value
|
||||
|
||||
#define S2C_CONNACCEPT 'J'
|
||||
#define S2C_CONNACCEPT 'J' // special protocol for accepted connections
|
||||
#define S2C_CONNREJECT 'K' // special protocol for rejected connections
|
||||
|
||||
// Generic Ping Request
|
||||
#define A2A_PING 'L' // respond with an A2A_ACK
|
||||
#define A2A_ACK 'M' // general acknowledgment without info
|
||||
#define A2A_PING 'L' // respond with an A2A_ACK
|
||||
#define A2A_ACK 'M' // general acknowledgment without info
|
||||
|
||||
#define S2C_UNKNOWN_UISCRIPT 'N' // TODO: figure out what this does, see [r5apex + 0x288880]
|
||||
#define S2C_MATCHINFO_UPDATE 'N' // remote match info update
|
||||
|
||||
// Data Block Request
|
||||
#define S2C_DATABLOCK_FRAGMENT 'O' // data block fragment
|
||||
|
@ -113,6 +113,8 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
|
||||
"vgui"
|
||||
"rui"
|
||||
|
||||
"particles"
|
||||
|
||||
"d3d11.lib"
|
||||
"${THIRDPARTY_SOURCE_DIR}/nvapi/amd64/nvapi64.lib"
|
||||
)
|
||||
|
@ -18,6 +18,9 @@
|
||||
#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"
|
||||
@ -55,8 +58,8 @@ void Show_Emblem()
|
||||
|
||||
// Log the SDK's 'build_id' under the emblem.
|
||||
Msg(eDLL_T::SYSTEM_ERROR,
|
||||
"+------------------------------------------------[%s%010d%s]-+\n",
|
||||
g_svYellowF, g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svRedF);
|
||||
"+------------------------------------------------[%s%010u%s]-+\n",
|
||||
g_svYellowF.c_str(), g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svRedF.c_str());
|
||||
Msg(eDLL_T::SYSTEM_ERROR, "\n");
|
||||
}
|
||||
|
||||
@ -124,6 +127,10 @@ void SDK_Init()
|
||||
s_bConsoleInitialized = Console_Init(bAnsiColor);
|
||||
}
|
||||
|
||||
#ifndef DEDICATED
|
||||
ImguiSystem()->SetEnabled(!CommandLine()->CheckParm("-noimgui"));
|
||||
#endif // !DEDICATED
|
||||
|
||||
SpdLog_Init(bAnsiColor);
|
||||
Show_Emblem();
|
||||
|
||||
|
@ -44,11 +44,13 @@
|
||||
#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"
|
||||
@ -267,15 +269,17 @@ 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
|
||||
@ -559,6 +563,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
|
||||
#ifndef DEDICATED
|
||||
REGISTER(VMaterialGlue);
|
||||
REGISTER(VShaderGlue);
|
||||
REGISTER(VTextureStreaming);
|
||||
|
||||
// Studio
|
||||
REGISTER(VStudioRenderContext);
|
||||
@ -569,6 +574,9 @@ 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);
|
||||
|
@ -2,13 +2,8 @@
|
||||
#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()
|
||||
{
|
||||
@ -60,17 +55,14 @@ void SpdLog_Init(const bool bAnsiColor)
|
||||
|
||||
#ifndef _TOOLS
|
||||
g_LogSessionUUID = CreateUUID();
|
||||
g_LogSessionDirectory = fmt::format("platform/logs/{:s}", g_LogSessionUUID);
|
||||
/************************
|
||||
* IMGUI LOGGER SETUP *
|
||||
************************/
|
||||
|
||||
if (g_LogSessionUUID.empty())
|
||||
{
|
||||
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);
|
||||
// Fall-back directory in case of a failure.
|
||||
g_LogSessionUUID = "00000000-0000-0000-0000-000000000000";
|
||||
}
|
||||
|
||||
g_LogSessionDirectory = fmt::format("platform/logs/{:s}", g_LogSessionUUID);
|
||||
#endif // !_TOOLS
|
||||
/************************
|
||||
* WINDOWS LOGGER SETUP *
|
||||
@ -92,7 +84,6 @@ void SpdLog_Init(const bool bAnsiColor)
|
||||
{
|
||||
g_TermLogger->set_pattern("%v");
|
||||
}
|
||||
//g_TermLogger->set_level(spdlog::level::trace);
|
||||
}
|
||||
|
||||
#ifndef _TOOLS
|
||||
|
@ -22,11 +22,6 @@ 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);
|
||||
|
||||
|
@ -72,21 +72,24 @@ ImVec4 GetColorForContext(LogType_t type, eDLL_T context)
|
||||
}
|
||||
#endif // !DEDICATED && !_TOOLS
|
||||
|
||||
const char* GetContextNameByIndex(eDLL_T context, const bool ansiColor = false)
|
||||
static const char* GetContextNameByIndex(eDLL_T context, size_t& numTotalChars, size_t& numAnsiChars, const bool ansiColor)
|
||||
{
|
||||
int index = static_cast<int>(context);
|
||||
const char* contextName = s_DefaultAnsiColor;
|
||||
const int index = static_cast<int>(context);
|
||||
const char* contextName;
|
||||
|
||||
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:
|
||||
@ -102,17 +105,22 @@ const char* GetContextNameByIndex(eDLL_T context, const bool ansiColor = false)
|
||||
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 += sizeof(s_DefaultAnsiColor) - 1;
|
||||
contextName += s_AnsiColorTextSize;
|
||||
numTotalChars -= s_AnsiColorTextSize;
|
||||
}
|
||||
else
|
||||
numAnsiChars = s_AnsiColorTextSize;
|
||||
|
||||
return contextName;
|
||||
}
|
||||
@ -147,11 +155,16 @@ 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);
|
||||
|
||||
const char* pszContext = GetContextNameByIndex(context, bUseColor);
|
||||
message.append(pszContext);
|
||||
size_t numTotalContextTextChars = 0;
|
||||
size_t numAnsiContextChars = 0;
|
||||
|
||||
const char* pszContext = GetContextNameByIndex(context, numTotalContextTextChars, numAnsiContextChars, bUseColor);
|
||||
message.append(pszContext, numTotalContextTextChars);
|
||||
|
||||
#if !defined (DEDICATED) && !defined (_TOOLS)
|
||||
ImVec4 overlayColor = GetColorForContext(logType, context);
|
||||
@ -166,6 +179,9 @@ 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
|
||||
//-------------------------------------------------------------------------
|
||||
@ -178,6 +194,7 @@ 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:
|
||||
@ -187,6 +204,7 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
|
||||
if (bUseColor)
|
||||
{
|
||||
message.append(g_svRedF);
|
||||
numMessageAnsiChars = g_svRedF.length();
|
||||
}
|
||||
break;
|
||||
#ifndef _TOOLS
|
||||
@ -248,12 +266,28 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
|
||||
|
||||
if (bUseColor)
|
||||
{
|
||||
message.append(g_svRedF);
|
||||
if (logType != LogType_t::LOG_ERROR)
|
||||
{
|
||||
if (numMessageAnsiChars > 0)
|
||||
message.replace(messageTextStartIndex, numMessageAnsiChars, g_svRedF);
|
||||
else
|
||||
message.append(g_svRedF);
|
||||
|
||||
numMessageAnsiChars = g_svRedF.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bUseColor && bWarning)
|
||||
{
|
||||
message.append(g_svYellowF);
|
||||
if (logType != LogType_t::LOG_ERROR)
|
||||
{
|
||||
if (numMessageAnsiChars > 0)
|
||||
message.replace(messageTextStartIndex, numMessageAnsiChars, g_svYellowF);
|
||||
else
|
||||
message.append(g_svYellowF);
|
||||
|
||||
numMessageAnsiChars = g_svYellowF.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !_TOOLS
|
||||
@ -267,9 +301,24 @@ 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)
|
||||
{
|
||||
// Remove ANSI rows before emitting to file or over wire.
|
||||
// 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.
|
||||
message = std::regex_replace(message, s_AnsiRowRegex, "");
|
||||
}
|
||||
}
|
||||
@ -282,38 +331,32 @@ 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);
|
||||
ntlogger->debug(message);
|
||||
|
||||
if (ntlogger)
|
||||
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(), pszUpTime, netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG,
|
||||
RCONServer()->SendEncoded(formatted.c_str(), formatted.length(), pszUpTime, contextTextStartIndex, netcon::response_e::SERVERDATA_RESPONSE_CONSOLE_LOG,
|
||||
int(context), int(logType));
|
||||
}
|
||||
#endif // !CLIENT_DLL
|
||||
#ifndef DEDICATED
|
||||
g_ImGuiLogger->debug(message);
|
||||
|
||||
const string logStreamBuf = g_LogStream.str();
|
||||
g_Console.AddLog(logStreamBuf.c_str(), ImGui::ColorConvertFloat4ToU32(overlayColor));
|
||||
g_Console.AddLog(message.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, logStreamBuf.c_str());
|
||||
g_TextOverlay.AddLog(overlayContext, message.c_str(), (ssize_t)message.length());
|
||||
}
|
||||
#endif // !DEDICATED
|
||||
}
|
||||
|
||||
#ifndef DEDICATED
|
||||
g_LogStream.str(string());
|
||||
g_LogStream.clear();
|
||||
#endif // !DEDICATED
|
||||
|
||||
#else
|
||||
if (g_SuppementalToolsLogger)
|
||||
{
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
#include <charconv>
|
||||
|
||||
#include <smmintrin.h>
|
||||
|
||||
|
@ -25,6 +25,24 @@
|
||||
|
||||
#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"
|
||||
|
@ -1,19 +1,19 @@
|
||||
#include "core/stdafx.h"
|
||||
#include "core/termutil.h"
|
||||
|
||||
const char* g_svGreyF = "";
|
||||
const char* g_svRedF = "";
|
||||
const char* g_svGreenF = "";
|
||||
const char* g_svBlueF = "";
|
||||
const char* g_svYellowF = "";
|
||||
std::string g_svGreyF;
|
||||
std::string g_svRedF;
|
||||
std::string g_svGreenF;
|
||||
std::string g_svBlueF;
|
||||
std::string g_svYellowF;
|
||||
|
||||
const char* g_svGreyB = "";
|
||||
const char* g_svRedB = "";
|
||||
const char* g_svGreenB = "";
|
||||
const char* g_svBlueB = "";
|
||||
const char* g_svYellowB = "";
|
||||
std::string g_svGreyB;
|
||||
std::string g_svRedB;
|
||||
std::string g_svGreenB;
|
||||
std::string g_svBlueB;
|
||||
std::string g_svYellowB;
|
||||
|
||||
const char* g_svReset = "";
|
||||
std::string g_svReset;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the global ansi escape sequences.
|
||||
|
@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
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_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_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_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_svReset;
|
||||
extern std::string g_svReset;
|
||||
|
||||
void AnsiColors_Init();
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "public/studio.h"
|
||||
|
||||
CStudioFallbackHandler g_StudioMdlFallbackHandler;
|
||||
#define IS_VALID_DATACACHE_HANDLE(cacheHandle) (cacheHandle && cacheHandle != DC_INVALID_HANDLE)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: finds an MDL
|
||||
@ -47,7 +46,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle
|
||||
studiomodelcache_t* modelCache = studioData->GetModelCache();
|
||||
|
||||
// Store error and empty fallback models.
|
||||
if (IS_VALID_DATACACHE_HANDLE(modelCache))
|
||||
if (IsValidDataCacheHandle(modelCache))
|
||||
{
|
||||
studiohdr_t* const studioHdr = studioData->GetModelCache()->GetStudioHdr();
|
||||
|
||||
@ -67,7 +66,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle
|
||||
|
||||
if ((studioData->flags & nFlags))
|
||||
{
|
||||
if (IS_VALID_DATACACHE_HANDLE(modelCache))
|
||||
if (IsValidDataCacheHandle(modelCache))
|
||||
{
|
||||
if (a3)
|
||||
{
|
||||
@ -85,7 +84,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle
|
||||
|
||||
studioanimcache_t* const animCache = studioData->GetAnimCache();
|
||||
|
||||
if (IS_VALID_DATACACHE_HANDLE(animCache))
|
||||
if (IsValidDataCacheHandle(animCache))
|
||||
{
|
||||
studiohdr_t* const pStudioHdr = animCache->GetStudioHdr();
|
||||
|
||||
@ -158,7 +157,7 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* const cache, const MDLHandle_
|
||||
|
||||
studiomodelcache_t* const modelCache = pStudioData->GetModelCache();
|
||||
|
||||
if (IS_VALID_DATACACHE_HANDLE(modelCache))
|
||||
if (IsValidDataCacheHandle(modelCache))
|
||||
{
|
||||
FindCachedMDL(cache, pStudioData, a4);
|
||||
studioHdr = modelCache->GetStudioHdr();
|
||||
@ -168,7 +167,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 (IS_VALID_DATACACHE_HANDLE(animCache))
|
||||
if (IsValidDataCacheHandle(animCache))
|
||||
{
|
||||
studioHdr = animCache->GetStudioHdr();
|
||||
}
|
||||
@ -219,7 +218,7 @@ vcollide_t* CMDLCache::GetVCollide(CMDLCache* const cache, const MDLHandle_t han
|
||||
{
|
||||
studiomodelcache_t* const modelCache = cache->GetModelCache(handle);
|
||||
|
||||
if (!IS_VALID_DATACACHE_HANDLE(modelCache))
|
||||
if (!IsValidDataCacheHandle(modelCache))
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "Attempted to load collision data on model \"%s\" with invalid studio data!\n", cache->GetModelName(handle));
|
||||
return nullptr;
|
||||
@ -248,7 +247,7 @@ void* CMDLCache::GetPhysicsGeometry(CMDLCache* const cache, const MDLHandle_t ha
|
||||
{
|
||||
studiomodelcache_t* const modelCache = cache->GetModelCache(handle);
|
||||
|
||||
if (!IS_VALID_DATACACHE_HANDLE(modelCache))
|
||||
if (!IsValidDataCacheHandle(modelCache))
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "Attempted to load physics geometry on model \"%s\" with invalid studio data!\n", cache->GetModelName(handle));
|
||||
return nullptr;
|
||||
@ -278,7 +277,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 (!IS_VALID_DATACACHE_HANDLE(modelCache))
|
||||
if (!IsValidDataCacheHandle(modelCache))
|
||||
{
|
||||
if (!HasErrorModel())
|
||||
{
|
||||
|
@ -138,6 +138,7 @@ 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" )
|
||||
@ -161,6 +162,8 @@ 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"
|
||||
@ -226,6 +229,8 @@ 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"
|
||||
|
@ -6,12 +6,27 @@
|
||||
//=============================================================================//
|
||||
#include "core/stdafx.h"
|
||||
#include "public/const.h"
|
||||
#include "engine/host.h"
|
||||
#include "engine/client/cl_ents_parse.h"
|
||||
|
||||
bool 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)
|
||||
{
|
||||
int nNewEntity = *reinterpret_cast<int*>(a1 + 40);
|
||||
if (nNewEntity >= MAX_EDICTS || nNewEntity < NULL)
|
||||
// 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)
|
||||
{
|
||||
// Value isn't sanitized in release builds for
|
||||
// every game powered by the Source Engine 1
|
||||
@ -20,7 +35,11 @@ bool CL_CopyExistingEntity(__int64 a1, unsigned int* a2, char* a3)
|
||||
// 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(a1, a2, a3);
|
||||
|
||||
return v_CL_CopyExistingEntity(u, iClass, pbError);
|
||||
}
|
||||
|
@ -1,24 +1,30 @@
|
||||
#ifndef CL_ENTS_PARSE_H
|
||||
#define CL_ENTS_PARSE_H
|
||||
#include "engine/shared/ents_shared.h"
|
||||
|
||||
inline bool(*v_CL_CopyExistingEntity)(__int64 a1, unsigned int* a2, char* a3);
|
||||
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);
|
||||
|
||||
bool 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);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
@ -73,7 +73,7 @@ void CRConClient::RunFrame(void)
|
||||
{
|
||||
if (IsInitialized() && IsConnected())
|
||||
{
|
||||
CConnectedNetConsoleData* pData = GetData();
|
||||
ConnectedNetConsoleData_s* pData = GetData();
|
||||
Assert(pData != nullptr);
|
||||
|
||||
if (pData)
|
||||
@ -105,7 +105,7 @@ void CRConClient::Disconnect(const char* szReason)
|
||||
// Input : *pMsgBug -
|
||||
// nMsgLen -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRConClient::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
|
||||
bool CRConClient::ProcessMessage(const byte* const pMsgBuf, const u32 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* szEnable = bWantLog ? "1" : "0";
|
||||
const char* const szEnable = bWantLog ? "1" : "0";
|
||||
const SocketHandle_t hSocket = GetSocket();
|
||||
|
||||
vector<char> vecMsg;
|
||||
bool ret = Serialize(vecMsg, "", szEnable, netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
||||
vector<byte> vecMsg;
|
||||
const bool ret = Serialize(vecMsg, "", 0, szEnable, 1, netcon::request_e::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
||||
|
||||
if (ret && !Send(hSocket, vecMsg.data(), int(vecMsg.size())))
|
||||
if (ret && !Send(hSocket, vecMsg.data(), (u32)vecMsg.size()))
|
||||
{
|
||||
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||
}
|
||||
@ -177,14 +177,16 @@ 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<char>& vecBuf, const char* szReqBuf,
|
||||
const char* szReqVal, const netcon::request_e requestType) const
|
||||
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
|
||||
{
|
||||
return NetconClient_Serialize(this, vecBuf, szReqBuf, szReqVal, requestType,
|
||||
return NetconClient_Serialize(this, vecBuf, szReqBuf, nReqMsgLen, szReqVal, nReqValLen, requestType,
|
||||
rcon_encryptframes.GetBool(), rcon_debug.GetBool());
|
||||
}
|
||||
|
||||
@ -192,7 +194,7 @@ bool CRConClient::Serialize(vector<char>& vecBuf, const char* szReqBuf,
|
||||
// Purpose: retrieves the remote socket
|
||||
// Output : SOCKET_ERROR (-1) on failure
|
||||
//-----------------------------------------------------------------------------
|
||||
CConnectedNetConsoleData* CRConClient::GetData(void)
|
||||
ConnectedNetConsoleData_s* CRConClient::GetData(void)
|
||||
{
|
||||
return NetconShared_GetConnData(this, 0);
|
||||
}
|
||||
@ -321,7 +323,7 @@ static void RCON_CmdQuery_f(const CCommand& args)
|
||||
}
|
||||
else if (RCONClient()->IsConnected())
|
||||
{
|
||||
vector<char> vecMsg;
|
||||
vector<byte> vecMsg;
|
||||
bool bSuccess = false;
|
||||
const SocketHandle_t hSocket = RCONClient()->GetSocket();
|
||||
|
||||
@ -329,7 +331,10 @@ static void RCON_CmdQuery_f(const CCommand& args)
|
||||
{
|
||||
if (argCount > 2)
|
||||
{
|
||||
bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", netcon::request_e::SERVERDATA_REQUEST_AUTH);
|
||||
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);
|
||||
}
|
||||
else // Need at least 3 arguments for a password in PASS command (rcon PASS <password>)
|
||||
{
|
||||
@ -339,7 +344,7 @@ static void RCON_CmdQuery_f(const CCommand& args)
|
||||
|
||||
if (bSuccess)
|
||||
{
|
||||
RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size()));
|
||||
RCONClient()->Send(hSocket, vecMsg.data(), (u32)vecMsg.size());
|
||||
}
|
||||
|
||||
return;
|
||||
@ -350,10 +355,16 @@ static void RCON_CmdQuery_f(const CCommand& args)
|
||||
return;
|
||||
}
|
||||
|
||||
bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(1), args.ArgS(), netcon::request_e::SERVERDATA_REQUEST_EXECCOMMAND);
|
||||
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);
|
||||
if (bSuccess)
|
||||
{
|
||||
RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size()));
|
||||
RCONClient()->Send(hSocket, vecMsg.data(), (u32)vecMsg.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ public:
|
||||
void RunFrame(void);
|
||||
|
||||
virtual void Disconnect(const char* szReason = nullptr) override;
|
||||
virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override;
|
||||
virtual bool ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen) override;
|
||||
|
||||
bool Serialize(vector<char>& vecBuf, const char* szReqBuf,
|
||||
const char* szReqVal, const netcon::request_e requestType) const;
|
||||
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;
|
||||
|
||||
void RequestConsoleLog(const bool bWantLog);
|
||||
bool ShouldReceive(void);
|
||||
@ -27,7 +27,7 @@ public:
|
||||
bool IsInitialized(void) const;
|
||||
bool IsConnected(void);
|
||||
|
||||
CConnectedNetConsoleData* GetData(void);
|
||||
ConnectedNetConsoleData_s* GetData(void);
|
||||
SocketHandle_t GetSocket(void);
|
||||
|
||||
private:
|
||||
|
@ -75,7 +75,7 @@ static ConVar sv_onlineAuthValidateIssuedAt("sv_onlineAuthValidateIssuedAt", "1"
|
||||
static ConVar sv_onlineAuthExpiryTolerance("sv_onlineAuthExpiryTolerance", "1", FCVAR_DEVELOPMENTONLY, "The online authentication token 'expiry' claim tolerance in seconds", true, 0.f, true, float(UINT8_MAX), "Must range between [0,255]");
|
||||
static ConVar sv_onlineAuthIssuedAtTolerance("sv_onlineAuthIssuedAtTolerance", "30", FCVAR_DEVELOPMENTONLY, "The online authentication token 'issued at' claim tolerance in seconds", true, 0.f, true, float(UINT8_MAX), "Must range between [0,255]");
|
||||
|
||||
static ConVar sv_quota_stringCmdsPerSecond("sv_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands", true, 0.f, false, 0.f);
|
||||
static ConVar sv_quota_stringCmdsPerSecond("sv_quota_stringCmdsPerSecond", "32", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands", true, 0.f, false, 0.f);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Purpose: check whether this client is authorized to join this server
|
||||
|
@ -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.
|
||||
memset(g_PersonaName, '\0', MAX_PERSONA_NAME_LEN);
|
||||
strncpy(g_PersonaName, pszName, nLen);
|
||||
strncpy(g_PersonaName, pszName, nLen+1);
|
||||
name_cvar->SetValue(pszName);
|
||||
}
|
||||
static void Reconnect_f(const CCommand& args)
|
||||
{
|
||||
@ -234,6 +234,7 @@ 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
|
||||
)
|
||||
|
@ -158,5 +158,5 @@ static bool HK_ProcessDataBlock(ClientDataBlockReceiver* receiver, const double
|
||||
|
||||
void VClientDataBlockReceiver::Detour(const bool bAttach) const
|
||||
{
|
||||
DetourAttach(&ClientDataBlockReceiver__ProcessDataBlock, HK_ProcessDataBlock);
|
||||
DetourSetup(&ClientDataBlockReceiver__ProcessDataBlock, HK_ProcessDataBlock, bAttach);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ bool Cbuf_AddTextWithMarkers(const char* const pText, const ECmdExecutionMarker
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef DEDICATED
|
||||
ConVar cl_quota_stringCmdsPerSecond("cl_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second user is allowed to submit, 0 to allow all submissions.", true, 0.f, false, 0.f);
|
||||
ConVar cl_quota_stringCmdsPerSecond("cl_quota_stringCmdsPerSecond", "32", FCVAR_RELEASE, "How many string commands per second user is allowed to submit, 0 to allow all submissions.", true, 0.f, false, 0.f);
|
||||
#endif // DEDICATED
|
||||
|
||||
bool Cmd_ForwardToServer(const CCommand* args)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#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"
|
||||
@ -30,23 +31,23 @@
|
||||
CUtlVector<CUtlString> g_InstalledMaps;
|
||||
CFmtStrN<MAX_MAP_NAME> s_CurrentLevelName;
|
||||
|
||||
static CustomPakData_t s_customPakData;
|
||||
static CustomPakData_s s_customPakData;
|
||||
static KeyValues* s_pLevelSetKV = nullptr;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: load a custom pak and add it to the list
|
||||
//-----------------------------------------------------------------------------
|
||||
PakHandle_t CustomPakData_t::LoadAndAddPak(const char* const pakFile)
|
||||
PakHandle_t CustomPakData_s::LoadAndAddPak(const char* const pakFile)
|
||||
{
|
||||
if (numHandles >= MAX_CUSTOM_PAKS)
|
||||
{
|
||||
Error(eDLL_T::ENGINE, NO_ERROR, "Tried to load pak '%s', but already reached the SDK's limit of %d!\n", pakFile, MAX_CUSTOM_PAKS);
|
||||
Error(eDLL_T::ENGINE, NO_ERROR, "Tried to load pak '%s', but already reached the 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 and return the invalid handle.
|
||||
// failure, don't add; return the invalid handle.
|
||||
if (pakId == PAK_INVALID_HANDLE)
|
||||
return pakId;
|
||||
|
||||
@ -55,30 +56,72 @@ PakHandle_t CustomPakData_t::LoadAndAddPak(const char* const pakFile)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: unloads all active custom pak handles
|
||||
// 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!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CustomPakData_t::UnloadAndRemoveAll()
|
||||
void CustomPakData_s::UnloadAndRemovePak(const int index)
|
||||
{
|
||||
// Base SDK paks should not be unloaded here, but only right before base
|
||||
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 /
|
||||
// engine paks are unloaded. Only unload user requested and level settings
|
||||
// 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++)
|
||||
// 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--)
|
||||
{
|
||||
const PakHandle_t pakId = handles[i];
|
||||
assert(pakId != PAK_INVALID_HANDLE); // invalid handles should not be inserted
|
||||
UnloadAndRemovePak(n);
|
||||
}
|
||||
}
|
||||
|
||||
g_pakLoadApi->UnloadAsync(pakId);
|
||||
handles[i] = PAK_INVALID_HANDLE;
|
||||
|
||||
numHandles--;
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: loads the base SDK pak file by type
|
||||
//-----------------------------------------------------------------------------
|
||||
PakHandle_t CustomPakData_t::LoadBasePak(const char* const pakFile, const EPakType type)
|
||||
PakHandle_t CustomPakData_s::LoadBasePak(const char* const pakFile, const PakType_e type)
|
||||
{
|
||||
const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0);
|
||||
|
||||
@ -92,7 +135,7 @@ PakHandle_t CustomPakData_t::LoadBasePak(const char* const pakFile, const EPakTy
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: unload the SDK base pak file by type
|
||||
//-----------------------------------------------------------------------------
|
||||
void CustomPakData_t::UnloadBasePak(const EPakType type)
|
||||
void CustomPakData_s::UnloadBasePak(const PakType_e type)
|
||||
{
|
||||
const PakHandle_t pakId = handles[type];
|
||||
|
||||
@ -163,10 +206,71 @@ 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
|
||||
//-----------------------------------------------------------------------------
|
||||
void Mod_QueuedPakCacheFrame()
|
||||
static void Mod_QueuedPakCacheFrame()
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
bool bUnconnected = !(*g_pClientState_Shifted)->IsConnected();
|
||||
@ -228,11 +332,11 @@ void Mod_QueuedPakCacheFrame()
|
||||
|
||||
const int numToProcess = startIndex;
|
||||
|
||||
if (startIndex <= CommonPakData_t::PAK_TYPE_LEVEL)
|
||||
if (startIndex < CommonPakData_s::PAK_TYPE_COUNT)
|
||||
{
|
||||
bool keepLoaded = false;
|
||||
int numLeftToProcess = 4;
|
||||
CommonPakData_t* data = &g_commonPakData[4];
|
||||
CommonPakData_s* data = &g_commonPakData[4];
|
||||
|
||||
do
|
||||
{
|
||||
@ -261,32 +365,26 @@ void Mod_QueuedPakCacheFrame()
|
||||
switch (numLeftToProcess)
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
case CommonPakData_t::PAK_TYPE_UI_GM:
|
||||
s_customPakData.UnloadBasePak(CustomPakData_t::PAK_TYPE_UI_SDK);
|
||||
case CommonPakData_s::PakType_e::PAK_TYPE_UI_GM:
|
||||
s_customPakData.UnloadBasePak(CustomPakData_s::PakType_e::PAK_TYPE_UI_SDK);
|
||||
break;
|
||||
#endif // !DEDICATED
|
||||
|
||||
case CommonPakData_t::PAK_TYPE_COMMON:
|
||||
case CommonPakData_s::PakType_e::PAK_TYPE_COMMON:
|
||||
g_StudioMdlFallbackHandler.Clear();
|
||||
break;
|
||||
|
||||
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;
|
||||
case CommonPakData_s::PakType_e::PAK_TYPE_COMMON_GM:
|
||||
s_customPakData.UnloadBasePak(CustomPakData_s::PakType_e::PAK_TYPE_COMMON_SDK);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_pakLoadApi->UnloadAsync(data->pakId);
|
||||
|
||||
if (numLeftToProcess == CommonPakData_t::PAK_TYPE_LEVEL)
|
||||
if (numLeftToProcess == CommonPakData_s::PakType_e::PAK_TYPE_LEVEL)
|
||||
{
|
||||
Mod_UnloadPakFile(); // Unload mod pak files.
|
||||
Mod_UnloadLevelPaks(); // Unload mod pak files.
|
||||
|
||||
if (s_pLevelSetKV)
|
||||
{
|
||||
@ -295,6 +393,14 @@ 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)
|
||||
@ -311,7 +417,7 @@ void Mod_QueuedPakCacheFrame()
|
||||
}
|
||||
|
||||
*g_pPakPrecacheJobFinished = true;
|
||||
CommonPakData_t* commonData = g_commonPakData;
|
||||
CommonPakData_s* commonData = g_commonPakData;
|
||||
|
||||
int it = 0;
|
||||
|
||||
@ -335,7 +441,7 @@ void Mod_QueuedPakCacheFrame()
|
||||
} while (c);
|
||||
|
||||
if (!v20)
|
||||
goto CHECK_FOR_FAILURE;
|
||||
goto CHECK_LOAD_STATUS;
|
||||
|
||||
V_strncpy(name, commonData->basePakName, MAX_PATH);
|
||||
|
||||
@ -370,9 +476,9 @@ void Mod_QueuedPakCacheFrame()
|
||||
|
||||
if (ThreadInMainThread())
|
||||
{
|
||||
if (*g_bPakFifoLockAcquired)
|
||||
if (*g_bPakFifoLockAcquiredInMainThread)
|
||||
{
|
||||
*g_bPakFifoLockAcquired = 0;
|
||||
*g_bPakFifoLockAcquiredInMainThread = false;
|
||||
JT_ReleaseFifoLock(pakFifoLock);
|
||||
}
|
||||
}
|
||||
@ -391,38 +497,85 @@ void Mod_QueuedPakCacheFrame()
|
||||
}
|
||||
}
|
||||
|
||||
if (it == CommonPakData_t::PAK_TYPE_LOBBY)
|
||||
s_customPakData.basePaksLoaded = true;
|
||||
|
||||
if (s_customPakData.basePaksLoaded && !s_customPakData.levelResourcesLoaded)
|
||||
if (it == CommonPakData_s::PakType_e::PAK_TYPE_LOBBY)
|
||||
{
|
||||
Mod_PreloadLevelPaks(s_CurrentLevelName.String());
|
||||
s_customPakData.levelResourcesLoaded = true;
|
||||
Mod_PreloadPaks();
|
||||
s_customPakData.basePaksLoaded = true;
|
||||
}
|
||||
|
||||
commonData->pakId = g_pakLoadApi->LoadAsync(name, AlignedMemAlloc(), 4, 0);
|
||||
|
||||
#ifndef DEDICATED
|
||||
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_t::PAK_TYPE_COMMON_GM)
|
||||
s_customPakData.LoadBasePak("common_sdk.rpak", CustomPakData_t::PAK_TYPE_COMMON_SDK);
|
||||
|
||||
CHECK_FOR_FAILURE:
|
||||
|
||||
if (commonData->pakId != PAK_INVALID_HANDLE)
|
||||
if (it == CommonPakData_s::PakType_e::PAK_TYPE_LEVEL)
|
||||
{
|
||||
const PakLoadedInfo_s* const pli = Pak_GetPakInfo(commonData->pakId);
|
||||
Mod_LoadLevelPaks(s_CurrentLevelName.String());
|
||||
s_customPakData.levelResourcesLoaded = true;
|
||||
}
|
||||
|
||||
if (pli->handle != commonData->pakId || ((pli->status - 9) & 0xFFFFFFFB) != 0)
|
||||
#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
|
||||
#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);
|
||||
|
||||
CHECK_LOAD_STATUS:
|
||||
|
||||
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 (parseFailure)
|
||||
Error(eDLL_T::ENGINE, EXIT_FAILURE, "%s: failure parsing file '%s'\n", __FUNCTION__, preloadFile);
|
||||
else
|
||||
{
|
||||
*g_pPakPrecacheJobFinished = false;
|
||||
return;
|
||||
Warning(eDLL_T::ENGINE, "%s: could not load file '%s'\n", __FUNCTION__, preloadFile);
|
||||
return; // No preload file, thus no error. Warn and return out.
|
||||
}
|
||||
}
|
||||
|
||||
goto LOOP_AGAIN_OR_FINISH;
|
||||
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();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -467,10 +620,10 @@ KeyValues* Mod_GetLevelSettings(const char* const pszLevelName)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: loads required pakfile assets for specified BSP level
|
||||
// Input : &svSetFile -
|
||||
// Purpose: loads paks specified inside the level settings file
|
||||
// Input : *pszLevelName -
|
||||
//-----------------------------------------------------------------------------
|
||||
void Mod_PreloadLevelPaks(const char* const pszLevelName)
|
||||
void Mod_LoadLevelPaks(const char* const pszLevelName)
|
||||
{
|
||||
KeyValues* const pSettingsKV = Mod_GetLevelSettings(pszLevelName);
|
||||
|
||||
@ -498,11 +651,11 @@ void Mod_PreloadLevelPaks(const char* const pszLevelName)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: unloads all pakfiles loaded by the SDK
|
||||
// Purpose: unloads all paks loaded by the level settings file
|
||||
//-----------------------------------------------------------------------------
|
||||
void Mod_UnloadPakFile(void)
|
||||
void Mod_UnloadLevelPaks()
|
||||
{
|
||||
s_customPakData.UnloadAndRemoveAll();
|
||||
s_customPakData.UnloadAndRemoveNonPreloaded();
|
||||
|
||||
g_StudioMdlFallbackHandler.ClearBadModelHandleCache();
|
||||
g_StudioMdlFallbackHandler.ClearSuppresionList();
|
||||
|
@ -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_t
|
||||
struct CommonPakData_s
|
||||
{
|
||||
enum EPakType
|
||||
enum PakType_e
|
||||
{
|
||||
// the UI pak assigned to the current gamemode (range in GameMode_t)
|
||||
PAK_TYPE_UI_GM = 0,
|
||||
@ -32,7 +32,7 @@ struct CommonPakData_t
|
||||
PAK_TYPE_COUNT
|
||||
};
|
||||
|
||||
CommonPakData_t()
|
||||
CommonPakData_s()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
@ -62,9 +62,9 @@ struct CommonPakData_t
|
||||
// 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_t
|
||||
struct CustomPakData_s
|
||||
{
|
||||
enum EPakType
|
||||
enum PakType_e
|
||||
{
|
||||
// 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_t
|
||||
// the absolute max number of custom paks, note that the engine's limit
|
||||
// could still be reached before this number as game scripts and other
|
||||
// code still loads paks such as gladiator cards or load screens
|
||||
MAX_CUSTOM_PAKS = (PAK_MAX_LOADED_PAKS - CommonPakData_t::PAK_TYPE_COUNT)
|
||||
MAX_CUSTOM_PAKS = (PAK_MAX_LOADED_PAKS - CommonPakData_s::PAK_TYPE_COUNT)
|
||||
};
|
||||
|
||||
CustomPakData_t()
|
||||
CustomPakData_s()
|
||||
{
|
||||
for (size_t i = 0; i < V_ARRAYSIZE(handles); i++)
|
||||
{
|
||||
@ -95,30 +95,40 @@ struct CustomPakData_t
|
||||
|
||||
// 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);
|
||||
void UnloadAndRemoveAll();
|
||||
PakHandle_t PreloadAndAddPak(const char* const pakFile);
|
||||
|
||||
PakHandle_t LoadBasePak(const char* const pakFile, const EPakType type);
|
||||
void UnloadBasePak(const EPakType type);
|
||||
void UnloadAndRemoveNonPreloaded();
|
||||
void UnloadAndRemovePreloaded();
|
||||
|
||||
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];
|
||||
size_t numHandles;
|
||||
|
||||
int numHandles;
|
||||
int numPreload;
|
||||
|
||||
bool levelResourcesLoaded;
|
||||
bool basePaksLoaded;
|
||||
};
|
||||
|
||||
// array size = CommonPakData_t::PAK_TYPE_COUNT
|
||||
inline CommonPakData_t* g_commonPakData;
|
||||
inline CommonPakData_s* g_commonPakData;
|
||||
|
||||
inline void(*v_Mod_LoadPakForMap)(const char* szLevelName);
|
||||
inline void(*v_Mod_QueuedPakCacheFrame)(void);
|
||||
@ -131,11 +141,14 @@ 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_PreloadLevelPaks(const char* pszLevelName);
|
||||
void Mod_UnloadPakFile(void);
|
||||
void Mod_LoadLevelPaks(const char* pszLevelName);
|
||||
void Mod_UnloadLevelPaks(void);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -78,7 +78,7 @@ void _Host_RunFrame(void* unused, float time)
|
||||
return v_Host_RunFrame(unused, time);
|
||||
}
|
||||
|
||||
void _Host_Error(const char* error, ...)
|
||||
void Host_Error(const char* const 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
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ 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:
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "core/stdafx.h"
|
||||
#include "tier0/commandline.h"
|
||||
#include "rtech/pak/pakstate.h"
|
||||
#include "host_cmd.h"
|
||||
#include "common.h"
|
||||
#include "client/client.h"
|
||||
@ -7,6 +8,60 @@
|
||||
#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
|
||||
@ -15,7 +70,7 @@ Host_Shutdown
|
||||
systems
|
||||
==================
|
||||
*/
|
||||
void Host_Shutdown()
|
||||
static void Host_Shutdown()
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
DirectX_Shutdown();
|
||||
@ -31,7 +86,7 @@ Host_Status_PrintClient
|
||||
to console
|
||||
==================
|
||||
*/
|
||||
void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (const char* fmt, ...))
|
||||
static void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (const char* fmt, ...))
|
||||
{
|
||||
CNetChan* nci = client->GetNetChan();
|
||||
const char* state = "challenging";
|
||||
@ -45,7 +100,7 @@ void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (
|
||||
|
||||
if (nci != NULL)
|
||||
{
|
||||
print("# %i \"%s\" %llu %s %i %i %s %d\n",
|
||||
print("# %hu \"%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());
|
||||
|
||||
@ -56,7 +111,7 @@ void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (
|
||||
}
|
||||
else
|
||||
{
|
||||
print("#%2i \"%s\" %llu %s\n", client->GetHandle(), client->GetServerName(), client->GetNucleusID(), state);
|
||||
print("#%2hu \"%s\" %llu %s\n", client->GetHandle(), client->GetServerName(), client->GetNucleusID(), state);
|
||||
}
|
||||
|
||||
//print("\n");
|
||||
@ -70,7 +125,7 @@ DFS_InitializeFeatureFlagDefinitions
|
||||
flag definitions
|
||||
==================
|
||||
*/
|
||||
bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags)
|
||||
static bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags)
|
||||
{
|
||||
if (CommandLine()->CheckParm("-nodfs"))
|
||||
return false;
|
||||
@ -81,6 +136,7 @@ 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);
|
||||
|
@ -19,8 +19,11 @@ 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);
|
||||
@ -38,8 +41,11 @@ 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);
|
||||
@ -53,11 +59,14 @@ 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);
|
||||
|
||||
|
@ -63,8 +63,9 @@ 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.
|
||||
@ -120,8 +121,8 @@ static void HostState_KeepAlive()
|
||||
{
|
||||
g_ServerHostManager.SetCurrentToken(hostToken);
|
||||
Msg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
|
||||
g_svReset, g_svGreyB,
|
||||
hostToken.c_str(), g_svReset);
|
||||
g_svReset.c_str(), g_svGreyB.c_str(),
|
||||
hostToken.c_str(), g_svReset.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +424,12 @@ void CHostState::LoadConfig(void) const
|
||||
}
|
||||
if (CommandLine()->CheckParm("-offline"))
|
||||
{
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec system/autoexec_offline.cfg\n", cmd_source_t::kCommandSrcCode);
|
||||
#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
|
||||
}
|
||||
#ifndef CLIENT_DLL
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec liveapi.cfg\n", cmd_source_t::kCommandSrcCode);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
extern ConVar hostdesc;
|
||||
|
||||
enum class HostStates_t : int
|
||||
{
|
||||
HS_NEW_GAME = 0x0,
|
||||
|
@ -181,7 +181,7 @@ void NET_Config()
|
||||
void NET_PrintKey()
|
||||
{
|
||||
Msg(eDLL_T::ENGINE, "Installed NetKey: %s'%s%s%s'\n",
|
||||
g_svReset, g_svGreyB, g_pNetKey->GetBase64NetKey(), g_svReset);
|
||||
g_svReset.c_str(), g_svGreyB.c_str(), g_pNetKey->GetBase64NetKey(), g_svReset.c_str());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -247,12 +247,7 @@ void NET_PrintFunc(const char* fmt, ...)
|
||||
result = FormatV(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (result.back() != '\n')
|
||||
{
|
||||
result.push_back('\n');
|
||||
}
|
||||
|
||||
Msg(context, "%s", result.c_str());
|
||||
Msg(context, result.back() == '\n' ? "%s" : "%s\n", result.c_str());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -388,7 +383,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_EUNKOWNPSOBJ";
|
||||
case WSA_QOS_EUNKOWNPSOBJ : return "WSA_QOS_EUNKNOWNPSOBJ";
|
||||
case WSA_QOS_EPOLICYOBJ : return "WSA_QOS_EPOLICYOBJ";
|
||||
case WSA_QOS_EFLOWDESC : return "WSA_QOS_EFLOWDESC";
|
||||
case WSA_QOS_EPSFLOWSPEC : return "WSA_QOS_EPSFLOWSPEC";
|
||||
|
@ -47,9 +47,7 @@ int CServer::GetNumHumanPlayers(void) const
|
||||
int nHumans = 0;
|
||||
for (int i = 0; i < gpGlobals->maxClients; i++)
|
||||
{
|
||||
CClient* pClient = g_pServer->GetClient(i);
|
||||
if (!pClient)
|
||||
continue;
|
||||
const CClient* const pClient = g_pServer->GetClient(i);
|
||||
|
||||
if (pClient->IsHumanPlayer())
|
||||
nHumans++;
|
||||
@ -67,9 +65,7 @@ int CServer::GetNumFakeClients(void) const
|
||||
int nBots = 0;
|
||||
for (int i = 0; i < gpGlobals->maxClients; i++)
|
||||
{
|
||||
CClient* pClient = g_pServer->GetClient(i);
|
||||
if (!pClient)
|
||||
continue;
|
||||
const CClient* const pClient = g_pServer->GetClient(i);
|
||||
|
||||
if (pClient->IsConnected() && pClient->IsFakeClient())
|
||||
nBots++;
|
||||
@ -87,9 +83,7 @@ int CServer::GetNumClients(void) const
|
||||
int nClients = 0;
|
||||
for (int i = 0; i < gpGlobals->maxClients; i++)
|
||||
{
|
||||
CClient* pClient = g_pServer->GetClient(i);
|
||||
if (!pClient)
|
||||
continue;
|
||||
const CClient* const pClient = g_pServer->GetClient(i);
|
||||
|
||||
if (pClient->IsConnected())
|
||||
nClients++;
|
||||
@ -122,7 +116,7 @@ CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge)
|
||||
return nullptr;
|
||||
|
||||
char* pszPersonaName = pChallenge->personaName;
|
||||
uint64_t nNucleusID = pChallenge->personaId;
|
||||
NucleusID_t nNucleusID = pChallenge->personaId;
|
||||
|
||||
char pszAddresBuffer[128]; // Render the client's address.
|
||||
pChallenge->netAdr.ToString(pszAddresBuffer, sizeof(pszAddresBuffer), true);
|
||||
|
@ -23,7 +23,7 @@ struct user_creds_s
|
||||
int32_t protocolVer;
|
||||
int32_t challenge;
|
||||
uint32_t reservation;
|
||||
uint64_t personaId;
|
||||
NucleusID_t personaId;
|
||||
char* personaName;
|
||||
};
|
||||
|
||||
|
@ -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, svError.c_str());
|
||||
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "%s", 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);
|
||||
}
|
||||
@ -79,10 +79,6 @@ void SV_CheckClientsForBan(const CBanSystem::BannedList_t* const pBannedVec /*=
|
||||
for (int c = 0; c < gpGlobals->maxClients; c++) // Loop through all possible client instances.
|
||||
{
|
||||
CClient* const pClient = g_pServer->GetClient(c);
|
||||
|
||||
if (!pClient)
|
||||
continue;
|
||||
|
||||
const CNetChan* const pNetChan = pClient->GetNetChan();
|
||||
|
||||
if (!pNetChan)
|
||||
@ -199,9 +195,6 @@ void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data
|
||||
{
|
||||
CClient* const pClient = g_pServer->GetClient(i);
|
||||
|
||||
if (!pClient)
|
||||
continue;
|
||||
|
||||
// is this client fully connected
|
||||
if (pClient->GetSignonState() != SIGNONSTATE::SIGNONSTATE_FULL)
|
||||
continue;
|
||||
@ -246,9 +239,6 @@ void SV_BroadcastDurangoVoiceData(CClient* const cl, const int nBytes, char* con
|
||||
{
|
||||
CClient* const pClient = g_pServer->GetClient(i);
|
||||
|
||||
if (!pClient)
|
||||
continue;
|
||||
|
||||
// is this client fully connected
|
||||
if (pClient->GetSignonState() != SIGNONSTATE::SIGNONSTATE_FULL)
|
||||
continue;
|
||||
|
@ -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, false, 0.f);
|
||||
static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, true, 4096.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, g_svGreyB, GetKey(), g_svReset);
|
||||
m_Address.ToString(), g_svReset.c_str(), g_svGreyB.c_str(), GetKey(), g_svReset.c_str());
|
||||
|
||||
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 CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||
const ConnectedNetConsoleData_s& 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--)
|
||||
{
|
||||
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||
|
||||
if (CheckForBan(data))
|
||||
{
|
||||
SendEncoded(data.m_hSocket, s_BannedMessage, "",
|
||||
SendEncoded(data.m_hSocket, s_BannedMessage, sizeof(s_BannedMessage)-1, "", 0,
|
||||
netcon::response_e::SERVERDATA_RESPONSE_AUTH, int(eDLL_T::NETCON));
|
||||
|
||||
Disconnect("banned");
|
||||
@ -270,25 +270,18 @@ void CRConServer::RunFrame(void)
|
||||
// nMsgLen -
|
||||
// Output: true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRConServer::SendToAll(const char* pMsgBuf, const int nMsgLen) const
|
||||
bool CRConServer::SendToAll(const byte* pMsgBuf, const u32 nMsgLen) const
|
||||
{
|
||||
ostringstream sendbuf;
|
||||
const u_long nLen = htonl(u_long(nMsgLen));
|
||||
|
||||
const int nCount = m_Socket.GetAcceptedSocketCount();
|
||||
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 CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(i);
|
||||
const ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(i);
|
||||
|
||||
if (data.m_bAuthorized && !data.m_bInputOnly)
|
||||
{
|
||||
int ret = ::send(data.m_hSocket, sendbuf.str().data(),
|
||||
int(sendbuf.str().size()), MSG_NOSIGNAL);
|
||||
const int ret = ::send(data.m_hSocket, (const char*)pMsgBuf, (i32)nMsgLen, MSG_NOSIGNAL);
|
||||
|
||||
if (ret == SOCKET_ERROR)
|
||||
{
|
||||
@ -306,17 +299,19 @@ bool CRConServer::SendToAll(const char* pMsgBuf, const int 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 char* pResponseVal,
|
||||
bool CRConServer::SendEncoded(const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
|
||||
const netcon::response_e responseType, const int nMessageId, const int nMessageType) const
|
||||
{
|
||||
vector<char> vecMsg;
|
||||
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
|
||||
vector<byte> vecMsg;
|
||||
if (!Serialize(vecMsg, pResponseMsg, nResponseMsgLen, pResponseVal, nResponseValLen,
|
||||
responseType, nMessageId, nMessageType))
|
||||
{
|
||||
return false;
|
||||
@ -334,17 +329,20 @@ bool CRConServer::SendEncoded(const char* pResponseMsg, const char* pResponseVal
|
||||
// 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 char* pResponseVal,
|
||||
bool CRConServer::SendEncoded(const SocketHandle_t hSocket,
|
||||
const char* pResponseMsg, const size_t nResponseMsgLen, const char* pResponseVal, const size_t nResponseValLen,
|
||||
const netcon::response_e responseType, const int nMessageId, const int nMessageType) const
|
||||
{
|
||||
vector<char> vecMsg;
|
||||
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
|
||||
vector<byte> vecMsg;
|
||||
if (!Serialize(vecMsg, pResponseMsg, nResponseMsgLen, pResponseVal, nResponseValLen,
|
||||
responseType, nMessageId, nMessageType))
|
||||
{
|
||||
return false;
|
||||
@ -362,16 +360,19 @@ bool CRConServer::SendEncoded(const SocketHandle_t hSocket, const char* pRespons
|
||||
// Purpose: serializes input
|
||||
// Input : &vecBuf -
|
||||
// *responseMsg -
|
||||
// nResponseMsgLen -
|
||||
// *responseVal -
|
||||
// nResponseValLen -
|
||||
// responseType -
|
||||
// nMessageId -
|
||||
// nMessageType -
|
||||
// Output : serialized results as string
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRConServer::Serialize(vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal,
|
||||
bool CRConServer::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, const int nMessageType) const
|
||||
{
|
||||
return NetconServer_Serialize(this, vecBuf, pResponseMsg, pResponseVal, responseType, nMessageId, nMessageType,
|
||||
return NetconServer_Serialize(this, vecBuf, pResponseMsg, nResponseMsgLen, pResponseVal, nResponseValLen, responseType, nMessageId, nMessageType,
|
||||
rcon_encryptframes.GetBool(), rcon_debug.GetBool());
|
||||
}
|
||||
|
||||
@ -380,7 +381,7 @@ bool CRConServer::Serialize(vector<char>& vecBuf, const char* pResponseMsg, cons
|
||||
// Input : &request -
|
||||
// &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRConServer::Authenticate(const netcon::request& request, CConnectedNetConsoleData& data)
|
||||
void CRConServer::Authenticate(const netcon::request& request, ConnectedNetConsoleData_s& data)
|
||||
{
|
||||
if (data.m_bAuthorized)
|
||||
{
|
||||
@ -399,7 +400,7 @@ void CRConServer::Authenticate(const netcon::request& request, CConnectedNetCons
|
||||
|
||||
const char* pSendLogs = (!sv_rcon_sendlogs.GetBool() || data.m_bInputOnly) ? "0" : "1";
|
||||
|
||||
SendEncoded(data.m_hSocket, s_AuthMessage, pSendLogs,
|
||||
SendEncoded(data.m_hSocket, s_AuthMessage, sizeof(s_AuthMessage)-1, pSendLogs, 1,
|
||||
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
|
||||
}
|
||||
else // Bad password.
|
||||
@ -410,7 +411,7 @@ void CRConServer::Authenticate(const netcon::request& request, CConnectedNetCons
|
||||
Msg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString());
|
||||
}
|
||||
|
||||
SendEncoded(data.m_hSocket, s_WrongPwMessage, "",
|
||||
SendEncoded(data.m_hSocket, s_WrongPwMessage, sizeof(s_WrongPwMessage)-1, "", 0,
|
||||
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
|
||||
|
||||
data.m_bAuthorized = false;
|
||||
@ -444,7 +445,7 @@ bool CRConServer::Comparator(const string& svPassword) const
|
||||
// nMsgLen -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
|
||||
bool CRConServer::ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen)
|
||||
{
|
||||
netcon::request request;
|
||||
|
||||
@ -454,13 +455,13 @@ bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
|
||||
return false;
|
||||
}
|
||||
|
||||
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||
ConnectedNetConsoleData_s& 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, "",
|
||||
SendEncoded(data.m_hSocket, s_NoAuthMessage, sizeof(s_NoAuthMessage)-1, "", 0,
|
||||
netcon::response_e::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
|
||||
|
||||
data.m_bValidated = false;
|
||||
@ -521,7 +522,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(CConnectedNetConsoleData& data)
|
||||
bool CRConServer::CheckForBan(ConnectedNetConsoleData_s& data)
|
||||
{
|
||||
if (data.m_bValidated)
|
||||
{
|
||||
@ -596,7 +597,7 @@ void CRConServer::Disconnect(const char* szReason) // NETMGR
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRConServer::Disconnect(const int nIndex, const char* szReason) // NETMGR
|
||||
{
|
||||
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(nIndex);
|
||||
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(nIndex);
|
||||
if (data.m_bAuthorized)
|
||||
{
|
||||
// Inform server owner when authenticated connection has been closed.
|
||||
@ -621,7 +622,7 @@ void CRConServer::CloseNonAuthConnection(void)
|
||||
int nCount = m_Socket.GetAcceptedSocketCount();
|
||||
for (int i = nCount - 1; i >= 0; i--)
|
||||
{
|
||||
CConnectedNetConsoleData& data = m_Socket.GetAcceptedSocketData(i);
|
||||
ConnectedNetConsoleData_s& data = m_Socket.GetAcceptedSocketData(i);
|
||||
|
||||
if (!data.m_bAuthorized)
|
||||
{
|
||||
|
@ -25,27 +25,27 @@ public:
|
||||
void Think(void);
|
||||
void RunFrame(void);
|
||||
|
||||
bool SendEncoded(const char* pResponseMsg, const char* pResponseVal,
|
||||
bool SendEncoded(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 SendEncoded(const SocketHandle_t hSocket, const char* pResponseMsg,
|
||||
const char* pResponseVal, const netcon::response_e responseType,
|
||||
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,
|
||||
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;
|
||||
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;
|
||||
|
||||
void Authenticate(const netcon::request& request, CConnectedNetConsoleData& data);
|
||||
void Authenticate(const netcon::request& request, ConnectedNetConsoleData_s& data);
|
||||
bool Comparator(const string& svPassword) const;
|
||||
|
||||
virtual bool ProcessMessage(const char* pMsgBuf, const int nMsgLen) override;
|
||||
virtual bool ProcessMessage(const byte* pMsgBuf, const u32 nMsgLen) override;
|
||||
|
||||
void Execute(const netcon::request& request) const;
|
||||
bool CheckForBan(CConnectedNetConsoleData& data);
|
||||
bool CheckForBan(ConnectedNetConsoleData_s& data);
|
||||
|
||||
virtual void Disconnect(const char* szReason = nullptr) override;
|
||||
void Disconnect(const int nIndex, const char* szReason = nullptr);
|
||||
|
@ -9,10 +9,10 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the persistence var in the CClient instance to 'ready'
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CVEngineServer::PersistenceAvailable(void* entidx, int clientidx)
|
||||
bool CVEngineServer::PersistenceAvailable(CVEngineServer* const thisptr, const int clientidx)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
return CVEngineServer__PersistenceAvailable(entidx, clientidx);
|
||||
return CVEngineServer__PersistenceAvailable(thisptr, clientidx);
|
||||
}
|
||||
|
||||
void HVEngineServer::Detour(const bool bAttach) const
|
||||
|
@ -2,22 +2,21 @@
|
||||
#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(void* entidx, int clientidx);
|
||||
static bool PersistenceAvailable(CVEngineServer* const thisptr, const 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
|
||||
{
|
||||
|
@ -144,72 +144,88 @@ bool CNetConBase::Connect(const char* pHostName, const int nPort)
|
||||
// nMaxLen -
|
||||
// Output: true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNetConBase::ProcessBuffer(CConnectedNetConsoleData& data,
|
||||
const char* pRecvBuf, int nRecvLen, const int nMaxLen)
|
||||
bool CNetConBase::ProcessBuffer(ConnectedNetConsoleData_s& data, const byte* pRecvBuf, u32 nRecvLen, const int nMaxLen)
|
||||
{
|
||||
bool bSuccess = true;
|
||||
|
||||
while (nRecvLen > 0)
|
||||
{
|
||||
// Read payload if it's already in progress.
|
||||
if (data.m_nPayloadLen)
|
||||
{
|
||||
if (data.m_nPayloadRead < data.m_nPayloadLen)
|
||||
{
|
||||
data.m_RecvBuffer[data.m_nPayloadRead++] = *pRecvBuf;
|
||||
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;
|
||||
|
||||
pRecvBuf++;
|
||||
nRecvLen--;
|
||||
}
|
||||
if (data.m_nPayloadRead == data.m_nPayloadLen)
|
||||
{
|
||||
if (!ProcessMessage(
|
||||
reinterpret_cast<const char*>(data.m_RecvBuffer.data()), data.m_nPayloadLen)
|
||||
&& bSuccess)
|
||||
{
|
||||
bSuccess = false;
|
||||
}
|
||||
if (!ProcessMessage(data.m_RecvBuffer.data(), data.m_nPayloadLen))
|
||||
return false;
|
||||
|
||||
// Reset state.
|
||||
data.m_nPayloadLen = 0;
|
||||
data.m_nPayloadRead = 0;
|
||||
}
|
||||
}
|
||||
else if (data.m_nPayloadRead < sizeof(int)) // Read size field.
|
||||
else if (data.m_nPayloadRead < sizeof(NetConFrameHeader_s)) // Read the header if we haven't fully recv'd it.
|
||||
{
|
||||
data.m_RecvBuffer[data.m_nPayloadRead++] = *pRecvBuf;
|
||||
const u32 bytesToCopy = Min(nRecvLen, int(sizeof(NetConFrameHeader_s)) - data.m_nPayloadRead);
|
||||
memcpy(reinterpret_cast<char*>(&data.m_FrameHeader) + data.m_nPayloadRead, pRecvBuf, bytesToCopy);
|
||||
|
||||
pRecvBuf++;
|
||||
nRecvLen--;
|
||||
}
|
||||
else // Build prefix.
|
||||
{
|
||||
data.m_nPayloadLen = int(ntohl(*reinterpret_cast<u_long*>(&data.m_RecvBuffer[0])));
|
||||
data.m_nPayloadRead = 0;
|
||||
data.m_nPayloadRead += bytesToCopy;
|
||||
|
||||
if (!data.m_bAuthorized && nMaxLen > -1)
|
||||
pRecvBuf += bytesToCopy;
|
||||
nRecvLen -= bytesToCopy;
|
||||
|
||||
if (data.m_nPayloadRead == sizeof(NetConFrameHeader_s))
|
||||
{
|
||||
if (data.m_nPayloadLen > nMaxLen)
|
||||
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)
|
||||
{
|
||||
Disconnect("overflow"); // Sending large messages while not authenticated.
|
||||
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");
|
||||
|
||||
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).
|
||||
if ((!data.m_bAuthorized && nMaxLen > -1 && header.length > (u32)nMaxLen) ||
|
||||
header.length > RCON_FRAME_MAX_SIZE)
|
||||
{
|
||||
Disconnect("overflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.m_RecvBuffer.resize(data.m_nPayloadLen);
|
||||
data.m_nPayloadLen = header.length;
|
||||
data.m_nPayloadRead = 0;
|
||||
|
||||
data.m_RecvBuffer.resize(header.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -220,13 +236,12 @@ bool CNetConBase::ProcessBuffer(CConnectedNetConsoleData& data,
|
||||
// nDataLen -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNetConBase::Encrypt(CryptoContext_s& ctx, const char* pInBuf,
|
||||
char* pOutBuf, const size_t nDataLen) const
|
||||
bool CNetConBase::Encrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBuf, const u32 nDataLen) const
|
||||
{
|
||||
if (Crypto_GenerateIV(ctx, reinterpret_cast<const unsigned char*>(pInBuf), nDataLen))
|
||||
return Crypto_CTREncrypt(ctx, reinterpret_cast<const unsigned char*>(pInBuf),
|
||||
reinterpret_cast<unsigned char*>(pOutBuf), m_NetKey, nDataLen);
|
||||
if (Crypto_GenerateIV(ctx, pInBuf, nDataLen))
|
||||
return Crypto_CTREncrypt(ctx, pInBuf, pOutBuf, m_NetKey, nDataLen);
|
||||
|
||||
Assert(0);
|
||||
return false; // failure
|
||||
}
|
||||
|
||||
@ -238,11 +253,9 @@ bool CNetConBase::Encrypt(CryptoContext_s& ctx, const char* pInBuf,
|
||||
// nDataLen -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNetConBase::Decrypt(CryptoContext_s& ctx, const char* pInBuf,
|
||||
char* pOutBuf, const size_t nDataLen) const
|
||||
bool CNetConBase::Decrypt(CryptoContext_s& ctx, const byte* pInBuf, byte* pOutBuf, const u32 nDataLen) const
|
||||
{
|
||||
return Crypto_CTRDecrypt(ctx, reinterpret_cast<const unsigned char*>(pInBuf),
|
||||
reinterpret_cast<unsigned char*>(pOutBuf), m_NetKey, nDataLen);
|
||||
return Crypto_CTRDecrypt(ctx, pInBuf, pOutBuf, m_NetKey, nDataLen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -252,10 +265,9 @@ bool CNetConBase::Decrypt(CryptoContext_s& ctx, const char* pInBuf,
|
||||
// nMsgLen -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg,
|
||||
char* pMsgBuf, const size_t nMsgLen) const
|
||||
bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg, byte* pMsgBuf, const u32 nMsgLen) const
|
||||
{
|
||||
return pMsg->SerializeToArray(pMsgBuf, int(nMsgLen));
|
||||
return pMsg->SerializeToArray(pMsgBuf, (i32)nMsgLen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -265,10 +277,9 @@ bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg,
|
||||
// nMsgLen -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg,
|
||||
const char* pMsgBuf, const size_t nMsgLen) const
|
||||
bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg, const byte* pMsgBuf, const u32 nMsgLen) const
|
||||
{
|
||||
return pMsg->ParseFromArray(pMsgBuf, int(nMsgLen));
|
||||
return pMsg->ParseFromArray(pMsgBuf, (i32)nMsgLen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -278,18 +289,9 @@ bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg,
|
||||
// nMsgLen -
|
||||
// Output: true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNetConBase::Send(const SocketHandle_t hSocket, const char* pMsgBuf,
|
||||
const int nMsgLen) const
|
||||
bool CNetConBase::Send(const SocketHandle_t hSocket, const byte* pMsgBuf, const u32 nMsgLen) const
|
||||
{
|
||||
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);
|
||||
|
||||
const int ret = ::send(hSocket, (char*)pMsgBuf, (i32)nMsgLen, MSG_NOSIGNAL);
|
||||
return (ret != SOCKET_ERROR);
|
||||
}
|
||||
|
||||
@ -299,19 +301,19 @@ bool CNetConBase::Send(const SocketHandle_t hSocket, const char* pMsgBuf,
|
||||
// nMaxLen -
|
||||
// Output: true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNetConBase::Recv(CConnectedNetConsoleData& data, const int nMaxLen)
|
||||
void CNetConBase::Recv(ConnectedNetConsoleData_s& data, const int nMaxLen)
|
||||
{
|
||||
static char szRecvBuf[1024];
|
||||
|
||||
{//////////////////////////////////////////////
|
||||
const int nPendingLen = ::recv(data.m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
|
||||
const int nPendingLen = ::recv(data.m_hSocket, szRecvBuf, sizeof(szRecvBuf), MSG_PEEK);
|
||||
if (nPendingLen == SOCKET_ERROR && m_Socket.IsSocketBlocking())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (nPendingLen == 0) // Socket was closed.
|
||||
{
|
||||
Disconnect("remote closed socket");
|
||||
Disconnect("socket closed prematurely");
|
||||
return;
|
||||
}
|
||||
else if (nPendingLen < 0)
|
||||
@ -321,8 +323,8 @@ void CNetConBase::Recv(CConnectedNetConsoleData& data, const int nMaxLen)
|
||||
}
|
||||
}//////////////////////////////////////////////
|
||||
|
||||
int nReadLen = 0; // Find out how much we have to read.
|
||||
int iResult = ::ioctlsocket(data.m_hSocket, FIONREAD, reinterpret_cast<u_long*>(&nReadLen));
|
||||
u_long nReadLen = 0; // Find out how much we have to read.
|
||||
const int iResult = ::ioctlsocket(data.m_hSocket, FIONREAD, &nReadLen);
|
||||
|
||||
if (iResult == SOCKET_ERROR)
|
||||
{
|
||||
@ -344,8 +346,10 @@ void CNetConBase::Recv(CConnectedNetConsoleData& data, const int nMaxLen)
|
||||
break;
|
||||
}
|
||||
|
||||
nReadLen -= nRecvLen; // Process what we've got.
|
||||
ProcessBuffer(data, szRecvBuf, nRecvLen, nMaxLen);
|
||||
nReadLen -= static_cast<u_long>(nRecvLen); // Process what we've got.
|
||||
|
||||
if (!ProcessBuffer(data, reinterpret_cast<byte*>(&szRecvBuf), static_cast<u32>(nRecvLen), nMaxLen))
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1,14 +1,12 @@
|
||||
#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:
|
||||
@ -23,17 +21,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(CConnectedNetConsoleData& data, const char* pRecvBuf, int nRecvLen, const int nMaxLen = SOCKET_ERROR);
|
||||
virtual bool ProcessMessage(const char* /*pMsgBuf*/, int /*nMsgLen*/) { return true; };
|
||||
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 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 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 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 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 Send(const SocketHandle_t hSocket, const char* pMsgBuf, const int nMsgLen) const;
|
||||
virtual void Recv(CConnectedNetConsoleData& data, const int nMaxLen = SOCKET_ERROR);
|
||||
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);
|
||||
|
||||
CSocketCreator* GetSocketCreator(void) { return &m_Socket; }
|
||||
netadr_t* GetNetAddress(void) { return &m_Address; }
|
||||
|
66
src/engine/shared/ents_shared.h
Normal file
66
src/engine/shared/ents_shared.h
Normal file
@ -0,0 +1,66 @@
|
||||
//===== 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
|
@ -13,7 +13,9 @@
|
||||
// Input : *pBase -
|
||||
// &vecBuf -
|
||||
// *pResponseMsg -
|
||||
// nResponseMsgLen -
|
||||
// *pResponseVal -
|
||||
// nResponseValLen -
|
||||
// responseType -
|
||||
// nMessageId -
|
||||
// nMessageType -
|
||||
@ -21,7 +23,8 @@
|
||||
// bDebug -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool NetconServer_Serialize(const CNetConBase* pBase, vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal,
|
||||
bool NetconServer_Serialize(const CNetConBase* pBase, 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, const int nMessageType, const bool bEncrypt, const bool bDebug)
|
||||
{
|
||||
netcon::response response;
|
||||
@ -29,10 +32,10 @@ bool NetconServer_Serialize(const CNetConBase* pBase, vector<char>& vecBuf, cons
|
||||
response.set_messageid(nMessageId);
|
||||
response.set_messagetype(nMessageType);
|
||||
response.set_responsetype(responseType);
|
||||
response.set_responsemsg(pResponseMsg);
|
||||
response.set_responseval(pResponseVal);
|
||||
response.set_responsemsg(pResponseMsg, nResponseMsgLen);
|
||||
response.set_responseval(pResponseVal, nResponseValLen);
|
||||
|
||||
if (!NetconShared_PackEnvelope(pBase, vecBuf, response.ByteSizeLong(), &response, bEncrypt, bDebug))
|
||||
if (!NetconShared_PackEnvelope(pBase, vecBuf, (u32)response.ByteSizeLong(), &response, bEncrypt, bDebug))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -45,23 +48,25 @@ bool NetconServer_Serialize(const CNetConBase* pBase, vector<char>& vecBuf, cons
|
||||
// Input : *pBase -
|
||||
// &vecBuf -
|
||||
// *szReqBuf -
|
||||
// nReqMsgLen -
|
||||
// *szReqVal -
|
||||
// nReqValLen -
|
||||
// *requestType -
|
||||
// bEncrypt -
|
||||
// bDebug -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
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_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)
|
||||
{
|
||||
netcon::request request;
|
||||
|
||||
request.set_messageid(-1);
|
||||
request.set_requesttype(requestType);
|
||||
request.set_requestmsg(szReqBuf);
|
||||
request.set_requestval(szReqVal);
|
||||
request.set_requestmsg(szReqBuf, nReqMsgLen);
|
||||
request.set_requestval(szReqVal, nReqValLen);
|
||||
|
||||
if (!NetconShared_PackEnvelope(pBase, vecBuf, request.ByteSizeLong(), &request, bEncrypt, bDebug))
|
||||
if (!NetconShared_PackEnvelope(pBase, vecBuf, (u32)request.ByteSizeLong(), &request, bEncrypt, bDebug))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -124,11 +129,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<char>& outMsgBuf, const size_t nMsgLen,
|
||||
google::protobuf::MessageLite* inMsg, const bool bEncrypt, const bool bDebug)
|
||||
bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<byte>& outMsgBuf, const u32 nMsgLen,
|
||||
google::protobuf::MessageLite* const inMsg, const bool bEncrypt, const bool bDebug)
|
||||
{
|
||||
char* encodeBuf = new char[nMsgLen];
|
||||
std::unique_ptr<char[]> encodedContainer(encodeBuf);
|
||||
byte* const encodeBuf = new byte[nMsgLen];
|
||||
std::unique_ptr<byte[]> encodedContainer(encodeBuf);
|
||||
|
||||
if (!pBase->Encode(inMsg, encodeBuf, nMsgLen))
|
||||
{
|
||||
@ -143,12 +148,12 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<char>& outMsgBuf
|
||||
netcon::envelope envelope;
|
||||
envelope.set_encrypted(bEncrypt);
|
||||
|
||||
const char* dataBuf = encodeBuf;
|
||||
std::unique_ptr<char[]> container;
|
||||
const byte* dataBuf = encodeBuf;
|
||||
std::unique_ptr<byte[]> container;
|
||||
|
||||
if (bEncrypt)
|
||||
{
|
||||
char* encryptBuf = new char[nMsgLen];
|
||||
byte* encryptBuf = new byte[nMsgLen];
|
||||
container.reset(encryptBuf);
|
||||
|
||||
CryptoContext_s ctx;
|
||||
@ -167,11 +172,12 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<char>& outMsgBuf
|
||||
}
|
||||
|
||||
envelope.set_data(dataBuf, nMsgLen);
|
||||
const size_t envelopeSize = envelope.ByteSizeLong();
|
||||
const u32 envelopeSize = (u32)envelope.ByteSizeLong();
|
||||
|
||||
outMsgBuf.resize(envelopeSize);
|
||||
outMsgBuf.resize(sizeof(NetConFrameHeader_s) + envelopeSize);
|
||||
byte* const scratch = outMsgBuf.data();
|
||||
|
||||
if (!pBase->Encode(&envelope, &outMsgBuf[0], envelopeSize))
|
||||
if (!pBase->Encode(&envelope, &scratch[sizeof(NetConFrameHeader_s)], envelopeSize))
|
||||
{
|
||||
if (bDebug)
|
||||
{
|
||||
@ -181,6 +187,12 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<char>& 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;
|
||||
}
|
||||
|
||||
@ -194,8 +206,8 @@ bool NetconShared_PackEnvelope(const CNetConBase* pBase, vector<char>& outMsgBuf
|
||||
// bDebug -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf, const size_t nMsgLen,
|
||||
google::protobuf::MessageLite* outMsg, const bool bDebug)
|
||||
bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const byte* pMsgBuf, const u32 nMsgLen,
|
||||
google::protobuf::MessageLite* const outMsg, const bool bDebug)
|
||||
{
|
||||
netcon::envelope envelope;
|
||||
|
||||
@ -209,33 +221,33 @@ bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf,
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t msgLen = envelope.data().size();
|
||||
const u32 msgLen = (u32)envelope.data().size();
|
||||
|
||||
if (msgLen > RCON_MAX_PAYLOAD_SIZE)
|
||||
if (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);
|
||||
Error(eDLL_T::ENGINE, NO_ERROR, "Data in RCON message envelope is too large (%u > %u)\n",
|
||||
msgLen, RCON_FRAME_MAX_SIZE);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* netMsg = envelope.data().c_str();
|
||||
const char* dataBuf = netMsg;
|
||||
const byte* netMsg = reinterpret_cast<const byte*>(envelope.data().c_str());
|
||||
const byte* dataBuf = netMsg;
|
||||
|
||||
std::unique_ptr<char[]> container;
|
||||
std::unique_ptr<byte[]> container;
|
||||
|
||||
if (envelope.encrypted())
|
||||
{
|
||||
char* decryptBuf = new char[msgLen];
|
||||
byte* decryptBuf = new byte[msgLen];
|
||||
container.reset(decryptBuf);
|
||||
|
||||
const size_t ivLen = envelope.nonce().size();
|
||||
const u32 ivLen = (u32)envelope.nonce().size();
|
||||
|
||||
if (ivLen != sizeof(CryptoIV_t))
|
||||
{
|
||||
if (bDebug)
|
||||
{
|
||||
Error(eDLL_T::ENGINE, NO_ERROR, "Nonce in RCON message envelope is invalid (%zu != %zu)\n",
|
||||
Error(eDLL_T::ENGINE, NO_ERROR, "Nonce in RCON message envelope is invalid (%u != %u)\n",
|
||||
ivLen, sizeof(CryptoIV_t));
|
||||
}
|
||||
|
||||
@ -279,7 +291,7 @@ bool NetconShared_UnpackEnvelope(const CNetConBase* pBase, const char* pMsgBuf,
|
||||
// iSocket -
|
||||
// Output : nullptr on failure
|
||||
//-----------------------------------------------------------------------------
|
||||
CConnectedNetConsoleData* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket)
|
||||
ConnectedNetConsoleData_s* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket)
|
||||
{
|
||||
CSocketCreator* pCreator = pBase->GetSocketCreator();
|
||||
Assert(iSocket >= 0 && (pCreator->GetAcceptedSocketCount() == 0
|
||||
@ -301,7 +313,7 @@ CConnectedNetConsoleData* NetconShared_GetConnData(CNetConBase* pBase, const int
|
||||
//-----------------------------------------------------------------------------
|
||||
SocketHandle_t NetconShared_GetSocketHandle(CNetConBase* pBase, const int iSocket)
|
||||
{
|
||||
const CConnectedNetConsoleData* pData = NetconShared_GetConnData(pBase, iSocket);
|
||||
const ConnectedNetConsoleData_s* pData = NetconShared_GetConnData(pBase, iSocket);
|
||||
if (!pData)
|
||||
{
|
||||
return SOCKET_ERROR;
|
||||
@ -344,19 +356,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, g_svGreyB, RCONClient()->GetKey(), g_svReset);
|
||||
g_svReset.c_str(), g_svGreyB.c_str(), RCONClient()->GetKey(), g_svReset.c_str());
|
||||
#else
|
||||
#ifdef DEDICATED
|
||||
RCONServer()->SetKey(pNewString);
|
||||
|
||||
Msg(eDLL_T::SERVER, "Installed RCON Key: %s'%s%s%s'\n",
|
||||
g_svReset, g_svGreyB, RCONServer()->GetKey(), g_svReset);
|
||||
g_svReset.c_str(), g_svGreyB.c_str(), RCONServer()->GetKey(), g_svReset.c_str());
|
||||
#endif // DEDICATED
|
||||
#ifdef CLIENT_DLL
|
||||
RCONClient()->SetKey(pNewString);
|
||||
|
||||
Msg(eDLL_T::CLIENT, "Installed RCON Key: %s'%s%s%s'\n",
|
||||
g_svReset, g_svGreyB, RCONClient()->GetKey(), g_svReset);
|
||||
g_svReset.c_str(), g_svGreyB.c_str(), RCONClient()->GetKey(), g_svReset.c_str());
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
#endif // !DEDICATED && !CLIENT_DLL
|
||||
|
@ -16,17 +16,18 @@ extern void RCON_InitClientAndTrySyncKeys();
|
||||
#endif // !DEDICATED
|
||||
#endif // _TOOLS
|
||||
|
||||
bool NetconServer_Serialize(const CNetConBase* pBase, vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal,
|
||||
bool NetconServer_Serialize(const CNetConBase* pBase, 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, const int nMessageType, 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_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_Connect(CNetConBase* pBase, const char* pHostAdr, const int nHostPort);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
CConnectedNetConsoleData* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket);
|
||||
ConnectedNetConsoleData_s* NetconShared_GetConnData(CNetConBase* pBase, const int iSocket);
|
||||
SocketHandle_t NetconShared_GetSocketHandle(CNetConBase* pBase, const int iSocket);
|
||||
|
||||
#endif // SHARED_RCON_H
|
||||
|
@ -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);
|
||||
|
||||
bool results = CEngineAPI__ModInit(pEngineAPI, pModName, pGameDir);
|
||||
const bool results = CEngineAPI__ModInit(pEngineAPI, pModName, pGameDir);
|
||||
if (!IsValveMod(pModName) && !IsRespawnMod(pModName))
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
@ -109,6 +109,15 @@ 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
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -297,6 +306,7 @@ 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);
|
||||
|
@ -2,17 +2,9 @@
|
||||
#include "vpc/interfaces.h"
|
||||
#include "common/engine_launcher_api.h"
|
||||
|
||||
class CEngineAPI : public IEngineAPI
|
||||
class CEngineAPI : public CTier1AppSystem<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;
|
||||
|
||||
@ -32,6 +24,7 @@ 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();
|
||||
@ -49,6 +42,7 @@ 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);
|
||||
@ -69,6 +63,7 @@ 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);
|
||||
@ -85,6 +80,7 @@ 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);
|
||||
|
@ -4,7 +4,6 @@
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "core/stdafx.h"
|
||||
#include "windows/id3dx.h"
|
||||
#include "engine/sys_getmodes.h"
|
||||
#include "gameui/imgui_system.h"
|
||||
|
||||
@ -13,9 +12,6 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
@ -30,10 +30,18 @@ void CGame::PlayStartupVideos(void)
|
||||
//-----------------------------------------------------------------------------
|
||||
LRESULT CGame::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (!ImguiSystem()->IsInitialized())
|
||||
return CGame__WindowProc(hWnd, uMsg, wParam, lParam);
|
||||
if (ImguiSystem()->IsInitialized())
|
||||
ImguiWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
ImguiSystem()->MessageHandler(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;
|
||||
|
||||
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)
|
||||
{
|
||||
@ -52,42 +60,40 @@ LRESULT CGame::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Console.IsActivated() || g_Browser.IsActivated())
|
||||
if (ImguiSystem()->IsSurfaceActive())
|
||||
{//////////////////////////////////////////////////////////////////////////////
|
||||
g_bBlockInput = true;
|
||||
hr = ImguiSystem()->MessageHandler(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
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:
|
||||
// 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_SETCURSOR:
|
||||
uMsg = WM_NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_bBlockInput = true;
|
||||
}//////////////////////////////////////////////////////////////////////////////
|
||||
else
|
||||
{
|
||||
g_bBlockInput = false;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return CGame__WindowProc(hWnd, uMsg, wParam, lParam);
|
||||
return hr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -113,6 +119,24 @@ 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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -6,6 +6,7 @@
|
||||
#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);
|
||||
@ -17,12 +18,16 @@ class CGame
|
||||
{
|
||||
public:
|
||||
static void PlayStartupVideos(void);
|
||||
static LRESULT WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
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; }
|
||||
@ -46,7 +51,7 @@ private:
|
||||
int m_iDesktopWidth;
|
||||
int m_iDesktopHeight;
|
||||
int m_iDesktopRefreshRate;
|
||||
void* m_pInputContext_Maybe;
|
||||
InputContextHandle_t m_hInputContext;
|
||||
}; static_assert(sizeof(CGame) == 64);
|
||||
|
||||
inline CGame* g_pGame = nullptr;
|
||||
|
@ -6,17 +6,6 @@
|
||||
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; };
|
||||
|
@ -14,295 +14,45 @@ bool C_Player::CheckMeleeWeapon()
|
||||
&& *(float*)&pWeapon->m_modVars[600] > (float)(m_currentFramePlayer__timeBase - m_melee.attackLastHitNonWorldEntity);
|
||||
}
|
||||
|
||||
void C_Player::CurveLook(C_Player* player, CInput::UserInput_t* input, float a3, float a4, float a5, int a6, float inputSampleFrametime, bool runAimAssist, JoyAngle_t* a9)
|
||||
static void ApplyPerOpticScalars(C_Player* const player, JoyAngle_t* const joyAngle)
|
||||
{
|
||||
float v11; // xmm7_4
|
||||
float v12; // xmm11_4
|
||||
float v13; // xmm14_4
|
||||
float v14; // xmm15_4
|
||||
float v17; // xmm0_4
|
||||
float v18; // xmm0_4
|
||||
__int64 v19; // xmm1_8
|
||||
bool m_bAutoAim_UnknownBool1AC; // r13
|
||||
bool m_bAutoAim_UnknownBool1AD; // r15
|
||||
bool m_bAutoAim_UnknownBool1B1; // r14
|
||||
QAngle* v24; // rax
|
||||
bool v25; // zf
|
||||
QAngle* p_m_angUnknown1C8; // rax
|
||||
float inputSampleFrametime_c; // xmm13_4
|
||||
float v31; // xmm8_4
|
||||
int selectedGamePadLookCurve; // r12d
|
||||
float v33; // xmm7_4
|
||||
float v34;
|
||||
int customAimSpeed; // eax
|
||||
int v37; // edx
|
||||
float* v38; // rsi
|
||||
char* v39; // rsi
|
||||
float v40; // xmm6_4
|
||||
float v42; // xmm0_4
|
||||
float v43; // xmm0_4
|
||||
float v44; // xmm10_4
|
||||
float v45; // xmm2_4
|
||||
float v46; // xmm6_4
|
||||
float v47; // xmm0_4
|
||||
float v48; // xmm7_4
|
||||
float v49; // xmm9_4
|
||||
float v50; // xmm6_4
|
||||
bool bZooming; // al
|
||||
bool v55; // cl
|
||||
float v56; // xmm1_4
|
||||
float v57; // xmm2_4
|
||||
float v58; // xmm0_4
|
||||
float v59; // xmm8_4
|
||||
float v60; // xmm9_4
|
||||
float v62; // xmm10_4
|
||||
float v63; // xmm0_4
|
||||
float v64; // xmm6_4
|
||||
JoyAngle_t* v65; // rsi
|
||||
float v66; // xmm7_4
|
||||
QAngle v68; // [rsp+68h] [rbp-A0h] BYREF
|
||||
QAngle v69; // [rsp+78h] [rbp-90h] BYREF
|
||||
Vector3D v70;
|
||||
QAngle v71; // [rsp+178h] [rbp+70h] BYREF
|
||||
float m_flUnknownFloat1B8; // [rsp+188h] [rbp+80h]
|
||||
float v73; // [rsp+190h] [rbp+88h]
|
||||
if (!GamePad_UseAdvancedAdsScalarsPerScope())
|
||||
return;
|
||||
|
||||
v73 = a4;
|
||||
v11 = sub_1408A0600(player);
|
||||
v12 = 1.0f - v11;
|
||||
v13 = (float)(1.0f - v11) * a3;
|
||||
v14 = (float)(1.0f - v11) * a4;
|
||||
const bool isZooming = player->IsZooming();
|
||||
|
||||
const C_WeaponX* activeWeapon = C_BaseCombatCharacter__GetActiveWeapon(player);
|
||||
const bool isZoomed = player->m_bZooming
|
||||
? !activeWeapon || activeWeapon->m_modVars[3100]
|
||||
: false;
|
||||
if (!isZooming)
|
||||
return;
|
||||
|
||||
v17 = fabs(v13);
|
||||
if (v17 > 0.050000001 || (v18 = fabs(v14), v18 > 0.050000001))
|
||||
(*double_14D413928) = Plat_FloatTime();
|
||||
const C_WeaponX* const activeWeapon = C_BaseCombatCharacter__GetActiveWeapon(player);
|
||||
|
||||
if (!runAimAssist)
|
||||
sub_1405B0E00(player, input);
|
||||
if (!activeWeapon)
|
||||
return;
|
||||
|
||||
// NOTE: in the decompiler and disassembler, it appears that this
|
||||
// 'runAimAssist' param is always a bool, but this function below
|
||||
// indexes beyond the size of bool, just 2 bytes.. Looking at the
|
||||
// stack, there always seem to be space for it and nothing gets
|
||||
// smashed, nor does that area contain random data; the 4 bytes
|
||||
// are always free. Comparing this with the original code results
|
||||
// in identical results. Keeping it like this for now as even though
|
||||
// it looks off, it actually is correct.
|
||||
// Also, even though the function below does set 2 extra bools next
|
||||
// to the address of 'runAimAssist', only 'runAimAssist' is ever used
|
||||
// based on my hardware breakpoint tests. So its possible the function
|
||||
// below technically expects an array of bools or something but then
|
||||
// the original code only passes in the 'runAimAssist' which is stored
|
||||
// on the stack, and only having the below call work properly due to
|
||||
// stack alignment.
|
||||
sub_1405AD760(player, (unsigned char*)&runAimAssist);
|
||||
const bool fullADS = activeWeapon->m_modVars[3100];
|
||||
|
||||
const bool gamePadCustomEnabled = gamepad_custom_enabled->GetBool();
|
||||
if (!fullADS)
|
||||
return;
|
||||
|
||||
if (gamePadCustomEnabled && !gamepad_custom_assist_on->GetBool()
|
||||
|| Plat_FloatTime() - (*double_14D4151B8) < 2.0
|
||||
|| (*double_14D4151B8) > (*double_14D413928)
|
||||
|| runAimAssist
|
||||
|| (unsigned int)sub_14066D190(player)
|
||||
|| C_Player__IsInTimeShift(player)
|
||||
|| v11 > 0.050000001
|
||||
|| !gamePadCustomEnabled && (unsigned int)C_Player__GetAimSpeed(player, isZoomed) == 7
|
||||
|| (v19 = *(_QWORD*)&player->pl.lastPlayerView_angle.x, v70.z = player->pl.lastPlayerView_angle.z, *(_QWORD*)&v70.x = v19, *(float*)&v19 < -50.0f)
|
||||
|| sub_1405AD4E0(player) < FLT_EPSILON)
|
||||
{
|
||||
m_bAutoAim_UnknownBool1AC = false;
|
||||
m_bAutoAim_UnknownBool1AD = false;
|
||||
runAimAssist = false;
|
||||
m_bAutoAim_UnknownBool1B1 = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bAutoAim_UnknownBool1AC = input->m_bAutoAim_UnknownBool1AC;
|
||||
m_bAutoAim_UnknownBool1AD = input->m_bAutoAim_UnknownBool1AD;
|
||||
runAimAssist = input->m_bAutoAim_UnknownBool1B0;
|
||||
m_bAutoAim_UnknownBool1B1 = input->m_bAutoAim_UnknownBool1B1;
|
||||
}
|
||||
const float interpAmount = activeWeapon->HasTargetZoomFOV()
|
||||
? activeWeapon->GetZoomFOVInterpAmount(g_ClientGlobalVariables->exactCurTime)
|
||||
: 1.0f - activeWeapon->GetZoomFOVInterpAmount(g_ClientGlobalVariables->exactCurTime);
|
||||
|
||||
v70 = input->m_vecUnknown1BC;
|
||||
m_flUnknownFloat1B8 = input->m_flUnknownFloat1B8;
|
||||
v24 = sub_1406257E0(&v69, player);
|
||||
v25 = !input->m_bUnknown1D4;
|
||||
v68 = *v24;
|
||||
p_m_angUnknown1C8 = &input->m_angUnknown1C8;
|
||||
const float baseScalar1 = GamePad_GetAdvancedAdsScalarForOptic((WeaponScopeZoomLevel_e)activeWeapon->m_modVars[0xA0C]);
|
||||
const float baseScalar2 = GamePad_GetAdvancedAdsScalarForOptic((WeaponScopeZoomLevel_e)activeWeapon->m_modVars[0xA10]);
|
||||
|
||||
if (v25)
|
||||
p_m_angUnknown1C8 = &v68;
|
||||
const float adsScalar = ((baseScalar2 - baseScalar1) * interpAmount) + baseScalar1;
|
||||
|
||||
inputSampleFrametime_c = inputSampleFrametime;
|
||||
v69 = *p_m_angUnknown1C8;
|
||||
if (m_bAutoAim_UnknownBool1AD && m_bAutoAim_UnknownBool1B1)
|
||||
input->m_flUnknownFloat1B4 = 0.0f;
|
||||
else
|
||||
input->m_flUnknownFloat1B4 = inputSampleFrametime + input->m_flUnknownFloat1B4;
|
||||
joyAngle->rotation.x *= adsScalar;
|
||||
joyAngle->rotation.y *= adsScalar;
|
||||
}
|
||||
|
||||
v71.Init();
|
||||
v31 = 0.0f;
|
||||
sub_1405B03A0(input, player, &v71);
|
||||
selectedGamePadLookCurve = 1;
|
||||
v33 = sub_1405B0BC0(player, input, 0);
|
||||
v34 = sub_1405B0BC0(player, input, 1);
|
||||
a5 = v34;
|
||||
void C_Player::CurveLook(C_Player* player, CInput::UserInput_t* input, float a3, float a4, float a5, int a6, float inputSampleFrametime, bool runAimAssist, JoyAngle_t* joyAngle)
|
||||
{
|
||||
C_Player__CurveLook(player, input, a3, a4, a5, a6, inputSampleFrametime, runAimAssist, joyAngle);
|
||||
ApplyPerOpticScalars(player, joyAngle);
|
||||
|
||||
const bool v36 = m_bAutoAim_UnknownBool1AD && runAimAssist;
|
||||
const bool v35 = m_bAutoAim_UnknownBool1AD && m_bAutoAim_UnknownBool1B1;
|
||||
|
||||
customAimSpeed = C_Player__GetAimSpeed(player, isZoomed);
|
||||
v37 = *(_DWORD*)((unsigned int)(*dword_1423880E0) + *(_QWORD*)&player->gap_21a0[16]);
|
||||
|
||||
if (gamePadCustomEnabled)
|
||||
{
|
||||
sub_1405AEA10(nullptr, isZoomed, v37 == 1);
|
||||
v38 = dword_16A2A1640;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v37 == 1)
|
||||
{
|
||||
if (isZoomed)
|
||||
v39 = (char*)g_lookSensitivity_TitanZoomed;
|
||||
else
|
||||
v39 = (char*)g_lookSensitivity_Titan;
|
||||
}
|
||||
else
|
||||
{
|
||||
v25 = !isZoomed;
|
||||
v39 = (char*)g_lookSensitivity_Zoomed;
|
||||
if (v25)
|
||||
v39 = (char*)g_lookSensitivity;
|
||||
}
|
||||
|
||||
v38 = (float*)&v39[276 * customAimSpeed];
|
||||
}
|
||||
|
||||
if (v35)
|
||||
{
|
||||
v40 = 0.64999998f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float m_flUnknownFloat1B4 = input->m_flUnknownFloat1B4;
|
||||
if (m_flUnknownFloat1B4 <= 0.2f)
|
||||
{
|
||||
v34 = 0.1f;
|
||||
if (m_flUnknownFloat1B4 > 0.1f)
|
||||
v40 = (float)((float)((float)(m_flUnknownFloat1B4 - 0.1f) / 0.1f) * 0.35000002f) + 0.64999998f;
|
||||
else
|
||||
v40 = 0.64999998f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v40 = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
v42 = m_flUnknownFloat1B8;
|
||||
sub_1405AF810(player, input, (__int64)v38, m_bAutoAim_UnknownBool1AC, v36, &v70, &v69, &v68, m_flUnknownFloat1B8);
|
||||
inputSampleFrametime = ((v34 * (1.0f - v40)) + v40) * (1.0f - (v33 * 0.94999999f));
|
||||
v43 = sqrtf((a3 * a3) + (v73 * v73));
|
||||
v44 = v43;
|
||||
|
||||
const int gamePadLookCurve = gamepad_look_curve->GetInt();
|
||||
|
||||
if (gamePadLookCurve <= 4u)
|
||||
selectedGamePadLookCurve = gamePadLookCurve;
|
||||
|
||||
v45 = fabs((v43 - 0.0f));
|
||||
if (v45 > 0.001f)
|
||||
{
|
||||
if (gamePadCustomEnabled)
|
||||
v47 = GamePad_CalcOuterDeadzoneCustom(v43);
|
||||
else
|
||||
v47 = GamePad_CalcOuterDeadzone(&g_aimCurveConfig[selectedGamePadLookCurve], v43);
|
||||
|
||||
v46 = v47 / v44;
|
||||
}
|
||||
else
|
||||
{
|
||||
v46 = 0.0;
|
||||
}
|
||||
|
||||
v48 = v46 * v13;
|
||||
v49 = 0.0f;
|
||||
v50 = v46 * v14;
|
||||
|
||||
if (v38[67] <= 0.0f
|
||||
|| v38[65] == 0.0f && v38[64] == 0.0
|
||||
|| m_bAutoAim_UnknownBool1AC
|
||||
|| v44 < 0.99000001f
|
||||
|| (unsigned int)(player->m_contextAction - 2) <= 1
|
||||
|| ((player->m_melee.scriptedState - 3) & 0xFFFFFFFA) == 0
|
||||
|| sub_1409DC4E0(player)
|
||||
|| (player->m_latestMeleeWeapon.IsValid())
|
||||
|| (player->CheckMeleeWeapon())
|
||||
|| player->m_MoveType == MOVETYPE_TRAVERSE && !player->m_traversalType
|
||||
|| (bZooming = input->m_bZooming, v55 = player->m_bZooming, input->m_bZooming = v55, bZooming) && !v55)
|
||||
{
|
||||
input->m_flSomeInputSampleFrameTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v56 = inputSampleFrametime_c + input->m_flSomeInputSampleFrameTime;
|
||||
input->m_flSomeInputSampleFrameTime = v56;
|
||||
v57 = v38[66];
|
||||
if (v57 <= v56)
|
||||
{
|
||||
v58 = GamePad_CalcOuterDeadzone((AimCurveConfig_s*)(v38 + 2), fminf(v56 - v57, v38[67]) / v38[67]);
|
||||
v31 = (float)(v58 * v48) * v38[65];
|
||||
v49 = (float)(v58 * v50) * v38[64];
|
||||
}
|
||||
}
|
||||
|
||||
v59 = v31 * v12;
|
||||
v60 = v49 * v12;
|
||||
|
||||
if (activeWeapon && C_Player__GetZoomFrac(player) >= 0.99000001f && activeWeapon->m_modVars[412])
|
||||
v62 = v38[0];
|
||||
else
|
||||
v62 = v38[1];
|
||||
|
||||
float adsScalar = 1.0f;
|
||||
|
||||
if (isZoomed && activeWeapon && GamePad_UseAdvancedAdsScalarsPerScope())
|
||||
{
|
||||
const float interpAmount = activeWeapon->HasTargetZoomFOV()
|
||||
? activeWeapon->GetZoomFOVInterpAmount(g_ClientGlobalVariables->exactCurTime)
|
||||
: 1.0f - activeWeapon->GetZoomFOVInterpAmount(g_ClientGlobalVariables->exactCurTime);
|
||||
|
||||
const float baseScalar1 = GamePad_GetAdvancedAdsScalarForOptic((WeaponScopeZoomLevel_e)activeWeapon->m_modVars[0xA0C]);
|
||||
const float baseScalar2 = GamePad_GetAdvancedAdsScalarForOptic((WeaponScopeZoomLevel_e)activeWeapon->m_modVars[0xA10]);
|
||||
|
||||
adsScalar = ((baseScalar2 - baseScalar1) * interpAmount) + baseScalar1;
|
||||
}
|
||||
|
||||
v63 = sub_1405D4300(player);
|
||||
v64 = (float)(v50 * inputSampleFrametime) * *v38;
|
||||
v65 = a9;
|
||||
v66 = (float)(v48 * inputSampleFrametime) * v62;
|
||||
a9->unk1 = v71.y;
|
||||
|
||||
v65->unk2.Init();
|
||||
|
||||
const float pitchX = ((v66 * adsScalar) + v59) * v63;
|
||||
const float pitchY = ((v64 * adsScalar) + v60) * v63;
|
||||
|
||||
v65->pitch.x = pitchX * inputSampleFrametime_c;
|
||||
v65->pitch.y = (pitchY * inputSampleFrametime_c) * -1.0f;
|
||||
v65->pitch.z = v71.x;
|
||||
|
||||
if (m_bAutoAim_UnknownBool1AD && runAimAssist)
|
||||
{
|
||||
sub_1405AF1F0(input, player, (QAngle*)&v70, &v69, v14, v13, inputSampleFrametime_c, a5, &v65->unk2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void V_Player::Detour(const bool bAttach) const
|
||||
|
@ -59,9 +59,11 @@ class C_KnockBack
|
||||
|
||||
struct JoyAngle_t
|
||||
{
|
||||
QAngle pitch;
|
||||
float unk1;
|
||||
Vector2D unk2;
|
||||
// The joystick rotation amount.
|
||||
QAngle rotation;
|
||||
|
||||
// The joystick counter amount (used for auto-aim).
|
||||
QAngle counter;
|
||||
};
|
||||
|
||||
class C_Player : public C_BaseCombatCharacter
|
||||
@ -69,6 +71,8 @@ class C_Player : public C_BaseCombatCharacter
|
||||
public:
|
||||
static void CurveLook(C_Player* player, CInput::UserInput_t* input, float a3, float a4, float a5, int a6, float inputSampleFrametime, bool runAimAssist, JoyAngle_t* a9);
|
||||
bool CheckMeleeWeapon();
|
||||
|
||||
inline bool IsZooming() const { return m_bZooming; }
|
||||
private:
|
||||
bool unk;
|
||||
bool m_bZooming;
|
||||
@ -348,32 +352,11 @@ static_assert(sizeof(C_Player) == 0x41C0);
|
||||
// move to combatcharacter!
|
||||
inline C_WeaponX* (*C_BaseCombatCharacter__GetActiveWeapon)(C_BaseCombatCharacter* thisptr);
|
||||
|
||||
inline float (*sub_1408A0600)(C_Player* player);
|
||||
inline void (*sub_1405B0E00)(C_Player* player, CInput::UserInput_t* input);
|
||||
inline void (*sub_1405AD760)(C_Player* player, unsigned char* unknown);
|
||||
inline int (*sub_14066D190)(C_Player* player);
|
||||
inline float (*sub_1405AD4E0)(C_Player* player);
|
||||
inline QAngle* (*sub_1406257E0)(QAngle* angle, C_Player* player);
|
||||
inline void (*sub_1405B03A0)(CInput::UserInput_t* input, C_Player* player, QAngle* angle);
|
||||
inline float (*sub_1405B0BC0)(C_Player* player, CInput::UserInput_t* input, int a3);
|
||||
inline void (*sub_1405AEA10)(void* a1, bool isZoomed, char a3);
|
||||
inline void (*sub_1405AF810)(C_Player* player, CInput::UserInput_t* input, __int64 a3, char a4, char a5, Vector3D* a6, QAngle* a7, QAngle* a8, float a9);
|
||||
inline C_BaseEntity* (*sub_1409DC4E0)(C_Player* player);
|
||||
inline float (*sub_1405D4300)(C_Player* player);
|
||||
inline QAngle* (*sub_1405AF1F0)(CInput::UserInput_t* a1, C_Player* a2, QAngle* a3, QAngle* a4, float a5, float a6, float a7, float a8, Vector2D* a9);
|
||||
|
||||
inline float (*C_Player__GetZoomFrac)(C_Player* thisptr);
|
||||
inline int (*C_Player__GetAimSpeed)(C_Player* thisptr, bool isZoomed);
|
||||
inline bool (*C_Player__IsInTimeShift)(C_Player* thisptr);
|
||||
|
||||
inline void (*C_Player__CurveLook)(C_Player* player, CInput::UserInput_t* input, float a3, float a4, float a5, int a6, float inputSampleFrametime, bool runAimAssist, JoyAngle_t* outAngles);
|
||||
|
||||
|
||||
inline double* double_14D413928;
|
||||
inline double* double_14D4151B8;
|
||||
|
||||
inline int* dword_1423880E0;
|
||||
inline float* dword_16A2A1640;
|
||||
inline void (*C_Player__CurveLook)(C_Player* player, CInput::UserInput_t* input, float a3, float a4, float a5, int a6, float inputSampleFrametime, bool runAimAssist, JoyAngle_t* joyAngle);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class V_Player : public IDetour
|
||||
@ -383,20 +366,6 @@ class V_Player : public IDetour
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 0F 2F 05 ?? ?? ?? ?? 76 ?? 0F 28 CF").FollowNearCallSelf().GetPtr(sub_1408A0600);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 8D 95 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 48 8B 05").FollowNearCallSelf().GetPtr(sub_1405B0E00);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 83 78 ?? ?? 74 ?? 48 8B 05").FollowNearCallSelf().GetPtr(sub_1405AD760);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? FF C8 83 F8").FollowNearCallSelf().GetPtr(sub_14066D190);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? F3 0F 10 35 ?? ?? ?? ?? 0F 28 E7").FollowNearCallSelf().GetPtr(sub_1405AD4E0);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? F3 44 0F 10 26").FollowNearCallSelf().GetPtr(sub_1406257E0);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 45 33 C0 48 8B D7 48 8B CB").FollowNearCallSelf().GetPtr(sub_1405B03A0);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? F3 0F 11 85").FollowNearCallSelf().GetPtr(sub_1405B0BC0);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 8D 35 ?? ?? ?? ?? EB").FollowNearCallSelf().GetPtr(sub_1405AEA10);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? F3 0F 59 3D ?? ?? ?? ?? 41 0F 28 CA").FollowNearCallSelf().GetPtr(sub_1405AF810);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 85 C0 0F 85 ?? ?? ?? ?? 8B 8B").FollowNearCallSelf().GetPtr(sub_1409DC4E0);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? F3 0F 59 B5").FollowNearCallSelf().GetPtr(sub_1405D4300);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? F3 0F 10 85 ?? ?? ?? ?? F3 0F 10 8D ?? ?? ?? ?? F3 0F 11 46").FollowNearCallSelf().GetPtr(sub_1405AF1F0);
|
||||
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 0F 2F 87").FollowNearCallSelf().GetPtr(C_Player__GetZoomFrac);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 83 F8 ?? 74 ?? F2 0F 10 8B").FollowNearCallSelf().GetPtr(C_Player__GetAimSpeed);
|
||||
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 3A D8 75").FollowNearCallSelf().GetPtr(C_Player__IsInTimeShift);
|
||||
@ -404,13 +373,7 @@ class V_Player : public IDetour
|
||||
|
||||
g_GameDll.FindPatternSIMD("48 83 EC ?? 48 8B 01 FF 90 ?? ?? ?? ?? 48 83 C0 ?? 4C 8D 40").GetPtr(C_BaseCombatCharacter__GetActiveWeapon);
|
||||
}
|
||||
virtual void GetVar(void) const
|
||||
{
|
||||
CMemory(C_Player__CurveLook).OffsetSelf(0xFC).FindPatternSelf("F2 0F").ResolveRelativeAddressSelf(4, 8).GetPtr(double_14D413928);
|
||||
CMemory(C_Player__CurveLook).OffsetSelf(0x140).FindPatternSelf("F2 0F").ResolveRelativeAddressSelf(4, 8).GetPtr(double_14D4151B8);
|
||||
CMemory(C_Player__CurveLook).OffsetSelf(0x350).FindPatternSelf("44 8B").ResolveRelativeAddressSelf(3, 7).GetPtr(dword_1423880E0);
|
||||
CMemory(C_Player__CurveLook).OffsetSelf(0x380).FindPatternSelf("48 8D").ResolveRelativeAddressSelf(3, 7).GetPtr(dword_16A2A1640);
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
virtual void GetCon(void) const { }
|
||||
virtual void Detour(const bool bAttach) const;
|
||||
};
|
||||
|
@ -1,5 +1,52 @@
|
||||
#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.
|
||||
|
@ -59,8 +59,10 @@ private:
|
||||
};
|
||||
COMPILE_TIME_ASSERT(sizeof(CClientEntityList) == 0x3800C0);
|
||||
|
||||
inline IClientEntityList* g_pClientEntityList = nullptr;
|
||||
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;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -73,14 +75,18 @@ class VClientEntityList : public IDetour
|
||||
{
|
||||
LogVarAdr("g_clientEntityList", g_clientEntityList);
|
||||
}
|
||||
virtual void GetFun(void) const { }
|
||||
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 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;
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -159,7 +159,7 @@ public:
|
||||
bool m_bUnknownBool1B2;
|
||||
float m_flUnknownFloat1B4;
|
||||
float m_flUnknownFloat1B8;
|
||||
Vector3D m_vecUnknown1BC;
|
||||
QAngle m_angUnknown1BC;
|
||||
QAngle m_angUnknown1C8;
|
||||
bool m_bUnknown1D4;
|
||||
bool m_bUnknown1D5;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#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"
|
||||
@ -81,6 +82,17 @@ 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
|
||||
@ -132,7 +144,7 @@ namespace VScriptCode
|
||||
else
|
||||
{
|
||||
hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str());
|
||||
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
|
||||
sq_pushstring(v, hiddenServerRequestMessage.c_str(), (SQInteger)hiddenServerRequestMessage.length());
|
||||
}
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
@ -145,12 +157,12 @@ namespace VScriptCode
|
||||
else
|
||||
hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str());
|
||||
|
||||
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
|
||||
sq_pushstring(v, hiddenServerRequestMessage.c_str(), (SQInteger)hiddenServerRequestMessage.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
hiddenServerRequestMessage = Format("Found server: %s", serverListing.name.c_str());
|
||||
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
|
||||
sq_pushstring(v, hiddenServerRequestMessage.c_str(), (SQInteger)hiddenServerRequestMessage.length());
|
||||
}
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
@ -170,7 +182,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(), -1);
|
||||
sq_pushstring(v, serverName.c_str(), (SQInteger)serverName.length());
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
@ -189,7 +201,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(), -1);
|
||||
sq_pushstring(v, serverDescription.c_str(), (SQInteger)serverDescription.length());
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
@ -207,8 +219,8 @@ namespace VScriptCode
|
||||
if (!Script_CheckServerIndexAndFailure(v, iServer))
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
|
||||
|
||||
const string& svServerMapName = g_ServerListManager.m_vServerList[iServer].map;
|
||||
sq_pushstring(v, svServerMapName.c_str(), -1);
|
||||
const string& serverMapName = g_ServerListManager.m_vServerList[iServer].map;
|
||||
sq_pushstring(v, serverMapName.c_str(), (SQInteger)serverMapName.length());
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
@ -227,7 +239,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(), -1);
|
||||
sq_pushstring(v, serverPlaylist.c_str(), (SQInteger)serverPlaylist.length());
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
@ -344,14 +356,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(), -1);
|
||||
sq_pushstring(v, eulaData.contents.c_str(), (SQInteger)eulaData.contents.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
string error = Format("Failed to load EULA Data: %s", eulaRequestMessage.c_str());
|
||||
const 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(), -1);
|
||||
sq_pushstring(v, error.c_str(), (SQInteger)error.length());
|
||||
}
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
@ -436,11 +448,52 @@ namespace VScriptCode
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks whether this SDK build is a client dll
|
||||
// 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 IsClientDLL(HSQUIRRELVM v)
|
||||
SQRESULT CreateServer(HSQUIRRELVM v)
|
||||
{
|
||||
sq_pushbool(v, ::IsClientDLL());
|
||||
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;
|
||||
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
}
|
||||
@ -456,6 +509,15 @@ 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 -
|
||||
@ -465,37 +527,34 @@ void Script_RegisterUIFunctions(CSquirrelVM* s)
|
||||
Script_RegisterCommonAbstractions(s);
|
||||
Script_RegisterCoreClientFunctions(s);
|
||||
|
||||
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", "");
|
||||
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", "");
|
||||
|
||||
// Functions for retrieving server browser data
|
||||
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, 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, 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, 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, GetServerMaxPlayers, "Gets the max 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");
|
||||
|
||||
// Misc main menu functions
|
||||
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetPromoData, "Gets promo data for specified slot type", "string", "int");
|
||||
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetEULAContents, "Gets EULA contents from masterserver", "string", "");
|
||||
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", "");
|
||||
|
||||
// Functions for connecting to servers
|
||||
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");
|
||||
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");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Purpose: core client script functions
|
||||
// Input : *s -
|
||||
//---------------------------------------------------------------------------------
|
||||
void Script_RegisterCoreClientFunctions(CSquirrelVM* s)
|
||||
void Script_RegisterUIServerFunctions(CSquirrelVM* s)
|
||||
{
|
||||
DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, IsClientDLL, "Returns whether this build is client only", "bool", "");
|
||||
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", "");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
|
@ -4,6 +4,11 @@
|
||||
namespace VScriptCode
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
SQRESULT IsClientDLL(HSQUIRRELVM v);
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
SQRESULT RefreshServerList(HSQUIRRELVM v);
|
||||
SQRESULT GetServerCount(HSQUIRRELVM v);
|
||||
@ -23,13 +28,12 @@ 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, \
|
||||
@ -37,6 +41,11 @@ 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)();
|
||||
|
@ -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 regardless of table data ( !slower! )");
|
||||
static ConVar navmesh_always_reachable("navmesh_always_reachable", "0", FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable by ignoring static pathing ( !slower! )");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: gets the navmesh by type from global array [small, med_short, medium, large, extra_large]
|
||||
@ -156,19 +156,22 @@ void Detour_HotSwap()
|
||||
Assert(ThreadInMainOrServerFrameThread());
|
||||
g_pServerScript->ExecuteCodeCallback("CodeCallback_OnNavMeshHotSwapBegin");
|
||||
|
||||
const dtNavMesh* queryNav = g_pNavMeshQuery->getAttachedNavMesh();
|
||||
const dtNavMesh* const queryNav = g_pNavMeshQuery->getAttachedNavMesh();
|
||||
NavMeshType_e queryNavType = NAVMESH_INVALID;
|
||||
|
||||
// Figure out which NavMesh type is attached to the global query.
|
||||
for (int i = 0; i < NAVMESH_COUNT; i++)
|
||||
if (queryNav)
|
||||
{
|
||||
const NavMeshType_e in = (NavMeshType_e)i;
|
||||
// Figure out which NavMesh type is attached to the global query.
|
||||
for (int i = 0; i < NAVMESH_COUNT; i++)
|
||||
{
|
||||
const NavMeshType_e in = (NavMeshType_e)i;
|
||||
|
||||
if (queryNav != Detour_GetNavMeshByType(in))
|
||||
continue;
|
||||
if (queryNav != Detour_GetNavMeshByType(in))
|
||||
continue;
|
||||
|
||||
queryNavType = in;
|
||||
break;
|
||||
queryNavType = in;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Free and re-init NavMesh.
|
||||
@ -182,7 +185,7 @@ void Detour_HotSwap()
|
||||
// Attach the new NavMesh to the global Detour query.
|
||||
if (queryNavType != NAVMESH_INVALID)
|
||||
{
|
||||
const dtNavMesh* newQueryNav = Detour_GetNavMeshByType(queryNavType);
|
||||
const dtNavMesh* const newQueryNav = Detour_GetNavMeshByType(queryNavType);
|
||||
|
||||
if (newQueryNav)
|
||||
g_pNavMeshQuery->attachNavMeshUnsafe(newQueryNav);
|
||||
|
@ -120,7 +120,7 @@ private:
|
||||
CTether m_tethers[2];
|
||||
EHANDLE m_titanSoul;
|
||||
Vector3D m_lastFootstepDamagePos;
|
||||
bool m_lastFoostepDamageOnGround;
|
||||
bool m_lastFootstepDamageOnGround;
|
||||
char gap_1781[3];
|
||||
int m_muzzleAttachment[2];
|
||||
int m_weaponHandAttachment;
|
||||
|
@ -168,13 +168,13 @@ void CServerGameClients::_ProcessUserCmds(CServerGameClients* thisp, edict_t edi
|
||||
Assert(numCmds >= 0);
|
||||
Assert((totalCmds - numCmds) >= 0);
|
||||
|
||||
CPlayer* pPlayer = UTIL_PlayerByIndex(edict);
|
||||
CPlayer* const pPlayer = UTIL_PlayerByIndex(edict);
|
||||
|
||||
// Too many commands?
|
||||
if (totalCmds < 0 || totalCmds >= (MAX_BACKUP_COMMANDS_PROCESS - 1) ||
|
||||
numCmds < 0 || numCmds > totalCmds)
|
||||
{
|
||||
CClient* pClient = g_pServer->GetClient(edict-1);
|
||||
const CClient* const pClient = g_pServer->GetClient(edict-1);
|
||||
|
||||
Warning(eDLL_T::SERVER, "%s: Player '%s' sent too many cmds (%i)\n", __FUNCTION__, pClient->GetServerName(), totalCmds);
|
||||
buf->SetOverflowFlag();
|
||||
|
@ -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\".\n", 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\".", 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,8 +406,7 @@ static bool LiveAPI_SetPlayerIdentityFields(HSQUIRRELVM const v, const SQTable*
|
||||
if (sq_isnull(node.key))
|
||||
continue;
|
||||
|
||||
if (!ranLoop)
|
||||
ranLoop = true;
|
||||
ranLoop = true;
|
||||
|
||||
if (!LiveAPI_CheckSwitchType(v, node.key))
|
||||
return false;
|
||||
@ -537,8 +536,7 @@ static bool LiveAPI_SetInventoryItem(HSQUIRRELVM const v, const SQTable* const t
|
||||
if (sq_isnull(node.key))
|
||||
continue;
|
||||
|
||||
if (!ranLoop)
|
||||
ranLoop = true;
|
||||
ranLoop = true;
|
||||
|
||||
if (!LiveAPI_CheckSwitchType(v, node.key))
|
||||
return false;
|
||||
@ -1792,8 +1790,7 @@ static bool LiveAPI_SetCustomArrayFields(HSQUIRRELVM const v, google::protobuf::
|
||||
if (sq_isnull(valueObj))
|
||||
continue;
|
||||
|
||||
if (!ranLoop)
|
||||
ranLoop = true;
|
||||
ranLoop = true;
|
||||
|
||||
const SQObjectType valueType = sq_type(valueObj);
|
||||
|
||||
@ -1857,8 +1854,7 @@ static bool LiveAPI_SetCustomTableFields(HSQUIRRELVM const v, google::protobuf::
|
||||
if (sq_isnull(node.key))
|
||||
continue;
|
||||
|
||||
if (!ranLoop)
|
||||
ranLoop = true;
|
||||
ranLoop = true;
|
||||
|
||||
const SQObjectType keyType = sq_type(node.key);
|
||||
|
||||
|
@ -24,13 +24,11 @@ void Physics_RunBotSimulation(bool bSimulating)
|
||||
|
||||
for (int i = 0; i < g_ServerGlobalVariables->maxClients; i++)
|
||||
{
|
||||
CClient* pClient = g_pServer->GetClient(i);
|
||||
if (!pClient)
|
||||
continue;
|
||||
const CClient* const pClient = g_pServer->GetClient(i);
|
||||
|
||||
if (pClient->IsActive() && pClient->IsFakeClient())
|
||||
{
|
||||
CPlayer* pPlayer = UTIL_PlayerByIndex(pClient->GetHandle());
|
||||
CPlayer* const pPlayer = UTIL_PlayerByIndex(pClient->GetHandle());
|
||||
if (pPlayer)
|
||||
pPlayer->RunNullCommand();
|
||||
}
|
||||
|
@ -258,23 +258,19 @@ static void CC_CreateFakePlayer_f(const CCommand& args)
|
||||
if (numPlayers >= g_ServerGlobalVariables->maxClients)
|
||||
return;
|
||||
|
||||
const char* playerName = args.Arg(1);
|
||||
const char* const playerName = args.Arg(1);
|
||||
const int teamNum = atoi(args.Arg(2));
|
||||
|
||||
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);
|
||||
// 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();
|
||||
|
||||
// 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);
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "liveapi/liveapi.h"
|
||||
#include "vscript_server.h"
|
||||
#include <engine/host_state.h>
|
||||
#include <networksystem/hostmanager.h>
|
||||
#include "player.h"
|
||||
#include <common/callback.h>
|
||||
|
||||
@ -42,61 +41,6 @@ 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
|
||||
@ -268,75 +212,6 @@ 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
|
||||
@ -365,7 +240,7 @@ namespace VScriptCode
|
||||
|
||||
if (!VALID_CHARSTAR(val))
|
||||
{
|
||||
v_SQVM_ScriptError("Empty or null class var");
|
||||
v_SQVM_ScriptError("Empty or null class value");
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
|
||||
}
|
||||
|
||||
@ -405,7 +280,7 @@ void Script_RegisterServerFunctions(CSquirrelVM* s)
|
||||
{
|
||||
Script_RegisterCommonAbstractions(s);
|
||||
Script_RegisterCoreServerFunctions(s);
|
||||
Script_RegisterAdminPanelFunctions(s);
|
||||
Script_RegisterAdminServerFunctions(s);
|
||||
|
||||
Script_RegisterLiveAPIFunctions(s);
|
||||
}
|
||||
@ -421,28 +296,15 @@ 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 panel script functions
|
||||
// Purpose: admin server 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_RegisterAdminPanelFunctions(CSquirrelVM* s)
|
||||
void Script_RegisterAdminServerFunctions(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", "");
|
||||
|
@ -29,7 +29,7 @@ namespace VScriptCode
|
||||
|
||||
void Script_RegisterServerFunctions(CSquirrelVM* s);
|
||||
void Script_RegisterCoreServerFunctions(CSquirrelVM* s);
|
||||
void Script_RegisterAdminPanelFunctions(CSquirrelVM* s);
|
||||
void Script_RegisterAdminServerFunctions(CSquirrelVM* s);
|
||||
|
||||
void Script_RegisterServerEnums(CSquirrelVM* const s);
|
||||
|
||||
|
@ -27,7 +27,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetSDKVersion(HSQUIRRELVM v)
|
||||
{
|
||||
sq_pushstring(v, SDK_VERSION, -1);
|
||||
sq_pushstring(v, SDK_VERSION, sizeof(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(), -1);
|
||||
sq_pushstring(v, mapName.String(), (SQInteger)mapName.Length());
|
||||
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(), -1);
|
||||
sq_pushstring(v, it.String(), (SQInteger)it.Length());
|
||||
sq_arrayappend(v, -2);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ 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)
|
||||
{
|
||||
@ -57,7 +58,8 @@ CBrowser::CBrowser(void)
|
||||
memset(m_serverAddressTextBuf, '\0', sizeof(m_serverAddressTextBuf));
|
||||
memset(m_serverNetKeyTextBuf, '\0', sizeof(m_serverNetKeyTextBuf));
|
||||
|
||||
m_lockedIconDataResource = GetModuleResource(IDB_PNG2);
|
||||
m_levelName = "mp_lobby";
|
||||
m_gameMode = "dev_default";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -75,7 +77,10 @@ bool CBrowser::Init(void)
|
||||
{
|
||||
SetStyleVar(927.f, 524.f, -500.f, 50.f);
|
||||
|
||||
bool ret = LoadTextureBuffer(reinterpret_cast<unsigned char*>(m_lockedIconDataResource.m_pData), int(m_lockedIconDataResource.m_nSize),
|
||||
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),
|
||||
&m_lockedIconShaderResource, &m_lockedIconDataResource.m_nWidth, &m_lockedIconDataResource.m_nHeight);
|
||||
|
||||
IM_ASSERT(ret && m_lockedIconShaderResource);
|
||||
@ -188,6 +193,9 @@ void CBrowser::RunTask()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBrowser::DrawSurface(void)
|
||||
{
|
||||
if (!IsVisible())
|
||||
return false;
|
||||
|
||||
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_None, &ResetInput))
|
||||
{
|
||||
ImGui::End();
|
||||
@ -273,9 +281,9 @@ void CBrowser::DrawBrowserPanel(void)
|
||||
const char* pszHostMap = server.map.c_str();
|
||||
const char* pszPlaylist = server.playlist.c_str();
|
||||
|
||||
if (m_serverBrowserTextFilter.PassFilter(pszHostName)
|
||||
|| m_serverBrowserTextFilter.PassFilter(pszHostMap)
|
||||
|| m_serverBrowserTextFilter.PassFilter(pszPlaylist))
|
||||
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()]))
|
||||
{
|
||||
filteredServers.push_back(&server);
|
||||
}
|
||||
@ -289,28 +297,32 @@ void CBrowser::DrawBrowserPanel(void)
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
|
||||
{
|
||||
const NetGameServer_t* const server = filteredServers[i];
|
||||
|
||||
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);
|
||||
const ImGuiTextFlags textFlags = ImGuiTextFlags_NoWidthForLargeClippedText;
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", pszHostName);
|
||||
|
||||
const char* const pszHostName = server->name.c_str();
|
||||
ImGui::TextEx(pszHostName, &pszHostName[server->name.length()], textFlags);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", pszHostMap);
|
||||
|
||||
const char* const pszHostMap = server->map.c_str();
|
||||
ImGui::TextEx(pszHostMap, &pszHostMap[server->map.length()], textFlags);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", pszPlaylist);
|
||||
|
||||
const char* const pszPlaylist = server->playlist.c_str();
|
||||
ImGui::TextEx(pszPlaylist, &pszPlaylist[server->playlist.length()], textFlags);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", Format("%3d/%3d", server->numPlayers, server->maxPlayers).c_str());
|
||||
|
||||
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::TableNextColumn();
|
||||
ImGui::Text("%s", pszHostPort);
|
||||
ImGui::Text("%d", server->port);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
string svConnectBtn = "Connect##";
|
||||
@ -517,47 +529,71 @@ 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
|
||||
NetGameServer_t& details = g_ServerHostManager.GetDetails();
|
||||
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());
|
||||
}
|
||||
|
||||
ImGui::InputTextWithHint("##ServerHost_ServerName", "Server name (required)", &details.name);
|
||||
ImGui::InputTextWithHint("##ServerHost_ServerDesc", "Server description (optional)", &details.description);
|
||||
ImGui::Spacing();
|
||||
|
||||
const char* const selectedPlaylists = details.playlist.c_str();
|
||||
|
||||
if (ImGui::BeginCombo("Mode", selectedPlaylists))
|
||||
if (ImGui::BeginCombo("Mode", m_gameMode.c_str()))
|
||||
{
|
||||
for (const CUtlString& svPlaylist : g_vecAllPlaylists)
|
||||
for (const CUtlString& playlist : g_vecAllPlaylists)
|
||||
{
|
||||
const char* const cachedPlaylists = svPlaylist.String();
|
||||
const char* const cachedPlaylists = playlist.String();
|
||||
|
||||
if (ImGui::Selectable(cachedPlaylists, (strcmp(cachedPlaylists, selectedPlaylists) == 0)))
|
||||
if (ImGui::Selectable(cachedPlaylists,
|
||||
playlist.IsEqual_CaseInsensitive(m_gameMode.c_str())))
|
||||
{
|
||||
details.playlist = svPlaylist;
|
||||
m_gameMode = cachedPlaylists;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Map", details.map.c_str()))
|
||||
if (ImGui::BeginCombo("Map", m_levelName.c_str()))
|
||||
{
|
||||
g_InstalledMapsMutex.Lock();
|
||||
|
||||
FOR_EACH_VEC(g_InstalledMaps, i)
|
||||
for (const CUtlString& mapName : g_InstalledMaps)
|
||||
{
|
||||
const CUtlString& mapName = g_InstalledMaps[i];
|
||||
const char* const cachedMapName = mapName.String();
|
||||
|
||||
if (ImGui::Selectable(mapName.String(),
|
||||
mapName.IsEqual_CaseInsensitive(details.map.c_str())))
|
||||
if (ImGui::Selectable(cachedMapName,
|
||||
mapName.IsEqual_CaseInsensitive(m_levelName.c_str())))
|
||||
{
|
||||
details.map = mapName.String();
|
||||
m_levelName = cachedMapName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,37 +635,22 @@ 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();
|
||||
|
||||
const bool enforceField = g_ServerHostManager.GetVisibility() == ServerVisibility_e::OFFLINE
|
||||
? true
|
||||
: !details.name.empty();
|
||||
|
||||
if (enforceField && !details.playlist.empty() && !details.map.empty())
|
||||
if (hasName && !m_levelName.empty() && !m_gameMode.empty())
|
||||
{
|
||||
g_ServerHostManager.LaunchServer(serverActive); // Launch server.
|
||||
g_ServerHostManager.LaunchServer(m_levelName.c_str(), m_gameMode.c_str()); // Launch server.
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
HandleInvalidFields(isOffline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -654,12 +675,14 @@ void CBrowser::DrawHostPanel(void)
|
||||
|
||||
if (ImGui::Button("Change level", ImVec2(contentRegionMax.x, 32)))
|
||||
{
|
||||
if (!details.map.empty())
|
||||
if (!m_levelName.empty() && !m_gameMode.empty())
|
||||
{
|
||||
g_ServerHostManager.LaunchServer(serverActive);
|
||||
g_ServerHostManager.ChangeLevel(m_levelName.c_str(), m_gameMode.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleInvalidFields(isOffline);
|
||||
|
||||
m_hostMessage = "Failed to change level: 'levelname' was empty.";
|
||||
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
|
||||
}
|
||||
@ -783,37 +806,23 @@ 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;
|
||||
}
|
||||
|
||||
if (*g_nServerRemoteChecksum == NULL) // Check if script checksum is valid yet.
|
||||
NetGameServer_t netGameServer
|
||||
{
|
||||
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,
|
||||
hostname->GetString(),
|
||||
hostdesc.GetString(),
|
||||
serverVisibility == ServerVisibility_e::HIDDEN,
|
||||
g_pHostState->m_levelName,
|
||||
v_Playlists_GetCurrent(),
|
||||
hostip->GetString(),
|
||||
@ -842,10 +851,10 @@ void CBrowser::UpdateHostingStatus(void)
|
||||
// host data on the server browser
|
||||
// Input : &gameServer -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBrowser::SendHostingPostRequest(const NetGameServer_t& gameServer)
|
||||
void CBrowser::SendHostingPostRequest(NetGameServer_t& gameServer)
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
std::thread request([&, gameServer]
|
||||
std::thread request([&, gameServer = std::move(gameServer)]
|
||||
{
|
||||
string hostRequestMessage;
|
||||
string hostToken;
|
||||
@ -855,7 +864,7 @@ void CBrowser::SendHostingPostRequest(const NetGameServer_t& gameServer)
|
||||
|
||||
g_TaskQueue.Dispatch([&, result, hostRequestMessage, hostToken, hostIp]
|
||||
{
|
||||
InstallHostingDetails(result, hostRequestMessage.c_str(), hostToken.c_str(), hostIp);
|
||||
InstallHostingDetails(result, hostRequestMessage, hostToken, hostIp);
|
||||
}, 0);
|
||||
}
|
||||
);
|
||||
@ -870,7 +879,7 @@ void CBrowser::SendHostingPostRequest(const NetGameServer_t& gameServer)
|
||||
// *hostToken -
|
||||
// &hostIp -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBrowser::InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp)
|
||||
void CBrowser::InstallHostingDetails(const bool postFailed, const string& hostMessage, const string& hostToken, const string& hostIp)
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
m_hostMessage = hostMessage;
|
||||
@ -884,14 +893,10 @@ void CBrowser::InstallHostingDetails(const bool postFailed, const char* const ho
|
||||
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 = ssMessage.str();
|
||||
m_hostMessage = m_hostToken.empty()
|
||||
? "Broadcasting"
|
||||
: "Broadcasting: share the following token for clients to connect: ";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -26,11 +26,13 @@ public:
|
||||
void RefreshServerList(void);
|
||||
|
||||
void HiddenServersModal(void);
|
||||
|
||||
void HandleInvalidFields(const bool offline);
|
||||
void DrawHostPanel(void);
|
||||
|
||||
void UpdateHostingStatus(void);
|
||||
void InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp);
|
||||
void SendHostingPostRequest(const NetGameServer_t& gameServer);
|
||||
void InstallHostingDetails(const bool postFailed, const string& hostMessage, const string& hostToken, const string& hostIp);
|
||||
void SendHostingPostRequest(NetGameServer_t& gameServer);
|
||||
|
||||
void ProcessCommand(const char* pszCommand) const;
|
||||
|
||||
@ -72,6 +74,12 @@ private:
|
||||
////////////////////
|
||||
string m_hiddenServerRequestMessage;
|
||||
ImVec4 m_hiddenServerMessageColor;
|
||||
|
||||
string m_serverName;
|
||||
string m_serverDescription;
|
||||
|
||||
string m_levelName;
|
||||
string m_gameMode;
|
||||
};
|
||||
|
||||
extern CBrowser g_Browser;
|
||||
|
@ -22,6 +22,7 @@ History:
|
||||
#include "windows/resource.h"
|
||||
#include "engine/cmd.h"
|
||||
#include "gameui/IConsole.h"
|
||||
#include "imgui_system.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Console variables
|
||||
@ -128,8 +129,6 @@ 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
|
||||
@ -139,9 +138,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();
|
||||
@ -187,6 +186,9 @@ void CConsole::RunFrame(void)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CConsole::DrawSurface(void)
|
||||
{
|
||||
if (!IsVisible())
|
||||
return false;
|
||||
|
||||
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_None, &ResetInput))
|
||||
{
|
||||
ImGui::End();
|
||||
@ -279,20 +281,6 @@ 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 |
|
||||
@ -310,18 +298,19 @@ bool CConsole::DrawSurface(void)
|
||||
// command from that instead
|
||||
if (m_suggestPos > ConAutoCompletePos_e::kPark)
|
||||
{
|
||||
DetermineInputTextFromSelectedSuggestion(m_vecSuggest[m_suggestPos], m_selectedSuggestionText);
|
||||
BuildSummaryText(m_selectedSuggestionText.c_str());
|
||||
|
||||
m_inputTextBufModified = true;
|
||||
m_reclaimFocus = true;
|
||||
HandleSuggest();
|
||||
}
|
||||
else
|
||||
{
|
||||
fnHandleInput();
|
||||
HandleCommand();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Tab))
|
||||
{
|
||||
HandleSuggest();
|
||||
}
|
||||
|
||||
// Auto-focus input field on window apparition.
|
||||
ImGui::SetItemDefaultFocus();
|
||||
|
||||
@ -337,7 +326,7 @@ bool CConsole::DrawSurface(void)
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Submit"))
|
||||
{
|
||||
fnHandleInput();
|
||||
HandleCommand();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
@ -352,43 +341,176 @@ void CConsole::DrawOptionsPanel(void)
|
||||
ImGui::Checkbox("Auto-scroll", &m_colorTextLogger.m_bAutoScroll);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(100);
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (ImGui::SmallButton("Clear"))
|
||||
if (ImGui::SmallButton("Clear Text"))
|
||||
{
|
||||
ClearLog();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Copies all logged text to the clip board
|
||||
if (ImGui::SmallButton("Copy"))
|
||||
if (ImGui::SmallButton("Copy Text"))
|
||||
{
|
||||
AUTO_LOCK(m_colorTextLoggerMutex);
|
||||
m_colorTextLogger.Copy(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Console hotkey:");
|
||||
ImGui::TextEx("Console HotKey:", nullptr, ImGuiTextFlags_NoWidthForLargeClippedText);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Hotkey("##ToggleConsole", &g_ImGuiConfig.m_ConsoleConfig.m_nBind0, ImVec2(80, 80)))
|
||||
int selected = g_ImGuiConfig.m_ConsoleConfig.m_nBind0;
|
||||
|
||||
if (ImGui::Hotkey("##ToggleConsolePrimary", &selected, ImVec2(80, 80)) &&
|
||||
!g_ImGuiConfig.KeyUsed(selected))
|
||||
{
|
||||
g_ImGuiConfig.m_ConsoleConfig.m_nBind0 = selected;
|
||||
g_ImGuiConfig.Save();
|
||||
}
|
||||
|
||||
ImGui::Text("Browser hotkey:");
|
||||
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::SameLine();
|
||||
|
||||
if (ImGui::Hotkey("##ToggleBrowser", &g_ImGuiConfig.m_BrowserConfig.m_nBind0, ImVec2(80, 80)))
|
||||
selected = g_ImGuiConfig.m_BrowserConfig.m_nBind0;
|
||||
|
||||
if (ImGui::Hotkey("##ToggleBrowserPrimary", &selected, ImVec2(80, 80)) &&
|
||||
!g_ImGuiConfig.KeyUsed(selected))
|
||||
{
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -433,16 +555,6 @@ 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;
|
||||
|
||||
@ -453,12 +565,12 @@ void CConsole::DrawAutoCompletePanel(void)
|
||||
if (suggest.flags & info.bit)
|
||||
{
|
||||
isFlagSet = true;
|
||||
fnAddHint(info);
|
||||
AddHint(info, m_vecFlagIcons);
|
||||
}
|
||||
}
|
||||
if (!isFlagSet) // Display the FCVAR_NONE flag if no flags are set.
|
||||
{
|
||||
fnAddHint(g_ConVarFlags.m_FlagsToDesc[0]);
|
||||
AddHint(g_ConVarFlags.m_FlagsToDesc[0], m_vecFlagIcons);
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
@ -478,7 +590,7 @@ void CConsole::DrawAutoCompletePanel(void)
|
||||
m_canAutoComplete = true;
|
||||
m_reclaimFocus = true;
|
||||
|
||||
BuildSummaryText(newInputText.c_str());
|
||||
BuildSummaryText(newInputText.c_str(), newInputText.size());
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@ -553,7 +665,7 @@ bool CConsole::RunAutoComplete(void)
|
||||
{
|
||||
const char c = m_inputTextBuf[i];
|
||||
|
||||
if (c == '\0' || isspace(c))
|
||||
if (c == '\0' || V_isspace(c))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -576,7 +688,8 @@ bool CConsole::RunAutoComplete(void)
|
||||
|
||||
for (int j = 0; j < iret; ++j)
|
||||
{
|
||||
m_vecSuggest.push_back(ConAutoCompleteSuggest_s(commands[j].String(), COMMAND_COMPLETION_MARKER));
|
||||
const CUtlString& cmdToAdd = commands[j];
|
||||
m_vecSuggest.emplace_back(cmdToAdd.String(), cmdToAdd.Length(), COMMAND_COMPLETION_MARKER);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -606,6 +719,40 @@ 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
|
||||
@ -641,30 +788,18 @@ void CConsole::CreateSuggestionsFromPartial(void)
|
||||
{
|
||||
string docString;
|
||||
|
||||
// Assign current value to string if its a ConVar.
|
||||
if (!commandBase->IsCommand())
|
||||
{
|
||||
const ConVar* conVar = reinterpret_cast<const ConVar*>(commandBase);
|
||||
|
||||
docString = " = ["; // Assign current value to string if its a ConVar.
|
||||
docString.append(conVar->GetString());
|
||||
docString.append("]");
|
||||
const ConVar* const conVar = reinterpret_cast<const ConVar*>(commandBase);
|
||||
AppendValueString(docString, conVar->GetString());
|
||||
}
|
||||
if (con_suggest_helptext.GetBool())
|
||||
{
|
||||
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());
|
||||
AppendDocString(docString, commandBase->GetHelpText());
|
||||
AppendDocString(docString, commandBase->GetUsageText());
|
||||
}
|
||||
m_vecSuggest.push_back(ConAutoCompleteSuggest_s(commandName + docString, commandBase->GetFlags()));
|
||||
m_vecSuggest.emplace_back(commandName + docString, commandBase->GetFlags());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -704,11 +839,11 @@ void CConsole::ProcessCommand(const char* const inputText)
|
||||
// formats the number of history items instead
|
||||
// Input : inputText -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConsole::BuildSummaryText(const char* const inputText)
|
||||
void CConsole::BuildSummaryText(const char* const inputText, const size_t textLen)
|
||||
{
|
||||
if (*inputText)
|
||||
if (textLen > 0)
|
||||
{
|
||||
string conVarFormatted(inputText);
|
||||
string conVarFormatted(inputText, textLen);
|
||||
|
||||
// Remove trailing space and/or semicolon before we call 'g_pCVar->FindVar(..)'.
|
||||
StringRTrim(conVarFormatted, " ;", true);
|
||||
@ -789,117 +924,25 @@ 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.push_back(MODULERESOURCE(GetModuleResource(i)));
|
||||
m_vecFlagIcons.emplace_back(GetModuleResource(sdkModule, 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);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
Assert(0, "Texture flags load failed for %i", i);
|
||||
break;
|
||||
}
|
||||
Assert(ret, "Texture flags load failed for %i", i);
|
||||
}
|
||||
|
||||
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 -
|
||||
@ -990,7 +1033,7 @@ int CConsole::TextEditCallback(ImGuiInputTextCallbackData* iData)
|
||||
}
|
||||
}
|
||||
|
||||
BuildSummaryText(iData->Buf);
|
||||
BuildSummaryText(iData->Buf, iData->BufTextLen);
|
||||
break;
|
||||
}
|
||||
case ImGuiInputTextFlags_CallbackAlways:
|
||||
@ -1055,7 +1098,7 @@ int CConsole::TextEditCallback(ImGuiInputTextCallbackData* iData)
|
||||
ResetAutoCompleteData();
|
||||
}
|
||||
|
||||
BuildSummaryText(iData->Buf);
|
||||
BuildSummaryText(iData->Buf, iData->BufTextLen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1074,6 +1117,50 @@ 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
|
||||
@ -1082,6 +1169,11 @@ int CConsole::TextEditCallbackStub(ImGuiInputTextCallbackData* iData)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConsole::AddLog(const char* const text, const ImU32 color)
|
||||
{
|
||||
if (!ImguiSystem()->IsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AUTO_LOCK(m_colorTextLoggerMutex);
|
||||
|
||||
m_colorTextLogger.InsertText(text, color);
|
||||
@ -1185,7 +1277,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.push_back' elsewhere as we
|
||||
// is added to the vector, do not call 'm_History.emplace_back' elsewhere as we
|
||||
// also manage the size of the vector here !!!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConsole::AddHistory(const char* const command)
|
||||
@ -1201,7 +1293,7 @@ void CConsole::AddHistory(const char* const command)
|
||||
}
|
||||
}
|
||||
|
||||
m_vecHistory.push_back(command);
|
||||
m_vecHistory.emplace_back(command);
|
||||
ClampHistorySize();
|
||||
}
|
||||
|
||||
@ -1220,7 +1312,7 @@ const vector<string>& CConsole::GetHistory(void) const
|
||||
void CConsole::ClearHistory(void)
|
||||
{
|
||||
m_vecHistory.clear();
|
||||
BuildSummaryText("");
|
||||
BuildSummaryText("", 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -30,14 +30,13 @@ private:
|
||||
void CreateSuggestionsFromPartial(void);
|
||||
void ProcessCommand(const char* const inputText);
|
||||
|
||||
void BuildSummaryText(const char* const inputText);
|
||||
void BuildSummaryText(const char* const inputText, const size_t textLen);
|
||||
|
||||
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);
|
||||
@ -61,6 +60,9 @@ 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);
|
||||
@ -69,7 +71,8 @@ private: // Internals.
|
||||
private:
|
||||
enum ConAutoCompletePos_e
|
||||
{
|
||||
// Park means the position is out of screen.
|
||||
// Park means the auto complete position is out of screen and not
|
||||
// indexing an item.
|
||||
kPark = -1,
|
||||
};
|
||||
|
||||
@ -80,6 +83,11 @@ 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;
|
||||
|
218
src/gameui/IStreamOverlay.cpp
Normal file
218
src/gameui/IStreamOverlay.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/******************************************************************************
|
||||
-------------------------------------------------------------------------------
|
||||
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);
|
||||
}
|
36
src/gameui/IStreamOverlay.h
Normal file
36
src/gameui/IStreamOverlay.h
Normal file
@ -0,0 +1,36 @@
|
||||
#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;
|
@ -23,8 +23,8 @@ public:
|
||||
// inlines:
|
||||
inline void ToggleActive() { m_activated ^= true; }
|
||||
|
||||
inline bool IsActivated() { return m_activated; }
|
||||
inline bool IsVisible() { return m_fadeAlpha > 0.0f; }
|
||||
inline bool IsActivated() const { return m_activated; }
|
||||
inline bool IsVisible() const { return m_fadeAlpha > 0.0f; }
|
||||
|
||||
protected:
|
||||
const char* m_surfaceLabel;
|
||||
|
@ -8,17 +8,16 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -28,14 +27,19 @@ CImguiSystem::CImguiSystem()
|
||||
bool CImguiSystem::Init()
|
||||
{
|
||||
Assert(ThreadInMainThread(), "CImguiSystem::Init() should only be called from the main thread!");
|
||||
Assert(m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT, "CImguiSystem::Init() called recursively?");
|
||||
Assert(!IsInitialized(), "CImguiSystem::Init() called recursively?");
|
||||
|
||||
Assert(IsEnabled(), "CImguiSystem::Init() called while system was disabled!");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGuiContext* const context = ImGui::CreateContext();
|
||||
|
||||
if (!context)
|
||||
{
|
||||
m_enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
AUTO_LOCK(m_snapshotBufferMutex);
|
||||
AUTO_LOCK(m_inputEventQueueMutex);
|
||||
@ -56,11 +60,13 @@ bool CImguiSystem::Init()
|
||||
{
|
||||
Assert(0);
|
||||
|
||||
m_systemInitState = ImguiSystemInitStage_e::IM_INIT_FAILURE;
|
||||
m_enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_systemInitState = ImguiSystemInitStage_e::IM_SYSTEM_INIT;
|
||||
m_initialized = true;
|
||||
m_hasNewFrame = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -70,23 +76,66 @@ bool CImguiSystem::Init()
|
||||
void CImguiSystem::Shutdown()
|
||||
{
|
||||
Assert(ThreadInMainThread(), "CImguiSystem::Shutdown() should only be called from the main thread!");
|
||||
Assert(m_systemInitState != ImguiSystemInitStage_e::IM_PENDING_INIT, "CImguiSystem::Shutdown() called recursively?");
|
||||
Assert(IsInitialized(), "CImguiSystem::Shutdown() called recursively?");
|
||||
|
||||
// Nothing to shutdown.
|
||||
if (m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT)
|
||||
return;
|
||||
Assert(IsEnabled(), "CImguiSystem::Shutdown() called while system was disabled!");
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -97,48 +146,19 @@ void CImguiSystem::Shutdown()
|
||||
void CImguiSystem::SwapBuffers()
|
||||
{
|
||||
Assert(ThreadInMainThread(), "CImguiSystem::SwapBuffers() should only be called from the main thread!");
|
||||
Assert(IsInitialized());
|
||||
|
||||
if (m_systemInitState < ImguiSystemInitStage_e::IM_FRAME_SAMPLED)
|
||||
ImDrawData* const drawData = ImGui::GetDrawData();
|
||||
Assert(drawData);
|
||||
|
||||
// Nothing has been drawn, nothing to swap.
|
||||
if (!drawData->CmdListsCount)
|
||||
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());
|
||||
|
||||
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;
|
||||
m_hasNewFrame = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -146,16 +166,27 @@ void CImguiSystem::SampleFrame()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CImguiSystem::RenderFrame()
|
||||
{
|
||||
if (m_systemInitState < ImguiSystemInitStage_e::IM_FRAME_SWAPPED)
|
||||
Assert(IsInitialized());
|
||||
|
||||
if (!m_hasNewFrame.exchange(false))
|
||||
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)
|
||||
{
|
||||
AUTO_LOCK(m_snapshotBufferMutex);
|
||||
ImGui_ImplDX11_RenderDrawData(&m_snapshotData.DrawData);
|
||||
if (m_surfaceList[i]->IsActivated())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_systemInitState == ImguiSystemInitStage_e::IM_FRAME_SAMPLED)
|
||||
m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_RENDERED;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -163,6 +194,9 @@ void CImguiSystem::RenderFrame()
|
||||
//-----------------------------------------------------------------------------
|
||||
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);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef IMGUI_SYSTEM_H
|
||||
#define IMGUI_SYSTEM_H
|
||||
#include "imgui/misc/imgui_snapshot.h"
|
||||
#include "imgui_surface.h"
|
||||
|
||||
class CImguiSystem
|
||||
{
|
||||
@ -15,54 +16,47 @@ 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 IsInitialized() const
|
||||
{
|
||||
return m_systemInitState >= ImguiSystemInitStage_e::IM_SYSTEM_INIT;
|
||||
};
|
||||
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; }
|
||||
|
||||
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 CThreadFastMutex m_snapshotBufferMutex;
|
||||
mutable CThreadMutex 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 CThreadFastMutex m_inputEventQueueMutex;
|
||||
mutable CThreadMutex m_inputEventQueueMutex;
|
||||
|
||||
bool m_enabled;
|
||||
bool m_initialized;
|
||||
|
||||
std::atomic_bool m_hasNewFrame;
|
||||
};
|
||||
|
||||
CImguiSystem* ImguiSystem();
|
||||
|
@ -31,16 +31,30 @@ InputContextHandle_t CInputStackSystem::PushInputContext()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pops the top input context off the input stack, and destroys it.
|
||||
// Pops the provided input context off the input stack, and destroys it.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInputStackSystem::PopInputContext( InputContextHandle_t hContext )
|
||||
void CInputStackSystem::PopInputContext( InputContextHandle_t& hContext )
|
||||
{
|
||||
if ( m_ContextStack.Count() == 0 )
|
||||
const int nCount = m_ContextStack.Count();
|
||||
|
||||
if ( nCount == 0 )
|
||||
return;
|
||||
|
||||
InputContext_t *pContext = NULL;
|
||||
m_ContextStack.Pop( pContext );
|
||||
delete pContext;
|
||||
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;
|
||||
|
||||
UpdateCursorState();
|
||||
}
|
||||
@ -202,36 +216,35 @@ void CInputStackSystem::UpdateCursorState()
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get dependencies
|
||||
//-----------------------------------------------------------------------------
|
||||
//static AppSystemInfo_t s_Dependencies[] =
|
||||
//{
|
||||
// { "inputsystem" DLL_EXT_STRING, INPUTSYSTEM_INTERFACE_VERSION },
|
||||
// { NULL, NULL }
|
||||
//};
|
||||
//
|
||||
//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();
|
||||
//}
|
||||
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 }
|
||||
};
|
||||
|
||||
const AppSystemInfo_t* CInputStackSystem::GetDependencies()
|
||||
{
|
||||
return s_Dependencies;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Singleton instance
|
||||
|
@ -30,18 +30,14 @@ 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 const AppSystemInfo_t* GetDependencies();
|
||||
//virtual void Shutdown();
|
||||
virtual void Shutdown();
|
||||
virtual const AppSystemInfo_t* GetDependencies();
|
||||
|
||||
// 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 );
|
||||
@ -56,6 +52,13 @@ 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;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -11,17 +11,16 @@
|
||||
// The executable exports table has been restructured; the exported function
|
||||
// 'GetDenuvoTimeTicketRequest' has been swapped with 'CreateGlobalMemAlloc',
|
||||
// the exported 'IEngineAPI' interface accessor has been replaced with
|
||||
// 'g_pMemAllocSingleton', and the exported function 'LauncherMain' has been
|
||||
// swapped with 'WinMain', so we can obtain the addresses without hardcoding.
|
||||
// 'g_pMemAllocSingleton', so we can obtain the addresses without hardcoding.
|
||||
//
|
||||
// These changes allow us to load the SDK in the following order:
|
||||
// - Create game process
|
||||
// - Import this loader stub by its dummy export.
|
||||
// - Immediately hook 'WinMain', by getting a pointer to it from its exports.
|
||||
// - Immediately hook 'LauncherMain' by getting the address from the exports.
|
||||
// - Determine if, and which SDK module to load.
|
||||
//
|
||||
// Since WinMain is called before anything of the game is, we can still hook
|
||||
// and modify anything of the game before it starts. With the above order of
|
||||
// Since LauncherMain is called before anything of the game is, we can still
|
||||
// hook and modify anything of the game before it starts. With this order of
|
||||
// initialization, we can now replace the standard memalloc system with that
|
||||
// of the game, by:
|
||||
//
|
||||
|
@ -10,6 +10,8 @@ add_sources( SOURCE_GROUP "Private"
|
||||
"cmaterialsystem.h"
|
||||
"cshaderglue.cpp"
|
||||
"cshaderglue.h"
|
||||
"texturestreaming.cpp"
|
||||
"texturestreaming.h"
|
||||
)
|
||||
|
||||
add_sources( SOURCE_GROUP "Public"
|
||||
|
@ -5,75 +5,89 @@
|
||||
#include "public/materialsystem/shader_vcs_version.h"
|
||||
#include "public/rendersystem/schema/texture.g.h"
|
||||
|
||||
struct MaterialDXState_t
|
||||
#define MATERIAL_RENDER_PARAMS_COUNT 2 // the same for r2 and r5
|
||||
#define MATERIAL_SAMPLER_COUNT 4
|
||||
|
||||
class CMaterialGlue;
|
||||
|
||||
enum MaterialDepthPass_e
|
||||
{
|
||||
uint32_t blendState[8];
|
||||
unsigned int unkFlags;
|
||||
unsigned __int16 depthStencilFlags;
|
||||
unsigned __int16 rasterizerFlags;
|
||||
char pad[8];
|
||||
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;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
class CMaterialGlue : public IMaterialInternal
|
||||
{
|
||||
public:
|
||||
uint8_t pad_0008[8]; //0x0008
|
||||
uint64_t assetGuid; //0x0010
|
||||
const char* name; //0x0018
|
||||
inline const MaterialGlue_s* Get() const { return &material; }
|
||||
inline MaterialGlue_s* Get() { return &material; }
|
||||
|
||||
const char* surfaceProp; //0x0020
|
||||
const char* surfaceProp2; //0x0028
|
||||
private:
|
||||
byte reserved[8];
|
||||
MaterialGlue_s material;
|
||||
|
||||
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;
|
||||
|
@ -15,8 +15,10 @@
|
||||
#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"
|
||||
|
||||
@ -45,10 +47,10 @@ static bool s_useLowLatency = false;
|
||||
InitReturnVal_t CMaterialSystem::Init(CMaterialSystem* thisptr)
|
||||
{
|
||||
#ifdef MATERIALSYSTEM_NODX
|
||||
// Only load the 'startup.rpak' file, as 'common_early.rpak' has assets
|
||||
// Only load the startup pak files, as 'common_early.rpak' has assets
|
||||
// that references assets in 'startup.rpak'.
|
||||
PakHandle_t pakHandle = g_pakLoadApi->LoadAsync("startup.rpak", AlignedMemAlloc(), 5, 0);
|
||||
g_pakLoadApi->WaitAsync(pakHandle, nullptr);
|
||||
g_pakLoadApi->LoadAsyncAndWait("startup.rpak", AlignedMemAlloc(), 5, 0);
|
||||
g_pakLoadApi->LoadAsyncAndWait("startup_sdk.rpak", AlignedMemAlloc(), 5, 0);
|
||||
|
||||
// Trick: return INIT_FAILED to disable the loading of hardware
|
||||
// configuration data, since we don't need it on the dedi.
|
||||
@ -69,7 +71,14 @@ InitReturnVal_t CMaterialSystem::Init(CMaterialSystem* thisptr)
|
||||
g_PCLStatsAvailable = true;
|
||||
}
|
||||
|
||||
return CMaterialSystem__Init(thisptr);
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -93,33 +102,6 @@ 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
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -139,7 +121,10 @@ void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64
|
||||
//---------------------------------------------------------------------------------
|
||||
ssize_t SpinPresent(void)
|
||||
{
|
||||
ImguiSystem()->RenderFrame();
|
||||
CImguiSystem* const imguiSystem = ImguiSystem();
|
||||
|
||||
if (imguiSystem->IsInitialized())
|
||||
imguiSystem->RenderFrame();
|
||||
|
||||
const ssize_t val = v_SpinPresent();
|
||||
return val;
|
||||
@ -147,8 +132,16 @@ ssize_t SpinPresent(void)
|
||||
|
||||
void* CMaterialSystem::SwapBuffers(CMaterialSystem* pMatSys)
|
||||
{
|
||||
ImguiSystem()->SampleFrame();
|
||||
ImguiSystem()->SwapBuffers();
|
||||
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();
|
||||
}
|
||||
|
||||
return CMaterialSystem__SwapBuffers(pMatSys);
|
||||
}
|
||||
@ -188,6 +181,57 @@ 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
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -203,7 +247,9 @@ void VMaterialSystem::Detour(const bool bAttach) const
|
||||
DetourSetup(&CMaterialSystem__SwapBuffers, &CMaterialSystem::SwapBuffers, bAttach);
|
||||
DetourSetup(&CMaterialSystem__FindMaterialEx, &CMaterialSystem::FindMaterialEx, bAttach);
|
||||
|
||||
DetourSetup(&v_StreamDB_Init, &StreamDB_Init, bAttach);
|
||||
DetourSetup(&CMaterialSystem__CreditModelTextures, &CMaterialSystem::CreditModelTextures, bAttach);
|
||||
DetourSetup(&CMaterialSystem__UpdateStreamCamera, &CMaterialSystem::UpdateStreamCamera, bAttach);
|
||||
|
||||
DetourSetup(&v_DispatchDrawCall, &DispatchDrawCall, bAttach);
|
||||
DetourSetup(&v_SpinPresent, &SpinPresent, bAttach);
|
||||
#endif // !MATERIALSYSTEM_NODX
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "cmaterialglue.h"
|
||||
#include "public/imaterialsystem.h"
|
||||
|
||||
#define STREAM_DB_EXT "stbsp"
|
||||
|
||||
class CMaterialSystem
|
||||
{
|
||||
public:
|
||||
@ -17,6 +15,9 @@ 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!
|
||||
@ -75,20 +76,15 @@ 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!
|
||||
@ -112,17 +108,13 @@ class VMaterialSystem : public IDetour
|
||||
LogFunAdr("CMaterialSystem::SwapBuffers", CMaterialSystem__SwapBuffers);
|
||||
LogFunAdr("CMaterialSystem::FindMaterialEx", CMaterialSystem__FindMaterialEx);
|
||||
LogFunAdr("CMaterialSystem::GetScreenSize", CMaterialSystem__GetScreenSize);
|
||||
LogFunAdr("CMaterialSystem::GetStreamOverlay", CMaterialSystem__GetStreamOverlay);
|
||||
LogFunAdr("CMaterialSystem::DrawStreamOverlay", CMaterialSystem__DrawStreamOverlay);
|
||||
LogFunAdr("CMaterialSystem::CreditModelTextures", CMaterialSystem__CreditModelTextures);
|
||||
LogFunAdr("CMaterialSystem::UpdateStreamCamera", CMaterialSystem__UpdateStreamCamera);
|
||||
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
|
||||
@ -140,22 +132,17 @@ 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("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("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("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
|
||||
|
69
src/materialsystem/texturestreaming.cpp
Normal file
69
src/materialsystem/texturestreaming.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#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);
|
||||
}
|
178
src/materialsystem/texturestreaming.h
Normal file
178
src/materialsystem/texturestreaming.h
Normal file
@ -0,0 +1,178 @@
|
||||
//=============================================================================//
|
||||
//
|
||||
// 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
|
@ -21,8 +21,8 @@
|
||||
|
||||
struct BoundsItem
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
float bmin[3];
|
||||
float bmax[3];
|
||||
int i;
|
||||
};
|
||||
|
||||
@ -48,30 +48,56 @@ 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)
|
||||
inline int longestAxis(float x, float y, float z)
|
||||
{
|
||||
return y > x ? 1 : 0;
|
||||
int axis = 0;
|
||||
float maxVal = x;
|
||||
if (y > maxVal)
|
||||
{
|
||||
axis = 1;
|
||||
maxVal = y;
|
||||
}
|
||||
if (z > maxVal)
|
||||
{
|
||||
axis = 2;
|
||||
}
|
||||
return axis;
|
||||
}
|
||||
|
||||
static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk,
|
||||
@ -110,8 +136,9 @@ static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int tri
|
||||
// Split
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
|
||||
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||
node.bmax[1] - node.bmin[1]);
|
||||
const int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||
node.bmax[1] - node.bmin[1],
|
||||
node.bmax[2] - node.bmin[2]);
|
||||
|
||||
if (axis == 0)
|
||||
{
|
||||
@ -123,6 +150,11 @@ 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;
|
||||
|
||||
@ -162,17 +194,20 @@ 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 XY bounds.
|
||||
// Calc triangle XYZ 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];
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,18 +313,19 @@ int rcGetChunksOverlappingRect(const rcChunkyTriMesh * cm, float bmin[2], float
|
||||
|
||||
|
||||
|
||||
static bool checkOverlapSegment(const float p[2], const float q[2],
|
||||
const float bmin[2], const float bmax[2])
|
||||
static bool checkOverlapSegment(const float p[3], const float q[3],
|
||||
const float bmin[3], const float bmax[3])
|
||||
{
|
||||
float tmin = 0;
|
||||
float tmax = 1;
|
||||
float d[2];
|
||||
float d[3];
|
||||
d[0] = q[0] - p[0];
|
||||
d[1] = q[1] - p[1];
|
||||
d[2] = q[2] - p[2];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (fabsf(d[i]) < RD_EPS)
|
||||
if (rdMathFabsf(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])
|
||||
@ -310,8 +346,9 @@ static bool checkOverlapSegment(const float p[2], const float q[2],
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm,
|
||||
float p[2], float q[2],
|
||||
float p[3], float q[3],
|
||||
int* ids, const int maxIds)
|
||||
{
|
||||
// Traverse tree
|
||||
|
@ -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] = 0000000030;
|
||||
s_traverseAnimTraverseFlags[ANIMTYPE_GOLIATH] = 0000000030; // TODO: figure out all the activities GOLIATH has.
|
||||
s_traverseAnimTraverseFlags[ANIMTYPE_TITAN] = 0x00000030;
|
||||
s_traverseAnimTraverseFlags[ANIMTYPE_GOLIATH] = 0x00000030; // TODO: figure out all the activities GOLIATH has.
|
||||
}
|
||||
|
||||
TraverseType_s s_traverseTable[NUM_TRAVERSE_TYPES];
|
||||
@ -150,6 +150,7 @@ Editor::Editor() :
|
||||
m_filterWalkableLowHeightSpans(true),
|
||||
m_buildTraversePortals(true),
|
||||
m_traverseRayDynamicOffset(true),
|
||||
m_traverseLinkSinglePortalPerPolyPair(false),
|
||||
m_collapseLinkedPolyGroups(false),
|
||||
m_buildBvTree(true),
|
||||
m_selectedNavMeshType(NAVMESH_SMALL),
|
||||
@ -471,6 +472,8 @@ 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))
|
||||
@ -630,6 +633,11 @@ 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
|
||||
@ -652,7 +660,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 (geom->raycastMesh(basePos, offsetPos, TRAVERSE_LINK_TRACE_MASK))
|
||||
if (raycastMesh(geom, basePos, offsetPos))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -695,7 +703,7 @@ static bool traverseLinkIntersectsPlaneOverPlane(const InputGeom* geom, const fl
|
||||
float rayMidEnd[3];
|
||||
rdVset(rayMidEnd, rayMidStart[0], rayMidStart[1], rayMidStart[2]+walkableHeight);
|
||||
|
||||
if (geom->raycastMesh(rayMidStart, rayMidEnd, TRAVERSE_LINK_TRACE_MASK))
|
||||
if (raycastMesh(geom, rayMidStart, rayMidEnd))
|
||||
return true;
|
||||
|
||||
const float distance = rdVdist(lowPos, highPos);
|
||||
@ -708,13 +716,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 (geom->raycastMesh(rayMidStart, rayMidEnd, TRAVERSE_LINK_TRACE_MASK))
|
||||
if (raycastMesh(geom, rayMidStart, rayMidEnd))
|
||||
return true;
|
||||
|
||||
rdVsad(rayMidMidStart, rayMidStart, highPos, 0.5f);
|
||||
rdVset(rayMidEnd, rayMidMidStart[0], rayMidMidStart[1], rayMidMidStart[2]+walkableHeight);
|
||||
|
||||
if (geom->raycastMesh(rayMidStart, rayMidEnd, TRAVERSE_LINK_TRACE_MASK))
|
||||
if (raycastMesh(geom, rayMidStart, rayMidEnd))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -758,7 +766,7 @@ static bool traverseLinkIntersectsOverhangOverPoint(const InputGeom* geom, const
|
||||
startPos[2] + (walkableHeight*2)
|
||||
};
|
||||
|
||||
return geom->raycastMesh(minClearanceHeight, startPos, TRAVERSE_LINK_TRACE_MASK);
|
||||
return raycastMesh(geom, minClearanceHeight, startPos);
|
||||
}
|
||||
|
||||
static bool traverseLinkInLOS(void* userData, const float* lowPos, const float* highPos, const float* lowNorm,
|
||||
@ -858,7 +866,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 (geom->raycastMesh(targetRayPos, lowPos, TRAVERSE_LINK_TRACE_MASK))
|
||||
if (raycastMesh(geom, targetRayPos, lowPos))
|
||||
return false;
|
||||
|
||||
const float angle = rdCalcSlopeAngle(lowPos, highPos);
|
||||
@ -900,7 +908,7 @@ static int addToPolyMap(void* userData, const dtPolyRef basePolyRef, const dtPol
|
||||
|
||||
try
|
||||
{
|
||||
auto ret = editor->getTraverseLinkPolyMap().emplace(TraverseLinkPolyPair(basePolyRef, landPolyRef), traverseTypeBit);
|
||||
const auto ret = editor->getTraverseLinkPolyMap().emplace(TraverseLinkPolyPair(basePolyRef, landPolyRef), traverseTypeBit);
|
||||
if (!ret.second)
|
||||
{
|
||||
rdAssert(ret.second); // Called 'addToPolyMap' while poly link already exists.
|
||||
@ -925,6 +933,7 @@ void Editor::createTraverseLinkParams(dtTraverseLinkConnectParams& params)
|
||||
params.userData = this;
|
||||
params.minEdgeOverlap = m_traverseEdgeMinOverlap;
|
||||
params.maxPortalAlign = m_traversePortalMaxAlign;
|
||||
params.singlePortalPerPair = m_traverseLinkSinglePortalPerPolyPair;
|
||||
}
|
||||
|
||||
bool Editor::createTraverseLinks()
|
||||
@ -1392,11 +1401,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::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 },
|
||||
{ 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 },
|
||||
};
|
||||
|
||||
void Editor::selectNavMeshType(const NavMeshType_e navMeshType)
|
||||
|
@ -35,7 +35,7 @@ void scanDirectoryAppend(const string& path, const string& ext, vector<string>&
|
||||
|
||||
do
|
||||
{
|
||||
filelist.push_back(dir.name);
|
||||
filelist.emplace_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.push_back(current->d_name);
|
||||
filelist.emplace_back(current->d_name);
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
|
@ -533,11 +533,13 @@ bool InputGeom::raycastMesh(const float* src, const float* dst, const unsigned i
|
||||
if (!traceWorld)
|
||||
return false;
|
||||
|
||||
float p[2], q[2];
|
||||
float p[3], q[3];
|
||||
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)
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
struct rcChunkyTriMeshNode
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
float bmin[3];
|
||||
float bmax[3];
|
||||
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[2], float q[2], int* ids, const int maxIds);
|
||||
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm, float p[3], float q[3], int* ids, const int maxIds);
|
||||
|
||||
|
||||
#endif // CHUNKYTRIMESH_H
|
||||
|
@ -247,6 +247,7 @@ protected:
|
||||
bool m_filterWalkableLowHeightSpans;
|
||||
bool m_buildTraversePortals;
|
||||
bool m_traverseRayDynamicOffset;
|
||||
bool m_traverseLinkSinglePortalPerPolyPair;
|
||||
bool m_collapseLinkedPolyGroups;
|
||||
bool m_buildBvTree;
|
||||
|
||||
|
@ -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;
|
||||
Uint32 flags = SDL_WINDOW_OPENGL | SDL_RENDERER_PRESENTVSYNC | SDL_WINDOW_RESIZABLE;
|
||||
if (presentationMode)
|
||||
{
|
||||
// Create a fullscreen window at the native resolution.
|
||||
@ -752,6 +752,24 @@ 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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user