diff options
Diffstat (limited to 'NorthstarDLL/squirrel/squirrel.h')
-rw-r--r-- | NorthstarDLL/squirrel/squirrel.h | 526 |
1 files changed, 0 insertions, 526 deletions
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 |