From 49f784c40c7b531b8161f9d9b0503f578871ef46 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Wed, 11 Oct 2023 20:25:57 +0200 Subject: add Squirrel function registration --- src/internal/sqfuncregistrationproxy.h | 78 ++++++++++++++++++++++++++++++++++ src/plugin.cpp | 26 +++++++++++- src/plugin.h | 4 ++ src/server.cpp | 8 ++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/internal/sqfuncregistrationproxy.h diff --git a/src/internal/sqfuncregistrationproxy.h b/src/internal/sqfuncregistrationproxy.h new file mode 100644 index 0000000..3c08c61 --- /dev/null +++ b/src/internal/sqfuncregistrationproxy.h @@ -0,0 +1,78 @@ +#ifndef SQFUCREGISTRATIONPROXY_H +#define SQFUCREGISTRATIONPROXY_H + +#include "ns_plugin.h" +#include "proxy.h" +#include "types.h" + +static eSQReturnType SQReturnTypeFromString(const char* pReturnType) +{ + static const std::map 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 +} + +class SQFuncRegistrationProxy : public ClassProxy { + private: + std::string returnType; + std::string name; + std::string argTypes; + std::string helpText; + ScriptContext context; + SQFunction func; + + public: + SQFuncRegistrationProxy( + std::string returnType, + std::string name, + std::string argTypes, + std::string helpText, + ScriptContext context, + SQFunction func + ) : + returnType(returnType), + name(name), + argTypes(argTypes), + helpText(helpText), + context(context), + func(func) + {} + + virtual void initialize(void* data) + { + ptr = new SQFuncRegistration; + + ptr->squirrelFuncName = new char[name.size() + 1]; + strcpy((char*)ptr->squirrelFuncName, name.c_str()); + ptr->cppFuncName = ptr->squirrelFuncName; + + ptr->helpText = new char[helpText.size() + 1]; + strcpy((char*)ptr->helpText, helpText.c_str()); + + ptr->returnTypeString = new char[returnType.size() + 1]; + strcpy((char*)ptr->returnTypeString, returnType.c_str()); + ptr->returnType = SQReturnTypeFromString(returnType.c_str()); + + ptr->argTypes = new char[argTypes.size() + 1]; + strcpy((char*)ptr->argTypes, argTypes.c_str()); + + ptr->funcPtr = func; + } + + ScriptContext getContext() { return this->context; } + std::string getName() { return this->name; } +}; + +#endif \ No newline at end of file diff --git a/src/plugin.cpp b/src/plugin.cpp index 387846c..1e3f63b 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -9,6 +9,7 @@ #include "internal/types.h" #include "internal/concommandproxy.h" #include "internal/convarproxy.h" +#include "internal/sqfuncregistrationproxy.h" Plugin::Plugin(PluginInitFuncs* funcs, PluginNorthstarData* data) { @@ -114,24 +115,38 @@ void Plugin::LoadSQVMFunctions(ScriptContext context, SquirrelFunctions* funcs) void Plugin::LoadSQVM(ScriptContext context, CSquirrelVM* sqvm) { + SquirrelFunctions* funcs = nullptr; switch (context) { case ScriptContext::CLIENT: this->client_vm = *sqvm; + funcs = &this->client_sqvm_funcs; break; case ScriptContext::SERVER: this->server_vm = *sqvm; + funcs = &this->server_sqvm_funcs; break; case ScriptContext::UI: this->ui_vm = *sqvm; + funcs = &this->client_sqvm_funcs; break; case ScriptContext::INVALID: default: spdlog::warn("Received invalid script context"); - break; + return; + } + + for (SQFuncRegistrationProxy* proxy : this->squirrel_functions) + { + if (proxy->getContext() == context) + { + SQFuncRegistration* reg = proxy->get(); + spdlog::info("Registering Squirrel Function {}", proxy->getName()); + funcs->RegisterSquirrelFunc(sqvm, reg, 1); + } } } @@ -230,6 +245,15 @@ SQRESULT Plugin::RunSquirrelCode(ScriptContext context, std::string code, SQObje return SQRESULT_NOTNULL; } +SQFuncRegistrationProxy* Plugin::AddNativeSquirrelFunction(std::string returnType, std::string name, std::string argTypes, std::string helpText, ScriptContext context, SQFunction func) +{ + SQFuncRegistrationProxy* sqfrp = new SQFuncRegistrationProxy(returnType, name, argTypes, helpText, context, func); + + sqfrp->initialize(nullptr); + + return this->squirrel_functions.emplace_back(sqfrp); +} + ConCommandProxy* Plugin::ConCommand(const char* name, FnCommandCallback_t callback, const char* helpString, int flags, void* parent) { ConCommandProxy* proxy = new ConCommandProxy(name, callback, helpString, flags, parent); diff --git a/src/plugin.h b/src/plugin.h index 2d3d2d9..b913412 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -6,6 +6,7 @@ #include "ns_plugin.h" #include "internal/concommandproxy.h" #include "internal/convarproxy.h" +#include "internal/sqfuncregistrationproxy.h" class rpc_server; @@ -34,6 +35,8 @@ class Plugin { std::vector commands; std::vector variables; + std::vector squirrel_functions; + HMODULE GetModuleByName(const char* name); public: @@ -48,6 +51,7 @@ class Plugin { void StartServer(); void RunCommand(const char* cmd); SQRESULT RunSquirrelCode(ScriptContext context, std::string code, SQObject* ret_val); + SQFuncRegistrationProxy* AddNativeSquirrelFunction(std::string returnType, std::string name, std::string argTypes, std::string helpText, ScriptContext context, SQFunction func); // Wraps around the internals we receive ConCommandProxy* ConCommand(const char* name, FnCommandCallback_t callback, const char* helpString, int flags, void* parent = nullptr); diff --git a/src/server.cpp b/src/server.cpp index 199c2b9..9156260 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -17,6 +17,12 @@ void ConCommand_southrpc_status(const CCommand& args) spdlog::info("Yes"); } +SQRESULT Script_test(HSquirrelVM* sqvm) +{ + spdlog::info("Script_test invoked"); + return SQRESULT_NOTNULL; +} + rpc_server::rpc_server(Plugin* plugin) : parent(plugin) { @@ -24,6 +30,8 @@ rpc_server::rpc_server(Plugin* plugin) this->Convar_Port = plugin->ConVar("southrpc_port", DEFAULT_PORT, FCVAR_ARCHIVE, "South RPC HTTP Port (requires restart, default: " DEFAULT_PORT ")"); + plugin->AddNativeSquirrelFunction("void", "south_test", "", "", ScriptContext::UI, Script_test); + if (WSAStartup(MAKEWORD(2, 2), &this->wsaData) != 0) { spdlog::error("Failed to open Windows Socket"); return; -- cgit v1.2.3