Skip to content
Basalt Server

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:

bash
kiln new greeter "Greeter"
greeter/
  plugin.toml
  src/main.lua
  resources/config.toml

plugin.toml is the manifest:

toml
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:

lua
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#

bash
kiln check greeter

Kiln 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#

bash
kiln pack greeter

This 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.

Edit this page