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