aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSmallJoker <mk939@ymail.com>2017-01-02 15:17:28 +0100
committersapier <sapier at gmx dot net>2017-01-28 16:38:46 +0100
commit79d752ba4f6f0197627cc20f99b2540f63b6dc88 (patch)
tree7f73a72e0c777f25552f6e572797b9c9f9d38472
parent814ee971f70a8ef1fa4a470bcf385300686e9e70 (diff)
downloadminetest-79d752ba4f6f0197627cc20f99b2540f63b6dc88.tar.gz
minetest-79d752ba4f6f0197627cc20f99b2540f63b6dc88.tar.bz2
minetest-79d752ba4f6f0197627cc20f99b2540f63b6dc88.zip
from_table: Fix crash for missing inventory or field
-rw-r--r--doc/lua_api.txt3
-rw-r--r--src/script/lua_api/l_nodemeta.cpp46
2 files changed, 29 insertions, 20 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index ff745c1c2..9a1cb6bac 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -2781,8 +2781,9 @@ Can be gotten via `minetest.get_meta(pos)`.
* `get_inventory()`: returns `InvRef`
* `to_table()`: returns `nil` or `{fields = {...}, inventory = {list1 = {}, ...}}`
* `from_table(nil or {})`
- * to clear metadata, use from_table(nil)
+ * Any non-table value will clear the metadata
* See "Node Metadata"
+ * returns `true` on success
### `NodeTimerRef`
Node Timers: a high resolution persistent per-node timer.
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index 3d03c0c41..631aa68ce 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -250,7 +250,7 @@ int NodeMetaRef::l_from_table(lua_State *L)
// clear old metadata first
ref->m_env->getMap().removeNodeMetadata(ref->m_p);
- if(lua_isnil(L, base)){
+ if (!lua_istable(L, base)) {
// No metadata
lua_pushboolean(L, true);
return 1;
@@ -258,34 +258,42 @@ int NodeMetaRef::l_from_table(lua_State *L)
// Create new metadata
NodeMetadata *meta = getmeta(ref, true);
- if(meta == NULL){
+ if (meta == NULL) {
lua_pushboolean(L, false);
return 1;
}
+
// 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
+ if (lua_istable(L, -1)) {
+ 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);
+ meta->setString(name, std::string(cs, cl));
+ lua_pop(L, 1); // Remove value, keep key for next iteration
+ }
+ lua_pop(L, 1);
}
+
// 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);
- read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
- lua_pop(L, 1); // removes value, keeps key for next iteration
+ if (lua_istable(L, -1)) {
+ 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);
+ read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
+ lua_pop(L, 1); // Remove value, keep key for next iteration
+ }
+ lua_pop(L, 1);
}
+
reportMetadataChange(ref);
lua_pushboolean(L, true);
return 1;