from_table: Fix crash for missing inventory or field

master
SmallJoker 2017-01-02 15:17:28 +01:00 committed by sapier
parent 814ee971f7
commit 79d752ba4f
2 changed files with 29 additions and 20 deletions

View File

@ -2781,8 +2781,9 @@ Can be gotten via `minetest.get_meta(pos)`.
* `get_inventory()`: returns `InvRef` * `get_inventory()`: returns `InvRef`
* `to_table()`: returns `nil` or `{fields = {...}, inventory = {list1 = {}, ...}}` * `to_table()`: returns `nil` or `{fields = {...}, inventory = {list1 = {}, ...}}`
* `from_table(nil or {})` * `from_table(nil or {})`
* to clear metadata, use from_table(nil) * Any non-table value will clear the metadata
* See "Node Metadata" * See "Node Metadata"
* returns `true` on success
### `NodeTimerRef` ### `NodeTimerRef`
Node Timers: a high resolution persistent per-node timer. Node Timers: a high resolution persistent per-node timer.

View File

@ -250,7 +250,7 @@ int NodeMetaRef::l_from_table(lua_State *L)
// clear old metadata first // clear old metadata first
ref->m_env->getMap().removeNodeMetadata(ref->m_p); ref->m_env->getMap().removeNodeMetadata(ref->m_p);
if(lua_isnil(L, base)){ if (!lua_istable(L, base)) {
// No metadata // No metadata
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;
@ -258,34 +258,42 @@ int NodeMetaRef::l_from_table(lua_State *L)
// Create new metadata // Create new metadata
NodeMetadata *meta = getmeta(ref, true); NodeMetadata *meta = getmeta(ref, true);
if(meta == NULL){ if (meta == NULL) {
lua_pushboolean(L, false); lua_pushboolean(L, false);
return 1; return 1;
} }
// Set fields // Set fields
lua_getfield(L, base, "fields"); lua_getfield(L, base, "fields");
if (lua_istable(L, -1)) {
int fieldstable = lua_gettop(L); int fieldstable = lua_gettop(L);
lua_pushnil(L); lua_pushnil(L);
while(lua_next(L, fieldstable) != 0){ while (lua_next(L, fieldstable) != 0) {
// key at index -2 and value at index -1 // key at index -2 and value at index -1
std::string name = lua_tostring(L, -2); std::string name = lua_tostring(L, -2);
size_t cl; size_t cl;
const char *cs = lua_tolstring(L, -1, &cl); const char *cs = lua_tolstring(L, -1, &cl);
std::string value(cs, cl); meta->setString(name, std::string(cs, cl));
meta->setString(name, value); lua_pop(L, 1); // Remove value, keep key for next iteration
lua_pop(L, 1); // removes value, keeps key for next iteration
} }
lua_pop(L, 1);
}
// Set inventory // Set inventory
Inventory *inv = meta->getInventory(); Inventory *inv = meta->getInventory();
lua_getfield(L, base, "inventory"); lua_getfield(L, base, "inventory");
if (lua_istable(L, -1)) {
int inventorytable = lua_gettop(L); int inventorytable = lua_gettop(L);
lua_pushnil(L); lua_pushnil(L);
while(lua_next(L, inventorytable) != 0){ while (lua_next(L, inventorytable) != 0) {
// key at index -2 and value at index -1 // key at index -2 and value at index -1
std::string name = lua_tostring(L, -2); std::string name = lua_tostring(L, -2);
read_inventory_list(L, -1, inv, name.c_str(), getServer(L)); read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
lua_pop(L, 1); // removes value, keeps key for next iteration lua_pop(L, 1); // Remove value, keep key for next iteration
} }
lua_pop(L, 1);
}
reportMetadataChange(ref); reportMetadataChange(ref);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;