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