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