Per-mod file storage. Every call is sandboxed to data/<MOD_NAME>/ — a mod can only read and write inside its own folder. Absolute paths and .. are rejected.
functiondata.write(name, contents) → boolean
Writes contents to name (overwriting), creating sub-folders as needed.
| Param | Type | Notes |
| name | string | File path relative to your folder, e.g. "save.txt" or "sub/x.dat". |
| contents | string | Data to write (may contain binary bytes). |
| returns | boolean — true on success; false if the write failed or the path was rejected. |
functiondata.read(name) → string | nil
Reads a file back.
| Param | Type | Notes |
| name | string | File path relative to your folder. |
| returns | string with the contents, or nil if it doesn't exist / can't be read. |
functiondata.append(name, contents) → boolean
Appends contents to the end of name (creating it if needed).
| Param | Type | Notes |
| name | string | File path relative to your folder. |
| contents | string | Data to append. |
| returns | boolean — success. |
functiondata.write / append(name, buf, from, len) → boolean
Both take a slice of a Buffer instead of a string. The bytes go from the buffer to the file with no copy at all — where data.append(name, buf:sub(from, len)) would build a Lua string of the whole slice first, which for anything big is the entire cost of the write, and the garbage afterwards.
| Param | Type | Notes |
| buf | Buffer | Source. |
| from | number | 0-based offset to start at. |
| len | number | How many bytes. Clamped to the end of the buffer. |
functiondata.exists(name) → boolean
Whether a file exists in your data folder.
| Param | Type | Notes |
| name | string | File path relative to your folder. |
| returns | boolean. |
functiondata.delete(name) → boolean
Deletes a file.
| Param | Type | Notes |
| name | string | File path relative to your folder. |
| returns | boolean — whether a file was removed. |
functiondata.list() → string[]
Lists your saved files. Takes no parameters. Returns a Lua array (table) of string relative paths of all files in your data folder, recursively.
functiondata.path() → string
The absolute path of your data folder (informational). Takes no parameters. Returns a string.
Persist and restore a value:
local score = tonumber(data.read("score.txt")) or 0
score = score + 1
data.write("score.txt", tostring(score))
log(MOD_NAME .. " score is now " .. score)