diff options
Diffstat (limited to 'NorthstarDLL/squirrel')
-rw-r--r-- | NorthstarDLL/squirrel/squirrel.cpp | 943 | ||||
-rw-r--r-- | NorthstarDLL/squirrel/squirrel.h | 526 | ||||
-rw-r--r-- | NorthstarDLL/squirrel/squirrelautobind.cpp | 20 | ||||
-rw-r--r-- | NorthstarDLL/squirrel/squirrelautobind.h | 76 | ||||
-rw-r--r-- | NorthstarDLL/squirrel/squirrelclasstypes.h | 248 | ||||
-rw-r--r-- | NorthstarDLL/squirrel/squirreldatatypes.h | 501 |
6 files changed, 0 insertions, 2314 deletions
diff --git a/NorthstarDLL/squirrel/squirrel.cpp b/NorthstarDLL/squirrel/squirrel.cpp deleted file mode 100644 index ac9a2ce9..00000000 --- a/NorthstarDLL/squirrel/squirrel.cpp +++ /dev/null @@ -1,943 +0,0 @@ -#include "squirrel.h" -#include "mods/modsavefiles.h" -#include "logging/logging.h" -#include "core/convar/concommand.h" -#include "mods/modmanager.h" -#include "dedicated/dedicated.h" -#include "engine/r2engine.h" -#include "core/tier0.h" -#include "plugins/plugin_abi.h" -#include "plugins/plugins.h" -#include "ns_version.h" -#include "core/vanilla.h" - -#include <any> - -AUTOHOOK_INIT() - -std::shared_ptr<ColoredLogger> getSquirrelLoggerByContext(ScriptContext context) -{ - switch (context) - { - case ScriptContext::UI: - return NS::log::SCRIPT_UI; - case ScriptContext::CLIENT: - return NS::log::SCRIPT_CL; - case ScriptContext::SERVER: - return NS::log::SCRIPT_SV; - default: - throw std::runtime_error("getSquirrelLoggerByContext called with invalid context"); - return nullptr; - } -} - -namespace NS::log -{ - template <ScriptContext context> std::shared_ptr<spdlog::logger> squirrel_logger() - { - // Switch statements can't be constexpr afaik - // clang-format off - if constexpr (context == ScriptContext::UI) { return SCRIPT_UI; } - if constexpr (context == ScriptContext::CLIENT) { return SCRIPT_CL; } - if constexpr (context == ScriptContext::SERVER) { return SCRIPT_SV; } - // clang-format on - } -}; // namespace NS::log - -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"; - } -} - -const char* GetContextName_Short(ScriptContext context) -{ - switch (context) - { - case ScriptContext::CLIENT: - return "CL"; - case ScriptContext::SERVER: - return "SV"; - case ScriptContext::UI: - return "UI"; - default: - return "??"; - } -} - -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 -} - -ScriptContext ScriptContextFromString(std::string string) -{ - if (string == "UI") - return ScriptContext::UI; - if (string == "CLIENT") - return ScriptContext::CLIENT; - if (string == "SERVER") - return ScriptContext::SERVER; - else - return ScriptContext::INVALID; -} - -const char* SQTypeNameFromID(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 OT_ARRAY: - 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 OT_TABLE: - return "table"; - case 0xA008000: - return "instance"; - case OT_ENTITY: - return "entity"; - } - return ""; -} - -template <ScriptContext context> void SquirrelManager<context>::GenerateSquirrelFunctionsStruct(SquirrelFunctions* s) -{ - s->RegisterSquirrelFunc = RegisterSquirrelFunc; - s->__sq_defconst = __sq_defconst; - - s->__sq_compilebuffer = __sq_compilebuffer; - s->__sq_call = __sq_call; - s->__sq_raiseerror = __sq_raiseerror; - s->__sq_compilefile = __sq_compilefile; - - s->__sq_newarray = __sq_newarray; - s->__sq_arrayappend = __sq_arrayappend; - - s->__sq_newtable = __sq_newtable; - s->__sq_newslot = __sq_newslot; - - s->__sq_pushroottable = __sq_pushroottable; - s->__sq_pushstring = __sq_pushstring; - s->__sq_pushinteger = __sq_pushinteger; - s->__sq_pushfloat = __sq_pushfloat; - s->__sq_pushbool = __sq_pushbool; - s->__sq_pushasset = __sq_pushasset; - s->__sq_pushvector = __sq_pushvector; - s->__sq_pushobject = __sq_pushobject; - - s->__sq_getstring = __sq_getstring; - s->__sq_getinteger = __sq_getinteger; - s->__sq_getfloat = __sq_getfloat; - s->__sq_getbool = __sq_getbool; - s->__sq_get = __sq_get; - s->__sq_getasset = __sq_getasset; - s->__sq_getuserdata = __sq_getuserdata; - s->__sq_getvector = __sq_getvector; - s->__sq_getthisentity = __sq_getthisentity; - s->__sq_getobject = __sq_getobject; - - s->__sq_stackinfos = __sq_stackinfos; - - s->__sq_createuserdata = __sq_createuserdata; - s->__sq_setuserdatatypeid = __sq_setuserdatatypeid; - s->__sq_getfunction = __sq_getfunction; - - s->__sq_schedule_call_external = AsyncCall_External; - - s->__sq_getentityfrominstance = __sq_getentityfrominstance; - s->__sq_GetEntityConstant_CBaseEntity = __sq_GetEntityConstant_CBaseEntity; - - s->__sq_pushnewstructinstance = __sq_pushnewstructinstance; - s->__sq_sealstructslot = __sq_sealstructslot; -} - -// Allows for generating squirrelmessages from plugins. -void AsyncCall_External(ScriptContext context, const char* func_name, SquirrelMessage_External_Pop function, void* userdata) -{ - SquirrelMessage message {}; - message.functionName = func_name; - message.isExternal = true; - message.externalFunc = function; - message.userdata = userdata; - switch (context) - { - case ScriptContext::CLIENT: - g_pSquirrel<ScriptContext::CLIENT>->messageBuffer->push(message); - break; - case ScriptContext::SERVER: - g_pSquirrel<ScriptContext::SERVER>->messageBuffer->push(message); - break; - case ScriptContext::UI: - g_pSquirrel<ScriptContext::UI>->messageBuffer->push(message); - break; - } -} - -// 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>; - -template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquirrelVM* newSqvm) -{ - m_pSQVM = newSqvm; - - for (SQFuncRegistration* funcReg : m_funcRegistrations) - { - spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName); - RegisterSquirrelFunc(m_pSQVM, funcReg, 1); - } - - for (auto& pair : g_pModManager->m_DependencyConstants) - { - bool bWasFound = false; - - for (Mod& dependency : g_pModManager->m_LoadedMods) - { - if (!dependency.m_bEnabled) - continue; - - if (dependency.Name == pair.second) - { - bWasFound = true; - break; - } - } - - defconst(m_pSQVM, pair.first.c_str(), bWasFound); - } - - auto loadedPlugins = &g_pPluginManager->m_vLoadedPlugins; - for (const auto& pluginName : g_pModManager->m_PluginDependencyConstants) - { - auto f = [&](Plugin plugin) -> bool { return plugin.dependencyName == pluginName; }; - defconst(m_pSQVM, pluginName.c_str(), std::find_if(loadedPlugins->begin(), loadedPlugins->end(), f) != loadedPlugins->end()); - } - - defconst(m_pSQVM, "MAX_FOLDER_SIZE", GetMaxSaveFolderSize() / 1024); - - // define squirrel constants for northstar(.dll) version - constexpr int version[4] {NORTHSTAR_VERSION}; - defconst(m_pSQVM, "NS_VERSION_MAJOR", version[0]); - defconst(m_pSQVM, "NS_VERSION_MINOR", version[1]); - defconst(m_pSQVM, "NS_VERSION_PATCH", version[2]); - defconst(m_pSQVM, "NS_VERSION_DEV", version[3]); - - // define squirrel constant for if we are in vanilla-compatibility mode - defconst(m_pSQVM, "VANILLA", g_pVanillaCompatibility->GetVanillaCompatibility()); - - g_pSquirrel<context>->messageBuffer = new SquirrelMessageBuffer(); - g_pPluginManager->InformSQVMCreated(context, newSqvm); -} - -template <ScriptContext context> void SquirrelManager<context>::VMDestroyed() -{ - // Call all registered mod Destroy callbacks. - if (g_pModManager) - { - NS::log::squirrel_logger<context>()->info("Calling Destroy callbacks for all loaded mods."); - - for (const Mod& loadedMod : g_pModManager->m_LoadedMods) - { - for (const ModScript& script : loadedMod.Scripts) - { - for (const ModScriptCallback& callback : script.Callbacks) - { - if (callback.Context != context || callback.DestroyCallback.length() == 0) - { - continue; - } - - Call(callback.DestroyCallback.c_str()); - NS::log::squirrel_logger<context>()->info("Executed Destroy callback {}.", callback.DestroyCallback); - } - } - } - } - - g_pPluginManager->InformSQVMDestroyed(context); - - // Discard the previous vm and delete the message buffer. - m_pSQVM = nullptr; - - delete g_pSquirrel<context>->messageBuffer; - g_pSquirrel<context>->messageBuffer = nullptr; -} - -template <ScriptContext context> void SquirrelManager<context>::ExecuteCode(const char* pCode) -{ - if (!m_pSQVM || !m_pSQVM->sqvm) - { - spdlog::error("Cannot execute code, {} squirrel vm is not initialised", GetContextName(context)); - return; - } - - spdlog::info("Executing {} script code {} ", GetContextName(context), pCode); - - std::string strCode(pCode); - CompileBufferState bufferState = CompileBufferState(strCode); - - SQRESULT compileResult = compilebuffer(&bufferState, "console"); - spdlog::info("sq_compilebuffer returned {}", PrintSQRESULT.at(compileResult)); - - if (compileResult != SQRESULT_ERROR) - { - pushroottable(m_pSQVM->sqvm); - SQRESULT callResult = _call(m_pSQVM->sqvm, 0); - spdlog::info("sq_call returned {}", PrintSQRESULT.at(callResult)); - } -} - -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; - - 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->returnTypeString = new char[returnType.size() + 1]; - strcpy((char*)reg->returnTypeString, returnType.c_str()); - reg->returnType = SQReturnTypeFromString(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); -} - -template <ScriptContext context> SQRESULT SquirrelManager<context>::setupfunc(const SQChar* funcname) -{ - pushroottable(m_pSQVM->sqvm); - pushstring(m_pSQVM->sqvm, funcname, -1); - - SQRESULT result = get(m_pSQVM->sqvm, -2); - if (result != SQRESULT_ERROR) - pushroottable(m_pSQVM->sqvm); - - return result; -} - -template <ScriptContext context> void SquirrelManager<context>::AddFuncOverride(std::string name, SQFunction func) -{ - m_funcOverrides[name] = func; -} - -// hooks -bool IsUIVM(ScriptContext context, HSquirrelVM* pSqvm) -{ - return ScriptContext(pSqvm->sharedState->cSquirrelVM->vmContext) == ScriptContext::UI; -} - -template <ScriptContext context> void* (*sq_compiler_create)(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError); -template <ScriptContext context> void* __fastcall sq_compiler_createHook(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError) -{ - // store whether errors generated from this compile should be fatal - if (IsUIVM(context, sqvm)) - g_pSquirrel<ScriptContext::UI>->m_bFatalCompilationErrors = bShouldThrowError; - else - g_pSquirrel<context>->m_bFatalCompilationErrors = bShouldThrowError; - - return sq_compiler_create<context>(sqvm, a2, a3, bShouldThrowError); -} - -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); - - SQChar buf[1024]; - int charsWritten = vsnprintf_s(buf, _TRUNCATE, fmt, va); - - if (charsWritten > 0) - { - if (buf[charsWritten - 1] == '\n') - buf[charsWritten - 1] = '\0'; - g_pSquirrel<context>->logger->info("{}", buf); - } - - va_end(va); - return 0; -} - -template <ScriptContext context> CSquirrelVM* (*CreateNewVM)(void* a1, ScriptContext realContext); -template <ScriptContext context> CSquirrelVM* __fastcall CreateNewVMHook(void* a1, ScriptContext realContext) -{ - 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), (void*)sqvm); - return sqvm; -} - -template <ScriptContext context> bool (*CSquirrelVM_init)(CSquirrelVM* vm, ScriptContext realContext, float time); -template <ScriptContext context> bool __fastcall CSquirrelVM_initHook(CSquirrelVM* vm, ScriptContext realContext, float time) -{ - bool ret = CSquirrelVM_init<context>(vm, realContext, time); - for (Mod mod : g_pModManager->m_LoadedMods) - { - if (mod.m_bEnabled && mod.initScript.size() != 0) - { - std::string name = mod.initScript.substr(mod.initScript.find_last_of('/') + 1); - std::string path = std::string("scripts/vscripts/") + mod.initScript; - if (g_pSquirrel<context>->compilefile(vm, path.c_str(), name.c_str(), 0)) - g_pSquirrel<context>->compilefile(vm, path.c_str(), name.c_str(), 1); - } - } - return ret; -} - -template <ScriptContext context> void (*DestroyVM)(void* a1, CSquirrelVM* sqvm); -template <ScriptContext context> void __fastcall DestroyVMHook(void* a1, CSquirrelVM* sqvm) -{ - ScriptContext realContext = context; // ui and client use the same function so we use this for prints - if (IsUIVM(context, sqvm->sqvm)) - { - realContext = ScriptContext::UI; - g_pSquirrel<ScriptContext::UI>->VMDestroyed(); - DestroyVM<ScriptContext::CLIENT>(a1, sqvm); // If we pass UI here it crashes - } - else - { - g_pSquirrel<context>->VMDestroyed(); - DestroyVM<context>(a1, sqvm); - } - - spdlog::info("DestroyVM {} {}", GetContextName(realContext), (void*)sqvm); -} - -template <ScriptContext context> void (*SQCompileError)(HSquirrelVM* sqvm, const char* error, const char* file, int line, int column); -template <ScriptContext context> -void __fastcall ScriptCompileErrorHook(HSquirrelVM* sqvm, const char* error, const char* file, int line, int column) -{ - bool bIsFatalError = g_pSquirrel<context>->m_bFatalCompilationErrors; - ScriptContext realContext = context; // ui and client use the same function so we use this for prints - if (IsUIVM(context, sqvm)) - { - realContext = ScriptContext::UI; - bIsFatalError = g_pSquirrel<ScriptContext::UI>->m_bFatalCompilationErrors; - } - - auto logger = getSquirrelLoggerByContext(realContext); - - logger->error("COMPILE ERROR {}", error); - logger->error("{} line [{}] column [{}]", file, line, column); - - // 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()) - { - logger->error("Exiting dedicated server, compile error is fatal"); - // flush the logger before we exit so debug things get saved to log file - logger->flush(); - exit(EXIT_FAILURE); - } - else - { - Cbuf_AddText( - Cbuf_GetCurrentPlayer(), - fmt::format("disconnect \"Encountered {} script compilation error, see console for details.\"", GetContextName(realContext)) - .c_str(), - 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) - Cbuf_AddText(Cbuf_GetCurrentPlayer(), "showconsole", cmd_source_t::kCommandSrcCode); - } - } - - // dont call the original function since it kills game lol -} - -template <ScriptContext context> int64_t (*RegisterSquirrelFunction)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown); -template <ScriptContext context> -int64_t __fastcall RegisterSquirrelFunctionHook(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown) -{ - if (IsUIVM(context, sqvm->sqvm)) - { - if (g_pSquirrel<ScriptContext::UI>->m_funcOverrides.count(funcReg->squirrelFuncName)) - { - 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)); - } - - return g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc(sqvm, funcReg, unknown); - } - - if (g_pSquirrel<context>->m_funcOverrides.find(funcReg->squirrelFuncName) != g_pSquirrel<context>->m_funcOverrides.end()) - { - 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)); - } - - return g_pSquirrel<context>->RegisterSquirrelFunc(sqvm, funcReg, unknown); -} - -template <ScriptContext context> bool (*CallScriptInitCallback)(void* sqvm, const char* callback); -template <ScriptContext context> bool __fastcall CallScriptInitCallbackHook(void* sqvm, const char* callback) -{ - 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) - bShouldCallCustomCallbacks = !strcmp(callback, "CodeCallback_MapSpawn"); - - if (bShouldCallCustomCallbacks) - { - for (Mod mod : g_pModManager->m_LoadedMods) - { - if (!mod.m_bEnabled) - 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); - CallScriptInitCallback<context>(sqvm, modCallback.BeforeCallback.c_str()); - } - } - } - } - } - - 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 (bShouldCallCustomCallbacks) - { - for (Mod mod : g_pModManager->m_LoadedMods) - { - if (!mod.m_bEnabled) - 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); - CallScriptInitCallback<context>(sqvm, modCallback.AfterCallback.c_str()); - } - } - } - } - } - - return ret; -} - -template <ScriptContext context> void ConCommand_script(const CCommand& args) -{ - g_pSquirrel<context>->ExecuteCode(args.ArgS()); -} - -// literal class type that wraps a constant expression string -template <size_t N> struct TemplateStringLiteral -{ - constexpr TemplateStringLiteral(const char (&str)[N]) - { - std::copy_n(str, N, value); - } - - char value[N]; -}; - -template <ScriptContext context, TemplateStringLiteral funcName> SQRESULT SQ_StubbedFunc(HSquirrelVM* sqvm) -{ - spdlog::info("Blocking call to stubbed function {} in {}", funcName.value, GetContextName(context)); - return SQRESULT_NULL; -} - -template <ScriptContext context> void StubUnsafeSQFuncs() -{ - if (!CommandLine()->CheckParm("-allowunsafesqfuncs")) - { - g_pSquirrel<context>->AddFuncOverride("DevTextBufferWrite", SQ_StubbedFunc<context, "DevTextBufferWrite">); - g_pSquirrel<context>->AddFuncOverride("DevTextBufferClear", SQ_StubbedFunc<context, "DevTextBufferClear">); - g_pSquirrel<context>->AddFuncOverride("DevTextBufferDumpToFile", SQ_StubbedFunc<context, "DevTextBufferDumpToFile">); - g_pSquirrel<context>->AddFuncOverride("Dev_CommandLineAddParam", SQ_StubbedFunc<context, "Dev_CommandLineAddParam">); - g_pSquirrel<context>->AddFuncOverride("DevP4Checkout", SQ_StubbedFunc<context, "DevP4Checkout">); - g_pSquirrel<context>->AddFuncOverride("DevP4Add", SQ_StubbedFunc<context, "DevP4Add">); - } -} - -template <ScriptContext context> void SquirrelManager<context>::ProcessMessageBuffer() -{ - while (std::optional<SquirrelMessage> maybeMessage = messageBuffer->pop()) - { - SquirrelMessage message = maybeMessage.value(); - - SQObject functionobj {}; - int result = sq_getfunction(m_pSQVM->sqvm, message.functionName.c_str(), &functionobj, 0); - if (result != 0) // This func returns 0 on success for some reason - { - NS::log::squirrel_logger<context>()->error( - "ProcessMessageBuffer was unable to find function with name '{}'. Is it global?", message.functionName); - continue; - } - - pushobject(m_pSQVM->sqvm, &functionobj); // Push the function object - pushroottable(m_pSQVM->sqvm); - - int argsAmount = message.args.size(); - - if (message.isExternal && message.externalFunc != NULL) - { - argsAmount = message.externalFunc(m_pSQVM->sqvm, message.userdata); - } - else - { - for (auto& v : message.args) - { - // Execute lambda to push arg to stack - v(); - } - } - - _call(m_pSQVM->sqvm, argsAmount); - } -} - -ADD_SQFUNC( - "string", - NSGetCurrentModName, - "", - "Returns the mod name of the script running this function", - ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER) -{ - int depth = g_pSquirrel<context>->getinteger(sqvm, 1); - if (auto mod = g_pSquirrel<context>->getcallingmod(sqvm, depth); mod == nullptr) - { - g_pSquirrel<context>->raiseerror(sqvm, "NSGetModName was called from a non-mod script. This shouldn't be possible"); - return SQRESULT_ERROR; - } - else - { - g_pSquirrel<context>->pushstring(sqvm, mod->Name.c_str()); - } - return SQRESULT_NOTNULL; -} - -ADD_SQFUNC( - "string", - NSGetCallingModName, - "int depth = 0", - "Returns the mod name of the script running this function", - ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER) -{ - int depth = g_pSquirrel<context>->getinteger(sqvm, 1); - if (auto mod = g_pSquirrel<context>->getcallingmod(sqvm, depth); mod == nullptr) - { - g_pSquirrel<context>->pushstring(sqvm, "Unknown"); - } - else - { - g_pSquirrel<context>->pushstring(sqvm, mod->Name.c_str()); - } - return SQRESULT_NOTNULL; -} - -ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module)) -{ - AUTOHOOK_DISPATCH_MODULE(client.dll) - - g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst = module.Offset(0x12120).RCast<sq_defconstType>(); - g_pSquirrel<ScriptContext::UI>->__sq_defconst = g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst; - - g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer = module.Offset(0x3110).RCast<sq_compilebufferType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable = module.Offset(0x5860).RCast<sq_pushroottableType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_compilefile = module.Offset(0xF950).RCast<sq_compilefileType>(); - 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::UI>->__sq_compilefile = g_pSquirrel<ScriptContext::CLIENT>->__sq_compilefile; - - g_pSquirrel<ScriptContext::CLIENT>->__sq_call = module.Offset(0x8650).RCast<sq_callType>(); - g_pSquirrel<ScriptContext::UI>->__sq_call = g_pSquirrel<ScriptContext::CLIENT>->__sq_call; - - g_pSquirrel<ScriptContext::CLIENT>->__sq_newarray = module.Offset(0x39F0).RCast<sq_newarrayType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_arrayappend = module.Offset(0x3C70).RCast<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).RCast<sq_newtableType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_newslot = module.Offset(0x70B0).RCast<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).RCast<sq_pushstringType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger = module.Offset(0x36A0).RCast<sq_pushintegerType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat = module.Offset(0x3800).RCast<sq_pushfloatType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool = module.Offset(0x3710).RCast<sq_pushboolType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset = module.Offset(0x3560).RCast<sq_pushassetType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector = module.Offset(0x3780).RCast<sq_pushvectorType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushobject = module.Offset(0x83D0).RCast<sq_pushobjectType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror = module.Offset(0x8470).RCast<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_pushobject = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushobject; - g_pSquirrel<ScriptContext::UI>->__sq_raiseerror = g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror; - - g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring = module.Offset(0x60C0).RCast<sq_getstringType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger = module.Offset(0x60E0).RCast<sq_getintegerType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat = module.Offset(0x6100).RCast<sq_getfloatType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool = module.Offset(0x6130).RCast<sq_getboolType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_get = module.Offset(0x7C30).RCast<sq_getType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset = module.Offset(0x6010).RCast<sq_getassetType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata = module.Offset(0x63D0).RCast<sq_getuserdataType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector = module.Offset(0x6140).RCast<sq_getvectorType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getthisentity = module.Offset(0x12F80).RCast<sq_getthisentityType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getobject = module.Offset(0x6160).RCast<sq_getobjectType>(); - 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::UI>->__sq_getthisentity = g_pSquirrel<ScriptContext::CLIENT>->__sq_getthisentity; - g_pSquirrel<ScriptContext::UI>->__sq_getobject = g_pSquirrel<ScriptContext::CLIENT>->__sq_getobject; - - g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata = module.Offset(0x38D0).RCast<sq_createuserdataType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid = module.Offset(0x6490).RCast<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; - - g_pSquirrel<ScriptContext::CLIENT>->__sq_GetEntityConstant_CBaseEntity = module.Offset(0x3E49B0).RCast<sq_GetEntityConstantType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_getentityfrominstance = module.Offset(0x114F0).RCast<sq_getentityfrominstanceType>(); - g_pSquirrel<ScriptContext::UI>->__sq_GetEntityConstant_CBaseEntity = - g_pSquirrel<ScriptContext::CLIENT>->__sq_GetEntityConstant_CBaseEntity; - g_pSquirrel<ScriptContext::UI>->__sq_getentityfrominstance = g_pSquirrel<ScriptContext::CLIENT>->__sq_getentityfrominstance; - - // Message buffer stuff - g_pSquirrel<ScriptContext::UI>->messageBuffer = g_pSquirrel<ScriptContext::CLIENT>->messageBuffer; - g_pSquirrel<ScriptContext::CLIENT>->__sq_getfunction = module.Offset(0x572FB0).RCast<sq_getfunctionType>(); - g_pSquirrel<ScriptContext::UI>->__sq_getfunction = g_pSquirrel<ScriptContext::CLIENT>->__sq_getfunction; - g_pSquirrel<ScriptContext::CLIENT>->__sq_stackinfos = module.Offset(0x35970).RCast<sq_stackinfosType>(); - g_pSquirrel<ScriptContext::UI>->__sq_stackinfos = g_pSquirrel<ScriptContext::CLIENT>->__sq_stackinfos; - - // Structs - g_pSquirrel<ScriptContext::CLIENT>->__sq_pushnewstructinstance = module.Offset(0x5400).RCast<sq_pushnewstructinstanceType>(); - g_pSquirrel<ScriptContext::CLIENT>->__sq_sealstructslot = module.Offset(0x5530).RCast<sq_sealstructslotType>(); - g_pSquirrel<ScriptContext::UI>->__sq_pushnewstructinstance = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushnewstructinstance; - g_pSquirrel<ScriptContext::UI>->__sq_sealstructslot = g_pSquirrel<ScriptContext::CLIENT>->__sq_sealstructslot; - - MAKEHOOK( - module.Offset(0x108E0), - &RegisterSquirrelFunctionHook<ScriptContext::CLIENT>, - &g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc); - g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc; - - g_pSquirrel<ScriptContext::CLIENT>->logger = NS::log::SCRIPT_CL; - g_pSquirrel<ScriptContext::UI>->logger = NS::log::SCRIPT_UI; - - // 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(0xE3B0), &CSquirrelVM_initHook<ScriptContext::CLIENT>, &CSquirrelVM_init<ScriptContext::CLIENT>); - - 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); - - StubUnsafeSQFuncs<ScriptContext::CLIENT>(); - StubUnsafeSQFuncs<ScriptContext::UI>(); - - g_pSquirrel<ScriptContext::CLIENT>->__sq_getfunction = module.Offset(0x6CB0).RCast<sq_getfunctionType>(); - g_pSquirrel<ScriptContext::UI>->__sq_getfunction = g_pSquirrel<ScriptContext::CLIENT>->__sq_getfunction; - - SquirrelFunctions s = {}; - g_pSquirrel<ScriptContext::CLIENT>->GenerateSquirrelFunctionsStruct(&s); - g_pPluginManager->InformSQVMLoad(ScriptContext::CLIENT, &s); -} - -ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module)) -{ - AUTOHOOK_DISPATCH_MODULE(server.dll) - - g_pSquirrel<ScriptContext::SERVER>->__sq_defconst = module.Offset(0x1F550).RCast<sq_defconstType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_compilebuffer = module.Offset(0x3110).RCast<sq_compilebufferType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushroottable = module.Offset(0x5840).RCast<sq_pushroottableType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_call = module.Offset(0x8620).RCast<sq_callType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_compilefile = module.Offset(0x1CD80).RCast<sq_compilefileType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_newarray = module.Offset(0x39F0).RCast<sq_newarrayType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_arrayappend = module.Offset(0x3C70).RCast<sq_arrayappendType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_newtable = module.Offset(0x3960).RCast<sq_newtableType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_newslot = module.Offset(0x7080).RCast<sq_newslotType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_pushstring = module.Offset(0x3440).RCast<sq_pushstringType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushinteger = module.Offset(0x36A0).RCast<sq_pushintegerType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushfloat = module.Offset(0x3800).RCast<sq_pushfloatType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushbool = module.Offset(0x3710).RCast<sq_pushboolType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushasset = module.Offset(0x3560).RCast<sq_pushassetType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushvector = module.Offset(0x3780).RCast<sq_pushvectorType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_pushobject = module.Offset(0x83A0).RCast<sq_pushobjectType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_raiseerror = module.Offset(0x8440).RCast<sq_raiseerrorType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_getstring = module.Offset(0x60A0).RCast<sq_getstringType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getinteger = module.Offset(0x60C0).RCast<sq_getintegerType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getfloat = module.Offset(0x60E0).RCast<sq_getfloatType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getbool = module.Offset(0x6110).RCast<sq_getboolType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getasset = module.Offset(0x5FF0).RCast<sq_getassetType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getuserdata = module.Offset(0x63B0).RCast<sq_getuserdataType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getvector = module.Offset(0x6120).RCast<sq_getvectorType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_get = module.Offset(0x7C00).RCast<sq_getType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_getthisentity = module.Offset(0x203B0).RCast<sq_getthisentityType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getobject = module.Offset(0x6140).RCast<sq_getobjectType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_createuserdata = module.Offset(0x38D0).RCast<sq_createuserdataType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_setuserdatatypeid = module.Offset(0x6470).RCast<sq_setuserdatatypeidType>(); - - g_pSquirrel<ScriptContext::SERVER>->__sq_GetEntityConstant_CBaseEntity = module.Offset(0x418AF0).RCast<sq_GetEntityConstantType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_getentityfrominstance = module.Offset(0x1E920).RCast<sq_getentityfrominstanceType>(); - - g_pSquirrel<ScriptContext::SERVER>->logger = NS::log::SCRIPT_SV; - // Message buffer stuff - g_pSquirrel<ScriptContext::SERVER>->__sq_getfunction = module.Offset(0x6C85).RCast<sq_getfunctionType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_stackinfos = module.Offset(0x35920).RCast<sq_stackinfosType>(); - - // Structs - g_pSquirrel<ScriptContext::SERVER>->__sq_pushnewstructinstance = module.Offset(0x53e0).RCast<sq_pushnewstructinstanceType>(); - g_pSquirrel<ScriptContext::SERVER>->__sq_sealstructslot = module.Offset(0x5510).RCast<sq_sealstructslotType>(); - - MAKEHOOK( - module.Offset(0x1DD10), - &RegisterSquirrelFunctionHook<ScriptContext::SERVER>, - &g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc); - - 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(0x1B7E0), &CSquirrelVM_initHook<ScriptContext::SERVER>, &CSquirrelVM_init<ScriptContext::SERVER>); - // 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); - - StubUnsafeSQFuncs<ScriptContext::SERVER>(); - - SquirrelFunctions s = {}; - g_pSquirrel<ScriptContext::SERVER>->GenerateSquirrelFunctionsStruct(&s); - g_pPluginManager->InformSQVMLoad(ScriptContext::SERVER, &s); -} - -void InitialiseSquirrelManagers() -{ - g_pSquirrel<ScriptContext::CLIENT> = new SquirrelManager<ScriptContext::CLIENT>; - g_pSquirrel<ScriptContext::UI> = new SquirrelManager<ScriptContext::UI>; - g_pSquirrel<ScriptContext::SERVER> = new SquirrelManager<ScriptContext::SERVER>; -} diff --git a/NorthstarDLL/squirrel/squirrel.h b/NorthstarDLL/squirrel/squirrel.h deleted file mode 100644 index a4932044..00000000 --- a/NorthstarDLL/squirrel/squirrel.h +++ /dev/null @@ -1,526 +0,0 @@ -#pragma once - -#include "squirrelclasstypes.h" -#include "squirrelautobind.h" -#include "core/math/vector.h" -#include "plugins/plugin_abi.h" -#include "mods/modmanager.h" - -/* - definitions from hell - required to function -*/ - -template <ScriptContext context, typename T> inline void SqRecurseArgs(FunctionVector& v, T& arg); - -template <ScriptContext context, typename T, typename... Args> inline void SqRecurseArgs(FunctionVector& v, T& arg, Args... args); - -/* - sanity below -*/ - -// stolen from ttf2sdk: sqvm types -typedef float SQFloat; -typedef long SQInteger; -typedef unsigned long SQUnsignedInteger; -typedef char SQChar; -typedef SQUnsignedInteger SQBool; - -static constexpr int operator&(ScriptContext first, ScriptContext second) -{ - return first == second; -} - -static constexpr int operator&(int first, ScriptContext second) -{ - return first & (1 << static_cast<int>(second)); -} - -static constexpr int operator|(ScriptContext first, ScriptContext second) -{ - return (1 << static_cast<int>(first)) + (1 << static_cast<int>(second)); -} - -static constexpr int operator|(int first, ScriptContext second) -{ - return first + (1 << static_cast<int>(second)); -} - -const char* GetContextName(ScriptContext context); -const char* GetContextName_Short(ScriptContext context); -eSQReturnType SQReturnTypeFromString(const char* pReturnType); -const char* SQTypeNameFromID(const int iTypeId); - -void AsyncCall_External(ScriptContext context, const char* func_name, SquirrelMessage_External_Pop function, void* userdata); - -ScriptContext ScriptContextFromString(std::string string); - -namespace NS::log -{ - template <ScriptContext context> std::shared_ptr<spdlog::logger> squirrel_logger(); -}; // namespace NS::log - -// This base class means that only the templated functions have to be rebuilt for each template instance -// Cuts down on compile time by ~5 seconds -class SquirrelManagerBase -{ -protected: - std::vector<SQFuncRegistration*> m_funcRegistrations; - -public: - CSquirrelVM* m_pSQVM; - std::map<std::string, SQFunction> m_funcOverrides = {}; - std::map<std::string, SQFunction> m_funcOriginals = {}; - - bool m_bFatalCompilationErrors = false; - - std::shared_ptr<spdlog::logger> logger; - -#pragma region SQVM funcs - RegisterSquirrelFuncType RegisterSquirrelFunc; - sq_defconstType __sq_defconst; - - sq_compilebufferType __sq_compilebuffer; - sq_callType __sq_call; - sq_raiseerrorType __sq_raiseerror; - sq_compilefileType __sq_compilefile; - - sq_newarrayType __sq_newarray; - sq_arrayappendType __sq_arrayappend; - - sq_newtableType __sq_newtable; - sq_newslotType __sq_newslot; - - sq_pushroottableType __sq_pushroottable; - sq_pushstringType __sq_pushstring; - sq_pushintegerType __sq_pushinteger; - sq_pushfloatType __sq_pushfloat; - sq_pushboolType __sq_pushbool; - sq_pushassetType __sq_pushasset; - sq_pushvectorType __sq_pushvector; - sq_pushobjectType __sq_pushobject; - - sq_getstringType __sq_getstring; - sq_getintegerType __sq_getinteger; - sq_getfloatType __sq_getfloat; - sq_getboolType __sq_getbool; - sq_getType __sq_get; - sq_getassetType __sq_getasset; - sq_getuserdataType __sq_getuserdata; - sq_getvectorType __sq_getvector; - sq_getthisentityType __sq_getthisentity; - sq_getobjectType __sq_getobject; - - sq_stackinfosType __sq_stackinfos; - - sq_createuserdataType __sq_createuserdata; - sq_setuserdatatypeidType __sq_setuserdatatypeid; - sq_getfunctionType __sq_getfunction; - - sq_getentityfrominstanceType __sq_getentityfrominstance; - sq_GetEntityConstantType __sq_GetEntityConstant_CBaseEntity; - - sq_pushnewstructinstanceType __sq_pushnewstructinstance; - sq_sealstructslotType __sq_sealstructslot; - -#pragma endregion - -#pragma region SQVM func wrappers - inline void defconst(CSquirrelVM* sqvm, const SQChar* pName, int nValue) - { - __sq_defconst(sqvm, pName, nValue); - } - - inline SQRESULT - compilebuffer(CompileBufferState* bufferState, const SQChar* bufferName = "unnamedbuffer", const SQBool bShouldThrowError = false) - { - return __sq_compilebuffer(m_pSQVM->sqvm, bufferState, bufferName, -1, bShouldThrowError); - } - - inline SQRESULT _call(HSquirrelVM* sqvm, const SQInteger args) - { - return __sq_call(sqvm, args + 1, false, false); - } - - inline SQInteger raiseerror(HSquirrelVM* sqvm, const SQChar* sError) - { - return __sq_raiseerror(sqvm, sError); - } - - inline bool compilefile(CSquirrelVM* sqvm, const char* path, const char* name, int a4) - { - return __sq_compilefile(sqvm, path, name, a4); - } - - inline void newarray(HSquirrelVM* sqvm, const SQInteger stackpos = 0) - { - __sq_newarray(sqvm, stackpos); - } - - inline SQRESULT arrayappend(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return __sq_arrayappend(sqvm, stackpos); - } - - inline SQRESULT newtable(HSquirrelVM* sqvm) - { - return __sq_newtable(sqvm); - } - - inline SQRESULT newslot(HSquirrelVM* sqvm, SQInteger idx, SQBool bStatic) - { - return __sq_newslot(sqvm, idx, bStatic); - } - - inline void pushroottable(HSquirrelVM* sqvm) - { - __sq_pushroottable(sqvm); - } - - inline void pushstring(HSquirrelVM* sqvm, const SQChar* sVal, int length = -1) - { - __sq_pushstring(sqvm, sVal, length); - } - - inline void pushinteger(HSquirrelVM* sqvm, const SQInteger iVal) - { - __sq_pushinteger(sqvm, iVal); - } - - inline void pushfloat(HSquirrelVM* sqvm, const SQFloat flVal) - { - __sq_pushfloat(sqvm, flVal); - } - - inline void pushbool(HSquirrelVM* sqvm, const SQBool bVal) - { - __sq_pushbool(sqvm, bVal); - } - - inline void pushasset(HSquirrelVM* sqvm, const SQChar* sVal, int length = -1) - { - __sq_pushasset(sqvm, sVal, length); - } - - inline void pushvector(HSquirrelVM* sqvm, const Vector3 pVal) - { - __sq_pushvector(sqvm, (float*)&pVal); - } - - inline void pushobject(HSquirrelVM* sqvm, SQObject* obj) - { - __sq_pushobject(sqvm, obj); - } - - inline const SQChar* getstring(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return __sq_getstring(sqvm, stackpos); - } - - inline SQInteger getinteger(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return __sq_getinteger(sqvm, stackpos); - } - - inline SQFloat getfloat(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return __sq_getfloat(sqvm, stackpos); - } - - inline SQBool getbool(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return __sq_getbool(sqvm, stackpos); - } - - inline SQRESULT get(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return __sq_get(sqvm, stackpos); - } - - inline Vector3 getvector(HSquirrelVM* sqvm, const SQInteger stackpos) - { - return *(Vector3*)__sq_getvector(sqvm, stackpos); - } - - inline int sq_getfunction(HSquirrelVM* sqvm, const char* name, SQObject* returnObj, const char* signature) - { - return __sq_getfunction(sqvm, name, returnObj, signature); - } - - inline SQRESULT getasset(HSquirrelVM* sqvm, const SQInteger stackpos, const char** result) - { - return __sq_getasset(sqvm, stackpos, result); - } - - inline long long sq_stackinfos(HSquirrelVM* sqvm, int level, SQStackInfos& out) - { - return __sq_stackinfos(sqvm, level, &out, sqvm->_callstacksize); - } - - inline Mod* getcallingmod(HSquirrelVM* sqvm, int depth = 0) - { - SQStackInfos stackInfo {}; - if (1 + depth >= sqvm->_callstacksize) - { - return nullptr; - } - sq_stackinfos(sqvm, 1 + depth, stackInfo); - std::string sourceName = stackInfo._sourceName; - std::replace(sourceName.begin(), sourceName.end(), '/', '\\'); - std::string filename = g_pModManager->NormaliseModFilePath(fs::path("scripts\\vscripts\\" + sourceName)); - if (auto res = g_pModManager->m_ModFiles.find(filename); res != g_pModManager->m_ModFiles.end()) - { - return res->second.m_pOwningMod; - } - return nullptr; - } - template <typename T> inline SQRESULT getuserdata(HSquirrelVM* sqvm, const SQInteger stackpos, T* data, uint64_t* typeId) - { - return __sq_getuserdata(sqvm, stackpos, (void**)data, typeId); // this sometimes crashes idk - } - - template <typename T> inline T* createuserdata(HSquirrelVM* sqvm, SQInteger size) - { - void* ret = __sq_createuserdata(sqvm, size); - memset(ret, 0, size); - return (T*)ret; - } - - inline SQRESULT setuserdatatypeid(HSquirrelVM* sqvm, const SQInteger stackpos, uint64_t typeId) - { - return __sq_setuserdatatypeid(sqvm, stackpos, typeId); - } - - template <typename T> inline SQBool getthisentity(HSquirrelVM* sqvm, T* ppEntity) - { - return __sq_getthisentity(sqvm, (void**)ppEntity); - } - - template <typename T> inline T* getentity(HSquirrelVM* sqvm, SQInteger iStackPos) - { - SQObject obj; - __sq_getobject(sqvm, iStackPos, &obj); - - // there are entity constants for other types, but seemingly CBaseEntity's is the only one needed - return (T*)__sq_getentityfrominstance(m_pSQVM, &obj, __sq_GetEntityConstant_CBaseEntity()); - } - - inline SQRESULT pushnewstructinstance(HSquirrelVM* sqvm, const int fieldCount) - { - return __sq_pushnewstructinstance(sqvm, fieldCount); - } - - inline SQRESULT sealstructslot(HSquirrelVM* sqvm, const int fieldIndex) - { - return __sq_sealstructslot(sqvm, fieldIndex); - } -#pragma endregion -}; - -template <ScriptContext context> class SquirrelManager : public virtual SquirrelManagerBase -{ -public: -#pragma region MessageBuffer - SquirrelMessageBuffer* messageBuffer; - - template <typename... Args> SquirrelMessage AsyncCall(std::string funcname, Args... args) - { - // This function schedules a call to be executed on the next frame - // This is useful for things like threads and plugins, which do not run on the main thread - FunctionVector functionVector; - SqRecurseArgs<context>(functionVector, args...); - SquirrelMessage message = {funcname, functionVector}; - messageBuffer->push(message); - return message; - } - - SquirrelMessage AsyncCall(std::string funcname) - { - // This function schedules a call to be executed on the next frame - // This is useful for things like threads and plugins, which do not run on the main thread - FunctionVector functionVector = {}; - SquirrelMessage message = {funcname, functionVector}; - messageBuffer->push(message); - return message; - } - - SQRESULT Call(const char* funcname) - { - // Warning! - // This function assumes the squirrel VM is stopped/blocked at the moment of call - // Calling this function while the VM is running is likely to result in a crash due to stack destruction - // If you want to call into squirrel asynchronously, use `AsyncCall` instead - - if (!m_pSQVM || !m_pSQVM->sqvm) - { - spdlog::error( - "{} was called on context {} while VM was not initialized. This will crash", __FUNCTION__, GetContextName(context)); - } - - SQObject functionobj {}; - int result = sq_getfunction(m_pSQVM->sqvm, funcname, &functionobj, 0); - if (result != 0) // This func returns 0 on success for some reason - { - NS::log::squirrel_logger<context>()->error("Call was unable to find function with name '{}'. Is it global?", funcname); - return SQRESULT_ERROR; - } - pushobject(m_pSQVM->sqvm, &functionobj); // Push the function object - pushroottable(m_pSQVM->sqvm); // Push root table - return _call(m_pSQVM->sqvm, 0); - } - - template <typename... Args> SQRESULT Call(const char* funcname, Args... args) - { - // Warning! - // This function assumes the squirrel VM is stopped/blocked at the moment of call - // Calling this function while the VM is running is likely to result in a crash due to stack destruction - // If you want to call into squirrel asynchronously, use `schedule_call` instead - if (!m_pSQVM || !m_pSQVM->sqvm) - { - spdlog::error( - "{} was called on context {} while VM was not initialized. This will crash", __FUNCTION__, GetContextName(context)); - } - SQObject functionobj {}; - int result = sq_getfunction(m_pSQVM->sqvm, funcname, &functionobj, 0); - if (result != 0) // This func returns 0 on success for some reason - { - NS::log::squirrel_logger<context>()->error("Call was unable to find function with name '{}'. Is it global?", funcname); - return SQRESULT_ERROR; - } - pushobject(m_pSQVM->sqvm, &functionobj); // Push the function object - pushroottable(m_pSQVM->sqvm); // Push root table - - FunctionVector functionVector; - SqRecurseArgs<context>(functionVector, args...); - - for (auto& v : functionVector) - { - // Execute lambda to push arg to stack - v(); - } - - return _call(m_pSQVM->sqvm, functionVector.size()); - } - -#pragma endregion - -public: - SquirrelManager() - { - m_pSQVM = nullptr; - } - - void VMCreated(CSquirrelVM* newSqvm); - void VMDestroyed(); - void ExecuteCode(const char* code); - void AddFuncRegistration(std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func); - SQRESULT setupfunc(const SQChar* funcname); - void AddFuncOverride(std::string name, SQFunction func); - void ProcessMessageBuffer(); - void GenerateSquirrelFunctionsStruct(SquirrelFunctions* s); -}; - -template <ScriptContext context> SquirrelManager<context>* g_pSquirrel; - -void InitialiseSquirrelManagers(); - -/* - Beware all ye who enter below. - This place is not a place of honor... no highly esteemed deed is commemorated here... nothing valued is here. - What is here was dangerous and repulsive to us. This message is a warning about danger. -*/ - -#pragma region MessageBuffer templates - -// Clang-formatting makes this whole thing unreadable -// clang-format off - -#ifndef MessageBufferFuncs -#define MessageBufferFuncs -// Bools -template <ScriptContext context, typename T> -requires std::convertible_to<T, bool> && (!std::is_floating_point_v<T>) && (!std::convertible_to<T, std::string>) && (!std::convertible_to<T, int>) -inline VoidFunction SQMessageBufferPushArg(T& arg) { - return [arg]{ g_pSquirrel<context>->pushbool(g_pSquirrel<context>->m_pSQVM->sqvm, static_cast<bool>(arg)); }; -} -// Vectors -template <ScriptContext context> -inline VoidFunction SQMessageBufferPushArg(Vector3& arg) { - return [arg]{ g_pSquirrel<context>->pushvector(g_pSquirrel<context>->m_pSQVM->sqvm, arg); }; -} -// Vectors -template <ScriptContext context> -inline VoidFunction SQMessageBufferPushArg(SQObject* arg) { - return [arg]{ g_pSquirrel<context>->pushSQObject(g_pSquirrel<context>->m_pSQVM->sqvm, arg); }; -} -// Ints -template <ScriptContext context, typename T> -requires std::convertible_to<T, int> && (!std::is_floating_point_v<T>) -inline VoidFunction SQMessageBufferPushArg(T& arg) { - return [arg]{ g_pSquirrel<context>->pushinteger(g_pSquirrel<context>->m_pSQVM->sqvm, static_cast<int>(arg)); }; -} -// Floats -template <ScriptContext context, typename T> -requires std::convertible_to<T, float> && (std::is_floating_point_v<T>) -inline VoidFunction SQMessageBufferPushArg(T& arg) { - return [arg]{ g_pSquirrel<context>->pushfloat(g_pSquirrel<context>->m_pSQVM->sqvm, static_cast<float>(arg)); }; -} -// Strings -template <ScriptContext context, typename T> -requires (std::convertible_to<T, std::string> || std::is_constructible_v<std::string, T>) -inline VoidFunction SQMessageBufferPushArg(T& arg) { - auto converted = std::string(arg); - return [converted]{ g_pSquirrel<context>->pushstring(g_pSquirrel<context>->m_pSQVM->sqvm, converted.c_str(), converted.length()); }; -} -// Assets -template <ScriptContext context> -inline VoidFunction SQMessageBufferPushArg(SquirrelAsset& arg) { - return [arg]{ g_pSquirrel<context>->pushasset(g_pSquirrel<context>->m_pSQVM->sqvm, arg.path.c_str(), arg.path.length()); }; -} -// Maps -template <ScriptContext context, typename T> -requires is_iterable<T> -inline VoidFunction SQMessageBufferPushArg(T& arg) { - FunctionVector localv = {}; - localv.push_back([]{g_pSquirrel<context>->newarray(g_pSquirrel<context>->m_pSQVM->sqvm, 0);}); - - for (const auto& item : arg) { - localv.push_back(SQMessageBufferPushArg<context>(item)); - localv.push_back([]{g_pSquirrel<context>->arrayappend(g_pSquirrel<context>->m_pSQVM->sqvm, -2);}); - } - - return [localv] { for (auto& func : localv) { func(); } }; -} -// Vectors -template <ScriptContext context, typename T> -requires is_map<T> -inline VoidFunction SQMessageBufferPushArg(T& map) { - FunctionVector localv = {}; - localv.push_back([]{g_pSquirrel<context>->newtable(g_pSquirrel<context>->m_pSQVM->sqvm);}); - - for (const auto& item : map) { - localv.push_back(SQMessageBufferPushArg<context>(item.first)); - localv.push_back(SQMessageBufferPushArg<context>(item.second)); - localv.push_back([]{g_pSquirrel<context>->newslot(g_pSquirrel<context>->m_pSQVM->sqvm, -3, false);}); - } - - return [localv]{ for (auto& func : localv) { func(); } }; -} - -template <ScriptContext context, typename T> -inline void SqRecurseArgs(FunctionVector& v, T& arg) { - v.push_back(SQMessageBufferPushArg<context>(arg)); -} - -// This function is separated from the PushArg function so as to not generate too many template instances -// This is the main function responsible for unrolling the argument pack -template <ScriptContext context, typename T, typename... Args> -inline void SqRecurseArgs(FunctionVector& v, T& arg, Args... args) { - v.push_back(SQMessageBufferPushArg<context>(arg)); - SqRecurseArgs<context>(v, args...); -} - -// clang-format on -#endif - -#pragma endregion diff --git a/NorthstarDLL/squirrel/squirrelautobind.cpp b/NorthstarDLL/squirrel/squirrelautobind.cpp deleted file mode 100644 index c15240f5..00000000 --- a/NorthstarDLL/squirrel/squirrelautobind.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "squirrelautobind.h" - -SquirrelAutoBindContainer* g_pSqAutoBindContainer; - -ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrelAutoBind, ClientSquirrel, (CModule module)) -{ - spdlog::info("ClientSquirrelAutoBInd AutoBindFuncsVectorsize {}", g_pSqAutoBindContainer->clientSqAutoBindFuncs.size()); - for (auto& autoBindFunc : g_pSqAutoBindContainer->clientSqAutoBindFuncs) - { - autoBindFunc(); - } -} - -ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrelAutoBind, ServerSquirrel, (CModule module)) -{ - for (auto& autoBindFunc : g_pSqAutoBindContainer->serverSqAutoBindFuncs) - { - autoBindFunc(); - } -} diff --git a/NorthstarDLL/squirrel/squirrelautobind.h b/NorthstarDLL/squirrel/squirrelautobind.h deleted file mode 100644 index 0fc599f3..00000000 --- a/NorthstarDLL/squirrel/squirrelautobind.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include <vector> - -typedef void (*SqAutoBindFunc)(); - -class SquirrelAutoBindContainer -{ -public: - std::vector<std::function<void()>> clientSqAutoBindFuncs; - std::vector<std::function<void()>> serverSqAutoBindFuncs; -}; - -extern SquirrelAutoBindContainer* g_pSqAutoBindContainer; - -class __squirrelautobind; - -#define ADD_SQFUNC(returnType, funcName, argTypes, helpText, runOnContext) \ - template <ScriptContext context> SQRESULT CONCAT2(Script_, funcName)(HSquirrelVM * sqvm); \ - namespace \ - { \ - __squirrelautobind CONCAT2(__squirrelautobind, __LINE__)( \ - []() \ - { \ - if constexpr ((runOnContext)&ScriptContext::UI) \ - g_pSquirrel<ScriptContext::UI>->AddFuncRegistration( \ - returnType, __STR(funcName), argTypes, helpText, CONCAT2(Script_, funcName) < ScriptContext::UI >); \ - if constexpr ((runOnContext)&ScriptContext::CLIENT) \ - g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration( \ - returnType, __STR(funcName), argTypes, helpText, CONCAT2(Script_, funcName) < ScriptContext::CLIENT >); \ - }, \ - []() \ - { \ - if constexpr ((runOnContext)&ScriptContext::SERVER) \ - g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration( \ - returnType, __STR(funcName), argTypes, helpText, CONCAT2(Script_, funcName) < ScriptContext::SERVER >); \ - }); \ - } \ - template <ScriptContext context> SQRESULT CONCAT2(Script_, funcName)(HSquirrelVM * sqvm) - -#define REPLACE_SQFUNC(funcName, runOnContext) \ - template <ScriptContext context> SQRESULT CONCAT2(Script_, funcName)(HSquirrelVM * sqvm); \ - namespace \ - { \ - __squirrelautobind CONCAT2(__squirrelautobind, __LINE__)( \ - []() \ - { \ - if constexpr ((runOnContext)&ScriptContext::UI) \ - g_pSquirrel<ScriptContext::UI>->AddFuncOverride(__STR(funcName), CONCAT2(Script_, funcName) < ScriptContext::UI >); \ - if constexpr ((runOnContext)&ScriptContext::CLIENT) \ - g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride( \ - __STR(funcName), CONCAT2(Script_, funcName) < ScriptContext::CLIENT >); \ - }, \ - []() \ - { \ - if constexpr ((runOnContext)&ScriptContext::SERVER) \ - g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride( \ - __STR(funcName), CONCAT2(Script_, funcName) < ScriptContext::SERVER >); \ - }); \ - } \ - template <ScriptContext context> SQRESULT CONCAT2(Script_, funcName)(HSquirrelVM * sqvm) - -class __squirrelautobind -{ -public: - __squirrelautobind() = delete; - - __squirrelautobind(std::function<void()> clientAutoBindFunc, std::function<void()> serverAutoBindFunc) - { - // Bit hacky but we can't initialise this normally since this gets run automatically on load - if (g_pSqAutoBindContainer == nullptr) - g_pSqAutoBindContainer = new SquirrelAutoBindContainer(); - - g_pSqAutoBindContainer->clientSqAutoBindFuncs.push_back(clientAutoBindFunc); - g_pSqAutoBindContainer->serverSqAutoBindFuncs.push_back(serverAutoBindFunc); - } -}; diff --git a/NorthstarDLL/squirrel/squirrelclasstypes.h b/NorthstarDLL/squirrel/squirrelclasstypes.h deleted file mode 100644 index cd777551..00000000 --- a/NorthstarDLL/squirrel/squirrelclasstypes.h +++ /dev/null @@ -1,248 +0,0 @@ -#pragma once -#include "squirreldatatypes.h" - -#include <queue> - -enum SQRESULT : SQInteger -{ - SQRESULT_ERROR = -1, - SQRESULT_NULL = 0, - SQRESULT_NOTNULL = 1, -}; - -typedef SQRESULT (*SQFunction)(HSquirrelVM* sqvm); - -enum class eSQReturnType -{ - Float = 0x1, - Vector = 0x3, - Integer = 0x5, - Boolean = 0x6, - Entity = 0xD, - String = 0x21, - Default = 0x20, - Arrays = 0x25, - Asset = 0x28, - Table = 0x26, -}; - -const std::map<SQRESULT, const char*> PrintSQRESULT = { - {SQRESULT::SQRESULT_ERROR, "SQRESULT_ERROR"}, - {SQRESULT::SQRESULT_NULL, "SQRESULT_NULL"}, - {SQRESULT::SQRESULT_NOTNULL, "SQRESULT_NOTNULL"}}; - -struct CompileBufferState -{ - const SQChar* buffer; - const SQChar* bufferPlusLength; - const SQChar* bufferAgain; - - CompileBufferState(const std::string& code) - { - buffer = code.c_str(); - bufferPlusLength = code.c_str() + code.size(); - bufferAgain = code.c_str(); - } -}; - -struct SQFuncRegistration -{ - const char* squirrelFuncName; - const char* cppFuncName; - const char* helpText; - const char* returnTypeString; - const char* argTypes; - uint32_t unknown1; - uint32_t devLevel; - const char* shortNameMaybe; - uint32_t unknown2; - eSQReturnType returnType; - uint32_t* externalBufferPointer; - uint64_t externalBufferSize; - uint64_t unknown3; - uint64_t unknown4; - SQFunction funcPtr; - - SQFuncRegistration() - { - memset(this, 0, sizeof(SQFuncRegistration)); - this->returnType = eSQReturnType::Default; - } -}; - -enum class ScriptContext : int -{ - INVALID = -1, - SERVER, - CLIENT, - UI, -}; - -typedef std::vector<std::function<void()>> FunctionVector; -typedef std::function<void()> VoidFunction; - -// clang-format off -template <typename T> -concept is_map = - // Simple maps - std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> || - std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>> || - - // Nested maps - std::same_as < - std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>, - std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type> - > || - std::same_as < - std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>, - std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type> - > || - std::same_as < - std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>, - std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type> - > || - std::same_as < - std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>, - std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type> - > -; - -template<typename T> -concept is_iterable = requires(std::ranges::range_value_t<T> x) -{ - x.begin(); // must have `x.begin()` - x.end(); // and `x.end()` -}; - -// clang-format on - -typedef int (*SquirrelMessage_External_Pop)(HSquirrelVM* sqvm, void* userdata); -typedef void (*sq_schedule_call_externalType)( - ScriptContext context, const char* funcname, SquirrelMessage_External_Pop function, void* userdata); - -class SquirrelMessage -{ -public: - std::string functionName; - FunctionVector args; - bool isExternal = false; - void* userdata = NULL; - SquirrelMessage_External_Pop externalFunc = NULL; -}; - -class SquirrelMessageBuffer -{ - -private: - std::queue<SquirrelMessage> messages = {}; - -public: - std::mutex mutex; - std::optional<SquirrelMessage> pop() - { - std::lock_guard<std::mutex> guard(mutex); - if (!messages.empty()) - { - auto message = messages.front(); - messages.pop(); - return message; - } - else - { - return std::nullopt; - } - } - - void unwind() - { - auto maybeMessage = this->pop(); - if (!maybeMessage) - { - spdlog::error("Plugin tried consuming SquirrelMessage while buffer was empty"); - return; - } - auto message = maybeMessage.value(); - for (auto& v : message.args) - { - // Execute lambda to push arg to stack - v(); - } - } - - void push(SquirrelMessage message) - { - std::lock_guard<std::mutex> guard(mutex); - messages.push(message); - } -}; - -// Super simple wrapper class to allow pushing Assets via call -class SquirrelAsset -{ -public: - std::string path; - SquirrelAsset(std::string path) : path(path) {}; -}; - -#pragma region TypeDefs - -// core sqvm funcs -typedef int64_t (*RegisterSquirrelFuncType)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown); -typedef void (*sq_defconstType)(CSquirrelVM* sqvm, const SQChar* name, int value); - -typedef SQRESULT (*sq_compilebufferType)( - HSquirrelVM* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, SQBool bShouldThrowError); -typedef SQRESULT (*sq_callType)(HSquirrelVM* sqvm, SQInteger iArgs, SQBool bShouldReturn, SQBool bThrowError); -typedef SQInteger (*sq_raiseerrorType)(HSquirrelVM* sqvm, const SQChar* pError); -typedef bool (*sq_compilefileType)(CSquirrelVM* sqvm, const char* path, const char* name, int a4); - -// sq stack array funcs -typedef void (*sq_newarrayType)(HSquirrelVM* sqvm, SQInteger iStackpos); -typedef SQRESULT (*sq_arrayappendType)(HSquirrelVM* sqvm, SQInteger iStackpos); - -// sq table funcs -typedef SQRESULT (*sq_newtableType)(HSquirrelVM* sqvm); -typedef SQRESULT (*sq_newslotType)(HSquirrelVM* sqvm, SQInteger idx, SQBool bStatic); - -// sq stack push funcs -typedef void (*sq_pushroottableType)(HSquirrelVM* sqvm); -typedef void (*sq_pushstringType)(HSquirrelVM* sqvm, const SQChar* pStr, SQInteger iLength); -typedef void (*sq_pushintegerType)(HSquirrelVM* sqvm, SQInteger i); -typedef void (*sq_pushfloatType)(HSquirrelVM* sqvm, SQFloat f); -typedef void (*sq_pushboolType)(HSquirrelVM* sqvm, SQBool b); -typedef void (*sq_pushassetType)(HSquirrelVM* sqvm, const SQChar* str, SQInteger iLength); -typedef void (*sq_pushvectorType)(HSquirrelVM* sqvm, const SQFloat* pVec); -typedef void (*sq_pushobjectType)(HSquirrelVM* sqvm, SQObject* pVec); - -// sq stack get funcs -typedef const SQChar* (*sq_getstringType)(HSquirrelVM* sqvm, SQInteger iStackpos); -typedef SQInteger (*sq_getintegerType)(HSquirrelVM* sqvm, SQInteger iStackpos); -typedef SQFloat (*sq_getfloatType)(HSquirrelVM*, SQInteger iStackpos); -typedef SQBool (*sq_getboolType)(HSquirrelVM*, SQInteger iStackpos); -typedef SQRESULT (*sq_getType)(HSquirrelVM* sqvm, SQInteger iStackpos); -typedef SQRESULT (*sq_getassetType)(HSquirrelVM* sqvm, SQInteger iStackpos, const char** pResult); -typedef SQRESULT (*sq_getuserdataType)(HSquirrelVM* sqvm, SQInteger iStackpos, void** pData, uint64_t* pTypeId); -typedef SQFloat* (*sq_getvectorType)(HSquirrelVM* sqvm, SQInteger iStackpos); -typedef SQBool (*sq_getthisentityType)(HSquirrelVM*, void** ppEntity); -typedef void (*sq_getobjectType)(HSquirrelVM*, SQInteger iStackPos, SQObject* pOutObj); - -typedef long long (*sq_stackinfosType)(HSquirrelVM* sqvm, int iLevel, SQStackInfos* pOutObj, int iCallStackSize); - -// sq stack userpointer funcs -typedef void* (*sq_createuserdataType)(HSquirrelVM* sqvm, SQInteger iSize); -typedef SQRESULT (*sq_setuserdatatypeidType)(HSquirrelVM* sqvm, SQInteger iStackpos, uint64_t iTypeId); - -// sq misc entity funcs -typedef void* (*sq_getentityfrominstanceType)(CSquirrelVM* sqvm, SQObject* pInstance, char** ppEntityConstant); -typedef char** (*sq_GetEntityConstantType)(); - -typedef int (*sq_getfunctionType)(HSquirrelVM* sqvm, const char* name, SQObject* returnObj, const char* signature); - -// structs -typedef SQRESULT (*sq_pushnewstructinstanceType)(HSquirrelVM* sqvm, int fieldCount); -typedef SQRESULT (*sq_sealstructslotType)(HSquirrelVM* sqvm, int slotIndex); - -#pragma endregion - -// These "external" versions of the types are for plugins -typedef int64_t (*RegisterSquirrelFuncType_External)(ScriptContext context, SQFuncRegistration* funcReg, char unknown); diff --git a/NorthstarDLL/squirrel/squirreldatatypes.h b/NorthstarDLL/squirrel/squirreldatatypes.h deleted file mode 100644 index 84ab15ec..00000000 --- a/NorthstarDLL/squirrel/squirreldatatypes.h +++ /dev/null @@ -1,501 +0,0 @@ -#pragma once -/* - This file has been generated by IDA. - It contains local type definitions from - the type library 'server.dll' -*/ - -struct HSquirrelVM; -struct CallInfo; -struct SQTable; -struct SQString; -struct SQFunctionProto; -struct SQClosure; -struct SQSharedState; -struct StringTable; -struct SQStructInstance; -struct SQStructDef; -struct SQNativeClosure; -struct SQArray; -struct tableNode; -struct SQUserData; -struct CSquirrelVM; - -typedef void (*releasehookType)(void* val, int size); - -// stolen from ttf2sdk: sqvm types -typedef float SQFloat; -typedef long SQInteger; -typedef unsigned long SQUnsignedInteger; -typedef char SQChar; -typedef SQUnsignedInteger SQBool; - -/* 127 */ -enum SQObjectType : int -{ - _RT_NULL = 0x1, - _RT_INTEGER = 0x2, - _RT_FLOAT = 0x4, - _RT_BOOL = 0x8, - _RT_STRING = 0x10, - _RT_TABLE = 0x20, - _RT_ARRAY = 0x40, - _RT_USERDATA = 0x80, - _RT_CLOSURE = 0x100, - _RT_NATIVECLOSURE = 0x200, - _RT_GENERATOR = 0x400, - OT_USERPOINTER = 0x800, - _RT_USERPOINTER = 0x800, - _RT_THREAD = 0x1000, - _RT_FUNCPROTO = 0x2000, - _RT_CLASS = 0x4000, - _RT_INSTANCE = 0x8000, - _RT_WEAKREF = 0x10000, - OT_VECTOR = 0x40000, - SQOBJECT_CANBEFALSE = 0x1000000, - OT_NULL = 0x1000001, - OT_BOOL = 0x1000008, - SQOBJECT_DELEGABLE = 0x2000000, - SQOBJECT_NUMERIC = 0x4000000, - OT_INTEGER = 0x5000002, - OT_FLOAT = 0x5000004, - SQOBJECT_REF_COUNTED = 0x8000000, - OT_STRING = 0x8000010, - OT_ARRAY = 0x8000040, - OT_CLOSURE = 0x8000100, - OT_NATIVECLOSURE = 0x8000200, - OT_ASSET = 0x8000400, - OT_THREAD = 0x8001000, - OT_FUNCPROTO = 0x8002000, - OT_CLAAS = 0x8004000, - OT_STRUCT = 0x8200000, - OT_WEAKREF = 0x8010000, - OT_TABLE = 0xA000020, - OT_USERDATA = 0xA000080, - OT_INSTANCE = 0xA008000, - OT_ENTITY = 0xA400000, -}; - -/* 156 */ -union SQObjectValue -{ - SQString* asString; - SQTable* asTable; - SQClosure* asClosure; - SQFunctionProto* asFuncProto; - SQStructDef* asStructDef; - long long as64Integer; - SQNativeClosure* asNativeClosure; - SQArray* asArray; - HSquirrelVM* asThread; - float asFloat; - int asInteger; - SQUserData* asUserdata; - SQStructInstance* asStructInstance; -}; - -/* 160 */ -struct SQVector -{ - SQObjectType _Type; - float x; - float y; - float z; -}; - -/* 128 */ -struct SQObject -{ - SQObjectType _Type; - int structNumber; - SQObjectValue _VAL; -}; - -/* 138 */ -struct alignas(8) SQString -{ - void* vftable; - int uiRef; - int padding; - SQString* _next_maybe; - SQSharedState* sharedState; - int length; - unsigned char gap_24[4]; - char _hash[8]; - char _val[1]; -}; - -/* 137 */ -struct alignas(8) SQTable -{ - void* vftable; - unsigned char gap_08[4]; - int uiRef; - unsigned char gap_10[8]; - void* pointer_18; - void* pointer_20; - void* _sharedState; - long long field_30; - tableNode* _nodes; - int _numOfNodes; - int size; - int field_48; - int _usedNodes; - unsigned char _gap_50[20]; - int field_64; - unsigned char _gap_68[80]; -}; - -/* 140 */ -struct alignas(8) SQClosure -{ - void* vftable; - unsigned char gap_08[4]; - int uiRef; - void* pointer_10; - void* pointer_18; - void* pointer_20; - void* sharedState; - SQObject obj_30; - SQObject _function; - SQObject* _outervalues; - unsigned char gap_58[8]; - unsigned char gap_60[96]; - SQObject* objectPointer_C0; - unsigned char gap_C8[16]; -}; - -/* 139 */ -struct alignas(8) SQFunctionProto -{ - void* vftable; - unsigned char gap_08[4]; - int uiRef; - unsigned char gap_10[8]; - void* pointer_18; - void* pointer_20; - void* sharedState; - void* pointer_30; - SQObjectType _fileNameType; - SQString* _fileName; - SQObjectType _funcNameType; - SQString* _funcName; - SQObject obj_58; - unsigned char gap_68[12]; - int _stacksize; - unsigned char gap_78[48]; - int nParameters; - unsigned char gap_AC[60]; - int nDefaultParams; - unsigned char gap_EC[200]; -}; - -/* 152 */ -struct SQStructDef -{ - void* vtable; - int uiRef; - unsigned char padding_C[4]; - unsigned char unknown[24]; - SQSharedState* sharedState; - SQObjectType _nameType; - SQString* _name; - unsigned char gap_38[16]; - SQObjectType _variableNamesType; - SQTable* _variableNames; - unsigned char gap_[32]; -}; - -/* 157 */ -struct alignas(8) SQNativeClosure -{ - void* vftable; - int uiRef; - unsigned char gap_C[4]; - long long value_10; - long long value_18; - long long value_20; - SQSharedState* sharedState; - char unknown_30; - unsigned char padding_34[7]; - long long value_38; - long long value_40; - long long value_48; - long long value_50; - long long value_58; - SQObjectType _nameType; - SQString* _name; - long long value_70; - long long value_78; - unsigned char justInCaseGap_80[300]; -}; - -/* 162 */ -struct SQArray -{ - void* vftable; - int uiRef; - unsigned char gap_24[36]; - SQObject* _values; - int _usedSlots; - int _allocated; -}; - -/* 129 */ -struct alignas(8) HSquirrelVM -{ - void* vftable; - int uiRef; - unsigned char gap_8[12]; - void* _toString; - void* _roottable_pointer; - void* pointer_28; - CallInfo* ci; - CallInfo* _callstack; - int _callstacksize; - int _stackbase; - SQObject* _stackOfCurrentFunction; - SQSharedState* sharedState; - void* pointer_58; - void* pointer_60; - int _top; - SQObject* _stack; - unsigned char gap_78[8]; - SQObject* _vargvstack; - unsigned char gap_88[8]; - SQObject temp_reg; - unsigned char gapA0[8]; - void* pointer_A8; - unsigned char gap_B0[8]; - SQObject _roottable_object; - SQObject _lasterror; - SQObject _errorHandler; - long long field_E8; - int traps; - unsigned char gap_F4[12]; - int _nnativecalls; - int _suspended; - int _suspended_root; - int _unk; - int _suspended_target; - int trapAmount; - int _suspend_varargs; - int unknown_field_11C; - SQObject object_120; -}; - -/* 150 */ -struct SQStructInstance -{ - void* vftable; - __int32 uiRef; - BYTE gap_C[4]; - __int64 unknown_10; - void* pointer_18; - __int64 unknown_20; - SQSharedState* _sharedState; - unsigned int size; - BYTE gap_34[4]; - SQObject data[1]; // This struct is dynamically sized, so this size is unknown -}; - -/* 148 */ -struct SQSharedState -{ - unsigned char gap_0[72]; - void* unknown; - unsigned char gap_50[16344]; - SQObjectType _unknownTableType00; - long long _unknownTableValue00; - unsigned char gap_4038[16]; - StringTable* _stringTable; - unsigned char gap_4050[32]; - SQObjectType _unknownTableType0; - long long _unknownTableValue0; - SQObjectType _unknownObjectType1; - long long _unknownObjectValue1; - unsigned char gap_4090[8]; - SQObjectType _unknownArrayType2; - long long _unknownArrayValue2; - SQObjectType _gobalsArrayType; - SQStructInstance* _globalsArray; - unsigned char gap_40B8[16]; - SQObjectType _nativeClosuresType; - SQTable* _nativeClosures; - SQObjectType _typedConstantsType; - SQTable* _typedConstants; - SQObjectType _untypedConstantsType; - SQTable* _untypedConstants; - SQObjectType _globalsMaybeType; - SQTable* _globals; - SQObjectType _functionsType; - SQTable* _functions; - SQObjectType _structsType; - SQTable* _structs; - SQObjectType _typeDefsType; - SQTable* _typeDefs; - SQObjectType unknownTableType; - SQTable* unknownTable; - SQObjectType _squirrelFilesType; - SQTable* _squirrelFiles; - unsigned char gap_4158[80]; - SQObjectType _nativeClosures2Type; - SQTable* _nativeClosures2; - SQObjectType _entityTypesMaybeType; - SQTable* _entityTypesMaybe; - SQObjectType unknownTable2Type; - SQTable* unknownTable2; - unsigned char gap_41D8[72]; - SQObjectType _compilerKeywordsType; - SQTable* _compilerKeywords; - HSquirrelVM* _currentThreadMaybe; - unsigned char gap_4238[8]; - SQObjectType unknownTable3Type; - SQTable* unknownTable3; - unsigned char gap_4250[16]; - SQObjectType unknownThreadType; - SQTable* unknownThread; - SQObjectType _tableNativeFunctionsType; - SQTable* _tableNativeFunctions; - SQObjectType _unknownTableType4; - long long _unknownObjectValue4; - SQObjectType _unknownObjectType5; - long long _unknownObjectValue5; - SQObjectType _unknownObjectType6; - long long _unknownObjectValue6; - SQObjectType _unknownObjectType7; - long long _unknownObjectValue7; - SQObjectType _unknownObjectType8; - long long _unknownObjectValue8; - SQObjectType _unknownObjectType9; - long long _unknownObjectValue9; - SQObjectType _unknownObjectType10; - long long _unknownObjectValue10; - SQObjectType _unknownObjectType11; - long long _unknownObjectValue11; - SQObjectType _unknownObjectType12; - long long _unknownObjectValue12; - SQObjectType _unknownObjectType13; - long long _unknownObjectValue13; - SQObjectType _unknownObjectType14; - long long _unknownObjectValue14; - SQObjectType _unknownObjectType15; - long long _unknownObjectValue15; - unsigned char gap_4340[16]; - void* printFunction; - unsigned char gap_4358[16]; - void* logEntityFunction; - unsigned char gap_4370[40]; - SQObjectType _waitStringType; - SQString* _waitStringValue; - SQObjectType _SpinOffAndWaitForStringType; - SQString* _SpinOffAndWaitForStringValue; - SQObjectType _SpinOffAndWaitForSoloStringType; - SQString* _SpinOffAndWaitForSoloStringValue; - SQObjectType _SpinOffStringType; - SQString* _SpinOffStringValue; - SQObjectType _SpinOffDelayedStringType; - SQString* _SpinOffDelayedStringValue; - CSquirrelVM* cSquirrelVM; - bool enableDebugInfo; // functionality stripped - unsigned char gap_43F1[23]; -}; - -/* 165 */ -struct tableNode -{ - SQObject val; - SQObject key; - tableNode* next; -}; - -/* 136 */ -struct alignas(8) CallInfo -{ - long long ip; - SQObject* _literals; - SQObject obj10; - SQObject closure; - int _etraps[4]; - int _root; - short _vargs_size; - short _vargs_base; - unsigned char gap[16]; -}; - -/* 149 */ -struct StringTable -{ - unsigned char gap_0[12]; - int _numofslots; - unsigned char gap_10[200]; -}; - -/* 141 */ -struct alignas(8) SQStackInfos -{ - char* _name; - char* _sourceName; - int _line; -}; - -/* 151 */ -struct alignas(4) SQInstruction -{ - int op; - int arg1; - int output; - short arg2; - short arg3; -}; - -/* 154 */ -struct SQLexer -{ - unsigned char gap_0[112]; -}; - -/* 153 */ -struct SQCompiler -{ - unsigned char gap_0[4]; - int _token; - unsigned char gap_8[8]; - SQObject object_10; - SQLexer lexer; - unsigned char gap_90[752]; - HSquirrelVM* sqvm; - unsigned char gap_288[8]; -}; - -/* 155 */ -struct CSquirrelVM -{ - BYTE gap_0[8]; - HSquirrelVM* sqvm; - BYTE gap_10[8]; - SQObject unknownObject_18; - __int64 unknown_28; - BYTE gap_30[12]; - __int32 vmContext; - BYTE gap_40[648]; - char* (*formatString)(__int64 a1, const char* format, ...); - BYTE gap_2D0[24]; -}; - -struct SQUserData -{ - void* vftable; - int uiRef; - char gap_12[4]; - long long unknown_10; - long long unknown_18; - long long unknown_20; - long long sharedState; - long long unknown_30; - int size; - char padding1[4]; - releasehookType releaseHook; - long long typeId; - char data[1]; -}; |