aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL/squirrel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDLL/squirrel.cpp')
-rw-r--r--NorthstarDLL/squirrel.cpp840
1 files changed, 422 insertions, 418 deletions
diff --git a/NorthstarDLL/squirrel.cpp b/NorthstarDLL/squirrel.cpp
index 2fa957fb..7cf46f4f 100644
--- a/NorthstarDLL/squirrel.cpp
+++ b/NorthstarDLL/squirrel.cpp
@@ -1,271 +1,165 @@
#include "pch.h"
#include "squirrel.h"
-#include "hooks.h"
-#include "hookutils.h"
-#include "sigscanning.h"
#include "concommand.h"
#include "modmanager.h"
-#include <iostream>
-#include "gameutils.h"
+#include "dedicated.h"
+#include "r2engine.h"
-// hook forward declarations
-typedef SQInteger (*SQPrintType)(void* sqvm, char* fmt, ...);
-SQPrintType ClientSQPrint;
-SQPrintType UISQPrint;
-SQPrintType ServerSQPrint;
-template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...);
+AUTOHOOK_INIT()
-typedef void* (*CreateNewVMType)(void* a1, ScriptContext contextArg);
-CreateNewVMType ClientCreateNewVM; // only need a client one since ui doesn't have its own func for this
-CreateNewVMType ServerCreateNewVM;
-template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext contextArg);
-
-typedef void (*DestroyVMType)(void* a1, void* sqvm);
-DestroyVMType ClientDestroyVM; // only need a client one since ui doesn't have its own func for this
-DestroyVMType ServerDestroyVM;
-template <ScriptContext context> void DestroyVMHook(void* a1, void* sqvm);
-
-typedef void (*ScriptCompileError)(void* sqvm, const char* error, const char* file, int line, int column);
-ScriptCompileError ClientSQCompileError; // only need a client one since ui doesn't have its own func for this
-ScriptCompileError ServerSQCompileError;
-template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column);
-
-typedef char (*CallScriptInitCallbackType)(void* sqvm, const char* callback);
-CallScriptInitCallbackType ClientCallScriptInitCallback;
-CallScriptInitCallbackType ServerCallScriptInitCallback;
-template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, const char* callback);
-
-RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
-RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
-template <ScriptContext context> int64_t RegisterSquirrelFuncHook(void* sqvm, SQFuncRegistration* funcReg, char unknown);
-
-// core sqvm funcs
-sq_compilebufferType ClientSq_compilebuffer;
-sq_compilebufferType ServerSq_compilebuffer;
-
-sq_pushroottableType ClientSq_pushroottable;
-sq_pushroottableType ServerSq_pushroottable;
+const char* GetContextName(ScriptContext context)
+{
+ switch (context)
+ {
+ case ScriptContext::CLIENT:
+ return "CLIENT";
+ case ScriptContext::SERVER:
+ return "SERVER";
+ case ScriptContext::UI:
+ return "UI";
+ default:
+ return "UNKNOWN";
+ }
+}
-sq_callType ClientSq_call;
-sq_callType ServerSq_call;
+eSQReturnType SQReturnTypeFromString(const char* pReturnType)
+{
+ static const std::map<std::string, eSQReturnType> sqReturnTypeNameToString = {
+ {"bool", eSQReturnType::Boolean},
+ {"float", eSQReturnType::Float},
+ {"vector", eSQReturnType::Vector},
+ {"int", eSQReturnType::Integer},
+ {"entity", eSQReturnType::Entity},
+ {"string", eSQReturnType::String},
+ {"array", eSQReturnType::Arrays},
+ {"asset", eSQReturnType::Asset},
+ {"table", eSQReturnType::Table}};
+
+ if (sqReturnTypeNameToString.find(pReturnType) != sqReturnTypeNameToString.end())
+ return sqReturnTypeNameToString.at(pReturnType);
+ else
+ return eSQReturnType::Default; // previous default value
+}
-// sq stack array funcs
-sq_newarrayType ClientSq_newarray;
-sq_newarrayType ServerSq_newarray;
+// needed to define implementations for squirrelmanager outside of squirrel.h without compiler errors
+template class SquirrelManager<ScriptContext::SERVER>;
+template class SquirrelManager<ScriptContext::CLIENT>;
+template class SquirrelManager<ScriptContext::UI>;
-sq_arrayappendType ClientSq_arrayappend;
-sq_arrayappendType ServerSq_arrayappend;
+template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquirrelVM* newSqvm)
+{
+ SquirrelVM = newSqvm;
+ sqvm = SquirrelVM->sqvm; // honestly not 100% sure on what this is, but alot of functions take it
-// sq stack push funcs
-sq_pushstringType ClientSq_pushstring;
-sq_pushstringType ServerSq_pushstring;
+ for (SQFuncRegistration* funcReg : m_funcRegistrations)
+ {
+ spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName);
+ RegisterSquirrelFunc(SquirrelVM, funcReg, 1);
+ }
-sq_pushintegerType ClientSq_pushinteger;
-sq_pushintegerType ServerSq_pushinteger;
+ for (auto& pair : g_pModManager->m_DependencyConstants)
+ {
+ bool bWasFound = false;
+ for (Mod& dependency : g_pModManager->m_LoadedMods)
+ {
+ if (!dependency.m_bEnabled)
+ continue;
-sq_pushfloatType ClientSq_pushfloat;
-sq_pushfloatType ServerSq_pushfloat;
+ if (dependency.Name == pair.second)
+ {
+ bWasFound = true;
+ break;
+ }
+ }
-sq_pushboolType ClientSq_pushbool;
-sq_pushboolType ServerSq_pushbool;
+ defconst(SquirrelVM, pair.first.c_str(), bWasFound);
+ }
+}
-sq_pusherrorType ClientSq_pusherror;
-sq_pusherrorType ServerSq_pusherror;
+template <ScriptContext context> void SquirrelManager<context>::VMDestroyed()
+{
+ SquirrelVM = nullptr;
+}
-sq_defconst ClientSq_defconst;
-sq_defconst ServerSq_defconst;
+template <ScriptContext context> void SquirrelManager<context>::ExecuteCode(const char* pCode)
+{
+ if (!SquirrelVM)
+ {
+ spdlog::error("Cannot execute code, {} squirrel vm is not initialised", GetContextName(context));
+ return;
+ }
-sq_pushAssetType ClientSq_pushAsset;
-sq_pushAssetType ServerSq_pushAsset;
+ spdlog::info("Executing {} script code {} ", GetContextName(context), pCode);
-// sq stack get funcs
-sq_getstringType ClientSq_getstring;
-sq_getstringType ServerSq_getstring;
+ std::string strCode(pCode);
+ CompileBufferState bufferState = CompileBufferState(strCode);
-sq_getintegerType ClientSq_getinteger;
-sq_getintegerType ServerSq_getinteger;
+ SQRESULT compileResult = compilebuffer(&bufferState, "console");
+ spdlog::info("sq_compilebuffer returned {}", PrintSQRESULT.at(compileResult));
-sq_getfloatType ClientSq_getfloat;
-sq_getfloatType ServerSq_getfloat;
+ if (compileResult != SQRESULT_ERROR)
+ {
+ pushroottable(sqvm);
+ SQRESULT callResult = call(sqvm, 0);
+ spdlog::info("sq_call returned {}", PrintSQRESULT.at(callResult));
+ }
+}
-sq_getboolType ClientSq_getbool;
-sq_getboolType ServerSq_getbool;
+template <ScriptContext context> void SquirrelManager<context>::AddFuncRegistration(
+ std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func)
+{
+ SQFuncRegistration* reg = new SQFuncRegistration;
-sq_getType ClientSq_sq_get;
-sq_getType ServerSq_sq_get;
+ reg->squirrelFuncName = new char[name.size() + 1];
+ strcpy((char*)reg->squirrelFuncName, name.c_str());
+ reg->cppFuncName = reg->squirrelFuncName;
-sq_newSlotType ServerSq_newSlot;
-sq_newSlotType ClientSq_newSlot;
+ reg->helpText = new char[helpText.size() + 1];
+ strcpy((char*)reg->helpText, helpText.c_str());
-sq_newTableType ServerSq_newTable;
-sq_newTableType ClientSq_newTable;
+ reg->returnTypeString = new char[returnType.size() + 1];
+ strcpy((char*)reg->returnTypeString, returnType.c_str());
+ reg->returnType = SQReturnTypeFromString(returnType.c_str());
-template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args);
+ reg->argTypes = new char[argTypes.size() + 1];
+ strcpy((char*)reg->argTypes, argTypes.c_str());
-// inits
-SquirrelManager<ScriptContext::CLIENT>* g_ClientSquirrelManager;
-SquirrelManager<ScriptContext::SERVER>* g_ServerSquirrelManager;
-SquirrelManager<ScriptContext::UI>* g_UISquirrelManager;
+ reg->funcPtr = func;
-SQInteger NSTestFunc(void* sqvm)
-{
- return 1;
+ m_funcRegistrations.push_back(reg);
}
-void InitialiseClientSquirrel(HMODULE baseAddress)
+template <ScriptContext context> SQRESULT SquirrelManager<context>::setupfunc(const SQChar* funcname)
{
- HookEnabler hook;
+ pushroottable(sqvm);
+ pushstring(sqvm, funcname, -1);
- // client inits
- g_ClientSquirrelManager = new SquirrelManager<ScriptContext::CLIENT>();
+ SQRESULT result = get(sqvm, -2);
+ if (result != SQRESULT_ERROR)
+ pushroottable(sqvm);
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x12B00,
- &SQPrintHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientSQPrint)); // client print function
- RegisterConCommand(
- "script_client", ExecuteCodeCommand<ScriptContext::CLIENT>, "Executes script code on the client vm", FCVAR_CLIENTDLL);
-
- // ui inits
- g_UISquirrelManager = new SquirrelManager<ScriptContext::UI>();
-
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x12BA0, &SQPrintHook<ScriptContext::UI>, reinterpret_cast<LPVOID*>(&UISQPrint)); // ui print function
- RegisterConCommand("script_ui", ExecuteCodeCommand<ScriptContext::UI>, "Executes script code on the ui vm", FCVAR_CLIENTDLL);
-
- // inits for both client and ui, since they share some functions
- ClientSq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- ClientSq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860);
- ClientSq_call = (sq_callType)((char*)baseAddress + 0x8650);
- ClientRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0);
-
- ClientSq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- ClientSq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
-
- ClientSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- ClientSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- ClientSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- ClientSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- ClientSq_pusherror = (sq_pusherrorType)((char*)baseAddress + 0x8470);
- ClientSq_pushAsset = (sq_pushAssetType)((char*)baseAddress + 0x3560);
-
- ClientSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
- ClientSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
- ClientSq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
- ClientSq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130);
-
- ClientSq_sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
-
- ClientSq_defconst = (sq_defconst)((char*)baseAddress + 0x12120);
-
- // Table functions
- ClientSq_newTable = (sq_newTableType)((char*)baseAddress + 0x3960);
- ClientSq_newSlot = (sq_newSlotType)((char*)baseAddress + 0x70B0);
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x26130,
- &CreateNewVMHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientCreateNewVM)); // client createnewvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x26E70,
- &DestroyVMHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientDestroyVM)); // client destroyvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x79A50,
- &ScriptCompileErrorHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientSQCompileError)); // client compileerror function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x10190,
- &CallScriptInitCallbackHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientCallScriptInitCallback)); // client callscriptinitcallback function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x108E0,
- &RegisterSquirrelFuncHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientRegisterSquirrelFunc)); // client registersquirrelfunc function
+ return result;
}
-
-void InitialiseServerSquirrel(HMODULE baseAddress)
+template <ScriptContext context> void SquirrelManager<context>::AddFuncOverride(std::string name, SQFunction func)
{
- g_ServerSquirrelManager = new SquirrelManager<ScriptContext::SERVER>();
-
- HookEnabler hook;
-
- ServerSq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- ServerSq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5840);
- ServerSq_call = (sq_callType)((char*)baseAddress + 0x8620);
- ServerRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x1DD10);
-
- ServerSq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- ServerSq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
-
- ServerSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- ServerSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- ServerSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- ServerSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- ServerSq_pusherror = (sq_pusherrorType)((char*)baseAddress + 0x8440);
- ServerSq_pushAsset = (sq_pushAssetType)((char*)baseAddress + 0x3560);
-
- ServerSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0);
- ServerSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0);
- ServerSq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x60E0);
- ServerSq_getbool = (sq_getboolType)((char*)baseAddress + 0x6110);
-
- ServerSq_sq_get = (sq_getType)((char*)baseAddress + 0x7C00);
-
- ServerSq_defconst = (sq_defconst)((char*)baseAddress + 0x1F550);
-
- ServerSq_newSlot = (sq_newSlotType)((char*)baseAddress + 0x7080);
- ServerSq_newTable = (sq_newTableType)((char*)baseAddress + 0x3960);
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1FE90,
- &SQPrintHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerSQPrint)); // server print function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x260E0,
- &CreateNewVMHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerCreateNewVM)); // server createnewvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x26E20,
- &DestroyVMHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerDestroyVM)); // server destroyvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x799E0,
- &ScriptCompileErrorHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerSQCompileError)); // server compileerror function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1D5C0,
- &CallScriptInitCallbackHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerCallScriptInitCallback)); // server callscriptinitcallback function
+ m_funcOverrides[name] = func;
+}
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1DD10,
- &RegisterSquirrelFuncHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerRegisterSquirrelFunc)); // server registersquirrelfunc function
+// hooks
+template <ScriptContext context> void* (*sq_compiler_create)(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError);
+template <ScriptContext context> void* sq_compiler_createHook(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError)
+{
+ // store whether errors generated from this compile should be fatal
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm)
+ g_pSquirrel<ScriptContext::UI>->m_bCompilationErrorsFatal = bShouldThrowError;
+ else
+ g_pSquirrel<context>->m_bCompilationErrorsFatal = bShouldThrowError;
- // cheat and clientcmd_can_execute allows clients to execute this, but since it's unsafe we only allow it when cheats are enabled
- // for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
- RegisterConCommand(
- "script",
- ExecuteCodeCommand<ScriptContext::SERVER>,
- "Executes script code on the server vm",
- FCVAR_GAMEDLL | FCVAR_CLIENTCMD_CAN_EXECUTE | FCVAR_CHEAT);
+ return sq_compiler_create<context>(sqvm, a2, a3, bShouldThrowError);
}
-// hooks
-template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...)
+template <ScriptContext context> SQInteger (*SQPrint)(HSquirrelVM* sqvm, const char* fmt);
+template <ScriptContext context> SQInteger SQPrintHook(HSquirrelVM* sqvm, const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
@@ -285,189 +179,162 @@ template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ..
return 0;
}
-template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext realContext)
+template <ScriptContext context> CSquirrelVM* (*CreateNewVM)(void* a1, ScriptContext contextArg);
+template <ScriptContext context> CSquirrelVM* CreateNewVMHook(void* a1, ScriptContext realContext)
{
- void* sqvm;
-
- if (context == ScriptContext::CLIENT)
- {
- sqvm = ClientCreateNewVM(a1, realContext);
-
- if (realContext == ScriptContext::UI)
- g_UISquirrelManager->VMCreated(sqvm);
- else
- g_ClientSquirrelManager->VMCreated(sqvm);
- }
- else if (context == ScriptContext::SERVER)
- {
- sqvm = ServerCreateNewVM(a1, context);
- g_ServerSquirrelManager->VMCreated(sqvm);
- }
+ CSquirrelVM* sqvm = CreateNewVM<context>(a1, realContext);
+ if (realContext == ScriptContext::UI)
+ g_pSquirrel<ScriptContext::UI>->VMCreated(sqvm);
+ else
+ g_pSquirrel<context>->VMCreated(sqvm);
- spdlog::info("CreateNewVM {} {}", GetContextName(realContext), sqvm);
+ spdlog::info("CreateNewVM {} {}", GetContextName(realContext), (void*)sqvm);
return sqvm;
}
+template <ScriptContext context> void (*DestroyVM)(void* a1, void* sqvm);
template <ScriptContext context> void DestroyVMHook(void* a1, void* sqvm)
{
ScriptContext realContext = context; // ui and client use the same function so we use this for prints
-
- if (context == ScriptContext::CLIENT)
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm)
{
- if (g_ClientSquirrelManager->sqvm == sqvm)
- g_ClientSquirrelManager->VMDestroyed();
- else if (g_UISquirrelManager->sqvm == sqvm)
- {
- g_UISquirrelManager->VMDestroyed();
- realContext = ScriptContext::UI;
- }
-
- ClientDestroyVM(a1, sqvm);
- }
- else if (context == ScriptContext::SERVER)
- {
- g_ServerSquirrelManager->VMDestroyed();
- ServerDestroyVM(a1, sqvm);
+ realContext = ScriptContext::UI;
+ g_pSquirrel<ScriptContext::UI>->VMDestroyed();
}
+ else
+ DestroyVM<context>(a1, sqvm);
spdlog::info("DestroyVM {} {}", GetContextName(realContext), sqvm);
}
+template <ScriptContext context> void (*SQCompileError)(void* sqvm, const char* error, const char* file, int line, int column);
template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column)
{
+ bool bIsFatalError = g_pSquirrel<context>->m_bCompilationErrorsFatal;
ScriptContext realContext = context; // ui and client use the same function so we use this for prints
- if (context == ScriptContext::CLIENT && sqvm == g_UISquirrelManager->sqvm)
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm)
+ {
realContext = ScriptContext::UI;
+ bIsFatalError = g_pSquirrel<ScriptContext::UI>->m_bCompilationErrorsFatal;
+ }
spdlog::error("{} SCRIPT COMPILE ERROR {}", GetContextName(realContext), error);
spdlog::error("{} line [{}] column [{}]", file, line, column);
- // dont call the original since it kills game
- // in the future it'd be nice to do an actual error with UICodeCallback_ErrorDialog here, but only if we're compiling level scripts
- // compilestring and stuff shouldn't tho
- // though, that also has potential to be REALLY bad if we're compiling ui scripts lol
+ // use disconnect to display an error message for the compile error, but only if the compilation error was fatal
+ // todo, we could get this from sqvm itself probably, rather than hooking sq_compiler_create
+ if (bIsFatalError)
+ {
+ // kill dedicated server if we hit this
+ if (IsDedicatedServer())
+ abort();
+ else
+ {
+ R2::Cbuf_AddText(
+ R2::Cbuf_GetCurrentPlayer(),
+ fmt::format("disconnect \"Encountered {} script compilation error, see console for details.\"", GetContextName(realContext))
+ .c_str(),
+ R2::cmd_source_t::kCommandSrcCode);
+
+ // likely temp: show console so user can see any errors, as error message wont display if ui is dead
+ // maybe we could disable all mods other than the coremods and try a reload before doing this?
+ // could also maybe do some vgui bullshit to show something visually rather than console
+ if (realContext == ScriptContext::UI)
+ R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "showconsole", R2::cmd_source_t::kCommandSrcCode);
+ }
+ }
+
+ // dont call the original function since it kills game lol
}
-template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, const char* callback)
-{
- char ret;
- if (context == ScriptContext::CLIENT)
- {
- ScriptContext realContext = context; // ui and client use the same function so we use this for prints
- bool shouldCallCustomCallbacks = false;
- // since we don't hook arbitrary callbacks yet, make sure we're only doing callbacks on inits
- if (!strcmp(callback, "UICodeCallback_UIInit"))
+
+template <ScriptContext context> int64_t(*RegisterSquirrelFunction)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown);
+template <ScriptContext context> int64_t RegisterSquirrelFunctionHook(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown)
+{
+
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->SquirrelVM)
+ {
+ if (g_pSquirrel<ScriptContext::UI>->m_funcOverrides.count(funcReg->squirrelFuncName))
{
- realContext = ScriptContext::UI;
- shouldCallCustomCallbacks = true;
+ g_pSquirrel<ScriptContext::UI>->m_funcOriginals[funcReg->squirrelFuncName] = funcReg->funcPtr;
+ funcReg->funcPtr = g_pSquirrel<ScriptContext::UI>->m_funcOverrides[funcReg->squirrelFuncName];
+ spdlog::info("Replacing {} in UI", std::string(funcReg->squirrelFuncName));
}
- else if (!strcmp(callback, "ClientCodeCallback_MapSpawn"))
- shouldCallCustomCallbacks = true;
- // run before callbacks
- // todo: we need to verify if RunOn is valid for current state before calling callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
+ return g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc(sqvm, funcReg, unknown);
+ }
- for (ModScript script : mod.Scripts)
- {
- for (ModScriptCallback modCallback : script.Callbacks)
- {
- if (modCallback.Context == realContext && modCallback.BeforeCallback.length())
- {
- spdlog::info(
- "Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.BeforeCallback);
- ClientCallScriptInitCallback(sqvm, modCallback.BeforeCallback.c_str());
- }
- }
- }
- }
- }
+ if (g_pSquirrel<context>->m_funcOverrides.count(funcReg->squirrelFuncName))
+ {
+ g_pSquirrel<context>->m_funcOriginals[funcReg->squirrelFuncName] = funcReg->funcPtr;
+ funcReg->funcPtr = g_pSquirrel<context>->m_funcOverrides[funcReg->squirrelFuncName];
+ spdlog::info("Replacing {} in Client", std::string(funcReg->squirrelFuncName));
+ }
- spdlog::info("{} CodeCallback {} called", GetContextName(realContext), callback);
- if (!shouldCallCustomCallbacks)
- spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
- ret = ClientCallScriptInitCallback(sqvm, callback);
+ return g_pSquirrel<context>->RegisterSquirrelFunc(sqvm, funcReg, unknown);
+}
- // run after callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
+template <ScriptContext context> bool (*CallScriptInitCallback)(void* sqvm, const char* callback);
+template <ScriptContext context> bool CallScriptInitCallbackHook(void* sqvm, const char* callback)
+{
- for (ModScript script : mod.Scripts)
- {
- for (ModScriptCallback modCallback : script.Callbacks)
- {
- if (modCallback.Context == realContext && modCallback.AfterCallback.length())
- {
- spdlog::info(
- "Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.AfterCallback);
- ClientCallScriptInitCallback(sqvm, modCallback.AfterCallback.c_str());
- }
- }
- }
- }
- }
+ ScriptContext realContext = context;
+ bool bShouldCallCustomCallbacks = true;
+
+ if (context == ScriptContext::CLIENT)
+ {
+ if (!strcmp(callback, "UICodeCallback_UIInit"))
+ realContext = ScriptContext::UI;
+ else if (strcmp(callback, "ClientCodeCallback_MapSpawn"))
+ bShouldCallCustomCallbacks = false;
}
else if (context == ScriptContext::SERVER)
- {
- // since we don't hook arbitrary callbacks yet, make sure we're only doing callbacks on inits
- bool shouldCallCustomCallbacks = !strcmp(callback, "CodeCallback_MapSpawn");
+ bShouldCallCustomCallbacks = !strcmp(callback, "CodeCallback_MapSpawn");
- // run before callbacks
- // todo: we need to verify if RunOn is valid for current state before calling callbacks
- if (shouldCallCustomCallbacks)
+ if (bShouldCallCustomCallbacks)
+ {
+ for (Mod mod : g_pModManager->m_LoadedMods)
{
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
+ if (!mod.m_bEnabled)
+ continue;
- for (ModScript script : mod.Scripts)
+ for (ModScript script : mod.Scripts)
+ {
+ for (ModScriptCallback modCallback : script.Callbacks)
{
- for (ModScriptCallback modCallback : script.Callbacks)
+ if (modCallback.Context == realContext && modCallback.BeforeCallback.length())
{
- if (modCallback.Context == ScriptContext::SERVER && modCallback.BeforeCallback.length())
- {
- spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback.BeforeCallback);
- ServerCallScriptInitCallback(sqvm, modCallback.BeforeCallback.c_str());
- }
+ spdlog::info("Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.BeforeCallback);
+ CallScriptInitCallback<context>(sqvm, modCallback.BeforeCallback.c_str());
}
}
}
}
+ }
- spdlog::info("{} CodeCallback {} called", GetContextName(context), callback);
- if (!shouldCallCustomCallbacks)
- spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
- ret = ServerCallScriptInitCallback(sqvm, callback);
+ spdlog::info("{} CodeCallback {} called", GetContextName(realContext), callback);
+ if (!bShouldCallCustomCallbacks)
+ spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
+ bool ret = CallScriptInitCallback<context>(sqvm, callback);
- // run after callbacks
- if (shouldCallCustomCallbacks)
+ // run after callbacks
+ if (bShouldCallCustomCallbacks)
+ {
+ for (Mod mod : g_pModManager->m_LoadedMods)
{
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
+ if (!mod.m_bEnabled)
+ continue;
- for (ModScript script : mod.Scripts)
+ for (ModScript script : mod.Scripts)
+ {
+ for (ModScriptCallback modCallback : script.Callbacks)
{
- for (ModScriptCallback modCallback : script.Callbacks)
+ if (modCallback.Context == realContext && modCallback.AfterCallback.length())
{
- if (modCallback.Context == ScriptContext::SERVER && modCallback.AfterCallback.length())
- {
- spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback.AfterCallback);
- ServerCallScriptInitCallback(sqvm, modCallback.AfterCallback.c_str());
- }
+ spdlog::info("Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.AfterCallback);
+ CallScriptInitCallback<context>(sqvm, modCallback.AfterCallback.c_str());
}
}
}
@@ -477,42 +344,203 @@ template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, con
return ret;
}
-template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args)
+template <ScriptContext context> void ConCommand_script(const CCommand& args)
{
- if (context == ScriptContext::CLIENT)
- g_ClientSquirrelManager->ExecuteCode(args.ArgS());
- else if (context == ScriptContext::UI)
- g_UISquirrelManager->ExecuteCode(args.ArgS());
- else if (context == ScriptContext::SERVER)
- g_ServerSquirrelManager->ExecuteCode(args.ArgS());
+ g_pSquirrel<context>->ExecuteCode(args.ArgS());
}
-SQRESULT SQ_DevFuncStub(void* sqvm)
+SQRESULT SQ_Stub(HSquirrelVM* sqvm)
{
- spdlog::warn("Blocked execution of squirrel developer function for security reasons. To re-enable them use start parameter "
- "-allowSquirrelDevFunctions.");
+ spdlog::info("Stubbed Function called");
return SQRESULT_NULL;
}
-template <ScriptContext context> int64_t RegisterSquirrelFuncHook(void* sqvm, SQFuncRegistration* funcReg, char unknown)
+ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
{
- static std::set<std::string> allowedDevFunctions = {
- "Dev_CommandLineHasParm",
- "Dev_CommandLineParmValue",
- "Dev_CommandLineRemoveParm",
- };
-
- if ((funcReg->devLevel == 1) && (!CommandLine()->CheckParm("-allowSquirrelDevFunctions")) &&
- (!allowedDevFunctions.count(funcReg->squirrelFuncName)))
- funcReg->funcPtr = reinterpret_cast<void*>(SQ_DevFuncStub);
-
- if (context == ScriptContext::SERVER)
- return ServerRegisterSquirrelFunc(sqvm, funcReg, unknown);
- else
- return ClientRegisterSquirrelFunc(sqvm, funcReg, unknown);
+ AUTOHOOK_DISPATCH_MODULE(client.dll)
+
+ g_pSquirrel<ScriptContext::CLIENT> = new SquirrelManager<ScriptContext::CLIENT>;
+ g_pSquirrel<ScriptContext::UI> = new SquirrelManager<ScriptContext::UI>;
+
+ //g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc = module.Offset(0x108E0).As<RegisterSquirrelFuncType>();
+ //g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc;
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst = module.Offset(0x12120).As<sq_defconstType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_defconst = g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable = module.Offset(0x5860).As<sq_pushroottableType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_compilebuffer = g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushroottable = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_call = module.Offset(0x8650).As<sq_callType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_call = g_pSquirrel<ScriptContext::CLIENT>->__sq_call;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_newarray = module.Offset(0x39F0).As<sq_newarrayType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_arrayappend = module.Offset(0x3C70).As<sq_arrayappendType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_newarray = g_pSquirrel<ScriptContext::CLIENT>->__sq_newarray;
+ g_pSquirrel<ScriptContext::UI>->__sq_arrayappend = g_pSquirrel<ScriptContext::CLIENT>->__sq_arrayappend;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_newtable = module.Offset(0x3960).As<sq_newtableType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_newslot = module.Offset(0x70B0).As<sq_newslotType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_newtable = g_pSquirrel<ScriptContext::CLIENT>->__sq_newtable;
+ g_pSquirrel<ScriptContext::UI>->__sq_newslot = g_pSquirrel<ScriptContext::CLIENT>->__sq_newslot;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushstring = module.Offset(0x3440).As<sq_pushstringType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger = module.Offset(0x36A0).As<sq_pushintegerType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat = module.Offset(0x3800).As<sq_pushfloatType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool = module.Offset(0x3710).As<sq_pushboolType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset = module.Offset(0x3560).As<sq_pushassetType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector = module.Offset(0x3780).As<sq_pushvectorType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror = module.Offset(0x8470).As<sq_raiseerrorType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_pushstring = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushstring;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushinteger = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushfloat = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushbool = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushvector = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushasset = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset;
+ g_pSquirrel<ScriptContext::UI>->__sq_raiseerror = g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror;
+
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring = module.Offset(0x60C0).As<sq_getstringType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger = module.Offset(0x60E0).As<sq_getintegerType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat = module.Offset(0x6100).As<sq_getfloatType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool = module.Offset(0x6130).As<sq_getboolType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_get = module.Offset(0x7C30).As<sq_getType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset = module.Offset(0x6010).As<sq_getassetType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata = module.Offset(0x63D0).As<sq_getuserdataType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector = module.Offset(0x6140).As<sq_getvectorType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_getstring = g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring;
+ g_pSquirrel<ScriptContext::UI>->__sq_getinteger = g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger;
+ g_pSquirrel<ScriptContext::UI>->__sq_getfloat = g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat;
+ g_pSquirrel<ScriptContext::UI>->__sq_getbool = g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool;
+ g_pSquirrel<ScriptContext::UI>->__sq_get = g_pSquirrel<ScriptContext::CLIENT>->__sq_get;
+ g_pSquirrel<ScriptContext::UI>->__sq_getasset = g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset;
+ g_pSquirrel<ScriptContext::UI>->__sq_getuserdata = g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata;
+ g_pSquirrel<ScriptContext::UI>->__sq_getvector = g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata = module.Offset(0x38D0).As<sq_createuserdataType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid = module.Offset(0x6490).As<sq_setuserdatatypeidType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_createuserdata = g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata;
+ g_pSquirrel<ScriptContext::UI>->__sq_setuserdatatypeid = g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid;
+
+ // uiscript_reset concommand: don't loop forever if compilation fails
+ module.Offset(0x3C6E4C).NOP(6);
+
+ MAKEHOOK(module.Offset(0x8AD0),
+ &sq_compiler_createHook<ScriptContext::CLIENT>,
+ &sq_compiler_create<ScriptContext::CLIENT>);
+
+ MAKEHOOK(module.Offset(0x12B00), &SQPrintHook<ScriptContext::CLIENT>, &SQPrint<ScriptContext::CLIENT>);
+ MAKEHOOK(module.Offset(0x12BA0), &SQPrintHook<ScriptContext::UI>, &SQPrint<ScriptContext::UI>);
+
+ MAKEHOOK(module.Offset(0x26130), &CreateNewVMHook<ScriptContext::CLIENT>, &CreateNewVM<ScriptContext::CLIENT>);
+ MAKEHOOK(module.Offset(0x26E70), &DestroyVMHook<ScriptContext::CLIENT>, &DestroyVM<ScriptContext::CLIENT>);
+ MAKEHOOK(
+ module.Offset(0x79A50),
+ &ScriptCompileErrorHook<ScriptContext::CLIENT>,
+ &SQCompileError<ScriptContext::CLIENT>);
+
+ MAKEHOOK(
+ module.Offset(0x10190),
+ &CallScriptInitCallbackHook<ScriptContext::CLIENT>,
+ &CallScriptInitCallback<ScriptContext::CLIENT>);
+
+ MAKEHOOK(module.Offset(0x108E0), &RegisterSquirrelFunctionHook<ScriptContext::CLIENT>, &g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc);
+
+ g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc;
+
+ RegisterConCommand("script_client", ConCommand_script<ScriptContext::CLIENT>, "Executes script code on the client vm", FCVAR_CLIENTDLL);
+ RegisterConCommand("script_ui", ConCommand_script<ScriptContext::UI>, "Executes script code on the ui vm", FCVAR_CLIENTDLL);
+
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevTextBufferWrite", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevTextBufferClear", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevTextBufferDumpToFile", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("Dev_CommandLineAddParam", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevP4Checkout", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevP4Add", SQ_Stub);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevTextBufferWrite", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevTextBufferClear", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevTextBufferDumpToFile", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("Dev_CommandLineAddParam", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevP4Checkout", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevP4Add", SQ_Stub);
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+
+ g_pSquirrel<ScriptContext::SERVER> = new SquirrelManager<ScriptContext::SERVER>;
+
+ //g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc = module.Offset(0x1DD10).As<RegisterSquirrelFuncType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_defconst = module.Offset(0x1F550).As<sq_defconstType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushroottable = module.Offset(0x5840).As<sq_pushroottableType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_call = module.Offset(0x8620).As<sq_callType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_newarray = module.Offset(0x39F0).As<sq_newarrayType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_arrayappend = module.Offset(0x3C70).As<sq_arrayappendType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_newtable = module.Offset(0x3960).As<sq_newtableType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_newslot = module.Offset(0x7080).As<sq_newslotType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushstring = module.Offset(0x3440).As<sq_pushstringType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushinteger = module.Offset(0x36A0).As<sq_pushintegerType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushfloat = module.Offset(0x3800).As<sq_pushfloatType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushbool = module.Offset(0x3710).As<sq_pushboolType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushasset = module.Offset(0x3560).As<sq_pushassetType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushvector = module.Offset(0x3780).As<sq_pushvectorType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_raiseerror = module.Offset(0x8440).As<sq_raiseerrorType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getstring = module.Offset(0x60A0).As<sq_getstringType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getinteger = module.Offset(0x60C0).As<sq_getintegerType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getfloat = module.Offset(0x60E0).As<sq_getfloatType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getbool = module.Offset(0x6110).As<sq_getboolType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getasset = module.Offset(0x5FF0).As<sq_getassetType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getuserdata = module.Offset(0x63B0).As<sq_getuserdataType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getvector = module.Offset(0x6120).As<sq_getvectorType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_get = module.Offset(0x7C00).As<sq_getType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_createuserdata = module.Offset(0x38D0).As<sq_createuserdataType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_setuserdatatypeid = module.Offset(0x6470).As<sq_setuserdatatypeidType>();
+
+ MAKEHOOK(module.Offset(0x8AA0),
+ &sq_compiler_createHook<ScriptContext::SERVER>,
+ &sq_compiler_create<ScriptContext::SERVER>);
+
+ MAKEHOOK(module.Offset(0x1FE90), &SQPrintHook<ScriptContext::SERVER>, &SQPrint<ScriptContext::SERVER>);
+ MAKEHOOK(module.Offset(0x260E0), &CreateNewVMHook<ScriptContext::SERVER>, &CreateNewVM<ScriptContext::SERVER>);
+ MAKEHOOK(module.Offset(0x26E20), &DestroyVMHook<ScriptContext::SERVER>, &DestroyVM<ScriptContext::SERVER>);
+ MAKEHOOK(
+ module.Offset(0x799E0),
+ &ScriptCompileErrorHook<ScriptContext::SERVER>,
+ &SQCompileError<ScriptContext::SERVER>);
+ MAKEHOOK(
+ module.Offset(0x1D5C0),
+ &CallScriptInitCallbackHook<ScriptContext::SERVER>,
+ &CallScriptInitCallback<ScriptContext::SERVER>);
+
+ MAKEHOOK(module.Offset(0x1DD10), &RegisterSquirrelFunctionHook<ScriptContext::SERVER>, &g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc);
+
+ // FCVAR_CHEAT and FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS allows clients to execute this, but since it's unsafe we only allow it when cheats
+ // are enabled for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
+ RegisterConCommand(
+ "script",
+ ConCommand_script<ScriptContext::SERVER>,
+ "Executes script code on the server vm",
+ FCVAR_GAMEDLL | FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS | FCVAR_CHEAT);
+
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevTextBufferWrite", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevTextBufferClear", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevTextBufferDumpToFile", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("Dev_CommandLineAddParam", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevP4Checkout", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevP4Add", SQ_Stub);
}
-const char* sq_getTypeName(int type)
+const char* SQTypeNameFromID(int type)
{
switch (type)
{
@@ -536,7 +564,7 @@ const char* sq_getTypeName(int type)
return "float";
case OT_STRING:
return "string";
- case 0x8000040:
+ case OT_ARRAY:
return "array";
case 0x8000200:
return "function";
@@ -554,36 +582,12 @@ const char* sq_getTypeName(int type)
return "unimplemented function";
case 0x8200000:
return "struct instance";
- case 0xA000020:
+ case OT_TABLE:
return "table";
case 0xA008000:
return "instance";
- case 0xA400000:
+ case OT_ENTITY:
return "entity";
}
return "";
-}
-
-SQReturnTypeEnum GetReturnTypeEnumFromString(const char* returnTypeString)
-{
-
- static std::map<std::string, SQReturnTypeEnum> sqEnumStrMap = {
- {"bool", SqReturnBoolean},
- {"float", SqReturnFloat},
- {"vector", SqReturnVector},
- {"int", SqReturnInteger},
- {"entity", SqReturnEntity},
- {"string", SqReturnString},
- {"array", SqReturnArrays},
- {"asset", SqReturnAsset},
- {"table", SqReturnTable}};
-
- if (sqEnumStrMap.count(returnTypeString))
- {
- return sqEnumStrMap[returnTypeString];
- }
- else
- {
- return SqReturnDefault; // previous default value
- }
-}
+} \ No newline at end of file