aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest/squirrel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDedicatedTest/squirrel.cpp')
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp589
1 files changed, 0 insertions, 589 deletions
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
deleted file mode 100644
index 2fa957fb..00000000
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ /dev/null
@@ -1,589 +0,0 @@
-#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"
-
-// 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);
-
-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;
-
-sq_callType ClientSq_call;
-sq_callType ServerSq_call;
-
-// sq stack array funcs
-sq_newarrayType ClientSq_newarray;
-sq_newarrayType ServerSq_newarray;
-
-sq_arrayappendType ClientSq_arrayappend;
-sq_arrayappendType ServerSq_arrayappend;
-
-// sq stack push funcs
-sq_pushstringType ClientSq_pushstring;
-sq_pushstringType ServerSq_pushstring;
-
-sq_pushintegerType ClientSq_pushinteger;
-sq_pushintegerType ServerSq_pushinteger;
-
-sq_pushfloatType ClientSq_pushfloat;
-sq_pushfloatType ServerSq_pushfloat;
-
-sq_pushboolType ClientSq_pushbool;
-sq_pushboolType ServerSq_pushbool;
-
-sq_pusherrorType ClientSq_pusherror;
-sq_pusherrorType ServerSq_pusherror;
-
-sq_defconst ClientSq_defconst;
-sq_defconst ServerSq_defconst;
-
-sq_pushAssetType ClientSq_pushAsset;
-sq_pushAssetType ServerSq_pushAsset;
-
-// sq stack get funcs
-sq_getstringType ClientSq_getstring;
-sq_getstringType ServerSq_getstring;
-
-sq_getintegerType ClientSq_getinteger;
-sq_getintegerType ServerSq_getinteger;
-
-sq_getfloatType ClientSq_getfloat;
-sq_getfloatType ServerSq_getfloat;
-
-sq_getboolType ClientSq_getbool;
-sq_getboolType ServerSq_getbool;
-
-sq_getType ClientSq_sq_get;
-sq_getType ServerSq_sq_get;
-
-sq_newSlotType ServerSq_newSlot;
-sq_newSlotType ClientSq_newSlot;
-
-sq_newTableType ServerSq_newTable;
-sq_newTableType ClientSq_newTable;
-
-template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args);
-
-// inits
-SquirrelManager<ScriptContext::CLIENT>* g_ClientSquirrelManager;
-SquirrelManager<ScriptContext::SERVER>* g_ServerSquirrelManager;
-SquirrelManager<ScriptContext::UI>* g_UISquirrelManager;
-
-SQInteger NSTestFunc(void* sqvm)
-{
- return 1;
-}
-
-void InitialiseClientSquirrel(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);
-
- // 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
-}
-
-void InitialiseServerSquirrel(HMODULE baseAddress)
-{
- 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
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1DD10,
- &RegisterSquirrelFuncHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerRegisterSquirrelFunc)); // server registersquirrelfunc 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
-template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
-
- SQChar buf[1024];
- int charsWritten = vsnprintf_s(buf, _TRUNCATE, fmt, va);
-
- if (charsWritten > 0)
- {
- if (buf[charsWritten - 1] == '\n')
- buf[charsWritten - 1] = '\0';
-
- spdlog::info("[{} SCRIPT] {}", GetContextName(context), buf);
- }
-
- va_end(va);
- return 0;
-}
-
-template <ScriptContext context> void* 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);
- }
-
- spdlog::info("CreateNewVM {} {}", GetContextName(realContext), sqvm);
- return 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 (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);
- }
-
- spdlog::info("DestroyVM {} {}", GetContextName(realContext), sqvm);
-}
-
-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)
- 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
-}
-
-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"))
- {
- 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 (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");
-
- // 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 == ScriptContext::SERVER && modCallback.BeforeCallback.length())
- {
- spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback.BeforeCallback);
- ServerCallScriptInitCallback(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);
-
- // 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 == ScriptContext::SERVER && modCallback.AfterCallback.length())
- {
- spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback.AfterCallback);
- ServerCallScriptInitCallback(sqvm, modCallback.AfterCallback.c_str());
- }
- }
- }
- }
- }
- }
-
- return ret;
-}
-
-template <ScriptContext context> void ExecuteCodeCommand(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());
-}
-
-SQRESULT SQ_DevFuncStub(void* sqvm)
-{
- spdlog::warn("Blocked execution of squirrel developer function for security reasons. To re-enable them use start parameter "
- "-allowSquirrelDevFunctions.");
- return SQRESULT_NULL;
-}
-
-template <ScriptContext context> int64_t RegisterSquirrelFuncHook(void* sqvm, SQFuncRegistration* funcReg, char unknown)
-{
- 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);
-}
-
-const char* sq_getTypeName(int type)
-{
- switch (type)
- {
- case OT_ASSET:
- return "asset";
- case OT_INTEGER:
- return "int";
- case OT_BOOL:
- return "bool";
- case SQOBJECT_NUMERIC:
- return "float or int";
- case OT_NULL:
- return "null";
- case OT_VECTOR:
- return "vector";
- case 0:
- return "var";
- case OT_USERDATA:
- return "userdata";
- case OT_FLOAT:
- return "float";
- case OT_STRING:
- return "string";
- case 0x8000040:
- return "array";
- case 0x8000200:
- return "function";
- case 0x8100000:
- return "structdef";
- case OT_THREAD:
- return "thread";
- case OT_FUNCPROTO:
- return "function";
- case OT_CLAAS:
- return "class";
- case OT_WEAKREF:
- return "weakref";
- case 0x8080000:
- return "unimplemented function";
- case 0x8200000:
- return "struct instance";
- case 0xA000020:
- return "table";
- case 0xA008000:
- return "instance";
- case 0xA400000:
- 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
- }
-}