Skip to content

Creating your first Lua plugin

In this guide we will create a small plugin that greets the player in the console when a game starts and adds a console command that prints where the player is standing.

You need Balltze installed and a code editor. We recommend Visual Studio Code with the Lua extension.

Step 1: Create the plugin folder

Go to Documents\My Games\ringworld\balltze\plugins and create a folder called hello. The folder name does not matter to Balltze, but keeping it the same as the plugin name helps.

Step 2: Set up your editor

Open the hello folder in your editor. For code completion and type checking of the Balltze API, you need the annotation files balltze.lua, engine.lua, meta_types.lua and meta_types_extensions.lua (see Types). Put them in a folder on your computer and point the Lua language server at it. In the hello folder, create .luarc.json:

.luarc.json
{
    "runtime.version": "Lua 5.3",
    "workspace.library": ["C:\\path\\to\\balltze\\lua\\docs"]
}

Step 3: Write the manifest

Create manifest.json in the hello folder:

manifest.json
{
    "name": "hello",
    "author": "Your Name",
    "plugin_main": "main.lua",
    "version": "1.0.0",
    "target_api": "2.0.0",
    "reloadable": true
}

There is no maps field, so the plugin runs on every map. reloadable lets us reload it while we work on it.

Step 4: Write the plugin

Create main.lua next to the manifest:

main.lua
-- Runs once, when the plugin loads.
Balltze.logger.info("Hello plugin loaded")

-- Called on the first tick after the plugin loads.
function PluginOnGameStart()
    Engine.terminal.print({a = 1, r = 0.4, g = 1, b = 0.4}, "Hello from the hello plugin!")
end

-- Typed in the console as "hello_where".
Balltze.registerCommand(
    "where",                                  -- name
    "Prints the position of the local player", -- help
    nil,                                      -- parameters help
    false,                                    -- autosave
    0, 0,                                     -- minimum and maximum arguments
    true,                                     -- show in TAB completion
    false,                                    -- other plugins may not call it
    function(args)
        local player = Engine.player.getPlayer()
        if not player or player.unitHandle:isNull() then
            Engine.terminal.print("You are not spawned")
            return true
        end
        local position = Engine.object.getObjectPosition(player.unitHandle)
        Engine.terminal.print("You are at {:.2f}, {:.2f}, {:.2f}", position.x, position.y, position.z)
        return true
    end
)

The main file registers everything the plugin needs. PluginOnGameStart runs once the game is ticking, and the command runs whenever it is typed. Commands get the plugin name as a prefix, so where is typed as hello_where.

Step 5: Test the plugin

Start the game and open the console. You should see the greeting. Load a map, spawn, and type hello_where.

After changing main.lua, type balltze_reload_plugins to load the new version without restarting the game. If the plugin fails to load, the error and its stack trace are printed to the console.

Next steps