aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest/squirrel.cpp
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2022-05-09 16:42:33 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2022-05-09 16:42:33 +0100
commit5a58dd1c05e943d6b440bea5b4a6ae80ce16841e (patch)
tree9ea18142c2e2885b990671c04db4786aa05f86f3 /NorthstarDedicatedTest/squirrel.cpp
parent77a1195d77034c00959dfd030e2eb7a57d58a88d (diff)
downloadNorthstarLauncher-5a58dd1c05e943d6b440bea5b4a6ae80ce16841e.tar.gz
NorthstarLauncher-5a58dd1c05e943d6b440bea5b4a6ae80ce16841e.zip
refactor some squirrel stuff and ingame compilation error message
Diffstat (limited to 'NorthstarDedicatedTest/squirrel.cpp')
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp526
1 files changed, 235 insertions, 291 deletions
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
index 1772bdb8..7851192b 100644
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ b/NorthstarDedicatedTest/squirrel.cpp
@@ -2,58 +2,28 @@
#include "squirrel.h"
#include "hooks.h"
#include "hookutils.h"
-#include "sigscanning.h"
#include "concommand.h"
#include "modmanager.h"
-#include <iostream>
-
-// 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, ...);
-
-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);
+#include "gameutils.h"
RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
-template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args);
-
// inits
-SquirrelManager<ScriptContext::CLIENT>* g_ClientSquirrelManager;
-SquirrelManager<ScriptContext::SERVER>* g_ServerSquirrelManager;
-SquirrelManager<ScriptContext::UI>* g_UISquirrelManager;
+SquirrelManager<ScriptContext::CLIENT>* g_pClientSquirrel;
+SquirrelManager<ScriptContext::SERVER>* g_pServerSquirrel;
+SquirrelManager<ScriptContext::UI>* g_pUISquirrel;
template <ScriptContext context> SquirrelManager<context>* GetSquirrelManager()
{
switch (context)
{
case ScriptContext::CLIENT:
- return g_ClientSquirrelManager;
+ return g_pClientSquirrel;
case ScriptContext::SERVER:
- return g_ServerSquirrelManager;
+ return g_pServerSquirrel;
case ScriptContext::UI:
- return g_UISquirrelManager;
+ return g_pUISquirrel;
}
}
@@ -70,149 +40,11 @@ const char* GetContextName(ScriptContext context)
}
}
-ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (HMODULE baseAddress)
-{
- HookEnabler hook;
-
- // client inits
- g_ClientSquirrelManager = new SquirrelManager<ScriptContext::CLIENT>();
-
- 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);
-
- ClientRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0);
-
- g_ClientSquirrelManager->sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- g_UISquirrelManager->sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- g_ClientSquirrelManager->sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860);
- g_UISquirrelManager->sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860);
-
- g_ClientSquirrelManager->sq_call = (sq_callType)((char*)baseAddress + 0x8650);
- g_UISquirrelManager->sq_call = (sq_callType)((char*)baseAddress + 0x8650);
-
- g_ClientSquirrelManager->sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- g_UISquirrelManager->sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- g_ClientSquirrelManager->sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
- g_UISquirrelManager->sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
-
- g_ClientSquirrelManager->sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- g_UISquirrelManager->sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- g_ClientSquirrelManager->sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- g_UISquirrelManager->sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- g_ClientSquirrelManager->sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- g_UISquirrelManager->sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- g_ClientSquirrelManager->sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- g_UISquirrelManager->sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- g_ClientSquirrelManager->sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8470);
- g_UISquirrelManager->sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8470);
-
- g_ClientSquirrelManager->sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
- g_UISquirrelManager->sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
- g_ClientSquirrelManager->sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
- g_UISquirrelManager->sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
- g_ClientSquirrelManager->sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
- g_UISquirrelManager->sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
- g_ClientSquirrelManager->sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130);
- g_UISquirrelManager->sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130);
- g_ClientSquirrelManager->sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
- g_UISquirrelManager->sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
-
- 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
-})
-
-ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (HMODULE baseAddress)
-{
- g_ServerSquirrelManager = new SquirrelManager<ScriptContext::SERVER>();
-
- ServerRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x1DD10);
-
- g_ServerSquirrelManager->sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- g_ServerSquirrelManager->sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5840);
- g_ServerSquirrelManager->sq_call = (sq_callType)((char*)baseAddress + 0x8620);
-
- g_ServerSquirrelManager->sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- g_ServerSquirrelManager->sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
-
- g_ServerSquirrelManager->sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- g_ServerSquirrelManager->sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- g_ServerSquirrelManager->sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- g_ServerSquirrelManager->sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- g_ServerSquirrelManager->sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8440);
-
- g_ServerSquirrelManager->sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0);
- g_ServerSquirrelManager->sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0);
- g_ServerSquirrelManager->sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x60E0);
- g_ServerSquirrelManager->sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6110);
- g_ServerSquirrelManager->sq_get = (sq_getType)((char*)baseAddress + 0x7C00);
-
- HookEnabler hook;
- 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
-
- // 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);
-})
-
// hooks
+typedef SQInteger (*SQPrintType)(void* sqvm, char* fmt, ...);
+SQPrintType ClientSQPrint;
+SQPrintType UISQPrint;
+SQPrintType ServerSQPrint;
template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...)
{
va_list va;
@@ -233,6 +65,9 @@ template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ..
return 0;
}
+typedef void* (*CreateNewVMType)(void* a1, ScriptContext contextArg);
+CreateNewVMType ClientCreateNewVM;
+CreateNewVMType ServerCreateNewVM;
template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext realContext)
{
void* sqvm;
@@ -242,31 +77,34 @@ template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext r
sqvm = ClientCreateNewVM(a1, realContext);
if (realContext == ScriptContext::UI)
- g_UISquirrelManager->VMCreated(sqvm);
+ g_pUISquirrel->VMCreated(sqvm);
else
- g_ClientSquirrelManager->VMCreated(sqvm);
+ g_pClientSquirrel->VMCreated(sqvm);
}
else if (context == ScriptContext::SERVER)
{
sqvm = ServerCreateNewVM(a1, context);
- g_ServerSquirrelManager->VMCreated(sqvm);
+ g_pServerSquirrel->VMCreated(sqvm);
}
spdlog::info("CreateNewVM {} {}", GetContextName(realContext), sqvm);
return sqvm;
}
+typedef void (*DestroyVMType)(void* a1, void* sqvm);
+DestroyVMType ClientDestroyVM;
+DestroyVMType ServerDestroyVM;
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 (g_ClientSquirrelManager->sqvm == sqvm)
- g_ClientSquirrelManager->VMDestroyed();
- else if (g_UISquirrelManager->sqvm == sqvm)
+ if (g_pClientSquirrel->sqvm == sqvm)
+ g_pClientSquirrel->VMDestroyed();
+ else if (g_pUISquirrel->sqvm == sqvm)
{
- g_UISquirrelManager->VMDestroyed();
+ g_pUISquirrel->VMDestroyed();
realContext = ScriptContext::UI;
}
@@ -274,148 +112,108 @@ template <ScriptContext context> void DestroyVMHook(void* a1, void* sqvm)
}
else if (context == ScriptContext::SERVER)
{
- g_ServerSquirrelManager->VMDestroyed();
+ g_pServerSquirrel->VMDestroyed();
ServerDestroyVM(a1, sqvm);
}
spdlog::info("DestroyVM {} {}", GetContextName(realContext), sqvm);
}
+typedef void (*ScriptCompileError)(void* sqvm, const char* error, const char* file, int line, int column);
+ScriptCompileError ClientSQCompileError;
+ScriptCompileError ServerSQCompileError;
template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column)
{
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_pUISquirrel->sqvm2)
realContext = ScriptContext::UI;
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 we aren't compiling from console, or from compilestring()
+ // TODO: compilestring can actually define a custom buffer name as the second arg, we don't currently have a way of checking this
+ // ideally we'd just check if the sqvm was fully initialised here, somehow
+ if (strcmp(file, "console") && strcmp(file, "unnamedbuffer"))
+ {
+ Cbuf_AddText(
+ Cbuf_GetCurrentPlayer(),
+ fmt::format("disconnect \"Encountered {} script compilation error, see console for details.\"", GetContextName(realContext))
+ .c_str(),
+ cmd_source_t::kCommandSrcCode);
+
+ // TODO: for ui script, we need to prevent the infinite compilation error loop the game will get into on uiscript_reset if there is a compilation error
+ }
+
+ // dont call the original function since it kills game lol
}
-template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, const char* callback)
+typedef bool (*CallScriptInitCallbackType)(void* sqvm, const char* callback);
+CallScriptInitCallbackType ClientCallScriptInitCallback;
+CallScriptInitCallbackType ServerCallScriptInitCallback;
+template <ScriptContext context> bool CallScriptInitCallbackHook(void* sqvm, const char* callback)
{
- char ret;
+ CallScriptInitCallbackType callScriptInitCallback;
+ ScriptContext realContext = context;
+ bool shouldCallCustomCallbacks = true;
if (context == ScriptContext::CLIENT)
{
- ScriptContext realContext = context; // ui and client use the same function so we use this for prints
- bool shouldCallCustomCallbacks = false;
+ callScriptInitCallback = ClientCallScriptInitCallback;
- // since we don't hook arbitrary callbacks yet, make sure we're only doing callbacks on inits
if (!strcmp(callback, "UICodeCallback_UIInit"))
- {
realContext = ScriptContext::UI;
- shouldCallCustomCallbacks = true;
- }
- 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;
-
- 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());
- }
- }
- }
- }
- }
-
- spdlog::info("{} CodeCallback {} called", GetContextName(realContext), callback);
- if (!shouldCallCustomCallbacks)
- spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
- ret = ClientCallScriptInitCallback(sqvm, callback);
-
- // run after callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- 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());
- }
- }
- }
- }
- }
+ else if (strcmp(callback, "ClientCodeCallback_MapSpawn"))
+ shouldCallCustomCallbacks = 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");
+ callScriptInitCallback = ServerCallScriptInitCallback;
+ shouldCallCustomCallbacks = !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 (shouldCallCustomCallbacks)
+ {
+ for (Mod mod : g_ModManager->m_loadedMods)
{
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
+ if (!mod.Enabled)
+ 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(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 (!shouldCallCustomCallbacks)
+ spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
+ bool ret = callScriptInitCallback(sqvm, callback);
- // run after callbacks
- if (shouldCallCustomCallbacks)
+ // run after callbacks
+ if (shouldCallCustomCallbacks)
+ {
+ for (Mod mod : g_ModManager->m_loadedMods)
{
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
+ if (!mod.Enabled)
+ 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(sqvm, modCallback.AfterCallback.c_str());
}
}
}
@@ -428,9 +226,155 @@ template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, con
template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args)
{
if (context == ScriptContext::CLIENT)
- g_ClientSquirrelManager->ExecuteCode(args.ArgS());
+ g_pClientSquirrel->ExecuteCode(args.ArgS());
else if (context == ScriptContext::UI)
- g_UISquirrelManager->ExecuteCode(args.ArgS());
+ g_pUISquirrel->ExecuteCode(args.ArgS());
else if (context == ScriptContext::SERVER)
- g_ServerSquirrelManager->ExecuteCode(args.ArgS());
-} \ No newline at end of file
+ g_pServerSquirrel->ExecuteCode(args.ArgS());
+}
+
+ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (HMODULE baseAddress)
+{
+ HookEnabler hook;
+
+ // client inits
+ g_pClientSquirrel = new SquirrelManager<ScriptContext::CLIENT>;
+
+ 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_pUISquirrel = 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);
+
+ g_pClientSquirrel->RegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0);
+ g_pUISquirrel->RegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0);
+
+ g_pClientSquirrel->sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
+ g_pUISquirrel->sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
+ g_pClientSquirrel->sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860);
+ g_pUISquirrel->sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860);
+
+ g_pClientSquirrel->sq_call = (sq_callType)((char*)baseAddress + 0x8650);
+ g_pUISquirrel->sq_call = (sq_callType)((char*)baseAddress + 0x8650);
+
+ g_pClientSquirrel->sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
+ g_pUISquirrel->sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
+ g_pClientSquirrel->sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
+ g_pUISquirrel->sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
+
+ g_pClientSquirrel->sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
+ g_pUISquirrel->sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
+ g_pClientSquirrel->sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
+ g_pUISquirrel->sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
+ g_pClientSquirrel->sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
+ g_pUISquirrel->sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
+ g_pClientSquirrel->sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
+ g_pUISquirrel->sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
+ g_pClientSquirrel->sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8470);
+ g_pUISquirrel->sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8470);
+
+ g_pClientSquirrel->sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
+ g_pUISquirrel->sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
+ g_pClientSquirrel->sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
+ g_pUISquirrel->sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
+ g_pClientSquirrel->sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
+ g_pUISquirrel->sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
+ g_pClientSquirrel->sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130);
+ g_pUISquirrel->sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130);
+ g_pClientSquirrel->sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
+ g_pUISquirrel->sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
+
+ 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
+})
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (HMODULE baseAddress)
+{
+ g_pServerSquirrel = new SquirrelManager<ScriptContext::SERVER>;
+
+ g_pServerSquirrel->RegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x1DD10);
+
+ g_pServerSquirrel->sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
+ g_pServerSquirrel->sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5840);
+ g_pServerSquirrel->sq_call = (sq_callType)((char*)baseAddress + 0x8620);
+
+ g_pServerSquirrel->sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
+ g_pServerSquirrel->sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
+
+ g_pServerSquirrel->sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
+ g_pServerSquirrel->sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
+ g_pServerSquirrel->sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
+ g_pServerSquirrel->sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
+ g_pServerSquirrel->sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8440);
+
+ g_pServerSquirrel->sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0);
+ g_pServerSquirrel->sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0);
+ g_pServerSquirrel->sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x60E0);
+ g_pServerSquirrel->sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6110);
+ g_pServerSquirrel->sq_get = (sq_getType)((char*)baseAddress + 0x7C00);
+
+ HookEnabler hook;
+ 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
+
+ // 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);
+}) \ No newline at end of file