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