Files

97 lines
3.5 KiB
Markdown

# Native ABI v2
Every native plugin is a Go `main` package built with `-buildmode=c-shared` and
exports three C symbols:
```c
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:
```json
{
"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`](../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.