2020-02-25 20:47:42 +01:00
# Modding Library (`modlib`)
2020-02-13 11:11:52 +01:00
Multipurpose Minetest Modding Library
2019-05-01 16:53:01 +02:00
2019-05-03 13:51:17 +02:00
## About
2020-02-13 11:11:52 +01:00
No dependencies. Licensed under the MIT License. Written by Lars Mueller aka LMD or appguru(eu).
2019-05-03 13:51:17 +02:00
2019-05-01 16:53:01 +02:00
## API
2020-02-13 11:11:52 +01:00
2020-06-02 23:07:33 +02:00
Mostly self-documenting code. Mod namespace is `modlib` or `_ml` , containing all variables & functions.
2021-04-21 21:11:00 +02:00
### Persistence
#### Lua Log Files
A data log file based on Lua statements. **Experimental.** High performance. Example from `test.lua` :
```lua
local logfile = persistence.lua_log_file.new(mod.get_resource"logfile.test.lua", {})
logfile:init()
logfile.root = {}
logfile:rewrite()
logfile:set_root({a = 1}, {b = 2, c = 3})
logfile:close()
logfile:init()
assert(table.equals(logfile.root, {[{a = 1}] = {b = 2, c = 3}}))
```
2021-07-03 19:35:02 +02:00
Both strings and tables are stored in a reference table. Unused strings won't be garbage collected as Lua doesn't allow marking them as weak references.
This means that setting lots of temporary strings will waste memory until you call `:rewrite()` on the log file. An alternative is to set the third parameter, `reference_strings` , to `false` (default value is `true` ):
```lua
persistence.lua_log_file.new(mod.get_resource"logfile.test.lua", {}, false)
```
This will prevent strings from being referenced, possibly bloating file size, but saving memory.
2021-03-05 15:08:57 +01:00
### Bluon
Binary Lua object notation. **Experimental.** Handling of subnormal numbers (very small floats) may be broken.
#### `new(def)`
```lua
def = {
aux_is_valid = function(object)
return is_valid
end,
aux_len = function(object)
return length_in_bytes
end,
-- read type byte, stream providing :read(count), map of references -> id
aux_read = function(type, stream, references)
... = stream:read(...)
return object
end,
-- object to be written, stream providing :write(text), list of references
aux_write = function(object, stream, references)
stream:write(...)
end
}
```
#### `:is_valid(object)`
Returns whether the given object can be represented by the instance as boolean.
#### `:len(object)`
Returns the expected length of the object if serialized by the current instance in bytes.
#### `:write(object, stream)`
Writes the object to a stream supporting `:write(text)` . Throws an error if invalid.
#### `:read(stream)`
Reads a single bluon object from a stream supporting `:read(count)` . Throws an error if invalid bluon.
Checking whether the stream has been fully consumed by doing `assert(not stream:read(1))` is left up to the user.
#### Format
* `nil` : nothing (`""`)
* `false` : 0
* `true` : 1
* Numbers:
* Constants: 0, nan, +inf, -inf
* Integers: Little endian `U8` , `U16` , `U32` , `U64` , `-U8` , `-U16` , `-U32` , `-U64`
* Floats: Little endian `F32` , `F64`
* Strings:
* Constant: `""`
* Length as unsigned integer: `T8` , `T16` , `T32` , `T64`
* Tables:
* List and map part count as unsigned integers
* `L0` , `L8` , `L16` , `L32` , `L64` times `M0` , `M8` , `M16` , `M32` , `M64`
* Reference:
* Reference ID as unsigned integer: `R8` , `R16` , `R32` , `R64`
* Reserved types:
* Everything < = 55 => 200 free types
#### Features
* Embeddable: Written in pure Lua
* Storage efficient: No duplication of strings or reference-equal tables
* Flexible: Can serialize circular references and strings containing null
#### Simple example
```lua
local object = ...
-- Write to file
local file = io.open(..., "w")
modlib.bluon:write(object, file)
file:close()
-- Write to text
local rope = modlib.table.rope{}
modlib.bluon:write(object, rope)
text = rope:to_text()
-- Read from text
local inputstream = modlib.text.inputstream"\1"
assert(modlib.bluon:read(object, rope) == true)
```
#### Advanced example
```lua
-- Serializes all userdata to a constant string:
local custom_bluon = bluon.new{
aux_is_valid = function(object)
return type(object) == "userdata"
end,
aux_len = function(object)
return 1 + ("userdata"):len())
end,
aux_read = function(type, stream, references)
assert(type == 100, "unsupported type")
assert(stream:read(("userdata"):len()) == "userdata")
return userdata()
end,
-- object to be written, stream providing :write(text), list of references
aux_write = function(object, stream, references)
assert(type(object) == "userdata")
stream:write"\100userdata"
end
}
-- Write to text
local rope = modlib.table.rope{}
custom_bluon:write(userdata(), rope)
assert(rope:to_text() == "\100userdata")
```
2021-03-31 22:36:03 +02:00
### Schema
Place a file `schema.lua` in your mod, returning a schema table.
#### Non-string entries and `minetest.conf`
Suppose you have the following schema:
```lua
return {
type = "table",
entries = {
[42] = {
type = "boolean",
description = "The Answer"
default = true
}
}
}
```
And a user sets the following config:
```conf
mod.42 = false
```
It won't work, as the resulting table will be `{["42"] = false}` instead of `{[42] = false}` . In order to make this work, you have to convert the keys yourself:
```lua
return {
type = "table",
keys = {
-- this will convert all keys to numbers
type = "number"
},
entries = {
[42] = {
type = "boolean",
description = "The Answer"
default = true
}
}
}
```
This is best left explicit. First, you shouldn't be using numbered field keys if you want decent `minetest.conf` support, and second, `modlib` 's schema module could only guess in this case, attempting conversion to number / boolean. What if both number and string field were set as possible entries? Should the string field be deleted? And so on.
2020-06-02 23:07:33 +02:00
## Configuration
2020-12-20 14:39:01 +01:00
### Legacy
2020-06-28 22:42:24 +02:00
1. Configuration is loaded from `<worldpath>/config/<modname>.<extension>` , the following extensions are supported and loaded (in the given order), with loaded configurations overriding properties of previous ones:
2020-06-02 23:07:33 +02:00
1. [`json` ](https://json.org )
2020-06-28 22:42:24 +02:00
2. [`lua` ](https://lua.org )
3. [`luon` ](https://github.com/appgurueu/luon ), Lua but without the `return`
4. [`conf` ](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt )
2020-12-20 14:39:01 +01:00
2. Settings are loaded from `minetest.conf` and override configuration values
### Locations
0. Default configuration: `<modfolder>/conf.lua`
1. World configuration: `config/<modname>.<format>`
2. Mod configuration: `<modfolder>/conf.<format>`
3. Minetest configuration: `minetest.conf`
### Formats
1. [`lua` ](https://lua.org )
* Lua, with the environment being the configuration object
* `field = value` works
* Return new configuration object to replace
2. [`luon` ](https://github.com/appgurueu/luon )
* Single Lua literal
* Booleans, numbers, strings and tables
3. [`conf` ](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt )
* Minetest-like configuration files
4. [`json` ](https://json.org )
2021-03-30 18:10:50 +02:00
* Not recommended
2021-05-04 16:18:46 +02:00
## `debug`
`modlib.debug` offers utilities dumping program state in tables.
### `variables(stacklevel)`
Dumps local variables, upvalues and the function environment of the function at the given stacklevel (default `1` ).
### `stack(stacklevel)`
Dumps function info & variables for all functions in stack, starting with stacklevel (default `1` ).
2021-05-08 21:17:09 +02:00
## `minetest`
### `schematic`
A schematic format with support for metadata and baked light data. **Experimental.**
2021-04-23 19:35:03 +02:00
## Release Notes
2021-06-18 20:58:21 +02:00
### `rolling-70`
* Fixes module environments once and for all
* Fixes vector aliases
* Presumably boosts performance
2021-05-13 15:15:04 +02:00
### `rolling-69`
* Fixes various things, **most importantly modules indexing the global table**
2021-04-23 19:35:03 +02:00
### `rolling-68`
* Replace changelog by release notes (see the commit log for changes)
2021-03-30 18:10:50 +02:00
2021-04-23 12:43:05 +02:00
### `rolling-67`
* Fixes various things, **most importantly objects indexing the global table**
* Concerns `kdtree` , `trie` , `ranked_set` , `vector` , `schema`
2021-04-21 21:40:07 +02:00
### `rolling-66`
* Adds `modlib.persistence.lua_log_file`
2021-04-02 21:09:40 +02:00
### `rolling-62`
* Fix `modlib.func.curry_tail`
* Change `b3d:get_animated_bone_properties` to return a list according to hierarchy
2021-04-01 01:06:12 +02:00
### `rolling-61`
* Fix `quaternion.to_euler_rotation`
2021-04-01 00:05:34 +02:00
### `rolling-60`
* Fix `vector.interpolate`
2021-03-31 23:42:41 +02:00
### `rolling-59`
* Schema failing check handling fixes
2021-03-31 22:37:04 +02:00
### `rolling-58`
* Schema improvements & docs
2021-03-30 22:27:16 +02:00
### `rolling-57`
* Uses `minetest.safe_file_write` for `file.write`
2021-03-30 18:10:50 +02:00
### `rolling-56`
* Fixes `math.fround`
2021-03-30 18:12:25 +02:00
* Other minor fixes
* Switch to lazy loading
* Do `_ = modlib.<module>` to avoid lag spikes at run time