#pragma once void InitialiseClientSquirrel(HMODULE baseAddress); void InitialiseServerSquirrel(HMODULE baseAddress); // stolen from ttf2sdk: sqvm types typedef float SQFloat; typedef long SQInteger; typedef unsigned long SQUnsignedInteger; typedef char SQChar; typedef SQUnsignedInteger SQBool; typedef SQInteger SQRESULT; 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* returnValueType; const char* argTypes; int16_t somethingThatsZero; int16_t padding1; int32_t unknown1; int64_t unknown2; int32_t unknown3; int32_t padding2; int64_t unknown4; int64_t unknown5; int64_t unknown6; int32_t unknown7; int32_t padding3; void* funcPtr; SQFuncRegistration() { memset(this, 0, sizeof(SQFuncRegistration)); this->padding2 = 32; } }; typedef SQRESULT(*sq_compilebufferType)(void* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, int a2); extern sq_compilebufferType ClientSq_compilebuffer; extern sq_compilebufferType ServerSq_compilebuffer; typedef void(*sq_pushroottableType)(void* sqvm); extern sq_pushroottableType ClientSq_pushroottable; extern sq_pushroottableType ServerSq_pushroottable; typedef SQRESULT(*sq_callType)(void* sqvm, SQInteger s1, SQBool a2, SQBool a3); extern sq_callType ClientSq_call; extern sq_callType ServerSq_call; typedef int64_t(*RegisterSquirrelFuncType)(void* sqvm, SQFuncRegistration* funcReg, char unknown); extern RegisterSquirrelFuncType ClientRegisterSquirrelFunc; extern RegisterSquirrelFuncType ServerRegisterSquirrelFunc; //template void ExecuteSQCode(SquirrelManager sqManager, const char* code); // need this because we can't do template class functions in the .cpp file typedef SQInteger(*SQFunction)(void* sqvm); template class SquirrelManager { private: std::vector m_funcRegistrations; public: void* sqvm; void* sqvm2; public: SquirrelManager() : sqvm(nullptr) {} void VMCreated(void* newSqvm) { sqvm = newSqvm; sqvm2 = *((void**)((char*)sqvm + 8)); // honestly not 100% sure on what this is, but alot of functions take it for (SQFuncRegistration* funcReg : m_funcRegistrations) { spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName); if (context == CLIENT || context == UI) ClientRegisterSquirrelFunc(sqvm, funcReg, 1); else ServerRegisterSquirrelFunc(sqvm, funcReg, 1); } } void VMDestroyed() { sqvm = nullptr; } void ExecuteCode(const char* code) { // ttf2sdk checks ThreadIsInMainThread here, might be good to do that? doesn't seem like an issue rn tho if (!sqvm) { spdlog::error("Cannot execute code, {} squirrel vm is not initialised", GetContextName(context)); return; } spdlog::info("Executing {} script code {} ", GetContextName(context), code); std::string strCode(code); CompileBufferState bufferState = CompileBufferState(strCode); SQRESULT compileResult; if (context == CLIENT || context == UI) compileResult = ClientSq_compilebuffer(sqvm2, &bufferState, "console", -1, context); else if (context == SERVER) compileResult = ServerSq_compilebuffer(sqvm2, &bufferState, "console", -1, context); spdlog::info("sq_compilebuffer returned {}", compileResult); if (compileResult >= 0) { if (context == CLIENT || context == UI) { ClientSq_pushroottable(sqvm2); SQRESULT callResult = ClientSq_call(sqvm2, 1, false, false); spdlog::info("sq_call returned {}", callResult); } else if (context == SERVER) { ServerSq_pushroottable(sqvm2); SQRESULT callResult = ServerSq_call(sqvm2, 1, false, false); spdlog::info("sq_call returned {}", callResult); } } } void AddFuncRegistration(std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func) { SQFuncRegistration* reg = new SQFuncRegistration; reg->squirrelFuncName = new char[name.size() + 1]; strcpy((char*)reg->squirrelFuncName, name.c_str()); reg->cppFuncName = reg->squirrelFuncName; reg->helpText = new char[helpText.size() + 1]; strcpy((char*)reg->helpText, helpText.c_str()); reg->returnValueType = new char[returnType.size() + 1]; strcpy((char*)reg->returnValueType, returnType.c_str()); reg->argTypes = new char[argTypes.size() + 1]; strcpy((char*)reg->argTypes, argTypes.c_str()); reg->funcPtr = func; m_funcRegistrations.push_back(reg); } }; extern SquirrelManager* g_ClientSquirrelManager; extern SquirrelManager* g_ServerSquirrelManager; extern SquirrelManager* g_UISquirrelManager;