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