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