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