cb2b0e737ae68b96c292de4fd1e16aaa22123552
[oweals/minetest.git] / src / script / common / c_content.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 #include "common/c_content.h"
20 #include "common/c_converter.h"
21 #include "common/c_types.h"
22 #include "nodedef.h"
23 #include "itemdef.h"
24 #include "object_properties.h"
25 #include "cpp_api/s_node.h"
26 #include "lua_api/l_object.h"
27 #include "lua_api/l_item.h"
28 #include "common/c_internal.h"
29 #include "server.h"
30 #include "log.h"
31 #include "tool.h"
32 #include "server.h"
33 #include "mapgen.h"
34
35 struct EnumString es_TileAnimationType[] =
36 {
37         {TAT_NONE, "none"},
38         {TAT_VERTICAL_FRAMES, "vertical_frames"},
39         {0, NULL},
40 };
41
42 /******************************************************************************/
43 ItemDefinition read_item_definition(lua_State* L,int index,
44                 ItemDefinition default_def)
45 {
46         if(index < 0)
47                 index = lua_gettop(L) + 1 + index;
48
49         // Read the item definition
50         ItemDefinition def = default_def;
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
59         lua_getfield(L, index, "wield_scale");
60         if(lua_istable(L, -1)){
61                 def.wield_scale = check_v3f(L, -1);
62         }
63         lua_pop(L, 1);
64
65         def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
66         if(def.stack_max == 0)
67                 def.stack_max = 1;
68
69         lua_getfield(L, index, "on_use");
70         def.usable = lua_isfunction(L, -1);
71         lua_pop(L, 1);
72
73         getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
74
75         warn_if_field_exists(L, index, "tool_digging_properties",
76                         "deprecated: use tool_capabilities");
77
78         lua_getfield(L, index, "tool_capabilities");
79         if(lua_istable(L, -1)){
80                 def.tool_capabilities = new ToolCapabilities(
81                                 read_tool_capabilities(L, -1));
82         }
83
84         // If name is "" (hand), ensure there are ToolCapabilities
85         // because it will be looked up there whenever any other item has
86         // no ToolCapabilities
87         if(def.name == "" && def.tool_capabilities == NULL){
88                 def.tool_capabilities = new ToolCapabilities();
89         }
90
91         lua_getfield(L, index, "groups");
92         read_groups(L, -1, def.groups);
93         lua_pop(L, 1);
94
95         lua_getfield(L, index, "sounds");
96         if(lua_istable(L, -1)){
97                 lua_getfield(L, -1, "place");
98                 read_soundspec(L, -1, def.sound_place);
99                 lua_pop(L, 1);
100         }
101         lua_pop(L, 1);
102
103         def.range = getfloatfield_default(L, index, "range", def.range);
104
105         // Client shall immediately place this node when player places the item.
106         // Server will update the precise end result a moment later.
107         // "" = no prediction
108         getstringfield(L, index, "node_placement_prediction",
109                         def.node_placement_prediction);
110
111         return def;
112 }
113
114 /******************************************************************************/
115 void read_object_properties(lua_State *L, int index,
116                 ObjectProperties *prop)
117 {
118         if(index < 0)
119                 index = lua_gettop(L) + 1 + index;
120         if(!lua_istable(L, index))
121                 return;
122
123         prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
124
125         getboolfield(L, -1, "physical", prop->physical);
126         getboolfield(L, -1, "collide_with_objects", prop->collideWithObjects);
127
128         getfloatfield(L, -1, "weight", prop->weight);
129
130         lua_getfield(L, -1, "collisionbox");
131         if(lua_istable(L, -1))
132                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
133         lua_pop(L, 1);
134
135         getstringfield(L, -1, "visual", prop->visual);
136
137         getstringfield(L, -1, "mesh", prop->mesh);
138
139         lua_getfield(L, -1, "visual_size");
140         if(lua_istable(L, -1))
141                 prop->visual_size = read_v2f(L, -1);
142         lua_pop(L, 1);
143
144         lua_getfield(L, -1, "textures");
145         if(lua_istable(L, -1)){
146                 prop->textures.clear();
147                 int table = lua_gettop(L);
148                 lua_pushnil(L);
149                 while(lua_next(L, table) != 0){
150                         // key at index -2 and value at index -1
151                         if(lua_isstring(L, -1))
152                                 prop->textures.push_back(lua_tostring(L, -1));
153                         else
154                                 prop->textures.push_back("");
155                         // removes value, keeps key for next iteration
156                         lua_pop(L, 1);
157                 }
158         }
159         lua_pop(L, 1);
160
161         lua_getfield(L, -1, "colors");
162         if(lua_istable(L, -1)){
163                 prop->colors.clear();
164                 int table = lua_gettop(L);
165                 lua_pushnil(L);
166                 while(lua_next(L, table) != 0){
167                         // key at index -2 and value at index -1
168                         if(lua_isstring(L, -1))
169                                 prop->colors.push_back(readARGB8(L, -1));
170                         else
171                                 prop->colors.push_back(video::SColor(255, 255, 255, 255));
172                         // removes value, keeps key for next iteration
173                         lua_pop(L, 1);
174                 }
175         }
176         lua_pop(L, 1);
177
178         lua_getfield(L, -1, "spritediv");
179         if(lua_istable(L, -1))
180                 prop->spritediv = read_v2s16(L, -1);
181         lua_pop(L, 1);
182
183         lua_getfield(L, -1, "initial_sprite_basepos");
184         if(lua_istable(L, -1))
185                 prop->initial_sprite_basepos = read_v2s16(L, -1);
186         lua_pop(L, 1);
187
188         getboolfield(L, -1, "is_visible", prop->is_visible);
189         getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
190         getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
191         getfloatfield(L, -1, "stepheight", prop->stepheight);
192         prop->stepheight*=BS;
193         getboolfield(L, -1, "automatic_face_movement_dir", prop->automatic_face_movement_dir);
194 }
195
196 /******************************************************************************/
197 TileDef read_tiledef(lua_State *L, int index)
198 {
199         if(index < 0)
200                 index = lua_gettop(L) + 1 + index;
201
202         TileDef tiledef;
203
204         // key at index -2 and value at index
205         if(lua_isstring(L, index)){
206                 // "default_lava.png"
207                 tiledef.name = lua_tostring(L, index);
208         }
209         else if(lua_istable(L, index))
210         {
211                 // {name="default_lava.png", animation={}}
212                 tiledef.name = "";
213                 getstringfield(L, index, "name", tiledef.name);
214                 getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
215                 tiledef.backface_culling = getboolfield_default(
216                                         L, index, "backface_culling", true);
217                 // animation = {}
218                 lua_getfield(L, index, "animation");
219                 if(lua_istable(L, -1)){
220                         // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
221                         tiledef.animation.type = (TileAnimationType)
222                                         getenumfield(L, -1, "type", es_TileAnimationType,
223                                         TAT_NONE);
224                         tiledef.animation.aspect_w =
225                                         getintfield_default(L, -1, "aspect_w", 16);
226                         tiledef.animation.aspect_h =
227                                         getintfield_default(L, -1, "aspect_h", 16);
228                         tiledef.animation.length =
229                                         getfloatfield_default(L, -1, "length", 1.0);
230                 }
231                 lua_pop(L, 1);
232         }
233
234         return tiledef;
235 }
236
237 /******************************************************************************/
238 ContentFeatures read_content_features(lua_State *L, int index)
239 {
240         if(index < 0)
241                 index = lua_gettop(L) + 1 + index;
242
243         ContentFeatures f;
244
245         /* Cache existence of some callbacks */
246         lua_getfield(L, index, "on_construct");
247         if(!lua_isnil(L, -1)) f.has_on_construct = true;
248         lua_pop(L, 1);
249         lua_getfield(L, index, "on_destruct");
250         if(!lua_isnil(L, -1)) f.has_on_destruct = true;
251         lua_pop(L, 1);
252         lua_getfield(L, index, "after_destruct");
253         if(!lua_isnil(L, -1)) f.has_after_destruct = true;
254         lua_pop(L, 1);
255
256         lua_getfield(L, index, "on_rightclick");
257         f.rightclickable = lua_isfunction(L, -1);
258         lua_pop(L, 1);
259         
260         /* Name */
261         getstringfield(L, index, "name", f.name);
262
263         /* Groups */
264         lua_getfield(L, index, "groups");
265         read_groups(L, -1, f.groups);
266         lua_pop(L, 1);
267
268         /* Visual definition */
269
270         f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype",
271                         ScriptApiNode::es_DrawType,NDT_NORMAL);
272         getfloatfield(L, index, "visual_scale", f.visual_scale);
273
274         // tiles = {}
275         lua_getfield(L, index, "tiles");
276         // If nil, try the deprecated name "tile_images" instead
277         if(lua_isnil(L, -1)){
278                 lua_pop(L, 1);
279                 warn_if_field_exists(L, index, "tile_images",
280                                 "Deprecated; new name is \"tiles\".");
281                 lua_getfield(L, index, "tile_images");
282         }
283         if(lua_istable(L, -1)){
284                 int table = lua_gettop(L);
285                 lua_pushnil(L);
286                 int i = 0;
287                 while(lua_next(L, table) != 0){
288                         // Read tiledef from value
289                         f.tiledef[i] = read_tiledef(L, -1);
290                         // removes value, keeps key for next iteration
291                         lua_pop(L, 1);
292                         i++;
293                         if(i==6){
294                                 lua_pop(L, 1);
295                                 break;
296                         }
297                 }
298                 // Copy last value to all remaining textures
299                 if(i >= 1){
300                         TileDef lasttile = f.tiledef[i-1];
301                         while(i < 6){
302                                 f.tiledef[i] = lasttile;
303                                 i++;
304                         }
305                 }
306         }
307         lua_pop(L, 1);
308
309         // special_tiles = {}
310         lua_getfield(L, index, "special_tiles");
311         // If nil, try the deprecated name "special_materials" instead
312         if(lua_isnil(L, -1)){
313                 lua_pop(L, 1);
314                 warn_if_field_exists(L, index, "special_materials",
315                                 "Deprecated; new name is \"special_tiles\".");
316                 lua_getfield(L, index, "special_materials");
317         }
318         if(lua_istable(L, -1)){
319                 int table = lua_gettop(L);
320                 lua_pushnil(L);
321                 int i = 0;
322                 while(lua_next(L, table) != 0){
323                         // Read tiledef from value
324                         f.tiledef_special[i] = read_tiledef(L, -1);
325                         // removes value, keeps key for next iteration
326                         lua_pop(L, 1);
327                         i++;
328                         if(i==6){
329                                 lua_pop(L, 1);
330                                 break;
331                         }
332                 }
333         }
334         lua_pop(L, 1);
335
336         f.alpha = getintfield_default(L, index, "alpha", 255);
337
338         bool usealpha = getboolfield_default(L, index,
339                         "use_texture_alpha", false);
340         if (usealpha)
341                 f.alpha = 0;
342
343         /* Other stuff */
344
345         lua_getfield(L, index, "post_effect_color");
346         if(!lua_isnil(L, -1))
347                 f.post_effect_color = readARGB8(L, -1);
348         lua_pop(L, 1);
349
350         f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
351                         ScriptApiNode::es_ContentParamType, CPT_NONE);
352         f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
353                         ScriptApiNode::es_ContentParamType2, CPT2_NONE);
354
355         // Warn about some deprecated fields
356         warn_if_field_exists(L, index, "wall_mounted",
357                         "deprecated: use paramtype2 = 'wallmounted'");
358         warn_if_field_exists(L, index, "light_propagates",
359                         "deprecated: determined from paramtype");
360         warn_if_field_exists(L, index, "dug_item",
361                         "deprecated: use 'drop' field");
362         warn_if_field_exists(L, index, "extra_dug_item",
363                         "deprecated: use 'drop' field");
364         warn_if_field_exists(L, index, "extra_dug_item_rarity",
365                         "deprecated: use 'drop' field");
366         warn_if_field_exists(L, index, "metadata_name",
367                         "deprecated: use on_add and metadata callbacks");
368
369         // True for all ground-like things like stone and mud, false for eg. trees
370         getboolfield(L, index, "is_ground_content", f.is_ground_content);
371         f.light_propagates = (f.param_type == CPT_LIGHT);
372         getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
373         // This is used for collision detection.
374         // Also for general solidness queries.
375         getboolfield(L, index, "walkable", f.walkable);
376         // Player can point to these
377         getboolfield(L, index, "pointable", f.pointable);
378         // Player can dig these
379         getboolfield(L, index, "diggable", f.diggable);
380         // Player can climb these
381         getboolfield(L, index, "climbable", f.climbable);
382         // Player can build on these
383         getboolfield(L, index, "buildable_to", f.buildable_to);
384         // Whether the node is non-liquid, source liquid or flowing liquid
385         f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
386                         ScriptApiNode::es_LiquidType, LIQUID_NONE);
387         // If the content is liquid, this is the flowing version of the liquid.
388         getstringfield(L, index, "liquid_alternative_flowing",
389                         f.liquid_alternative_flowing);
390         // If the content is liquid, this is the source version of the liquid.
391         getstringfield(L, index, "liquid_alternative_source",
392                         f.liquid_alternative_source);
393         // Viscosity for fluid flow, ranging from 1 to 7, with
394         // 1 giving almost instantaneous propagation and 7 being
395         // the slowest possible
396         f.liquid_viscosity = getintfield_default(L, index,
397                         "liquid_viscosity", f.liquid_viscosity);
398         f.liquid_range = getintfield_default(L, index,
399                         "liquid_range", f.liquid_range);
400         f.leveled = getintfield_default(L, index, "leveled", f.leveled);
401
402         getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
403         getstringfield(L, index, "freezemelt", f.freezemelt);
404         f.drowning = getintfield_default(L, index,
405                         "drowning", f.drowning);
406         // Amount of light the node emits
407         f.light_source = getintfield_default(L, index,
408                         "light_source", f.light_source);
409         f.damage_per_second = getintfield_default(L, index,
410                         "damage_per_second", f.damage_per_second);
411
412         lua_getfield(L, index, "node_box");
413         if(lua_istable(L, -1))
414                 f.node_box = read_nodebox(L, -1);
415         lua_pop(L, 1);
416
417         lua_getfield(L, index, "selection_box");
418         if(lua_istable(L, -1))
419                 f.selection_box = read_nodebox(L, -1);
420         lua_pop(L, 1);
421
422         // Set to true if paramtype used to be 'facedir_simple'
423         getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
424         // Set to true if wall_mounted used to be set to true
425         getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
426
427         // Sound table
428         lua_getfield(L, index, "sounds");
429         if(lua_istable(L, -1)){
430                 lua_getfield(L, -1, "footstep");
431                 read_soundspec(L, -1, f.sound_footstep);
432                 lua_pop(L, 1);
433                 lua_getfield(L, -1, "dig");
434                 read_soundspec(L, -1, f.sound_dig);
435                 lua_pop(L, 1);
436                 lua_getfield(L, -1, "dug");
437                 read_soundspec(L, -1, f.sound_dug);
438                 lua_pop(L, 1);
439         }
440         lua_pop(L, 1);
441
442         return f;
443 }
444
445 /******************************************************************************/
446 void read_server_sound_params(lua_State *L, int index,
447                 ServerSoundParams &params)
448 {
449         if(index < 0)
450                 index = lua_gettop(L) + 1 + index;
451         // Clear
452         params = ServerSoundParams();
453         if(lua_istable(L, index)){
454                 getfloatfield(L, index, "gain", params.gain);
455                 getstringfield(L, index, "to_player", params.to_player);
456                 lua_getfield(L, index, "pos");
457                 if(!lua_isnil(L, -1)){
458                         v3f p = read_v3f(L, -1)*BS;
459                         params.pos = p;
460                         params.type = ServerSoundParams::SSP_POSITIONAL;
461                 }
462                 lua_pop(L, 1);
463                 lua_getfield(L, index, "object");
464                 if(!lua_isnil(L, -1)){
465                         ObjectRef *ref = ObjectRef::checkobject(L, -1);
466                         ServerActiveObject *sao = ObjectRef::getobject(ref);
467                         if(sao){
468                                 params.object = sao->getId();
469                                 params.type = ServerSoundParams::SSP_OBJECT;
470                         }
471                 }
472                 lua_pop(L, 1);
473                 params.max_hear_distance = BS*getfloatfield_default(L, index,
474                                 "max_hear_distance", params.max_hear_distance/BS);
475                 getboolfield(L, index, "loop", params.loop);
476         }
477 }
478
479 /******************************************************************************/
480 void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
481 {
482         if(index < 0)
483                 index = lua_gettop(L) + 1 + index;
484         if(lua_isnil(L, index)){
485         } else if(lua_istable(L, index)){
486                 getstringfield(L, index, "name", spec.name);
487                 getfloatfield(L, index, "gain", spec.gain);
488         } else if(lua_isstring(L, index)){
489                 spec.name = lua_tostring(L, index);
490         }
491 }
492
493 /******************************************************************************/
494 NodeBox read_nodebox(lua_State *L, int index)
495 {
496         NodeBox nodebox;
497         if(lua_istable(L, -1)){
498                 nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
499                                 ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR);
500
501                 lua_getfield(L, index, "fixed");
502                 if(lua_istable(L, -1))
503                         nodebox.fixed = read_aabb3f_vector(L, -1, BS);
504                 lua_pop(L, 1);
505
506                 lua_getfield(L, index, "wall_top");
507                 if(lua_istable(L, -1))
508                         nodebox.wall_top = read_aabb3f(L, -1, BS);
509                 lua_pop(L, 1);
510
511                 lua_getfield(L, index, "wall_bottom");
512                 if(lua_istable(L, -1))
513                         nodebox.wall_bottom = read_aabb3f(L, -1, BS);
514                 lua_pop(L, 1);
515
516                 lua_getfield(L, index, "wall_side");
517                 if(lua_istable(L, -1))
518                         nodebox.wall_side = read_aabb3f(L, -1, BS);
519                 lua_pop(L, 1);
520         }
521         return nodebox;
522 }
523
524 /******************************************************************************/
525 MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
526 {
527         lua_getfield(L, index, "name");
528         const char *name = luaL_checkstring(L, -1);
529         lua_pop(L, 1);
530         u8 param1;
531         lua_getfield(L, index, "param1");
532         if(lua_isnil(L, -1))
533                 param1 = 0;
534         else
535                 param1 = lua_tonumber(L, -1);
536         lua_pop(L, 1);
537         u8 param2;
538         lua_getfield(L, index, "param2");
539         if(lua_isnil(L, -1))
540                 param2 = 0;
541         else
542                 param2 = lua_tonumber(L, -1);
543         lua_pop(L, 1);
544         return MapNode(ndef, name, param1, param2);
545 }
546
547 /******************************************************************************/
548 void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
549 {
550         lua_newtable(L);
551         lua_pushstring(L, ndef->get(n).name.c_str());
552         lua_setfield(L, -2, "name");
553         lua_pushnumber(L, n.getParam1());
554         lua_setfield(L, -2, "param1");
555         lua_pushnumber(L, n.getParam2());
556         lua_setfield(L, -2, "param2");
557 }
558
559 /******************************************************************************/
560 void warn_if_field_exists(lua_State *L, int table,
561                 const char *fieldname, const std::string &message)
562 {
563         lua_getfield(L, table, fieldname);
564         if(!lua_isnil(L, -1)){
565 //TODO find way to access backtrace fct from here
566                 //              infostream<<script_get_backtrace(L)<<std::endl;
567                 infostream<<"WARNING: field \""<<fieldname<<"\": "
568                                 <<message<<std::endl;
569         }
570         lua_pop(L, 1);
571 }
572
573 /******************************************************************************/
574 int getenumfield(lua_State *L, int table,
575                 const char *fieldname, const EnumString *spec, int default_)
576 {
577         int result = default_;
578         string_to_enum(spec, result,
579                         getstringfield_default(L, table, fieldname, ""));
580         return result;
581 }
582
583 /******************************************************************************/
584 bool string_to_enum(const EnumString *spec, int &result,
585                 const std::string &str)
586 {
587         const EnumString *esp = spec;
588         while(esp->str){
589                 if(str == std::string(esp->str)){
590                         result = esp->num;
591                         return true;
592                 }
593                 esp++;
594         }
595         return false;
596 }
597
598 /******************************************************************************/
599 ItemStack read_item(lua_State* L, int index,Server* srv)
600 {
601         if(index < 0)
602                 index = lua_gettop(L) + 1 + index;
603
604         if(lua_isnil(L, index))
605         {
606                 return ItemStack();
607         }
608         else if(lua_isuserdata(L, index))
609         {
610                 // Convert from LuaItemStack
611                 LuaItemStack *o = LuaItemStack::checkobject(L, index);
612                 return o->getItem();
613         }
614         else if(lua_isstring(L, index))
615         {
616                 // Convert from itemstring
617                 std::string itemstring = lua_tostring(L, index);
618                 IItemDefManager *idef = srv->idef();
619                 try
620                 {
621                         ItemStack item;
622                         item.deSerialize(itemstring, idef);
623                         return item;
624                 }
625                 catch(SerializationError &e)
626                 {
627                         infostream<<"WARNING: unable to create item from itemstring"
628                                         <<": "<<itemstring<<std::endl;
629                         return ItemStack();
630                 }
631         }
632         else if(lua_istable(L, index))
633         {
634                 // Convert from table
635                 IItemDefManager *idef = srv->idef();
636                 std::string name = getstringfield_default(L, index, "name", "");
637                 int count = getintfield_default(L, index, "count", 1);
638                 int wear = getintfield_default(L, index, "wear", 0);
639                 std::string metadata = getstringfield_default(L, index, "metadata", "");
640                 return ItemStack(name, count, wear, metadata, idef);
641         }
642         else
643         {
644                 throw LuaError(L, "Expecting itemstack, itemstring, table or nil");
645         }
646 }
647
648 /******************************************************************************/
649 void push_tool_capabilities(lua_State *L,
650                 const ToolCapabilities &toolcap)
651 {
652         lua_newtable(L);
653         setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval);
654                 setintfield(L, -1, "max_drop_level", toolcap.max_drop_level);
655                 // Create groupcaps table
656                 lua_newtable(L);
657                 // For each groupcap
658                 for(std::map<std::string, ToolGroupCap>::const_iterator
659                                 i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
660                         // Create groupcap table
661                         lua_newtable(L);
662                         const std::string &name = i->first;
663                         const ToolGroupCap &groupcap = i->second;
664                         // Create subtable "times"
665                         lua_newtable(L);
666                         for(std::map<int, float>::const_iterator
667                                         i = groupcap.times.begin(); i != groupcap.times.end(); i++){
668                                 int rating = i->first;
669                                 float time = i->second;
670                                 lua_pushinteger(L, rating);
671                                 lua_pushnumber(L, time);
672                                 lua_settable(L, -3);
673                         }
674                         // Set subtable "times"
675                         lua_setfield(L, -2, "times");
676                         // Set simple parameters
677                         setintfield(L, -1, "maxlevel", groupcap.maxlevel);
678                         setintfield(L, -1, "uses", groupcap.uses);
679                         // Insert groupcap table into groupcaps table
680                         lua_setfield(L, -2, name.c_str());
681                 }
682                 // Set groupcaps table
683                 lua_setfield(L, -2, "groupcaps");
684                 //Create damage_groups table
685                 lua_newtable(L);
686                 // For each damage group
687                 for(std::map<std::string, s16>::const_iterator
688                                 i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
689                         // Create damage group table
690                         lua_pushinteger(L, i->second);
691                         lua_setfield(L, -2, i->first.c_str());
692                 }
693                 lua_setfield(L, -2, "damage_groups");
694 }
695
696 /******************************************************************************/
697 void push_inventory_list(Inventory *inv, const char *name,
698                 lua_State *L)
699 {
700         InventoryList *invlist = inv->getList(name);
701         if(invlist == NULL){
702                 lua_pushnil(L);
703                 return;
704         }
705         std::vector<ItemStack> items;
706         for(u32 i=0; i<invlist->getSize(); i++)
707                 items.push_back(invlist->getItem(i));
708         push_items(L, items);
709 }
710
711 /******************************************************************************/
712 void read_inventory_list(Inventory *inv, const char *name,
713                 lua_State *L, int tableindex, Server* srv,int forcesize)
714 {
715         if(tableindex < 0)
716                 tableindex = lua_gettop(L) + 1 + tableindex;
717         // If nil, delete list
718         if(lua_isnil(L, tableindex)){
719                 inv->deleteList(name);
720                 return;
721         }
722         // Otherwise set list
723         std::vector<ItemStack> items = read_items(L, tableindex,srv);
724         int listsize = (forcesize != -1) ? forcesize : items.size();
725         InventoryList *invlist = inv->addList(name, listsize);
726         int index = 0;
727         for(std::vector<ItemStack>::const_iterator
728                         i = items.begin(); i != items.end(); i++){
729                 if(forcesize != -1 && index == forcesize)
730                         break;
731                 invlist->changeItem(index, *i);
732                 index++;
733         }
734         while(forcesize != -1 && index < forcesize){
735                 invlist->deleteItem(index);
736                 index++;
737         }
738 }
739
740 /******************************************************************************/
741 ToolCapabilities read_tool_capabilities(
742                 lua_State *L, int table)
743 {
744         ToolCapabilities toolcap;
745         getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
746         getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
747         lua_getfield(L, table, "groupcaps");
748         if(lua_istable(L, -1)){
749                 int table_groupcaps = lua_gettop(L);
750                 lua_pushnil(L);
751                 while(lua_next(L, table_groupcaps) != 0){
752                         // key at index -2 and value at index -1
753                         std::string groupname = luaL_checkstring(L, -2);
754                         if(lua_istable(L, -1)){
755                                 int table_groupcap = lua_gettop(L);
756                                 // This will be created
757                                 ToolGroupCap groupcap;
758                                 // Read simple parameters
759                                 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
760                                 getintfield(L, table_groupcap, "uses", groupcap.uses);
761                                 // DEPRECATED: maxwear
762                                 float maxwear = 0;
763                                 if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){
764                                         if(maxwear != 0)
765                                                 groupcap.uses = 1.0/maxwear;
766                                         else
767                                                 groupcap.uses = 0;
768                                         infostream<<script_get_backtrace(L)<<std::endl;
769                                         infostream<<"WARNING: field \"maxwear\" is deprecated; "
770                                                         <<"should replace with uses=1/maxwear"<<std::endl;
771                                 }
772                                 // Read "times" table
773                                 lua_getfield(L, table_groupcap, "times");
774                                 if(lua_istable(L, -1)){
775                                         int table_times = lua_gettop(L);
776                                         lua_pushnil(L);
777                                         while(lua_next(L, table_times) != 0){
778                                                 // key at index -2 and value at index -1
779                                                 int rating = luaL_checkinteger(L, -2);
780                                                 float time = luaL_checknumber(L, -1);
781                                                 groupcap.times[rating] = time;
782                                                 // removes value, keeps key for next iteration
783                                                 lua_pop(L, 1);
784                                         }
785                                 }
786                                 lua_pop(L, 1);
787                                 // Insert groupcap into toolcap
788                                 toolcap.groupcaps[groupname] = groupcap;
789                         }
790                         // removes value, keeps key for next iteration
791                         lua_pop(L, 1);
792                 }
793         }
794         lua_pop(L, 1);
795
796         lua_getfield(L, table, "damage_groups");
797         if(lua_istable(L, -1)){
798                 int table_damage_groups = lua_gettop(L);
799                 lua_pushnil(L);
800                 while(lua_next(L, table_damage_groups) != 0){
801                         // key at index -2 and value at index -1
802                         std::string groupname = luaL_checkstring(L, -2);
803                         u16 value = luaL_checkinteger(L, -1);
804                         toolcap.damageGroups[groupname] = value;
805                         // removes value, keeps key for next iteration
806                         lua_pop(L, 1);
807                 }
808         }
809         lua_pop(L, 1);
810         return toolcap;
811 }
812
813 /******************************************************************************/
814 void push_dig_params(lua_State *L,const DigParams &params)
815 {
816         lua_newtable(L);
817         setboolfield(L, -1, "diggable", params.diggable);
818         setfloatfield(L, -1, "time", params.time);
819         setintfield(L, -1, "wear", params.wear);
820 }
821
822 /******************************************************************************/
823 void push_hit_params(lua_State *L,const HitParams &params)
824 {
825         lua_newtable(L);
826         setintfield(L, -1, "hp", params.hp);
827         setintfield(L, -1, "wear", params.wear);
828 }
829
830 /******************************************************************************/
831 u32 getflagsfield(lua_State *L, int table,
832         const char *fieldname, FlagDesc *flagdesc) {
833         std::string flagstring;
834
835         flagstring = getstringfield_default(L, table, fieldname, "");
836         return readFlagString(flagstring, flagdesc);
837 }
838
839 /******************************************************************************/
840 /* Lua Stored data!                                                           */
841 /******************************************************************************/
842
843 /******************************************************************************/
844 void read_groups(lua_State *L, int index,
845                 std::map<std::string, int> &result)
846 {
847         if (!lua_istable(L,index))
848                 return;
849         result.clear();
850         lua_pushnil(L);
851         if(index < 0)
852                 index -= 1;
853         while(lua_next(L, index) != 0){
854                 // key at index -2 and value at index -1
855                 std::string name = luaL_checkstring(L, -2);
856                 int rating = luaL_checkinteger(L, -1);
857                 result[name] = rating;
858                 // removes value, keeps key for next iteration
859                 lua_pop(L, 1);
860         }
861 }
862
863 /******************************************************************************/
864 void push_items(lua_State *L, const std::vector<ItemStack> &items)
865 {
866         // Get the table insert function
867         lua_getglobal(L, "table");
868         lua_getfield(L, -1, "insert");
869         int table_insert = lua_gettop(L);
870         // Create and fill table
871         lua_newtable(L);
872         int table = lua_gettop(L);
873         for(u32 i=0; i<items.size(); i++){
874                 ItemStack item = items[i];
875                 lua_pushvalue(L, table_insert);
876                 lua_pushvalue(L, table);
877                 LuaItemStack::create(L, item);
878                 if(lua_pcall(L, 2, 0, 0))
879                         script_error(L, "error: %s", lua_tostring(L, -1));
880         }
881         lua_remove(L, -2); // Remove table
882         lua_remove(L, -2); // Remove insert
883 }
884
885 /******************************************************************************/
886 std::vector<ItemStack> read_items(lua_State *L, int index,Server* srv)
887 {
888         if(index < 0)
889                 index = lua_gettop(L) + 1 + index;
890
891         std::vector<ItemStack> items;
892         luaL_checktype(L, index, LUA_TTABLE);
893         lua_pushnil(L);
894         while(lua_next(L, index) != 0){
895                 // key at index -2 and value at index -1
896                 items.push_back(read_item(L, -1, srv));
897                 // removes value, keeps key for next iteration
898                 lua_pop(L, 1);
899         }
900         return items;
901 }
902
903 /******************************************************************************/
904 void luaentity_get(lua_State *L, u16 id)
905 {
906         // Get minetest.luaentities[i]
907         lua_getglobal(L, "minetest");
908         lua_getfield(L, -1, "luaentities");
909         luaL_checktype(L, -1, LUA_TTABLE);
910         lua_pushnumber(L, id);
911         lua_gettable(L, -2);
912         lua_remove(L, -2); // luaentities
913         lua_remove(L, -2); // minetest
914 }
915
916 /******************************************************************************/
917 NoiseParams *read_noiseparams(lua_State *L, int index)
918 {
919         if (index < 0)
920                 index = lua_gettop(L) + 1 + index;
921
922         if (!lua_istable(L, index))
923                 return NULL;
924
925         NoiseParams *np = new NoiseParams;
926
927         np->offset  = getfloatfield_default(L, index, "offset", 0.0);
928         np->scale   = getfloatfield_default(L, index, "scale", 0.0);
929         lua_getfield(L, index, "spread");
930         np->spread  = read_v3f(L, -1);
931         lua_pop(L, 1);
932         np->seed    = getintfield_default(L, index, "seed", 0);
933         np->octaves = getintfield_default(L, index, "octaves", 0);
934         np->persist = getfloatfield_default(L, index, "persist", 0.0);
935
936         return np;
937 }
938
939 /******************************************************************************/
940 bool read_schematic(lua_State *L, int index, DecoSchematic *dschem, Server *server) {
941         if (index < 0)
942                 index = lua_gettop(L) + 1 + index;
943
944         INodeDefManager *ndef = server->getNodeDefManager();
945
946         if (lua_istable(L, index)) {
947                 lua_getfield(L, index, "size");
948                 v3s16 size = read_v3s16(L, -1);
949                 lua_pop(L, 1);
950                 
951                 int numnodes = size.X * size.Y * size.Z;
952                 MapNode *schemdata = new MapNode[numnodes];
953                 int i = 0;
954                 
955                 lua_getfield(L, index, "data");
956                 luaL_checktype(L, -1, LUA_TTABLE);
957                 
958                 lua_pushnil(L);
959                 while (lua_next(L, -2)) {
960                         if (i < numnodes) {
961                                 // same as readnode, except param1 default is MTSCHEM_PROB_CONST
962                                 lua_getfield(L, -1, "name");
963                                 const char *name = luaL_checkstring(L, -1);
964                                 lua_pop(L, 1);
965                                 
966                                 u8 param1;
967                                 lua_getfield(L, -1, "param1");
968                                 param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS;
969                                 lua_pop(L, 1);
970         
971                                 u8 param2;
972                                 lua_getfield(L, -1, "param2");
973                                 param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
974                                 lua_pop(L, 1);
975                                 
976                                 schemdata[i] = MapNode(ndef, name, param1, param2);
977                         }
978                         
979                         i++;
980                         lua_pop(L, 1);
981                 }
982                 
983                 dschem->size      = size;
984                 dschem->schematic = schemdata;
985                 
986                 if (i != numnodes) {
987                         errorstream << "read_schematic: incorrect number of "
988                                 "nodes provided in raw schematic data (got " << i <<
989                                 ", expected " << numnodes << ")." << std::endl;
990                         return false;
991                 }
992         } else if (lua_isstring(L, index)) {
993                 dschem->filename = std::string(lua_tostring(L, index));
994         } else {
995                 errorstream << "read_schematic: missing schematic "
996                         "filename or raw schematic data" << std::endl;
997                 return false;
998         }
999         
1000         return true;
1001 }