Declare a module
Create my-module.lua in <config>/aesthetic/scripts/. The game can stay running.
local module = ui.create("code", "My Module")ui.create(icon, name[, description]) takes an icon glyph ("code", "bolt", "eye", …)
and a name unique among modules. The module lands in the Scripts tab.
Add settings
local delay = module:slider("Delay", 1, 100, 20, 1, "t")
local text = module:input("Text", "hello")
local on = module:switch("Enabled part", true)Each call adds one row to the panel, top to bottom in declaration order. Read a value with
:get(). Every control type is on Settings.
Handle events
local ticks = 0
module:event("enable", function()
ticks = 0
end)
module:event("tick", function()
ticks = ticks + 1
if on:get() and ticks % delay:get() == 0 then
print(text:get())
end
end)Names are exact snake_case strings: "enable" and "disable" fire on toggle, the rest come
from the game. See Events.
Save
Chat shows lua » Loaded my-module.lua and the module appears in the GUI. Enable it and keep
editing: each save reloads the script, keeping setting values and the enabled state.
Editor support
Every launch writes language-server files next to your scripts:
| Path | Contents |
|---|---|
scripts/library/*.lua |
LuaCATS stubs for the whole API |
scripts/docs/*.md |
Offline copy of this reference |
scripts/.luarc.json |
Points lua-language-server at the stubs |
library/ and docs/ are overwritten on every launch, so edits there are lost. .luarc.json
is only written when missing.
Open the scripts folder in an editor running lua-language-server for completion, hovers,
signature help and typed event callbacks:
Install the Lua extension (sumneko), then open the scripts folder. .luarc.json is
picked up automatically.
Install the SumnekoLua plugin and open the scripts folder as a project.
Enable lua_ls (for example through nvim-lspconfig) and start Neovim inside the scripts
folder, so the server finds .luarc.json at the workspace root.
Debug output
| Call | Goes to |
|---|---|
print("a", value) |
Chat, with a lua » prefix |
aesthetic.log(msg) |
Game log, prefixed with the script file name |
Shared code
require resolves relative to the scripts folder. Only top-level .lua files load as
scripts, so shared code goes in a subfolder:
local util = require "lib/util" -- <scripts>/lib/util.lua
module:event("enable", function()
util.greet()
end)local M = {}
function M.greet()
print("hello from lib")
end
return M