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
|
2023-05-06 16:23:56 +02:00
|
|
|
#include "vscript/languages/squirrel_re/include/squirrel.h"
|
|
|
|
#include "vscript/languages/squirrel_re/include/sqvm.h"
|
|
|
|
#include "vscript/languages/squirrel_re/include/sqstate.h"
|
|
|
|
#include "vscript/languages/squirrel_re/include/sqstdaux.h"
|
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.
|
2023-04-02 17:11:14 +02:00
|
|
|
// The compiler 'pointer truncation' warning couldn't be avoided, but it's safe to ignore it.
|
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));
|
2023-04-14 00:30:50 +02: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
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: prints the warning output of each VM to the console
|
2022-03-04 15:34:09 +01:00
|
|
|
// Input : *sqvm -
|
|
|
|
// a2 -
|
|
|
|
// a3 -
|
|
|
|
// *nStringSize -
|
|
|
|
// **ppString -
|
2021-12-25 22:36:38 +01:00
|
|
|
//---------------------------------------------------------------------------------
|
2022-05-19 02:19:43 +02:00
|
|
|
SQRESULT SQVM_WarningFunc(HSQUIRRELVM v, SQInteger a2, SQInteger a3, SQInteger* nStringSize, SQChar** ppString)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-04-10 19:59:34 +02:00
|
|
|
static void* retaddr = reinterpret_cast<void*>(p_SQVM_WarningCmd.Offset(0x10).FindPatternSelf("85 ?? ?? 99", CMemory::Direction::DOWN).GetPtr());
|
2022-05-19 02:19:43 +02:00
|
|
|
SQRESULT result = v_SQVM_WarningFunc(v, a2, a3, nStringSize, ppString);
|
2022-01-14 20:45:36 +01:00
|
|
|
|
2023-03-26 16:09:05 +02:00
|
|
|
if (retaddr != _ReturnAddress()) // Check if its SQVM_Warning calling.
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-03-31 02:26:05 +02:00
|
|
|
return result;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2023-04-02 02:19:08 +02:00
|
|
|
SQCONTEXT scriptContext = v->GetContext();
|
|
|
|
eDLL_T remoteContext;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
2023-03-26 16:09:05 +02:00
|
|
|
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-04-02 02:19:08 +02:00
|
|
|
remoteContext = eDLL_T::NONE;
|
2022-08-03 18:34:44 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-05-09 02:20:07 +02:00
|
|
|
std::string svConstructor(*ppString, *nStringSize); // Get string from memory via std::string constructor.
|
2023-03-26 18:18:50 +02:00
|
|
|
CoreMsg(LogType_t::SQ_WARNING, static_cast<LogLevel_t>(script_show_warning->GetInt()),
|
2023-03-26 16:09:05 +02:00
|
|
|
remoteContext, NO_ERROR, "squirrel_re(warning)", "%s", svConstructor.c_str());
|
2022-09-14 00:39:38 +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
|
|
|
{
|
2022-03-31 02:26:05 +02:00
|
|
|
static SQCONTEXT context{};
|
2022-03-04 15:34:09 +01:00
|
|
|
static char szContextBuf[256]{};
|
|
|
|
|
2022-05-21 11:15:36 +02:00
|
|
|
context = v->GetContext();
|
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
|
|
|
|
2022-09-14 01:14:51 +02:00
|
|
|
Error(static_cast<eDLL_T>(context), NO_ERROR, "%s SCRIPT COMPILE ERROR: %s\n", SQVM_GetContextName(context), pszError);
|
|
|
|
Error(static_cast<eDLL_T>(context), NO_ERROR, " -> %s\n\n", szContextBuf);
|
|
|
|
Error(static_cast<eDLL_T>(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);
|
|
|
|
}
|
|
|
|
|
2022-03-30 22:54:33 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Returns the VM name by context
|
|
|
|
// Input : context -
|
|
|
|
// Output : const SQChar*
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
const SQChar* SQVM_GetContextName(SQCONTEXT context)
|
|
|
|
{
|
|
|
|
switch (context)
|
|
|
|
{
|
|
|
|
case SQCONTEXT::SERVER:
|
|
|
|
return "SERVER";
|
|
|
|
case SQCONTEXT::CLIENT:
|
|
|
|
return "CLIENT";
|
|
|
|
case SQCONTEXT::UI:
|
|
|
|
return "UI";
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 02:19:43 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Returns the VM context by name
|
|
|
|
// Input : *sqvm -
|
|
|
|
// Output : const SQCONTEXT*
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
const SQCONTEXT SQVM_GetContextIndex(HSQUIRRELVM v)
|
|
|
|
{
|
|
|
|
if (strcmp(v->_sharedstate->_contextname, "SERVER") == 0)
|
|
|
|
return SQCONTEXT::SERVER;
|
|
|
|
if (strcmp(v->_sharedstate->_contextname, "CLIENT") == 0)
|
|
|
|
return SQCONTEXT::CLIENT;
|
|
|
|
if (strcmp(v->_sharedstate->_contextname, "UI") == 0)
|
|
|
|
return SQCONTEXT::UI;
|
|
|
|
|
|
|
|
return SQCONTEXT::NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
2023-05-06 16:23:56 +02:00
|
|
|
void VSquirrelVM::Attach() const
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-05-19 02:19:43 +02:00
|
|
|
DetourAttach((LPVOID*)&v_SQVM_PrintFunc, &SQVM_PrintFunc);
|
|
|
|
DetourAttach((LPVOID*)&v_SQVM_WarningFunc, &SQVM_WarningFunc);
|
|
|
|
DetourAttach((LPVOID*)&v_SQVM_CompileError, &SQVM_CompileError);
|
2022-06-22 12:12:08 +02:00
|
|
|
DetourAttach((LPVOID*)&v_SQVM_LogicError, &SQVM_LogicError);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
2022-05-19 02:19:43 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
2023-05-06 16:23:56 +02:00
|
|
|
void VSquirrelVM::Detach() const
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-05-19 02:19:43 +02:00
|
|
|
DetourDetach((LPVOID*)&v_SQVM_PrintFunc, &SQVM_PrintFunc);
|
|
|
|
DetourDetach((LPVOID*)&v_SQVM_WarningFunc, &SQVM_WarningFunc);
|
|
|
|
DetourDetach((LPVOID*)&v_SQVM_CompileError, &SQVM_CompileError);
|
2022-06-22 12:12:08 +02:00
|
|
|
DetourDetach((LPVOID*)&v_SQVM_LogicError, &SQVM_LogicError);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|