Plugins
A plugin is a 32-bit DLL that runs inside the game, loaded by the framework. Most bots are better as separate programs: a crash there never touches the game, and any language works. A plugin is for what a separate program cannot do:
- an in-process bot that answers within the same tick it was given, with no process boundary (the tick's own thread calls it);
- ImGui windows of its own in the overlay, drawn with the full Dear ImGui API;
- commands in the game's console (which bots and
ibf cmdcan run too); - probes: raw values read from the game's memory and published to every bot.
Loading one
Put it in ibf\plugins\ in the game folder and name it in ibf\ibf.toml:
[plugins]
enabled = ["hello"] # loads ibf\plugins\hello.dll
[plugins.hello] # its own settings, which it reads (and sees change at once)
greeting = "hi"Restart the game. The console command plugins lists them: loaded or not and why, their
callbacks, their ticks and their faults. The SDK zip has the example, examples\plugins\hello,
and how to build it.
Writing one
A plugin includes ibf_plugin.h (and imgui.h first, if it draws) and exports one
function, which the framework calls once, after the game has started:
#include <cstdio>
#include <imgui.h>
#include "ibf_plugin.h"
static const ibf_host_api* g_api;
static void IBF_PLUGIN_CALL on_tick(void*, const ibf_plugin_tick* tick) {
// tick->snapshot: the state just published. The game's own thread: be quick.
}
static void IBF_PLUGIN_CALL on_render(void*, const ibf_plugin_render* r) {
ibf_imgui_begin(r); // the game's ImGui context and allocator, first
if (r->flags & IBF_RENDER_PANELS) {
ImGui::Begin("my plugin");
ImGui::Text("hello");
ImGui::End();
}
}
static int IBF_PLUGIN_CALL cmd_hello(void*, int argc, const char* const* argv, char* out, uint32_t cap) {
snprintf(out, cap, "hello with %d words", argc);
return 0; // 0: success
}
extern "C" IBF_PLUGIN_EXPORT int IBF_PLUGIN_CALL ibf_plugin_entry(const ibf_host_api* api, uint32_t version,
ibf_plugin_info* info) {
g_api = api;
snprintf(info->version, sizeof(info->version), "1.0");
api->register_command(api->self, "myplugin.hello", "", "says hello", 0, &cmd_hello, nullptr);
api->on_tick(api->self, &on_tick, nullptr);
const ibf_imgui_abi imgui = IBF_IMGUI_ABI;
api->on_render(api->self, &imgui, &on_render, nullptr);
return 0; // anything else declines to load
}What the api table offers:
log |
into the game's log and console, as plugin:<name> |
register_command |
a console command, named <plugin>.<command> |
on_tick |
each published snapshot, on the game's tick thread, before lockstep waits for bots |
on_render |
the overlay's ImGui frame (only for a plugin built against the game's ImGui version) |
get_snapshot, tick_now, now_ns |
the newest state from any thread; the clock |
config_get |
a setting from [plugins.<name>] |
register_probe |
[[probe]] tables, as in ibf\probes.toml |
bind_pad, set_pad, draw_submit, params_define, param_values, stats_publish |
a bridge client of its own (IBF_PLUGIN_FLAG_CLIENT in info->flags): a bot pad, a draw list, parameters and stats in the Bots panel, like any bot |
world_to_screen |
in on_render: where a world point lands on screen |
Registration works only inside ibf_plugin_entry. The table only grows: a member added in a
later version is there when IBF_PLUGIN_HAS(api, member) says so. The
C API reference documents every member.
Rules
- Faults cost the plugin, not the game. Every call into a plugin is guarded: a crash or an exception that escapes it disables that plugin (its callbacks stop, and its commands answer that it is disabled), and the game, the framework and the other plugins go on. Plugins are never unloaded while the game runs.
on_tickruns on the game's thread. Do not block, wait or sleep there; its time is the game's frame time. Do heavy work on a thread of your own.- ImGui: build against the same Dear ImGui as the framework (the SDK zip has its headers
and library:
ibf::imguiin CMake), and callibf_imgui_begin(r)first inon_render. The framework refuses a render callback from another version. A window left open by a faulting plugin is closed for it. - 32-bit, statically linked runtime: the game is a 32-bit process. Build with
-A Win32;/MTavoids shipping a runtime.