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