]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/common/c_content.cpp
Pass ContentFeatures as reference to read_content_features (#10464)
[dragonfireclient.git] / src / script / common / c_content.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 #include "common/c_content.h"
20 #include "common/c_converter.h"
21 #include "common/c_types.h"
22 #include "nodedef.h"
23 #include "object_properties.h"
24 #include "collision.h"
25 #include "cpp_api/s_node.h"
26 #include "lua_api/l_object.h"
27 #include "lua_api/l_item.h"
28 #include "common/c_internal.h"
29 #include "server.h"
30 #include "log.h"
31 #include "tool.h"
32 #include "porting.h"
33 #include "mapgen/mg_schematic.h"
34 #include "noise.h"
35 #include "server/player_sao.h"
36 #include "util/pointedthing.h"
37 #include "debug.h" // For FATAL_ERROR
38 #include <json/json.h>
39
40 struct EnumString es_TileAnimationType[] =
41 {
42         {TAT_NONE, "none"},
43         {TAT_VERTICAL_FRAMES, "vertical_frames"},
44         {TAT_SHEET_2D, "sheet_2d"},
45         {0, NULL},
46 };
47
48 /******************************************************************************/
49 void read_item_definition(lua_State* L, int index,
50                 const ItemDefinition &default_def, ItemDefinition &def)
51 {
52         if (index < 0)
53                 index = lua_gettop(L) + 1 + index;
54
55         def.type = (ItemType)getenumfield(L, index, "type",
56                         es_ItemType, ITEM_NONE);
57         getstringfield(L, index, "name", def.name);
58         getstringfield(L, index, "description", def.description);
59         getstringfield(L, index, "short_description", def.short_description);
60         getstringfield(L, index, "inventory_image", def.inventory_image);
61         getstringfield(L, index, "inventory_overlay", def.inventory_overlay);
62         getstringfield(L, index, "wield_image", def.wield_image);
63         getstringfield(L, index, "wield_overlay", def.wield_overlay);
64         getstringfield(L, index, "palette", def.palette_image);
65
66         // Read item color.
67         lua_getfield(L, index, "color");
68         read_color(L, -1, &def.color);
69         lua_pop(L, 1);
70
71         lua_getfield(L, index, "wield_scale");
72         if(lua_istable(L, -1)){
73                 def.wield_scale = check_v3f(L, -1);
74         }
75         lua_pop(L, 1);
76
77         int stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
78         def.stack_max = rangelim(stack_max, 1, U16_MAX);
79
80         lua_getfield(L, index, "on_use");
81         def.usable = lua_isfunction(L, -1);
82         lua_pop(L, 1);
83
84         getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
85
86         warn_if_field_exists(L, index, "tool_digging_properties",
87                         "Obsolete; use tool_capabilities");
88
89         lua_getfield(L, index, "tool_capabilities");
90         if(lua_istable(L, -1)){
91                 def.tool_capabilities = new ToolCapabilities(
92                                 read_tool_capabilities(L, -1));
93         }
94
95         // If name is "" (hand), ensure there are ToolCapabilities
96         // because it will be looked up there whenever any other item has
97         // no ToolCapabilities
98         if (def.name.empty() && def.tool_capabilities == NULL){
99                 def.tool_capabilities = new ToolCapabilities();
100         }
101
102         lua_getfield(L, index, "groups");
103         read_groups(L, -1, def.groups);
104         lua_pop(L, 1);
105
106         lua_getfield(L, index, "sounds");
107         if (!lua_isnil(L, -1)) {
108                 luaL_checktype(L, -1, LUA_TTABLE);
109                 lua_getfield(L, -1, "place");
110                 read_soundspec(L, -1, def.sound_place);
111                 lua_pop(L, 1);
112                 lua_getfield(L, -1, "place_failed");
113                 read_soundspec(L, -1, def.sound_place_failed);
114                 lua_pop(L, 1);
115         }
116         lua_pop(L, 1);
117
118         def.range = getfloatfield_default(L, index, "range", def.range);
119
120         // Client shall immediately place this node when player places the item.
121         // Server will update the precise end result a moment later.
122         // "" = no prediction
123         getstringfield(L, index, "node_placement_prediction",
124                         def.node_placement_prediction);
125 }
126
127 /******************************************************************************/
128 void push_item_definition(lua_State *L, const ItemDefinition &i)
129 {
130         lua_newtable(L);
131         lua_pushstring(L, i.name.c_str());
132         lua_setfield(L, -2, "name");
133         lua_pushstring(L, i.description.c_str());
134         lua_setfield(L, -2, "description");
135 }
136
137 void push_item_definition_full(lua_State *L, const ItemDefinition &i)
138 {
139         std::string type(es_ItemType[(int)i.type].str);
140
141         lua_newtable(L);
142         lua_pushstring(L, i.name.c_str());
143         lua_setfield(L, -2, "name");
144         lua_pushstring(L, i.description.c_str());
145         lua_setfield(L, -2, "description");
146         lua_pushstring(L, i.short_description.c_str());
147         lua_setfield(L, -2, "short_description");
148         lua_pushstring(L, type.c_str());
149         lua_setfield(L, -2, "type");
150         lua_pushstring(L, i.inventory_image.c_str());
151         lua_setfield(L, -2, "inventory_image");
152         lua_pushstring(L, i.inventory_overlay.c_str());
153         lua_setfield(L, -2, "inventory_overlay");
154         lua_pushstring(L, i.wield_image.c_str());
155         lua_setfield(L, -2, "wield_image");
156         lua_pushstring(L, i.wield_overlay.c_str());
157         lua_setfield(L, -2, "wield_overlay");
158         lua_pushstring(L, i.palette_image.c_str());
159         lua_setfield(L, -2, "palette_image");
160         push_ARGB8(L, i.color);
161         lua_setfield(L, -2, "color");
162         push_v3f(L, i.wield_scale);
163         lua_setfield(L, -2, "wield_scale");
164         lua_pushinteger(L, i.stack_max);
165         lua_setfield(L, -2, "stack_max");
166         lua_pushboolean(L, i.usable);
167         lua_setfield(L, -2, "usable");
168         lua_pushboolean(L, i.liquids_pointable);
169         lua_setfield(L, -2, "liquids_pointable");
170         if (i.tool_capabilities) {
171                 push_tool_capabilities(L, *i.tool_capabilities);
172                 lua_setfield(L, -2, "tool_capabilities");
173         }
174         push_groups(L, i.groups);
175         lua_setfield(L, -2, "groups");
176         push_soundspec(L, i.sound_place);
177         lua_setfield(L, -2, "sound_place");
178         push_soundspec(L, i.sound_place_failed);
179         lua_setfield(L, -2, "sound_place_failed");
180         lua_pushstring(L, i.node_placement_prediction.c_str());
181         lua_setfield(L, -2, "node_placement_prediction");
182 }
183
184 /******************************************************************************/
185 void read_object_properties(lua_State *L, int index,
186                 ServerActiveObject *sao, ObjectProperties *prop, IItemDefManager *idef)
187 {
188         if(index < 0)
189                 index = lua_gettop(L) + 1 + index;
190         if (lua_isnil(L, index))
191                 return;
192
193         luaL_checktype(L, -1, LUA_TTABLE);
194
195         int hp_max = 0;
196         if (getintfield(L, -1, "hp_max", hp_max)) {
197                 prop->hp_max = (u16)rangelim(hp_max, 0, U16_MAX);
198
199                 if (prop->hp_max < sao->getHP()) {
200                         PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
201                         sao->setHP(prop->hp_max, reason);
202                         if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER)
203                                 sao->getEnv()->getGameDef()->SendPlayerHPOrDie((PlayerSAO *)sao, reason);
204                 }
205         }
206
207         if (getintfield(L, -1, "breath_max", prop->breath_max)) {
208                 if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
209                         PlayerSAO *player = (PlayerSAO *)sao;
210                         if (prop->breath_max < player->getBreath())
211                                 player->setBreath(prop->breath_max);
212                 }
213         }
214         getboolfield(L, -1, "physical", prop->physical);
215         getboolfield(L, -1, "collide_with_objects", prop->collideWithObjects);
216
217         lua_getfield(L, -1, "collisionbox");
218         bool collisionbox_defined = lua_istable(L, -1);
219         if (collisionbox_defined)
220                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
221         lua_pop(L, 1);
222
223         lua_getfield(L, -1, "selectionbox");
224         if (lua_istable(L, -1))
225                 prop->selectionbox = read_aabb3f(L, -1, 1.0);
226         else if (collisionbox_defined)
227                 prop->selectionbox = prop->collisionbox;
228         lua_pop(L, 1);
229
230         getboolfield(L, -1, "pointable", prop->pointable);
231         getstringfield(L, -1, "visual", prop->visual);
232
233         getstringfield(L, -1, "mesh", prop->mesh);
234
235         lua_getfield(L, -1, "visual_size");
236         if (lua_istable(L, -1)) {
237                 // Backwards compatibility: Also accept { x = ?, y = ? }
238                 v2f scale_xy = read_v2f(L, -1);
239
240                 f32 scale_z = scale_xy.X;
241                 lua_getfield(L, -1, "z");
242                 if (lua_isnumber(L, -1))
243                         scale_z = lua_tonumber(L, -1);
244                 lua_pop(L, 1);
245
246                 prop->visual_size = v3f(scale_xy.X, scale_xy.Y, scale_z);
247         }
248         lua_pop(L, 1);
249
250         lua_getfield(L, -1, "textures");
251         if(lua_istable(L, -1)){
252                 prop->textures.clear();
253                 int table = lua_gettop(L);
254                 lua_pushnil(L);
255                 while(lua_next(L, table) != 0){
256                         // key at index -2 and value at index -1
257                         if(lua_isstring(L, -1))
258                                 prop->textures.emplace_back(lua_tostring(L, -1));
259                         else
260                                 prop->textures.emplace_back("");
261                         // removes value, keeps key for next iteration
262                         lua_pop(L, 1);
263                 }
264         }
265         lua_pop(L, 1);
266
267         lua_getfield(L, -1, "colors");
268         if (lua_istable(L, -1)) {
269                 int table = lua_gettop(L);
270                 prop->colors.clear();
271                 for (lua_pushnil(L); lua_next(L, table); lua_pop(L, 1)) {
272                         video::SColor color(255, 255, 255, 255);
273                         read_color(L, -1, &color);
274                         prop->colors.push_back(color);
275                 }
276         }
277         lua_pop(L, 1);
278
279         lua_getfield(L, -1, "spritediv");
280         if(lua_istable(L, -1))
281                 prop->spritediv = read_v2s16(L, -1);
282         lua_pop(L, 1);
283
284         lua_getfield(L, -1, "initial_sprite_basepos");
285         if(lua_istable(L, -1))
286                 prop->initial_sprite_basepos = read_v2s16(L, -1);
287         lua_pop(L, 1);
288
289         getboolfield(L, -1, "is_visible", prop->is_visible);
290         getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
291         if (getfloatfield(L, -1, "stepheight", prop->stepheight))
292                 prop->stepheight *= BS;
293         getfloatfield(L, -1, "eye_height", prop->eye_height);
294
295         getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
296         lua_getfield(L, -1, "automatic_face_movement_dir");
297         if (lua_isnumber(L, -1)) {
298                 prop->automatic_face_movement_dir = true;
299                 prop->automatic_face_movement_dir_offset = luaL_checknumber(L, -1);
300         } else if (lua_isboolean(L, -1)) {
301                 prop->automatic_face_movement_dir = lua_toboolean(L, -1);
302                 prop->automatic_face_movement_dir_offset = 0.0;
303         }
304         lua_pop(L, 1);
305         getboolfield(L, -1, "backface_culling", prop->backface_culling);
306         getintfield(L, -1, "glow", prop->glow);
307
308         getstringfield(L, -1, "nametag", prop->nametag);
309         lua_getfield(L, -1, "nametag_color");
310         if (!lua_isnil(L, -1)) {
311                 video::SColor color = prop->nametag_color;
312                 if (read_color(L, -1, &color))
313                         prop->nametag_color = color;
314         }
315         lua_pop(L, 1);
316
317         lua_getfield(L, -1, "automatic_face_movement_max_rotation_per_sec");
318         if (lua_isnumber(L, -1)) {
319                 prop->automatic_face_movement_max_rotation_per_sec = luaL_checknumber(L, -1);
320         }
321         lua_pop(L, 1);
322
323         getstringfield(L, -1, "infotext", prop->infotext);
324         getboolfield(L, -1, "static_save", prop->static_save);
325
326         lua_getfield(L, -1, "wield_item");
327         if (!lua_isnil(L, -1))
328                 prop->wield_item = read_item(L, -1, idef).getItemString();
329         lua_pop(L, 1);
330
331         getfloatfield(L, -1, "zoom_fov", prop->zoom_fov);
332         getboolfield(L, -1, "use_texture_alpha", prop->use_texture_alpha);
333         getboolfield(L, -1, "shaded", prop->shaded);
334
335         getstringfield(L, -1, "damage_texture_modifier", prop->damage_texture_modifier);
336 }
337
338 /******************************************************************************/
339 void push_object_properties(lua_State *L, ObjectProperties *prop)
340 {
341         lua_newtable(L);
342         lua_pushnumber(L, prop->hp_max);
343         lua_setfield(L, -2, "hp_max");
344         lua_pushnumber(L, prop->breath_max);
345         lua_setfield(L, -2, "breath_max");
346         lua_pushboolean(L, prop->physical);
347         lua_setfield(L, -2, "physical");
348         lua_pushboolean(L, prop->collideWithObjects);
349         lua_setfield(L, -2, "collide_with_objects");
350         push_aabb3f(L, prop->collisionbox);
351         lua_setfield(L, -2, "collisionbox");
352         push_aabb3f(L, prop->selectionbox);
353         lua_setfield(L, -2, "selectionbox");
354         lua_pushboolean(L, prop->pointable);
355         lua_setfield(L, -2, "pointable");
356         lua_pushlstring(L, prop->visual.c_str(), prop->visual.size());
357         lua_setfield(L, -2, "visual");
358         lua_pushlstring(L, prop->mesh.c_str(), prop->mesh.size());
359         lua_setfield(L, -2, "mesh");
360         push_v3f(L, prop->visual_size);
361         lua_setfield(L, -2, "visual_size");
362
363         lua_createtable(L, prop->textures.size(), 0);
364         u16 i = 1;
365         for (const std::string &texture : prop->textures) {
366                 lua_pushlstring(L, texture.c_str(), texture.size());
367                 lua_rawseti(L, -2, i++);
368         }
369         lua_setfield(L, -2, "textures");
370
371         lua_createtable(L, prop->colors.size(), 0);
372         i = 1;
373         for (const video::SColor &color : prop->colors) {
374                 push_ARGB8(L, color);
375                 lua_rawseti(L, -2, i++);
376         }
377         lua_setfield(L, -2, "colors");
378
379         push_v2s16(L, prop->spritediv);
380         lua_setfield(L, -2, "spritediv");
381         push_v2s16(L, prop->initial_sprite_basepos);
382         lua_setfield(L, -2, "initial_sprite_basepos");
383         lua_pushboolean(L, prop->is_visible);
384         lua_setfield(L, -2, "is_visible");
385         lua_pushboolean(L, prop->makes_footstep_sound);
386         lua_setfield(L, -2, "makes_footstep_sound");
387         lua_pushnumber(L, prop->stepheight / BS);
388         lua_setfield(L, -2, "stepheight");
389         lua_pushnumber(L, prop->eye_height);
390         lua_setfield(L, -2, "eye_height");
391         lua_pushnumber(L, prop->automatic_rotate);
392         lua_setfield(L, -2, "automatic_rotate");
393         if (prop->automatic_face_movement_dir)
394                 lua_pushnumber(L, prop->automatic_face_movement_dir_offset);
395         else
396                 lua_pushboolean(L, false);
397         lua_setfield(L, -2, "automatic_face_movement_dir");
398         lua_pushboolean(L, prop->backface_culling);
399         lua_setfield(L, -2, "backface_culling");
400         lua_pushnumber(L, prop->glow);
401         lua_setfield(L, -2, "glow");
402         lua_pushlstring(L, prop->nametag.c_str(), prop->nametag.size());
403         lua_setfield(L, -2, "nametag");
404         push_ARGB8(L, prop->nametag_color);
405         lua_setfield(L, -2, "nametag_color");
406         lua_pushnumber(L, prop->automatic_face_movement_max_rotation_per_sec);
407         lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec");
408         lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size());
409         lua_setfield(L, -2, "infotext");
410         lua_pushboolean(L, prop->static_save);
411         lua_setfield(L, -2, "static_save");
412         lua_pushlstring(L, prop->wield_item.c_str(), prop->wield_item.size());
413         lua_setfield(L, -2, "wield_item");
414         lua_pushnumber(L, prop->zoom_fov);
415         lua_setfield(L, -2, "zoom_fov");
416         lua_pushboolean(L, prop->use_texture_alpha);
417         lua_setfield(L, -2, "use_texture_alpha");
418         lua_pushboolean(L, prop->shaded);
419         lua_setfield(L, -2, "shaded");
420         lua_pushlstring(L, prop->damage_texture_modifier.c_str(), prop->damage_texture_modifier.size());
421         lua_setfield(L, -2, "damage_texture_modifier");
422 }
423
424 /******************************************************************************/
425 TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
426 {
427         if(index < 0)
428                 index = lua_gettop(L) + 1 + index;
429
430         TileDef tiledef;
431
432         bool default_tiling = true;
433         bool default_culling = true;
434         switch (drawtype) {
435                 case NDT_PLANTLIKE:
436                 case NDT_PLANTLIKE_ROOTED:
437                 case NDT_FIRELIKE:
438                         default_tiling = false;
439                         // "break" is omitted here intentionaly, as PLANTLIKE
440                         // FIRELIKE drawtype both should default to having
441                         // backface_culling to false.
442                 case NDT_MESH:
443                 case NDT_LIQUID:
444                         default_culling = false;
445                         break;
446                 default:
447                         break;
448         }
449
450         // key at index -2 and value at index
451         if(lua_isstring(L, index)){
452                 // "default_lava.png"
453                 tiledef.name = lua_tostring(L, index);
454                 tiledef.tileable_vertical = default_tiling;
455                 tiledef.tileable_horizontal = default_tiling;
456                 tiledef.backface_culling = default_culling;
457         }
458         else if(lua_istable(L, index))
459         {
460                 // name="default_lava.png"
461                 tiledef.name = "";
462                 getstringfield(L, index, "name", tiledef.name);
463                 getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
464                 tiledef.backface_culling = getboolfield_default(
465                         L, index, "backface_culling", default_culling);
466                 tiledef.tileable_horizontal = getboolfield_default(
467                         L, index, "tileable_horizontal", default_tiling);
468                 tiledef.tileable_vertical = getboolfield_default(
469                         L, index, "tileable_vertical", default_tiling);
470                 std::string align_style;
471                 if (getstringfield(L, index, "align_style", align_style)) {
472                         if (align_style == "user")
473                                 tiledef.align_style = ALIGN_STYLE_USER_DEFINED;
474                         else if (align_style == "world")
475                                 tiledef.align_style = ALIGN_STYLE_WORLD;
476                         else
477                                 tiledef.align_style = ALIGN_STYLE_NODE;
478                 }
479                 tiledef.scale = getintfield_default(L, index, "scale", 0);
480                 // color = ...
481                 lua_getfield(L, index, "color");
482                 tiledef.has_color = read_color(L, -1, &tiledef.color);
483                 lua_pop(L, 1);
484                 // animation = {}
485                 lua_getfield(L, index, "animation");
486                 tiledef.animation = read_animation_definition(L, -1);
487                 lua_pop(L, 1);
488         }
489
490         return tiledef;
491 }
492
493 /******************************************************************************/
494 void read_content_features(lua_State *L, ContentFeatures &f, int index)
495 {
496         if(index < 0)
497                 index = lua_gettop(L) + 1 + index;
498
499         /* Cache existence of some callbacks */
500         lua_getfield(L, index, "on_construct");
501         if(!lua_isnil(L, -1)) f.has_on_construct = true;
502         lua_pop(L, 1);
503         lua_getfield(L, index, "on_destruct");
504         if(!lua_isnil(L, -1)) f.has_on_destruct = true;
505         lua_pop(L, 1);
506         lua_getfield(L, index, "after_destruct");
507         if(!lua_isnil(L, -1)) f.has_after_destruct = true;
508         lua_pop(L, 1);
509
510         lua_getfield(L, index, "on_rightclick");
511         f.rightclickable = lua_isfunction(L, -1);
512         lua_pop(L, 1);
513
514         /* Name */
515         getstringfield(L, index, "name", f.name);
516
517         /* Groups */
518         lua_getfield(L, index, "groups");
519         read_groups(L, -1, f.groups);
520         lua_pop(L, 1);
521
522         /* Visual definition */
523
524         f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype",
525                         ScriptApiNode::es_DrawType,NDT_NORMAL);
526         getfloatfield(L, index, "visual_scale", f.visual_scale);
527
528         /* Meshnode model filename */
529         getstringfield(L, index, "mesh", f.mesh);
530
531         // tiles = {}
532         lua_getfield(L, index, "tiles");
533         // If nil, try the deprecated name "tile_images" instead
534         if(lua_isnil(L, -1)){
535                 lua_pop(L, 1);
536                 warn_if_field_exists(L, index, "tile_images",
537                                 "Deprecated; new name is \"tiles\".");
538                 lua_getfield(L, index, "tile_images");
539         }
540         if(lua_istable(L, -1)){
541                 int table = lua_gettop(L);
542                 lua_pushnil(L);
543                 int i = 0;
544                 while(lua_next(L, table) != 0){
545                         // Read tiledef from value
546                         f.tiledef[i] = read_tiledef(L, -1, f.drawtype);
547                         // removes value, keeps key for next iteration
548                         lua_pop(L, 1);
549                         i++;
550                         if(i==6){
551                                 lua_pop(L, 1);
552                                 break;
553                         }
554                 }
555                 // Copy last value to all remaining textures
556                 if(i >= 1){
557                         TileDef lasttile = f.tiledef[i-1];
558                         while(i < 6){
559                                 f.tiledef[i] = lasttile;
560                                 i++;
561                         }
562                 }
563         }
564         lua_pop(L, 1);
565
566         // overlay_tiles = {}
567         lua_getfield(L, index, "overlay_tiles");
568         if (lua_istable(L, -1)) {
569                 int table = lua_gettop(L);
570                 lua_pushnil(L);
571                 int i = 0;
572                 while (lua_next(L, table) != 0) {
573                         // Read tiledef from value
574                         f.tiledef_overlay[i] = read_tiledef(L, -1, f.drawtype);
575                         // removes value, keeps key for next iteration
576                         lua_pop(L, 1);
577                         i++;
578                         if (i == 6) {
579                                 lua_pop(L, 1);
580                                 break;
581                         }
582                 }
583                 // Copy last value to all remaining textures
584                 if (i >= 1) {
585                         TileDef lasttile = f.tiledef_overlay[i - 1];
586                         while (i < 6) {
587                                 f.tiledef_overlay[i] = lasttile;
588                                 i++;
589                         }
590                 }
591         }
592         lua_pop(L, 1);
593
594         // special_tiles = {}
595         lua_getfield(L, index, "special_tiles");
596         // If nil, try the deprecated name "special_materials" instead
597         if(lua_isnil(L, -1)){
598                 lua_pop(L, 1);
599                 warn_if_field_exists(L, index, "special_materials",
600                                 "Deprecated; new name is \"special_tiles\".");
601                 lua_getfield(L, index, "special_materials");
602         }
603         if(lua_istable(L, -1)){
604                 int table = lua_gettop(L);
605                 lua_pushnil(L);
606                 int i = 0;
607                 while(lua_next(L, table) != 0){
608                         // Read tiledef from value
609                         f.tiledef_special[i] = read_tiledef(L, -1, f.drawtype);
610                         // removes value, keeps key for next iteration
611                         lua_pop(L, 1);
612                         i++;
613                         if(i==CF_SPECIAL_COUNT){
614                                 lua_pop(L, 1);
615                                 break;
616                         }
617                 }
618         }
619         lua_pop(L, 1);
620
621         f.alpha = getintfield_default(L, index, "alpha", 255);
622
623         bool usealpha = getboolfield_default(L, index,
624                         "use_texture_alpha", false);
625         if (usealpha)
626                 f.alpha = 0;
627
628         // Read node color.
629         lua_getfield(L, index, "color");
630         read_color(L, -1, &f.color);
631         lua_pop(L, 1);
632
633         getstringfield(L, index, "palette", f.palette_name);
634
635         /* Other stuff */
636
637         lua_getfield(L, index, "post_effect_color");
638         read_color(L, -1, &f.post_effect_color);
639         lua_pop(L, 1);
640
641         f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
642                         ScriptApiNode::es_ContentParamType, CPT_NONE);
643         f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
644                         ScriptApiNode::es_ContentParamType2, CPT2_NONE);
645
646         if (!f.palette_name.empty() &&
647                         !(f.param_type_2 == CPT2_COLOR ||
648                         f.param_type_2 == CPT2_COLORED_FACEDIR ||
649                         f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
650                 warningstream << "Node " << f.name.c_str()
651                         << " has a palette, but not a suitable paramtype2." << std::endl;
652
653         // Warn about some obsolete fields
654         warn_if_field_exists(L, index, "wall_mounted",
655                         "Obsolete; use paramtype2 = 'wallmounted'");
656         warn_if_field_exists(L, index, "light_propagates",
657                         "Obsolete; determined from paramtype");
658         warn_if_field_exists(L, index, "dug_item",
659                         "Obsolete; use 'drop' field");
660         warn_if_field_exists(L, index, "extra_dug_item",
661                         "Obsolete; use 'drop' field");
662         warn_if_field_exists(L, index, "extra_dug_item_rarity",
663                         "Obsolete; use 'drop' field");
664         warn_if_field_exists(L, index, "metadata_name",
665                         "Obsolete; use on_add and metadata callbacks");
666
667         // True for all ground-like things like stone and mud, false for eg. trees
668         getboolfield(L, index, "is_ground_content", f.is_ground_content);
669         f.light_propagates = (f.param_type == CPT_LIGHT);
670         getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
671         // This is used for collision detection.
672         // Also for general solidness queries.
673         getboolfield(L, index, "walkable", f.walkable);
674         // Player can point to these
675         getboolfield(L, index, "pointable", f.pointable);
676         // Player can dig these
677         getboolfield(L, index, "diggable", f.diggable);
678         // Player can climb these
679         getboolfield(L, index, "climbable", f.climbable);
680         // Player can build on these
681         getboolfield(L, index, "buildable_to", f.buildable_to);
682         // Liquids flow into and replace node
683         getboolfield(L, index, "floodable", f.floodable);
684         // Whether the node is non-liquid, source liquid or flowing liquid
685         f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
686                         ScriptApiNode::es_LiquidType, LIQUID_NONE);
687         // If the content is liquid, this is the flowing version of the liquid.
688         getstringfield(L, index, "liquid_alternative_flowing",
689                         f.liquid_alternative_flowing);
690         // If the content is liquid, this is the source version of the liquid.
691         getstringfield(L, index, "liquid_alternative_source",
692                         f.liquid_alternative_source);
693         // Viscosity for fluid flow, ranging from 1 to 7, with
694         // 1 giving almost instantaneous propagation and 7 being
695         // the slowest possible
696         f.liquid_viscosity = getintfield_default(L, index,
697                         "liquid_viscosity", f.liquid_viscosity);
698         f.liquid_range = getintfield_default(L, index,
699                         "liquid_range", f.liquid_range);
700         f.leveled = getintfield_default(L, index, "leveled", f.leveled);
701         f.leveled_max = getintfield_default(L, index,
702                         "leveled_max", f.leveled_max);
703
704         getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
705         f.drowning = getintfield_default(L, index,
706                         "drowning", f.drowning);
707         // Amount of light the node emits
708         f.light_source = getintfield_default(L, index,
709                         "light_source", f.light_source);
710         if (f.light_source > LIGHT_MAX) {
711                 warningstream << "Node " << f.name.c_str()
712                         << " had greater light_source than " << LIGHT_MAX
713                         << ", it was reduced." << std::endl;
714                 f.light_source = LIGHT_MAX;
715         }
716         f.damage_per_second = getintfield_default(L, index,
717                         "damage_per_second", f.damage_per_second);
718
719         lua_getfield(L, index, "node_box");
720         if(lua_istable(L, -1))
721                 f.node_box = read_nodebox(L, -1);
722         lua_pop(L, 1);
723
724         lua_getfield(L, index, "connects_to");
725         if (lua_istable(L, -1)) {
726                 int table = lua_gettop(L);
727                 lua_pushnil(L);
728                 while (lua_next(L, table) != 0) {
729                         // Value at -1
730                         f.connects_to.emplace_back(lua_tostring(L, -1));
731                         lua_pop(L, 1);
732                 }
733         }
734         lua_pop(L, 1);
735
736         lua_getfield(L, index, "connect_sides");
737         if (lua_istable(L, -1)) {
738                 int table = lua_gettop(L);
739                 lua_pushnil(L);
740                 while (lua_next(L, table) != 0) {
741                         // Value at -1
742                         std::string side(lua_tostring(L, -1));
743                         // Note faces are flipped to make checking easier
744                         if (side == "top")
745                                 f.connect_sides |= 2;
746                         else if (side == "bottom")
747                                 f.connect_sides |= 1;
748                         else if (side == "front")
749                                 f.connect_sides |= 16;
750                         else if (side == "left")
751                                 f.connect_sides |= 32;
752                         else if (side == "back")
753                                 f.connect_sides |= 4;
754                         else if (side == "right")
755                                 f.connect_sides |= 8;
756                         else
757                                 warningstream << "Unknown value for \"connect_sides\": "
758                                         << side << std::endl;
759                         lua_pop(L, 1);
760                 }
761         }
762         lua_pop(L, 1);
763
764         lua_getfield(L, index, "selection_box");
765         if(lua_istable(L, -1))
766                 f.selection_box = read_nodebox(L, -1);
767         lua_pop(L, 1);
768
769         lua_getfield(L, index, "collision_box");
770         if(lua_istable(L, -1))
771                 f.collision_box = read_nodebox(L, -1);
772         lua_pop(L, 1);
773
774         f.waving = getintfield_default(L, index,
775                         "waving", f.waving);
776
777         // Set to true if paramtype used to be 'facedir_simple'
778         getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
779         // Set to true if wall_mounted used to be set to true
780         getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
781
782         // Sound table
783         lua_getfield(L, index, "sounds");
784         if(lua_istable(L, -1)){
785                 lua_getfield(L, -1, "footstep");
786                 read_soundspec(L, -1, f.sound_footstep);
787                 lua_pop(L, 1);
788                 lua_getfield(L, -1, "dig");
789                 read_soundspec(L, -1, f.sound_dig);
790                 lua_pop(L, 1);
791                 lua_getfield(L, -1, "dug");
792                 read_soundspec(L, -1, f.sound_dug);
793                 lua_pop(L, 1);
794         }
795         lua_pop(L, 1);
796
797         // Node immediately placed by client when node is dug
798         getstringfield(L, index, "node_dig_prediction",
799                 f.node_dig_prediction);
800
801 }
802
803 void push_content_features(lua_State *L, const ContentFeatures &c)
804 {
805         std::string paramtype(ScriptApiNode::es_ContentParamType[(int)c.param_type].str);
806         std::string paramtype2(ScriptApiNode::es_ContentParamType2[(int)c.param_type_2].str);
807         std::string drawtype(ScriptApiNode::es_DrawType[(int)c.drawtype].str);
808         std::string liquid_type(ScriptApiNode::es_LiquidType[(int)c.liquid_type].str);
809
810         /* Missing "tiles" because I don't see a usecase (at least not yet). */
811
812         lua_newtable(L);
813         lua_pushboolean(L, c.has_on_construct);
814         lua_setfield(L, -2, "has_on_construct");
815         lua_pushboolean(L, c.has_on_destruct);
816         lua_setfield(L, -2, "has_on_destruct");
817         lua_pushboolean(L, c.has_after_destruct);
818         lua_setfield(L, -2, "has_after_destruct");
819         lua_pushstring(L, c.name.c_str());
820         lua_setfield(L, -2, "name");
821         push_groups(L, c.groups);
822         lua_setfield(L, -2, "groups");
823         lua_pushstring(L, paramtype.c_str());
824         lua_setfield(L, -2, "paramtype");
825         lua_pushstring(L, paramtype2.c_str());
826         lua_setfield(L, -2, "paramtype2");
827         lua_pushstring(L, drawtype.c_str());
828         lua_setfield(L, -2, "drawtype");
829         if (!c.mesh.empty()) {
830                 lua_pushstring(L, c.mesh.c_str());
831                 lua_setfield(L, -2, "mesh");
832         }
833 #ifndef SERVER
834         push_ARGB8(L, c.minimap_color);       // I know this is not set-able w/ register_node,
835         lua_setfield(L, -2, "minimap_color"); // but the people need to know!
836 #endif
837         lua_pushnumber(L, c.visual_scale);
838         lua_setfield(L, -2, "visual_scale");
839         lua_pushnumber(L, c.alpha);
840         lua_setfield(L, -2, "alpha");
841         if (!c.palette_name.empty()) {
842                 push_ARGB8(L, c.color);
843                 lua_setfield(L, -2, "color");
844
845                 lua_pushstring(L, c.palette_name.c_str());
846                 lua_setfield(L, -2, "palette_name");
847
848                 push_palette(L, c.palette);
849                 lua_setfield(L, -2, "palette");
850         }
851         lua_pushnumber(L, c.waving);
852         lua_setfield(L, -2, "waving");
853         lua_pushnumber(L, c.connect_sides);
854         lua_setfield(L, -2, "connect_sides");
855
856         lua_createtable(L, c.connects_to.size(), 0);
857         u16 i = 1;
858         for (const std::string &it : c.connects_to) {
859                 lua_pushlstring(L, it.c_str(), it.size());
860                 lua_rawseti(L, -2, i++);
861         }
862         lua_setfield(L, -2, "connects_to");
863
864         push_ARGB8(L, c.post_effect_color);
865         lua_setfield(L, -2, "post_effect_color");
866         lua_pushnumber(L, c.leveled);
867         lua_setfield(L, -2, "leveled");
868         lua_pushnumber(L, c.leveled_max);
869         lua_setfield(L, -2, "leveled_max");
870         lua_pushboolean(L, c.sunlight_propagates);
871         lua_setfield(L, -2, "sunlight_propagates");
872         lua_pushnumber(L, c.light_source);
873         lua_setfield(L, -2, "light_source");
874         lua_pushboolean(L, c.is_ground_content);
875         lua_setfield(L, -2, "is_ground_content");
876         lua_pushboolean(L, c.walkable);
877         lua_setfield(L, -2, "walkable");
878         lua_pushboolean(L, c.pointable);
879         lua_setfield(L, -2, "pointable");
880         lua_pushboolean(L, c.diggable);
881         lua_setfield(L, -2, "diggable");
882         lua_pushboolean(L, c.climbable);
883         lua_setfield(L, -2, "climbable");
884         lua_pushboolean(L, c.buildable_to);
885         lua_setfield(L, -2, "buildable_to");
886         lua_pushboolean(L, c.rightclickable);
887         lua_setfield(L, -2, "rightclickable");
888         lua_pushnumber(L, c.damage_per_second);
889         lua_setfield(L, -2, "damage_per_second");
890         if (c.isLiquid()) {
891                 lua_pushstring(L, liquid_type.c_str());
892                 lua_setfield(L, -2, "liquid_type");
893                 lua_pushstring(L, c.liquid_alternative_flowing.c_str());
894                 lua_setfield(L, -2, "liquid_alternative_flowing");
895                 lua_pushstring(L, c.liquid_alternative_source.c_str());
896                 lua_setfield(L, -2, "liquid_alternative_source");
897                 lua_pushnumber(L, c.liquid_viscosity);
898                 lua_setfield(L, -2, "liquid_viscosity");
899                 lua_pushboolean(L, c.liquid_renewable);
900                 lua_setfield(L, -2, "liquid_renewable");
901                 lua_pushnumber(L, c.liquid_range);
902                 lua_setfield(L, -2, "liquid_range");
903         }
904         lua_pushnumber(L, c.drowning);
905         lua_setfield(L, -2, "drowning");
906         lua_pushboolean(L, c.floodable);
907         lua_setfield(L, -2, "floodable");
908         push_nodebox(L, c.node_box);
909         lua_setfield(L, -2, "node_box");
910         push_nodebox(L, c.selection_box);
911         lua_setfield(L, -2, "selection_box");
912         push_nodebox(L, c.collision_box);
913         lua_setfield(L, -2, "collision_box");
914         lua_newtable(L);
915         push_soundspec(L, c.sound_footstep);
916         lua_setfield(L, -2, "sound_footstep");
917         push_soundspec(L, c.sound_dig);
918         lua_setfield(L, -2, "sound_dig");
919         push_soundspec(L, c.sound_dug);
920         lua_setfield(L, -2, "sound_dug");
921         lua_setfield(L, -2, "sounds");
922         lua_pushboolean(L, c.legacy_facedir_simple);
923         lua_setfield(L, -2, "legacy_facedir_simple");
924         lua_pushboolean(L, c.legacy_wallmounted);
925         lua_setfield(L, -2, "legacy_wallmounted");
926         lua_pushstring(L, c.node_dig_prediction.c_str());
927         lua_setfield(L, -2, "node_dig_prediction");
928 }
929
930 /******************************************************************************/
931 void push_nodebox(lua_State *L, const NodeBox &box)
932 {
933         lua_newtable(L);
934         switch (box.type)
935         {
936                 case NODEBOX_REGULAR:
937                         lua_pushstring(L, "regular");
938                         lua_setfield(L, -2, "type");
939                         break;
940                 case NODEBOX_LEVELED:
941                 case NODEBOX_FIXED:
942                         lua_pushstring(L, "fixed");
943                         lua_setfield(L, -2, "type");
944                         push_box(L, box.fixed);
945                         lua_setfield(L, -2, "fixed");
946                         break;
947                 case NODEBOX_WALLMOUNTED:
948                         lua_pushstring(L, "wallmounted");
949                         lua_setfield(L, -2, "type");
950                         push_aabb3f(L, box.wall_top);
951                         lua_setfield(L, -2, "wall_top");
952                         push_aabb3f(L, box.wall_bottom);
953                         lua_setfield(L, -2, "wall_bottom");
954                         push_aabb3f(L, box.wall_side);
955                         lua_setfield(L, -2, "wall_side");
956                         break;
957                 case NODEBOX_CONNECTED:
958                         lua_pushstring(L, "connected");
959                         lua_setfield(L, -2, "type");
960                         push_box(L, box.connect_top);
961                         lua_setfield(L, -2, "connect_top");
962                         push_box(L, box.connect_bottom);
963                         lua_setfield(L, -2, "connect_bottom");
964                         push_box(L, box.connect_front);
965                         lua_setfield(L, -2, "connect_front");
966                         push_box(L, box.connect_back);
967                         lua_setfield(L, -2, "connect_back");
968                         push_box(L, box.connect_left);
969                         lua_setfield(L, -2, "connect_left");
970                         push_box(L, box.connect_right);
971                         lua_setfield(L, -2, "connect_right");
972                         break;
973                 default:
974                         FATAL_ERROR("Invalid box.type");
975                         break;
976         }
977 }
978
979 void push_box(lua_State *L, const std::vector<aabb3f> &box)
980 {
981         lua_createtable(L, box.size(), 0);
982         u8 i = 1;
983         for (const aabb3f &it : box) {
984                 push_aabb3f(L, it);
985                 lua_rawseti(L, -2, i++);
986         }
987 }
988
989 /******************************************************************************/
990 void push_palette(lua_State *L, const std::vector<video::SColor> *palette)
991 {
992         lua_createtable(L, palette->size(), 0);
993         int newTable = lua_gettop(L);
994         int index = 1;
995         std::vector<video::SColor>::const_iterator iter;
996         for (iter = palette->begin(); iter != palette->end(); ++iter) {
997                 push_ARGB8(L, (*iter));
998                 lua_rawseti(L, newTable, index);
999                 index++;
1000         }
1001 }
1002
1003 /******************************************************************************/
1004 void read_server_sound_params(lua_State *L, int index,
1005                 ServerSoundParams &params)
1006 {
1007         if(index < 0)
1008                 index = lua_gettop(L) + 1 + index;
1009         // Clear
1010         params = ServerSoundParams();
1011         if(lua_istable(L, index)){
1012                 getfloatfield(L, index, "gain", params.gain);
1013                 getstringfield(L, index, "to_player", params.to_player);
1014                 getfloatfield(L, index, "fade", params.fade);
1015                 getfloatfield(L, index, "pitch", params.pitch);
1016                 lua_getfield(L, index, "pos");
1017                 if(!lua_isnil(L, -1)){
1018                         v3f p = read_v3f(L, -1)*BS;
1019                         params.pos = p;
1020                         params.type = ServerSoundParams::SSP_POSITIONAL;
1021                 }
1022                 lua_pop(L, 1);
1023                 lua_getfield(L, index, "object");
1024                 if(!lua_isnil(L, -1)){
1025                         ObjectRef *ref = ObjectRef::checkobject(L, -1);
1026                         ServerActiveObject *sao = ObjectRef::getobject(ref);
1027                         if(sao){
1028                                 params.object = sao->getId();
1029                                 params.type = ServerSoundParams::SSP_OBJECT;
1030                         }
1031                 }
1032                 lua_pop(L, 1);
1033                 params.max_hear_distance = BS*getfloatfield_default(L, index,
1034                                 "max_hear_distance", params.max_hear_distance/BS);
1035                 getboolfield(L, index, "loop", params.loop);
1036                 getstringfield(L, index, "exclude_player", params.exclude_player);
1037         }
1038 }
1039
1040 /******************************************************************************/
1041 void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
1042 {
1043         if(index < 0)
1044                 index = lua_gettop(L) + 1 + index;
1045         if (lua_isnil(L, index))
1046                 return;
1047
1048         if (lua_istable(L, index)) {
1049                 getstringfield(L, index, "name", spec.name);
1050                 getfloatfield(L, index, "gain", spec.gain);
1051                 getfloatfield(L, index, "fade", spec.fade);
1052                 getfloatfield(L, index, "pitch", spec.pitch);
1053         } else if (lua_isstring(L, index)) {
1054                 spec.name = lua_tostring(L, index);
1055         }
1056 }
1057
1058 void push_soundspec(lua_State *L, const SimpleSoundSpec &spec)
1059 {
1060         lua_createtable(L, 0, 3);
1061         lua_pushstring(L, spec.name.c_str());
1062         lua_setfield(L, -2, "name");
1063         lua_pushnumber(L, spec.gain);
1064         lua_setfield(L, -2, "gain");
1065         lua_pushnumber(L, spec.fade);
1066         lua_setfield(L, -2, "fade");
1067         lua_pushnumber(L, spec.pitch);
1068         lua_setfield(L, -2, "pitch");
1069 }
1070
1071 /******************************************************************************/
1072 NodeBox read_nodebox(lua_State *L, int index)
1073 {
1074         NodeBox nodebox;
1075         if (lua_isnil(L, -1))
1076                 return nodebox;
1077
1078         luaL_checktype(L, -1, LUA_TTABLE);
1079
1080         nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
1081                         ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR);
1082
1083 #define NODEBOXREAD(n, s){ \
1084                 lua_getfield(L, index, (s)); \
1085                 if (lua_istable(L, -1)) \
1086                         (n) = read_aabb3f(L, -1, BS); \
1087                 lua_pop(L, 1); \
1088         }
1089
1090 #define NODEBOXREADVEC(n, s) \
1091         lua_getfield(L, index, (s)); \
1092         if (lua_istable(L, -1)) \
1093                 (n) = read_aabb3f_vector(L, -1, BS); \
1094         lua_pop(L, 1);
1095
1096         NODEBOXREADVEC(nodebox.fixed, "fixed");
1097         NODEBOXREAD(nodebox.wall_top, "wall_top");
1098         NODEBOXREAD(nodebox.wall_bottom, "wall_bottom");
1099         NODEBOXREAD(nodebox.wall_side, "wall_side");
1100         NODEBOXREADVEC(nodebox.connect_top, "connect_top");
1101         NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom");
1102         NODEBOXREADVEC(nodebox.connect_front, "connect_front");
1103         NODEBOXREADVEC(nodebox.connect_left, "connect_left");
1104         NODEBOXREADVEC(nodebox.connect_back, "connect_back");
1105         NODEBOXREADVEC(nodebox.connect_right, "connect_right");
1106         NODEBOXREADVEC(nodebox.disconnected_top, "disconnected_top");
1107         NODEBOXREADVEC(nodebox.disconnected_bottom, "disconnected_bottom");
1108         NODEBOXREADVEC(nodebox.disconnected_front, "disconnected_front");
1109         NODEBOXREADVEC(nodebox.disconnected_left, "disconnected_left");
1110         NODEBOXREADVEC(nodebox.disconnected_back, "disconnected_back");
1111         NODEBOXREADVEC(nodebox.disconnected_right, "disconnected_right");
1112         NODEBOXREADVEC(nodebox.disconnected, "disconnected");
1113         NODEBOXREADVEC(nodebox.disconnected_sides, "disconnected_sides");
1114
1115         return nodebox;
1116 }
1117
1118 /******************************************************************************/
1119 MapNode readnode(lua_State *L, int index, const NodeDefManager *ndef)
1120 {
1121         lua_getfield(L, index, "name");
1122         if (!lua_isstring(L, -1))
1123                 throw LuaError("Node name is not set or is not a string!");
1124         std::string name = lua_tostring(L, -1);
1125         lua_pop(L, 1);
1126
1127         u8 param1 = 0;
1128         lua_getfield(L, index, "param1");
1129         if (!lua_isnil(L, -1))
1130                 param1 = lua_tonumber(L, -1);
1131         lua_pop(L, 1);
1132
1133         u8 param2 = 0;
1134         lua_getfield(L, index, "param2");
1135         if (!lua_isnil(L, -1))
1136                 param2 = lua_tonumber(L, -1);
1137         lua_pop(L, 1);
1138
1139         content_t id = CONTENT_IGNORE;
1140         if (!ndef->getId(name, id))
1141                 throw LuaError("\"" + name + "\" is not a registered node!");
1142
1143         return {id, param1, param2};
1144 }
1145
1146 /******************************************************************************/
1147 void pushnode(lua_State *L, const MapNode &n, const NodeDefManager *ndef)
1148 {
1149         lua_createtable(L, 0, 3);
1150         lua_pushstring(L, ndef->get(n).name.c_str());
1151         lua_setfield(L, -2, "name");
1152         lua_pushinteger(L, n.getParam1());
1153         lua_setfield(L, -2, "param1");
1154         lua_pushinteger(L, n.getParam2());
1155         lua_setfield(L, -2, "param2");
1156 }
1157
1158 /******************************************************************************/
1159 void warn_if_field_exists(lua_State *L, int table,
1160                 const char *name, const std::string &message)
1161 {
1162         lua_getfield(L, table, name);
1163         if (!lua_isnil(L, -1)) {
1164                 warningstream << "Field \"" << name << "\": "
1165                                 << message << std::endl;
1166                 infostream << script_get_backtrace(L) << std::endl;
1167         }
1168         lua_pop(L, 1);
1169 }
1170
1171 /******************************************************************************/
1172 int getenumfield(lua_State *L, int table,
1173                 const char *fieldname, const EnumString *spec, int default_)
1174 {
1175         int result = default_;
1176         string_to_enum(spec, result,
1177                         getstringfield_default(L, table, fieldname, ""));
1178         return result;
1179 }
1180
1181 /******************************************************************************/
1182 bool string_to_enum(const EnumString *spec, int &result,
1183                 const std::string &str)
1184 {
1185         const EnumString *esp = spec;
1186         while(esp->str){
1187                 if (!strcmp(str.c_str(), esp->str)) {
1188                         result = esp->num;
1189                         return true;
1190                 }
1191                 esp++;
1192         }
1193         return false;
1194 }
1195
1196 /******************************************************************************/
1197 ItemStack read_item(lua_State* L, int index, IItemDefManager *idef)
1198 {
1199         if(index < 0)
1200                 index = lua_gettop(L) + 1 + index;
1201
1202         if (lua_isnil(L, index)) {
1203                 return ItemStack();
1204         }
1205
1206         if (lua_isuserdata(L, index)) {
1207                 // Convert from LuaItemStack
1208                 LuaItemStack *o = LuaItemStack::checkobject(L, index);
1209                 return o->getItem();
1210         }
1211
1212         if (lua_isstring(L, index)) {
1213                 // Convert from itemstring
1214                 std::string itemstring = lua_tostring(L, index);
1215                 try
1216                 {
1217                         ItemStack item;
1218                         item.deSerialize(itemstring, idef);
1219                         return item;
1220                 }
1221                 catch(SerializationError &e)
1222                 {
1223                         warningstream<<"unable to create item from itemstring"
1224                                         <<": "<<itemstring<<std::endl;
1225                         return ItemStack();
1226                 }
1227         }
1228         else if(lua_istable(L, index))
1229         {
1230                 // Convert from table
1231                 std::string name = getstringfield_default(L, index, "name", "");
1232                 int count = getintfield_default(L, index, "count", 1);
1233                 int wear = getintfield_default(L, index, "wear", 0);
1234
1235                 ItemStack istack(name, count, wear, idef);
1236
1237                 // BACKWARDS COMPATIBLITY
1238                 std::string value = getstringfield_default(L, index, "metadata", "");
1239                 istack.metadata.setString("", value);
1240
1241                 // Get meta
1242                 lua_getfield(L, index, "meta");
1243                 int fieldstable = lua_gettop(L);
1244                 if (lua_istable(L, fieldstable)) {
1245                         lua_pushnil(L);
1246                         while (lua_next(L, fieldstable) != 0) {
1247                                 // key at index -2 and value at index -1
1248                                 std::string key = lua_tostring(L, -2);
1249                                 size_t value_len;
1250                                 const char *value_cs = lua_tolstring(L, -1, &value_len);
1251                                 std::string value(value_cs, value_len);
1252                                 istack.metadata.setString(key, value);
1253                                 lua_pop(L, 1); // removes value, keeps key for next iteration
1254                         }
1255                 }
1256
1257                 return istack;
1258         } else {
1259                 throw LuaError("Expecting itemstack, itemstring, table or nil");
1260         }
1261 }
1262
1263 /******************************************************************************/
1264 void push_tool_capabilities(lua_State *L,
1265                 const ToolCapabilities &toolcap)
1266 {
1267         lua_newtable(L);
1268         setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval);
1269         setintfield(L, -1, "max_drop_level", toolcap.max_drop_level);
1270         setintfield(L, -1, "punch_attack_uses", toolcap.punch_attack_uses);
1271                 // Create groupcaps table
1272                 lua_newtable(L);
1273                 // For each groupcap
1274                 for (const auto &gc_it : toolcap.groupcaps) {
1275                         // Create groupcap table
1276                         lua_newtable(L);
1277                         const std::string &name = gc_it.first;
1278                         const ToolGroupCap &groupcap = gc_it.second;
1279                         // Create subtable "times"
1280                         lua_newtable(L);
1281                         for (auto time : groupcap.times) {
1282                                 lua_pushinteger(L, time.first);
1283                                 lua_pushnumber(L, time.second);
1284                                 lua_settable(L, -3);
1285                         }
1286                         // Set subtable "times"
1287                         lua_setfield(L, -2, "times");
1288                         // Set simple parameters
1289                         setintfield(L, -1, "maxlevel", groupcap.maxlevel);
1290                         setintfield(L, -1, "uses", groupcap.uses);
1291                         // Insert groupcap table into groupcaps table
1292                         lua_setfield(L, -2, name.c_str());
1293                 }
1294                 // Set groupcaps table
1295                 lua_setfield(L, -2, "groupcaps");
1296                 //Create damage_groups table
1297                 lua_newtable(L);
1298                 // For each damage group
1299                 for (const auto &damageGroup : toolcap.damageGroups) {
1300                         // Create damage group table
1301                         lua_pushinteger(L, damageGroup.second);
1302                         lua_setfield(L, -2, damageGroup.first.c_str());
1303                 }
1304                 lua_setfield(L, -2, "damage_groups");
1305 }
1306
1307 /******************************************************************************/
1308 void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
1309 {
1310         InventoryList *invlist = inv->getList(name);
1311         if(invlist == NULL){
1312                 lua_pushnil(L);
1313                 return;
1314         }
1315         std::vector<ItemStack> items;
1316         for(u32 i=0; i<invlist->getSize(); i++)
1317                 items.push_back(invlist->getItem(i));
1318         push_items(L, items);
1319 }
1320
1321 /******************************************************************************/
1322 void read_inventory_list(lua_State *L, int tableindex,
1323                 Inventory *inv, const char *name, Server* srv, int forcesize)
1324 {
1325         if(tableindex < 0)
1326                 tableindex = lua_gettop(L) + 1 + tableindex;
1327         // If nil, delete list
1328         if(lua_isnil(L, tableindex)){
1329                 inv->deleteList(name);
1330                 return;
1331         }
1332         // Otherwise set list
1333         std::vector<ItemStack> items = read_items(L, tableindex,srv);
1334         int listsize = (forcesize != -1) ? forcesize : items.size();
1335         InventoryList *invlist = inv->addList(name, listsize);
1336         int index = 0;
1337         for(std::vector<ItemStack>::const_iterator
1338                         i = items.begin(); i != items.end(); ++i){
1339                 if(forcesize != -1 && index == forcesize)
1340                         break;
1341                 invlist->changeItem(index, *i);
1342                 index++;
1343         }
1344         while(forcesize != -1 && index < forcesize){
1345                 invlist->deleteItem(index);
1346                 index++;
1347         }
1348 }
1349
1350 /******************************************************************************/
1351 struct TileAnimationParams read_animation_definition(lua_State *L, int index)
1352 {
1353         if(index < 0)
1354                 index = lua_gettop(L) + 1 + index;
1355
1356         struct TileAnimationParams anim;
1357         anim.type = TAT_NONE;
1358         if (!lua_istable(L, index))
1359                 return anim;
1360
1361         anim.type = (TileAnimationType)
1362                 getenumfield(L, index, "type", es_TileAnimationType,
1363                 TAT_NONE);
1364         if (anim.type == TAT_VERTICAL_FRAMES) {
1365                 // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
1366                 anim.vertical_frames.aspect_w =
1367                         getintfield_default(L, index, "aspect_w", 16);
1368                 anim.vertical_frames.aspect_h =
1369                         getintfield_default(L, index, "aspect_h", 16);
1370                 anim.vertical_frames.length =
1371                         getfloatfield_default(L, index, "length", 1.0);
1372         } else if (anim.type == TAT_SHEET_2D) {
1373                 // {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
1374                 getintfield(L, index, "frames_w",
1375                         anim.sheet_2d.frames_w);
1376                 getintfield(L, index, "frames_h",
1377                         anim.sheet_2d.frames_h);
1378                 getfloatfield(L, index, "frame_length",
1379                         anim.sheet_2d.frame_length);
1380         }
1381
1382         return anim;
1383 }
1384
1385 /******************************************************************************/
1386 ToolCapabilities read_tool_capabilities(
1387                 lua_State *L, int table)
1388 {
1389         ToolCapabilities toolcap;
1390         getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
1391         getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
1392         getintfield(L, table, "punch_attack_uses", toolcap.punch_attack_uses);
1393         lua_getfield(L, table, "groupcaps");
1394         if(lua_istable(L, -1)){
1395                 int table_groupcaps = lua_gettop(L);
1396                 lua_pushnil(L);
1397                 while(lua_next(L, table_groupcaps) != 0){
1398                         // key at index -2 and value at index -1
1399                         std::string groupname = luaL_checkstring(L, -2);
1400                         if(lua_istable(L, -1)){
1401                                 int table_groupcap = lua_gettop(L);
1402                                 // This will be created
1403                                 ToolGroupCap groupcap;
1404                                 // Read simple parameters
1405                                 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
1406                                 getintfield(L, table_groupcap, "uses", groupcap.uses);
1407                                 // DEPRECATED: maxwear
1408                                 float maxwear = 0;
1409                                 if (getfloatfield(L, table_groupcap, "maxwear", maxwear)){
1410                                         if (maxwear != 0)
1411                                                 groupcap.uses = 1.0/maxwear;
1412                                         else
1413                                                 groupcap.uses = 0;
1414                                         warningstream << "Field \"maxwear\" is deprecated; "
1415                                                         << "replace with uses=1/maxwear" << std::endl;
1416                                         infostream << script_get_backtrace(L) << std::endl;
1417                                 }
1418                                 // Read "times" table
1419                                 lua_getfield(L, table_groupcap, "times");
1420                                 if(lua_istable(L, -1)){
1421                                         int table_times = lua_gettop(L);
1422                                         lua_pushnil(L);
1423                                         while(lua_next(L, table_times) != 0){
1424                                                 // key at index -2 and value at index -1
1425                                                 int rating = luaL_checkinteger(L, -2);
1426                                                 float time = luaL_checknumber(L, -1);
1427                                                 groupcap.times[rating] = time;
1428                                                 // removes value, keeps key for next iteration
1429                                                 lua_pop(L, 1);
1430                                         }
1431                                 }
1432                                 lua_pop(L, 1);
1433                                 // Insert groupcap into toolcap
1434                                 toolcap.groupcaps[groupname] = groupcap;
1435                         }
1436                         // removes value, keeps key for next iteration
1437                         lua_pop(L, 1);
1438                 }
1439         }
1440         lua_pop(L, 1);
1441
1442         lua_getfield(L, table, "damage_groups");
1443         if(lua_istable(L, -1)){
1444                 int table_damage_groups = lua_gettop(L);
1445                 lua_pushnil(L);
1446                 while(lua_next(L, table_damage_groups) != 0){
1447                         // key at index -2 and value at index -1
1448                         std::string groupname = luaL_checkstring(L, -2);
1449                         u16 value = luaL_checkinteger(L, -1);
1450                         toolcap.damageGroups[groupname] = value;
1451                         // removes value, keeps key for next iteration
1452                         lua_pop(L, 1);
1453                 }
1454         }
1455         lua_pop(L, 1);
1456         return toolcap;
1457 }
1458
1459 /******************************************************************************/
1460 void push_dig_params(lua_State *L,const DigParams &params)
1461 {
1462         lua_createtable(L, 0, 3);
1463         setboolfield(L, -1, "diggable", params.diggable);
1464         setfloatfield(L, -1, "time", params.time);
1465         setintfield(L, -1, "wear", params.wear);
1466 }
1467
1468 /******************************************************************************/
1469 void push_hit_params(lua_State *L,const HitParams &params)
1470 {
1471         lua_createtable(L, 0, 3);
1472         setintfield(L, -1, "hp", params.hp);
1473         setintfield(L, -1, "wear", params.wear);
1474 }
1475
1476 /******************************************************************************/
1477
1478 bool getflagsfield(lua_State *L, int table, const char *fieldname,
1479         FlagDesc *flagdesc, u32 *flags, u32 *flagmask)
1480 {
1481         lua_getfield(L, table, fieldname);
1482
1483         bool success = read_flags(L, -1, flagdesc, flags, flagmask);
1484
1485         lua_pop(L, 1);
1486
1487         return success;
1488 }
1489
1490 bool read_flags(lua_State *L, int index, FlagDesc *flagdesc,
1491         u32 *flags, u32 *flagmask)
1492 {
1493         if (lua_isstring(L, index)) {
1494                 std::string flagstr = lua_tostring(L, index);
1495                 *flags = readFlagString(flagstr, flagdesc, flagmask);
1496         } else if (lua_istable(L, index)) {
1497                 *flags = read_flags_table(L, index, flagdesc, flagmask);
1498         } else {
1499                 return false;
1500         }
1501
1502         return true;
1503 }
1504
1505 u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
1506 {
1507         u32 flags = 0, mask = 0;
1508         char fnamebuf[64] = "no";
1509
1510         for (int i = 0; flagdesc[i].name; i++) {
1511                 bool result;
1512
1513                 if (getboolfield(L, table, flagdesc[i].name, result)) {
1514                         mask |= flagdesc[i].flag;
1515                         if (result)
1516                                 flags |= flagdesc[i].flag;
1517                 }
1518
1519                 strlcpy(fnamebuf + 2, flagdesc[i].name, sizeof(fnamebuf) - 2);
1520                 if (getboolfield(L, table, fnamebuf, result))
1521                         mask |= flagdesc[i].flag;
1522         }
1523
1524         if (flagmask)
1525                 *flagmask = mask;
1526
1527         return flags;
1528 }
1529
1530 void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask)
1531 {
1532         std::string flagstring = writeFlagString(flags, flagdesc, flagmask);
1533         lua_pushlstring(L, flagstring.c_str(), flagstring.size());
1534 }
1535
1536 /******************************************************************************/
1537 /* Lua Stored data!                                                           */
1538 /******************************************************************************/
1539
1540 /******************************************************************************/
1541 void read_groups(lua_State *L, int index, ItemGroupList &result)
1542 {
1543         if (lua_isnil(L, index))
1544                 return;
1545
1546         luaL_checktype(L, index, LUA_TTABLE);
1547
1548         result.clear();
1549         lua_pushnil(L);
1550         if (index < 0)
1551                 index -= 1;
1552         while (lua_next(L, index) != 0) {
1553                 // key at index -2 and value at index -1
1554                 std::string name = luaL_checkstring(L, -2);
1555                 int rating = luaL_checkinteger(L, -1);
1556                 // zero rating indicates not in the group
1557                 if (rating != 0)
1558                         result[name] = rating;
1559                 // removes value, keeps key for next iteration
1560                 lua_pop(L, 1);
1561         }
1562 }
1563
1564 /******************************************************************************/
1565 void push_groups(lua_State *L, const ItemGroupList &groups)
1566 {
1567         lua_createtable(L, 0, groups.size());
1568         for (const auto &group : groups) {
1569                 lua_pushinteger(L, group.second);
1570                 lua_setfield(L, -2, group.first.c_str());
1571         }
1572 }
1573
1574 /******************************************************************************/
1575 void push_items(lua_State *L, const std::vector<ItemStack> &items)
1576 {
1577         lua_createtable(L, items.size(), 0);
1578         for (u32 i = 0; i != items.size(); i++) {
1579                 LuaItemStack::create(L, items[i]);
1580                 lua_rawseti(L, -2, i + 1);
1581         }
1582 }
1583
1584 /******************************************************************************/
1585 std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
1586 {
1587         if(index < 0)
1588                 index = lua_gettop(L) + 1 + index;
1589
1590         std::vector<ItemStack> items;
1591         luaL_checktype(L, index, LUA_TTABLE);
1592         lua_pushnil(L);
1593         while (lua_next(L, index)) {
1594                 s32 key = luaL_checkinteger(L, -2);
1595                 if (key < 1) {
1596                         throw LuaError("Invalid inventory list index");
1597                 }
1598                 if (items.size() < (u32) key) {
1599                         items.resize(key);
1600                 }
1601                 items[key - 1] = read_item(L, -1, srv->idef());
1602                 lua_pop(L, 1);
1603         }
1604         return items;
1605 }
1606
1607 /******************************************************************************/
1608 void luaentity_get(lua_State *L, u16 id)
1609 {
1610         // Get luaentities[i]
1611         lua_getglobal(L, "core");
1612         lua_getfield(L, -1, "luaentities");
1613         luaL_checktype(L, -1, LUA_TTABLE);
1614         lua_pushinteger(L, id);
1615         lua_gettable(L, -2);
1616         lua_remove(L, -2); // Remove luaentities
1617         lua_remove(L, -2); // Remove core
1618 }
1619
1620 /******************************************************************************/
1621 bool read_noiseparams(lua_State *L, int index, NoiseParams *np)
1622 {
1623         if (index < 0)
1624                 index = lua_gettop(L) + 1 + index;
1625
1626         if (!lua_istable(L, index))
1627                 return false;
1628
1629         getfloatfield(L, index, "offset",      np->offset);
1630         getfloatfield(L, index, "scale",       np->scale);
1631         getfloatfield(L, index, "persist",     np->persist);
1632         getfloatfield(L, index, "persistence", np->persist);
1633         getfloatfield(L, index, "lacunarity",  np->lacunarity);
1634         getintfield(L,   index, "seed",        np->seed);
1635         getintfield(L,   index, "octaves",     np->octaves);
1636
1637         u32 flags    = 0;
1638         u32 flagmask = 0;
1639         np->flags = getflagsfield(L, index, "flags", flagdesc_noiseparams,
1640                 &flags, &flagmask) ? flags : NOISE_FLAG_DEFAULTS;
1641
1642         lua_getfield(L, index, "spread");
1643         np->spread  = read_v3f(L, -1);
1644         lua_pop(L, 1);
1645
1646         return true;
1647 }
1648
1649 void push_noiseparams(lua_State *L, NoiseParams *np)
1650 {
1651         lua_newtable(L);
1652         push_float_string(L, np->offset);
1653         lua_setfield(L, -2, "offset");
1654         push_float_string(L, np->scale);
1655         lua_setfield(L, -2, "scale");
1656         push_float_string(L, np->persist);
1657         lua_setfield(L, -2, "persistence");
1658         push_float_string(L, np->lacunarity);
1659         lua_setfield(L, -2, "lacunarity");
1660         lua_pushnumber(L, np->seed);
1661         lua_setfield(L, -2, "seed");
1662         lua_pushnumber(L, np->octaves);
1663         lua_setfield(L, -2, "octaves");
1664
1665         push_flags_string(L, flagdesc_noiseparams, np->flags,
1666                 np->flags);
1667         lua_setfield(L, -2, "flags");
1668
1669         push_v3_float_string(L, np->spread);
1670         lua_setfield(L, -2, "spread");
1671 }
1672
1673 /******************************************************************************/
1674 // Returns depth of json value tree
1675 static int push_json_value_getdepth(const Json::Value &value)
1676 {
1677         if (!value.isArray() && !value.isObject())
1678                 return 1;
1679
1680         int maxdepth = 0;
1681         for (const auto &it : value) {
1682                 int elemdepth = push_json_value_getdepth(it);
1683                 if (elemdepth > maxdepth)
1684                         maxdepth = elemdepth;
1685         }
1686         return maxdepth + 1;
1687 }
1688 // Recursive function to convert JSON --> Lua table
1689 static bool push_json_value_helper(lua_State *L, const Json::Value &value,
1690                 int nullindex)
1691 {
1692         switch(value.type()) {
1693                 case Json::nullValue:
1694                 default:
1695                         lua_pushvalue(L, nullindex);
1696                         break;
1697                 case Json::intValue:
1698                         lua_pushinteger(L, value.asLargestInt());
1699                         break;
1700                 case Json::uintValue:
1701                         lua_pushinteger(L, value.asLargestUInt());
1702                         break;
1703                 case Json::realValue:
1704                         lua_pushnumber(L, value.asDouble());
1705                         break;
1706                 case Json::stringValue:
1707                         {
1708                                 const char *str = value.asCString();
1709                                 lua_pushstring(L, str ? str : "");
1710                         }
1711                         break;
1712                 case Json::booleanValue:
1713                         lua_pushboolean(L, value.asInt());
1714                         break;
1715                 case Json::arrayValue:
1716                         lua_createtable(L, value.size(), 0);
1717                         for (Json::Value::const_iterator it = value.begin();
1718                                         it != value.end(); ++it) {
1719                                 push_json_value_helper(L, *it, nullindex);
1720                                 lua_rawseti(L, -2, it.index() + 1);
1721                         }
1722                         break;
1723                 case Json::objectValue:
1724                         lua_createtable(L, 0, value.size());
1725                         for (Json::Value::const_iterator it = value.begin();
1726                                         it != value.end(); ++it) {
1727 #if !defined(JSONCPP_STRING) && (JSONCPP_VERSION_MAJOR < 1 || JSONCPP_VERSION_MINOR < 9)
1728                                 const char *str = it.memberName();
1729                                 lua_pushstring(L, str ? str : "");
1730 #else
1731                                 std::string str = it.name();
1732                                 lua_pushstring(L, str.c_str());
1733 #endif
1734                                 push_json_value_helper(L, *it, nullindex);
1735                                 lua_rawset(L, -3);
1736                         }
1737                         break;
1738         }
1739         return true;
1740 }
1741 // converts JSON --> Lua table; returns false if lua stack limit exceeded
1742 // nullindex: Lua stack index of value to use in place of JSON null
1743 bool push_json_value(lua_State *L, const Json::Value &value, int nullindex)
1744 {
1745         if(nullindex < 0)
1746                 nullindex = lua_gettop(L) + 1 + nullindex;
1747
1748         int depth = push_json_value_getdepth(value);
1749
1750         // The maximum number of Lua stack slots used at each recursion level
1751         // of push_json_value_helper is 2, so make sure there a depth * 2 slots
1752         if (lua_checkstack(L, depth * 2))
1753                 return push_json_value_helper(L, value, nullindex);
1754
1755         return false;
1756 }
1757
1758 // Converts Lua table --> JSON
1759 void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion)
1760 {
1761         if (recursion > 16) {
1762                 throw SerializationError("Maximum recursion depth exceeded");
1763         }
1764         int type = lua_type(L, index);
1765         if (type == LUA_TBOOLEAN) {
1766                 root = (bool) lua_toboolean(L, index);
1767         } else if (type == LUA_TNUMBER) {
1768                 root = lua_tonumber(L, index);
1769         } else if (type == LUA_TSTRING) {
1770                 size_t len;
1771                 const char *str = lua_tolstring(L, index, &len);
1772                 root = std::string(str, len);
1773         } else if (type == LUA_TTABLE) {
1774                 lua_pushnil(L);
1775                 while (lua_next(L, index)) {
1776                         // Key is at -2 and value is at -1
1777                         Json::Value value;
1778                         read_json_value(L, value, lua_gettop(L), recursion + 1);
1779
1780                         Json::ValueType roottype = root.type();
1781                         int keytype = lua_type(L, -1);
1782                         if (keytype == LUA_TNUMBER) {
1783                                 lua_Number key = lua_tonumber(L, -1);
1784                                 if (roottype != Json::nullValue && roottype != Json::arrayValue) {
1785                                         throw SerializationError("Can't mix array and object values in JSON");
1786                                 } else if (key < 1) {
1787                                         throw SerializationError("Can't use zero-based or negative indexes in JSON");
1788                                 } else if (floor(key) != key) {
1789                                         throw SerializationError("Can't use indexes with a fractional part in JSON");
1790                                 }
1791                                 root[(Json::ArrayIndex) key - 1] = value;
1792                         } else if (keytype == LUA_TSTRING) {
1793                                 if (roottype != Json::nullValue && roottype != Json::objectValue) {
1794                                         throw SerializationError("Can't mix array and object values in JSON");
1795                                 }
1796                                 root[lua_tostring(L, -1)] = value;
1797                         } else {
1798                                 throw SerializationError("Lua key to convert to JSON is not a string or number");
1799                         }
1800                 }
1801         } else if (type == LUA_TNIL) {
1802                 root = Json::nullValue;
1803         } else {
1804                 throw SerializationError("Can only store booleans, numbers, strings, objects, arrays, and null in JSON");
1805         }
1806         lua_pop(L, 1); // Pop value
1807 }
1808
1809 void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm,
1810         bool hitpoint)
1811 {
1812         lua_newtable(L);
1813         if (pointed.type == POINTEDTHING_NODE) {
1814                 lua_pushstring(L, "node");
1815                 lua_setfield(L, -2, "type");
1816                 push_v3s16(L, pointed.node_undersurface);
1817                 lua_setfield(L, -2, "under");
1818                 push_v3s16(L, pointed.node_abovesurface);
1819                 lua_setfield(L, -2, "above");
1820         } else if (pointed.type == POINTEDTHING_OBJECT) {
1821                 lua_pushstring(L, "object");
1822                 lua_setfield(L, -2, "type");
1823
1824                 if (csm) {
1825                         lua_pushinteger(L, pointed.object_id);
1826                         lua_setfield(L, -2, "id");
1827                 } else {
1828                         push_objectRef(L, pointed.object_id);
1829                         lua_setfield(L, -2, "ref");
1830                 }
1831         } else {
1832                 lua_pushstring(L, "nothing");
1833                 lua_setfield(L, -2, "type");
1834         }
1835         if (hitpoint && (pointed.type != POINTEDTHING_NOTHING)) {
1836                 push_v3f(L, pointed.intersection_point / BS); // convert to node coords
1837                 lua_setfield(L, -2, "intersection_point");
1838                 push_v3s16(L, pointed.intersection_normal);
1839                 lua_setfield(L, -2, "intersection_normal");
1840                 lua_pushinteger(L, pointed.box_id + 1); // change to Lua array index
1841                 lua_setfield(L, -2, "box_id");
1842         }
1843 }
1844
1845 void push_objectRef(lua_State *L, const u16 id)
1846 {
1847         // Get core.object_refs[i]
1848         lua_getglobal(L, "core");
1849         lua_getfield(L, -1, "object_refs");
1850         luaL_checktype(L, -1, LUA_TTABLE);
1851         lua_pushinteger(L, id);
1852         lua_gettable(L, -2);
1853         lua_remove(L, -2); // object_refs
1854         lua_remove(L, -2); // core
1855 }
1856
1857 void read_hud_element(lua_State *L, HudElement *elem)
1858 {
1859         elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
1860                                                                         es_HudElementType, HUD_ELEM_TEXT);
1861
1862         lua_getfield(L, 2, "position");
1863         elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1864         lua_pop(L, 1);
1865
1866         lua_getfield(L, 2, "scale");
1867         elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1868         lua_pop(L, 1);
1869
1870         lua_getfield(L, 2, "size");
1871         elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32();
1872         lua_pop(L, 1);
1873
1874         elem->name    = getstringfield_default(L, 2, "name", "");
1875         elem->text    = getstringfield_default(L, 2, "text", "");
1876         elem->number  = getintfield_default(L, 2, "number", 0);
1877         if (elem->type == HUD_ELEM_WAYPOINT)
1878                 // waypoints reuse the item field to store precision, item = precision + 1
1879                 elem->item = getintfield_default(L, 2, "precision", -1) + 1;
1880         else
1881                 elem->item = getintfield_default(L, 2, "item", 0);
1882         elem->dir     = getintfield_default(L, 2, "direction", 0);
1883         elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX,
1884                         getintfield_default(L, 2, "z_index", 0)));
1885         elem->text2   = getstringfield_default(L, 2, "text2", "");
1886
1887         // Deprecated, only for compatibility's sake
1888         if (elem->dir == 0)
1889                 elem->dir = getintfield_default(L, 2, "dir", 0);
1890
1891         lua_getfield(L, 2, "alignment");
1892         elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1893         lua_pop(L, 1);
1894
1895         lua_getfield(L, 2, "offset");
1896         elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1897         lua_pop(L, 1);
1898
1899         lua_getfield(L, 2, "world_pos");
1900         elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
1901         lua_pop(L, 1);
1902
1903         /* check for known deprecated element usage */
1904         if ((elem->type  == HUD_ELEM_STATBAR) && (elem->size == v2s32()))
1905                 log_deprecated(L,"Deprecated usage of statbar without size!");
1906 }
1907
1908 void push_hud_element(lua_State *L, HudElement *elem)
1909 {
1910         lua_newtable(L);
1911
1912         lua_pushstring(L, es_HudElementType[(u8)elem->type].str);
1913         lua_setfield(L, -2, "type");
1914
1915         push_v2f(L, elem->pos);
1916         lua_setfield(L, -2, "position");
1917
1918         lua_pushstring(L, elem->name.c_str());
1919         lua_setfield(L, -2, "name");
1920
1921         push_v2f(L, elem->scale);
1922         lua_setfield(L, -2, "scale");
1923
1924         lua_pushstring(L, elem->text.c_str());
1925         lua_setfield(L, -2, "text");
1926
1927         lua_pushnumber(L, elem->number);
1928         lua_setfield(L, -2, "number");
1929
1930         lua_pushnumber(L, elem->item);
1931         lua_setfield(L, -2, "item");
1932
1933         lua_pushnumber(L, elem->dir);
1934         lua_setfield(L, -2, "direction");
1935
1936         push_v2f(L, elem->offset);
1937         lua_setfield(L, -2, "offset");
1938
1939         push_v2f(L, elem->align);
1940         lua_setfield(L, -2, "alignment");
1941
1942         push_v2s32(L, elem->size);
1943         lua_setfield(L, -2, "size");
1944
1945         // Deprecated, only for compatibility's sake
1946         lua_pushnumber(L, elem->dir);
1947         lua_setfield(L, -2, "dir");
1948
1949         push_v3f(L, elem->world_pos);
1950         lua_setfield(L, -2, "world_pos");
1951
1952         lua_pushnumber(L, elem->z_index);
1953         lua_setfield(L, -2, "z_index");
1954
1955         lua_pushstring(L, elem->text2.c_str());
1956         lua_setfield(L, -2, "text2");
1957 }
1958
1959 HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
1960 {
1961         HudElementStat stat = HUD_STAT_NUMBER;
1962         std::string statstr;
1963         if (lua_isstring(L, 3)) {
1964                 int statint;
1965                 statstr = lua_tostring(L, 3);
1966                 stat = string_to_enum(es_HudElementStat, statint, statstr) ?
1967                                 (HudElementStat)statint : stat;
1968         }
1969
1970         switch (stat) {
1971                 case HUD_STAT_POS:
1972                         elem->pos = read_v2f(L, 4);
1973                         *value = &elem->pos;
1974                         break;
1975                 case HUD_STAT_NAME:
1976                         elem->name = luaL_checkstring(L, 4);
1977                         *value = &elem->name;
1978                         break;
1979                 case HUD_STAT_SCALE:
1980                         elem->scale = read_v2f(L, 4);
1981                         *value = &elem->scale;
1982                         break;
1983                 case HUD_STAT_TEXT:
1984                         elem->text = luaL_checkstring(L, 4);
1985                         *value = &elem->text;
1986                         break;
1987                 case HUD_STAT_NUMBER:
1988                         elem->number = luaL_checknumber(L, 4);
1989                         *value = &elem->number;
1990                         break;
1991                 case HUD_STAT_ITEM:
1992                         elem->item = luaL_checknumber(L, 4);
1993                         if (elem->type == HUD_ELEM_WAYPOINT && statstr == "precision")
1994                                 elem->item++;
1995                         *value = &elem->item;
1996                         break;
1997                 case HUD_STAT_DIR:
1998                         elem->dir = luaL_checknumber(L, 4);
1999                         *value = &elem->dir;
2000                         break;
2001                 case HUD_STAT_ALIGN:
2002                         elem->align = read_v2f(L, 4);
2003                         *value = &elem->align;
2004                         break;
2005                 case HUD_STAT_OFFSET:
2006                         elem->offset = read_v2f(L, 4);
2007                         *value = &elem->offset;
2008                         break;
2009                 case HUD_STAT_WORLD_POS:
2010                         elem->world_pos = read_v3f(L, 4);
2011                         *value = &elem->world_pos;
2012                         break;
2013                 case HUD_STAT_SIZE:
2014                         elem->size = read_v2s32(L, 4);
2015                         *value = &elem->size;
2016                         break;
2017                 case HUD_STAT_Z_INDEX:
2018                         elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4)));
2019                         *value = &elem->z_index;
2020                         break;
2021                 case HUD_STAT_TEXT2:
2022                         elem->text2 = luaL_checkstring(L, 4);
2023                         *value = &elem->text2;
2024                         break;
2025         }
2026         return stat;
2027 }
2028
2029 /******************************************************************************/
2030
2031 // Indices must match values in `enum CollisionType` exactly!!
2032 static const char *collision_type_str[] = {
2033         "node",
2034         "object",
2035 };
2036
2037 // Indices must match values in `enum CollisionAxis` exactly!!
2038 static const char *collision_axis_str[] = {
2039         "x",
2040         "y",
2041         "z",
2042 };
2043
2044 void push_collision_move_result(lua_State *L, const collisionMoveResult &res)
2045 {
2046         lua_createtable(L, 0, 4);
2047
2048         setboolfield(L, -1, "touching_ground", res.touching_ground);
2049         setboolfield(L, -1, "collides", res.collides);
2050         setboolfield(L, -1, "standing_on_object", res.standing_on_object);
2051
2052         /* collisions */
2053         lua_createtable(L, res.collisions.size(), 0);
2054         int i = 1;
2055         for (const auto &c : res.collisions) {
2056                 lua_createtable(L, 0, 5);
2057
2058                 lua_pushstring(L, collision_type_str[c.type]);
2059                 lua_setfield(L, -2, "type");
2060
2061                 assert(c.axis != COLLISION_AXIS_NONE);
2062                 lua_pushstring(L, collision_axis_str[c.axis]);
2063                 lua_setfield(L, -2, "axis");
2064
2065                 if (c.type == COLLISION_NODE) {
2066                         push_v3s16(L, c.node_p);
2067                         lua_setfield(L, -2, "node_pos");
2068                 } else if (c.type == COLLISION_OBJECT) {
2069                         push_objectRef(L, c.object->getId());
2070                         lua_setfield(L, -2, "object");
2071                 }
2072
2073                 push_v3f(L, c.old_speed / BS);
2074                 lua_setfield(L, -2, "old_velocity");
2075
2076                 push_v3f(L, c.new_speed / BS);
2077                 lua_setfield(L, -2, "new_velocity");
2078
2079                 lua_rawseti(L, -2, i++);
2080         }
2081         lua_setfield(L, -2, "collisions");
2082         /**/
2083 }