Libraries
An addon that exports a table is a library; another addon reads it with hafen.client():addons():get(id):api(). This page writes one, mylib, and one addon that uses it, myaddon. The verbs are in addons and libraries.
Writing one
A library is an ordinary addon: a folder, a manifest, files. What makes it a library is one call in its file body.
{ "id": "mylib", "name": "My Library", "version": "1.0.0", "author": "you", "api_version": "1.7", "files": ["mylib.lua"],
"description": "A notice at the top of the screen, for other addons to show" }
-- mylib.lua
local open = 0
local function show(text)
open = open + 1
local box = hafen.ui():widget():size(240, 28):position(400, 40 + open * 32)
hafen.ui():label():text(text):parent(box):position(8, 6)
hafen.timer():after(3, function() box:destroy(); open = open - 1 end)
return open
end
hafen.client():addons():export({
show = show,
count = function() return open end,
})
| Rule |
Why |
| Export in the file body |
Every addon that names you in a dependency list runs after you, so your export is there before their first line. |
| Export functions, not state |
The export is copied once, at the call; a number in it never changes for the reader. count() answers a value, count = open would not. |
| Return values, never handles |
The box show builds is yours; it cannot cross. Answer an id, a table, a function. |
| Your code runs as you |
Under your permissions, your store, your budget — whoever calls. A library that walks needs player.move in its own manifest, and the user consents to it when enabling the library. |
| A breaking change is a new id |
Inside mylib, only add. Rename or reshape a function and publish mylib2; consumers move when they choose. |
| Data stays with its owner |
Your store holds your own state and what is shared by nature (an index every consumer feeds). A consumer’s settings go in the consumer’s hafen.store() — lend it functions, not files. |
Using one
{ "id": "myaddon", "version": "0.3.0", "api_version": "1.7", "files": ["main.lua"],
"optional_dependencies": ["mylib>=1.0.0"] }
-- main.lua
local library = hafen.client():addons():get("mylib") -- a handle, installed or not
local function notify(text)
local api = library:api() -- the export, or nil
if api then api.show(text) else hafen.log():write(text) end
end
hafen.console():on("hello", function(args)
notify("Hello " .. (args[1] or ""))
end)
| Choice |
Effect |
optional_dependencies |
mylib runs before you when it is installed; nothing happens when it is not. Ask :api() when you need it. |
dependencies |
You do not run without it: error: needs mylib, which is not installed on your row. Use it when a missing library means your addon means nothing. |
mylib>=1.2.0 |
The version you need. Below it a hard dependency is an error and an optional one answers nil. |
| A callback |
A function you pass (api.on("click", function() hafen.log():write("clicked") end), when a library offers one) runs as you, through the client, when the library calls it. |
What happens
| Moment |
Detail |
| Load |
mylib runs, exports; myaddon runs after it. |
:hello |
myaddon calls api.show; the notice is built inside mylib, with mylib’s budget and consent. |
mylib removed |
The next reload: myaddon still loads, :api() is nil, notify writes to the log. |
mylib stopped by the watchdog |
myaddon keeps running; its :api() is nil from then on, a kept copy’s functions refuse mylib.show: mylib is disabled. A hard dependant would stop with it. |
See Also