mirror of
https://github.com/minetest/minetest_docs.git
synced 2024-10-05 17:33:08 +02:00
Document MetaData & subclasses (#40)
* Document MetaData & subclasses * Document `context` inv location availability * ModStorage: Add section on backends * Document client support
This commit is contained in:
parent
6bdf60a6c4
commit
48230eda06
116
doc/classes/ItemStackMetaData.adoc
Normal file
116
doc/classes/ItemStackMetaData.adoc
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
= ItemStackMetaData
|
||||||
|
|
||||||
|
include::../include/config.adoc[]
|
||||||
|
include::../include/types.adoc[]
|
||||||
|
:description: Per-ItemStack persistent key-value store
|
||||||
|
:keywords: meta, data, metadata, item, stack, storage, key, value, persistence
|
||||||
|
|
||||||
|
ItemStackMetaData is a subclass of MetaData obtained via `stack:get_meta()`
|
||||||
|
allowing for persistent storage of key-value pairs tied to ItemStacks.
|
||||||
|
|
||||||
|
WARNING: ItemStack metadata is serialized with ItemStacks, increasing the ItemString length.
|
||||||
|
Inventories have to store multiple ItemStrings, all of which an attacker will try to get to maximum length.
|
||||||
|
Always limit the size of your ItemStackMetaData to keep inventories sendable.
|
||||||
|
|
||||||
|
== Special Fields
|
||||||
|
|
||||||
|
=== Description
|
||||||
|
|
||||||
|
* `description`: The description to be shown when hovering over the item (see `ItemStack:get_description`).
|
||||||
|
* `short_description`: A short description of the item (see `ItemStack:get_short_description`).
|
||||||
|
|
||||||
|
=== Hardware Colorization
|
||||||
|
|
||||||
|
* `color`: ColorString to use for hardware colorization of the stack.
|
||||||
|
* `palette_index`: Palette index to use for hardware colorization of the stack (if the stack has a palette).
|
||||||
|
|
||||||
|
=== Count
|
||||||
|
|
||||||
|
Requires Minetest 5.6 clients for the count override
|
||||||
|
(older clients will simply show the item count according to the item definition);
|
||||||
|
works on all 5.x servers since it only uses ItemStackMetaData serverside.
|
||||||
|
|
||||||
|
==== `count_meta`
|
||||||
|
|
||||||
|
String to show in inventory lists instead of the item count.
|
||||||
|
|
||||||
|
==== `count_alignment`
|
||||||
|
|
||||||
|
Integer (use with `:get_int` and `:set_int`).
|
||||||
|
|
||||||
|
Alignment of the displayed item count value is encoded as `x_align + 4 * y_align`
|
||||||
|
where `x_align` and `y_align` are one of:
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| Value | X-alignment (horizontally) | Y-alignment (vertically)
|
||||||
|
| `0` | Default (currently same as `3`: Right) | Default (currently same as `3`: Bottom/Down)
|
||||||
|
| `1` | Left | Top/Up
|
||||||
|
| `2` | Centered/Middle | Centered/Middle
|
||||||
|
| `3` | Right | Bottom/Down
|
||||||
|
|===
|
||||||
|
|
||||||
|
[TIP]
|
||||||
|
.Code quality
|
||||||
|
====
|
||||||
|
Magic numbers make code unreadable.
|
||||||
|
|
||||||
|
Add an explanatory comment when setting alignment:
|
||||||
|
|
||||||
|
[source,lua]
|
||||||
|
----
|
||||||
|
local meta = stack:get_meta()
|
||||||
|
meta:set_string("count_alignment", 3 + 4 * 1) -- aligned to the top-right corner
|
||||||
|
----
|
||||||
|
|
||||||
|
or use well-named (constant) local variables:
|
||||||
|
|
||||||
|
[source,lua]
|
||||||
|
----
|
||||||
|
local meta = stack:get_meta()
|
||||||
|
local align_top_right = 3 + 4 * 1
|
||||||
|
meta:set_int("count_alignment", align_top_right)
|
||||||
|
----
|
||||||
|
|
||||||
|
or perhaps wrap this all up in a useful helper:
|
||||||
|
|
||||||
|
[source,lua]
|
||||||
|
----
|
||||||
|
local vert_align = {
|
||||||
|
default = 0,
|
||||||
|
top = 1,
|
||||||
|
center = 2,
|
||||||
|
bottom = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
local horz_align = {
|
||||||
|
default = 0,
|
||||||
|
left = 1,
|
||||||
|
center = 2,
|
||||||
|
right = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
local function set_stack_cnt_align(stack, vertically, horizontally)
|
||||||
|
stack:get_meta():set_int("count_alignment", horz_align[horizontally] + 4 * vert_align[vertically])
|
||||||
|
end
|
||||||
|
|
||||||
|
set_stack_cnt_align(stack, "top", "right")
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
== Methods
|
||||||
|
|
||||||
|
=== `:set_tool_capabilities(tool_capabilities)`
|
||||||
|
|
||||||
|
Allows overriding the tool capabilities specified in the item definition.
|
||||||
|
|
||||||
|
==== Arguments
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `tool_capabilities` | `nil` or a tool capabilities table | Either:
|
||||||
|
* `nil`: Clears the tool capability override, or
|
||||||
|
* Tool capabilities table: Overrides the defined tool capabilities (see ItemDefinition for the table format)
|
||||||
|
|===
|
||||||
|
|
||||||
|
NOTE: The corresponding `:get_tool_capabilities` is not a method of ItemStackMetaData but rather of the "parent" ItemStack.
|
227
doc/classes/MetaData.adoc
Normal file
227
doc/classes/MetaData.adoc
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
= MetaData
|
||||||
|
|
||||||
|
include::../include/config.adoc[]
|
||||||
|
include::../include/types.adoc[]
|
||||||
|
:description: Base class of various meta data classes used to persist key-value pairs
|
||||||
|
:keywords: meta, data, metadata, storage, key, value, persistence
|
||||||
|
|
||||||
|
MetaData is an interface implemented by various reference types implementing persistent
|
||||||
|
string-based key-value stores.
|
||||||
|
|
||||||
|
The methods documented below are available in all subclasses.
|
||||||
|
|
||||||
|
== Subclasses
|
||||||
|
|
||||||
|
Subclasses tie the key-value store to various objects recognized by Minetest:
|
||||||
|
|
||||||
|
* ModStorage - per mod
|
||||||
|
* NodeMetaData - per node on the map
|
||||||
|
* ItemStackMetaData - per item stack
|
||||||
|
* PlayerMetaData - per player
|
||||||
|
|
||||||
|
== Methods
|
||||||
|
|
||||||
|
=== Getters
|
||||||
|
|
||||||
|
NOTE: No type information is stored for values; values will be coerced to and from string as needed.
|
||||||
|
Mods need to know which type they expect in order to call the appropriate getters & setters.
|
||||||
|
Do not rely on coercion to work one way or another; never mix different types.
|
||||||
|
|
||||||
|
WARNING: https://github.com/minetest/minetest/issues/12577[Getters currently resolve the value `${key}` to the value associated with `key`].
|
||||||
|
|
||||||
|
[TIP]
|
||||||
|
.Storing other types
|
||||||
|
====
|
||||||
|
Due to the limitations of the provided setters & getters, you might favor using your own
|
||||||
|
(de)serialization for coercion of Lua types to strings which can be stored in the string k-v store.
|
||||||
|
|
||||||
|
* `minetest.write_json` & `minetest.parse_json` for Lua tables which are representable as JSON;
|
||||||
|
* `minetest.serialize` & `minetest.deserialize` for arbitrary Lua tables (consisting of tables & primitive types);
|
||||||
|
|
||||||
|
[source,lua]
|
||||||
|
----
|
||||||
|
local meta = ... -- some MetaData reference
|
||||||
|
|
||||||
|
local json = {key = "value", list = {1, 2, 3}}
|
||||||
|
meta:set_string("json", minetest.write_json(json))
|
||||||
|
local got_json = minetest.parse_json(meta:get_string"json")
|
||||||
|
assert(got_json.key == "value" and got_json.list[1] == 1 and got_json.list[2] == 2 and got_json.list[3] == 3)
|
||||||
|
|
||||||
|
local lua = {[42] = true, [true] = false} -- JSON only allows string keys
|
||||||
|
meta:set_string("lua", minetest.serialize(lua))
|
||||||
|
local got_lua = minetest.deserialize(meta:get_string"lua")
|
||||||
|
assert(got_lua[42] == true and got_lua[true] == false)
|
||||||
|
----
|
||||||
|
|
||||||
|
Applying serialization to numbers provides you with safe number storage;
|
||||||
|
you don't have to worry about C(++) type bounds.
|
||||||
|
====
|
||||||
|
|
||||||
|
==== Arguments
|
||||||
|
|
||||||
|
All getters take only a single argument: The key/name.
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `key` | `{type-string}` | the key/name
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:contains(key)`
|
||||||
|
|
||||||
|
Checks for the existence of a key-value pair.
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `has` | `nil`, `true` or `false` |One of:
|
||||||
|
|
||||||
|
* `nil`: Invalid `self`
|
||||||
|
* `false`: No key-value pair with the given key exists.
|
||||||
|
* `true`: A key-value pair with the given key exists.
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:get(key)`
|
||||||
|
|
||||||
|
Retrieves the value associated with a key.
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `nil` or `{type-string}` | Either:
|
||||||
|
* `nil` if no matching key-value pair exists, or
|
||||||
|
* `{type-string}`: The associated value
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:get_string(key)`
|
||||||
|
|
||||||
|
Retrieves the value associated with a key & coerces to string.
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-string}` | Either:
|
||||||
|
* `""` if no matching key-value pair exists, or
|
||||||
|
* `{type-string}`: The associated value
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:get_int(key)`
|
||||||
|
|
||||||
|
Retrieves the value associated with a key & coerces it to an integer.
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-number}` | Either:
|
||||||
|
* `0` if no matching key-value pair exists, or
|
||||||
|
* `{type-number}`: The associated value, coerced to an integer
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:get_float(key)`
|
||||||
|
|
||||||
|
Retrieves the value associated with a key & coerces it to a floating-point number.
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-number}` | Either:
|
||||||
|
* `0` if no matching key-value pair exists, or
|
||||||
|
* `{type-number}`: The associated value, coerced to a floating point number
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== Setters
|
||||||
|
|
||||||
|
==== Arguments & Returns
|
||||||
|
|
||||||
|
Setters have no return values; they all take exactly two arguments: Key & value.
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `key` | `{type-string}` | the key/name
|
||||||
|
| `value` | depends on the setter | the value
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
==== `:set_string(key, value)`
|
||||||
|
|
||||||
|
==== Arguments
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-string}` | The value to associate with `key`. Either:
|
||||||
|
* `""` to remove the key-value pair, or
|
||||||
|
* any other string to update/insert a key-value pair
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:set_int(key, value)`
|
||||||
|
|
||||||
|
==== Arguments
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-number}` | The integer value to coerce to a string & associate with `key`
|
||||||
|
|
||||||
|
WARNING: Integer refers to a C(++) `int` as internally used by the implementation - usually 32 bits wide -
|
||||||
|
meaning it is unable to represent as large integer numbers as the Lua number type.
|
||||||
|
Be careful when storing integers with large absolute values; they may overflow.
|
||||||
|
Keep `value` between `-2^31` and `2^31 - 1`, both inclusive.
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:set_float(key, value)`
|
||||||
|
|
||||||
|
==== Arguments
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-number}` | The floating-point value to coerce to a string & associate with `key`
|
||||||
|
|
||||||
|
WARNING: The implementation internally uses the C(++) `float` type - usually 32 bits wide -
|
||||||
|
whereas Lua guarantees 64-bit "double-precision" floating point numbers.
|
||||||
|
This may lead to a precision loss. Large numbers in particular may be hardly representable.
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:equals(other)`
|
||||||
|
|
||||||
|
===== Arguments
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `other` | MetaData | a MetaData object
|
||||||
|
|===
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `same` | `{type-bool}` | whether `self` has the same key-value pairs as `other`
|
||||||
|
|===
|
||||||
|
|
||||||
|
==== `:to_table()`
|
||||||
|
|
||||||
|
Converts the metadata to a Lua table representation.
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `nil` or `{type-table}` | Either:
|
||||||
|
* `nil` if the metadata is invalid (?), or
|
||||||
|
* `{type-table}`: A table representation of the metadata with the following fields:
|
||||||
|
** `fields`: Table `{[key] = value, ...}`
|
||||||
|
** Additional fields depending on the subclass
|
||||||
|
|===
|
||||||
|
|
||||||
|
TIP: Use `table = assert(meta:to_table())` to error if the operation failed.
|
||||||
|
|
||||||
|
==== `:from_table(table)`
|
||||||
|
|
||||||
|
Sets the key-value pairs to match those of a given table representation or clears the metadata.
|
||||||
|
|
||||||
|
===== Arguments
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `table` | `{type-table}` or any other type | Either:
|
||||||
|
* The table representation as produced by `:to_table()`, or
|
||||||
|
* Any non-table value: Clears the metadata
|
||||||
|
|===
|
||||||
|
|
||||||
|
===== Returns
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `value` | `{type-bool}` | whether loading the table representation succeeded
|
||||||
|
|===
|
||||||
|
|
||||||
|
TIP: Use `assert(meta:from_table(table))` to error if the operation failed.
|
68
doc/classes/ModStorage.adoc
Normal file
68
doc/classes/ModStorage.adoc
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
= ModStorage
|
||||||
|
|
||||||
|
include::../include/config.adoc[]
|
||||||
|
include::../include/types.adoc[]
|
||||||
|
:description: Per-mod persistent key-value store
|
||||||
|
:keywords: meta, data, metadata, mod, storage, key, value, persistence
|
||||||
|
|
||||||
|
ModStorage is a per-world, per-mod persistent string key-value store implementing all methods of MetaData.
|
||||||
|
|
||||||
|
The granularity of the persisted snapshots is determined by the `map_save_interval` setting.
|
||||||
|
|
||||||
|
== Backends
|
||||||
|
|
||||||
|
Two backends are available for ModStorage: JSON and SQLite3.
|
||||||
|
|
||||||
|
WARNING: The JSON backend is incapable of saving raw binary data due to JSON restrictions.
|
||||||
|
Even though the SQLite3 backend supports arbitrary bytestrings,
|
||||||
|
you may not rely on saving arbitrary bytestrings to work,
|
||||||
|
since you can't ensure that the SQLite3 backend is being used.
|
||||||
|
|
||||||
|
If the SQLite3 backend is used, it is usually more efficient to leverage the key-value store
|
||||||
|
than to store fully serialized data structures; fully serializing the data takes linear time
|
||||||
|
in the size of the data whereas updating the key-value store only takes linear time
|
||||||
|
in the size of the changes with the SQLite3 backend;
|
||||||
|
for the JSON backend it is irrelevant -
|
||||||
|
it has to fully serialize the data every map save interval
|
||||||
|
anyways, increasing the risk of data loss if writing the file fails
|
||||||
|
due to a hard crash (or freeze) of the Minetest server process.
|
||||||
|
|
||||||
|
== `minetest.get_mod_storage()`
|
||||||
|
|
||||||
|
Must be called at load time.
|
||||||
|
|
||||||
|
=== Returns
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `storage` | ModStorage | Private ModStorage object for the currently loading mod
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== Example
|
||||||
|
|
||||||
|
A basic greeting mod with a persistent greeting might look as follows:
|
||||||
|
|
||||||
|
[source,lua]
|
||||||
|
----
|
||||||
|
local storage = minetest.get_mod_storage()
|
||||||
|
|
||||||
|
-- Send the greeting to joining players
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
local greeting = storage:get"greeting"
|
||||||
|
if greeting then
|
||||||
|
minetest.chat_send_player(player:get_player_name(), greeting)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Allow moderators to change the greeting
|
||||||
|
minetest.register_chatcommand("/set_greeting", {
|
||||||
|
params = "<greeting>",
|
||||||
|
description = "Sets the greeting",
|
||||||
|
privs = {server = true},
|
||||||
|
func = function(name, param)
|
||||||
|
param = param:trim() -- MT-provided string.trim
|
||||||
|
storage:set_string("greeting", param)
|
||||||
|
return true, param == "" and "Greeting cleared." or "Greeting set."
|
||||||
|
end
|
||||||
|
})
|
||||||
|
----
|
144
doc/classes/NodeMetaData.adoc
Normal file
144
doc/classes/NodeMetaData.adoc
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
= NodeMetaData
|
||||||
|
|
||||||
|
include::../include/config.adoc[]
|
||||||
|
include::../include/types.adoc[]
|
||||||
|
:description: Per-node persistent key-value store
|
||||||
|
:keywords: meta, data, metadata, node, storage, key, value, persistence
|
||||||
|
|
||||||
|
Node storage in Minetest is usually limited to
|
||||||
|
|
||||||
|
* A content ID (determining the node name),
|
||||||
|
* The `param1` unsigned byte (`0` - `255` both inclusive) which is usually reserved for lighting,
|
||||||
|
* The `param2` unsigned byte (`0` - `255` both inclusive) which can be used depending on `paramtype2`
|
||||||
|
|
||||||
|
NodeMetaData allows extending this with a per-world, per-in-world-node
|
||||||
|
persistent string key-value store implementing all methods of MetaData
|
||||||
|
allowing you to associate arbitrary data with any node.
|
||||||
|
|
||||||
|
Additionally, node metadata allows storing inventories for nodes like chests or furnaces.
|
||||||
|
|
||||||
|
== `minetest.get_meta(pos)`
|
||||||
|
|
||||||
|
Obtains a mutable NodeMetaData reference for the node at `pos`.
|
||||||
|
|
||||||
|
=== Arguments
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `pos` | Vector | Node position on the map; floats are rounded appropriately.
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== Returns
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `meta` | NodeMetaData | Corresponding NodeMetaData reference
|
||||||
|
|===
|
||||||
|
|
||||||
|
== `minetest.find_nodes_with_meta(pos1, pos2)`
|
||||||
|
|
||||||
|
Searches a region for nodes with non-empty metadata.
|
||||||
|
|
||||||
|
=== Arguments
|
||||||
|
|
||||||
|
Cuboid corners are rounded properly if they are not integers.
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `pos1` | Vector | First corner of the cuboid region (inclusive)
|
||||||
|
| `pos2` | Vector | Second corner of the cuboid region (inclusive)
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== Returns
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `positions` | List of Vector | List of integer positions of nodes that have non-empty meta
|
||||||
|
|===
|
||||||
|
|
||||||
|
== Special Fields
|
||||||
|
|
||||||
|
=== `formspec`
|
||||||
|
|
||||||
|
FormSpec to show when the node is interacted with using the "place/use" key (rightclick by default).
|
||||||
|
|
||||||
|
Has no effect if `on_rightclick` is defined in the node definition (see `minetest.register_node`).
|
||||||
|
|
||||||
|
The most notable advantage of this over calling
|
||||||
|
`minetest.show_formspec` in `on_rightclick` is clientside prediction:
|
||||||
|
|
||||||
|
The client can immediately show the FormSpec; the second approach requires the client to first inform
|
||||||
|
the server of the interaction, to which the server then responds with the FormSpec.
|
||||||
|
This takes one round-trip time (RTT).
|
||||||
|
|
||||||
|
The obvious disadvantage is that FormSpecs can't be dynamically generated in response to user interaction;
|
||||||
|
formspecs must be mostly static. To alleviate this, formspecs provide context-dependant placeholders
|
||||||
|
like the `context` or `current_player` inventory locations (see FormSpec).
|
||||||
|
|
||||||
|
IMPORTANT: The `context` inventory location can only be used in FormSpecs using the special `formspec` NodeMetaData field.
|
||||||
|
FormSpecs shown using `minetest.show_formspec` must use `nodemeta:<X>,<Y>,<Z>` to reference inventories instead.
|
||||||
|
|
||||||
|
Another disadvantage is that plenty of redundant metadata - often a constant FormSpec - has to be stored with every node.
|
||||||
|
This metadata also has to be sent to clients. Minetest's mapblock compression should be able to compress duplicate substrings -
|
||||||
|
FormSpecs in this case - reasonably well though.
|
||||||
|
|
||||||
|
In terms of network traffic it depends: With meta, the FormSpec is "only" sent when the mapblock gets updated;
|
||||||
|
whereas the other approach resends the FormSpec every time the user interacts with the node.
|
||||||
|
|
||||||
|
=== `infotext`
|
||||||
|
|
||||||
|
Text to show when the node is pointed at (same as the `infotext` object property).
|
||||||
|
|
||||||
|
Long texts are line-wrapped, even longer texts are truncated.
|
||||||
|
|
||||||
|
== Methods
|
||||||
|
|
||||||
|
=== `:mark_as_private(keys)`
|
||||||
|
|
||||||
|
NodeMetaData is by default fully sent to clients;
|
||||||
|
the special `formspec` and `infotext` fields triggering clientside behavior
|
||||||
|
obviously need to be sent to clients to work.
|
||||||
|
|
||||||
|
All other fields do not need to be sent to clients
|
||||||
|
unless you want to explicitly support local mapsaving.
|
||||||
|
|
||||||
|
TIP: Mark all other fields as private to reduce traffic.
|
||||||
|
|
||||||
|
If you don't want clients to be able to see private NodeMetaData fields -
|
||||||
|
usually to prevent cheating - you must mark them as private.
|
||||||
|
|
||||||
|
NOTE: The private marking is tied to a key-value pair.
|
||||||
|
If the key-value pair is deleted, the private marking is deleted as well.
|
||||||
|
If the key-value pair is recreated, the private marking must be recreated as well.
|
||||||
|
|
||||||
|
NOTE: `to_table` and `from_table` do not keep track of which fields were marked as private.
|
||||||
|
|
||||||
|
==== Arguments
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `keys` | `{type-string}` or list of `{type-string}` | Either:
|
||||||
|
* A single key to mark as private, or
|
||||||
|
* A list of keys to mark as private
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== `:get_inventory()`
|
||||||
|
|
||||||
|
==== Returns
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `inv` | Inventory | The inventory associated with the node
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== `:to_table()`
|
||||||
|
|
||||||
|
Extends MetaData `:to_table()` by additionally adding an `inventory` field for
|
||||||
|
a table `{[listname] = list}` where `list` is a list of ItemStrings
|
||||||
|
(`""` for empty) with the same length as the size of the inventory list.
|
||||||
|
|
||||||
|
TIP: Use `table = assert(meta:to_table())` to error if the operation failed.
|
||||||
|
|
||||||
|
==== `:from_table(table)`
|
||||||
|
|
||||||
|
Extends MetaData `:from_table(table)` to add support for the `inventory` field.
|
44
doc/classes/PlayerMetaData.adoc
Normal file
44
doc/classes/PlayerMetaData.adoc
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
= PlayerMetaData
|
||||||
|
|
||||||
|
include::../include/config.adoc[]
|
||||||
|
include::../include/types.adoc[]
|
||||||
|
:description: Per-player persistent key-value store
|
||||||
|
:keywords: meta, data, metadata, player, storage, key, value, persistence
|
||||||
|
|
||||||
|
PlayerMetaData is a per-world, per-player persistent string key-value store implementing all methods of MetaData.
|
||||||
|
|
||||||
|
The granularity of the persisted snapshots is determined by the `map_save_interval` setting.
|
||||||
|
|
||||||
|
NOTE: Since PlayerMetaData is shared across all mods,
|
||||||
|
it is considered good practice to prefix the keys set by your mod with your mod name plus a delimiter
|
||||||
|
such as `:` to avoid collisions: The `score` field of a quest mod and a mobs mod f.E. might
|
||||||
|
be called `fancy_quests:score` and `fancy_mobs:score` respectively.
|
||||||
|
|
||||||
|
== `player:get_meta()`
|
||||||
|
|
||||||
|
Used to obtain a mutable PlayerMetaData reference.
|
||||||
|
|
||||||
|
=== Arguments
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `player` | A valid Player object
|
||||||
|
|===
|
||||||
|
|
||||||
|
NOTE: Minetest requiring a valid `player` object means PlayerMetaData is only accessible
|
||||||
|
while players are online; if you need per-player storage while players are offline,
|
||||||
|
you can use ModStorage and save either a serialized table per-player or concatenate
|
||||||
|
the keys of the per-player entries with the playername using a delimiter.
|
||||||
|
Reusing the above example, `fancy_quests:score` might be stored as `<playername>:score`
|
||||||
|
or as key-value pair with key `<playername>` and value `minetest.write_json{score = ...}`
|
||||||
|
(or `minetest.serialize`) in ModStorage.
|
||||||
|
|
||||||
|
A https://github.com/minetest/minetest/issues/6193[feature request]
|
||||||
|
to make PlayerMetaData available for offline players exists;
|
||||||
|
|
||||||
|
=== Returns
|
||||||
|
|
||||||
|
[%autowidth, frame=none]
|
||||||
|
|===
|
||||||
|
| `meta` | PlayerMetaData | Public & shared PlayerMetaData object for the player
|
||||||
|
|===
|
Loading…
Reference in New Issue
Block a user