2021-12-25 22:36:38 +01:00
//=============================================================================//
//
// Purpose: Squirrel VM
//
//=============================================================================//
# include "core/stdafx.h"
2022-06-22 12:12:08 +02:00
# include "tier0/platform_internal.h"
2022-01-14 20:45:36 +01:00
# include "tier0/commandline.h"
2023-01-29 16:07:02 +01:00
# ifndef CLIENT_DLL
2022-05-20 11:52:19 +02:00
# include "engine/server/sv_rcon.h"
2023-01-29 16:07:02 +01:00
# endif // CLIENT_DLL
# ifndef DEDICATED
2023-05-10 00:05:38 +02:00
# include "engine/client/cdll_engine_int.h"
2022-02-19 02:31:16 +01:00
# include "vgui/vgui_debugpanel.h"
2021-12-25 22:36:38 +01:00
# include "gameui/IConsole.h"
2023-01-29 16:07:02 +01:00
# endif // !DEDICATED
2024-03-16 11:36:49 +01:00
# include "squirrel.h"
# include "sqvm.h"
# include "sqstate.h"
# include "sqstdaux.h"
2021-12-25 22:36:38 +01:00
2024-02-24 02:15:09 +01:00
//---------------------------------------------------------------------------------
// Console variables
//---------------------------------------------------------------------------------
static ConVar script_show_output ( " script_show_output " , " 0 " , FCVAR_RELEASE , " Prints the VM output to the console ( !slower! ) . " , true, 0.f, true, 2.f, " 0 = log to file . 1 = 0 + log to console . 2 = 1 + log to notify " ) ;
static ConVar script_show_warning ( " script_show_warning " , " 0 " , FCVAR_RELEASE , " Prints the VM warning output to the console ( !slower! ) . " , true, 0.f, true, 2.f, " 0 = log to file . 1 = 0 + log to console . 2 = 1 + log to notify " ) ;
2021-12-25 22:36:38 +01:00
//---------------------------------------------------------------------------------
// Purpose: prints the output of each VM to the console
2022-03-04 15:34:09 +01:00
// Input : *sqvm -
// *fmt -
// ... -
2021-12-25 22:36:38 +01:00
//---------------------------------------------------------------------------------
2022-05-19 02:19:43 +02:00
SQRESULT SQVM_PrintFunc ( HSQUIRRELVM v , SQChar * fmt , . . . )
2021-12-25 22:36:38 +01:00
{
2023-03-26 16:09:05 +02:00
eDLL_T remoteContext ;
2022-02-17 18:00:29 +01:00
// We use the sqvm pointer as index for SDK usage as the function prototype has to match assembly.
2024-03-16 11:36:49 +01:00
// The compiler 'pointer truncation' warning couldn't be avoided, but it's safe to ignore it here.
2023-04-03 14:55:16 +02:00
# pragma warning(push)
# pragma warning(disable : 4302 4311)
2022-03-31 02:26:05 +02:00
switch ( static_cast < SQCONTEXT > ( reinterpret_cast < int > ( v ) ) )
2023-04-03 14:55:16 +02:00
# pragma warning(pop)
2022-02-17 18:00:29 +01:00
{
2022-03-31 02:26:05 +02:00
case SQCONTEXT : : SERVER :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : SCRIPT_SERVER ;
2022-02-17 18:00:29 +01:00
break ;
2022-03-31 02:26:05 +02:00
case SQCONTEXT : : CLIENT :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : SCRIPT_CLIENT ;
2022-02-17 18:00:29 +01:00
break ;
2022-03-31 02:26:05 +02:00
case SQCONTEXT : : UI :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : SCRIPT_UI ;
2022-02-17 18:00:29 +01:00
break ;
2022-03-31 02:26:05 +02:00
case SQCONTEXT : : NONE :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : NONE ;
2022-02-17 18:00:29 +01:00
break ;
default :
2022-08-09 02:35:00 +02:00
2023-03-26 16:09:05 +02:00
SQCONTEXT scriptContext = v - > GetContext ( ) ;
switch ( scriptContext )
2022-08-03 18:34:44 +02:00
{
case SQCONTEXT : : SERVER :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : SCRIPT_SERVER ;
2022-08-03 18:34:44 +02:00
break ;
case SQCONTEXT : : CLIENT :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : SCRIPT_CLIENT ;
2022-08-03 18:34:44 +02:00
break ;
case SQCONTEXT : : UI :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : SCRIPT_UI ;
2022-08-03 18:34:44 +02:00
break ;
default :
2023-03-26 16:09:05 +02:00
remoteContext = eDLL_T : : NONE ;
2022-08-03 18:34:44 +02:00
break ;
}
2022-02-17 18:00:29 +01:00
break ;
}
2022-08-03 18:34:44 +02:00
2023-04-14 00:30:50 +02:00
// Determine whether this is an info or warning log.
2023-04-08 19:00:28 +02:00
bool bLogLevelOverride = ( g_bSQAuxError | | ( g_bSQAuxBadLogic & & v = = g_pErrorVM ) ) ;
2024-02-24 02:15:09 +01:00
LogLevel_t level = LogLevel_t ( script_show_output . GetInt ( ) ) ;
2023-03-26 16:09:05 +02:00
LogType_t type = bLogLevelOverride ? LogType_t : : SQ_WARNING : LogType_t : : SQ_INFO ;
2022-08-14 15:20:28 +02:00
2023-04-14 00:30:50 +02:00
// Always log script related problems to the console.
if ( type = = LogType_t : : SQ_WARNING & &
level = = LogLevel_t : : LEVEL_DISK_ONLY )
{
level = LogLevel_t : : LEVEL_CONSOLE ;
}
2023-03-26 16:09:05 +02:00
va_list args ;
va_start ( args , fmt ) ;
2023-04-14 00:30:50 +02:00
CoreMsgV ( type , level , remoteContext , " squirrel_re " , fmt , args ) ;
2023-03-26 16:09:05 +02:00
va_end ( args ) ;
2022-01-14 20:45:36 +01:00
2022-03-31 02:26:05 +02:00
return SQ_OK ;
2021-12-25 22:36:38 +01:00
}
//---------------------------------------------------------------------------------
2023-08-12 22:41:48 +01:00
// Purpose: sprintf from SQVM stack
2022-03-04 15:34:09 +01:00
// Input : *sqvm -
// a2 -
// a3 -
// *nStringSize -
// **ppString -
2021-12-25 22:36:38 +01:00
//---------------------------------------------------------------------------------
2023-08-12 22:41:48 +01:00
SQRESULT SQVM_sprintf ( HSQUIRRELVM v , SQInteger a2 , SQInteger a3 , SQInteger * nStringSize , SQChar * * ppString )
2021-12-25 22:36:38 +01:00
{
2024-01-02 15:21:36 +01:00
static void * const retaddr = reinterpret_cast < void * > ( CMemory ( v_SQVM_WarningCmd ) . Offset ( 0x10 ) . FindPatternSelf ( " 85 ?? ?? 99 " , CMemory : : Direction : : DOWN ) . GetPtr ( ) ) ;
const SQRESULT result = v_SQVM_sprintf ( v , a2 , a3 , nStringSize , ppString ) ;
2022-01-14 20:45:36 +01:00
2023-08-12 22:41:48 +01:00
if ( retaddr = = _ReturnAddress ( ) ) // Check if its SQVM_Warning calling.
2021-12-25 22:36:38 +01:00
{
2024-01-02 15:21:36 +01:00
const SQCONTEXT scriptContext = v - > GetContext ( ) ;
2023-08-12 22:41:48 +01:00
eDLL_T remoteContext ;
2021-12-25 22:36:38 +01:00
2023-08-12 22:41:48 +01:00
switch ( scriptContext )
{
case SQCONTEXT : : SERVER :
remoteContext = eDLL_T : : SCRIPT_SERVER ;
break ;
case SQCONTEXT : : CLIENT :
remoteContext = eDLL_T : : SCRIPT_CLIENT ;
break ;
case SQCONTEXT : : UI :
remoteContext = eDLL_T : : SCRIPT_UI ;
break ;
default :
remoteContext = eDLL_T : : NONE ;
break ;
}
2021-12-25 22:36:38 +01:00
2024-01-02 15:21:36 +01:00
const std : : string svConstructor ( * ppString , * nStringSize ) ; // Get string from memory via std::string constructor.
2024-02-24 02:15:09 +01:00
CoreMsg ( LogType_t : : SQ_WARNING , static_cast < LogLevel_t > ( script_show_warning . GetInt ( ) ) ,
2023-08-12 22:41:48 +01:00
remoteContext , NO_ERROR , " squirrel_re(warning) " , " %s " , svConstructor . c_str ( ) ) ;
2022-08-03 18:34:44 +02:00
}
2021-12-25 22:36:38 +01:00
return result ;
}
2022-03-04 15:34:09 +01:00
//---------------------------------------------------------------------------------
// Purpose: prints the compile error and context to the console
// Input : *sqvm -
// *pszError -
// *pszFile -
// nLine -
// nColumn -
//---------------------------------------------------------------------------------
2022-05-19 02:19:43 +02:00
void SQVM_CompileError ( HSQUIRRELVM v , const SQChar * pszError , const SQChar * pszFile , SQUnsignedInteger nLine , SQInteger nColumn )
2022-03-04 15:34:09 +01:00
{
static char szContextBuf [ 256 ] { } ;
2022-09-22 17:51:41 +02:00
v_SQVM_GetErrorLine ( pszFile , nLine , szContextBuf , sizeof ( szContextBuf ) - 1 ) ;
2022-03-04 15:34:09 +01:00
2024-03-25 01:41:52 +01:00
const eDLL_T context = v - > GetNativeContext ( ) ;
Error ( context , NO_ERROR , " %s SCRIPT COMPILE ERROR: %s \n " , v - > GetContextName ( ) , pszError ) ;
Error ( context , NO_ERROR , " -> %s \n \n " , szContextBuf ) ;
Error ( context , NO_ERROR , " %s line [%d] column [%d] \n " , pszFile , nLine , nColumn ) ;
2022-03-04 15:34:09 +01:00
}
2022-06-22 12:12:08 +02:00
//---------------------------------------------------------------------------------
// Purpose: prints the logic error and context to the console
// Input : bPrompt -
//---------------------------------------------------------------------------------
void SQVM_LogicError ( SQBool bPrompt )
{
2022-08-08 17:49:46 +02:00
if ( ( * g_flErrorTimeStamp ) > 0.0 & & ( bPrompt | | Plat_FloatTime ( ) > ( * g_flErrorTimeStamp ) + 0.0 ) )
2022-06-22 12:12:08 +02:00
{
g_bSQAuxBadLogic = true ;
}
2022-08-08 17:49:46 +02:00
else
{
g_bSQAuxBadLogic = false ;
g_pErrorVM = nullptr ;
}
2022-06-22 12:12:08 +02:00
v_SQVM_LogicError ( bPrompt ) ;
}
2024-03-25 01:41:52 +01:00
void SQVM : : Push ( const SQObjectPtr & o ) { _stack [ _top + + ] = o ; }
SQObjectPtr & SQVM : : Top ( ) { return _stack [ _top - 1 ] ; }
SQObjectPtr & SQVM : : PopGet ( ) { return _stack [ - - _top ] ; }
SQObjectPtr & SQVM : : GetUp ( SQInteger n ) { return _stack [ _top + n ] ; }
SQObjectPtr & SQVM : : GetAt ( SQInteger n ) { return _stack [ n ] ; }
# include "vscript/languages/squirrel_re/vsquirrel.h"
CSquirrelVM * SQVM : : GetScriptVM ( )
2022-03-30 22:54:33 +02:00
{
2024-03-25 01:41:52 +01:00
return _sharedstate - > GetScriptVM ( ) ;
2022-03-30 22:54:33 +02:00
}
2024-03-25 01:41:52 +01:00
SQChar * SQVM : : GetContextName ( )
{
return _sharedstate - > _contextname ;
}
SQCONTEXT SQVM : : GetContext ( )
{
return GetScriptVM ( ) - > GetContext ( ) ;
}
eDLL_T SQVM : : GetNativeContext ( )
2022-05-19 02:19:43 +02:00
{
2024-03-25 01:41:52 +01:00
return ( eDLL_T ) GetContext ( ) ;
2022-05-19 02:19:43 +02:00
}
//---------------------------------------------------------------------------------
2023-11-26 13:21:20 +01:00
void VSquirrelVM : : Detour ( const bool bAttach ) const
2021-12-25 22:36:38 +01:00
{
2023-11-26 13:21:20 +01:00
DetourSetup ( & v_SQVM_PrintFunc , & SQVM_PrintFunc , bAttach ) ;
DetourSetup ( & v_SQVM_sprintf , & SQVM_sprintf , bAttach ) ;
DetourSetup ( & v_SQVM_CompileError , & SQVM_CompileError , bAttach ) ;
DetourSetup ( & v_SQVM_LogicError , & SQVM_LogicError , bAttach ) ;
2021-12-25 22:36:38 +01:00
}