Files
GoMinecraftBridge/docs/native-abi.md
T

3.5 KiB

Native ABI v2

Every native plugin is a Go main package built with -buildmode=c-shared and exports three C symbols:

int32_t gmb_abi_version(void);

int32_t gmb_call(
    int32_t operation,
    const uint8_t *input,
    uint64_t input_length,
    uint8_t **output,
    uint64_t *output_length
);

void gmb_free(void *pointer);

Plugin authors do not implement these symbols. Importing the Go SDK includes their native implementation in the final c-shared library.

gmb_call receives an operation-specific byte buffer and returns a buffer allocated by the plugin. The host copies the buffer and always returns it through gmb_free. A zero C status means the transport succeeded. Go callback errors and panics are represented in the JSON response rather than the C status.

Operations

Code Name Input
1 metadata empty
2 init InitEvent
3 tick FlatBuffers ServerSnapshot (GMBS)
4 chat ChatEvent
5 death DeathEvent
6 system call result SystemCallResult
7 deinit DeinitEvent
8 client tick ClientTickEvent

Every successful transport response uses this envelope:

{
  "status": "ok",
  "error": "",
  "stack": "",
  "data": null,
  "logs": [],
  "actions": [],
  "systemCalls": [],
  "snapshot": null
}

status is one of ok, error, or panic. The host disables a plugin after a panic. An ordinary handler error is logged but does not disable an already-running plugin.

All inputs except operation 3 are UTF-8 JSON. Server tick input follows schema/tick_snapshot.fbs and includes the FlatBuffers file identifier GMBS. Responses remain UTF-8 JSON because action, log, subscription, and system-call batches are normally small. A native library compiled against ABI v1 is rejected by an ABI v2 host before initialization.

All memory ownership stays on its allocating side. Java objects, Go pointers, and Go structs never cross the boundary.

Plugin environment metadata

The metadata response may contain an environment field with one of server, client, or both. Server hosts execute server and both plugins; client hosts execute client and both plugins. Metadata without this field predates the declaration and is treated as server, so adding it does not change ABI v2.

Client libraries are loaded from config/go-minecraft-bridge/client-plugins; their persistent data is isolated under config/go-minecraft-bridge/client-data/<plugin-id>. They start even when the connected server does not have Go Minecraft Bridge installed. The client tick JSON contains the tick number, connection state, remote address, local player UUID/name, and current dimension; world-dependent strings are absent outside a world.

The client runtime accepts only the minecraft:client.chat.display action, queued by Context.DisplayClientMessage. Server actions, snapshot subscriptions, and system calls are rejected locally and are never forwarded to the connected server. InitEvent.runtimeEnvironment tells a both plugin which host invoked it (server or client).

The Paper/Purpur host implements the server side of the same ABI without a separate Go SDK. Native packages are discovered under plugins/GoMinecraftBridge/go-plugins, and receive runtimeEnvironment=server. The public Bukkit/Paper API supplies entity/block snapshots, actions, and the built-in Minecraft system calls, so native plugin binaries can be moved between Fabric, Paper, and Purpur servers without recompilation when the operating system and CPU architecture match.