Skip to content

Introduction

Balltze plugins are written in Lua. A plugin can react to what happens in the game through events, add console commands, read and change tags and objects, draw text on screen, talk to the server or its players over the network, and keep its own files and settings.

Plugins are loaded while the game runs. They can be limited to certain maps, in which case they are loaded and unloaded as those maps come and go, and they can be reloaded from the console while you work on them.

Lua

Plugins run on Lua 5.3. Every plugin gets its own Lua state, so plugins do not share globals and cannot break each other.

The API is documented with LuaLS annotations, which give code completion and type checking in editors that support the Lua language server. See Editor setup.

Plugins folder

Plugins live in Documents\My Games\ringworld\balltze\plugins. Every plugin is a folder with a manifest.json file and a main Lua file:

Documents\My Games\ringworld\balltze\plugins
|-- my_plugin
|   |-- manifest.json
|   |-- main.lua
|   |-- modules
|   |   `-- my_module.lua
|   `-- assets
|       `-- my_asset.png
`-- other_plugin
    |-- manifest.json
    `-- main.lua

Loose .lua files placed directly in the plugins folder are ignored. The plugins folder is scanned once, when the game starts: a new plugin, or a change to a manifest, needs a restart.

Manifest

manifest.json describes the plugin:

manifest.json
{
    "name": "my_plugin",
    "author": "Your Name",
    "plugin_main": "main.lua",
    "version": "1.0.0",
    "target_api": "2.0.0",
    "maps": [],
    "reloadable": true
}
Field Required Description
name Yes Name of the plugin. It prefixes the plugin's console commands and tags its log messages.
author Yes Author of the plugin.
plugin_main Yes Main Lua file, relative to the plugin folder. Must end in .lua and exist.
version Yes Version of the plugin, as a semantic version such as 1.0.0.
target_api Yes Version of the Balltze API the plugin was written for, as a semantic version. The current API is 2.0.0.
maps No Names of the maps the plugin runs on, e.g. ["bloodgulch", "sidewinder"]. Empty or missing means every map. Default is [].
reloadable No Whether balltze_reload_plugins reloads the plugin. Default is false.

A plugin with a missing or invalid manifest is skipped.

Lifecycle

There is no load function. When a plugin loads, its main file runs from top to bottom: that is where it registers its commands and event listeners and sets up its state. If the main file raises an error, the plugin fails to load.

Two global functions are called later, if the plugin defines them:

PluginOnGameStart()
Called once, on the first game tick after the plugin loaded. Game state such as players and objects is available from here on.
PluginUnload()
Called when the plugin is unloaded, before its Lua state is closed. Use it to clean up what the plugin changed in the game.

When a plugin unloads, Balltze removes its console commands, event listeners, timers, on-screen texts, HUD elements and network listeners on its own.

When plugins load

Plugins are loaded when a map loads, starting with the menu map when the game starts. On every map load:

  1. Plugins without a maps list that are not loaded yet are loaded. They stay loaded from then on.
  2. Every plugin with a maps list is unloaded, even when the new map is also in its list.
  3. Plugins whose maps list has the name of the new map are loaded.

Plugins are loaded while the map is loading, on the loading thread, before the tags of the new map are available. Anything that needs the map's tags or objects should wait for the map_loaded event or for PluginOnGameStart.

Warning

A map plugin is unloaded while the game is already switching maps. Objects it spawned may be gone by the time PluginUnload runs, so check them before touching them.

Reloading

The console command balltze_reload_plugins unloads and loads again every loaded plugin with "reloadable": true, on the next tick. Its main file runs again and PluginOnGameStart is called again on that same tick. The manifest is not read again.

A plugin that failed to load is not retried until the game is restarted.

Environment

  • Plugins run on Lua 5.3.5.
  • Every standard Lua library is available, except os.exit, os.getenv and os.execute.
  • require looks for modules in the modules folder of the plugin, as modules\<name>.lua or modules\<name>.dll.
  • These libraries are bundled with Balltze and can be loaded with require from any plugin:
Module Version Description
json rxi/json.lua 0.1.2 JSON encoding and decoding.
inspect kikito/inspect.lua 3.1.0 Human readable representation of tables, for debugging.
luna Sledmine/luna 2.10.0 Utility functions for strings and tables.
lfmt starwing/lua-fmt The {} style string formatting used by the logger.
lanes LuaLanes/lanes 3.17.0 Multithreading. Already configured.
  • Log messages from Balltze.logger are printed to the game console, tagged with the plugin name.
  • Balltze.filesystem works with paths relative to the plugin folder. The standard io library works with any path.