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