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