aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest/squirrel.cpp
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-21 00:51:32 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-21 00:51:32 +0100
commit93fe64e04ed766727634e5b5f6906f6461a70711 (patch)
tree467f58533ddf4c139f896166894bde8213fd34c8 /NorthstarDedicatedTest/squirrel.cpp
parent958d03d2817e312c8eb70234f1c65e4bcbded716 (diff)
downloadNorthstarLauncher-93fe64e04ed766727634e5b5f6906f6461a70711.tar.gz
NorthstarLauncher-93fe64e04ed766727634e5b5f6906f6461a70711.zip
add eval commands and script compile error hook
Diffstat (limited to 'NorthstarDedicatedTest/squirrel.cpp')
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp130
1 files changed, 106 insertions, 24 deletions
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
index 90d16e89..27b997ab 100644
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ b/NorthstarDedicatedTest/squirrel.cpp
@@ -3,6 +3,7 @@
#include "hooks.h"
#include "hookutils.h"
#include "sigscanning.h"
+#include "concommand.h"
#include <iostream>
// hook forward declarations
@@ -12,10 +13,31 @@ SQPrintType UISQPrint;
SQPrintType ServerSQPrint;
template<Context context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...);
-typedef void* (*CreateNewVMType)(void* a1, Context contextArg);
+typedef void*(*CreateNewVMType)(void* a1, Context contextArg);
CreateNewVMType ClientCreateNewVM; // only need a client one since ui doesn't have its own func for this
CreateNewVMType ServerCreateNewVM;
-void* CreateNewVMHook(void* a1, Context contextArg);
+template<Context context> void* CreateNewVMHook(void* a1, Context 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<Context context> void DestroyVMHook(void* a1, void* sqvm);
+
+typedef void (*SQCompileErrorType)(void* sqvm, const char* error, const char* file, int line, int column);
+SQCompileErrorType ClientSQCompileError; // only need a client one since ui doesn't have its own func for this
+SQCompileErrorType ServerSQCompileError;
+template<Context context> void SQCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column);
+
+sq_compilebufferType ClientSq_compilebuffer;
+sq_compilebufferType ServerSq_compilebuffer;
+
+sq_pushroottableType ClientSq_pushroottable;
+sq_pushroottableType ServerSq_pushroottable;
+
+sq_callType ClientSq_call;
+sq_callType ServerSq_call;
+
+template<Context context> void ExecuteCodeCommand(const CCommand& args);
// inits
SquirrelManager<CLIENT>* g_ClientSquirrelManager;
@@ -29,13 +51,21 @@ void InitialiseClientSquirrel(HMODULE baseAddress)
// client inits
g_ClientSquirrelManager = new SquirrelManager<CLIENT>();
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x12B00, &SQPrintHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientSQPrint)); // client print function
+ RegisterConCommand("script_client", ExecuteCodeCommand<CLIENT>, "Executes script code in the client vm", FCVAR_CLIENTDLL);
// ui inits
g_UISquirrelManager = new SquirrelManager<UI>();
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x12BA0, &SQPrintHook<UI>, reinterpret_cast<LPVOID*>(&UISQPrint)); // ui print function
+ RegisterConCommand("script_ui", ExecuteCodeCommand<UI>, "Executes script code in the client 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);
- // hooks for both client and ui, since they share some functions
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26130, &CreateNewVMHook, reinterpret_cast<LPVOID*>(&ClientCreateNewVM)); // client createnewvm function
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26130, &CreateNewVMHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientCreateNewVM)); // client createnewvm function
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26E70, &DestroyVMHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientDestroyVM)); // client destroyvm function
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x79A50, &SQCompileErrorHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientSQCompileError)); // client compileerror function
}
void InitialiseServerSquirrel(HMODULE baseAddress)
@@ -43,8 +73,17 @@ void InitialiseServerSquirrel(HMODULE baseAddress)
g_ServerSquirrelManager = new SquirrelManager<SERVER>();
HookEnabler hook;
+
+ ServerSq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
+ ServerSq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5840);
+ ServerSq_call = (sq_callType)((char*)baseAddress + 0x8620);
+
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1FE90, &SQPrintHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerSQPrint)); // server print function
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x260E0, &CreateNewVMHook, reinterpret_cast<LPVOID*>(&ServerCreateNewVM)); // server createnewvm function
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x260E0, &CreateNewVMHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerCreateNewVM)); // server createnewvm function
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26E20, &DestroyVMHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerDestroyVM)); // server destroyvm function
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x799E0, &SQCompileErrorHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerSQCompileError)); // server compileerror function
+
+ RegisterConCommand("script", ExecuteCodeCommand<SERVER>, "Executes script code in the server vm", FCVAR_GAMEDLL);
}
// hooks
@@ -59,7 +98,7 @@ template<Context context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...)
if (charsWritten > 0)
{
if (buf[charsWritten - 1] == '\n')
- buf[charsWritten - 1] == '\0';
+ buf[charsWritten - 1] = '\0';
spdlog::info("[{} SCRIPT] {}", GetContextName(context), buf);
}
@@ -68,35 +107,78 @@ template<Context context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...)
return 0;
}
-void* CreateNewVMHook(void* a1, Context context)
-{
- spdlog::info("CreateNewVM {}", GetContextName(context));
-
+template<Context context> void* CreateNewVMHook(void* a1, Context realContext)
+{
+ void* sqvm;
+
if (context == CLIENT)
{
- void* sqvm = ClientCreateNewVM(a1, context);
- g_ClientSquirrelManager->sqvm = sqvm;
+ sqvm = ClientCreateNewVM(a1, realContext);
- return sqvm;
+ if (realContext == UI)
+ g_UISquirrelManager->sqvm = sqvm;
+ else
+ g_ClientSquirrelManager->sqvm = sqvm;
}
- else if (context == UI)
+ else if (context == SERVER)
{
- void* sqvm = ClientCreateNewVM(a1, context);
- g_UISquirrelManager->sqvm = sqvm;
+ sqvm = ServerCreateNewVM(a1, context);
+ g_ServerSquirrelManager->sqvm = sqvm;
+ }
+
+ spdlog::info("CreateNewVM {} {}", GetContextName(context), sqvm);
+ return sqvm;
+}
+
+template<Context context> void DestroyVMHook(void* a1, void* sqvm)
+{
+ Context realContext = context; // ui and client use the same function so we use this for prints
- return sqvm;
+ if (context == CLIENT)
+ {
+ if (g_ClientSquirrelManager->sqvm == sqvm)
+ g_ClientSquirrelManager->sqvm = nullptr;
+ else if (g_UISquirrelManager->sqvm == sqvm)
+ {
+ g_UISquirrelManager->sqvm = nullptr;
+ realContext == UI;
+ }
+
+ ClientDestroyVM(a1, sqvm);
}
else if (context == SERVER)
{
- void* sqvm = ServerCreateNewVM(a1, context);
- g_ServerSquirrelManager->sqvm = sqvm;
-
- return sqvm;
+ g_ServerSquirrelManager->sqvm = nullptr;
+ ServerDestroyVM(a1, sqvm);
}
+
+ spdlog::info("DestroyVM {} {}", GetContextName(realContext), sqvm);
}
-// manager
-template<Context context> SquirrelManager<context>::SquirrelManager() : sqvm(nullptr)
+template<Context context> void SQCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column)
{
-
+ // note: i think vanilla might actually show the script line that errored, might be nice to implement that if it's a thing
+ // look into client.dll+79540 for way better errors too
+
+ Context realContext = context;
+ if (context == CLIENT && sqvm == g_UISquirrelManager->sqvm)
+ realContext = 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<Context context> void ExecuteCodeCommand(const CCommand& args)
+{
+ if (context == CLIENT)
+ g_ClientSquirrelManager->ExecuteCode(args.ArgS());
+ else if (context == UI)
+ g_UISquirrelManager->ExecuteCode(args.ArgS());
+ else if (context == SERVER)
+ g_ServerSquirrelManager->ExecuteCode(args.ArgS());
} \ No newline at end of file