aboutsummaryrefslogtreecommitdiff
path: root/primedev/plugins/interfaces
diff options
context:
space:
mode:
Diffstat (limited to 'primedev/plugins/interfaces')
-rw-r--r--primedev/plugins/interfaces/IPluginCallbacks.h36
-rw-r--r--primedev/plugins/interfaces/IPluginId.h31
-rw-r--r--primedev/plugins/interfaces/interface.cpp36
-rw-r--r--primedev/plugins/interfaces/interface.h39
-rw-r--r--primedev/plugins/interfaces/sys/ISys.cpp66
-rw-r--r--primedev/plugins/interfaces/sys/ISys.h21
6 files changed, 229 insertions, 0 deletions
diff --git a/primedev/plugins/interfaces/IPluginCallbacks.h b/primedev/plugins/interfaces/IPluginCallbacks.h
new file mode 100644
index 00000000..c02ce8a6
--- /dev/null
+++ b/primedev/plugins/interfaces/IPluginCallbacks.h
@@ -0,0 +1,36 @@
+#ifndef IPLUGIN_CALLBACKS_H
+#define IPLUGIN_CALLBACKS_H
+
+#include <windows.h>
+#include <stdint.h>
+#include "squirrel/squirrel.h"
+
+// can't use bitwise ops on enum classes but I don't want these in the global namespace (user defined operators suck)
+namespace PluginContext
+{
+ enum : uint64_t
+ {
+ DEDICATED = 0x1,
+ CLIENT = 0x2,
+ };
+}
+
+struct PluginNorthstarData
+{
+ HMODULE pluginHandle;
+};
+
+class IPluginCallbacks
+{
+public:
+ virtual void
+ Init(HMODULE northstarModule, const PluginNorthstarData* initData, bool reloaded) = 0; // runs after the plugin is loaded and validated
+ virtual void Finalize() = 0; // runs after all plugins have been loaded
+ virtual bool Unload() = 0; // runs just before the library is freed
+ virtual void OnSqvmCreated(CSquirrelVM* sqvm) = 0;
+ virtual void OnSqvmDestroying(CSquirrelVM* sqvm) = 0;
+ virtual void OnLibraryLoaded(HMODULE module, const char* name) = 0;
+ virtual void RunFrame() = 0;
+};
+
+#endif
diff --git a/primedev/plugins/interfaces/IPluginId.h b/primedev/plugins/interfaces/IPluginId.h
new file mode 100644
index 00000000..dc4c548b
--- /dev/null
+++ b/primedev/plugins/interfaces/IPluginId.h
@@ -0,0 +1,31 @@
+#ifndef IPLUGIN_ID_H
+#define IPLUGIN_ID_H
+
+#include <stdint.h>
+#include "squirrel/squirrelclasstypes.h"
+
+#define PLUGIN_ID_VERSION "PluginId001"
+
+// an identifier for the type of string data requested from the plugin
+enum class PluginString : int
+{
+ NAME = 0,
+ LOG_NAME = 1,
+ DEPENDENCY_NAME = 2,
+};
+
+// an identifier for the type of bitflag requested from the plugin
+enum class PluginField : int
+{
+ CONTEXT = 0,
+};
+
+// an interface that is required from every plugin to query data about it
+class IPluginId
+{
+public:
+ virtual const char* GetString(PluginString prop) = 0;
+ virtual int64_t GetField(PluginField prop) = 0;
+};
+
+#endif
diff --git a/primedev/plugins/interfaces/interface.cpp b/primedev/plugins/interfaces/interface.cpp
new file mode 100644
index 00000000..4c006f2c
--- /dev/null
+++ b/primedev/plugins/interfaces/interface.cpp
@@ -0,0 +1,36 @@
+#include <string.h>
+#include "interface.h"
+
+InterfaceReg* s_pInterfaceRegs;
+
+InterfaceReg::InterfaceReg(InstantiateInterfaceFn fn, const char* pName) : m_pName(pName)
+{
+ m_CreateFn = fn;
+ m_pNext = s_pInterfaceRegs;
+ s_pInterfaceRegs = this;
+}
+
+void* CreateInterface(const char* pName, InterfaceStatus* pReturnCode)
+{
+ for (InterfaceReg* pCur = s_pInterfaceRegs; pCur; pCur = pCur->m_pNext)
+ {
+ if (strcmp(pCur->m_pName, pName) == 0)
+ {
+ if (pReturnCode)
+ {
+ *pReturnCode = InterfaceStatus::IFACE_OK;
+ }
+
+ NS::log::PLUGINSYS->info("creating interface {}", pName);
+ return pCur->m_CreateFn();
+ }
+ }
+
+ if (pReturnCode)
+ {
+ *pReturnCode = InterfaceStatus::IFACE_FAILED;
+ }
+
+ NS::log::PLUGINSYS->error("could not find interface {}", pName);
+ return NULL;
+}
diff --git a/primedev/plugins/interfaces/interface.h b/primedev/plugins/interfaces/interface.h
new file mode 100644
index 00000000..440db5b2
--- /dev/null
+++ b/primedev/plugins/interfaces/interface.h
@@ -0,0 +1,39 @@
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+typedef void* (*InstantiateInterfaceFn)();
+
+// Used internally to register classes.
+class InterfaceReg
+{
+public:
+ InterfaceReg(InstantiateInterfaceFn fn, const char* pName);
+
+ InstantiateInterfaceFn m_CreateFn;
+ const char* m_pName;
+ InterfaceReg* m_pNext;
+};
+
+// Use this to expose an interface that can have multiple instances.
+#define EXPOSE_INTERFACE(className, interfaceName, versionName) \
+ static void* __Create##className##_interface() \
+ { \
+ return static_cast<interfaceName*>(new className); \
+ } \
+ static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName);
+
+#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
+ static void* __Create##className##interfaceName##_interface() \
+ { \
+ return static_cast<interfaceName*>(&globalVarName); \
+ } \
+ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
+
+// Use this to expose a singleton interface. This creates the global variable for you automatically.
+#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
+ static className __g_##className##_singleton; \
+ EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
+
+EXPORT void* CreateInterface(const char* pName, InterfaceStatus* pReturnCode);
+
+#endif
diff --git a/primedev/plugins/interfaces/sys/ISys.cpp b/primedev/plugins/interfaces/sys/ISys.cpp
new file mode 100644
index 00000000..6b0b41dd
--- /dev/null
+++ b/primedev/plugins/interfaces/sys/ISys.cpp
@@ -0,0 +1,66 @@
+#include "plugins/interfaces/interface.h"
+#include "ISys.h"
+#include "plugins/plugins.h"
+#include "plugins/pluginmanager.h"
+
+class CSys : public ISys
+{
+public:
+ void Log(HMODULE handle, LogLevel level, char* msg)
+ {
+ spdlog::level::level_enum spdLevel;
+
+ switch (level)
+ {
+ case LogLevel::WARN:
+ spdLevel = spdlog::level::level_enum::warn;
+ break;
+ case LogLevel::ERR:
+ spdLevel = spdlog::level::level_enum::err;
+ break;
+ default:
+ NS::log::PLUGINSYS->warn("Attempted to log with invalid level {}. Defaulting to info", (int)level);
+ case LogLevel::INFO:
+ spdLevel = spdlog::level::level_enum::info;
+ break;
+ }
+
+ std::optional<Plugin> plugin = g_pPluginManager->GetPlugin(handle);
+ if (plugin)
+ {
+ plugin->Log(spdLevel, msg);
+ }
+ else
+ {
+ NS::log::PLUGINSYS->warn("Attempted to log message '{}' with invalid plugin handle {}", msg, static_cast<void*>(handle));
+ }
+ }
+
+ void Unload(HMODULE handle)
+ {
+ std::optional<Plugin> plugin = g_pPluginManager->GetPlugin(handle);
+ if (plugin)
+ {
+ plugin->Unload();
+ }
+ else
+ {
+ NS::log::PLUGINSYS->warn("Attempted to unload plugin with invalid handle {}", static_cast<void*>(handle));
+ }
+ }
+
+ void Reload(HMODULE handle)
+ {
+ std::optional<Plugin> plugin = g_pPluginManager->GetPlugin(handle);
+ if (plugin)
+ {
+ plugin->Reload();
+ }
+ else
+ {
+ NS::log::PLUGINSYS->warn("Attempted to reload plugin with invalid handle {}", static_cast<void*>(handle));
+ }
+ }
+};
+
+EXPOSE_SINGLE_INTERFACE(CSys, ISys, SYS_VERSION);
diff --git a/primedev/plugins/interfaces/sys/ISys.h b/primedev/plugins/interfaces/sys/ISys.h
new file mode 100644
index 00000000..3e55a6d9
--- /dev/null
+++ b/primedev/plugins/interfaces/sys/ISys.h
@@ -0,0 +1,21 @@
+#ifndef ILOGGING_H
+#define ILOGGING_H
+
+#define SYS_VERSION "NSSys001"
+
+enum class LogLevel : int
+{
+ INFO = 0,
+ WARN,
+ ERR,
+};
+
+class ISys
+{
+public:
+ virtual void Log(HMODULE handle, LogLevel level, char* msg) = 0;
+ virtual void Unload(HMODULE handle) = 0;
+ virtual void Reload(HMODULE handle) = 0;
+};
+
+#endif