Skip to Content
Plugin DevelopmentPlugin Structure

Plugin Structure

MudForge plugins are Lua scripts that run their code at the top level.

Basic Structure

print("Loading...") local widget = createWidget({ type = "canvas", title = "My Widget", width = 200, height = 100 }) local function draw() clear("#1e1e2e") drawRect(10, 10, 180, 80, "#89b4fa") drawText("Hello!", 60, 50, "#cdd6f4") end registerWidgetEvent(widget, "resize", function() draw() end) function init() draw() end print("Loaded!")

Lifecycle Methods

Plugins can define these global functions to hook into the plugin lifecycle:

FunctionAliasWhen Called
init()onPluginInstall()When plugin is loaded
onPluginEnable()-After init, each time plugin is enabled
onPluginDisable()-Before cleanup, each time plugin is disabled
cleanup()onPluginClose()When plugin is unloaded

Lifecycle Order:

  • Load: init()onPluginEnable()
  • Unload: onPluginDisable()cleanup()

The init() Function

The init() function (or its alias onPluginInstall()) is called after the canvas is ready for drawing:

local widget = createWidget({ type = "canvas", title = "Demo", width = 300, height = 200 }) local function draw() clear("#222222") drawRect(10, 10, 280, 180, "#4a4a6a") drawText("Ready!", 120, 100, "#ffffff") end registerWidgetEvent(widget, "resize", function() draw() end) function init() draw() end

Enable/Disable Hooks

Use onPluginEnable() and onPluginDisable() for operations that should happen each time the plugin is toggled:

local heartbeatTimer = nil function init() -- One-time setup print("Plugin installed!") end function onPluginEnable() -- Start operations when enabled heartbeatTimer = addTimer(10000, function() Send("look") end, true) print("Plugin enabled - starting heartbeat") end function onPluginDisable() -- Pause operations when disabled if heartbeatTimer then removeTimer(heartbeatTimer) heartbeatTimer = nil end print("Plugin disabled - stopped heartbeat") end function cleanup() -- Final cleanup when unloaded print("Plugin unloaded!") end

Resize Handling

Always redraw when the widget is resized:

registerWidgetEvent(widget, "resize", function(eventData) draw() end)

Multiple Widgets

Only use setActiveWidget() when you have multiple widgets:

local widget1 = createWidget({ type = "canvas", title = "One", width = 200, height = 100 }) local widget2 = createWidget({ type = "canvas", title = "Two", width = 200, height = 100 }) local function drawWidget1() setActiveWidget(widget1) clear("#1e1e2e") drawText("Widget 1", 50, 50, "#ffffff") end local function drawWidget2() setActiveWidget(widget2) clear("#2e1e1e") drawText("Widget 2", 50, 50, "#ffffff") end

Complete Example

A health bar that responds to MUD output:

print("Health Monitor loading...") local widget = createWidget({ type = "canvas", title = "Health", width = 200, height = 40 }) local currentHP = 100 local maxHP = 100 local function draw() clear("#222222") drawRect(5, 10, 190, 20, "#333333") local pct = currentHP / maxHP local color = pct > 0.5 and "#00ff00" or pct > 0.25 and "#ffff00" or "#ff0000" drawRect(7, 12, 186 * pct, 16, color) drawText(currentHP .. "/" .. maxHP, 75, 25, "#ffffff") end registerWidgetEvent(widget, "resize", function() draw() end) function init() draw() end addTrigger("HP:\\s*(\\d+)/(\\d+)", function(line, matches) currentHP = tonumber(matches[1]) maxHP = tonumber(matches[2]) draw() end, { type = "regex" }) registerCommand("sethp", function(args) if args[1] then local hp, max = string.match(args[1], "(%d+)/(%d+)") if hp then currentHP, maxHP = tonumber(hp), tonumber(max) draw() end end end, "Set health: /sethp 50/100") print("Health Monitor loaded!")

Cleanup

MudForge automatically cleans up when plugins are unloaded:

  • Widgets are destroyed
  • Timers are cancelled
  • Event listeners are removed

For custom cleanup logic, define the cleanup() function (or its alias onPluginClose()):

local connections = {} function init() -- Setup connections, resources, etc. connections.database = openDatabase() end function cleanup() -- Custom cleanup when plugin unloads if connections.database then connections.database:close() end saveTable("my_plugin_state", currentState) print("Plugin cleaned up!") end

registerCommand

registerCommand(name, handler, description)
ParameterTypeDescription
namestringCommand name (without /)
handlerfunctionCallback receiving args table
descriptionstringHelp text

The args parameter is a table of space-separated arguments:

registerCommand("greet", function(args) local name = args[1] or "stranger" print("Hello, " .. name .. "!") end, "Greet someone") -- /greet Bob → args = { "Bob" }

Best Practices

  1. Use init() for drawing - Initial canvas drawing happens in init()
  2. Handle resize - Use registerWidgetEvent(widget, "resize", ...)
  3. Use local variables - Avoid conflicts between plugins
  4. Print loading messages - Help users know when plugins load
Last updated on