aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-25 18:19:26 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-25 18:19:26 +0100
commit80428e6f62899162c036f2752edfbfd7d1adb80b (patch)
tree28dd9731e8947f5d14ddbe2da9aa4ecd94e1ec88
parentbb2caa078c64e2207482806da891c37e75551faf (diff)
downloadNorthstarLauncher-80428e6f62899162c036f2752edfbfd7d1adb80b.tar.gz
NorthstarLauncher-80428e6f62899162c036f2752edfbfd7d1adb80b.zip
add custom native script function support
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp65
-rw-r--r--NorthstarDedicatedTest/squirrel.h72
2 files changed, 127 insertions, 10 deletions
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
index addb8862..15c144c5 100644
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ b/NorthstarDedicatedTest/squirrel.cpp
@@ -43,6 +43,9 @@ sq_pushroottableType ServerSq_pushroottable;
sq_callType ClientSq_call;
sq_callType ServerSq_call;
+RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
+RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
+
template<Context context> void ExecuteCodeCommand(const CCommand& args);
// inits
@@ -50,24 +53,32 @@ SquirrelManager<CLIENT>* g_ClientSquirrelManager;
SquirrelManager<SERVER>* g_ServerSquirrelManager;
SquirrelManager<UI>* g_UISquirrelManager;
+SQInteger NSTestFunc(void* sqvm)
+{
+ return 1;
+}
+
void InitialiseClientSquirrel(HMODULE baseAddress)
{
HookEnabler hook;
// 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);
+ RegisterConCommand("script_client", ExecuteCodeCommand<CLIENT>, "Executes script code on 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);
+ RegisterConCommand("script_ui", ExecuteCodeCommand<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);
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
@@ -84,13 +95,14 @@ void InitialiseServerSquirrel(HMODULE baseAddress)
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 + 0x1DDD10);
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1FE90, &SQPrintHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerSQPrint)); // server print 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, &ScriptCompileErrorHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerSQCompileError)); // server compileerror function
- RegisterConCommand("script", ExecuteCodeCommand<SERVER>, "Executes script code in the server vm", FCVAR_GAMEDLL);
+ RegisterConCommand("script", ExecuteCodeCommand<SERVER>, "Executes script code on the server vm", FCVAR_GAMEDLL);
}
// hooks
@@ -244,7 +256,52 @@ template<Context context> char CallScriptInitCallbackHook(void* sqvm, const char
}
else if (context == SERVER)
{
- // todo lol
+ // 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)
+ {
+ for (ModScript* script : mod->Scripts)
+ {
+ for (ModScriptCallback* modCallback : script->Callbacks)
+ {
+ if (modCallback->Context == 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)
+ {
+ for (ModScript* script : mod->Scripts)
+ {
+ for (ModScriptCallback* modCallback : script->Callbacks)
+ {
+ if (modCallback->Context == SERVER && modCallback->AfterCallback.length())
+ {
+ spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback->AfterCallback);
+ ClientCallScriptInitCallback(sqvm, modCallback->AfterCallback.c_str());
+ }
+ }
+ }
+ }
+ }
}
return ret;
diff --git a/NorthstarDedicatedTest/squirrel.h b/NorthstarDedicatedTest/squirrel.h
index 43f6cef8..2704dbc7 100644
--- a/NorthstarDedicatedTest/squirrel.h
+++ b/NorthstarDedicatedTest/squirrel.h
@@ -26,6 +26,33 @@ struct CompileBufferState
}
};
+struct SQFuncRegistration
+{
+ const char* squirrelFuncName;
+ const char* cppFuncName;
+ const char* helpText;
+ const char* returnValueType;
+ const char* argTypes;
+ int16_t somethingThatsZero;
+ int16_t padding1;
+ int32_t unknown1;
+ int64_t unknown2;
+ int32_t unknown3;
+ int32_t padding2;
+ int64_t unknown4;
+ int64_t unknown5;
+ int64_t unknown6;
+ int32_t unknown7;
+ int32_t padding3;
+ void* funcPtr;
+
+ SQFuncRegistration()
+ {
+ memset(this, 0, sizeof(SQFuncRegistration));
+ this->padding2 = 32;
+ }
+};
+
typedef SQRESULT(*sq_compilebufferType)(void* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, int a2);
extern sq_compilebufferType ClientSq_compilebuffer;
extern sq_compilebufferType ServerSq_compilebuffer;
@@ -38,22 +65,41 @@ typedef SQRESULT(*sq_callType)(void* sqvm, SQInteger s1, SQBool a2, SQBool a3);
extern sq_callType ClientSq_call;
extern sq_callType ServerSq_call;
+typedef int64_t(*RegisterSquirrelFuncType)(void* sqvm, SQFuncRegistration* funcReg, char unknown);
+extern RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
+extern RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
+
//template<Context context> void ExecuteSQCode(SquirrelManager<context> sqManager, const char* code); // need this because we can't do template class functions in the .cpp file
typedef SQInteger(*SQFunction)(void* sqvm);
template<Context context> class SquirrelManager
{
+private:
+ std::vector<SQFuncRegistration*> m_funcRegistrations;
+
public:
void* sqvm;
+ void* sqvm2;
public:
SquirrelManager() : sqvm(nullptr)
{}
- void VMCreated(void* sqvm)
+ void VMCreated(void* newSqvm)
{
- sqvm = sqvm;
+ sqvm = newSqvm;
+ sqvm2 = *((void**)((char*)sqvm + 8)); // honestly not 100% sure on what this is, but alot of functions take it
+
+ for (SQFuncRegistration* funcReg : m_funcRegistrations)
+ {
+ spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName);
+
+ if (context == CLIENT || context == UI)
+ ClientRegisterSquirrelFunc(sqvm, funcReg, 1);
+ else
+ ServerRegisterSquirrelFunc(sqvm, funcReg, 1);
+ }
}
void VMDestroyed()
@@ -71,9 +117,6 @@ public:
return;
}
- void* sqvm2 = *((void**)((char*)sqvm + 8)); // honestly not 100% sure on what this is, but it seems to be what this function is supposed to take
- // potentially move to a property later if it's used alot
-
spdlog::info("Executing {} script code {} ", GetContextName(context), code);
std::string strCode(code);
@@ -105,7 +148,24 @@ public:
void AddFuncRegistration(std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func)
{
-
+ SQFuncRegistration* reg = new SQFuncRegistration;
+
+ reg->squirrelFuncName = new char[name.size() + 1];
+ strcpy((char*)reg->squirrelFuncName, name.c_str());
+ reg->cppFuncName = reg->squirrelFuncName;
+
+ reg->helpText = new char[helpText.size() + 1];
+ strcpy((char*)reg->helpText, helpText.c_str());
+
+ reg->returnValueType = new char[returnType.size() + 1];
+ strcpy((char*)reg->returnValueType, returnType.c_str());
+
+ reg->argTypes = new char[argTypes.size() + 1];
+ strcpy((char*)reg->argTypes, argTypes.c_str());
+
+ reg->funcPtr = func;
+
+ m_funcRegistrations.push_back(reg);
}
};