mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-09-02 00:38:46 -04:00
inter mod communication
This commit is contained in:
+37
-1
@@ -16,7 +16,8 @@ Mods are shared libraries packaged into a `.dusk` zip archive. The loader scans
|
||||
- [Post-hooks](#post-hooks)
|
||||
- [Replace hooks](#replace-hooks)
|
||||
- [Reading and writing arguments](#reading-and-writing-arguments)
|
||||
9. [Full Example](#full-example)
|
||||
9. [Inter-Mod Communication](#inter-mod-communication)
|
||||
10. [Full Example](#full-example)
|
||||
|
||||
---
|
||||
|
||||
@@ -98,6 +99,8 @@ The `api` pointer is valid for the lifetime of the mod. When using `hook.hpp`, c
|
||||
| `register_tab_content` | Add a panel to the mod manager's per-mod tab |
|
||||
| `register_menu_item` | Add an item to the quick-access menu |
|
||||
| `hook_dispatch_pre` / `hook_dispatch_post` | Called by the trampoline, do not call directly |
|
||||
| `service_publish` | Register a named pointer in the global service registry |
|
||||
| `service_get` | Look up a named pointer registered by another mod |
|
||||
|
||||
---
|
||||
|
||||
@@ -248,6 +251,39 @@ dusk::hookAddPre<&daEnemy_c::takeDamage>(on_takeDamage_pre);
|
||||
For reference parameters (e.g. `const cXyz& pos`), use `argRef<cXyz>` to get a direct reference.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Inter-Mod Communication
|
||||
|
||||
Mods can expose a public API to each other through a global service registry. The convention for names is `"mod_name/service_name"`.
|
||||
|
||||
**Mod A — publishing:**
|
||||
|
||||
```cpp
|
||||
struct MyModAPI {
|
||||
void (*do_thing)(int value);
|
||||
};
|
||||
|
||||
static void my_do_thing(int value) { ... }
|
||||
static MyModAPI g_api = { my_do_thing };
|
||||
|
||||
extern "C" void mod_init(DuskModAPI* api) {
|
||||
api->service_publish("my_mod/api", &g_api);
|
||||
}
|
||||
```
|
||||
|
||||
**Mod B — consuming:**
|
||||
|
||||
```cpp
|
||||
#include "my_mod_api.h"
|
||||
|
||||
static MyModAPI* g_my_mod = nullptr;
|
||||
|
||||
extern "C" void mod_init(DuskModAPI* api) {
|
||||
g_my_mod = static_cast<MyModAPI*>(api->service_get("my_mod/api"));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Full Example
|
||||
|
||||
@@ -38,6 +38,9 @@ typedef struct DuskModAPI {
|
||||
|
||||
bool (*hook_dispatch_pre) (void* fn_addr, void* args);
|
||||
void (*hook_dispatch_post)(void* fn_addr, void* args);
|
||||
|
||||
void (*service_publish)(const char* name, void* ptr);
|
||||
void* (*service_get) (const char* name);
|
||||
} DuskModAPI;
|
||||
|
||||
void mod_init(DuskModAPI* api);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <cstdarg>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "miniz.h"
|
||||
@@ -59,6 +60,7 @@ static constexpr const char* k_libExt = ".so";
|
||||
#endif
|
||||
|
||||
static dusk::LoadedMod* g_currentMod = nullptr;
|
||||
static std::unordered_map<std::string, void*> g_services;
|
||||
|
||||
namespace dusk {
|
||||
void* g_dusk_hook_current_mod = nullptr;
|
||||
@@ -134,6 +136,20 @@ static void cb_register_tab_content(void (*draw_fn)(void*), void* userdata) {
|
||||
g_currentMod->tab_content.push_back({draw_fn, userdata});
|
||||
}
|
||||
|
||||
static void cb_service_publish(const char* name, void* ptr) {
|
||||
if (name) {
|
||||
g_services[name] = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void* cb_service_get(const char* name) {
|
||||
if (!name) {
|
||||
return nullptr;
|
||||
}
|
||||
auto it = g_services.find(name);
|
||||
return it != g_services.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
static void cb_register_menu_item(void (*draw_fn)(void*), void* userdata) {
|
||||
if (g_currentMod && draw_fn)
|
||||
g_currentMod->menu_items.push_back({draw_fn, userdata});
|
||||
@@ -174,6 +190,8 @@ void ModLoader::buildAPI(LoadedMod& mod) {
|
||||
mod.api.hook_replace = api_hook_replace;
|
||||
mod.api.hook_dispatch_pre = hookDispatchPre;
|
||||
mod.api.hook_dispatch_post = hookDispatchPost;
|
||||
mod.api.service_publish = cb_service_publish;
|
||||
mod.api.service_get = cb_service_get;
|
||||
}
|
||||
|
||||
void ModLoader::tryLoadDusk(const std::filesystem::path& modPath) {
|
||||
@@ -365,6 +383,7 @@ void ModLoader::shutdown() {
|
||||
}
|
||||
}
|
||||
m_mods.clear();
|
||||
g_services.clear();
|
||||
DuskLog.info("ModLoader: all mods unloaded");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user