]> git.lizzy.rs Git - minetest.git/blob - src/script/common/c_content.cpp
99e12cd829bbd8b1044eaa94642969f0c288bf37
[minetest.git] / src / script / common / c_content.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 #include "common/c_content.h"
20 #include "common/c_converter.h"
21 #include "common/c_types.h"
22 #include "nodedef.h"
23 #include "object_properties.h"
24 #include "cpp_api/s_node.h"
25 #include "lua_api/l_object.h"
26 #include "lua_api/l_item.h"
27 #include "common/c_internal.h"
28 #include "server.h"
29 #include "log.h"
30 #include "tool.h"
31 #include "serverobject.h"
32 #include "porting.h"
33 #include "mg_schematic.h"
34 #include "noise.h"
35 #include <json/json.h>
36
37 struct EnumString es_TileAnimationType[] =
38 {
39         {TAT_NONE, "none"},
40         {TAT_VERTICAL_FRAMES, "vertical_frames"},
41         {TAT_SHEET_2D, "sheet_2d"},
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"
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                 // color = ...
335                 lua_getfield(L, index, "color");
336                 tiledef.has_color = read_color(L, -1, &tiledef.color);
337                 lua_pop(L, 1);
338                 // animation = {}
339                 lua_getfield(L, index, "animation");
340                 tiledef.animation = read_animation_definition(L, -1);
341                 lua_pop(L, 1);
342         }
343
344         return tiledef;
345 }
346
347 /******************************************************************************/
348 ContentFeatures read_content_features(lua_State *L, int index)
349 {
350         if(index < 0)
351                 index = lua_gettop(L) + 1 + index;
352
353         ContentFeatures f;
354
355         /* Cache existence of some callbacks */
356         lua_getfield(L, index, "on_construct");
357         if(!lua_isnil(L, -1)) f.has_on_construct = true;
358         lua_pop(L, 1);
359         lua_getfield(L, index, "on_destruct");
360         if(!lua_isnil(L, -1)) f.has_on_destruct = true;
361         lua_pop(L, 1);
362         lua_getfield(L, index, "after_destruct");
363         if(!lua_isnil(L, -1)) f.has_after_destruct = true;
364         lua_pop(L, 1);
365
366         lua_getfield(L, index, "on_rightclick");
367         f.rightclickable = lua_isfunction(L, -1);
368         lua_pop(L, 1);
369
370         /* Name */
371         getstringfield(L, index, "name", f.name);
372
373         /* Groups */
374         lua_getfield(L, index, "groups");
375         read_groups(L, -1, f.groups);
376         lua_pop(L, 1);
377
378         /* Visual definition */
379
380         f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype",
381                         ScriptApiNode::es_DrawType,NDT_NORMAL);
382         getfloatfield(L, index, "visual_scale", f.visual_scale);
383
384         /* Meshnode model filename */
385         getstringfield(L, index, "mesh", f.mesh);
386
387         // tiles = {}
388         lua_getfield(L, index, "tiles");
389         // If nil, try the deprecated name "tile_images" instead
390         if(lua_isnil(L, -1)){
391                 lua_pop(L, 1);
392                 warn_if_field_exists(L, index, "tile_images",
393                                 "Deprecated; new name is \"tiles\".");
394                 lua_getfield(L, index, "tile_images");
395         }
396         if(lua_istable(L, -1)){
397                 int table = lua_gettop(L);
398                 lua_pushnil(L);
399                 int i = 0;
400                 while(lua_next(L, table) != 0){
401                         // Read tiledef from value
402                         f.tiledef[i] = read_tiledef(L, -1, f.drawtype);
403                         // removes value, keeps key for next iteration
404                         lua_pop(L, 1);
405                         i++;
406                         if(i==6){
407                                 lua_pop(L, 1);
408                                 break;
409                         }
410                 }
411                 // Copy last value to all remaining textures
412                 if(i >= 1){
413                         TileDef lasttile = f.tiledef[i-1];
414                         while(i < 6){
415                                 f.tiledef[i] = lasttile;
416                                 i++;
417                         }
418                 }
419         }
420         lua_pop(L, 1);
421
422         // special_tiles = {}
423         lua_getfield(L, index, "special_tiles");
424         // If nil, try the deprecated name "special_materials" instead
425         if(lua_isnil(L, -1)){
426                 lua_pop(L, 1);
427                 warn_if_field_exists(L, index, "special_materials",
428                                 "Deprecated; new name is \"special_tiles\".");
429                 lua_getfield(L, index, "special_materials");
430         }
431         if(lua_istable(L, -1)){
432                 int table = lua_gettop(L);
433                 lua_pushnil(L);
434                 int i = 0;
435                 while(lua_next(L, table) != 0){
436                         // Read tiledef from value
437                         f.tiledef_special[i] = read_tiledef(L, -1, f.drawtype);
438                         // removes value, keeps key for next iteration
439                         lua_pop(L, 1);
440                         i++;
441                         if(i==CF_SPECIAL_COUNT){
442                                 lua_pop(L, 1);
443                                 break;
444                         }
445                 }
446         }
447         lua_pop(L, 1);
448
449         f.alpha = getintfield_default(L, index, "alpha", 255);
450
451         bool usealpha = getboolfield_default(L, index,
452                         "use_texture_alpha", false);
453         if (usealpha)
454                 f.alpha = 0;
455
456         // Read node color.
457         lua_getfield(L, index, "color");
458         read_color(L, -1, &f.color);
459         lua_pop(L, 1);
460
461         getstringfield(L, index, "palette", f.palette_name);
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         if (f.palette_name != "" &&
475                         !(f.param_type_2 == CPT2_COLOR ||
476                         f.param_type_2 == CPT2_COLORED_FACEDIR ||
477                         f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
478                 warningstream << "Node " << f.name.c_str()
479                         << " has a palette, but not a suitable paramtype2." << std::endl;
480
481         // Warn about some deprecated fields
482         warn_if_field_exists(L, index, "wall_mounted",
483                         "Deprecated; use paramtype2 = 'wallmounted'");
484         warn_if_field_exists(L, index, "light_propagates",
485                         "Deprecated; determined from paramtype");
486         warn_if_field_exists(L, index, "dug_item",
487                         "Deprecated; use 'drop' field");
488         warn_if_field_exists(L, index, "extra_dug_item",
489                         "Deprecated; use 'drop' field");
490         warn_if_field_exists(L, index, "extra_dug_item_rarity",
491                         "Deprecated; use 'drop' field");
492         warn_if_field_exists(L, index, "metadata_name",
493                         "Deprecated; use on_add and metadata callbacks");
494
495         // True for all ground-like things like stone and mud, false for eg. trees
496         getboolfield(L, index, "is_ground_content", f.is_ground_content);
497         f.light_propagates = (f.param_type == CPT_LIGHT);
498         getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
499         // This is used for collision detection.
500         // Also for general solidness queries.
501         getboolfield(L, index, "walkable", f.walkable);
502         // Player can point to these
503         getboolfield(L, index, "pointable", f.pointable);
504         // Player can dig these
505         getboolfield(L, index, "diggable", f.diggable);
506         // Player can climb these
507         getboolfield(L, index, "climbable", f.climbable);
508         // Player can build on these
509         getboolfield(L, index, "buildable_to", f.buildable_to);
510         // Liquids flow into and replace node
511         getboolfield(L, index, "floodable", f.floodable);
512         // Whether the node is non-liquid, source liquid or flowing liquid
513         f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
514                         ScriptApiNode::es_LiquidType, LIQUID_NONE);
515         // If the content is liquid, this is the flowing version of the liquid.
516         getstringfield(L, index, "liquid_alternative_flowing",
517                         f.liquid_alternative_flowing);
518         // If the content is liquid, this is the source version of the liquid.
519         getstringfield(L, index, "liquid_alternative_source",
520                         f.liquid_alternative_source);
521         // Viscosity for fluid flow, ranging from 1 to 7, with
522         // 1 giving almost instantaneous propagation and 7 being
523         // the slowest possible
524         f.liquid_viscosity = getintfield_default(L, index,
525                         "liquid_viscosity", f.liquid_viscosity);
526         f.liquid_range = getintfield_default(L, index,
527                         "liquid_range", f.liquid_range);
528         f.leveled = getintfield_default(L, index, "leveled", f.leveled);
529
530         getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
531         f.drowning = getintfield_default(L, index,
532                         "drowning", f.drowning);
533         // Amount of light the node emits
534         f.light_source = getintfield_default(L, index,
535                         "light_source", f.light_source);
536         if (f.light_source > LIGHT_MAX) {
537                 warningstream << "Node " << f.name.c_str()
538                         << " had greater light_source than " << LIGHT_MAX
539                         << ", it was reduced." << std::endl;
540                 f.light_source = LIGHT_MAX;
541         }
542         f.damage_per_second = getintfield_default(L, index,
543                         "damage_per_second", f.damage_per_second);
544
545         lua_getfield(L, index, "node_box");
546         if(lua_istable(L, -1))
547                 f.node_box = read_nodebox(L, -1);
548         lua_pop(L, 1);
549
550         lua_getfield(L, index, "connects_to");
551         if (lua_istable(L, -1)) {
552                 int table = lua_gettop(L);
553                 lua_pushnil(L);
554                 while (lua_next(L, table) != 0) {
555                         // Value at -1
556                         f.connects_to.push_back(lua_tostring(L, -1));
557                         lua_pop(L, 1);
558                 }
559         }
560         lua_pop(L, 1);
561
562         lua_getfield(L, index, "connect_sides");
563         if (lua_istable(L, -1)) {
564                 int table = lua_gettop(L);
565                 lua_pushnil(L);
566                 while (lua_next(L, table) != 0) {
567                         // Value at -1
568                         std::string side(lua_tostring(L, -1));
569                         // Note faces are flipped to make checking easier
570                         if (side == "top")
571                                 f.connect_sides |= 2;
572                         else if (side == "bottom")
573                                 f.connect_sides |= 1;
574                         else if (side == "front")
575                                 f.connect_sides |= 16;
576                         else if (side == "left")
577                                 f.connect_sides |= 32;
578                         else if (side == "back")
579                                 f.connect_sides |= 4;
580                         else if (side == "right")
581                                 f.connect_sides |= 8;
582                         else
583                                 warningstream << "Unknown value for \"connect_sides\": "
584                                         << side << std::endl;
585                         lua_pop(L, 1);
586                 }
587         }
588         lua_pop(L, 1);
589
590         lua_getfield(L, index, "selection_box");
591         if(lua_istable(L, -1))
592                 f.selection_box = read_nodebox(L, -1);
593         lua_pop(L, 1);
594
595         lua_getfield(L, index, "collision_box");
596         if(lua_istable(L, -1))
597                 f.collision_box = read_nodebox(L, -1);
598         lua_pop(L, 1);
599
600         f.waving = getintfield_default(L, index,
601                         "waving", f.waving);
602
603         // Set to true if paramtype used to be 'facedir_simple'
604         getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
605         // Set to true if wall_mounted used to be set to true
606         getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
607
608         // Sound table
609         lua_getfield(L, index, "sounds");
610         if(lua_istable(L, -1)){
611                 lua_getfield(L, -1, "footstep");
612                 read_soundspec(L, -1, f.sound_footstep);
613                 lua_pop(L, 1);
614                 lua_getfield(L, -1, "dig");
615                 read_soundspec(L, -1, f.sound_dig);
616                 lua_pop(L, 1);
617                 lua_getfield(L, -1, "dug");
618                 read_soundspec(L, -1, f.sound_dug);
619                 lua_pop(L, 1);
620         }
621         lua_pop(L, 1);
622
623         return f;
624 }
625
626 /******************************************************************************/
627 void read_server_sound_params(lua_State *L, int index,
628                 ServerSoundParams &params)
629 {
630         if(index < 0)
631                 index = lua_gettop(L) + 1 + index;
632         // Clear
633         params = ServerSoundParams();
634         if(lua_istable(L, index)){
635                 getfloatfield(L, index, "gain", params.gain);
636                 getstringfield(L, index, "to_player", params.to_player);
637                 lua_getfield(L, index, "pos");
638                 if(!lua_isnil(L, -1)){
639                         v3f p = read_v3f(L, -1)*BS;
640                         params.pos = p;
641                         params.type = ServerSoundParams::SSP_POSITIONAL;
642                 }
643                 lua_pop(L, 1);
644                 lua_getfield(L, index, "object");
645                 if(!lua_isnil(L, -1)){
646                         ObjectRef *ref = ObjectRef::checkobject(L, -1);
647                         ServerActiveObject *sao = ObjectRef::getobject(ref);
648                         if(sao){
649                                 params.object = sao->getId();
650                                 params.type = ServerSoundParams::SSP_OBJECT;
651                         }
652                 }
653                 lua_pop(L, 1);
654                 params.max_hear_distance = BS*getfloatfield_default(L, index,
655                                 "max_hear_distance", params.max_hear_distance/BS);
656                 getboolfield(L, index, "loop", params.loop);
657         }
658 }
659
660 /******************************************************************************/
661 void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
662 {
663         if(index < 0)
664                 index = lua_gettop(L) + 1 + index;
665         if(lua_isnil(L, index)){
666         } else if(lua_istable(L, index)){
667                 getstringfield(L, index, "name", spec.name);
668                 getfloatfield(L, index, "gain", spec.gain);
669         } else if(lua_isstring(L, index)){
670                 spec.name = lua_tostring(L, index);
671         }
672 }
673
674 /******************************************************************************/
675 NodeBox read_nodebox(lua_State *L, int index)
676 {
677         NodeBox nodebox;
678         if(lua_istable(L, -1)){
679                 nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
680                                 ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR);
681
682 #define NODEBOXREAD(n, s) \
683         do { \
684                 lua_getfield(L, index, (s)); \
685                 if (lua_istable(L, -1)) \
686                         (n) = read_aabb3f(L, -1, BS); \
687                 lua_pop(L, 1); \
688         } while (0)
689
690 #define NODEBOXREADVEC(n, s) \
691         do { \
692                 lua_getfield(L, index, (s)); \
693                 if (lua_istable(L, -1)) \
694                         (n) = read_aabb3f_vector(L, -1, BS); \
695                 lua_pop(L, 1); \
696         } while (0)
697                 NODEBOXREADVEC(nodebox.fixed, "fixed");
698                 NODEBOXREAD(nodebox.wall_top, "wall_top");
699                 NODEBOXREAD(nodebox.wall_bottom, "wall_bottom");
700                 NODEBOXREAD(nodebox.wall_side, "wall_side");
701                 NODEBOXREADVEC(nodebox.connect_top, "connect_top");
702                 NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom");
703                 NODEBOXREADVEC(nodebox.connect_front, "connect_front");
704                 NODEBOXREADVEC(nodebox.connect_left, "connect_left");
705                 NODEBOXREADVEC(nodebox.connect_back, "connect_back");
706                 NODEBOXREADVEC(nodebox.connect_right, "connect_right");
707         }
708         return nodebox;
709 }
710
711 /******************************************************************************/
712 MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
713 {
714         lua_getfield(L, index, "name");
715         if (!lua_isstring(L, -1))
716                 throw LuaError("Node name is not set or is not a string!");
717         const char *name = lua_tostring(L, -1);
718         lua_pop(L, 1);
719
720         u8 param1 = 0;
721         lua_getfield(L, index, "param1");
722         if (!lua_isnil(L, -1))
723                 param1 = lua_tonumber(L, -1);
724         lua_pop(L, 1);
725
726         u8 param2 = 0;
727         lua_getfield(L, index, "param2");
728         if (!lua_isnil(L, -1))
729                 param2 = lua_tonumber(L, -1);
730         lua_pop(L, 1);
731
732         return MapNode(ndef, name, param1, param2);
733 }
734
735 /******************************************************************************/
736 void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
737 {
738         lua_newtable(L);
739         lua_pushstring(L, ndef->get(n).name.c_str());
740         lua_setfield(L, -2, "name");
741         lua_pushnumber(L, n.getParam1());
742         lua_setfield(L, -2, "param1");
743         lua_pushnumber(L, n.getParam2());
744         lua_setfield(L, -2, "param2");
745 }
746
747 /******************************************************************************/
748 void warn_if_field_exists(lua_State *L, int table,
749                 const char *name, const std::string &message)
750 {
751         lua_getfield(L, table, name);
752         if (!lua_isnil(L, -1)) {
753                 warningstream << "Field \"" << name << "\": "
754                                 << message << std::endl;
755                 infostream << script_get_backtrace(L) << std::endl;
756         }
757         lua_pop(L, 1);
758 }
759
760 /******************************************************************************/
761 int getenumfield(lua_State *L, int table,
762                 const char *fieldname, const EnumString *spec, int default_)
763 {
764         int result = default_;
765         string_to_enum(spec, result,
766                         getstringfield_default(L, table, fieldname, ""));
767         return result;
768 }
769
770 /******************************************************************************/
771 bool string_to_enum(const EnumString *spec, int &result,
772                 const std::string &str)
773 {
774         const EnumString *esp = spec;
775         while(esp->str){
776                 if(str == std::string(esp->str)){
777                         result = esp->num;
778                         return true;
779                 }
780                 esp++;
781         }
782         return false;
783 }
784
785 /******************************************************************************/
786 ItemStack read_item(lua_State* L, int index, IItemDefManager *idef)
787 {
788         if(index < 0)
789                 index = lua_gettop(L) + 1 + index;
790
791         if(lua_isnil(L, index))
792         {
793                 return ItemStack();
794         }
795         else if(lua_isuserdata(L, index))
796         {
797                 // Convert from LuaItemStack
798                 LuaItemStack *o = LuaItemStack::checkobject(L, index);
799                 return o->getItem();
800         }
801         else if(lua_isstring(L, index))
802         {
803                 // Convert from itemstring
804                 std::string itemstring = lua_tostring(L, index);
805                 try
806                 {
807                         ItemStack item;
808                         item.deSerialize(itemstring, idef);
809                         return item;
810                 }
811                 catch(SerializationError &e)
812                 {
813                         warningstream<<"unable to create item from itemstring"
814                                         <<": "<<itemstring<<std::endl;
815                         return ItemStack();
816                 }
817         }
818         else if(lua_istable(L, index))
819         {
820                 // Convert from table
821                 std::string name = getstringfield_default(L, index, "name", "");
822                 int count = getintfield_default(L, index, "count", 1);
823                 int wear = getintfield_default(L, index, "wear", 0);
824
825                 ItemStack istack(name, count, wear, idef);
826
827                 // BACKWARDS COMPATIBLITY
828                 std::string value = getstringfield_default(L, index, "metadata", "");
829                 istack.metadata.setString("", value);
830
831                 // Get meta
832                 lua_getfield(L, index, "meta");
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(key, value);
843                                 lua_pop(L, 1); // removes value, keeps key for next iteration
844                         }
845                 }
846
847                 return istack;
848         } else {
849                 throw LuaError("Expecting itemstack, itemstring, table or nil");
850         }
851 }
852
853 /******************************************************************************/
854 void push_tool_capabilities(lua_State *L,
855                 const ToolCapabilities &toolcap)
856 {
857         lua_newtable(L);
858         setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval);
859                 setintfield(L, -1, "max_drop_level", toolcap.max_drop_level);
860                 // Create groupcaps table
861                 lua_newtable(L);
862                 // For each groupcap
863                 for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
864                         i != toolcap.groupcaps.end(); i++) {
865                         // Create groupcap table
866                         lua_newtable(L);
867                         const std::string &name = i->first;
868                         const ToolGroupCap &groupcap = i->second;
869                         // Create subtable "times"
870                         lua_newtable(L);
871                         for (UNORDERED_MAP<int, float>::const_iterator
872                                         i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
873                                 lua_pushinteger(L, i->first);
874                                 lua_pushnumber(L, i->second);
875                                 lua_settable(L, -3);
876                         }
877                         // Set subtable "times"
878                         lua_setfield(L, -2, "times");
879                         // Set simple parameters
880                         setintfield(L, -1, "maxlevel", groupcap.maxlevel);
881                         setintfield(L, -1, "uses", groupcap.uses);
882                         // Insert groupcap table into groupcaps table
883                         lua_setfield(L, -2, name.c_str());
884                 }
885                 // Set groupcaps table
886                 lua_setfield(L, -2, "groupcaps");
887                 //Create damage_groups table
888                 lua_newtable(L);
889                 // For each damage group
890                 for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
891                         i != toolcap.damageGroups.end(); i++) {
892                         // Create damage group table
893                         lua_pushinteger(L, i->second);
894                         lua_setfield(L, -2, i->first.c_str());
895                 }
896                 lua_setfield(L, -2, "damage_groups");
897 }
898
899 /******************************************************************************/
900 void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
901 {
902         InventoryList *invlist = inv->getList(name);
903         if(invlist == NULL){
904                 lua_pushnil(L);
905                 return;
906         }
907         std::vector<ItemStack> items;
908         for(u32 i=0; i<invlist->getSize(); i++)
909                 items.push_back(invlist->getItem(i));
910         push_items(L, items);
911 }
912
913 /******************************************************************************/
914 void read_inventory_list(lua_State *L, int tableindex,
915                 Inventory *inv, const char *name, Server* srv, int forcesize)
916 {
917         if(tableindex < 0)
918                 tableindex = lua_gettop(L) + 1 + tableindex;
919         // If nil, delete list
920         if(lua_isnil(L, tableindex)){
921                 inv->deleteList(name);
922                 return;
923         }
924         // Otherwise set list
925         std::vector<ItemStack> items = read_items(L, tableindex,srv);
926         int listsize = (forcesize != -1) ? forcesize : items.size();
927         InventoryList *invlist = inv->addList(name, listsize);
928         int index = 0;
929         for(std::vector<ItemStack>::const_iterator
930                         i = items.begin(); i != items.end(); i++){
931                 if(forcesize != -1 && index == forcesize)
932                         break;
933                 invlist->changeItem(index, *i);
934                 index++;
935         }
936         while(forcesize != -1 && index < forcesize){
937                 invlist->deleteItem(index);
938                 index++;
939         }
940 }
941
942 /******************************************************************************/
943 struct TileAnimationParams read_animation_definition(lua_State *L, int index)
944 {
945         if(index < 0)
946                 index = lua_gettop(L) + 1 + index;
947
948         struct TileAnimationParams anim;
949         anim.type = TAT_NONE;
950         if (!lua_istable(L, index))
951                 return anim;
952
953         anim.type = (TileAnimationType)
954                 getenumfield(L, index, "type", es_TileAnimationType,
955                 TAT_NONE);
956         if (anim.type == TAT_VERTICAL_FRAMES) {
957                 // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
958                 anim.vertical_frames.aspect_w =
959                         getintfield_default(L, index, "aspect_w", 16);
960                 anim.vertical_frames.aspect_h =
961                         getintfield_default(L, index, "aspect_h", 16);
962                 anim.vertical_frames.length =
963                         getfloatfield_default(L, index, "length", 1.0);
964         } else if (anim.type == TAT_SHEET_2D) {
965                 // {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
966                 getintfield(L, index, "frames_w",
967                         anim.sheet_2d.frames_w);
968                 getintfield(L, index, "frames_h",
969                         anim.sheet_2d.frames_h);
970                 getfloatfield(L, index, "frame_length",
971                         anim.sheet_2d.frame_length);
972         }
973
974         return anim;
975 }
976
977 /******************************************************************************/
978 ToolCapabilities read_tool_capabilities(
979                 lua_State *L, int table)
980 {
981         ToolCapabilities toolcap;
982         getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
983         getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
984         lua_getfield(L, table, "groupcaps");
985         if(lua_istable(L, -1)){
986                 int table_groupcaps = lua_gettop(L);
987                 lua_pushnil(L);
988                 while(lua_next(L, table_groupcaps) != 0){
989                         // key at index -2 and value at index -1
990                         std::string groupname = luaL_checkstring(L, -2);
991                         if(lua_istable(L, -1)){
992                                 int table_groupcap = lua_gettop(L);
993                                 // This will be created
994                                 ToolGroupCap groupcap;
995                                 // Read simple parameters
996                                 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
997                                 getintfield(L, table_groupcap, "uses", groupcap.uses);
998                                 // DEPRECATED: maxwear
999                                 float maxwear = 0;
1000                                 if (getfloatfield(L, table_groupcap, "maxwear", maxwear)){
1001                                         if (maxwear != 0)
1002                                                 groupcap.uses = 1.0/maxwear;
1003                                         else
1004                                                 groupcap.uses = 0;
1005                                         warningstream << "Field \"maxwear\" is deprecated; "
1006                                                         << "replace with uses=1/maxwear" << std::endl;
1007                                         infostream << script_get_backtrace(L) << std::endl;
1008                                 }
1009                                 // Read "times" table
1010                                 lua_getfield(L, table_groupcap, "times");
1011                                 if(lua_istable(L, -1)){
1012                                         int table_times = lua_gettop(L);
1013                                         lua_pushnil(L);
1014                                         while(lua_next(L, table_times) != 0){
1015                                                 // key at index -2 and value at index -1
1016                                                 int rating = luaL_checkinteger(L, -2);
1017                                                 float time = luaL_checknumber(L, -1);
1018                                                 groupcap.times[rating] = time;
1019                                                 // removes value, keeps key for next iteration
1020                                                 lua_pop(L, 1);
1021                                         }
1022                                 }
1023                                 lua_pop(L, 1);
1024                                 // Insert groupcap into toolcap
1025                                 toolcap.groupcaps[groupname] = groupcap;
1026                         }
1027                         // removes value, keeps key for next iteration
1028                         lua_pop(L, 1);
1029                 }
1030         }
1031         lua_pop(L, 1);
1032
1033         lua_getfield(L, table, "damage_groups");
1034         if(lua_istable(L, -1)){
1035                 int table_damage_groups = lua_gettop(L);
1036                 lua_pushnil(L);
1037                 while(lua_next(L, table_damage_groups) != 0){
1038                         // key at index -2 and value at index -1
1039                         std::string groupname = luaL_checkstring(L, -2);
1040                         u16 value = luaL_checkinteger(L, -1);
1041                         toolcap.damageGroups[groupname] = value;
1042                         // removes value, keeps key for next iteration
1043                         lua_pop(L, 1);
1044                 }
1045         }
1046         lua_pop(L, 1);
1047         return toolcap;
1048 }
1049
1050 /******************************************************************************/
1051 void push_dig_params(lua_State *L,const DigParams &params)
1052 {
1053         lua_newtable(L);
1054         setboolfield(L, -1, "diggable", params.diggable);
1055         setfloatfield(L, -1, "time", params.time);
1056         setintfield(L, -1, "wear", params.wear);
1057 }
1058
1059 /******************************************************************************/
1060 void push_hit_params(lua_State *L,const HitParams &params)
1061 {
1062         lua_newtable(L);
1063         setintfield(L, -1, "hp", params.hp);
1064         setintfield(L, -1, "wear", params.wear);
1065 }
1066
1067 /******************************************************************************/
1068
1069 bool getflagsfield(lua_State *L, int table, const char *fieldname,
1070         FlagDesc *flagdesc, u32 *flags, u32 *flagmask)
1071 {
1072         lua_getfield(L, table, fieldname);
1073
1074         bool success = read_flags(L, -1, flagdesc, flags, flagmask);
1075
1076         lua_pop(L, 1);
1077
1078         return success;
1079 }
1080
1081 bool read_flags(lua_State *L, int index, FlagDesc *flagdesc,
1082         u32 *flags, u32 *flagmask)
1083 {
1084         if (lua_isstring(L, index)) {
1085                 std::string flagstr = lua_tostring(L, index);
1086                 *flags = readFlagString(flagstr, flagdesc, flagmask);
1087         } else if (lua_istable(L, index)) {
1088                 *flags = read_flags_table(L, index, flagdesc, flagmask);
1089         } else {
1090                 return false;
1091         }
1092
1093         return true;
1094 }
1095
1096 u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
1097 {
1098         u32 flags = 0, mask = 0;
1099         char fnamebuf[64] = "no";
1100
1101         for (int i = 0; flagdesc[i].name; i++) {
1102                 bool result;
1103
1104                 if (getboolfield(L, table, flagdesc[i].name, result)) {
1105                         mask |= flagdesc[i].flag;
1106                         if (result)
1107                                 flags |= flagdesc[i].flag;
1108                 }
1109
1110                 strlcpy(fnamebuf + 2, flagdesc[i].name, sizeof(fnamebuf) - 2);
1111                 if (getboolfield(L, table, fnamebuf, result))
1112                         mask |= flagdesc[i].flag;
1113         }
1114
1115         if (flagmask)
1116                 *flagmask = mask;
1117
1118         return flags;
1119 }
1120
1121 void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask)
1122 {
1123         std::string flagstring = writeFlagString(flags, flagdesc, flagmask);
1124         lua_pushlstring(L, flagstring.c_str(), flagstring.size());
1125 }
1126
1127 /******************************************************************************/
1128 /* Lua Stored data!                                                           */
1129 /******************************************************************************/
1130
1131 /******************************************************************************/
1132 void read_groups(lua_State *L, int index, ItemGroupList &result)
1133 {
1134         if (!lua_istable(L,index))
1135                 return;
1136         result.clear();
1137         lua_pushnil(L);
1138         if(index < 0)
1139                 index -= 1;
1140         while(lua_next(L, index) != 0){
1141                 // key at index -2 and value at index -1
1142                 std::string name = luaL_checkstring(L, -2);
1143                 int rating = luaL_checkinteger(L, -1);
1144                 result[name] = rating;
1145                 // removes value, keeps key for next iteration
1146                 lua_pop(L, 1);
1147         }
1148 }
1149
1150 /******************************************************************************/
1151 void push_groups(lua_State *L, const ItemGroupList &groups)
1152 {
1153         lua_newtable(L);
1154         for (ItemGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it) {
1155                 lua_pushnumber(L, it->second);
1156                 lua_setfield(L, -2, it->first.c_str());
1157         }
1158 }
1159
1160 /******************************************************************************/
1161 void push_items(lua_State *L, const std::vector<ItemStack> &items)
1162 {
1163         lua_createtable(L, items.size(), 0);
1164         for (u32 i = 0; i != items.size(); i++) {
1165                 LuaItemStack::create(L, items[i]);
1166                 lua_rawseti(L, -2, i + 1);
1167         }
1168 }
1169
1170 /******************************************************************************/
1171 std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
1172 {
1173         if(index < 0)
1174                 index = lua_gettop(L) + 1 + index;
1175
1176         std::vector<ItemStack> items;
1177         luaL_checktype(L, index, LUA_TTABLE);
1178         lua_pushnil(L);
1179         while (lua_next(L, index)) {
1180                 s32 key = luaL_checkinteger(L, -2);
1181                 if (key < 1) {
1182                         throw LuaError("Invalid inventory list index");
1183                 }
1184                 if (items.size() < (u32) key) {
1185                         items.resize(key);
1186                 }
1187                 items[key - 1] = read_item(L, -1, srv->idef());
1188                 lua_pop(L, 1);
1189         }
1190         return items;
1191 }
1192
1193 /******************************************************************************/
1194 void luaentity_get(lua_State *L, u16 id)
1195 {
1196         // Get luaentities[i]
1197         lua_getglobal(L, "core");
1198         lua_getfield(L, -1, "luaentities");
1199         luaL_checktype(L, -1, LUA_TTABLE);
1200         lua_pushnumber(L, id);
1201         lua_gettable(L, -2);
1202         lua_remove(L, -2); // Remove luaentities
1203         lua_remove(L, -2); // Remove core
1204 }
1205
1206 /******************************************************************************/
1207 bool read_noiseparams(lua_State *L, int index, NoiseParams *np)
1208 {
1209         if (index < 0)
1210                 index = lua_gettop(L) + 1 + index;
1211
1212         if (!lua_istable(L, index))
1213                 return false;
1214
1215         getfloatfield(L, index, "offset",      np->offset);
1216         getfloatfield(L, index, "scale",       np->scale);
1217         getfloatfield(L, index, "persist",     np->persist);
1218         getfloatfield(L, index, "persistence", np->persist);
1219         getfloatfield(L, index, "lacunarity",  np->lacunarity);
1220         getintfield(L,   index, "seed",        np->seed);
1221         getintfield(L,   index, "octaves",     np->octaves);
1222
1223         u32 flags    = 0;
1224         u32 flagmask = 0;
1225         np->flags = getflagsfield(L, index, "flags", flagdesc_noiseparams,
1226                 &flags, &flagmask) ? flags : NOISE_FLAG_DEFAULTS;
1227
1228         lua_getfield(L, index, "spread");
1229         np->spread  = read_v3f(L, -1);
1230         lua_pop(L, 1);
1231
1232         return true;
1233 }
1234
1235 void push_noiseparams(lua_State *L, NoiseParams *np)
1236 {
1237         lua_newtable(L);
1238         lua_pushnumber(L, np->offset);
1239         lua_setfield(L, -2, "offset");
1240         lua_pushnumber(L, np->scale);
1241         lua_setfield(L, -2, "scale");
1242         lua_pushnumber(L, np->persist);
1243         lua_setfield(L, -2, "persistence");
1244         lua_pushnumber(L, np->lacunarity);
1245         lua_setfield(L, -2, "lacunarity");
1246         lua_pushnumber(L, np->seed);
1247         lua_setfield(L, -2, "seed");
1248         lua_pushnumber(L, np->octaves);
1249         lua_setfield(L, -2, "octaves");
1250
1251         push_flags_string(L, flagdesc_noiseparams, np->flags,
1252                 np->flags);
1253         lua_setfield(L, -2, "flags");
1254
1255         push_v3f(L, np->spread);
1256         lua_setfield(L, -2, "spread");
1257 }
1258
1259 /******************************************************************************/
1260 // Returns depth of json value tree
1261 static int push_json_value_getdepth(const Json::Value &value)
1262 {
1263         if (!value.isArray() && !value.isObject())
1264                 return 1;
1265
1266         int maxdepth = 0;
1267         for (Json::Value::const_iterator it = value.begin();
1268                         it != value.end(); ++it) {
1269                 int elemdepth = push_json_value_getdepth(*it);
1270                 if (elemdepth > maxdepth)
1271                         maxdepth = elemdepth;
1272         }
1273         return maxdepth + 1;
1274 }
1275 // Recursive function to convert JSON --> Lua table
1276 static bool push_json_value_helper(lua_State *L, const Json::Value &value,
1277                 int nullindex)
1278 {
1279         switch(value.type()) {
1280                 case Json::nullValue:
1281                 default:
1282                         lua_pushvalue(L, nullindex);
1283                         break;
1284                 case Json::intValue:
1285                         lua_pushinteger(L, value.asInt());
1286                         break;
1287                 case Json::uintValue:
1288                         lua_pushinteger(L, value.asUInt());
1289                         break;
1290                 case Json::realValue:
1291                         lua_pushnumber(L, value.asDouble());
1292                         break;
1293                 case Json::stringValue:
1294                         {
1295                                 const char *str = value.asCString();
1296                                 lua_pushstring(L, str ? str : "");
1297                         }
1298                         break;
1299                 case Json::booleanValue:
1300                         lua_pushboolean(L, value.asInt());
1301                         break;
1302                 case Json::arrayValue:
1303                         lua_newtable(L);
1304                         for (Json::Value::const_iterator it = value.begin();
1305                                         it != value.end(); ++it) {
1306                                 push_json_value_helper(L, *it, nullindex);
1307                                 lua_rawseti(L, -2, it.index() + 1);
1308                         }
1309                         break;
1310                 case Json::objectValue:
1311                         lua_newtable(L);
1312                         for (Json::Value::const_iterator it = value.begin();
1313                                         it != value.end(); ++it) {
1314 #ifndef JSONCPP_STRING
1315                                 const char *str = it.memberName();
1316                                 lua_pushstring(L, str ? str : "");
1317 #else
1318                                 std::string str = it.name();
1319                                 lua_pushstring(L, str.c_str());
1320 #endif
1321                                 push_json_value_helper(L, *it, nullindex);
1322                                 lua_rawset(L, -3);
1323                         }
1324                         break;
1325         }
1326         return true;
1327 }
1328 // converts JSON --> Lua table; returns false if lua stack limit exceeded
1329 // nullindex: Lua stack index of value to use in place of JSON null
1330 bool push_json_value(lua_State *L, const Json::Value &value, int nullindex)
1331 {
1332         if(nullindex < 0)
1333                 nullindex = lua_gettop(L) + 1 + nullindex;
1334
1335         int depth = push_json_value_getdepth(value);
1336
1337         // The maximum number of Lua stack slots used at each recursion level
1338         // of push_json_value_helper is 2, so make sure there a depth * 2 slots
1339         if (lua_checkstack(L, depth * 2))
1340                 return push_json_value_helper(L, value, nullindex);
1341         else
1342                 return false;
1343 }
1344
1345 // Converts Lua table --> JSON
1346 void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion)
1347 {
1348         if (recursion > 16) {
1349                 throw SerializationError("Maximum recursion depth exceeded");
1350         }
1351         int type = lua_type(L, index);
1352         if (type == LUA_TBOOLEAN) {
1353                 root = (bool) lua_toboolean(L, index);
1354         } else if (type == LUA_TNUMBER) {
1355                 root = lua_tonumber(L, index);
1356         } else if (type == LUA_TSTRING) {
1357                 size_t len;
1358                 const char *str = lua_tolstring(L, index, &len);
1359                 root = std::string(str, len);
1360         } else if (type == LUA_TTABLE) {
1361                 lua_pushnil(L);
1362                 while (lua_next(L, index)) {
1363                         // Key is at -2 and value is at -1
1364                         Json::Value value;
1365                         read_json_value(L, value, lua_gettop(L), recursion + 1);
1366
1367                         Json::ValueType roottype = root.type();
1368                         int keytype = lua_type(L, -1);
1369                         if (keytype == LUA_TNUMBER) {
1370                                 lua_Number key = lua_tonumber(L, -1);
1371                                 if (roottype != Json::nullValue && roottype != Json::arrayValue) {
1372                                         throw SerializationError("Can't mix array and object values in JSON");
1373                                 } else if (key < 1) {
1374                                         throw SerializationError("Can't use zero-based or negative indexes in JSON");
1375                                 } else if (floor(key) != key) {
1376                                         throw SerializationError("Can't use indexes with a fractional part in JSON");
1377                                 }
1378                                 root[(Json::ArrayIndex) key - 1] = value;
1379                         } else if (keytype == LUA_TSTRING) {
1380                                 if (roottype != Json::nullValue && roottype != Json::objectValue) {
1381                                         throw SerializationError("Can't mix array and object values in JSON");
1382                                 }
1383                                 root[lua_tostring(L, -1)] = value;
1384                         } else {
1385                                 throw SerializationError("Lua key to convert to JSON is not a string or number");
1386                         }
1387                 }
1388         } else if (type == LUA_TNIL) {
1389                 root = Json::nullValue;
1390         } else {
1391                 throw SerializationError("Can only store booleans, numbers, strings, objects, arrays, and null in JSON");
1392         }
1393         lua_pop(L, 1); // Pop value
1394 }