]> git.lizzy.rs Git - minetest.git/blob - src/script/common/c_content.cpp
Add ItemStack key-value meta storage
[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                 lua_getfield(L, index, "metadata");
831
832                 // Support old metadata format by checking type
833                 int fieldstable = lua_gettop(L);
834                 if (lua_istable(L, fieldstable)) {
835                         lua_pushnil(L);
836                         while (lua_next(L, fieldstable) != 0) {
837                                 // key at index -2 and value at index -1
838                                 std::string key = lua_tostring(L, -2);
839                                 size_t value_len;
840                                 const char *value_cs = lua_tolstring(L, -1, &value_len);
841                                 std::string value(value_cs, value_len);
842                                 istack.metadata.setString(name, value);
843                                 lua_pop(L, 1); // removes value, keeps key for next iteration
844                         }
845                 } else {
846                         // BACKWARDS COMPATIBLITY
847                         std::string value = getstringfield_default(L, index, "metadata", "");
848                         istack.metadata.setString("", value);
849                 }
850
851                 return istack;
852         } else {
853                 throw LuaError("Expecting itemstack, itemstring, table or nil");
854         }
855 }
856
857 /******************************************************************************/
858 void push_tool_capabilities(lua_State *L,
859                 const ToolCapabilities &toolcap)
860 {
861         lua_newtable(L);
862         setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval);
863                 setintfield(L, -1, "max_drop_level", toolcap.max_drop_level);
864                 // Create groupcaps table
865                 lua_newtable(L);
866                 // For each groupcap
867                 for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
868                         i != toolcap.groupcaps.end(); i++) {
869                         // Create groupcap table
870                         lua_newtable(L);
871                         const std::string &name = i->first;
872                         const ToolGroupCap &groupcap = i->second;
873                         // Create subtable "times"
874                         lua_newtable(L);
875                         for (UNORDERED_MAP<int, float>::const_iterator
876                                         i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
877                                 lua_pushinteger(L, i->first);
878                                 lua_pushnumber(L, i->second);
879                                 lua_settable(L, -3);
880                         }
881                         // Set subtable "times"
882                         lua_setfield(L, -2, "times");
883                         // Set simple parameters
884                         setintfield(L, -1, "maxlevel", groupcap.maxlevel);
885                         setintfield(L, -1, "uses", groupcap.uses);
886                         // Insert groupcap table into groupcaps table
887                         lua_setfield(L, -2, name.c_str());
888                 }
889                 // Set groupcaps table
890                 lua_setfield(L, -2, "groupcaps");
891                 //Create damage_groups table
892                 lua_newtable(L);
893                 // For each damage group
894                 for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
895                         i != toolcap.damageGroups.end(); i++) {
896                         // Create damage group table
897                         lua_pushinteger(L, i->second);
898                         lua_setfield(L, -2, i->first.c_str());
899                 }
900                 lua_setfield(L, -2, "damage_groups");
901 }
902
903 /******************************************************************************/
904 void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
905 {
906         InventoryList *invlist = inv->getList(name);
907         if(invlist == NULL){
908                 lua_pushnil(L);
909                 return;
910         }
911         std::vector<ItemStack> items;
912         for(u32 i=0; i<invlist->getSize(); i++)
913                 items.push_back(invlist->getItem(i));
914         push_items(L, items);
915 }
916
917 /******************************************************************************/
918 void read_inventory_list(lua_State *L, int tableindex,
919                 Inventory *inv, const char *name, Server* srv, int forcesize)
920 {
921         if(tableindex < 0)
922                 tableindex = lua_gettop(L) + 1 + tableindex;
923         // If nil, delete list
924         if(lua_isnil(L, tableindex)){
925                 inv->deleteList(name);
926                 return;
927         }
928         // Otherwise set list
929         std::vector<ItemStack> items = read_items(L, tableindex,srv);
930         int listsize = (forcesize != -1) ? forcesize : items.size();
931         InventoryList *invlist = inv->addList(name, listsize);
932         int index = 0;
933         for(std::vector<ItemStack>::const_iterator
934                         i = items.begin(); i != items.end(); i++){
935                 if(forcesize != -1 && index == forcesize)
936                         break;
937                 invlist->changeItem(index, *i);
938                 index++;
939         }
940         while(forcesize != -1 && index < forcesize){
941                 invlist->deleteItem(index);
942                 index++;
943         }
944 }
945
946 /******************************************************************************/
947 struct TileAnimationParams read_animation_definition(lua_State *L, int index)
948 {
949         if(index < 0)
950                 index = lua_gettop(L) + 1 + index;
951
952         struct TileAnimationParams anim;
953         anim.type = TAT_NONE;
954         if (!lua_istable(L, index))
955                 return anim;
956
957         anim.type = (TileAnimationType)
958                 getenumfield(L, index, "type", es_TileAnimationType,
959                 TAT_NONE);
960         if (anim.type == TAT_VERTICAL_FRAMES) {
961                 // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
962                 anim.vertical_frames.aspect_w =
963                         getintfield_default(L, index, "aspect_w", 16);
964                 anim.vertical_frames.aspect_h =
965                         getintfield_default(L, index, "aspect_h", 16);
966                 anim.vertical_frames.length =
967                         getfloatfield_default(L, index, "length", 1.0);
968         } else if (anim.type == TAT_SHEET_2D) {
969                 // {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
970                 getintfield(L, index, "frames_w",
971                         anim.sheet_2d.frames_w);
972                 getintfield(L, index, "frames_h",
973                         anim.sheet_2d.frames_h);
974                 getfloatfield(L, index, "frame_length",
975                         anim.sheet_2d.frame_length);
976         }
977
978         return anim;
979 }
980
981 /******************************************************************************/
982 ToolCapabilities read_tool_capabilities(
983                 lua_State *L, int table)
984 {
985         ToolCapabilities toolcap;
986         getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
987         getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
988         lua_getfield(L, table, "groupcaps");
989         if(lua_istable(L, -1)){
990                 int table_groupcaps = lua_gettop(L);
991                 lua_pushnil(L);
992                 while(lua_next(L, table_groupcaps) != 0){
993                         // key at index -2 and value at index -1
994                         std::string groupname = luaL_checkstring(L, -2);
995                         if(lua_istable(L, -1)){
996                                 int table_groupcap = lua_gettop(L);
997                                 // This will be created
998                                 ToolGroupCap groupcap;
999                                 // Read simple parameters
1000                                 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
1001                                 getintfield(L, table_groupcap, "uses", groupcap.uses);
1002                                 // DEPRECATED: maxwear
1003                                 float maxwear = 0;
1004                                 if (getfloatfield(L, table_groupcap, "maxwear", maxwear)){
1005                                         if (maxwear != 0)
1006                                                 groupcap.uses = 1.0/maxwear;
1007                                         else
1008                                                 groupcap.uses = 0;
1009                                         warningstream << "Field \"maxwear\" is deprecated; "
1010                                                         << "replace with uses=1/maxwear" << std::endl;
1011                                         infostream << script_get_backtrace(L) << std::endl;
1012                                 }
1013                                 // Read "times" table
1014                                 lua_getfield(L, table_groupcap, "times");
1015                                 if(lua_istable(L, -1)){
1016                                         int table_times = lua_gettop(L);
1017                                         lua_pushnil(L);
1018                                         while(lua_next(L, table_times) != 0){
1019                                                 // key at index -2 and value at index -1
1020                                                 int rating = luaL_checkinteger(L, -2);
1021                                                 float time = luaL_checknumber(L, -1);
1022                                                 groupcap.times[rating] = time;
1023                                                 // removes value, keeps key for next iteration
1024                                                 lua_pop(L, 1);
1025                                         }
1026                                 }
1027                                 lua_pop(L, 1);
1028                                 // Insert groupcap into toolcap
1029                                 toolcap.groupcaps[groupname] = groupcap;
1030                         }
1031                         // removes value, keeps key for next iteration
1032                         lua_pop(L, 1);
1033                 }
1034         }
1035         lua_pop(L, 1);
1036
1037         lua_getfield(L, table, "damage_groups");
1038         if(lua_istable(L, -1)){
1039                 int table_damage_groups = lua_gettop(L);
1040                 lua_pushnil(L);
1041                 while(lua_next(L, table_damage_groups) != 0){
1042                         // key at index -2 and value at index -1
1043                         std::string groupname = luaL_checkstring(L, -2);
1044                         u16 value = luaL_checkinteger(L, -1);
1045                         toolcap.damageGroups[groupname] = value;
1046                         // removes value, keeps key for next iteration
1047                         lua_pop(L, 1);
1048                 }
1049         }
1050         lua_pop(L, 1);
1051         return toolcap;
1052 }
1053
1054 /******************************************************************************/
1055 void push_dig_params(lua_State *L,const DigParams &params)
1056 {
1057         lua_newtable(L);
1058         setboolfield(L, -1, "diggable", params.diggable);
1059         setfloatfield(L, -1, "time", params.time);
1060         setintfield(L, -1, "wear", params.wear);
1061 }
1062
1063 /******************************************************************************/
1064 void push_hit_params(lua_State *L,const HitParams &params)
1065 {
1066         lua_newtable(L);
1067         setintfield(L, -1, "hp", params.hp);
1068         setintfield(L, -1, "wear", params.wear);
1069 }
1070
1071 /******************************************************************************/
1072
1073 bool getflagsfield(lua_State *L, int table, const char *fieldname,
1074         FlagDesc *flagdesc, u32 *flags, u32 *flagmask)
1075 {
1076         lua_getfield(L, table, fieldname);
1077
1078         bool success = read_flags(L, -1, flagdesc, flags, flagmask);
1079
1080         lua_pop(L, 1);
1081
1082         return success;
1083 }
1084
1085 bool read_flags(lua_State *L, int index, FlagDesc *flagdesc,
1086         u32 *flags, u32 *flagmask)
1087 {
1088         if (lua_isstring(L, index)) {
1089                 std::string flagstr = lua_tostring(L, index);
1090                 *flags = readFlagString(flagstr, flagdesc, flagmask);
1091         } else if (lua_istable(L, index)) {
1092                 *flags = read_flags_table(L, index, flagdesc, flagmask);
1093         } else {
1094                 return false;
1095         }
1096
1097         return true;
1098 }
1099
1100 u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
1101 {
1102         u32 flags = 0, mask = 0;
1103         char fnamebuf[64] = "no";
1104
1105         for (int i = 0; flagdesc[i].name; i++) {
1106                 bool result;
1107
1108                 if (getboolfield(L, table, flagdesc[i].name, result)) {
1109                         mask |= flagdesc[i].flag;
1110                         if (result)
1111                                 flags |= flagdesc[i].flag;
1112                 }
1113
1114                 strlcpy(fnamebuf + 2, flagdesc[i].name, sizeof(fnamebuf) - 2);
1115                 if (getboolfield(L, table, fnamebuf, result))
1116                         mask |= flagdesc[i].flag;
1117         }
1118
1119         if (flagmask)
1120                 *flagmask = mask;
1121
1122         return flags;
1123 }
1124
1125 void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask)
1126 {
1127         std::string flagstring = writeFlagString(flags, flagdesc, flagmask);
1128         lua_pushlstring(L, flagstring.c_str(), flagstring.size());
1129 }
1130
1131 /******************************************************************************/
1132 /* Lua Stored data!                                                           */
1133 /******************************************************************************/
1134
1135 /******************************************************************************/
1136 void read_groups(lua_State *L, int index, ItemGroupList &result)
1137 {
1138         if (!lua_istable(L,index))
1139                 return;
1140         result.clear();
1141         lua_pushnil(L);
1142         if(index < 0)
1143                 index -= 1;
1144         while(lua_next(L, index) != 0){
1145                 // key at index -2 and value at index -1
1146                 std::string name = luaL_checkstring(L, -2);
1147                 int rating = luaL_checkinteger(L, -1);
1148                 result[name] = rating;
1149                 // removes value, keeps key for next iteration
1150                 lua_pop(L, 1);
1151         }
1152 }
1153
1154 /******************************************************************************/
1155 void push_groups(lua_State *L, const ItemGroupList &groups)
1156 {
1157         lua_newtable(L);
1158         for (ItemGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it) {
1159                 lua_pushnumber(L, it->second);
1160                 lua_setfield(L, -2, it->first.c_str());
1161         }
1162 }
1163
1164 /******************************************************************************/
1165 void push_items(lua_State *L, const std::vector<ItemStack> &items)
1166 {
1167         lua_createtable(L, items.size(), 0);
1168         for (u32 i = 0; i != items.size(); i++) {
1169                 LuaItemStack::create(L, items[i]);
1170                 lua_rawseti(L, -2, i + 1);
1171         }
1172 }
1173
1174 /******************************************************************************/
1175 std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
1176 {
1177         if(index < 0)
1178                 index = lua_gettop(L) + 1 + index;
1179
1180         std::vector<ItemStack> items;
1181         luaL_checktype(L, index, LUA_TTABLE);
1182         lua_pushnil(L);
1183         while (lua_next(L, index)) {
1184                 s32 key = luaL_checkinteger(L, -2);
1185                 if (key < 1) {
1186                         throw LuaError("Invalid inventory list index");
1187                 }
1188                 if (items.size() < (u32) key) {
1189                         items.resize(key);
1190                 }
1191                 items[key - 1] = read_item(L, -1, srv);
1192                 lua_pop(L, 1);
1193         }
1194         return items;
1195 }
1196
1197 /******************************************************************************/
1198 void luaentity_get(lua_State *L, u16 id)
1199 {
1200         // Get luaentities[i]
1201         lua_getglobal(L, "core");
1202         lua_getfield(L, -1, "luaentities");
1203         luaL_checktype(L, -1, LUA_TTABLE);
1204         lua_pushnumber(L, id);
1205         lua_gettable(L, -2);
1206         lua_remove(L, -2); // Remove luaentities
1207         lua_remove(L, -2); // Remove core
1208 }
1209
1210 /******************************************************************************/
1211 bool read_noiseparams(lua_State *L, int index, NoiseParams *np)
1212 {
1213         if (index < 0)
1214                 index = lua_gettop(L) + 1 + index;
1215
1216         if (!lua_istable(L, index))
1217                 return false;
1218
1219         getfloatfield(L, index, "offset",      np->offset);
1220         getfloatfield(L, index, "scale",       np->scale);
1221         getfloatfield(L, index, "persist",     np->persist);
1222         getfloatfield(L, index, "persistence", np->persist);
1223         getfloatfield(L, index, "lacunarity",  np->lacunarity);
1224         getintfield(L,   index, "seed",        np->seed);
1225         getintfield(L,   index, "octaves",     np->octaves);
1226
1227         u32 flags    = 0;
1228         u32 flagmask = 0;
1229         np->flags = getflagsfield(L, index, "flags", flagdesc_noiseparams,
1230                 &flags, &flagmask) ? flags : NOISE_FLAG_DEFAULTS;
1231
1232         lua_getfield(L, index, "spread");
1233         np->spread  = read_v3f(L, -1);
1234         lua_pop(L, 1);
1235
1236         return true;
1237 }
1238
1239 void push_noiseparams(lua_State *L, NoiseParams *np)
1240 {
1241         lua_newtable(L);
1242         lua_pushnumber(L, np->offset);
1243         lua_setfield(L, -2, "offset");
1244         lua_pushnumber(L, np->scale);
1245         lua_setfield(L, -2, "scale");
1246         lua_pushnumber(L, np->persist);
1247         lua_setfield(L, -2, "persistence");
1248         lua_pushnumber(L, np->lacunarity);
1249         lua_setfield(L, -2, "lacunarity");
1250         lua_pushnumber(L, np->seed);
1251         lua_setfield(L, -2, "seed");
1252         lua_pushnumber(L, np->octaves);
1253         lua_setfield(L, -2, "octaves");
1254
1255         push_flags_string(L, flagdesc_noiseparams, np->flags,
1256                 np->flags);
1257         lua_setfield(L, -2, "flags");
1258
1259         push_v3f(L, np->spread);
1260         lua_setfield(L, -2, "spread");
1261 }
1262
1263 /******************************************************************************/
1264 // Returns depth of json value tree
1265 static int push_json_value_getdepth(const Json::Value &value)
1266 {
1267         if (!value.isArray() && !value.isObject())
1268                 return 1;
1269
1270         int maxdepth = 0;
1271         for (Json::Value::const_iterator it = value.begin();
1272                         it != value.end(); ++it) {
1273                 int elemdepth = push_json_value_getdepth(*it);
1274                 if (elemdepth > maxdepth)
1275                         maxdepth = elemdepth;
1276         }
1277         return maxdepth + 1;
1278 }
1279 // Recursive function to convert JSON --> Lua table
1280 static bool push_json_value_helper(lua_State *L, const Json::Value &value,
1281                 int nullindex)
1282 {
1283         switch(value.type()) {
1284                 case Json::nullValue:
1285                 default:
1286                         lua_pushvalue(L, nullindex);
1287                         break;
1288                 case Json::intValue:
1289                         lua_pushinteger(L, value.asInt());
1290                         break;
1291                 case Json::uintValue:
1292                         lua_pushinteger(L, value.asUInt());
1293                         break;
1294                 case Json::realValue:
1295                         lua_pushnumber(L, value.asDouble());
1296                         break;
1297                 case Json::stringValue:
1298                         {
1299                                 const char *str = value.asCString();
1300                                 lua_pushstring(L, str ? str : "");
1301                         }
1302                         break;
1303                 case Json::booleanValue:
1304                         lua_pushboolean(L, value.asInt());
1305                         break;
1306                 case Json::arrayValue:
1307                         lua_newtable(L);
1308                         for (Json::Value::const_iterator it = value.begin();
1309                                         it != value.end(); ++it) {
1310                                 push_json_value_helper(L, *it, nullindex);
1311                                 lua_rawseti(L, -2, it.index() + 1);
1312                         }
1313                         break;
1314                 case Json::objectValue:
1315                         lua_newtable(L);
1316                         for (Json::Value::const_iterator it = value.begin();
1317                                         it != value.end(); ++it) {
1318 #ifndef JSONCPP_STRING
1319                                 const char *str = it.memberName();
1320                                 lua_pushstring(L, str ? str : "");
1321 #else
1322                                 std::string str = it.name();
1323                                 lua_pushstring(L, str.c_str());
1324 #endif
1325                                 push_json_value_helper(L, *it, nullindex);
1326                                 lua_rawset(L, -3);
1327                         }
1328                         break;
1329         }
1330         return true;
1331 }
1332 // converts JSON --> Lua table; returns false if lua stack limit exceeded
1333 // nullindex: Lua stack index of value to use in place of JSON null
1334 bool push_json_value(lua_State *L, const Json::Value &value, int nullindex)
1335 {
1336         if(nullindex < 0)
1337                 nullindex = lua_gettop(L) + 1 + nullindex;
1338
1339         int depth = push_json_value_getdepth(value);
1340
1341         // The maximum number of Lua stack slots used at each recursion level
1342         // of push_json_value_helper is 2, so make sure there a depth * 2 slots
1343         if (lua_checkstack(L, depth * 2))
1344                 return push_json_value_helper(L, value, nullindex);
1345         else
1346                 return false;
1347 }
1348
1349 // Converts Lua table --> JSON
1350 void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion)
1351 {
1352         if (recursion > 16) {
1353                 throw SerializationError("Maximum recursion depth exceeded");
1354         }
1355         int type = lua_type(L, index);
1356         if (type == LUA_TBOOLEAN) {
1357                 root = (bool) lua_toboolean(L, index);
1358         } else if (type == LUA_TNUMBER) {
1359                 root = lua_tonumber(L, index);
1360         } else if (type == LUA_TSTRING) {
1361                 size_t len;
1362                 const char *str = lua_tolstring(L, index, &len);
1363                 root = std::string(str, len);
1364         } else if (type == LUA_TTABLE) {
1365                 lua_pushnil(L);
1366                 while (lua_next(L, index)) {
1367                         // Key is at -2 and value is at -1
1368                         Json::Value value;
1369                         read_json_value(L, value, lua_gettop(L), recursion + 1);
1370
1371                         Json::ValueType roottype = root.type();
1372                         int keytype = lua_type(L, -1);
1373                         if (keytype == LUA_TNUMBER) {
1374                                 lua_Number key = lua_tonumber(L, -1);
1375                                 if (roottype != Json::nullValue && roottype != Json::arrayValue) {
1376                                         throw SerializationError("Can't mix array and object values in JSON");
1377                                 } else if (key < 1) {
1378                                         throw SerializationError("Can't use zero-based or negative indexes in JSON");
1379                                 } else if (floor(key) != key) {
1380                                         throw SerializationError("Can't use indexes with a fractional part in JSON");
1381                                 }
1382                                 root[(Json::ArrayIndex) key - 1] = value;
1383                         } else if (keytype == LUA_TSTRING) {
1384                                 if (roottype != Json::nullValue && roottype != Json::objectValue) {
1385                                         throw SerializationError("Can't mix array and object values in JSON");
1386                                 }
1387                                 root[lua_tostring(L, -1)] = value;
1388                         } else {
1389                                 throw SerializationError("Lua key to convert to JSON is not a string or number");
1390                         }
1391                 }
1392         } else if (type == LUA_TNIL) {
1393                 root = Json::nullValue;
1394         } else {
1395                 throw SerializationError("Can only store booleans, numbers, strings, objects, arrays, and null in JSON");
1396         }
1397         lua_pop(L, 1); // Pop value
1398 }