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