Move serveractiveobject & unitsao
[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 "object_properties.h"
24 #include "content_sao.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/serveractiveobject.h"
33 #include "porting.h"
34 #include "mapgen/mg_schematic.h"
35 #include "noise.h"
36 #include "util/pointedthing.h"
37 #include "debug.h" // For FATAL_ERROR
38 #include <json/json.h>
39
40 struct EnumString es_TileAnimationType[] =
41 {
42         {TAT_NONE, "none"},
43         {TAT_VERTICAL_FRAMES, "vertical_frames"},
44         {TAT_SHEET_2D, "sheet_2d"},
45         {0, NULL},
46 };
47
48 /******************************************************************************/
49 void read_item_definition(lua_State* L, int index,
50                 const ItemDefinition &default_def, ItemDefinition &def)
51 {
52         if (index < 0)
53                 index = lua_gettop(L) + 1 + index;
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, "inventory_overlay", def.inventory_overlay);
61         getstringfield(L, index, "wield_image", def.wield_image);
62         getstringfield(L, index, "wield_overlay", def.wield_overlay);
63         getstringfield(L, index, "palette", def.palette_image);
64
65         // Read item color.
66         lua_getfield(L, index, "color");
67         read_color(L, -1, &def.color);
68         lua_pop(L, 1);
69
70         lua_getfield(L, index, "wield_scale");
71         if(lua_istable(L, -1)){
72                 def.wield_scale = check_v3f(L, -1);
73         }
74         lua_pop(L, 1);
75
76         int stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
77         def.stack_max = rangelim(stack_max, 1, U16_MAX);
78
79         lua_getfield(L, index, "on_use");
80         def.usable = lua_isfunction(L, -1);
81         lua_pop(L, 1);
82
83         getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
84
85         warn_if_field_exists(L, index, "tool_digging_properties",
86                         "Obsolete; use tool_capabilities");
87
88         lua_getfield(L, index, "tool_capabilities");
89         if(lua_istable(L, -1)){
90                 def.tool_capabilities = new ToolCapabilities(
91                                 read_tool_capabilities(L, -1));
92         }
93
94         // If name is "" (hand), ensure there are ToolCapabilities
95         // because it will be looked up there whenever any other item has
96         // no ToolCapabilities
97         if (def.name.empty() && def.tool_capabilities == NULL){
98                 def.tool_capabilities = new ToolCapabilities();
99         }
100
101         lua_getfield(L, index, "groups");
102         read_groups(L, -1, def.groups);
103         lua_pop(L, 1);
104
105         lua_getfield(L, index, "sounds");
106         if(lua_istable(L, -1)){
107                 lua_getfield(L, -1, "place");
108                 read_soundspec(L, -1, def.sound_place);
109                 lua_pop(L, 1);
110                 lua_getfield(L, -1, "place_failed");
111                 read_soundspec(L, -1, def.sound_place_failed);
112                 lua_pop(L, 1);
113         }
114         lua_pop(L, 1);
115
116         def.range = getfloatfield_default(L, index, "range", def.range);
117
118         // Client shall immediately place this node when player places the item.
119         // Server will update the precise end result a moment later.
120         // "" = no prediction
121         getstringfield(L, index, "node_placement_prediction",
122                         def.node_placement_prediction);
123 }
124
125 /******************************************************************************/
126 void push_item_definition(lua_State *L, const ItemDefinition &i)
127 {
128         lua_newtable(L);
129         lua_pushstring(L, i.name.c_str());
130         lua_setfield(L, -2, "name");
131         lua_pushstring(L, i.description.c_str());
132         lua_setfield(L, -2, "description");
133 }
134
135 void push_item_definition_full(lua_State *L, const ItemDefinition &i)
136 {
137         std::string type(es_ItemType[(int)i.type].str);
138
139         lua_newtable(L);
140         lua_pushstring(L, i.name.c_str());
141         lua_setfield(L, -2, "name");
142         lua_pushstring(L, i.description.c_str());
143         lua_setfield(L, -2, "description");
144         lua_pushstring(L, type.c_str());
145         lua_setfield(L, -2, "type");
146         lua_pushstring(L, i.inventory_image.c_str());
147         lua_setfield(L, -2, "inventory_image");
148         lua_pushstring(L, i.inventory_overlay.c_str());
149         lua_setfield(L, -2, "inventory_overlay");
150         lua_pushstring(L, i.wield_image.c_str());
151         lua_setfield(L, -2, "wield_image");
152         lua_pushstring(L, i.wield_overlay.c_str());
153         lua_setfield(L, -2, "wield_overlay");
154         lua_pushstring(L, i.palette_image.c_str());
155         lua_setfield(L, -2, "palette_image");
156         push_ARGB8(L, i.color);
157         lua_setfield(L, -2, "color");
158         push_v3f(L, i.wield_scale);
159         lua_setfield(L, -2, "wield_scale");
160         lua_pushinteger(L, i.stack_max);
161         lua_setfield(L, -2, "stack_max");
162         lua_pushboolean(L, i.usable);
163         lua_setfield(L, -2, "usable");
164         lua_pushboolean(L, i.liquids_pointable);
165         lua_setfield(L, -2, "liquids_pointable");
166         if (i.type == ITEM_TOOL) {
167                 push_tool_capabilities(L, *i.tool_capabilities);
168                 lua_setfield(L, -2, "tool_capabilities");
169         }
170         push_groups(L, i.groups);
171         lua_setfield(L, -2, "groups");
172         push_soundspec(L, i.sound_place);
173         lua_setfield(L, -2, "sound_place");
174         push_soundspec(L, i.sound_place_failed);
175         lua_setfield(L, -2, "sound_place_failed");
176         lua_pushstring(L, i.node_placement_prediction.c_str());
177         lua_setfield(L, -2, "node_placement_prediction");
178 }
179
180 /******************************************************************************/
181 void read_object_properties(lua_State *L, int index,
182                 ServerActiveObject *sao, ObjectProperties *prop, IItemDefManager *idef)
183 {
184         if(index < 0)
185                 index = lua_gettop(L) + 1 + index;
186         if(!lua_istable(L, index))
187                 return;
188
189         int hp_max = 0;
190         if (getintfield(L, -1, "hp_max", hp_max)) {
191                 prop->hp_max = (u16)rangelim(hp_max, 0, U16_MAX);
192
193                 if (prop->hp_max < sao->getHP()) {
194                         PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
195                         sao->setHP(prop->hp_max, reason);
196                         if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER)
197                                 sao->getEnv()->getGameDef()->SendPlayerHPOrDie((PlayerSAO *)sao, reason);
198                 }
199         }
200
201         if (getintfield(L, -1, "breath_max", prop->breath_max)) {
202                 if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
203                         PlayerSAO *player = (PlayerSAO *)sao;
204                         if (prop->breath_max < player->getBreath())
205                                 player->setBreath(prop->breath_max);
206                 }
207         }
208         getboolfield(L, -1, "physical", prop->physical);
209         getboolfield(L, -1, "collide_with_objects", prop->collideWithObjects);
210
211         lua_getfield(L, -1, "collisionbox");
212         bool collisionbox_defined = lua_istable(L, -1);
213         if (collisionbox_defined)
214                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
215         lua_pop(L, 1);
216
217         lua_getfield(L, -1, "selectionbox");
218         if (lua_istable(L, -1))
219                 prop->selectionbox = read_aabb3f(L, -1, 1.0);
220         else if (collisionbox_defined)
221                 prop->selectionbox = prop->collisionbox;
222         lua_pop(L, 1);
223
224         getboolfield(L, -1, "pointable", prop->pointable);
225         getstringfield(L, -1, "visual", prop->visual);
226
227         getstringfield(L, -1, "mesh", prop->mesh);
228
229         lua_getfield(L, -1, "visual_size");
230         if (lua_istable(L, -1)) {
231                 // Backwards compatibility: Also accept { x = ?, y = ? }
232                 v2f scale_xy = read_v2f(L, -1);
233
234                 f32 scale_z = scale_xy.X;
235                 lua_getfield(L, -1, "z");
236                 if (lua_isnumber(L, -1))
237                         scale_z = lua_tonumber(L, -1);
238                 lua_pop(L, 1);
239
240                 prop->visual_size = v3f(scale_xy.X, scale_xy.Y, scale_z);
241         }
242         lua_pop(L, 1);
243
244         lua_getfield(L, -1, "textures");
245         if(lua_istable(L, -1)){
246                 prop->textures.clear();
247                 int table = lua_gettop(L);
248                 lua_pushnil(L);
249                 while(lua_next(L, table) != 0){
250                         // key at index -2 and value at index -1
251                         if(lua_isstring(L, -1))
252                                 prop->textures.emplace_back(lua_tostring(L, -1));
253                         else
254                                 prop->textures.emplace_back("");
255                         // removes value, keeps key for next iteration
256                         lua_pop(L, 1);
257                 }
258         }
259         lua_pop(L, 1);
260
261         lua_getfield(L, -1, "colors");
262         if (lua_istable(L, -1)) {
263                 int table = lua_gettop(L);
264                 prop->colors.clear();
265                 for (lua_pushnil(L); lua_next(L, table); lua_pop(L, 1)) {
266                         video::SColor color(255, 255, 255, 255);
267                         read_color(L, -1, &color);
268                         prop->colors.push_back(color);
269                 }
270         }
271         lua_pop(L, 1);
272
273         lua_getfield(L, -1, "spritediv");
274         if(lua_istable(L, -1))
275                 prop->spritediv = read_v2s16(L, -1);
276         lua_pop(L, 1);
277
278         lua_getfield(L, -1, "initial_sprite_basepos");
279         if(lua_istable(L, -1))
280                 prop->initial_sprite_basepos = read_v2s16(L, -1);
281         lua_pop(L, 1);
282
283         getboolfield(L, -1, "is_visible", prop->is_visible);
284         getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
285         if (getfloatfield(L, -1, "stepheight", prop->stepheight))
286                 prop->stepheight *= BS;
287         getfloatfield(L, -1, "eye_height", prop->eye_height);
288
289         getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
290         lua_getfield(L, -1, "automatic_face_movement_dir");
291         if (lua_isnumber(L, -1)) {
292                 prop->automatic_face_movement_dir = true;
293                 prop->automatic_face_movement_dir_offset = luaL_checknumber(L, -1);
294         } else if (lua_isboolean(L, -1)) {
295                 prop->automatic_face_movement_dir = lua_toboolean(L, -1);
296                 prop->automatic_face_movement_dir_offset = 0.0;
297         }
298         lua_pop(L, 1);
299         getboolfield(L, -1, "backface_culling", prop->backface_culling);
300         getintfield(L, -1, "glow", prop->glow);
301
302         getstringfield(L, -1, "nametag", prop->nametag);
303         lua_getfield(L, -1, "nametag_color");
304         if (!lua_isnil(L, -1)) {
305                 video::SColor color = prop->nametag_color;
306                 if (read_color(L, -1, &color))
307                         prop->nametag_color = color;
308         }
309         lua_pop(L, 1);
310
311         lua_getfield(L, -1, "automatic_face_movement_max_rotation_per_sec");
312         if (lua_isnumber(L, -1)) {
313                 prop->automatic_face_movement_max_rotation_per_sec = luaL_checknumber(L, -1);
314         }
315         lua_pop(L, 1);
316
317         getstringfield(L, -1, "infotext", prop->infotext);
318         getboolfield(L, -1, "static_save", prop->static_save);
319
320         lua_getfield(L, -1, "wield_item");
321         if (!lua_isnil(L, -1))
322                 prop->wield_item = read_item(L, -1, idef).getItemString();
323         lua_pop(L, 1);
324
325         getfloatfield(L, -1, "zoom_fov", prop->zoom_fov);
326         getboolfield(L, -1, "use_texture_alpha", prop->use_texture_alpha);
327 }
328
329 /******************************************************************************/
330 void push_object_properties(lua_State *L, ObjectProperties *prop)
331 {
332         lua_newtable(L);
333         lua_pushnumber(L, prop->hp_max);
334         lua_setfield(L, -2, "hp_max");
335         lua_pushnumber(L, prop->breath_max);
336         lua_setfield(L, -2, "breath_max");
337         lua_pushboolean(L, prop->physical);
338         lua_setfield(L, -2, "physical");
339         lua_pushboolean(L, prop->collideWithObjects);
340         lua_setfield(L, -2, "collide_with_objects");
341         push_aabb3f(L, prop->collisionbox);
342         lua_setfield(L, -2, "collisionbox");
343         push_aabb3f(L, prop->selectionbox);
344         lua_setfield(L, -2, "selectionbox");
345         lua_pushboolean(L, prop->pointable);
346         lua_setfield(L, -2, "pointable");
347         lua_pushlstring(L, prop->visual.c_str(), prop->visual.size());
348         lua_setfield(L, -2, "visual");
349         lua_pushlstring(L, prop->mesh.c_str(), prop->mesh.size());
350         lua_setfield(L, -2, "mesh");
351         push_v3f(L, prop->visual_size);
352         lua_setfield(L, -2, "visual_size");
353
354         lua_newtable(L);
355         u16 i = 1;
356         for (const std::string &texture : prop->textures) {
357                 lua_pushlstring(L, texture.c_str(), texture.size());
358                 lua_rawseti(L, -2, i++);
359         }
360         lua_setfield(L, -2, "textures");
361
362         lua_newtable(L);
363         i = 1;
364         for (const video::SColor &color : prop->colors) {
365                 push_ARGB8(L, color);
366                 lua_rawseti(L, -2, i++);
367         }
368         lua_setfield(L, -2, "colors");
369
370         push_v2s16(L, prop->spritediv);
371         lua_setfield(L, -2, "spritediv");
372         push_v2s16(L, prop->initial_sprite_basepos);
373         lua_setfield(L, -2, "initial_sprite_basepos");
374         lua_pushboolean(L, prop->is_visible);
375         lua_setfield(L, -2, "is_visible");
376         lua_pushboolean(L, prop->makes_footstep_sound);
377         lua_setfield(L, -2, "makes_footstep_sound");
378         lua_pushnumber(L, prop->stepheight / BS);
379         lua_setfield(L, -2, "stepheight");
380         lua_pushnumber(L, prop->eye_height);
381         lua_setfield(L, -2, "eye_height");
382         lua_pushnumber(L, prop->automatic_rotate);
383         lua_setfield(L, -2, "automatic_rotate");
384         if (prop->automatic_face_movement_dir)
385                 lua_pushnumber(L, prop->automatic_face_movement_dir_offset);
386         else
387                 lua_pushboolean(L, false);
388         lua_setfield(L, -2, "automatic_face_movement_dir");
389         lua_pushboolean(L, prop->backface_culling);
390         lua_setfield(L, -2, "backface_culling");
391         lua_pushnumber(L, prop->glow);
392         lua_setfield(L, -2, "glow");
393         lua_pushlstring(L, prop->nametag.c_str(), prop->nametag.size());
394         lua_setfield(L, -2, "nametag");
395         push_ARGB8(L, prop->nametag_color);
396         lua_setfield(L, -2, "nametag_color");
397         lua_pushnumber(L, prop->automatic_face_movement_max_rotation_per_sec);
398         lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec");
399         lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size());
400         lua_setfield(L, -2, "infotext");
401         lua_pushboolean(L, prop->static_save);
402         lua_setfield(L, -2, "static_save");
403         lua_pushlstring(L, prop->wield_item.c_str(), prop->wield_item.size());
404         lua_setfield(L, -2, "wield_item");
405         lua_pushnumber(L, prop->zoom_fov);
406         lua_setfield(L, -2, "zoom_fov");
407         lua_pushboolean(L, prop->use_texture_alpha);
408         lua_setfield(L, -2, "use_texture_alpha");
409 }
410
411 /******************************************************************************/
412 TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
413 {
414         if(index < 0)
415                 index = lua_gettop(L) + 1 + index;
416
417         TileDef tiledef;
418
419         bool default_tiling = true;
420         bool default_culling = true;
421         switch (drawtype) {
422                 case NDT_PLANTLIKE:
423                 case NDT_PLANTLIKE_ROOTED:
424                 case NDT_FIRELIKE:
425                         default_tiling = false;
426                         // "break" is omitted here intentionaly, as PLANTLIKE
427                         // FIRELIKE drawtype both should default to having
428                         // backface_culling to false.
429                 case NDT_MESH:
430                 case NDT_LIQUID:
431                         default_culling = false;
432                         break;
433                 default:
434                         break;
435         }
436
437         // key at index -2 and value at index
438         if(lua_isstring(L, index)){
439                 // "default_lava.png"
440                 tiledef.name = lua_tostring(L, index);
441                 tiledef.tileable_vertical = default_tiling;
442                 tiledef.tileable_horizontal = default_tiling;
443                 tiledef.backface_culling = default_culling;
444         }
445         else if(lua_istable(L, index))
446         {
447                 // name="default_lava.png"
448                 tiledef.name = "";
449                 getstringfield(L, index, "name", tiledef.name);
450                 getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
451                 tiledef.backface_culling = getboolfield_default(
452                         L, index, "backface_culling", default_culling);
453                 tiledef.tileable_horizontal = getboolfield_default(
454                         L, index, "tileable_horizontal", default_tiling);
455                 tiledef.tileable_vertical = getboolfield_default(
456                         L, index, "tileable_vertical", default_tiling);
457                 std::string align_style;
458                 if (getstringfield(L, index, "align_style", align_style)) {
459                         if (align_style == "user")
460                                 tiledef.align_style = ALIGN_STYLE_USER_DEFINED;
461                         else if (align_style == "world")
462                                 tiledef.align_style = ALIGN_STYLE_WORLD;
463                         else
464                                 tiledef.align_style = ALIGN_STYLE_NODE;
465                 }
466                 tiledef.scale = getintfield_default(L, index, "scale", 0);
467                 // color = ...
468                 lua_getfield(L, index, "color");
469                 tiledef.has_color = read_color(L, -1, &tiledef.color);
470                 lua_pop(L, 1);
471                 // animation = {}
472                 lua_getfield(L, index, "animation");
473                 tiledef.animation = read_animation_definition(L, -1);
474                 lua_pop(L, 1);
475         }
476
477         return tiledef;
478 }
479
480 /******************************************************************************/
481 ContentFeatures read_content_features(lua_State *L, int index)
482 {
483         if(index < 0)
484                 index = lua_gettop(L) + 1 + index;
485
486         ContentFeatures f;
487
488         /* Cache existence of some callbacks */
489         lua_getfield(L, index, "on_construct");
490         if(!lua_isnil(L, -1)) f.has_on_construct = true;
491         lua_pop(L, 1);
492         lua_getfield(L, index, "on_destruct");
493         if(!lua_isnil(L, -1)) f.has_on_destruct = true;
494         lua_pop(L, 1);
495         lua_getfield(L, index, "after_destruct");
496         if(!lua_isnil(L, -1)) f.has_after_destruct = true;
497         lua_pop(L, 1);
498
499         lua_getfield(L, index, "on_rightclick");
500         f.rightclickable = lua_isfunction(L, -1);
501         lua_pop(L, 1);
502
503         /* Name */
504         getstringfield(L, index, "name", f.name);
505
506         /* Groups */
507         lua_getfield(L, index, "groups");
508         read_groups(L, -1, f.groups);
509         lua_pop(L, 1);
510
511         /* Visual definition */
512
513         f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype",
514                         ScriptApiNode::es_DrawType,NDT_NORMAL);
515         getfloatfield(L, index, "visual_scale", f.visual_scale);
516
517         /* Meshnode model filename */
518         getstringfield(L, index, "mesh", f.mesh);
519
520         // tiles = {}
521         lua_getfield(L, index, "tiles");
522         // If nil, try the deprecated name "tile_images" instead
523         if(lua_isnil(L, -1)){
524                 lua_pop(L, 1);
525                 warn_if_field_exists(L, index, "tile_images",
526                                 "Deprecated; new name is \"tiles\".");
527                 lua_getfield(L, index, "tile_images");
528         }
529         if(lua_istable(L, -1)){
530                 int table = lua_gettop(L);
531                 lua_pushnil(L);
532                 int i = 0;
533                 while(lua_next(L, table) != 0){
534                         // Read tiledef from value
535                         f.tiledef[i] = read_tiledef(L, -1, f.drawtype);
536                         // removes value, keeps key for next iteration
537                         lua_pop(L, 1);
538                         i++;
539                         if(i==6){
540                                 lua_pop(L, 1);
541                                 break;
542                         }
543                 }
544                 // Copy last value to all remaining textures
545                 if(i >= 1){
546                         TileDef lasttile = f.tiledef[i-1];
547                         while(i < 6){
548                                 f.tiledef[i] = lasttile;
549                                 i++;
550                         }
551                 }
552         }
553         lua_pop(L, 1);
554
555         // overlay_tiles = {}
556         lua_getfield(L, index, "overlay_tiles");
557         if (lua_istable(L, -1)) {
558                 int table = lua_gettop(L);
559                 lua_pushnil(L);
560                 int i = 0;
561                 while (lua_next(L, table) != 0) {
562                         // Read tiledef from value
563                         f.tiledef_overlay[i] = read_tiledef(L, -1, f.drawtype);
564                         // removes value, keeps key for next iteration
565                         lua_pop(L, 1);
566                         i++;
567                         if (i == 6) {
568                                 lua_pop(L, 1);
569                                 break;
570                         }
571                 }
572                 // Copy last value to all remaining textures
573                 if (i >= 1) {
574                         TileDef lasttile = f.tiledef_overlay[i - 1];
575                         while (i < 6) {
576                                 f.tiledef_overlay[i] = lasttile;
577                                 i++;
578                         }
579                 }
580         }
581         lua_pop(L, 1);
582
583         // special_tiles = {}
584         lua_getfield(L, index, "special_tiles");
585         // If nil, try the deprecated name "special_materials" instead
586         if(lua_isnil(L, -1)){
587                 lua_pop(L, 1);
588                 warn_if_field_exists(L, index, "special_materials",
589                                 "Deprecated; new name is \"special_tiles\".");
590                 lua_getfield(L, index, "special_materials");
591         }
592         if(lua_istable(L, -1)){
593                 int table = lua_gettop(L);
594                 lua_pushnil(L);
595                 int i = 0;
596                 while(lua_next(L, table) != 0){
597                         // Read tiledef from value
598                         f.tiledef_special[i] = read_tiledef(L, -1, f.drawtype);
599                         // removes value, keeps key for next iteration
600                         lua_pop(L, 1);
601                         i++;
602                         if(i==CF_SPECIAL_COUNT){
603                                 lua_pop(L, 1);
604                                 break;
605                         }
606                 }
607         }
608         lua_pop(L, 1);
609
610         f.alpha = getintfield_default(L, index, "alpha", 255);
611
612         bool usealpha = getboolfield_default(L, index,
613                         "use_texture_alpha", false);
614         if (usealpha)
615                 f.alpha = 0;
616
617         // Read node color.
618         lua_getfield(L, index, "color");
619         read_color(L, -1, &f.color);
620         lua_pop(L, 1);
621
622         getstringfield(L, index, "palette", f.palette_name);
623
624         /* Other stuff */
625
626         lua_getfield(L, index, "post_effect_color");
627         read_color(L, -1, &f.post_effect_color);
628         lua_pop(L, 1);
629
630         f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
631                         ScriptApiNode::es_ContentParamType, CPT_NONE);
632         f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
633                         ScriptApiNode::es_ContentParamType2, CPT2_NONE);
634
635         if (!f.palette_name.empty() &&
636                         !(f.param_type_2 == CPT2_COLOR ||
637                         f.param_type_2 == CPT2_COLORED_FACEDIR ||
638                         f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
639                 warningstream << "Node " << f.name.c_str()
640                         << " has a palette, but not a suitable paramtype2." << std::endl;
641
642         // Warn about some obsolete fields
643         warn_if_field_exists(L, index, "wall_mounted",
644                         "Obsolete; use paramtype2 = 'wallmounted'");
645         warn_if_field_exists(L, index, "light_propagates",
646                         "Obsolete; determined from paramtype");
647         warn_if_field_exists(L, index, "dug_item",
648                         "Obsolete; use 'drop' field");
649         warn_if_field_exists(L, index, "extra_dug_item",
650                         "Obsolete; use 'drop' field");
651         warn_if_field_exists(L, index, "extra_dug_item_rarity",
652                         "Obsolete; use 'drop' field");
653         warn_if_field_exists(L, index, "metadata_name",
654                         "Obsolete; use on_add and metadata callbacks");
655
656         // True for all ground-like things like stone and mud, false for eg. trees
657         getboolfield(L, index, "is_ground_content", f.is_ground_content);
658         f.light_propagates = (f.param_type == CPT_LIGHT);
659         getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
660         // This is used for collision detection.
661         // Also for general solidness queries.
662         getboolfield(L, index, "walkable", f.walkable);
663         // Player can point to these
664         getboolfield(L, index, "pointable", f.pointable);
665         // Player can dig these
666         getboolfield(L, index, "diggable", f.diggable);
667         // Player can climb these
668         getboolfield(L, index, "climbable", f.climbable);
669         // Player can build on these
670         getboolfield(L, index, "buildable_to", f.buildable_to);
671         // Liquids flow into and replace node
672         getboolfield(L, index, "floodable", f.floodable);
673         // Whether the node is non-liquid, source liquid or flowing liquid
674         f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
675                         ScriptApiNode::es_LiquidType, LIQUID_NONE);
676         // If the content is liquid, this is the flowing version of the liquid.
677         getstringfield(L, index, "liquid_alternative_flowing",
678                         f.liquid_alternative_flowing);
679         // If the content is liquid, this is the source version of the liquid.
680         getstringfield(L, index, "liquid_alternative_source",
681                         f.liquid_alternative_source);
682         // Viscosity for fluid flow, ranging from 1 to 7, with
683         // 1 giving almost instantaneous propagation and 7 being
684         // the slowest possible
685         f.liquid_viscosity = getintfield_default(L, index,
686                         "liquid_viscosity", f.liquid_viscosity);
687         f.liquid_range = getintfield_default(L, index,
688                         "liquid_range", f.liquid_range);
689         f.leveled = getintfield_default(L, index, "leveled", f.leveled);
690
691         getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
692         f.drowning = getintfield_default(L, index,
693                         "drowning", f.drowning);
694         // Amount of light the node emits
695         f.light_source = getintfield_default(L, index,
696                         "light_source", f.light_source);
697         if (f.light_source > LIGHT_MAX) {
698                 warningstream << "Node " << f.name.c_str()
699                         << " had greater light_source than " << LIGHT_MAX
700                         << ", it was reduced." << std::endl;
701                 f.light_source = LIGHT_MAX;
702         }
703         f.damage_per_second = getintfield_default(L, index,
704                         "damage_per_second", f.damage_per_second);
705
706         lua_getfield(L, index, "node_box");
707         if(lua_istable(L, -1))
708                 f.node_box = read_nodebox(L, -1);
709         lua_pop(L, 1);
710
711         lua_getfield(L, index, "connects_to");
712         if (lua_istable(L, -1)) {
713                 int table = lua_gettop(L);
714                 lua_pushnil(L);
715                 while (lua_next(L, table) != 0) {
716                         // Value at -1
717                         f.connects_to.emplace_back(lua_tostring(L, -1));
718                         lua_pop(L, 1);
719                 }
720         }
721         lua_pop(L, 1);
722
723         lua_getfield(L, index, "connect_sides");
724         if (lua_istable(L, -1)) {
725                 int table = lua_gettop(L);
726                 lua_pushnil(L);
727                 while (lua_next(L, table) != 0) {
728                         // Value at -1
729                         std::string side(lua_tostring(L, -1));
730                         // Note faces are flipped to make checking easier
731                         if (side == "top")
732                                 f.connect_sides |= 2;
733                         else if (side == "bottom")
734                                 f.connect_sides |= 1;
735                         else if (side == "front")
736                                 f.connect_sides |= 16;
737                         else if (side == "left")
738                                 f.connect_sides |= 32;
739                         else if (side == "back")
740                                 f.connect_sides |= 4;
741                         else if (side == "right")
742                                 f.connect_sides |= 8;
743                         else
744                                 warningstream << "Unknown value for \"connect_sides\": "
745                                         << side << std::endl;
746                         lua_pop(L, 1);
747                 }
748         }
749         lua_pop(L, 1);
750
751         lua_getfield(L, index, "selection_box");
752         if(lua_istable(L, -1))
753                 f.selection_box = read_nodebox(L, -1);
754         lua_pop(L, 1);
755
756         lua_getfield(L, index, "collision_box");
757         if(lua_istable(L, -1))
758                 f.collision_box = read_nodebox(L, -1);
759         lua_pop(L, 1);
760
761         f.waving = getintfield_default(L, index,
762                         "waving", f.waving);
763
764         // Set to true if paramtype used to be 'facedir_simple'
765         getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
766         // Set to true if wall_mounted used to be set to true
767         getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
768
769         // Sound table
770         lua_getfield(L, index, "sounds");
771         if(lua_istable(L, -1)){
772                 lua_getfield(L, -1, "footstep");
773                 read_soundspec(L, -1, f.sound_footstep);
774                 lua_pop(L, 1);
775                 lua_getfield(L, -1, "dig");
776                 read_soundspec(L, -1, f.sound_dig);
777                 lua_pop(L, 1);
778                 lua_getfield(L, -1, "dug");
779                 read_soundspec(L, -1, f.sound_dug);
780                 lua_pop(L, 1);
781         }
782         lua_pop(L, 1);
783
784         // Node immediately placed by client when node is dug
785         getstringfield(L, index, "node_dig_prediction",
786                 f.node_dig_prediction);
787
788         return f;
789 }
790
791 void push_content_features(lua_State *L, const ContentFeatures &c)
792 {
793         std::string paramtype(ScriptApiNode::es_ContentParamType[(int)c.param_type].str);
794         std::string paramtype2(ScriptApiNode::es_ContentParamType2[(int)c.param_type_2].str);
795         std::string drawtype(ScriptApiNode::es_DrawType[(int)c.drawtype].str);
796         std::string liquid_type(ScriptApiNode::es_LiquidType[(int)c.liquid_type].str);
797
798         /* Missing "tiles" because I don't see a usecase (at least not yet). */
799
800         lua_newtable(L);
801         lua_pushboolean(L, c.has_on_construct);
802         lua_setfield(L, -2, "has_on_construct");
803         lua_pushboolean(L, c.has_on_destruct);
804         lua_setfield(L, -2, "has_on_destruct");
805         lua_pushboolean(L, c.has_after_destruct);
806         lua_setfield(L, -2, "has_after_destruct");
807         lua_pushstring(L, c.name.c_str());
808         lua_setfield(L, -2, "name");
809         push_groups(L, c.groups);
810         lua_setfield(L, -2, "groups");
811         lua_pushstring(L, paramtype.c_str());
812         lua_setfield(L, -2, "paramtype");
813         lua_pushstring(L, paramtype2.c_str());
814         lua_setfield(L, -2, "paramtype2");
815         lua_pushstring(L, drawtype.c_str());
816         lua_setfield(L, -2, "drawtype");
817         if (!c.mesh.empty()) {
818                 lua_pushstring(L, c.mesh.c_str());
819                 lua_setfield(L, -2, "mesh");
820         }
821 #ifndef SERVER
822         push_ARGB8(L, c.minimap_color);       // I know this is not set-able w/ register_node,
823         lua_setfield(L, -2, "minimap_color"); // but the people need to know!
824 #endif
825         lua_pushnumber(L, c.visual_scale);
826         lua_setfield(L, -2, "visual_scale");
827         lua_pushnumber(L, c.alpha);
828         lua_setfield(L, -2, "alpha");
829         if (!c.palette_name.empty()) {
830                 push_ARGB8(L, c.color);
831                 lua_setfield(L, -2, "color");
832
833                 lua_pushstring(L, c.palette_name.c_str());
834                 lua_setfield(L, -2, "palette_name");
835
836                 push_palette(L, c.palette);
837                 lua_setfield(L, -2, "palette");
838         }
839         lua_pushnumber(L, c.waving);
840         lua_setfield(L, -2, "waving");
841         lua_pushnumber(L, c.connect_sides);
842         lua_setfield(L, -2, "connect_sides");
843
844         lua_newtable(L);
845         u16 i = 1;
846         for (const std::string &it : c.connects_to) {
847                 lua_pushlstring(L, it.c_str(), it.size());
848                 lua_rawseti(L, -2, i++);
849         }
850         lua_setfield(L, -2, "connects_to");
851
852         push_ARGB8(L, c.post_effect_color);
853         lua_setfield(L, -2, "post_effect_color");
854         lua_pushnumber(L, c.leveled);
855         lua_setfield(L, -2, "leveled");
856         lua_pushboolean(L, c.sunlight_propagates);
857         lua_setfield(L, -2, "sunlight_propagates");
858         lua_pushnumber(L, c.light_source);
859         lua_setfield(L, -2, "light_source");
860         lua_pushboolean(L, c.is_ground_content);
861         lua_setfield(L, -2, "is_ground_content");
862         lua_pushboolean(L, c.walkable);
863         lua_setfield(L, -2, "walkable");
864         lua_pushboolean(L, c.pointable);
865         lua_setfield(L, -2, "pointable");
866         lua_pushboolean(L, c.diggable);
867         lua_setfield(L, -2, "diggable");
868         lua_pushboolean(L, c.climbable);
869         lua_setfield(L, -2, "climbable");
870         lua_pushboolean(L, c.buildable_to);
871         lua_setfield(L, -2, "buildable_to");
872         lua_pushboolean(L, c.rightclickable);
873         lua_setfield(L, -2, "rightclickable");
874         lua_pushnumber(L, c.damage_per_second);
875         lua_setfield(L, -2, "damage_per_second");
876         if (c.isLiquid()) {
877                 lua_pushstring(L, liquid_type.c_str());
878                 lua_setfield(L, -2, "liquid_type");
879                 lua_pushstring(L, c.liquid_alternative_flowing.c_str());
880                 lua_setfield(L, -2, "liquid_alternative_flowing");
881                 lua_pushstring(L, c.liquid_alternative_source.c_str());
882                 lua_setfield(L, -2, "liquid_alternative_source");
883                 lua_pushnumber(L, c.liquid_viscosity);
884                 lua_setfield(L, -2, "liquid_viscosity");
885                 lua_pushboolean(L, c.liquid_renewable);
886                 lua_setfield(L, -2, "liquid_renewable");
887                 lua_pushnumber(L, c.liquid_range);
888                 lua_setfield(L, -2, "liquid_range");
889         }
890         lua_pushnumber(L, c.drowning);
891         lua_setfield(L, -2, "drowning");
892         lua_pushboolean(L, c.floodable);
893         lua_setfield(L, -2, "floodable");
894         push_nodebox(L, c.node_box);
895         lua_setfield(L, -2, "node_box");
896         push_nodebox(L, c.selection_box);
897         lua_setfield(L, -2, "selection_box");
898         push_nodebox(L, c.collision_box);
899         lua_setfield(L, -2, "collision_box");
900         lua_newtable(L);
901         push_soundspec(L, c.sound_footstep);
902         lua_setfield(L, -2, "sound_footstep");
903         push_soundspec(L, c.sound_dig);
904         lua_setfield(L, -2, "sound_dig");
905         push_soundspec(L, c.sound_dug);
906         lua_setfield(L, -2, "sound_dug");
907         lua_setfield(L, -2, "sounds");
908         lua_pushboolean(L, c.legacy_facedir_simple);
909         lua_setfield(L, -2, "legacy_facedir_simple");
910         lua_pushboolean(L, c.legacy_wallmounted);
911         lua_setfield(L, -2, "legacy_wallmounted");
912         lua_pushstring(L, c.node_dig_prediction.c_str());
913         lua_setfield(L, -2, "node_dig_prediction");
914 }
915
916 /******************************************************************************/
917 void push_nodebox(lua_State *L, const NodeBox &box)
918 {
919         lua_newtable(L);
920         switch (box.type)
921         {
922                 case NODEBOX_REGULAR:
923                         lua_pushstring(L, "regular");
924                         lua_setfield(L, -2, "type");
925                         break;
926                 case NODEBOX_LEVELED:
927                 case NODEBOX_FIXED:
928                         lua_pushstring(L, "fixed");
929                         lua_setfield(L, -2, "type");
930                         push_box(L, box.fixed);
931                         lua_setfield(L, -2, "fixed");
932                         break;
933                 case NODEBOX_WALLMOUNTED:
934                         lua_pushstring(L, "wallmounted");
935                         lua_setfield(L, -2, "type");
936                         push_aabb3f(L, box.wall_top);
937                         lua_setfield(L, -2, "wall_top");
938                         push_aabb3f(L, box.wall_bottom);
939                         lua_setfield(L, -2, "wall_bottom");
940                         push_aabb3f(L, box.wall_side);
941                         lua_setfield(L, -2, "wall_side");
942                         break;
943                 case NODEBOX_CONNECTED:
944                         lua_pushstring(L, "connected");
945                         lua_setfield(L, -2, "type");
946                         push_box(L, box.connect_top);
947                         lua_setfield(L, -2, "connect_top");
948                         push_box(L, box.connect_bottom);
949                         lua_setfield(L, -2, "connect_bottom");
950                         push_box(L, box.connect_front);
951                         lua_setfield(L, -2, "connect_front");
952                         push_box(L, box.connect_back);
953                         lua_setfield(L, -2, "connect_back");
954                         push_box(L, box.connect_left);
955                         lua_setfield(L, -2, "connect_left");
956                         push_box(L, box.connect_right);
957                         lua_setfield(L, -2, "connect_right");
958                         break;
959                 default:
960                         FATAL_ERROR("Invalid box.type");
961                         break;
962         }
963 }
964
965 void push_box(lua_State *L, const std::vector<aabb3f> &box)
966 {
967         lua_newtable(L);
968         u8 i = 1;
969         for (const aabb3f &it : box) {
970                 push_aabb3f(L, it);
971                 lua_rawseti(L, -2, i++);
972         }
973 }
974
975 /******************************************************************************/
976 void push_palette(lua_State *L, const std::vector<video::SColor> *palette)
977 {
978         lua_createtable(L, palette->size(), 0);
979         int newTable = lua_gettop(L);
980         int index = 1;
981         std::vector<video::SColor>::const_iterator iter;
982         for (iter = palette->begin(); iter != palette->end(); ++iter) {
983                 push_ARGB8(L, (*iter));
984                 lua_rawseti(L, newTable, index);
985                 index++;
986         }
987 }
988
989 /******************************************************************************/
990 void read_server_sound_params(lua_State *L, int index,
991                 ServerSoundParams &params)
992 {
993         if(index < 0)
994                 index = lua_gettop(L) + 1 + index;
995         // Clear
996         params = ServerSoundParams();
997         if(lua_istable(L, index)){
998                 getfloatfield(L, index, "gain", params.gain);
999                 getstringfield(L, index, "to_player", params.to_player);
1000                 getfloatfield(L, index, "fade", params.fade);
1001                 getfloatfield(L, index, "pitch", params.pitch);
1002                 lua_getfield(L, index, "pos");
1003                 if(!lua_isnil(L, -1)){
1004                         v3f p = read_v3f(L, -1)*BS;
1005                         params.pos = p;
1006                         params.type = ServerSoundParams::SSP_POSITIONAL;
1007                 }
1008                 lua_pop(L, 1);
1009                 lua_getfield(L, index, "object");
1010                 if(!lua_isnil(L, -1)){
1011                         ObjectRef *ref = ObjectRef::checkobject(L, -1);
1012                         ServerActiveObject *sao = ObjectRef::getobject(ref);
1013                         if(sao){
1014                                 params.object = sao->getId();
1015                                 params.type = ServerSoundParams::SSP_OBJECT;
1016                         }
1017                 }
1018                 lua_pop(L, 1);
1019                 params.max_hear_distance = BS*getfloatfield_default(L, index,
1020                                 "max_hear_distance", params.max_hear_distance/BS);
1021                 getboolfield(L, index, "loop", params.loop);
1022                 getstringfield(L, index, "exclude_player", params.exclude_player);
1023         }
1024 }
1025
1026 /******************************************************************************/
1027 void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
1028 {
1029         if(index < 0)
1030                 index = lua_gettop(L) + 1 + index;
1031         if(lua_isnil(L, index)){
1032         } else if(lua_istable(L, index)){
1033                 getstringfield(L, index, "name", spec.name);
1034                 getfloatfield(L, index, "gain", spec.gain);
1035                 getfloatfield(L, index, "fade", spec.fade);
1036                 getfloatfield(L, index, "pitch", spec.pitch);
1037         } else if(lua_isstring(L, index)){
1038                 spec.name = lua_tostring(L, index);
1039         }
1040 }
1041
1042 void push_soundspec(lua_State *L, const SimpleSoundSpec &spec)
1043 {
1044         lua_newtable(L);
1045         lua_pushstring(L, spec.name.c_str());
1046         lua_setfield(L, -2, "name");
1047         lua_pushnumber(L, spec.gain);
1048         lua_setfield(L, -2, "gain");
1049         lua_pushnumber(L, spec.fade);
1050         lua_setfield(L, -2, "fade");
1051         lua_pushnumber(L, spec.pitch);
1052         lua_setfield(L, -2, "pitch");
1053 }
1054
1055 /******************************************************************************/
1056 NodeBox read_nodebox(lua_State *L, int index)
1057 {
1058         NodeBox nodebox;
1059         if(lua_istable(L, -1)){
1060                 nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
1061                                 ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR);
1062
1063 #define NODEBOXREAD(n, s){ \
1064                 lua_getfield(L, index, (s)); \
1065                 if (lua_istable(L, -1)) \
1066                         (n) = read_aabb3f(L, -1, BS); \
1067                 lua_pop(L, 1); \
1068         }
1069
1070 #define NODEBOXREADVEC(n, s) \
1071                 lua_getfield(L, index, (s)); \
1072                 if (lua_istable(L, -1)) \
1073                         (n) = read_aabb3f_vector(L, -1, BS); \
1074                 lua_pop(L, 1);
1075
1076                 NODEBOXREADVEC(nodebox.fixed, "fixed");
1077                 NODEBOXREAD(nodebox.wall_top, "wall_top");
1078                 NODEBOXREAD(nodebox.wall_bottom, "wall_bottom");
1079                 NODEBOXREAD(nodebox.wall_side, "wall_side");
1080                 NODEBOXREADVEC(nodebox.connect_top, "connect_top");
1081                 NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom");
1082                 NODEBOXREADVEC(nodebox.connect_front, "connect_front");
1083                 NODEBOXREADVEC(nodebox.connect_left, "connect_left");
1084                 NODEBOXREADVEC(nodebox.connect_back, "connect_back");
1085                 NODEBOXREADVEC(nodebox.connect_right, "connect_right");
1086                 NODEBOXREADVEC(nodebox.disconnected_top, "disconnected_top");
1087                 NODEBOXREADVEC(nodebox.disconnected_bottom, "disconnected_bottom");
1088                 NODEBOXREADVEC(nodebox.disconnected_front, "disconnected_front");
1089                 NODEBOXREADVEC(nodebox.disconnected_left, "disconnected_left");
1090                 NODEBOXREADVEC(nodebox.disconnected_back, "disconnected_back");
1091                 NODEBOXREADVEC(nodebox.disconnected_right, "disconnected_right");
1092                 NODEBOXREADVEC(nodebox.disconnected, "disconnected");
1093                 NODEBOXREADVEC(nodebox.disconnected_sides, "disconnected_sides");
1094         }
1095         return nodebox;
1096 }
1097
1098 /******************************************************************************/
1099 MapNode readnode(lua_State *L, int index, const NodeDefManager *ndef)
1100 {
1101         lua_getfield(L, index, "name");
1102         if (!lua_isstring(L, -1))
1103                 throw LuaError("Node name is not set or is not a string!");
1104         std::string name = lua_tostring(L, -1);
1105         lua_pop(L, 1);
1106
1107         u8 param1 = 0;
1108         lua_getfield(L, index, "param1");
1109         if (!lua_isnil(L, -1))
1110                 param1 = lua_tonumber(L, -1);
1111         lua_pop(L, 1);
1112
1113         u8 param2 = 0;
1114         lua_getfield(L, index, "param2");
1115         if (!lua_isnil(L, -1))
1116                 param2 = lua_tonumber(L, -1);
1117         lua_pop(L, 1);
1118
1119         content_t id = CONTENT_IGNORE;
1120         if (!ndef->getId(name, id))
1121                 throw LuaError("\"" + name + "\" is not a registered node!");
1122
1123         return {id, param1, param2};
1124 }
1125
1126 /******************************************************************************/
1127 void pushnode(lua_State *L, const MapNode &n, const NodeDefManager *ndef)
1128 {
1129         lua_newtable(L);
1130         lua_pushstring(L, ndef->get(n).name.c_str());
1131         lua_setfield(L, -2, "name");
1132         lua_pushnumber(L, n.getParam1());
1133         lua_setfield(L, -2, "param1");
1134         lua_pushnumber(L, n.getParam2());
1135         lua_setfield(L, -2, "param2");
1136 }
1137
1138 /******************************************************************************/
1139 void warn_if_field_exists(lua_State *L, int table,
1140                 const char *name, const std::string &message)
1141 {
1142         lua_getfield(L, table, name);
1143         if (!lua_isnil(L, -1)) {
1144                 warningstream << "Field \"" << name << "\": "
1145                                 << message << std::endl;
1146                 infostream << script_get_backtrace(L) << std::endl;
1147         }
1148         lua_pop(L, 1);
1149 }
1150
1151 /******************************************************************************/
1152 int getenumfield(lua_State *L, int table,
1153                 const char *fieldname, const EnumString *spec, int default_)
1154 {
1155         int result = default_;
1156         string_to_enum(spec, result,
1157                         getstringfield_default(L, table, fieldname, ""));
1158         return result;
1159 }
1160
1161 /******************************************************************************/
1162 bool string_to_enum(const EnumString *spec, int &result,
1163                 const std::string &str)
1164 {
1165         const EnumString *esp = spec;
1166         while(esp->str){
1167                 if(str == std::string(esp->str)){
1168                         result = esp->num;
1169                         return true;
1170                 }
1171                 esp++;
1172         }
1173         return false;
1174 }
1175
1176 /******************************************************************************/
1177 ItemStack read_item(lua_State* L, int index, IItemDefManager *idef)
1178 {
1179         if(index < 0)
1180                 index = lua_gettop(L) + 1 + index;
1181
1182         if (lua_isnil(L, index)) {
1183                 return ItemStack();
1184         }
1185
1186         if (lua_isuserdata(L, index)) {
1187                 // Convert from LuaItemStack
1188                 LuaItemStack *o = LuaItemStack::checkobject(L, index);
1189                 return o->getItem();
1190         }
1191
1192         if (lua_isstring(L, index)) {
1193                 // Convert from itemstring
1194                 std::string itemstring = lua_tostring(L, index);
1195                 try
1196                 {
1197                         ItemStack item;
1198                         item.deSerialize(itemstring, idef);
1199                         return item;
1200                 }
1201                 catch(SerializationError &e)
1202                 {
1203                         warningstream<<"unable to create item from itemstring"
1204                                         <<": "<<itemstring<<std::endl;
1205                         return ItemStack();
1206                 }
1207         }
1208         else if(lua_istable(L, index))
1209         {
1210                 // Convert from table
1211                 std::string name = getstringfield_default(L, index, "name", "");
1212                 int count = getintfield_default(L, index, "count", 1);
1213                 int wear = getintfield_default(L, index, "wear", 0);
1214
1215                 ItemStack istack(name, count, wear, idef);
1216
1217                 // BACKWARDS COMPATIBLITY
1218                 std::string value = getstringfield_default(L, index, "metadata", "");
1219                 istack.metadata.setString("", value);
1220
1221                 // Get meta
1222                 lua_getfield(L, index, "meta");
1223                 int fieldstable = lua_gettop(L);
1224                 if (lua_istable(L, fieldstable)) {
1225                         lua_pushnil(L);
1226                         while (lua_next(L, fieldstable) != 0) {
1227                                 // key at index -2 and value at index -1
1228                                 std::string key = lua_tostring(L, -2);
1229                                 size_t value_len;
1230                                 const char *value_cs = lua_tolstring(L, -1, &value_len);
1231                                 std::string value(value_cs, value_len);
1232                                 istack.metadata.setString(key, value);
1233                                 lua_pop(L, 1); // removes value, keeps key for next iteration
1234                         }
1235                 }
1236
1237                 return istack;
1238         } else {
1239                 throw LuaError("Expecting itemstack, itemstring, table or nil");
1240         }
1241 }
1242
1243 /******************************************************************************/
1244 void push_tool_capabilities(lua_State *L,
1245                 const ToolCapabilities &toolcap)
1246 {
1247         lua_newtable(L);
1248         setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval);
1249         setintfield(L, -1, "max_drop_level", toolcap.max_drop_level);
1250         setintfield(L, -1, "punch_attack_uses", toolcap.punch_attack_uses);
1251                 // Create groupcaps table
1252                 lua_newtable(L);
1253                 // For each groupcap
1254                 for (const auto &gc_it : toolcap.groupcaps) {
1255                         // Create groupcap table
1256                         lua_newtable(L);
1257                         const std::string &name = gc_it.first;
1258                         const ToolGroupCap &groupcap = gc_it.second;
1259                         // Create subtable "times"
1260                         lua_newtable(L);
1261                         for (auto time : groupcap.times) {
1262                                 lua_pushinteger(L, time.first);
1263                                 lua_pushnumber(L, time.second);
1264                                 lua_settable(L, -3);
1265                         }
1266                         // Set subtable "times"
1267                         lua_setfield(L, -2, "times");
1268                         // Set simple parameters
1269                         setintfield(L, -1, "maxlevel", groupcap.maxlevel);
1270                         setintfield(L, -1, "uses", groupcap.uses);
1271                         // Insert groupcap table into groupcaps table
1272                         lua_setfield(L, -2, name.c_str());
1273                 }
1274                 // Set groupcaps table
1275                 lua_setfield(L, -2, "groupcaps");
1276                 //Create damage_groups table
1277                 lua_newtable(L);
1278                 // For each damage group
1279                 for (const auto &damageGroup : toolcap.damageGroups) {
1280                         // Create damage group table
1281                         lua_pushinteger(L, damageGroup.second);
1282                         lua_setfield(L, -2, damageGroup.first.c_str());
1283                 }
1284                 lua_setfield(L, -2, "damage_groups");
1285 }
1286
1287 /******************************************************************************/
1288 void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
1289 {
1290         InventoryList *invlist = inv->getList(name);
1291         if(invlist == NULL){
1292                 lua_pushnil(L);
1293                 return;
1294         }
1295         std::vector<ItemStack> items;
1296         for(u32 i=0; i<invlist->getSize(); i++)
1297                 items.push_back(invlist->getItem(i));
1298         push_items(L, items);
1299 }
1300
1301 /******************************************************************************/
1302 void read_inventory_list(lua_State *L, int tableindex,
1303                 Inventory *inv, const char *name, Server* srv, int forcesize)
1304 {
1305         if(tableindex < 0)
1306                 tableindex = lua_gettop(L) + 1 + tableindex;
1307         // If nil, delete list
1308         if(lua_isnil(L, tableindex)){
1309                 inv->deleteList(name);
1310                 return;
1311         }
1312         // Otherwise set list
1313         std::vector<ItemStack> items = read_items(L, tableindex,srv);
1314         int listsize = (forcesize != -1) ? forcesize : items.size();
1315         InventoryList *invlist = inv->addList(name, listsize);
1316         int index = 0;
1317         for(std::vector<ItemStack>::const_iterator
1318                         i = items.begin(); i != items.end(); ++i){
1319                 if(forcesize != -1 && index == forcesize)
1320                         break;
1321                 invlist->changeItem(index, *i);
1322                 index++;
1323         }
1324         while(forcesize != -1 && index < forcesize){
1325                 invlist->deleteItem(index);
1326                 index++;
1327         }
1328 }
1329
1330 /******************************************************************************/
1331 struct TileAnimationParams read_animation_definition(lua_State *L, int index)
1332 {
1333         if(index < 0)
1334                 index = lua_gettop(L) + 1 + index;
1335
1336         struct TileAnimationParams anim;
1337         anim.type = TAT_NONE;
1338         if (!lua_istable(L, index))
1339                 return anim;
1340
1341         anim.type = (TileAnimationType)
1342                 getenumfield(L, index, "type", es_TileAnimationType,
1343                 TAT_NONE);
1344         if (anim.type == TAT_VERTICAL_FRAMES) {
1345                 // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
1346                 anim.vertical_frames.aspect_w =
1347                         getintfield_default(L, index, "aspect_w", 16);
1348                 anim.vertical_frames.aspect_h =
1349                         getintfield_default(L, index, "aspect_h", 16);
1350                 anim.vertical_frames.length =
1351                         getfloatfield_default(L, index, "length", 1.0);
1352         } else if (anim.type == TAT_SHEET_2D) {
1353                 // {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
1354                 getintfield(L, index, "frames_w",
1355                         anim.sheet_2d.frames_w);
1356                 getintfield(L, index, "frames_h",
1357                         anim.sheet_2d.frames_h);
1358                 getfloatfield(L, index, "frame_length",
1359                         anim.sheet_2d.frame_length);
1360         }
1361
1362         return anim;
1363 }
1364
1365 /******************************************************************************/
1366 ToolCapabilities read_tool_capabilities(
1367                 lua_State *L, int table)
1368 {
1369         ToolCapabilities toolcap;
1370         getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
1371         getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
1372         getintfield(L, table, "punch_attack_uses", toolcap.punch_attack_uses);
1373         lua_getfield(L, table, "groupcaps");
1374         if(lua_istable(L, -1)){
1375                 int table_groupcaps = lua_gettop(L);
1376                 lua_pushnil(L);
1377                 while(lua_next(L, table_groupcaps) != 0){
1378                         // key at index -2 and value at index -1
1379                         std::string groupname = luaL_checkstring(L, -2);
1380                         if(lua_istable(L, -1)){
1381                                 int table_groupcap = lua_gettop(L);
1382                                 // This will be created
1383                                 ToolGroupCap groupcap;
1384                                 // Read simple parameters
1385                                 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
1386                                 getintfield(L, table_groupcap, "uses", groupcap.uses);
1387                                 // DEPRECATED: maxwear
1388                                 float maxwear = 0;
1389                                 if (getfloatfield(L, table_groupcap, "maxwear", maxwear)){
1390                                         if (maxwear != 0)
1391                                                 groupcap.uses = 1.0/maxwear;
1392                                         else
1393                                                 groupcap.uses = 0;
1394                                         warningstream << "Field \"maxwear\" is deprecated; "
1395                                                         << "replace with uses=1/maxwear" << std::endl;
1396                                         infostream << script_get_backtrace(L) << std::endl;
1397                                 }
1398                                 // Read "times" table
1399                                 lua_getfield(L, table_groupcap, "times");
1400                                 if(lua_istable(L, -1)){
1401                                         int table_times = lua_gettop(L);
1402                                         lua_pushnil(L);
1403                                         while(lua_next(L, table_times) != 0){
1404                                                 // key at index -2 and value at index -1
1405                                                 int rating = luaL_checkinteger(L, -2);
1406                                                 float time = luaL_checknumber(L, -1);
1407                                                 groupcap.times[rating] = time;
1408                                                 // removes value, keeps key for next iteration
1409                                                 lua_pop(L, 1);
1410                                         }
1411                                 }
1412                                 lua_pop(L, 1);
1413                                 // Insert groupcap into toolcap
1414                                 toolcap.groupcaps[groupname] = groupcap;
1415                         }
1416                         // removes value, keeps key for next iteration
1417                         lua_pop(L, 1);
1418                 }
1419         }
1420         lua_pop(L, 1);
1421
1422         lua_getfield(L, table, "damage_groups");
1423         if(lua_istable(L, -1)){
1424                 int table_damage_groups = lua_gettop(L);
1425                 lua_pushnil(L);
1426                 while(lua_next(L, table_damage_groups) != 0){
1427                         // key at index -2 and value at index -1
1428                         std::string groupname = luaL_checkstring(L, -2);
1429                         u16 value = luaL_checkinteger(L, -1);
1430                         toolcap.damageGroups[groupname] = value;
1431                         // removes value, keeps key for next iteration
1432                         lua_pop(L, 1);
1433                 }
1434         }
1435         lua_pop(L, 1);
1436         return toolcap;
1437 }
1438
1439 /******************************************************************************/
1440 void push_dig_params(lua_State *L,const DigParams &params)
1441 {
1442         lua_newtable(L);
1443         setboolfield(L, -1, "diggable", params.diggable);
1444         setfloatfield(L, -1, "time", params.time);
1445         setintfield(L, -1, "wear", params.wear);
1446 }
1447
1448 /******************************************************************************/
1449 void push_hit_params(lua_State *L,const HitParams &params)
1450 {
1451         lua_newtable(L);
1452         setintfield(L, -1, "hp", params.hp);
1453         setintfield(L, -1, "wear", params.wear);
1454 }
1455
1456 /******************************************************************************/
1457
1458 bool getflagsfield(lua_State *L, int table, const char *fieldname,
1459         FlagDesc *flagdesc, u32 *flags, u32 *flagmask)
1460 {
1461         lua_getfield(L, table, fieldname);
1462
1463         bool success = read_flags(L, -1, flagdesc, flags, flagmask);
1464
1465         lua_pop(L, 1);
1466
1467         return success;
1468 }
1469
1470 bool read_flags(lua_State *L, int index, FlagDesc *flagdesc,
1471         u32 *flags, u32 *flagmask)
1472 {
1473         if (lua_isstring(L, index)) {
1474                 std::string flagstr = lua_tostring(L, index);
1475                 *flags = readFlagString(flagstr, flagdesc, flagmask);
1476         } else if (lua_istable(L, index)) {
1477                 *flags = read_flags_table(L, index, flagdesc, flagmask);
1478         } else {
1479                 return false;
1480         }
1481
1482         return true;
1483 }
1484
1485 u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
1486 {
1487         u32 flags = 0, mask = 0;
1488         char fnamebuf[64] = "no";
1489
1490         for (int i = 0; flagdesc[i].name; i++) {
1491                 bool result;
1492
1493                 if (getboolfield(L, table, flagdesc[i].name, result)) {
1494                         mask |= flagdesc[i].flag;
1495                         if (result)
1496                                 flags |= flagdesc[i].flag;
1497                 }
1498
1499                 strlcpy(fnamebuf + 2, flagdesc[i].name, sizeof(fnamebuf) - 2);
1500                 if (getboolfield(L, table, fnamebuf, result))
1501                         mask |= flagdesc[i].flag;
1502         }
1503
1504         if (flagmask)
1505                 *flagmask = mask;
1506
1507         return flags;
1508 }
1509
1510 void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask)
1511 {
1512         std::string flagstring = writeFlagString(flags, flagdesc, flagmask);
1513         lua_pushlstring(L, flagstring.c_str(), flagstring.size());
1514 }
1515
1516 /******************************************************************************/
1517 /* Lua Stored data!                                                           */
1518 /******************************************************************************/
1519
1520 /******************************************************************************/
1521 void read_groups(lua_State *L, int index, ItemGroupList &result)
1522 {
1523         if (!lua_istable(L,index))
1524                 return;
1525         result.clear();
1526         lua_pushnil(L);
1527         if (index < 0)
1528                 index -= 1;
1529         while (lua_next(L, index) != 0) {
1530                 // key at index -2 and value at index -1
1531                 std::string name = luaL_checkstring(L, -2);
1532                 int rating = luaL_checkinteger(L, -1);
1533                 // zero rating indicates not in the group
1534                 if (rating != 0)
1535                         result[name] = rating;
1536                 // removes value, keeps key for next iteration
1537                 lua_pop(L, 1);
1538         }
1539 }
1540
1541 /******************************************************************************/
1542 void push_groups(lua_State *L, const ItemGroupList &groups)
1543 {
1544         lua_newtable(L);
1545         for (const auto &group : groups) {
1546                 lua_pushnumber(L, group.second);
1547                 lua_setfield(L, -2, group.first.c_str());
1548         }
1549 }
1550
1551 /******************************************************************************/
1552 void push_items(lua_State *L, const std::vector<ItemStack> &items)
1553 {
1554         lua_createtable(L, items.size(), 0);
1555         for (u32 i = 0; i != items.size(); i++) {
1556                 LuaItemStack::create(L, items[i]);
1557                 lua_rawseti(L, -2, i + 1);
1558         }
1559 }
1560
1561 /******************************************************************************/
1562 std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
1563 {
1564         if(index < 0)
1565                 index = lua_gettop(L) + 1 + index;
1566
1567         std::vector<ItemStack> items;
1568         luaL_checktype(L, index, LUA_TTABLE);
1569         lua_pushnil(L);
1570         while (lua_next(L, index)) {
1571                 s32 key = luaL_checkinteger(L, -2);
1572                 if (key < 1) {
1573                         throw LuaError("Invalid inventory list index");
1574                 }
1575                 if (items.size() < (u32) key) {
1576                         items.resize(key);
1577                 }
1578                 items[key - 1] = read_item(L, -1, srv->idef());
1579                 lua_pop(L, 1);
1580         }
1581         return items;
1582 }
1583
1584 /******************************************************************************/
1585 void luaentity_get(lua_State *L, u16 id)
1586 {
1587         // Get luaentities[i]
1588         lua_getglobal(L, "core");
1589         lua_getfield(L, -1, "luaentities");
1590         luaL_checktype(L, -1, LUA_TTABLE);
1591         lua_pushnumber(L, id);
1592         lua_gettable(L, -2);
1593         lua_remove(L, -2); // Remove luaentities
1594         lua_remove(L, -2); // Remove core
1595 }
1596
1597 /******************************************************************************/
1598 bool read_noiseparams(lua_State *L, int index, NoiseParams *np)
1599 {
1600         if (index < 0)
1601                 index = lua_gettop(L) + 1 + index;
1602
1603         if (!lua_istable(L, index))
1604                 return false;
1605
1606         getfloatfield(L, index, "offset",      np->offset);
1607         getfloatfield(L, index, "scale",       np->scale);
1608         getfloatfield(L, index, "persist",     np->persist);
1609         getfloatfield(L, index, "persistence", np->persist);
1610         getfloatfield(L, index, "lacunarity",  np->lacunarity);
1611         getintfield(L,   index, "seed",        np->seed);
1612         getintfield(L,   index, "octaves",     np->octaves);
1613
1614         u32 flags    = 0;
1615         u32 flagmask = 0;
1616         np->flags = getflagsfield(L, index, "flags", flagdesc_noiseparams,
1617                 &flags, &flagmask) ? flags : NOISE_FLAG_DEFAULTS;
1618
1619         lua_getfield(L, index, "spread");
1620         np->spread  = read_v3f(L, -1);
1621         lua_pop(L, 1);
1622
1623         return true;
1624 }
1625
1626 void push_noiseparams(lua_State *L, NoiseParams *np)
1627 {
1628         lua_newtable(L);
1629         push_float_string(L, np->offset);
1630         lua_setfield(L, -2, "offset");
1631         push_float_string(L, np->scale);
1632         lua_setfield(L, -2, "scale");
1633         push_float_string(L, np->persist);
1634         lua_setfield(L, -2, "persistence");
1635         push_float_string(L, np->lacunarity);
1636         lua_setfield(L, -2, "lacunarity");
1637         lua_pushnumber(L, np->seed);
1638         lua_setfield(L, -2, "seed");
1639         lua_pushnumber(L, np->octaves);
1640         lua_setfield(L, -2, "octaves");
1641
1642         push_flags_string(L, flagdesc_noiseparams, np->flags,
1643                 np->flags);
1644         lua_setfield(L, -2, "flags");
1645
1646         push_v3_float_string(L, np->spread);
1647         lua_setfield(L, -2, "spread");
1648 }
1649
1650 /******************************************************************************/
1651 // Returns depth of json value tree
1652 static int push_json_value_getdepth(const Json::Value &value)
1653 {
1654         if (!value.isArray() && !value.isObject())
1655                 return 1;
1656
1657         int maxdepth = 0;
1658         for (const auto &it : value) {
1659                 int elemdepth = push_json_value_getdepth(it);
1660                 if (elemdepth > maxdepth)
1661                         maxdepth = elemdepth;
1662         }
1663         return maxdepth + 1;
1664 }
1665 // Recursive function to convert JSON --> Lua table
1666 static bool push_json_value_helper(lua_State *L, const Json::Value &value,
1667                 int nullindex)
1668 {
1669         switch(value.type()) {
1670                 case Json::nullValue:
1671                 default:
1672                         lua_pushvalue(L, nullindex);
1673                         break;
1674                 case Json::intValue:
1675                         lua_pushinteger(L, value.asInt());
1676                         break;
1677                 case Json::uintValue:
1678                         lua_pushinteger(L, value.asUInt());
1679                         break;
1680                 case Json::realValue:
1681                         lua_pushnumber(L, value.asDouble());
1682                         break;
1683                 case Json::stringValue:
1684                         {
1685                                 const char *str = value.asCString();
1686                                 lua_pushstring(L, str ? str : "");
1687                         }
1688                         break;
1689                 case Json::booleanValue:
1690                         lua_pushboolean(L, value.asInt());
1691                         break;
1692                 case Json::arrayValue:
1693                         lua_newtable(L);
1694                         for (Json::Value::const_iterator it = value.begin();
1695                                         it != value.end(); ++it) {
1696                                 push_json_value_helper(L, *it, nullindex);
1697                                 lua_rawseti(L, -2, it.index() + 1);
1698                         }
1699                         break;
1700                 case Json::objectValue:
1701                         lua_newtable(L);
1702                         for (Json::Value::const_iterator it = value.begin();
1703                                         it != value.end(); ++it) {
1704 #ifndef JSONCPP_STRING
1705                                 const char *str = it.memberName();
1706                                 lua_pushstring(L, str ? str : "");
1707 #else
1708                                 std::string str = it.name();
1709                                 lua_pushstring(L, str.c_str());
1710 #endif
1711                                 push_json_value_helper(L, *it, nullindex);
1712                                 lua_rawset(L, -3);
1713                         }
1714                         break;
1715         }
1716         return true;
1717 }
1718 // converts JSON --> Lua table; returns false if lua stack limit exceeded
1719 // nullindex: Lua stack index of value to use in place of JSON null
1720 bool push_json_value(lua_State *L, const Json::Value &value, int nullindex)
1721 {
1722         if(nullindex < 0)
1723                 nullindex = lua_gettop(L) + 1 + nullindex;
1724
1725         int depth = push_json_value_getdepth(value);
1726
1727         // The maximum number of Lua stack slots used at each recursion level
1728         // of push_json_value_helper is 2, so make sure there a depth * 2 slots
1729         if (lua_checkstack(L, depth * 2))
1730                 return push_json_value_helper(L, value, nullindex);
1731
1732         return false;
1733 }
1734
1735 // Converts Lua table --> JSON
1736 void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion)
1737 {
1738         if (recursion > 16) {
1739                 throw SerializationError("Maximum recursion depth exceeded");
1740         }
1741         int type = lua_type(L, index);
1742         if (type == LUA_TBOOLEAN) {
1743                 root = (bool) lua_toboolean(L, index);
1744         } else if (type == LUA_TNUMBER) {
1745                 root = lua_tonumber(L, index);
1746         } else if (type == LUA_TSTRING) {
1747                 size_t len;
1748                 const char *str = lua_tolstring(L, index, &len);
1749                 root = std::string(str, len);
1750         } else if (type == LUA_TTABLE) {
1751                 lua_pushnil(L);
1752                 while (lua_next(L, index)) {
1753                         // Key is at -2 and value is at -1
1754                         Json::Value value;
1755                         read_json_value(L, value, lua_gettop(L), recursion + 1);
1756
1757                         Json::ValueType roottype = root.type();
1758                         int keytype = lua_type(L, -1);
1759                         if (keytype == LUA_TNUMBER) {
1760                                 lua_Number key = lua_tonumber(L, -1);
1761                                 if (roottype != Json::nullValue && roottype != Json::arrayValue) {
1762                                         throw SerializationError("Can't mix array and object values in JSON");
1763                                 } else if (key < 1) {
1764                                         throw SerializationError("Can't use zero-based or negative indexes in JSON");
1765                                 } else if (floor(key) != key) {
1766                                         throw SerializationError("Can't use indexes with a fractional part in JSON");
1767                                 }
1768                                 root[(Json::ArrayIndex) key - 1] = value;
1769                         } else if (keytype == LUA_TSTRING) {
1770                                 if (roottype != Json::nullValue && roottype != Json::objectValue) {
1771                                         throw SerializationError("Can't mix array and object values in JSON");
1772                                 }
1773                                 root[lua_tostring(L, -1)] = value;
1774                         } else {
1775                                 throw SerializationError("Lua key to convert to JSON is not a string or number");
1776                         }
1777                 }
1778         } else if (type == LUA_TNIL) {
1779                 root = Json::nullValue;
1780         } else {
1781                 throw SerializationError("Can only store booleans, numbers, strings, objects, arrays, and null in JSON");
1782         }
1783         lua_pop(L, 1); // Pop value
1784 }
1785
1786 void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm,
1787         bool hitpoint)
1788 {
1789         lua_newtable(L);
1790         if (pointed.type == POINTEDTHING_NODE) {
1791                 lua_pushstring(L, "node");
1792                 lua_setfield(L, -2, "type");
1793                 push_v3s16(L, pointed.node_undersurface);
1794                 lua_setfield(L, -2, "under");
1795                 push_v3s16(L, pointed.node_abovesurface);
1796                 lua_setfield(L, -2, "above");
1797         } else if (pointed.type == POINTEDTHING_OBJECT) {
1798                 lua_pushstring(L, "object");
1799                 lua_setfield(L, -2, "type");
1800
1801                 if (csm) {
1802                         lua_pushinteger(L, pointed.object_id);
1803                         lua_setfield(L, -2, "id");
1804                 } else {
1805                         push_objectRef(L, pointed.object_id);
1806                         lua_setfield(L, -2, "ref");
1807                 }
1808         } else {
1809                 lua_pushstring(L, "nothing");
1810                 lua_setfield(L, -2, "type");
1811         }
1812         if (hitpoint && (pointed.type != POINTEDTHING_NOTHING)) {
1813                 push_v3f(L, pointed.intersection_point / BS); // convert to node coords
1814                 lua_setfield(L, -2, "intersection_point");
1815                 push_v3s16(L, pointed.intersection_normal);
1816                 lua_setfield(L, -2, "intersection_normal");
1817                 lua_pushinteger(L, pointed.box_id + 1); // change to Lua array index
1818                 lua_setfield(L, -2, "box_id");
1819         }
1820 }
1821
1822 void push_objectRef(lua_State *L, const u16 id)
1823 {
1824         // Get core.object_refs[i]
1825         lua_getglobal(L, "core");
1826         lua_getfield(L, -1, "object_refs");
1827         luaL_checktype(L, -1, LUA_TTABLE);
1828         lua_pushnumber(L, id);
1829         lua_gettable(L, -2);
1830         lua_remove(L, -2); // object_refs
1831         lua_remove(L, -2); // core
1832 }
1833
1834 void read_hud_element(lua_State *L, HudElement *elem)
1835 {
1836         elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
1837                                                                         es_HudElementType, HUD_ELEM_TEXT);
1838
1839         lua_getfield(L, 2, "position");
1840         elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1841         lua_pop(L, 1);
1842
1843         lua_getfield(L, 2, "scale");
1844         elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1845         lua_pop(L, 1);
1846
1847         lua_getfield(L, 2, "size");
1848         elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32();
1849         lua_pop(L, 1);
1850
1851         elem->name    = getstringfield_default(L, 2, "name", "");
1852         elem->text    = getstringfield_default(L, 2, "text", "");
1853         elem->number  = getintfield_default(L, 2, "number", 0);
1854         elem->item    = getintfield_default(L, 2, "item", 0);
1855         elem->dir     = getintfield_default(L, 2, "direction", 0);
1856         elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX,
1857                         getintfield_default(L, 2, "z_index", 0)));
1858
1859         // Deprecated, only for compatibility's sake
1860         if (elem->dir == 0)
1861                 elem->dir = getintfield_default(L, 2, "dir", 0);
1862
1863         lua_getfield(L, 2, "alignment");
1864         elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1865         lua_pop(L, 1);
1866
1867         lua_getfield(L, 2, "offset");
1868         elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1869         lua_pop(L, 1);
1870
1871         lua_getfield(L, 2, "world_pos");
1872         elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
1873         lua_pop(L, 1);
1874
1875         /* check for known deprecated element usage */
1876         if ((elem->type  == HUD_ELEM_STATBAR) && (elem->size == v2s32()))
1877                 log_deprecated(L,"Deprecated usage of statbar without size!");
1878 }
1879
1880 void push_hud_element(lua_State *L, HudElement *elem)
1881 {
1882         lua_newtable(L);
1883
1884         lua_pushstring(L, es_HudElementType[(u8)elem->type].str);
1885         lua_setfield(L, -2, "type");
1886
1887         push_v2f(L, elem->pos);
1888         lua_setfield(L, -2, "position");
1889
1890         lua_pushstring(L, elem->name.c_str());
1891         lua_setfield(L, -2, "name");
1892
1893         push_v2f(L, elem->scale);
1894         lua_setfield(L, -2, "scale");
1895
1896         lua_pushstring(L, elem->text.c_str());
1897         lua_setfield(L, -2, "text");
1898
1899         lua_pushnumber(L, elem->number);
1900         lua_setfield(L, -2, "number");
1901
1902         lua_pushnumber(L, elem->item);
1903         lua_setfield(L, -2, "item");
1904
1905         lua_pushnumber(L, elem->dir);
1906         lua_setfield(L, -2, "direction");
1907
1908         push_v2f(L, elem->offset);
1909         lua_setfield(L, -2, "offset");
1910
1911         push_v2f(L, elem->align);
1912         lua_setfield(L, -2, "alignment");
1913
1914         push_v2s32(L, elem->size);
1915         lua_setfield(L, -2, "size");
1916
1917         // Deprecated, only for compatibility's sake
1918         lua_pushnumber(L, elem->dir);
1919         lua_setfield(L, -2, "dir");
1920
1921         push_v3f(L, elem->world_pos);
1922         lua_setfield(L, -2, "world_pos");
1923
1924         lua_pushnumber(L, elem->z_index);
1925         lua_setfield(L, -2, "z_index");
1926 }
1927
1928 HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
1929 {
1930         HudElementStat stat = HUD_STAT_NUMBER;
1931         if (lua_isstring(L, 3)) {
1932                 int statint;
1933                 std::string statstr = lua_tostring(L, 3);
1934                 stat = string_to_enum(es_HudElementStat, statint, statstr) ?
1935                                 (HudElementStat)statint : stat;
1936         }
1937
1938         switch (stat) {
1939                 case HUD_STAT_POS:
1940                         elem->pos = read_v2f(L, 4);
1941                         *value = &elem->pos;
1942                         break;
1943                 case HUD_STAT_NAME:
1944                         elem->name = luaL_checkstring(L, 4);
1945                         *value = &elem->name;
1946                         break;
1947                 case HUD_STAT_SCALE:
1948                         elem->scale = read_v2f(L, 4);
1949                         *value = &elem->scale;
1950                         break;
1951                 case HUD_STAT_TEXT:
1952                         elem->text = luaL_checkstring(L, 4);
1953                         *value = &elem->text;
1954                         break;
1955                 case HUD_STAT_NUMBER:
1956                         elem->number = luaL_checknumber(L, 4);
1957                         *value = &elem->number;
1958                         break;
1959                 case HUD_STAT_ITEM:
1960                         elem->item = luaL_checknumber(L, 4);
1961                         *value = &elem->item;
1962                         break;
1963                 case HUD_STAT_DIR:
1964                         elem->dir = luaL_checknumber(L, 4);
1965                         *value = &elem->dir;
1966                         break;
1967                 case HUD_STAT_ALIGN:
1968                         elem->align = read_v2f(L, 4);
1969                         *value = &elem->align;
1970                         break;
1971                 case HUD_STAT_OFFSET:
1972                         elem->offset = read_v2f(L, 4);
1973                         *value = &elem->offset;
1974                         break;
1975                 case HUD_STAT_WORLD_POS:
1976                         elem->world_pos = read_v3f(L, 4);
1977                         *value = &elem->world_pos;
1978                         break;
1979                 case HUD_STAT_SIZE:
1980                         elem->size = read_v2s32(L, 4);
1981                         *value = &elem->size;
1982                         break;
1983                 case HUD_STAT_Z_INDEX:
1984                         elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4)));
1985                         *value = &elem->z_index;
1986                         break;
1987         }
1988         return stat;
1989 }