Plugins
Write a Lua plugin for Basalt Server, run it and package it, from an empty folder to a .bspkg.
Plugins are written in Lua 5.5 and run inside the server, with no process boundary and no second runtime to install.
A plugin is a folder with a manifest (plugin.toml), its code under src/ and its data files under resources/. The
same folder, zipped, is a .bspkg package. Everything the server can do, a plugin can do through this API.
This page takes a plugin from nothing to a package. The rest of the section is the reference:
| Page | Covers |
|---|---|
| Manifest and layout | plugin.toml, the folder layout, dependencies, capabilities, the /plugins command |
| Events | on, watch, priorities, filters, cancelling and editing events, custom events |
| Commands | cmd, argument types, permissions |
| Scheduler and coroutines | wait, later, every, at, request_chunk |
| The sandbox | Instruction budget, memory ceiling, which globals exist, what happens on an error |
| Config and lang files | config, translations, MiniMessage text, placeholders |
| Storage | data, store, player.data, files |
| Menus and HUD | menu, form, sidebar, boss_bar |
| Shared code | require across plugins, service |
| Tooling | Kiln, the VS Code extension, editor definitions |
| Testing and distribution | kiln test, packing, signing compiled plugins |
Then one page per area of the API: the events reference, players, entities, worlds, items and recipes, scoreboards and boss bars, server control and packets. Existing Bukkit and Paper jars run from the same folder, see Bukkit plugins.
Create a plugin#
Kiln is the plugin command line: download it and see Tooling. kiln new makes the skeleton:
kiln new greeter "Greeter"greeter/
plugin.toml
src/main.lua
resources/config.tomlplugin.toml is the manifest:
id = "greeter"
name = "Greeter"
version = "0.1.0"
authors = []
api = 1
main = "src/main.lua"Replace src/main.lua with a join message and a command:
on("player.join", function(e)
e.player:send("<green>Welcome, {name}!", { name = e.player.name })
end)
cmd("hello [who: word]", function(src, who)
src:send("<yellow>Hello, {who}!", { who = who or src.name })
end, { permission = "" })on(event, handler)listens to an event. Every event, with its fields, is in the events reference.cmd(spec, handler, options)registers a command. The spec declares its arguments and their types, and the handler receives the source of the command followed by one value per argument.permission = ""opens it to everyone, otherwise only operators may run it, see Commands.- Text is MiniMessage, never
ยงcolour codes.{name}is replaced from the table given after the text.
Run it#
A plugin folder works as it is. Put it, or a symlink to it, in the plugins/ folder of the server and start the server,
or run /plugins load on a server that is already up:
plugins/
greeter/ a folder with plugin.toml
arena.bspkg a package/plugins lists what is loaded, with the registrations and errors of each plugin. While you edit, /plugins reload greeter unloads the plugin, releasing every handler, command and task it registered, and loads it again from disk.
The data folder
A loose folder uses its own resources/ folder as its data folder, so config.toml and lang/ are the files you edit.
A .bspkg copies its resources/ to plugins/<id>/ the first time it loads, and never overwrites a file that is already
there, so the operator can edit them. See Manifest and layout.
Check it#
kiln check greeterKiln reads the manifest, every Lua file, every require and every name the code takes from the API, and reports what is
wrong before the plugin reaches a server: a misspelt players.onlin, a require of a module that does not exist, a
manifest without a version.
Package it#
kiln pack greeterThis checks the plugin again and writes greeter/build/greeter-0.1.0.bspkg, the same bytes every time for the same
files. Drop the file in plugins/ and start the server. To ship bytecode instead of source, and to sign it, see
Testing and distribution.
What the server gives a plugin#
A plugin sees a small set of globals: on, watch, cmd and emit for events and commands, wait, later, every
and at for time, players, worlds and the other tables of the API, config, store, data and files for its
data, log and plugin for itself. The complete list is in The sandbox.
A defective plugin is a plugin problem and never a server problem. Every failure is reported with the plugin that caused it, a plugin that keeps failing is switched off, and the server keeps running. See The sandbox.