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