#pragma once #include "squirreldatatypes.h" #include 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 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> FunctionVector; typedef std::function VoidFunction; // clang-format off template concept is_map = // Simple maps std::same_as> || std::same_as> || // Nested maps std::same_as < std::map, std::map > || std::same_as < std::unordered_map, std::unordered_map > || std::same_as < std::unordered_map, std::map > || std::same_as < std::map, std::unordered_map > ; template concept is_iterable = requires(std::ranges::range_value_t x) { x.begin(); // must have `x.begin()` x.end(); // and `x.end()` }; // clang-format on class SquirrelMessage { public: std::string functionName; FunctionVector args; }; class SquirrelMessageBuffer { private: std::queue messages = {}; public: std::mutex mutex; std::optional pop() { std::lock_guard 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 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