]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi.cpp
Reshape LuaEntityCAO implementation a bit and make TNT to blink
[minetest.git] / src / scriptapi.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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
20 #include "scriptapi.h"
21
22 #include <iostream>
23 extern "C" {
24 #include <lua.h>
25 #include <lualib.h>
26 #include <lauxlib.h>
27 }
28
29 #include "log.h"
30 #include "server.h"
31 #include "porting.h"
32 #include "filesys.h"
33 #include "serverobject.h"
34 #include "script.h"
35 //#include "luna.h"
36 #include "luaentity_common.h"
37 #include "content_sao.h" // For LuaEntitySAO
38 #include "tooldef.h"
39 #include "nodedef.h"
40 #include "craftdef.h"
41 #include "main.h" // For g_settings
42 #include "settings.h" // For accessing g_settings
43
44 /*
45 TODO:
46 - Random node triggers (like grass growth)
47 - All kinds of callbacks
48 - Object visual client-side stuff
49         - Blink effect
50         - Spritesheets and animation
51 - LuaNodeMetadata
52         blockdef.metadata_name =
53                 ""
54                 "sign"
55                 "furnace"
56                 "chest"
57                 "locked_chest"
58                 "lua"
59         - Stores an inventory and stuff in a Settings object
60         meta.inventory_add_list("main")
61         blockdef.on_inventory_modified
62         meta.set("owner", playername)
63         meta.get("owner")
64 - Item definition (actually, only CraftItem)
65 - (not scripting) Putting items in node metadata (virtual)
66 */
67
68 static void stackDump(lua_State *L, std::ostream &o)
69 {
70   int i;
71   int top = lua_gettop(L);
72   for (i = 1; i <= top; i++) {  /* repeat for each level */
73         int t = lua_type(L, i);
74         switch (t) {
75
76           case LUA_TSTRING:  /* strings */
77                 o<<"\""<<lua_tostring(L, i)<<"\"";
78                 break;
79
80           case LUA_TBOOLEAN:  /* booleans */
81                 o<<(lua_toboolean(L, i) ? "true" : "false");
82                 break;
83
84           case LUA_TNUMBER:  /* numbers */ {
85                 char buf[10];
86                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
87                 o<<buf;
88                 break; }
89
90           default:  /* other values */
91                 o<<lua_typename(L, t);
92                 break;
93
94         }
95         o<<" ";
96   }
97   o<<std::endl;
98 }
99
100 static void realitycheck(lua_State *L)
101 {
102         int top = lua_gettop(L);
103         if(top >= 30){
104                 dstream<<"Stack is over 30:"<<std::endl;
105                 stackDump(L, dstream);
106                 script_error(L, "Stack is over 30 (reality check)");
107         }
108 }
109
110 class StackUnroller
111 {
112 private:
113         lua_State *m_lua;
114         int m_original_top;
115 public:
116         StackUnroller(lua_State *L):
117                 m_lua(L),
118                 m_original_top(-1)
119         {
120                 m_original_top = lua_gettop(m_lua); // store stack height
121         }
122         ~StackUnroller()
123         {
124                 lua_settop(m_lua, m_original_top); // restore stack height
125         }
126 };
127
128 static v3f readFloatPos(lua_State *L, int index)
129 {
130         v3f pos;
131         luaL_checktype(L, index, LUA_TTABLE);
132         lua_getfield(L, index, "x");
133         pos.X = lua_tonumber(L, -1);
134         lua_pop(L, 1);
135         lua_getfield(L, index, "y");
136         pos.Y = lua_tonumber(L, -1);
137         lua_pop(L, 1);
138         lua_getfield(L, index, "z");
139         pos.Z = lua_tonumber(L, -1);
140         lua_pop(L, 1);
141         pos *= BS; // Scale to internal format
142         return pos;
143 }
144
145 static void pushpos(lua_State *L, v3s16 p)
146 {
147         lua_newtable(L);
148         lua_pushnumber(L, p.X);
149         lua_setfield(L, -2, "x");
150         lua_pushnumber(L, p.Y);
151         lua_setfield(L, -2, "y");
152         lua_pushnumber(L, p.Z);
153         lua_setfield(L, -2, "z");
154 }
155
156 static v3s16 readpos(lua_State *L, int index)
157 {
158         // Correct rounding at <0
159         v3f pf = readFloatPos(L, index);
160         return floatToInt(pf, BS);
161 }
162
163 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
164 {
165         lua_newtable(L);
166         lua_pushstring(L, ndef->get(n).name.c_str());
167         lua_setfield(L, -2, "name");
168         lua_pushnumber(L, n.getParam1());
169         lua_setfield(L, -2, "param1");
170         lua_pushnumber(L, n.getParam2());
171         lua_setfield(L, -2, "param2");
172 }
173
174 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
175 {
176         lua_getfield(L, index, "name");
177         const char *name = lua_tostring(L, -1);
178         lua_pop(L, 1);
179         u8 param1;
180         lua_getfield(L, index, "param1");
181         if(lua_isnil(L, -1))
182                 param1 = 0;
183         else
184                 param1 = lua_tonumber(L, -1);
185         lua_pop(L, 1);
186         u8 param2;
187         lua_getfield(L, index, "param2");
188         if(lua_isnil(L, -1))
189                 param2 = 0;
190         else
191                 param2 = lua_tonumber(L, -1);
192         lua_pop(L, 1);
193         return MapNode(ndef, name, param1, param2);
194 }
195
196 static video::SColor readARGB8(lua_State *L, int index)
197 {
198         video::SColor color;
199         luaL_checktype(L, index, LUA_TTABLE);
200         lua_getfield(L, index, "a");
201         if(lua_isnumber(L, -1))
202                 color.setAlpha(lua_tonumber(L, -1));
203         lua_pop(L, 1);
204         lua_getfield(L, index, "r");
205         color.setRed(lua_tonumber(L, -1));
206         lua_pop(L, 1);
207         lua_getfield(L, index, "g");
208         color.setGreen(lua_tonumber(L, -1));
209         lua_pop(L, 1);
210         lua_getfield(L, index, "b");
211         color.setBlue(lua_tonumber(L, -1));
212         lua_pop(L, 1);
213         return color;
214 }
215
216 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
217 {
218         core::aabbox3d<f32> box;
219         if(lua_istable(L, -1)){
220                 lua_rawgeti(L, -1, 1);
221                 box.MinEdge.X = lua_tonumber(L, -1) * scale;
222                 lua_pop(L, 1);
223                 lua_rawgeti(L, -1, 2);
224                 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
225                 lua_pop(L, 1);
226                 lua_rawgeti(L, -1, 3);
227                 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
228                 lua_pop(L, 1);
229                 lua_rawgeti(L, -1, 4);
230                 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
231                 lua_pop(L, 1);
232                 lua_rawgeti(L, -1, 5);
233                 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
234                 lua_pop(L, 1);
235                 lua_rawgeti(L, -1, 6);
236                 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
237                 lua_pop(L, 1);
238         }
239         return box;
240 }
241
242 static bool getstringfield(lua_State *L, int table,
243                 const char *fieldname, std::string &result)
244 {
245         lua_getfield(L, table, fieldname);
246         bool got = false;
247         if(lua_isstring(L, -1)){
248                 result = lua_tostring(L, -1);
249                 got = true;
250         }
251         lua_pop(L, 1);
252         return got;
253 }
254
255 static bool getintfield(lua_State *L, int table,
256                 const char *fieldname, int &result)
257 {
258         lua_getfield(L, table, fieldname);
259         bool got = false;
260         if(lua_isnumber(L, -1)){
261                 result = lua_tonumber(L, -1);
262                 got = true;
263         }
264         lua_pop(L, 1);
265         return got;
266 }
267
268 static bool getfloatfield(lua_State *L, int table,
269                 const char *fieldname, float &result)
270 {
271         lua_getfield(L, table, fieldname);
272         bool got = false;
273         if(lua_isnumber(L, -1)){
274                 result = lua_tonumber(L, -1);
275                 got = true;
276         }
277         lua_pop(L, 1);
278         return got;
279 }
280
281 static bool getboolfield(lua_State *L, int table,
282                 const char *fieldname, bool &result)
283 {
284         lua_getfield(L, table, fieldname);
285         bool got = false;
286         if(lua_isboolean(L, -1)){
287                 result = lua_toboolean(L, -1);
288                 got = true;
289         }
290         lua_pop(L, 1);
291         return got;
292 }
293
294 static std::string getstringfield_default(lua_State *L, int table,
295                 const char *fieldname, const std::string &default_)
296 {
297         std::string result = default_;
298         getstringfield(L, table, fieldname, result);
299         return result;
300 }
301
302 static int getintfield_default(lua_State *L, int table,
303                 const char *fieldname, int default_)
304 {
305         int result = default_;
306         getintfield(L, table, fieldname, result);
307         return result;
308 }
309
310 static bool getboolfield_default(lua_State *L, int table,
311                 const char *fieldname, bool default_)
312 {
313         bool result = default_;
314         getboolfield(L, table, fieldname, result);
315         return result;
316 }
317
318 struct EnumString
319 {
320         int num;
321         const char *str;
322 };
323
324 static bool string_to_enum(const EnumString *spec, int &result,
325                 const std::string &str)
326 {
327         const EnumString *esp = spec;
328         while(esp->str){
329                 if(str == std::string(esp->str)){
330                         result = esp->num;
331                         return true;
332                 }
333                 esp++;
334         }
335         return false;
336 }
337
338 /*static bool enum_to_string(const EnumString *spec, std::string &result,
339                 int num)
340 {
341         const EnumString *esp = spec;
342         while(esp){
343                 if(num == esp->num){
344                         result = esp->str;
345                         return true;
346                 }
347                 esp++;
348         }
349         return false;
350 }*/
351
352 static int getenumfield(lua_State *L, int table,
353                 const char *fieldname, const EnumString *spec, int default_)
354 {
355         int result = default_;
356         string_to_enum(spec, result,
357                         getstringfield_default(L, table, fieldname, ""));
358         return result;
359 }
360
361 struct EnumString es_DrawType[] =
362 {
363         {NDT_NORMAL, "normal"},
364         {NDT_AIRLIKE, "airlike"},
365         {NDT_LIQUID, "liquid"},
366         {NDT_FLOWINGLIQUID, "flowingliquid"},
367         {NDT_GLASSLIKE, "glasslike"},
368         {NDT_ALLFACES, "allfaces"},
369         {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
370         {NDT_TORCHLIKE, "torchlike"},
371         {NDT_SIGNLIKE, "signlike"},
372         {NDT_PLANTLIKE, "plantlike"},
373         {NDT_FENCELIKE, "fencelike"},
374         {NDT_RAILLIKE, "raillike"},
375         {0, NULL},
376 };
377
378 struct EnumString es_ContentParamType[] =
379 {
380         {CPT_NONE, "none"},
381         {CPT_LIGHT, "light"},
382         {CPT_MINERAL, "mineral"},
383         {CPT_FACEDIR_SIMPLE, "facedir_simple"},
384 };
385
386 struct EnumString es_LiquidType[] =
387 {
388         {LIQUID_NONE, "none"},
389         {LIQUID_FLOWING, "flowing"},
390         {LIQUID_SOURCE, "source"},
391 };
392
393 struct EnumString es_NodeBoxType[] =
394 {
395         {NODEBOX_REGULAR, "regular"},
396         {NODEBOX_FIXED, "fixed"},
397         {NODEBOX_WALLMOUNTED, "wallmounted"},
398 };
399
400 struct EnumString es_Diggability[] =
401 {
402         {DIGGABLE_NOT, "not"},
403         {DIGGABLE_NORMAL, "normal"},
404         {DIGGABLE_CONSTANT, "constant"},
405 };
406
407 /*
408         Global functions
409 */
410
411 static int l_register_nodedef_defaults(lua_State *L)
412 {
413         luaL_checktype(L, 1, LUA_TTABLE);
414
415         lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
416         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
417
418         return 0;
419 }
420
421 // Register new object prototype
422 // register_entity(name, prototype)
423 static int l_register_entity(lua_State *L)
424 {
425         const char *name = luaL_checkstring(L, 1);
426         infostream<<"register_entity: "<<name<<std::endl;
427         luaL_checktype(L, 2, LUA_TTABLE);
428
429         // Get minetest.registered_entities
430         lua_getglobal(L, "minetest");
431         lua_getfield(L, -1, "registered_entities");
432         luaL_checktype(L, -1, LUA_TTABLE);
433         int registered_entities = lua_gettop(L);
434         lua_pushvalue(L, 2); // Object = param 2 -> stack top
435         // registered_entities[name] = object
436         lua_setfield(L, registered_entities, name);
437         
438         // Get registered object to top of stack
439         lua_pushvalue(L, 2);
440         
441         // Set __index to point to itself
442         lua_pushvalue(L, -1);
443         lua_setfield(L, -2, "__index");
444
445         // Set metatable.__index = metatable
446         luaL_getmetatable(L, "minetest.entity");
447         lua_pushvalue(L, -1); // duplicate metatable
448         lua_setfield(L, -2, "__index");
449         // Set object metatable
450         lua_setmetatable(L, -2);
451
452         return 0; /* number of results */
453 }
454
455 // register_tool(name, {lots of stuff})
456 static int l_register_tool(lua_State *L)
457 {
458         const char *name = luaL_checkstring(L, 1);
459         infostream<<"register_tool: "<<name<<std::endl;
460         luaL_checktype(L, 2, LUA_TTABLE);
461         int table = 2;
462
463         // Get server from registry
464         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
465         Server *server = (Server*)lua_touserdata(L, -1);
466         // And get the writable tool definition manager from the server
467         IWritableToolDefManager *tooldef =
468                         server->getWritableToolDefManager();
469         
470         ToolDefinition def;
471         
472         getstringfield(L, table, "image", def.imagename);
473         getfloatfield(L, table, "basetime", def.properties.basetime);
474         getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
475         getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
476         getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
477         getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
478         getfloatfield(L, table, "basedurability", def.properties.basedurability);
479         getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
480         getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
481         getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
482         getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
483
484         tooldef->registerTool(name, def);
485         return 0; /* number of results */
486 }
487
488 // register_node(name, {lots of stuff})
489 static int l_register_node(lua_State *L)
490 {
491         const char *name = luaL_checkstring(L, 1);
492         infostream<<"register_node: "<<name<<std::endl;
493         luaL_checktype(L, 2, LUA_TTABLE);
494         int nodedef_table = 2;
495
496         // Get server from registry
497         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
498         Server *server = (Server*)lua_touserdata(L, -1);
499         // And get the writable node definition manager from the server
500         IWritableNodeDefManager *nodedef =
501                         server->getWritableNodeDefManager();
502         
503         // Get default node definition from registry
504         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
505         int nodedef_default = lua_gettop(L);
506
507         /*
508                 Add to minetest.registered_nodes with default as metatable
509         */
510         
511         // Get the node definition table given as parameter
512         lua_pushvalue(L, nodedef_table);
513
514         // Set __index to point to itself
515         lua_pushvalue(L, -1);
516         lua_setfield(L, -2, "__index");
517
518         // Set nodedef_default as metatable for the definition
519         lua_pushvalue(L, nodedef_default);
520         lua_setmetatable(L, nodedef_table);
521         
522         // minetest.registered_nodes[name] = nodedef
523         lua_getglobal(L, "minetest");
524         lua_getfield(L, -1, "registered_nodes");
525         luaL_checktype(L, -1, LUA_TTABLE);
526         lua_pushstring(L, name);
527         lua_pushvalue(L, nodedef_table);
528         lua_settable(L, -3);
529
530         /*
531                 Create definition
532         */
533         
534         ContentFeatures f;
535
536         // Default to getting the corresponding NodeItem when dug
537         f.dug_item = std::string("NodeItem \"")+name+"\" 1";
538         
539         // Default to unknown_block.png as all textures
540         f.setAllTextures("unknown_block.png");
541
542         /*
543                 Read definiton from Lua
544         */
545
546         f.name = name;
547         
548         /* Visual definition */
549
550         f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
551                         NDT_NORMAL);
552         getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
553
554         lua_getfield(L, nodedef_table, "tile_images");
555         if(lua_istable(L, -1)){
556                 int table = lua_gettop(L);
557                 lua_pushnil(L);
558                 int i = 0;
559                 while(lua_next(L, table) != 0){
560                         // key at index -2 and value at index -1
561                         if(lua_isstring(L, -1))
562                                 f.tname_tiles[i] = lua_tostring(L, -1);
563                         else
564                                 f.tname_tiles[i] = "";
565                         // removes value, keeps key for next iteration
566                         lua_pop(L, 1);
567                         i++;
568                         if(i==6){
569                                 lua_pop(L, 1);
570                                 break;
571                         }
572                 }
573                 // Copy last value to all remaining textures
574                 if(i >= 1){
575                         std::string lastname = f.tname_tiles[i-1];
576                         while(i < 6){
577                                 f.tname_tiles[i] = lastname;
578                                 i++;
579                         }
580                 }
581         }
582         lua_pop(L, 1);
583
584         getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
585
586         lua_getfield(L, nodedef_table, "special_materials");
587         if(lua_istable(L, -1)){
588                 int table = lua_gettop(L);
589                 lua_pushnil(L);
590                 int i = 0;
591                 while(lua_next(L, table) != 0){
592                         // key at index -2 and value at index -1
593                         int smtable = lua_gettop(L);
594                         std::string tname = getstringfield_default(
595                                         L, smtable, "image", "");
596                         bool backface_culling = getboolfield_default(
597                                         L, smtable, "backface_culling", true);
598                         MaterialSpec mspec(tname, backface_culling);
599                         f.setSpecialMaterial(i, mspec);
600                         // removes value, keeps key for next iteration
601                         lua_pop(L, 1);
602                         i++;
603                         if(i==6){
604                                 lua_pop(L, 1);
605                                 break;
606                         }
607                 }
608         }
609         lua_pop(L, 1);
610
611         f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
612
613         /* Other stuff */
614         
615         lua_getfield(L, nodedef_table, "post_effect_color");
616         if(!lua_isnil(L, -1))
617                 f.post_effect_color = readARGB8(L, -1);
618         lua_pop(L, 1);
619
620         f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
621                         es_ContentParamType, CPT_NONE);
622         
623         // True for all ground-like things like stone and mud, false for eg. trees
624         getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
625         getboolfield(L, nodedef_table, "light_propagates", f.light_propagates);
626         getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
627         // This is used for collision detection.
628         // Also for general solidness queries.
629         getboolfield(L, nodedef_table, "walkable", f.walkable);
630         // Player can point to these
631         getboolfield(L, nodedef_table, "pointable", f.pointable);
632         // Player can dig these
633         getboolfield(L, nodedef_table, "diggable", f.diggable);
634         // Player can climb these
635         getboolfield(L, nodedef_table, "climbable", f.climbable);
636         // Player can build on these
637         getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
638         // If true, param2 is set to direction when placed. Used for torches.
639         // NOTE: the direction format is quite inefficient and should be changed
640         getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
641         // Whether this content type often contains mineral.
642         // Used for texture atlas creation.
643         // Currently only enabled for CONTENT_STONE.
644         getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
645         // Inventory item string as which the node appears in inventory when dug.
646         // Mineral overrides this.
647         getstringfield(L, nodedef_table, "dug_item", f.dug_item);
648         // Extra dug item and its rarity
649         getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
650         // Usual get interval for extra dug item
651         getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
652         // Metadata name of node (eg. "furnace")
653         getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
654         // Whether the node is non-liquid, source liquid or flowing liquid
655         f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
656                         es_LiquidType, LIQUID_NONE);
657         // If the content is liquid, this is the flowing version of the liquid.
658         getstringfield(L, nodedef_table, "liquid_alternative_flowing",
659                         f.liquid_alternative_flowing);
660         // If the content is liquid, this is the source version of the liquid.
661         getstringfield(L, nodedef_table, "liquid_alternative_source",
662                         f.liquid_alternative_source);
663         // Viscosity for fluid flow, ranging from 1 to 7, with
664         // 1 giving almost instantaneous propagation and 7 being
665         // the slowest possible
666         f.liquid_viscosity = getintfield_default(L, nodedef_table,
667                         "liquid_viscosity", f.liquid_viscosity);
668         // Amount of light the node emits
669         f.light_source = getintfield_default(L, nodedef_table,
670                         "light_source", f.light_source);
671         f.damage_per_second = getintfield_default(L, nodedef_table,
672                         "damage_per_second", f.damage_per_second);
673         
674         lua_getfield(L, nodedef_table, "selection_box");
675         if(lua_istable(L, -1)){
676                 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
677                                 es_NodeBoxType, NODEBOX_REGULAR);
678
679                 lua_getfield(L, -1, "fixed");
680                 if(lua_istable(L, -1))
681                         f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
682                 lua_pop(L, 1);
683
684                 lua_getfield(L, -1, "wall_top");
685                 if(lua_istable(L, -1))
686                         f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
687                 lua_pop(L, 1);
688
689                 lua_getfield(L, -1, "wall_bottom");
690                 if(lua_istable(L, -1))
691                         f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
692                 lua_pop(L, 1);
693
694                 lua_getfield(L, -1, "wall_side");
695                 if(lua_istable(L, -1))
696                         f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
697                 lua_pop(L, 1);
698         }
699         lua_pop(L, 1);
700
701         lua_getfield(L, nodedef_table, "material");
702         if(lua_istable(L, -1)){
703                 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
704                                 es_Diggability, DIGGABLE_NORMAL);
705                 
706                 getfloatfield(L, -1, "constant_time", f.material.constant_time);
707                 getfloatfield(L, -1, "weight", f.material.weight);
708                 getfloatfield(L, -1, "crackiness", f.material.crackiness);
709                 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
710                 getfloatfield(L, -1, "cuttability", f.material.cuttability);
711                 getfloatfield(L, -1, "flammability", f.material.flammability);
712         }
713         lua_pop(L, 1);
714
715         getstringfield(L, nodedef_table, "cookresult_item", f.cookresult_item);
716         getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
717         getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
718         
719         /*
720                 Register it
721         */
722         
723         nodedef->set(name, f);
724         
725         return 0; /* number of results */
726 }
727
728 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
729 static int l_register_craft(lua_State *L)
730 {
731         infostream<<"register_craft"<<std::endl;
732         luaL_checktype(L, 1, LUA_TTABLE);
733         int table0 = 1;
734
735         // Get server from registry
736         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
737         Server *server = (Server*)lua_touserdata(L, -1);
738         // And get the writable craft definition manager from the server
739         IWritableCraftDefManager *craftdef =
740                         server->getWritableCraftDefManager();
741         
742         std::string output;
743         int width = 0;
744         std::vector<std::string> input;
745
746         lua_getfield(L, table0, "output");
747         luaL_checktype(L, -1, LUA_TSTRING);
748         if(lua_isstring(L, -1))
749                 output = lua_tostring(L, -1);
750         lua_pop(L, 1);
751
752         lua_getfield(L, table0, "recipe");
753         luaL_checktype(L, -1, LUA_TTABLE);
754         if(lua_istable(L, -1)){
755                 int table1 = lua_gettop(L);
756                 lua_pushnil(L);
757                 int rowcount = 0;
758                 while(lua_next(L, table1) != 0){
759                         int colcount = 0;
760                         // key at index -2 and value at index -1
761                         luaL_checktype(L, -1, LUA_TTABLE);
762                         if(lua_istable(L, -1)){
763                                 int table2 = lua_gettop(L);
764                                 lua_pushnil(L);
765                                 while(lua_next(L, table2) != 0){
766                                         // key at index -2 and value at index -1
767                                         luaL_checktype(L, -1, LUA_TSTRING);
768                                         input.push_back(lua_tostring(L, -1));
769                                         // removes value, keeps key for next iteration
770                                         lua_pop(L, 1);
771                                         colcount++;
772                                 }
773                         }
774                         if(rowcount == 0){
775                                 width = colcount;
776                         } else {
777                                 if(colcount != width){
778                                         script_error(L, "error: %s\n", "Invalid crafting recipe");
779                                 }
780                         }
781                         // removes value, keeps key for next iteration
782                         lua_pop(L, 1);
783                         rowcount++;
784                 }
785         }
786         lua_pop(L, 1);
787
788         CraftDefinition def(output, width, input);
789         craftdef->registerCraft(def);
790
791         return 0; /* number of results */
792 }
793
794 static int register_lua_callback(lua_State *L, const char *tablename)
795 {
796         luaL_checktype(L, 1, LUA_TFUNCTION);
797
798         lua_getglobal(L, "table");
799         lua_getfield(L, -1, "insert");
800         int table_insert = lua_gettop(L);
801         // Get minetest.registered_globalsteps
802         lua_getglobal(L, "minetest");
803         lua_getfield(L, -1, tablename);
804         luaL_checktype(L, -1, LUA_TTABLE);
805         int registered = lua_gettop(L);
806         // table.insert(registered_globalsteps, func)
807         lua_pushvalue(L, table_insert);
808         lua_pushvalue(L, registered);
809         lua_pushvalue(L, 1); // push function from argument 1
810         // Call insert
811         if(lua_pcall(L, 2, 0, 0))
812                 script_error(L, "error: %s\n", lua_tostring(L, -1));
813
814         return 0; /* number of results */
815 }
816
817 // Register a global step function
818 // register_globalstep(function)
819 static int l_register_globalstep(lua_State *L)
820 {
821         infostream<<"register_globalstep"<<std::endl;
822         return register_lua_callback(L, "registered_globalsteps");
823 }
824
825 // register_on_placenode(function)
826 static int l_register_on_placenode(lua_State *L)
827 {
828         infostream<<"register_on_placenode"<<std::endl;
829         return register_lua_callback(L, "registered_on_placenodes");
830 }
831
832 // register_on_dignode(function)
833 static int l_register_on_dignode(lua_State *L)
834 {
835         infostream<<"register_on_dignode"<<std::endl;
836         return register_lua_callback(L, "registered_on_dignodes");
837 }
838
839 // register_on_punchnode(function)
840 static int l_register_on_punchnode(lua_State *L)
841 {
842         infostream<<"register_on_punchnode"<<std::endl;
843         return register_lua_callback(L, "registered_on_punchnodes");
844 }
845
846 // register_on_newplayer(function)
847 static int l_register_on_newplayer(lua_State *L)
848 {
849         infostream<<"register_on_newplayer"<<std::endl;
850         return register_lua_callback(L, "registered_on_newplayers");
851 }
852
853 // register_on_respawnplayer(function)
854 static int l_register_on_respawnplayer(lua_State *L)
855 {
856         infostream<<"register_on_respawnplayer"<<std::endl;
857         return register_lua_callback(L, "registered_on_respawnplayers");
858 }
859
860 // setting_get(name)
861 static int l_setting_get(lua_State *L)
862 {
863         const char *name = luaL_checkstring(L, 1);
864         try{
865                 std::string value = g_settings->get(name);
866                 lua_pushstring(L, value.c_str());
867         } catch(SettingNotFoundException &e){
868                 lua_pushnil(L);
869         }
870         return 1;
871 }
872
873 // setting_getbool(name)
874 static int l_setting_getbool(lua_State *L)
875 {
876         const char *name = luaL_checkstring(L, 1);
877         try{
878                 bool value = g_settings->getBool(name);
879                 lua_pushboolean(L, value);
880         } catch(SettingNotFoundException &e){
881                 lua_pushnil(L);
882         }
883         return 1;
884 }
885
886 static const struct luaL_Reg minetest_f [] = {
887         {"register_nodedef_defaults", l_register_nodedef_defaults},
888         {"register_entity", l_register_entity},
889         {"register_tool", l_register_tool},
890         {"register_node", l_register_node},
891         {"register_craft", l_register_craft},
892         {"register_globalstep", l_register_globalstep},
893         {"register_on_placenode", l_register_on_placenode},
894         {"register_on_dignode", l_register_on_dignode},
895         {"register_on_punchnode", l_register_on_punchnode},
896         {"register_on_newplayer", l_register_on_newplayer},
897         {"register_on_respawnplayer", l_register_on_respawnplayer},
898         {"setting_get", l_setting_get},
899         {"setting_getbool", l_setting_getbool},
900         {NULL, NULL}
901 };
902
903 /*
904         LuaEntity functions
905 */
906
907 static const struct luaL_Reg minetest_entity_m [] = {
908         {NULL, NULL}
909 };
910
911 /*
912         Getters for stuff in main tables
913 */
914
915 static void objectref_get(lua_State *L, u16 id)
916 {
917         // Get minetest.object_refs[i]
918         lua_getglobal(L, "minetest");
919         lua_getfield(L, -1, "object_refs");
920         luaL_checktype(L, -1, LUA_TTABLE);
921         lua_pushnumber(L, id);
922         lua_gettable(L, -2);
923         lua_remove(L, -2); // object_refs
924         lua_remove(L, -2); // minetest
925 }
926
927 static void luaentity_get(lua_State *L, u16 id)
928 {
929         // Get minetest.luaentities[i]
930         lua_getglobal(L, "minetest");
931         lua_getfield(L, -1, "luaentities");
932         luaL_checktype(L, -1, LUA_TTABLE);
933         lua_pushnumber(L, id);
934         lua_gettable(L, -2);
935         lua_remove(L, -2); // luaentities
936         lua_remove(L, -2); // minetest
937 }
938
939 /*
940         Reference objects
941 */
942 #define method(class, name) {#name, class::l_##name}
943
944 class EnvRef
945 {
946 private:
947         ServerEnvironment *m_env;
948
949         static const char className[];
950         static const luaL_reg methods[];
951
952         static EnvRef *checkobject(lua_State *L, int narg)
953         {
954                 luaL_checktype(L, narg, LUA_TUSERDATA);
955                 void *ud = luaL_checkudata(L, narg, className);
956                 if(!ud) luaL_typerror(L, narg, className);
957                 return *(EnvRef**)ud;  // unbox pointer
958         }
959         
960         // Exported functions
961
962         // EnvRef:add_node(pos, node)
963         // pos = {x=num, y=num, z=num}
964         static int l_add_node(lua_State *L)
965         {
966                 infostream<<"EnvRef::l_add_node()"<<std::endl;
967                 EnvRef *o = checkobject(L, 1);
968                 ServerEnvironment *env = o->m_env;
969                 if(env == NULL) return 0;
970                 // pos
971                 v3s16 pos = readpos(L, 2);
972                 // content
973                 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
974                 // Do it
975                 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
976                 lua_pushboolean(L, succeeded);
977                 return 1;
978         }
979
980         // EnvRef:remove_node(pos)
981         // pos = {x=num, y=num, z=num}
982         static int l_remove_node(lua_State *L)
983         {
984                 infostream<<"EnvRef::l_remove_node()"<<std::endl;
985                 EnvRef *o = checkobject(L, 1);
986                 ServerEnvironment *env = o->m_env;
987                 if(env == NULL) return 0;
988                 // pos
989                 v3s16 pos = readpos(L, 2);
990                 // Do it
991                 bool succeeded = env->getMap().removeNodeWithEvent(pos);
992                 lua_pushboolean(L, succeeded);
993                 return 1;
994         }
995
996         // EnvRef:get_node(pos)
997         // pos = {x=num, y=num, z=num}
998         static int l_get_node(lua_State *L)
999         {
1000                 infostream<<"EnvRef::l_get_node()"<<std::endl;
1001                 EnvRef *o = checkobject(L, 1);
1002                 ServerEnvironment *env = o->m_env;
1003                 if(env == NULL) return 0;
1004                 // pos
1005                 v3s16 pos = readpos(L, 2);
1006                 // Do it
1007                 MapNode n = env->getMap().getNodeNoEx(pos);
1008                 // Return node
1009                 pushnode(L, n, env->getGameDef()->ndef());
1010                 return 1;
1011         }
1012
1013         // EnvRef:add_luaentity(pos, entityname)
1014         // pos = {x=num, y=num, z=num}
1015         static int l_add_luaentity(lua_State *L)
1016         {
1017                 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
1018                 EnvRef *o = checkobject(L, 1);
1019                 ServerEnvironment *env = o->m_env;
1020                 if(env == NULL) return 0;
1021                 // pos
1022                 v3f pos = readFloatPos(L, 2);
1023                 // content
1024                 const char *name = lua_tostring(L, 3);
1025                 // Do it
1026                 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
1027                 env->addActiveObject(obj);
1028                 return 0;
1029         }
1030
1031         static int gc_object(lua_State *L) {
1032                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
1033                 delete o;
1034                 return 0;
1035         }
1036
1037 public:
1038         EnvRef(ServerEnvironment *env):
1039                 m_env(env)
1040         {
1041                 infostream<<"EnvRef created"<<std::endl;
1042         }
1043
1044         ~EnvRef()
1045         {
1046                 infostream<<"EnvRef destructing"<<std::endl;
1047         }
1048
1049         // Creates an EnvRef and leaves it on top of stack
1050         // Not callable from Lua; all references are created on the C side.
1051         static void create(lua_State *L, ServerEnvironment *env)
1052         {
1053                 EnvRef *o = new EnvRef(env);
1054                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
1055                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1056                 luaL_getmetatable(L, className);
1057                 lua_setmetatable(L, -2);
1058         }
1059
1060         static void set_null(lua_State *L)
1061         {
1062                 EnvRef *o = checkobject(L, -1);
1063                 o->m_env = NULL;
1064         }
1065         
1066         static void Register(lua_State *L)
1067         {
1068                 lua_newtable(L);
1069                 int methodtable = lua_gettop(L);
1070                 luaL_newmetatable(L, className);
1071                 int metatable = lua_gettop(L);
1072
1073                 lua_pushliteral(L, "__metatable");
1074                 lua_pushvalue(L, methodtable);
1075                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1076
1077                 lua_pushliteral(L, "__index");
1078                 lua_pushvalue(L, methodtable);
1079                 lua_settable(L, metatable);
1080
1081                 lua_pushliteral(L, "__gc");
1082                 lua_pushcfunction(L, gc_object);
1083                 lua_settable(L, metatable);
1084
1085                 lua_pop(L, 1);  // drop metatable
1086
1087                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
1088                 lua_pop(L, 1);  // drop methodtable
1089
1090                 // Cannot be created from Lua
1091                 //lua_register(L, className, create_object);
1092         }
1093 };
1094 const char EnvRef::className[] = "EnvRef";
1095 const luaL_reg EnvRef::methods[] = {
1096         method(EnvRef, add_node),
1097         method(EnvRef, remove_node),
1098         method(EnvRef, get_node),
1099         method(EnvRef, add_luaentity),
1100         {0,0}
1101 };
1102
1103 class ObjectRef
1104 {
1105 private:
1106         ServerActiveObject *m_object;
1107
1108         static const char className[];
1109         static const luaL_reg methods[];
1110
1111         static ObjectRef *checkobject(lua_State *L, int narg)
1112         {
1113                 luaL_checktype(L, narg, LUA_TUSERDATA);
1114                 void *ud = luaL_checkudata(L, narg, className);
1115                 if(!ud) luaL_typerror(L, narg, className);
1116                 return *(ObjectRef**)ud;  // unbox pointer
1117         }
1118         
1119         static ServerActiveObject* getobject(ObjectRef *ref)
1120         {
1121                 ServerActiveObject *co = ref->m_object;
1122                 return co;
1123         }
1124         
1125         static LuaEntitySAO* getluaobject(ObjectRef *ref)
1126         {
1127                 ServerActiveObject *obj = getobject(ref);
1128                 if(obj == NULL)
1129                         return NULL;
1130                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1131                         return NULL;
1132                 return (LuaEntitySAO*)obj;
1133         }
1134         
1135         // Exported functions
1136         
1137         // garbage collector
1138         static int gc_object(lua_State *L) {
1139                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1140                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1141                 delete o;
1142                 return 0;
1143         }
1144
1145         // remove(self)
1146         static int l_remove(lua_State *L)
1147         {
1148                 ObjectRef *ref = checkobject(L, 1);
1149                 ServerActiveObject *co = getobject(ref);
1150                 if(co == NULL) return 0;
1151                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1152                 co->m_removed = true;
1153                 return 0;
1154         }
1155         
1156         // getpos(self)
1157         // returns: {x=num, y=num, z=num}
1158         static int l_getpos(lua_State *L)
1159         {
1160                 ObjectRef *ref = checkobject(L, 1);
1161                 ServerActiveObject *co = getobject(ref);
1162                 if(co == NULL) return 0;
1163                 v3f pos = co->getBasePosition() / BS;
1164                 lua_newtable(L);
1165                 lua_pushnumber(L, pos.X);
1166                 lua_setfield(L, -2, "x");
1167                 lua_pushnumber(L, pos.Y);
1168                 lua_setfield(L, -2, "y");
1169                 lua_pushnumber(L, pos.Z);
1170                 lua_setfield(L, -2, "z");
1171                 return 1;
1172         }
1173         
1174         // setpos(self, pos)
1175         static int l_setpos(lua_State *L)
1176         {
1177                 ObjectRef *ref = checkobject(L, 1);
1178                 //LuaEntitySAO *co = getluaobject(ref);
1179                 ServerActiveObject *co = getobject(ref);
1180                 if(co == NULL) return 0;
1181                 // pos
1182                 v3f pos = readFloatPos(L, 2);
1183                 // Do it
1184                 co->setPos(pos);
1185                 return 0;
1186         }
1187         
1188         // moveto(self, pos, continuous=false)
1189         static int l_moveto(lua_State *L)
1190         {
1191                 ObjectRef *ref = checkobject(L, 1);
1192                 //LuaEntitySAO *co = getluaobject(ref);
1193                 ServerActiveObject *co = getobject(ref);
1194                 if(co == NULL) return 0;
1195                 // pos
1196                 v3f pos = readFloatPos(L, 2);
1197                 // continuous
1198                 bool continuous = lua_toboolean(L, 3);
1199                 // Do it
1200                 co->moveTo(pos, continuous);
1201                 return 0;
1202         }
1203
1204         // setvelocity(self, velocity)
1205         static int l_setvelocity(lua_State *L)
1206         {
1207                 ObjectRef *ref = checkobject(L, 1);
1208                 LuaEntitySAO *co = getluaobject(ref);
1209                 if(co == NULL) return 0;
1210                 // pos
1211                 v3f pos = readFloatPos(L, 2);
1212                 // Do it
1213                 co->setVelocity(pos);
1214                 return 0;
1215         }
1216         
1217         // setacceleration(self, acceleration)
1218         static int l_setacceleration(lua_State *L)
1219         {
1220                 ObjectRef *ref = checkobject(L, 1);
1221                 LuaEntitySAO *co = getluaobject(ref);
1222                 if(co == NULL) return 0;
1223                 // pos
1224                 v3f pos = readFloatPos(L, 2);
1225                 // Do it
1226                 co->setAcceleration(pos);
1227                 return 0;
1228         }
1229         
1230         // add_to_inventory(self, itemstring)
1231         // returns: true if item was added, false otherwise
1232         static int l_add_to_inventory(lua_State *L)
1233         {
1234                 ObjectRef *ref = checkobject(L, 1);
1235                 luaL_checkstring(L, 2);
1236                 ServerActiveObject *co = getobject(ref);
1237                 if(co == NULL) return 0;
1238                 // itemstring
1239                 const char *itemstring = lua_tostring(L, 2);
1240                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1241                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1242                 // Do it
1243                 std::istringstream is(itemstring, std::ios::binary);
1244                 ServerEnvironment *env = co->getEnv();
1245                 assert(env);
1246                 IGameDef *gamedef = env->getGameDef();
1247                 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1248                 infostream<<"item="<<env<<std::endl;
1249                 bool fits = co->addToInventory(item);
1250                 // Return
1251                 lua_pushboolean(L, fits);
1252                 return 1;
1253         }
1254
1255         // settexturemod(self, mod)
1256         static int l_settexturemod(lua_State *L)
1257         {
1258                 ObjectRef *ref = checkobject(L, 1);
1259                 LuaEntitySAO *co = getluaobject(ref);
1260                 if(co == NULL) return 0;
1261                 // Do it
1262                 std::string mod = lua_tostring(L, 2);
1263                 co->setTextureMod(mod);
1264                 return 0;
1265         }
1266         
1267 public:
1268         ObjectRef(ServerActiveObject *object):
1269                 m_object(object)
1270         {
1271                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1272         }
1273
1274         ~ObjectRef()
1275         {
1276                 /*if(m_object)
1277                         infostream<<"ObjectRef destructing for id="
1278                                         <<m_object->getId()<<std::endl;
1279                 else
1280                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1281         }
1282
1283         // Creates an ObjectRef and leaves it on top of stack
1284         // Not callable from Lua; all references are created on the C side.
1285         static void create(lua_State *L, ServerActiveObject *object)
1286         {
1287                 ObjectRef *o = new ObjectRef(object);
1288                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1289                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1290                 luaL_getmetatable(L, className);
1291                 lua_setmetatable(L, -2);
1292         }
1293
1294         static void set_null(lua_State *L)
1295         {
1296                 ObjectRef *o = checkobject(L, -1);
1297                 o->m_object = NULL;
1298         }
1299         
1300         static void Register(lua_State *L)
1301         {
1302                 lua_newtable(L);
1303                 int methodtable = lua_gettop(L);
1304                 luaL_newmetatable(L, className);
1305                 int metatable = lua_gettop(L);
1306
1307                 lua_pushliteral(L, "__metatable");
1308                 lua_pushvalue(L, methodtable);
1309                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1310
1311                 lua_pushliteral(L, "__index");
1312                 lua_pushvalue(L, methodtable);
1313                 lua_settable(L, metatable);
1314
1315                 lua_pushliteral(L, "__gc");
1316                 lua_pushcfunction(L, gc_object);
1317                 lua_settable(L, metatable);
1318
1319                 lua_pop(L, 1);  // drop metatable
1320
1321                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
1322                 lua_pop(L, 1);  // drop methodtable
1323
1324                 // Cannot be created from Lua
1325                 //lua_register(L, className, create_object);
1326         }
1327 };
1328 const char ObjectRef::className[] = "ObjectRef";
1329 const luaL_reg ObjectRef::methods[] = {
1330         method(ObjectRef, remove),
1331         method(ObjectRef, getpos),
1332         method(ObjectRef, setpos),
1333         method(ObjectRef, moveto),
1334         method(ObjectRef, setvelocity),
1335         method(ObjectRef, setacceleration),
1336         method(ObjectRef, add_to_inventory),
1337         method(ObjectRef, settexturemod),
1338         {0,0}
1339 };
1340
1341 // Creates a new anonymous reference if id=0
1342 static void objectref_get_or_create(lua_State *L,
1343                 ServerActiveObject *cobj)
1344 {
1345         if(cobj->getId() == 0){
1346                 ObjectRef::create(L, cobj);
1347         } else {
1348                 objectref_get(L, cobj->getId());
1349         }
1350 }
1351
1352 /*
1353         Main export function
1354 */
1355
1356 void scriptapi_export(lua_State *L, Server *server)
1357 {
1358         realitycheck(L);
1359         assert(lua_checkstack(L, 20));
1360         infostream<<"scriptapi_export"<<std::endl;
1361         StackUnroller stack_unroller(L);
1362
1363         // Store server as light userdata in registry
1364         lua_pushlightuserdata(L, server);
1365         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
1366
1367         // Store nil as minetest_nodedef_defaults in registry
1368         lua_pushnil(L);
1369         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
1370         
1371         // Register global functions in table minetest
1372         lua_newtable(L);
1373         luaL_register(L, NULL, minetest_f);
1374         lua_setglobal(L, "minetest");
1375         
1376         // Get the main minetest table
1377         lua_getglobal(L, "minetest");
1378
1379         // Add tables to minetest
1380         
1381         lua_newtable(L);
1382         lua_setfield(L, -2, "registered_nodes");
1383         lua_newtable(L);
1384         lua_setfield(L, -2, "registered_entities");
1385         lua_newtable(L);
1386         lua_setfield(L, -2, "registered_globalsteps");
1387         lua_newtable(L);
1388         lua_setfield(L, -2, "registered_on_placenodes");
1389         lua_newtable(L);
1390         lua_setfield(L, -2, "registered_on_dignodes");
1391         lua_newtable(L);
1392         lua_setfield(L, -2, "registered_on_punchnodes");
1393         lua_newtable(L);
1394         lua_setfield(L, -2, "registered_on_newplayers");
1395         lua_newtable(L);
1396         lua_setfield(L, -2, "registered_on_respawnplayers");
1397         
1398         lua_newtable(L);
1399         lua_setfield(L, -2, "object_refs");
1400         lua_newtable(L);
1401         lua_setfield(L, -2, "luaentities");
1402
1403         // Create entity prototype
1404         luaL_newmetatable(L, "minetest.entity");
1405         // metatable.__index = metatable
1406         lua_pushvalue(L, -1); // Duplicate metatable
1407         lua_setfield(L, -2, "__index");
1408         // Put functions in metatable
1409         luaL_register(L, NULL, minetest_entity_m);
1410         // Put other stuff in metatable
1411
1412         // Environment C reference
1413         EnvRef::Register(L);
1414
1415         // Object C reference
1416         ObjectRef::Register(L);
1417 }
1418
1419 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
1420 {
1421         realitycheck(L);
1422         assert(lua_checkstack(L, 20));
1423         infostream<<"scriptapi_add_environment"<<std::endl;
1424         StackUnroller stack_unroller(L);
1425
1426         // Create EnvRef on stack
1427         EnvRef::create(L, env);
1428         int envref = lua_gettop(L);
1429
1430         // minetest.env = envref
1431         lua_getglobal(L, "minetest");
1432         luaL_checktype(L, -1, LUA_TTABLE);
1433         lua_pushvalue(L, envref);
1434         lua_setfield(L, -2, "env");
1435 }
1436
1437 #if 0
1438 // Dump stack top with the dump2 function
1439 static void dump2(lua_State *L, const char *name)
1440 {
1441         // Dump object (debug)
1442         lua_getglobal(L, "dump2");
1443         luaL_checktype(L, -1, LUA_TFUNCTION);
1444         lua_pushvalue(L, -2); // Get previous stack top as first parameter
1445         lua_pushstring(L, name);
1446         if(lua_pcall(L, 2, 0, 0))
1447                 script_error(L, "error: %s\n", lua_tostring(L, -1));
1448 }
1449 #endif
1450
1451 /*
1452         object_reference
1453 */
1454
1455 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1456 {
1457         realitycheck(L);
1458         assert(lua_checkstack(L, 20));
1459         infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1460         StackUnroller stack_unroller(L);
1461
1462         // Create object on stack
1463         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1464         int object = lua_gettop(L);
1465
1466         // Get minetest.object_refs table
1467         lua_getglobal(L, "minetest");
1468         lua_getfield(L, -1, "object_refs");
1469         luaL_checktype(L, -1, LUA_TTABLE);
1470         int objectstable = lua_gettop(L);
1471         
1472         // object_refs[id] = object
1473         lua_pushnumber(L, cobj->getId()); // Push id
1474         lua_pushvalue(L, object); // Copy object to top of stack
1475         lua_settable(L, objectstable);
1476 }
1477
1478 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1479 {
1480         realitycheck(L);
1481         assert(lua_checkstack(L, 20));
1482         infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1483         StackUnroller stack_unroller(L);
1484
1485         // Get minetest.object_refs table
1486         lua_getglobal(L, "minetest");
1487         lua_getfield(L, -1, "object_refs");
1488         luaL_checktype(L, -1, LUA_TTABLE);
1489         int objectstable = lua_gettop(L);
1490         
1491         // Get object_refs[id]
1492         lua_pushnumber(L, cobj->getId()); // Push id
1493         lua_gettable(L, objectstable);
1494         // Set object reference to NULL
1495         ObjectRef::set_null(L);
1496         lua_pop(L, 1); // pop object
1497
1498         // Set object_refs[id] = nil
1499         lua_pushnumber(L, cobj->getId()); // Push id
1500         lua_pushnil(L);
1501         lua_settable(L, objectstable);
1502 }
1503
1504
1505 /*
1506         misc
1507 */
1508
1509 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
1510 {
1511         realitycheck(L);
1512         assert(lua_checkstack(L, 20));
1513         StackUnroller stack_unroller(L);
1514
1515         // Get minetest.registered_on_newplayers
1516         lua_getglobal(L, "minetest");
1517         lua_getfield(L, -1, "registered_on_newplayers");
1518         luaL_checktype(L, -1, LUA_TTABLE);
1519         int table = lua_gettop(L);
1520         // Foreach
1521         lua_pushnil(L);
1522         while(lua_next(L, table) != 0){
1523                 // key at index -2 and value at index -1
1524                 luaL_checktype(L, -1, LUA_TFUNCTION);
1525                 // Call function
1526                 objectref_get_or_create(L, player);
1527                 if(lua_pcall(L, 1, 0, 0))
1528                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1529                 // value removed, keep key for next iteration
1530         }
1531 }
1532 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
1533 {
1534         realitycheck(L);
1535         assert(lua_checkstack(L, 20));
1536         StackUnroller stack_unroller(L);
1537
1538         bool positioning_handled_by_some = false;
1539
1540         // Get minetest.registered_on_respawnplayers
1541         lua_getglobal(L, "minetest");
1542         lua_getfield(L, -1, "registered_on_respawnplayers");
1543         luaL_checktype(L, -1, LUA_TTABLE);
1544         int table = lua_gettop(L);
1545         // Foreach
1546         lua_pushnil(L);
1547         while(lua_next(L, table) != 0){
1548                 // key at index -2 and value at index -1
1549                 luaL_checktype(L, -1, LUA_TFUNCTION);
1550                 // Call function
1551                 objectref_get_or_create(L, player);
1552                 if(lua_pcall(L, 1, 1, 0))
1553                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1554                 bool positioning_handled = lua_toboolean(L, -1);
1555                 lua_pop(L, 1);
1556                 if(positioning_handled)
1557                         positioning_handled_by_some = true;
1558                 // value removed, keep key for next iteration
1559         }
1560         return positioning_handled_by_some;
1561 }
1562
1563 /*
1564         environment
1565 */
1566
1567 void scriptapi_environment_step(lua_State *L, float dtime)
1568 {
1569         realitycheck(L);
1570         assert(lua_checkstack(L, 20));
1571         //infostream<<"scriptapi_environment_step"<<std::endl;
1572         StackUnroller stack_unroller(L);
1573
1574         // Get minetest.registered_globalsteps
1575         lua_getglobal(L, "minetest");
1576         lua_getfield(L, -1, "registered_globalsteps");
1577         luaL_checktype(L, -1, LUA_TTABLE);
1578         int table = lua_gettop(L);
1579         // Foreach
1580         lua_pushnil(L);
1581         while(lua_next(L, table) != 0){
1582                 // key at index -2 and value at index -1
1583                 luaL_checktype(L, -1, LUA_TFUNCTION);
1584                 // Call function
1585                 lua_pushnumber(L, dtime);
1586                 if(lua_pcall(L, 1, 0, 0))
1587                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1588                 // value removed, keep key for next iteration
1589         }
1590 }
1591
1592 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
1593                 ServerActiveObject *placer)
1594 {
1595         realitycheck(L);
1596         assert(lua_checkstack(L, 20));
1597         //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1598         StackUnroller stack_unroller(L);
1599
1600         // Get server from registry
1601         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1602         Server *server = (Server*)lua_touserdata(L, -1);
1603         // And get the writable node definition manager from the server
1604         IWritableNodeDefManager *ndef =
1605                         server->getWritableNodeDefManager();
1606         
1607         // Get minetest.registered_on_placenodes
1608         lua_getglobal(L, "minetest");
1609         lua_getfield(L, -1, "registered_on_placenodes");
1610         luaL_checktype(L, -1, LUA_TTABLE);
1611         int table = lua_gettop(L);
1612         // Foreach
1613         lua_pushnil(L);
1614         while(lua_next(L, table) != 0){
1615                 // key at index -2 and value at index -1
1616                 luaL_checktype(L, -1, LUA_TFUNCTION);
1617                 // Call function
1618                 pushpos(L, p);
1619                 pushnode(L, newnode, ndef);
1620                 objectref_get_or_create(L, placer);
1621                 if(lua_pcall(L, 3, 0, 0))
1622                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1623                 // value removed, keep key for next iteration
1624         }
1625 }
1626
1627 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
1628                 ServerActiveObject *digger)
1629 {
1630         realitycheck(L);
1631         assert(lua_checkstack(L, 20));
1632         //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1633         StackUnroller stack_unroller(L);
1634
1635         // Get server from registry
1636         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1637         Server *server = (Server*)lua_touserdata(L, -1);
1638         // And get the writable node definition manager from the server
1639         IWritableNodeDefManager *ndef =
1640                         server->getWritableNodeDefManager();
1641         
1642         // Get minetest.registered_on_dignodes
1643         lua_getglobal(L, "minetest");
1644         lua_getfield(L, -1, "registered_on_dignodes");
1645         luaL_checktype(L, -1, LUA_TTABLE);
1646         int table = lua_gettop(L);
1647         // Foreach
1648         lua_pushnil(L);
1649         while(lua_next(L, table) != 0){
1650                 // key at index -2 and value at index -1
1651                 luaL_checktype(L, -1, LUA_TFUNCTION);
1652                 // Call function
1653                 pushpos(L, p);
1654                 pushnode(L, oldnode, ndef);
1655                 objectref_get_or_create(L, digger);
1656                 if(lua_pcall(L, 3, 0, 0))
1657                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1658                 // value removed, keep key for next iteration
1659         }
1660 }
1661
1662 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
1663                 ServerActiveObject *puncher)
1664 {
1665         realitycheck(L);
1666         assert(lua_checkstack(L, 20));
1667         //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
1668         StackUnroller stack_unroller(L);
1669
1670         // Get server from registry
1671         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1672         Server *server = (Server*)lua_touserdata(L, -1);
1673         // And get the writable node definition manager from the server
1674         IWritableNodeDefManager *ndef =
1675                         server->getWritableNodeDefManager();
1676         
1677         // Get minetest.registered_on_punchnodes
1678         lua_getglobal(L, "minetest");
1679         lua_getfield(L, -1, "registered_on_punchnodes");
1680         luaL_checktype(L, -1, LUA_TTABLE);
1681         int table = lua_gettop(L);
1682         // Foreach
1683         lua_pushnil(L);
1684         while(lua_next(L, table) != 0){
1685                 // key at index -2 and value at index -1
1686                 luaL_checktype(L, -1, LUA_TFUNCTION);
1687                 // Call function
1688                 pushpos(L, p);
1689                 pushnode(L, node, ndef);
1690                 objectref_get_or_create(L, puncher);
1691                 if(lua_pcall(L, 3, 0, 0))
1692                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1693                 // value removed, keep key for next iteration
1694         }
1695 }
1696
1697 /*
1698         luaentity
1699 */
1700
1701 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1702                 const std::string &staticdata)
1703 {
1704         realitycheck(L);
1705         assert(lua_checkstack(L, 20));
1706         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1707                         <<name<<"\""<<std::endl;
1708         StackUnroller stack_unroller(L);
1709         
1710         // Get minetest.registered_entities[name]
1711         lua_getglobal(L, "minetest");
1712         lua_getfield(L, -1, "registered_entities");
1713         luaL_checktype(L, -1, LUA_TTABLE);
1714         lua_pushstring(L, name);
1715         lua_gettable(L, -2);
1716         // Should be a table, which we will use as a prototype
1717         //luaL_checktype(L, -1, LUA_TTABLE);
1718         if(lua_type(L, -1) != LUA_TTABLE){
1719                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1720                 return false;
1721         }
1722         int prototype_table = lua_gettop(L);
1723         //dump2(L, "prototype_table");
1724         
1725         // Create entity object
1726         lua_newtable(L);
1727         int object = lua_gettop(L);
1728
1729         // Set object metatable
1730         lua_pushvalue(L, prototype_table);
1731         lua_setmetatable(L, -2);
1732         
1733         // Add object reference
1734         // This should be userdata with metatable ObjectRef
1735         objectref_get(L, id);
1736         luaL_checktype(L, -1, LUA_TUSERDATA);
1737         if(!luaL_checkudata(L, -1, "ObjectRef"))
1738                 luaL_typerror(L, -1, "ObjectRef");
1739         lua_setfield(L, -2, "object");
1740
1741         // minetest.luaentities[id] = object
1742         lua_getglobal(L, "minetest");
1743         lua_getfield(L, -1, "luaentities");
1744         luaL_checktype(L, -1, LUA_TTABLE);
1745         lua_pushnumber(L, id); // Push id
1746         lua_pushvalue(L, object); // Copy object to top of stack
1747         lua_settable(L, -3);
1748         
1749         // Get on_activate function
1750         lua_pushvalue(L, object);
1751         lua_getfield(L, -1, "on_activate");
1752         if(!lua_isnil(L, -1)){
1753                 luaL_checktype(L, -1, LUA_TFUNCTION);
1754                 lua_pushvalue(L, object); // self
1755                 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
1756                 // Call with 2 arguments, 0 results
1757                 if(lua_pcall(L, 2, 0, 0))
1758                         script_error(L, "error running function %s:on_activate: %s\n",
1759                                         name, lua_tostring(L, -1));
1760         }
1761         
1762         return true;
1763 }
1764
1765 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1766 {
1767         realitycheck(L);
1768         assert(lua_checkstack(L, 20));
1769         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1770
1771         // Get minetest.luaentities table
1772         lua_getglobal(L, "minetest");
1773         lua_getfield(L, -1, "luaentities");
1774         luaL_checktype(L, -1, LUA_TTABLE);
1775         int objectstable = lua_gettop(L);
1776         
1777         // Set luaentities[id] = nil
1778         lua_pushnumber(L, id); // Push id
1779         lua_pushnil(L);
1780         lua_settable(L, objectstable);
1781         
1782         lua_pop(L, 2); // pop luaentities, minetest
1783 }
1784
1785 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
1786 {
1787         realitycheck(L);
1788         assert(lua_checkstack(L, 20));
1789         infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
1790         StackUnroller stack_unroller(L);
1791
1792         // Get minetest.luaentities[id]
1793         luaentity_get(L, id);
1794         int object = lua_gettop(L);
1795         
1796         // Get get_staticdata function
1797         lua_pushvalue(L, object);
1798         lua_getfield(L, -1, "get_staticdata");
1799         if(lua_isnil(L, -1))
1800                 return "";
1801         
1802         luaL_checktype(L, -1, LUA_TFUNCTION);
1803         lua_pushvalue(L, object); // self
1804         // Call with 1 arguments, 1 results
1805         if(lua_pcall(L, 1, 1, 0))
1806                 script_error(L, "error running function get_staticdata: %s\n",
1807                                 lua_tostring(L, -1));
1808         
1809         size_t len=0;
1810         const char *s = lua_tolstring(L, -1, &len);
1811         return std::string(s, len);
1812 }
1813
1814 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1815                 LuaEntityProperties *prop)
1816 {
1817         realitycheck(L);
1818         assert(lua_checkstack(L, 20));
1819         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1820         StackUnroller stack_unroller(L);
1821
1822         // Get minetest.luaentities[id]
1823         luaentity_get(L, id);
1824         //int object = lua_gettop(L);
1825
1826         lua_getfield(L, -1, "physical");
1827         if(lua_isboolean(L, -1))
1828                 prop->physical = lua_toboolean(L, -1);
1829         lua_pop(L, 1);
1830         
1831         lua_getfield(L, -1, "weight");
1832         prop->weight = lua_tonumber(L, -1);
1833         lua_pop(L, 1);
1834
1835         lua_getfield(L, -1, "collisionbox");
1836         if(lua_istable(L, -1))
1837                 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
1838         lua_pop(L, 1);
1839
1840         lua_getfield(L, -1, "visual");
1841         if(lua_isstring(L, -1))
1842                 prop->visual = lua_tostring(L, -1);
1843         lua_pop(L, 1);
1844         
1845         lua_getfield(L, -1, "textures");
1846         if(lua_istable(L, -1)){
1847                 prop->textures.clear();
1848                 int table = lua_gettop(L);
1849                 lua_pushnil(L);
1850                 while(lua_next(L, table) != 0){
1851                         // key at index -2 and value at index -1
1852                         if(lua_isstring(L, -1))
1853                                 prop->textures.push_back(lua_tostring(L, -1));
1854                         else
1855                                 prop->textures.push_back("");
1856                         // removes value, keeps key for next iteration
1857                         lua_pop(L, 1);
1858                 }
1859         }
1860         lua_pop(L, 1);
1861
1862 }
1863
1864 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1865 {
1866         realitycheck(L);
1867         assert(lua_checkstack(L, 20));
1868         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1869         StackUnroller stack_unroller(L);
1870
1871         // Get minetest.luaentities[id]
1872         luaentity_get(L, id);
1873         int object = lua_gettop(L);
1874         // State: object is at top of stack
1875         // Get step function
1876         lua_getfield(L, -1, "on_step");
1877         if(lua_isnil(L, -1))
1878                 return;
1879         luaL_checktype(L, -1, LUA_TFUNCTION);
1880         lua_pushvalue(L, object); // self
1881         lua_pushnumber(L, dtime); // dtime
1882         // Call with 2 arguments, 0 results
1883         if(lua_pcall(L, 2, 0, 0))
1884                 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
1885 }
1886
1887 // Calls entity:on_punch(ObjectRef puncher)
1888 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1889                 ServerActiveObject *puncher)
1890 {
1891         realitycheck(L);
1892         assert(lua_checkstack(L, 20));
1893         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1894         StackUnroller stack_unroller(L);
1895
1896         // Get minetest.luaentities[id]
1897         luaentity_get(L, id);
1898         int object = lua_gettop(L);
1899         // State: object is at top of stack
1900         // Get function
1901         lua_getfield(L, -1, "on_punch");
1902         if(lua_isnil(L, -1))
1903                 return;
1904         luaL_checktype(L, -1, LUA_TFUNCTION);
1905         lua_pushvalue(L, object); // self
1906         objectref_get_or_create(L, puncher); // Clicker reference
1907         // Call with 2 arguments, 0 results
1908         if(lua_pcall(L, 2, 0, 0))
1909                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1910 }
1911
1912 // Calls entity:on_rightclick(ObjectRef clicker)
1913 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1914                 ServerActiveObject *clicker)
1915 {
1916         realitycheck(L);
1917         assert(lua_checkstack(L, 20));
1918         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1919         StackUnroller stack_unroller(L);
1920
1921         // Get minetest.luaentities[id]
1922         luaentity_get(L, id);
1923         int object = lua_gettop(L);
1924         // State: object is at top of stack
1925         // Get function
1926         lua_getfield(L, -1, "on_rightclick");
1927         if(lua_isnil(L, -1))
1928                 return;
1929         luaL_checktype(L, -1, LUA_TFUNCTION);
1930         lua_pushvalue(L, object); // self
1931         objectref_get_or_create(L, clicker); // Clicker reference
1932         // Call with 2 arguments, 0 results
1933         if(lua_pcall(L, 2, 0, 0))
1934                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
1935 }
1936