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