NodeMetaRef:{to,from}_table and lua_api.txt additions
parent
5f3c70061d
commit
3899f83da8
|
@ -278,6 +278,8 @@ param2 is reserved for the engine when any of these are used:
|
|||
^ The rotation of the node is stored in param2. Furnaces and chests are
|
||||
rotated this way. Can be made by using minetest.dir_to_facedir().
|
||||
|
||||
Nodes can also contain extra data. See "Node Metadata".
|
||||
|
||||
Representations of simple things
|
||||
--------------------------------
|
||||
Position/vector:
|
||||
|
@ -548,6 +550,91 @@ time_from_last_punch, tool_capabilities, direction)''.
|
|||
* If ''direction'' is nil and ''puncher'' is not nil, ''direction'' will be
|
||||
automatically filled in based on the location of ''puncher''.
|
||||
|
||||
Node Metadata
|
||||
-------------
|
||||
The instance of a node in the world normally only contains the three values
|
||||
mentioned in "Nodes". However, it is possible to insert extra data into a
|
||||
node. It is called "node metadata"; See "NodeMetaRef".
|
||||
|
||||
Metadata contains two things:
|
||||
- A key-value store
|
||||
- An inventory
|
||||
|
||||
Some of the values in the key-value store are handled specially:
|
||||
- formspec: Defines a right-click inventory menu. See "Formspec".
|
||||
- infotext: Text shown on the screen when the node is pointed at
|
||||
|
||||
Example stuff:
|
||||
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
meta:set_string("formspec",
|
||||
"invsize[8,9;]"..
|
||||
"list[current_name;main;0,0;8,4;]"..
|
||||
"list[current_player;main;0,5;8,4;]")
|
||||
meta:set_string("infotext", "Chest");
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 8*4)
|
||||
print(dump(meta:to_table()))
|
||||
meta:from_table({
|
||||
inventory = {
|
||||
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", [5] = "", [6] = "", [7] = "", [8] = "", [9] = "", [10] = "", [11] = "", [12] = "", [13] = "", [14] = "default:cobble", [15] = "", [16] = "", [17] = "", [18] = "", [19] = "", [20] = "default:cobble", [21] = "", [22] = "", [23] = "", [24] = "", [25] = "", [26] = "", [27] = "", [28] = "", [29] = "", [30] = "", [31] = "", [32] = ""}
|
||||
},
|
||||
fields = {
|
||||
formspec = "invsize[8,9;]list[current_name;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
|
||||
infotext = "Chest"
|
||||
}
|
||||
})
|
||||
|
||||
Formspec
|
||||
--------
|
||||
Formspec defines a menu. Currently not much else than inventories are
|
||||
supported. It is a string, with a somewhat strange format.
|
||||
|
||||
Spaces and newlines can be inserted between the blocks, as is used in the
|
||||
examples.
|
||||
|
||||
Examples:
|
||||
- Chest:
|
||||
invsize[8,9;]
|
||||
list[current_name;main;0,0;8,4;]
|
||||
list[current_player;main;0,5;8,4;]
|
||||
- Furnace:
|
||||
invsize[8,9;]
|
||||
list[current_name;fuel;2,3;1,1;]
|
||||
list[current_name;src;2,1;1,1;]
|
||||
list[current_name;dst;5,1;2,2;]
|
||||
list[current_player;main;0,5;8,4;]
|
||||
|
||||
Elements:
|
||||
|
||||
invsize[<W>,<H>;]
|
||||
^ Define the size of the menu in inventory slots
|
||||
|
||||
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
|
||||
^ Show an inventory list
|
||||
|
||||
image[<X>,<Y>;<W>,<H>;<texture name>]
|
||||
^ Show an image
|
||||
^ Position and size units are inventory slots
|
||||
^ Not implemented
|
||||
|
||||
field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
|
||||
^ Textual field; will be sent to server when a button is clicked
|
||||
^ Position and size units are inventory slots
|
||||
^ Not implemented
|
||||
|
||||
button[<X>,<Y>;<W>,<H>;<name>;<label>]
|
||||
^ Clickable button. When clicked, fields will be sent.
|
||||
^ Button will be visible as a field, with the value "active".
|
||||
^ Position and size units are inventory slots
|
||||
^ Not implemented
|
||||
|
||||
Inventory location:
|
||||
- "current_name": Selected node metadata
|
||||
- "current_player": Player to whom the menu is shown
|
||||
- "player:<name>": Any player
|
||||
- "nodemeta:<X>,<Y>,<Z>": Any node metadata
|
||||
|
||||
Helper functions
|
||||
-----------------
|
||||
dump2(obj, name="_", dumped={})
|
||||
|
@ -766,7 +853,9 @@ Deprecated:
|
|||
- add_rat(pos): Add C++ rat object (no-op)
|
||||
- add_firefly(pos): Add C++ firefly object (no-op)
|
||||
|
||||
NodeMetaRef (this stuff is subject to change in a future version)
|
||||
NodeMetaRef: Node metadata - reference extra data and functionality stored
|
||||
in a node
|
||||
- Can be gotten via minetest.env:get_nodemeta(pos)
|
||||
methods:
|
||||
- set_string(name, value)
|
||||
- get_string(name)
|
||||
|
@ -775,6 +864,9 @@ methods:
|
|||
- set_float(name, value)
|
||||
- get_float(name)
|
||||
- get_inventory() -> InvRef
|
||||
- to_table() -> nil or {fields = {...}, inventory = {list1 = {}, ...}}
|
||||
- from_table(nil or {})
|
||||
^ See "Node Metadata"
|
||||
|
||||
ObjectRef: Moving things in the game are generally these
|
||||
(basically reference to a C++ ServerActiveObject)
|
||||
|
|
|
@ -915,6 +915,17 @@ InventoryList * Inventory::getList(const std::string &name)
|
|||
return m_lists[i];
|
||||
}
|
||||
|
||||
std::vector<const InventoryList*> Inventory::getLists()
|
||||
{
|
||||
std::vector<const InventoryList*> lists;
|
||||
for(u32 i=0; i<m_lists.size(); i++)
|
||||
{
|
||||
InventoryList *list = m_lists[i];
|
||||
lists.push_back(list);
|
||||
}
|
||||
return lists;
|
||||
}
|
||||
|
||||
bool Inventory::deleteList(const std::string &name)
|
||||
{
|
||||
s32 i = getListIndex(name);
|
||||
|
|
|
@ -262,6 +262,7 @@ public:
|
|||
InventoryList * addList(const std::string &name, u32 size);
|
||||
InventoryList * getList(const std::string &name);
|
||||
const InventoryList * getList(const std::string &name) const;
|
||||
std::vector<const InventoryList*> getLists();
|
||||
bool deleteList(const std::string &name);
|
||||
// A shorthand for adding items. Returns leftover item (possibly empty).
|
||||
ItemStack addItem(const std::string &listname, const ItemStack &newitem)
|
||||
|
|
12
src/map.cpp
12
src/map.cpp
|
@ -1009,6 +1009,12 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||
n.setLight(LIGHTBANK_DAY, LIGHT_SUN, nodemgr);
|
||||
}
|
||||
|
||||
/*
|
||||
Remove node metadata
|
||||
*/
|
||||
|
||||
removeNodeMetadata(p);
|
||||
|
||||
/*
|
||||
Set the node on the map
|
||||
*/
|
||||
|
@ -3451,15 +3457,15 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
|||
}
|
||||
catch(InvalidFilenameException &e)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
catch(FileNotGoodException &e)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,10 @@ public:
|
|||
else
|
||||
m_stringvars[name] = var;
|
||||
}
|
||||
std::map<std::string, std::string> getStrings() const
|
||||
{
|
||||
return m_stringvars;
|
||||
}
|
||||
|
||||
// The inventory
|
||||
Inventory* getInventory()
|
||||
|
|
|
@ -1233,6 +1233,8 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
|||
if(lua_pcall(L, 2, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
lua_remove(L, -2); // Remove table
|
||||
lua_remove(L, -2); // Remove insert
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2087,98 +2089,91 @@ private:
|
|||
InvRef::createNodeMeta(L, ref->m_p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_inventory_draw_spec(self)
|
||||
static int l_get_inventory_draw_spec(lua_State *L)
|
||||
|
||||
// to_table(self)
|
||||
static int l_to_table(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
|
||||
NodeMetadata *meta = getmeta(ref, false);
|
||||
NodeMetadata *meta = getmeta(ref, true);
|
||||
if(meta == NULL){
|
||||
lua_pushlstring(L, "", 0);
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
std::string str = meta->getString("formspec");
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
lua_newtable(L);
|
||||
// fields
|
||||
lua_newtable(L);
|
||||
{
|
||||
std::map<std::string, std::string> fields = meta->getStrings();
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = fields.begin(); i != fields.end(); i++){
|
||||
const std::string &name = i->first;
|
||||
const std::string &value = i->second;
|
||||
lua_pushlstring(L, name.c_str(), name.size());
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
lua_setfield(L, -2, "fields");
|
||||
// inventory
|
||||
lua_newtable(L);
|
||||
Inventory *inv = meta->getInventory();
|
||||
if(inv){
|
||||
std::vector<const InventoryList*> lists = inv->getLists();
|
||||
for(std::vector<const InventoryList*>::const_iterator
|
||||
i = lists.begin(); i != lists.end(); i++){
|
||||
inventory_get_list_to_lua(inv, (*i)->getName().c_str(), L);
|
||||
lua_setfield(L, -2, (*i)->getName().c_str());
|
||||
}
|
||||
}
|
||||
lua_setfield(L, -2, "inventory");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_inventory_draw_spec(self, text)
|
||||
static int l_set_inventory_draw_spec(lua_State *L)
|
||||
// from_table(self, table)
|
||||
static int l_from_table(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
size_t len = 0;
|
||||
const char *s = lua_tolstring(L, 2, &len);
|
||||
std::string str(s, len);
|
||||
|
||||
NodeMetadata *meta = getmeta(ref, !str.empty());
|
||||
if(meta == NULL || str == meta->getString("formspec"))
|
||||
return 0;
|
||||
meta->setString("formspec",str);
|
||||
reportMetadataChange(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_form_spec(self)
|
||||
static int l_get_form_spec(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
|
||||
NodeMetadata *meta = getmeta(ref, false);
|
||||
if(meta == NULL){
|
||||
lua_pushlstring(L, "", 0);
|
||||
int base = 2;
|
||||
|
||||
if(lua_isnil(L, base)){
|
||||
// No metadata
|
||||
ref->m_env->getMap().removeNodeMetadata(ref->m_p);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
std::string str = meta->getString("formspec");
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_form_spec(self, text)
|
||||
static int l_set_form_spec(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
size_t len = 0;
|
||||
const char *s = lua_tolstring(L, 2, &len);
|
||||
std::string str(s, len);
|
||||
|
||||
NodeMetadata *meta = getmeta(ref, !str.empty());
|
||||
if(meta == NULL || str == meta->getString("formspec"))
|
||||
return 0;
|
||||
meta->setString("formspec",str);
|
||||
reportMetadataChange(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_infotext(self)
|
||||
static int l_get_infotext(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
|
||||
NodeMetadata *meta = getmeta(ref, false);
|
||||
if(meta == NULL){
|
||||
lua_pushlstring(L, "", 0);
|
||||
return 1;
|
||||
// Has metadata; clear old one first
|
||||
ref->m_env->getMap().removeNodeMetadata(ref->m_p);
|
||||
// Create new metadata
|
||||
NodeMetadata *meta = getmeta(ref, true);
|
||||
// Set fields
|
||||
lua_getfield(L, base, "fields");
|
||||
int fieldstable = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, fieldstable) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
std::string name = lua_tostring(L, -2);
|
||||
size_t cl;
|
||||
const char *cs = lua_tolstring(L, -1, &cl);
|
||||
std::string value(cs, cl);
|
||||
meta->setString(name, value);
|
||||
lua_pop(L, 1); // removes value, keeps key for next iteration
|
||||
}
|
||||
// Set inventory
|
||||
Inventory *inv = meta->getInventory();
|
||||
lua_getfield(L, base, "inventory");
|
||||
int inventorytable = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, inventorytable) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
std::string name = lua_tostring(L, -2);
|
||||
inventory_set_list_from_lua(inv, name.c_str(), L, -1);
|
||||
lua_pop(L, 1); // removes value, keeps key for next iteration
|
||||
}
|
||||
std::string str = meta->getString("infotext");
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_infotext(self, text)
|
||||
static int l_set_infotext(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
size_t len = 0;
|
||||
const char *s = lua_tolstring(L, 2, &len);
|
||||
std::string str(s, len);
|
||||
|
||||
NodeMetadata *meta = getmeta(ref, !str.empty());
|
||||
if(meta == NULL || str == meta->getString("infotext"))
|
||||
return 0;
|
||||
meta->setString("infotext",str);
|
||||
reportMetadataChange(ref);
|
||||
return 0;
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -2240,12 +2235,8 @@ const luaL_reg NodeMetaRef::methods[] = {
|
|||
method(NodeMetaRef, get_float),
|
||||
method(NodeMetaRef, set_float),
|
||||
method(NodeMetaRef, get_inventory),
|
||||
method(NodeMetaRef, get_inventory_draw_spec),
|
||||
method(NodeMetaRef, set_inventory_draw_spec),
|
||||
method(NodeMetaRef, get_form_spec),
|
||||
method(NodeMetaRef, set_form_spec),
|
||||
method(NodeMetaRef, get_infotext),
|
||||
method(NodeMetaRef, set_infotext),
|
||||
method(NodeMetaRef, to_table),
|
||||
method(NodeMetaRef, from_table),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue