]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi.cpp
Determine light_propagates from paramtype
[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 #include <list>
24 extern "C" {
25 #include <lua.h>
26 #include <lualib.h>
27 #include <lauxlib.h>
28 }
29
30 #include "log.h"
31 #include "server.h"
32 #include "porting.h"
33 #include "filesys.h"
34 #include "serverobject.h"
35 #include "script.h"
36 //#include "luna.h"
37 #include "luaentity_common.h"
38 #include "content_sao.h" // For LuaEntitySAO
39 #include "tooldef.h"
40 #include "nodedef.h"
41 #include "craftdef.h"
42 #include "craftitemdef.h"
43 #include "main.h" // For g_settings
44 #include "settings.h" // For accessing g_settings
45 #include "nodemetadata.h"
46 #include "mapblock.h" // For getNodeBlockPos
47 #include "content_nodemeta.h"
48 #include "utility.h"
49
50 static void stackDump(lua_State *L, std::ostream &o)
51 {
52   int i;
53   int top = lua_gettop(L);
54   for (i = 1; i <= top; i++) {  /* repeat for each level */
55         int t = lua_type(L, i);
56         switch (t) {
57
58           case LUA_TSTRING:  /* strings */
59                 o<<"\""<<lua_tostring(L, i)<<"\"";
60                 break;
61
62           case LUA_TBOOLEAN:  /* booleans */
63                 o<<(lua_toboolean(L, i) ? "true" : "false");
64                 break;
65
66           case LUA_TNUMBER:  /* numbers */ {
67                 char buf[10];
68                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
69                 o<<buf;
70                 break; }
71
72           default:  /* other values */
73                 o<<lua_typename(L, t);
74                 break;
75
76         }
77         o<<" ";
78   }
79   o<<std::endl;
80 }
81
82 static void realitycheck(lua_State *L)
83 {
84         int top = lua_gettop(L);
85         if(top >= 30){
86                 dstream<<"Stack is over 30:"<<std::endl;
87                 stackDump(L, dstream);
88                 script_error(L, "Stack is over 30 (reality check)");
89         }
90 }
91
92 class StackUnroller
93 {
94 private:
95         lua_State *m_lua;
96         int m_original_top;
97 public:
98         StackUnroller(lua_State *L):
99                 m_lua(L),
100                 m_original_top(-1)
101         {
102                 m_original_top = lua_gettop(m_lua); // store stack height
103         }
104         ~StackUnroller()
105         {
106                 lua_settop(m_lua, m_original_top); // restore stack height
107         }
108 };
109
110 class ModNameStorer
111 {
112 private:
113         lua_State *L;
114 public:
115         ModNameStorer(lua_State *L_, const std::string modname):
116                 L(L_)
117         {
118                 // Store current modname in registry
119                 lua_pushstring(L, modname.c_str());
120                 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
121         }
122         ~ModNameStorer()
123         {
124                 // Clear current modname in registry
125                 lua_pushnil(L);
126                 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
127         }
128 };
129
130 std::string get_current_modname(lua_State *L)
131 {
132         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
133         std::string modname = "";
134         if(lua_type(L, -1) == LUA_TSTRING)
135                 modname = lua_tostring(L, -1);
136         lua_pop(L, 1);
137         return modname;
138 }
139
140 void check_modname_prefix(lua_State *L, std::string &name)
141 {
142         if(name.size() == 0)
143                 throw LuaError(L, std::string("Name is empty"));
144         
145         if(name[0] == ':'){
146                 name = name.substr(1);
147                 return;
148         }
149         
150         std::string modname = get_current_modname(L);
151         assert(modname != "");
152         
153         // For __builtin, anything goes
154         if(modname == "__builtin")
155                 return;
156         
157         if(name.substr(0, modname.size()+1) != modname + ":")
158                 throw LuaError(L, std::string("Name \"")+name
159                                 +"\" does not follow naming conventions: "
160                                 +"\"modname:\" or \":\" prefix required)");
161         
162         std::string subname = name.substr(modname.size()+1);
163         if(!string_allowed(subname, "abcdefghijklmnopqrstuvwxyz"
164                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
165                 throw LuaError(L, std::string("Name \"")+name
166                                 +"\" does not follow naming conventions: "
167                                 +"\"contains unallowed characters)");
168 }
169
170 static v3f readFloatPos(lua_State *L, int index)
171 {
172         v3f pos;
173         luaL_checktype(L, index, LUA_TTABLE);
174         lua_getfield(L, index, "x");
175         pos.X = lua_tonumber(L, -1);
176         lua_pop(L, 1);
177         lua_getfield(L, index, "y");
178         pos.Y = lua_tonumber(L, -1);
179         lua_pop(L, 1);
180         lua_getfield(L, index, "z");
181         pos.Z = lua_tonumber(L, -1);
182         lua_pop(L, 1);
183         pos *= BS; // Scale to internal format
184         return pos;
185 }
186
187 static void pushFloatPos(lua_State *L, v3f p)
188 {
189         p /= BS;
190         lua_newtable(L);
191         lua_pushnumber(L, p.X);
192         lua_setfield(L, -2, "x");
193         lua_pushnumber(L, p.Y);
194         lua_setfield(L, -2, "y");
195         lua_pushnumber(L, p.Z);
196         lua_setfield(L, -2, "z");
197 }
198
199 static void pushpos(lua_State *L, v3s16 p)
200 {
201         lua_newtable(L);
202         lua_pushnumber(L, p.X);
203         lua_setfield(L, -2, "x");
204         lua_pushnumber(L, p.Y);
205         lua_setfield(L, -2, "y");
206         lua_pushnumber(L, p.Z);
207         lua_setfield(L, -2, "z");
208 }
209
210 static v3s16 readpos(lua_State *L, int index)
211 {
212         // Correct rounding at <0
213         v3f pf = readFloatPos(L, index);
214         return floatToInt(pf, BS);
215 }
216
217 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
218 {
219         lua_newtable(L);
220         lua_pushstring(L, ndef->get(n).name.c_str());
221         lua_setfield(L, -2, "name");
222         lua_pushnumber(L, n.getParam1());
223         lua_setfield(L, -2, "param1");
224         lua_pushnumber(L, n.getParam2());
225         lua_setfield(L, -2, "param2");
226 }
227
228 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
229 {
230         lua_getfield(L, index, "name");
231         const char *name = lua_tostring(L, -1);
232         lua_pop(L, 1);
233         u8 param1;
234         lua_getfield(L, index, "param1");
235         if(lua_isnil(L, -1))
236                 param1 = 0;
237         else
238                 param1 = lua_tonumber(L, -1);
239         lua_pop(L, 1);
240         u8 param2;
241         lua_getfield(L, index, "param2");
242         if(lua_isnil(L, -1))
243                 param2 = 0;
244         else
245                 param2 = lua_tonumber(L, -1);
246         lua_pop(L, 1);
247         return MapNode(ndef, name, param1, param2);
248 }
249
250 static video::SColor readARGB8(lua_State *L, int index)
251 {
252         video::SColor color;
253         luaL_checktype(L, index, LUA_TTABLE);
254         lua_getfield(L, index, "a");
255         if(lua_isnumber(L, -1))
256                 color.setAlpha(lua_tonumber(L, -1));
257         lua_pop(L, 1);
258         lua_getfield(L, index, "r");
259         color.setRed(lua_tonumber(L, -1));
260         lua_pop(L, 1);
261         lua_getfield(L, index, "g");
262         color.setGreen(lua_tonumber(L, -1));
263         lua_pop(L, 1);
264         lua_getfield(L, index, "b");
265         color.setBlue(lua_tonumber(L, -1));
266         lua_pop(L, 1);
267         return color;
268 }
269
270 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
271 {
272         core::aabbox3d<f32> box;
273         if(lua_istable(L, -1)){
274                 lua_rawgeti(L, -1, 1);
275                 box.MinEdge.X = lua_tonumber(L, -1) * scale;
276                 lua_pop(L, 1);
277                 lua_rawgeti(L, -1, 2);
278                 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
279                 lua_pop(L, 1);
280                 lua_rawgeti(L, -1, 3);
281                 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
282                 lua_pop(L, 1);
283                 lua_rawgeti(L, -1, 4);
284                 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
285                 lua_pop(L, 1);
286                 lua_rawgeti(L, -1, 5);
287                 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
288                 lua_pop(L, 1);
289                 lua_rawgeti(L, -1, 6);
290                 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
291                 lua_pop(L, 1);
292         }
293         return box;
294 }
295
296 static v2s16 read_v2s16(lua_State *L, int index)
297 {
298         v2s16 p;
299         luaL_checktype(L, index, LUA_TTABLE);
300         lua_getfield(L, index, "x");
301         p.X = lua_tonumber(L, -1);
302         lua_pop(L, 1);
303         lua_getfield(L, index, "y");
304         p.Y = lua_tonumber(L, -1);
305         lua_pop(L, 1);
306         return p;
307 }
308
309 static v2f read_v2f(lua_State *L, int index)
310 {
311         v2f p;
312         luaL_checktype(L, index, LUA_TTABLE);
313         lua_getfield(L, index, "x");
314         p.X = lua_tonumber(L, -1);
315         lua_pop(L, 1);
316         lua_getfield(L, index, "y");
317         p.Y = lua_tonumber(L, -1);
318         lua_pop(L, 1);
319         return p;
320 }
321
322 static bool getstringfield(lua_State *L, int table,
323                 const char *fieldname, std::string &result)
324 {
325         lua_getfield(L, table, fieldname);
326         bool got = false;
327         if(lua_isstring(L, -1)){
328                 result = lua_tostring(L, -1);
329                 got = true;
330         }
331         lua_pop(L, 1);
332         return got;
333 }
334
335 static bool getintfield(lua_State *L, int table,
336                 const char *fieldname, int &result)
337 {
338         lua_getfield(L, table, fieldname);
339         bool got = false;
340         if(lua_isnumber(L, -1)){
341                 result = lua_tonumber(L, -1);
342                 got = true;
343         }
344         lua_pop(L, 1);
345         return got;
346 }
347
348 static bool getfloatfield(lua_State *L, int table,
349                 const char *fieldname, float &result)
350 {
351         lua_getfield(L, table, fieldname);
352         bool got = false;
353         if(lua_isnumber(L, -1)){
354                 result = lua_tonumber(L, -1);
355                 got = true;
356         }
357         lua_pop(L, 1);
358         return got;
359 }
360
361 static bool getboolfield(lua_State *L, int table,
362                 const char *fieldname, bool &result)
363 {
364         lua_getfield(L, table, fieldname);
365         bool got = false;
366         if(lua_isboolean(L, -1)){
367                 result = lua_toboolean(L, -1);
368                 got = true;
369         }
370         lua_pop(L, 1);
371         return got;
372 }
373
374 static std::string getstringfield_default(lua_State *L, int table,
375                 const char *fieldname, const std::string &default_)
376 {
377         std::string result = default_;
378         getstringfield(L, table, fieldname, result);
379         return result;
380 }
381
382 static int getintfield_default(lua_State *L, int table,
383                 const char *fieldname, int default_)
384 {
385         int result = default_;
386         getintfield(L, table, fieldname, result);
387         return result;
388 }
389
390 /*static float getfloatfield_default(lua_State *L, int table,
391                 const char *fieldname, float default_)
392 {
393         float result = default_;
394         getfloatfield(L, table, fieldname, result);
395         return result;
396 }*/
397
398 static bool getboolfield_default(lua_State *L, int table,
399                 const char *fieldname, bool default_)
400 {
401         bool result = default_;
402         getboolfield(L, table, fieldname, result);
403         return result;
404 }
405
406 struct EnumString
407 {
408         int num;
409         const char *str;
410 };
411
412 static bool string_to_enum(const EnumString *spec, int &result,
413                 const std::string &str)
414 {
415         const EnumString *esp = spec;
416         while(esp->str){
417                 if(str == std::string(esp->str)){
418                         result = esp->num;
419                         return true;
420                 }
421                 esp++;
422         }
423         return false;
424 }
425
426 /*static bool enum_to_string(const EnumString *spec, std::string &result,
427                 int num)
428 {
429         const EnumString *esp = spec;
430         while(esp){
431                 if(num == esp->num){
432                         result = esp->str;
433                         return true;
434                 }
435                 esp++;
436         }
437         return false;
438 }*/
439
440 static int getenumfield(lua_State *L, int table,
441                 const char *fieldname, const EnumString *spec, int default_)
442 {
443         int result = default_;
444         string_to_enum(spec, result,
445                         getstringfield_default(L, table, fieldname, ""));
446         return result;
447 }
448
449 static void setfloatfield(lua_State *L, int table,
450                 const char *fieldname, float value)
451 {
452         lua_pushnumber(L, value);
453         if(table < 0)
454                 table -= 1;
455         lua_setfield(L, table, fieldname);
456 }
457
458 static void warn_if_field_exists(lua_State *L, int table,
459                 const char *fieldname, const std::string &message)
460 {
461         lua_getfield(L, table, fieldname);
462         if(!lua_isnil(L, -1)){
463                 infostream<<script_get_backtrace(L)<<std::endl;
464                 infostream<<"WARNING: field \""<<fieldname<<"\": "
465                                 <<message<<std::endl;
466         }
467         lua_pop(L, 1);
468 }
469
470 /*
471         Inventory stuff
472 */
473
474 static void inventory_set_list_from_lua(Inventory *inv, const char *name,
475                 lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
476 {
477         if(tableindex < 0)
478                 tableindex = lua_gettop(L) + 1 + tableindex;
479         // If nil, delete list
480         if(lua_isnil(L, tableindex)){
481                 inv->deleteList(name);
482                 return;
483         }
484         // Otherwise set list
485         std::list<std::string> items;
486         luaL_checktype(L, tableindex, LUA_TTABLE);
487         int table = tableindex;
488         lua_pushnil(L);
489         while(lua_next(L, table) != 0){
490                 // key at index -2 and value at index -1
491                 luaL_checktype(L, -1, LUA_TSTRING);
492                 std::string itemstring = lua_tostring(L, -1);
493                 items.push_back(itemstring);
494                 // removes value, keeps key for next iteration
495                 lua_pop(L, 1);
496         }
497         int listsize = (forcesize != -1) ? forcesize : items.size();
498         InventoryList *invlist = inv->addList(name, listsize);
499         int index = 0;
500         for(std::list<std::string>::const_iterator
501                         i = items.begin(); i != items.end(); i++){
502                 if(forcesize != -1 && index == forcesize)
503                         break;
504                 const std::string &itemstring = *i;
505                 InventoryItem *newitem = NULL;
506                 if(itemstring != "")
507                         newitem = InventoryItem::deSerialize(itemstring,
508                                         gamedef);
509                 InventoryItem *olditem = invlist->changeItem(index, newitem);
510                 delete olditem;
511                 index++;
512         }
513         while(forcesize != -1 && index < forcesize){
514                 InventoryItem *olditem = invlist->changeItem(index, NULL);
515                 delete olditem;
516                 index++;
517         }
518 }
519
520 static void inventory_get_list_to_lua(Inventory *inv, const char *name,
521                 lua_State *L)
522 {
523         InventoryList *invlist = inv->getList(name);
524         if(invlist == NULL){
525                 lua_pushnil(L);
526                 return;
527         }
528         // Get the table insert function
529         lua_getglobal(L, "table");
530         lua_getfield(L, -1, "insert");
531         int table_insert = lua_gettop(L);
532         // Create and fill table
533         lua_newtable(L);
534         int table = lua_gettop(L);
535         for(u32 i=0; i<invlist->getSize(); i++){
536                 InventoryItem *item = invlist->getItem(i);
537                 lua_pushvalue(L, table_insert);
538                 lua_pushvalue(L, table);
539                 if(item == NULL){
540                         lua_pushstring(L, "");
541                 } else {
542                         lua_pushstring(L, item->getItemString().c_str());
543                 }
544                 if(lua_pcall(L, 2, 0, 0))
545                         script_error(L, "error: %s", lua_tostring(L, -1));
546         }
547 }
548
549 /*
550         ToolDiggingProperties
551 */
552
553 static ToolDiggingProperties read_tool_digging_properties(
554                 lua_State *L, int table)
555 {
556         ToolDiggingProperties prop;
557         getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
558         getfloatfield(L, table, "basetime", prop.basetime);
559         getfloatfield(L, table, "dt_weight", prop.dt_weight);
560         getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
561         getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
562         getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
563         getfloatfield(L, table, "basedurability", prop.basedurability);
564         getfloatfield(L, table, "dd_weight", prop.dd_weight);
565         getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
566         getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
567         getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
568         return prop;
569 }
570
571 static void set_tool_digging_properties(lua_State *L, int table,
572                 const ToolDiggingProperties &prop)
573 {
574         setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
575         setfloatfield(L, table, "basetime", prop.basetime);
576         setfloatfield(L, table, "dt_weight", prop.dt_weight);
577         setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
578         setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
579         setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
580         setfloatfield(L, table, "basedurability", prop.basedurability);
581         setfloatfield(L, table, "dd_weight", prop.dd_weight);
582         setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
583         setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
584         setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
585 }
586
587 static void push_tool_digging_properties(lua_State *L,
588                 const ToolDiggingProperties &prop)
589 {
590         lua_newtable(L);
591         set_tool_digging_properties(L, -1, prop);
592 }
593
594 /*
595         ToolDefinition
596 */
597
598 static ToolDefinition read_tool_definition(lua_State *L, int table)
599 {
600         ToolDefinition def;
601         getstringfield(L, table, "image", def.imagename);
602         def.properties = read_tool_digging_properties(L, table);
603         return def;
604 }
605
606 static void push_tool_definition(lua_State *L, const ToolDefinition &def)
607 {
608         lua_newtable(L);
609         lua_pushstring(L, def.imagename.c_str());
610         lua_setfield(L, -2, "image");
611         set_tool_digging_properties(L, -1, def.properties);
612 }
613
614 /*
615         EnumString definitions
616 */
617
618 struct EnumString es_DrawType[] =
619 {
620         {NDT_NORMAL, "normal"},
621         {NDT_AIRLIKE, "airlike"},
622         {NDT_LIQUID, "liquid"},
623         {NDT_FLOWINGLIQUID, "flowingliquid"},
624         {NDT_GLASSLIKE, "glasslike"},
625         {NDT_ALLFACES, "allfaces"},
626         {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
627         {NDT_TORCHLIKE, "torchlike"},
628         {NDT_SIGNLIKE, "signlike"},
629         {NDT_PLANTLIKE, "plantlike"},
630         {NDT_FENCELIKE, "fencelike"},
631         {NDT_RAILLIKE, "raillike"},
632         {0, NULL},
633 };
634
635 struct EnumString es_ContentParamType[] =
636 {
637         {CPT_NONE, "none"},
638         {CPT_LIGHT, "light"},
639         {CPT_MINERAL, "mineral"},
640         {CPT_FACEDIR_SIMPLE, "facedir_simple"},
641         {0, NULL},
642 };
643
644 struct EnumString es_LiquidType[] =
645 {
646         {LIQUID_NONE, "none"},
647         {LIQUID_FLOWING, "flowing"},
648         {LIQUID_SOURCE, "source"},
649         {0, NULL},
650 };
651
652 struct EnumString es_NodeBoxType[] =
653 {
654         {NODEBOX_REGULAR, "regular"},
655         {NODEBOX_FIXED, "fixed"},
656         {NODEBOX_WALLMOUNTED, "wallmounted"},
657         {0, NULL},
658 };
659
660 struct EnumString es_Diggability[] =
661 {
662         {DIGGABLE_NOT, "not"},
663         {DIGGABLE_NORMAL, "normal"},
664         {DIGGABLE_CONSTANT, "constant"},
665         {0, NULL},
666 };
667
668 /*
669         Global functions
670 */
671
672 static int l_register_nodedef_defaults(lua_State *L)
673 {
674         luaL_checktype(L, 1, LUA_TTABLE);
675
676         lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
677         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
678
679         return 0;
680 }
681
682 // Register new object prototype
683 // register_entity(name, prototype)
684 static int l_register_entity(lua_State *L)
685 {
686         std::string name = luaL_checkstring(L, 1);
687         check_modname_prefix(L, name);
688         //infostream<<"register_entity: "<<name<<std::endl;
689         luaL_checktype(L, 2, LUA_TTABLE);
690
691         // Get minetest.registered_entities
692         lua_getglobal(L, "minetest");
693         lua_getfield(L, -1, "registered_entities");
694         luaL_checktype(L, -1, LUA_TTABLE);
695         int registered_entities = lua_gettop(L);
696         lua_pushvalue(L, 2); // Object = param 2 -> stack top
697         // registered_entities[name] = object
698         lua_setfield(L, registered_entities, name.c_str());
699         
700         // Get registered object to top of stack
701         lua_pushvalue(L, 2);
702         
703         // Set __index to point to itself
704         lua_pushvalue(L, -1);
705         lua_setfield(L, -2, "__index");
706
707         // Set metatable.__index = metatable
708         luaL_getmetatable(L, "minetest.entity");
709         lua_pushvalue(L, -1); // duplicate metatable
710         lua_setfield(L, -2, "__index");
711         // Set object metatable
712         lua_setmetatable(L, -2);
713
714         return 0; /* number of results */
715 }
716
717 class LuaABM : public ActiveBlockModifier
718 {
719 private:
720         lua_State *m_lua;
721         int m_id;
722
723         std::set<std::string> m_trigger_contents;
724         std::set<std::string> m_required_neighbors;
725         float m_trigger_interval;
726         u32 m_trigger_chance;
727 public:
728         LuaABM(lua_State *L, int id,
729                         const std::set<std::string> &trigger_contents,
730                         const std::set<std::string> &required_neighbors,
731                         float trigger_interval, u32 trigger_chance):
732                 m_lua(L),
733                 m_id(id),
734                 m_trigger_contents(trigger_contents),
735                 m_required_neighbors(required_neighbors),
736                 m_trigger_interval(trigger_interval),
737                 m_trigger_chance(trigger_chance)
738         {
739         }
740         virtual std::set<std::string> getTriggerContents()
741         {
742                 return m_trigger_contents;
743         }
744         virtual std::set<std::string> getRequiredNeighbors()
745         {
746                 return m_required_neighbors;
747         }
748         virtual float getTriggerInterval()
749         {
750                 return m_trigger_interval;
751         }
752         virtual u32 getTriggerChance()
753         {
754                 return m_trigger_chance;
755         }
756         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
757                         u32 active_object_count, u32 active_object_count_wider)
758         {
759                 lua_State *L = m_lua;
760         
761                 realitycheck(L);
762                 assert(lua_checkstack(L, 20));
763                 StackUnroller stack_unroller(L);
764
765                 // Get minetest.registered_abms
766                 lua_getglobal(L, "minetest");
767                 lua_getfield(L, -1, "registered_abms");
768                 luaL_checktype(L, -1, LUA_TTABLE);
769                 int registered_abms = lua_gettop(L);
770
771                 // Get minetest.registered_abms[m_id]
772                 lua_pushnumber(L, m_id);
773                 lua_gettable(L, registered_abms);
774                 if(lua_isnil(L, -1))
775                         assert(0);
776                 
777                 // Call action
778                 luaL_checktype(L, -1, LUA_TTABLE);
779                 lua_getfield(L, -1, "action");
780                 luaL_checktype(L, -1, LUA_TFUNCTION);
781                 pushpos(L, p);
782                 pushnode(L, n, env->getGameDef()->ndef());
783                 lua_pushnumber(L, active_object_count);
784                 lua_pushnumber(L, active_object_count_wider);
785                 if(lua_pcall(L, 4, 0, 0))
786                         script_error(L, "error: %s", lua_tostring(L, -1));
787         }
788 };
789
790 // register_abm({...})
791 static int l_register_abm(lua_State *L)
792 {
793         //infostream<<"register_abm"<<std::endl;
794         luaL_checktype(L, 1, LUA_TTABLE);
795
796         // Get minetest.registered_abms
797         lua_getglobal(L, "minetest");
798         lua_getfield(L, -1, "registered_abms");
799         luaL_checktype(L, -1, LUA_TTABLE);
800         int registered_abms = lua_gettop(L);
801
802         int id = 1;
803         // Find free id
804         for(;;){
805                 lua_pushnumber(L, id);
806                 lua_gettable(L, registered_abms);
807                 if(lua_isnil(L, -1))
808                         break;
809                 lua_pop(L, 1);
810                 id++;
811         }
812         lua_pop(L, 1);
813
814         infostream<<"register_abm: id="<<id<<std::endl;
815
816         // registered_abms[id] = spec
817         lua_pushnumber(L, id);
818         lua_pushvalue(L, 1);
819         lua_settable(L, registered_abms);
820         
821         return 0; /* number of results */
822 }
823
824 // register_tool(name, {lots of stuff})
825 static int l_register_tool(lua_State *L)
826 {
827         std::string name = luaL_checkstring(L, 1);
828         check_modname_prefix(L, name);
829         //infostream<<"register_tool: "<<name<<std::endl;
830         luaL_checktype(L, 2, LUA_TTABLE);
831         int table = 2;
832
833         // Get server from registry
834         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
835         Server *server = (Server*)lua_touserdata(L, -1);
836         // And get the writable tool definition manager from the server
837         IWritableToolDefManager *tooldef =
838                         server->getWritableToolDefManager();
839         
840         ToolDefinition def = read_tool_definition(L, table);
841
842         tooldef->registerTool(name, def);
843         return 0; /* number of results */
844 }
845
846 // register_craftitem(name, {lots of stuff})
847 static int l_register_craftitem(lua_State *L)
848 {
849         std::string name = luaL_checkstring(L, 1);
850         check_modname_prefix(L, name);
851         //infostream<<"register_craftitem: "<<name<<std::endl;
852         luaL_checktype(L, 2, LUA_TTABLE);
853         int table = 2;
854
855         // Get server from registry
856         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
857         Server *server = (Server*)lua_touserdata(L, -1);
858         // And get the writable CraftItem definition manager from the server
859         IWritableCraftItemDefManager *craftitemdef =
860                         server->getWritableCraftItemDefManager();
861         
862         // Check if on_drop is defined
863         lua_getfield(L, table, "on_drop");
864         bool got_on_drop = !lua_isnil(L, -1);
865         lua_pop(L, 1);
866
867         // Check if on_use is defined
868         lua_getfield(L, table, "on_use");
869         bool got_on_use = !lua_isnil(L, -1);
870         lua_pop(L, 1);
871
872         CraftItemDefinition def;
873         
874         getstringfield(L, table, "image", def.imagename);
875         getstringfield(L, table, "cookresult_itemstring", def.cookresult_item);
876         getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
877         getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
878         def.usable = getboolfield_default(L, table, "usable", got_on_use);
879         getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
880         def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
881         def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
882
883         // If an on_drop callback is defined, force dropcount to 1
884         if (got_on_drop)
885                 def.dropcount = 1;
886
887         // Register it
888         craftitemdef->registerCraftItem(name, def);
889
890         lua_pushvalue(L, table);
891         scriptapi_add_craftitem(L, name.c_str());
892
893         return 0; /* number of results */
894 }
895
896 // register_node(name, {lots of stuff})
897 static int l_register_node(lua_State *L)
898 {
899         std::string name = luaL_checkstring(L, 1);
900         check_modname_prefix(L, name);
901         //infostream<<"register_node: "<<name<<std::endl;
902         luaL_checktype(L, 2, LUA_TTABLE);
903         int nodedef_table = 2;
904
905         // Get server from registry
906         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
907         Server *server = (Server*)lua_touserdata(L, -1);
908         // And get the writable node definition manager from the server
909         IWritableNodeDefManager *nodedef =
910                         server->getWritableNodeDefManager();
911         
912         // Get default node definition from registry
913         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
914         int nodedef_default = lua_gettop(L);
915
916         /*
917                 Add to minetest.registered_nodes with default as metatable
918         */
919         
920         // Get the node definition table given as parameter
921         lua_pushvalue(L, nodedef_table);
922
923         // Set __index to point to itself
924         lua_pushvalue(L, -1);
925         lua_setfield(L, -2, "__index");
926
927         // Set nodedef_default as metatable for the definition
928         lua_pushvalue(L, nodedef_default);
929         lua_setmetatable(L, nodedef_table);
930         
931         // minetest.registered_nodes[name] = nodedef
932         lua_getglobal(L, "minetest");
933         lua_getfield(L, -1, "registered_nodes");
934         luaL_checktype(L, -1, LUA_TTABLE);
935         lua_pushstring(L, name.c_str());
936         lua_pushvalue(L, nodedef_table);
937         lua_settable(L, -3);
938
939         /*
940                 Create definition
941         */
942         
943         ContentFeatures f;
944
945         // Default to getting the corresponding NodeItem when dug
946         f.dug_item = std::string("NodeItem \"")+name+"\" 1";
947         
948         // Default to unknown_block.png as all textures
949         f.setAllTextures("unknown_block.png");
950
951         /*
952                 Read definiton from Lua
953         */
954
955         f.name = name;
956         
957         /* Visual definition */
958
959         f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
960                         NDT_NORMAL);
961         getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
962
963         lua_getfield(L, nodedef_table, "tile_images");
964         if(lua_istable(L, -1)){
965                 int table = lua_gettop(L);
966                 lua_pushnil(L);
967                 int i = 0;
968                 while(lua_next(L, table) != 0){
969                         // key at index -2 and value at index -1
970                         if(lua_isstring(L, -1))
971                                 f.tname_tiles[i] = lua_tostring(L, -1);
972                         else
973                                 f.tname_tiles[i] = "";
974                         // removes value, keeps key for next iteration
975                         lua_pop(L, 1);
976                         i++;
977                         if(i==6){
978                                 lua_pop(L, 1);
979                                 break;
980                         }
981                 }
982                 // Copy last value to all remaining textures
983                 if(i >= 1){
984                         std::string lastname = f.tname_tiles[i-1];
985                         while(i < 6){
986                                 f.tname_tiles[i] = lastname;
987                                 i++;
988                         }
989                 }
990         }
991         lua_pop(L, 1);
992
993         getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
994
995         lua_getfield(L, nodedef_table, "special_materials");
996         if(lua_istable(L, -1)){
997                 int table = lua_gettop(L);
998                 lua_pushnil(L);
999                 int i = 0;
1000                 while(lua_next(L, table) != 0){
1001                         // key at index -2 and value at index -1
1002                         int smtable = lua_gettop(L);
1003                         std::string tname = getstringfield_default(
1004                                         L, smtable, "image", "");
1005                         bool backface_culling = getboolfield_default(
1006                                         L, smtable, "backface_culling", true);
1007                         MaterialSpec mspec(tname, backface_culling);
1008                         f.setSpecialMaterial(i, mspec);
1009                         // removes value, keeps key for next iteration
1010                         lua_pop(L, 1);
1011                         i++;
1012                         if(i==6){
1013                                 lua_pop(L, 1);
1014                                 break;
1015                         }
1016                 }
1017         }
1018         lua_pop(L, 1);
1019
1020         f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
1021
1022         /* Other stuff */
1023         
1024         lua_getfield(L, nodedef_table, "post_effect_color");
1025         if(!lua_isnil(L, -1))
1026                 f.post_effect_color = readARGB8(L, -1);
1027         lua_pop(L, 1);
1028
1029         f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
1030                         es_ContentParamType, CPT_NONE);
1031         
1032         // True for all ground-like things like stone and mud, false for eg. trees
1033         getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
1034         f.light_propagates = (f.param_type == CPT_LIGHT);
1035         warn_if_field_exists(L, nodedef_table, "light_propagates",
1036                         "deprecated: determined from paramtype");
1037         getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
1038         // This is used for collision detection.
1039         // Also for general solidness queries.
1040         getboolfield(L, nodedef_table, "walkable", f.walkable);
1041         // Player can point to these
1042         getboolfield(L, nodedef_table, "pointable", f.pointable);
1043         // Player can dig these
1044         getboolfield(L, nodedef_table, "diggable", f.diggable);
1045         // Player can climb these
1046         getboolfield(L, nodedef_table, "climbable", f.climbable);
1047         // Player can build on these
1048         getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
1049         // If true, param2 is set to direction when placed. Used for torches.
1050         // NOTE: the direction format is quite inefficient and should be changed
1051         getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
1052         // Whether this content type often contains mineral.
1053         // Used for texture atlas creation.
1054         // Currently only enabled for CONTENT_STONE.
1055         getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
1056         // Inventory item string as which the node appears in inventory when dug.
1057         // Mineral overrides this.
1058         getstringfield(L, nodedef_table, "dug_item", f.dug_item);
1059         // Extra dug item and its rarity
1060         getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
1061         // Usual get interval for extra dug item
1062         getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
1063         // Metadata name of node (eg. "furnace")
1064         getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
1065         // Whether the node is non-liquid, source liquid or flowing liquid
1066         f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
1067                         es_LiquidType, LIQUID_NONE);
1068         // If the content is liquid, this is the flowing version of the liquid.
1069         getstringfield(L, nodedef_table, "liquid_alternative_flowing",
1070                         f.liquid_alternative_flowing);
1071         // If the content is liquid, this is the source version of the liquid.
1072         getstringfield(L, nodedef_table, "liquid_alternative_source",
1073                         f.liquid_alternative_source);
1074         // Viscosity for fluid flow, ranging from 1 to 7, with
1075         // 1 giving almost instantaneous propagation and 7 being
1076         // the slowest possible
1077         f.liquid_viscosity = getintfield_default(L, nodedef_table,
1078                         "liquid_viscosity", f.liquid_viscosity);
1079         // Amount of light the node emits
1080         f.light_source = getintfield_default(L, nodedef_table,
1081                         "light_source", f.light_source);
1082         f.damage_per_second = getintfield_default(L, nodedef_table,
1083                         "damage_per_second", f.damage_per_second);
1084         
1085         lua_getfield(L, nodedef_table, "selection_box");
1086         if(lua_istable(L, -1)){
1087                 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
1088                                 es_NodeBoxType, NODEBOX_REGULAR);
1089
1090                 lua_getfield(L, -1, "fixed");
1091                 if(lua_istable(L, -1))
1092                         f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
1093                 lua_pop(L, 1);
1094
1095                 lua_getfield(L, -1, "wall_top");
1096                 if(lua_istable(L, -1))
1097                         f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
1098                 lua_pop(L, 1);
1099
1100                 lua_getfield(L, -1, "wall_bottom");
1101                 if(lua_istable(L, -1))
1102                         f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
1103                 lua_pop(L, 1);
1104
1105                 lua_getfield(L, -1, "wall_side");
1106                 if(lua_istable(L, -1))
1107                         f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
1108                 lua_pop(L, 1);
1109         }
1110         lua_pop(L, 1);
1111
1112         lua_getfield(L, nodedef_table, "material");
1113         if(lua_istable(L, -1)){
1114                 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
1115                                 es_Diggability, DIGGABLE_NORMAL);
1116                 
1117                 getfloatfield(L, -1, "constant_time", f.material.constant_time);
1118                 getfloatfield(L, -1, "weight", f.material.weight);
1119                 getfloatfield(L, -1, "crackiness", f.material.crackiness);
1120                 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
1121                 getfloatfield(L, -1, "cuttability", f.material.cuttability);
1122                 getfloatfield(L, -1, "flammability", f.material.flammability);
1123         }
1124         lua_pop(L, 1);
1125
1126         getstringfield(L, nodedef_table, "cookresult_itemstring", f.cookresult_item);
1127         getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
1128         getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
1129         
1130         /*
1131                 Register it
1132         */
1133         
1134         nodedef->set(name, f);
1135         
1136         return 0; /* number of results */
1137 }
1138
1139 // alias_node(name, convert_to_name)
1140 static int l_alias_node(lua_State *L)
1141 {
1142         std::string name = luaL_checkstring(L, 1);
1143         std::string convert_to = luaL_checkstring(L, 2);
1144
1145         // Get server from registry
1146         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1147         Server *server = (Server*)lua_touserdata(L, -1);
1148         // And get the writable node definition manager from the server
1149         IWritableNodeDefManager *nodedef =
1150                         server->getWritableNodeDefManager();
1151         
1152         nodedef->setAlias(name, convert_to);
1153         
1154         return 0; /* number of results */
1155 }
1156
1157 // alias_tool(name, convert_to_name)
1158 static int l_alias_tool(lua_State *L)
1159 {
1160         std::string name = luaL_checkstring(L, 1);
1161         std::string convert_to = luaL_checkstring(L, 2);
1162
1163         // Get server from registry
1164         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1165         Server *server = (Server*)lua_touserdata(L, -1);
1166         // And get the writable tool definition manager from the server
1167         IWritableToolDefManager *tooldef =
1168                         server->getWritableToolDefManager();
1169         
1170         tooldef->setAlias(name, convert_to);
1171
1172         return 0; /* number of results */
1173 }
1174
1175 // alias_craftitem(name, convert_to_name)
1176 static int l_alias_craftitem(lua_State *L)
1177 {
1178         std::string name = luaL_checkstring(L, 1);
1179         std::string convert_to = luaL_checkstring(L, 2);
1180
1181         // Get server from registry
1182         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1183         Server *server = (Server*)lua_touserdata(L, -1);
1184         // And get the writable CraftItem definition manager from the server
1185         IWritableCraftItemDefManager *craftitemdef =
1186                         server->getWritableCraftItemDefManager();
1187         
1188         craftitemdef->setAlias(name, convert_to);
1189
1190         return 0; /* number of results */
1191 }
1192
1193 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
1194 static int l_register_craft(lua_State *L)
1195 {
1196         //infostream<<"register_craft"<<std::endl;
1197         luaL_checktype(L, 1, LUA_TTABLE);
1198         int table0 = 1;
1199
1200         // Get server from registry
1201         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1202         Server *server = (Server*)lua_touserdata(L, -1);
1203         // And get the writable craft definition manager from the server
1204         IWritableCraftDefManager *craftdef =
1205                         server->getWritableCraftDefManager();
1206         
1207         std::string output;
1208         int width = 0;
1209         std::vector<std::string> input;
1210
1211         lua_getfield(L, table0, "output");
1212         luaL_checktype(L, -1, LUA_TSTRING);
1213         if(lua_isstring(L, -1))
1214                 output = lua_tostring(L, -1);
1215         lua_pop(L, 1);
1216
1217         lua_getfield(L, table0, "recipe");
1218         luaL_checktype(L, -1, LUA_TTABLE);
1219         if(lua_istable(L, -1)){
1220                 int table1 = lua_gettop(L);
1221                 lua_pushnil(L);
1222                 int rowcount = 0;
1223                 while(lua_next(L, table1) != 0){
1224                         int colcount = 0;
1225                         // key at index -2 and value at index -1
1226                         luaL_checktype(L, -1, LUA_TTABLE);
1227                         if(lua_istable(L, -1)){
1228                                 int table2 = lua_gettop(L);
1229                                 lua_pushnil(L);
1230                                 while(lua_next(L, table2) != 0){
1231                                         // key at index -2 and value at index -1
1232                                         luaL_checktype(L, -1, LUA_TSTRING);
1233                                         input.push_back(lua_tostring(L, -1));
1234                                         // removes value, keeps key for next iteration
1235                                         lua_pop(L, 1);
1236                                         colcount++;
1237                                 }
1238                         }
1239                         if(rowcount == 0){
1240                                 width = colcount;
1241                         } else {
1242                                 if(colcount != width){
1243                                         std::string error;
1244                                         error += "Invalid crafting recipe (output=\""
1245                                                         + output + "\")";
1246                                         throw LuaError(L, error);
1247                                 }
1248                         }
1249                         // removes value, keeps key for next iteration
1250                         lua_pop(L, 1);
1251                         rowcount++;
1252                 }
1253         }
1254         lua_pop(L, 1);
1255
1256         CraftDefinition def(output, width, input);
1257         craftdef->registerCraft(def);
1258
1259         return 0; /* number of results */
1260 }
1261
1262 // setting_get(name)
1263 static int l_setting_get(lua_State *L)
1264 {
1265         const char *name = luaL_checkstring(L, 1);
1266         try{
1267                 std::string value = g_settings->get(name);
1268                 lua_pushstring(L, value.c_str());
1269         } catch(SettingNotFoundException &e){
1270                 lua_pushnil(L);
1271         }
1272         return 1;
1273 }
1274
1275 // setting_getbool(name)
1276 static int l_setting_getbool(lua_State *L)
1277 {
1278         const char *name = luaL_checkstring(L, 1);
1279         try{
1280                 bool value = g_settings->getBool(name);
1281                 lua_pushboolean(L, value);
1282         } catch(SettingNotFoundException &e){
1283                 lua_pushnil(L);
1284         }
1285         return 1;
1286 }
1287
1288 // chat_send_all(text)
1289 static int l_chat_send_all(lua_State *L)
1290 {
1291         const char *text = luaL_checkstring(L, 1);
1292         // Get server from registry
1293         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1294         Server *server = (Server*)lua_touserdata(L, -1);
1295         // Send
1296         server->notifyPlayers(narrow_to_wide(text));
1297         return 0;
1298 }
1299
1300 // chat_send_player(name, text)
1301 static int l_chat_send_player(lua_State *L)
1302 {
1303         const char *name = luaL_checkstring(L, 1);
1304         const char *text = luaL_checkstring(L, 2);
1305         // Get server from registry
1306         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1307         Server *server = (Server*)lua_touserdata(L, -1);
1308         // Send
1309         server->notifyPlayer(name, narrow_to_wide(text));
1310         return 0;
1311 }
1312
1313 // get_player_privs(name, text)
1314 static int l_get_player_privs(lua_State *L)
1315 {
1316         const char *name = luaL_checkstring(L, 1);
1317         // Get server from registry
1318         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1319         Server *server = (Server*)lua_touserdata(L, -1);
1320         // Do it
1321         lua_newtable(L);
1322         int table = lua_gettop(L);
1323         u64 privs_i = server->getPlayerAuthPrivs(name);
1324         // Special case for the "name" setting (local player / server owner)
1325         if(name == g_settings->get("name"))
1326                 privs_i = PRIV_ALL;
1327         std::set<std::string> privs_s = privsToSet(privs_i);
1328         for(std::set<std::string>::const_iterator
1329                         i = privs_s.begin(); i != privs_s.end(); i++){
1330                 lua_pushboolean(L, true);
1331                 lua_setfield(L, table, i->c_str());
1332         }
1333         lua_pushvalue(L, table);
1334         return 1;
1335 }
1336
1337 static const struct luaL_Reg minetest_f [] = {
1338         {"register_nodedef_defaults", l_register_nodedef_defaults},
1339         {"register_entity", l_register_entity},
1340         {"register_tool", l_register_tool},
1341         {"register_craftitem", l_register_craftitem},
1342         {"register_node", l_register_node},
1343         {"register_craft", l_register_craft},
1344         {"register_abm", l_register_abm},
1345         {"alias_node", l_alias_node},
1346         {"alias_tool", l_alias_tool},
1347         {"alias_craftitem", l_alias_craftitem},
1348         {"setting_get", l_setting_get},
1349         {"setting_getbool", l_setting_getbool},
1350         {"chat_send_all", l_chat_send_all},
1351         {"chat_send_player", l_chat_send_player},
1352         {"get_player_privs", l_get_player_privs},
1353         {NULL, NULL}
1354 };
1355
1356 /*
1357         LuaEntity functions
1358 */
1359
1360 static const struct luaL_Reg minetest_entity_m [] = {
1361         {NULL, NULL}
1362 };
1363
1364 /*
1365         Getters for stuff in main tables
1366 */
1367
1368 static void objectref_get(lua_State *L, u16 id)
1369 {
1370         // Get minetest.object_refs[i]
1371         lua_getglobal(L, "minetest");
1372         lua_getfield(L, -1, "object_refs");
1373         luaL_checktype(L, -1, LUA_TTABLE);
1374         lua_pushnumber(L, id);
1375         lua_gettable(L, -2);
1376         lua_remove(L, -2); // object_refs
1377         lua_remove(L, -2); // minetest
1378 }
1379
1380 static void luaentity_get(lua_State *L, u16 id)
1381 {
1382         // Get minetest.luaentities[i]
1383         lua_getglobal(L, "minetest");
1384         lua_getfield(L, -1, "luaentities");
1385         luaL_checktype(L, -1, LUA_TTABLE);
1386         lua_pushnumber(L, id);
1387         lua_gettable(L, -2);
1388         lua_remove(L, -2); // luaentities
1389         lua_remove(L, -2); // minetest
1390 }
1391
1392 /*
1393         Reference wrappers
1394 */
1395
1396 #define method(class, name) {#name, class::l_##name}
1397
1398 /*
1399         NodeMetaRef
1400 */
1401
1402 class NodeMetaRef
1403 {
1404 private:
1405         v3s16 m_p;
1406         ServerEnvironment *m_env;
1407
1408         static const char className[];
1409         static const luaL_reg methods[];
1410
1411         static NodeMetaRef *checkobject(lua_State *L, int narg)
1412         {
1413                 luaL_checktype(L, narg, LUA_TUSERDATA);
1414                 void *ud = luaL_checkudata(L, narg, className);
1415                 if(!ud) luaL_typerror(L, narg, className);
1416                 return *(NodeMetaRef**)ud;  // unbox pointer
1417         }
1418         
1419         static NodeMetadata* getmeta(NodeMetaRef *ref)
1420         {
1421                 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1422                 return meta;
1423         }
1424
1425         /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1426         {
1427                 NodeMetadata *meta = getmeta(ref);
1428                 if(meta == NULL)
1429                         return NULL;
1430                 if(meta->typeId() != NODEMETA_GENERIC)
1431                         return NULL;
1432                 return (IGenericNodeMetadata*)meta;
1433         }*/
1434
1435         static void reportMetadataChange(NodeMetaRef *ref)
1436         {
1437                 // Inform other things that the metadata has changed
1438                 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1439                 MapEditEvent event;
1440                 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1441                 event.p = blockpos;
1442                 ref->m_env->getMap().dispatchEvent(&event);
1443                 // Set the block to be saved
1444                 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1445                 if(block)
1446                         block->raiseModified(MOD_STATE_WRITE_NEEDED,
1447                                         "NodeMetaRef::reportMetadataChange");
1448         }
1449         
1450         // Exported functions
1451         
1452         // garbage collector
1453         static int gc_object(lua_State *L) {
1454                 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1455                 delete o;
1456                 return 0;
1457         }
1458
1459         // get_type(self)
1460         static int l_get_type(lua_State *L)
1461         {
1462                 NodeMetaRef *ref = checkobject(L, 1);
1463                 NodeMetadata *meta = getmeta(ref);
1464                 if(meta == NULL){
1465                         lua_pushnil(L);
1466                         return 1;
1467                 }
1468                 // Do it
1469                 lua_pushstring(L, meta->typeName());
1470                 return 1;
1471         }
1472
1473         // allows_text_input(self)
1474         static int l_allows_text_input(lua_State *L)
1475         {
1476                 NodeMetaRef *ref = checkobject(L, 1);
1477                 NodeMetadata *meta = getmeta(ref);
1478                 if(meta == NULL) return 0;
1479                 // Do it
1480                 lua_pushboolean(L, meta->allowsTextInput());
1481                 return 1;
1482         }
1483
1484         // set_text(self, text)
1485         static int l_set_text(lua_State *L)
1486         {
1487                 NodeMetaRef *ref = checkobject(L, 1);
1488                 NodeMetadata *meta = getmeta(ref);
1489                 if(meta == NULL) return 0;
1490                 // Do it
1491                 std::string text = lua_tostring(L, 2);
1492                 meta->setText(text);
1493                 reportMetadataChange(ref);
1494                 return 0;
1495         }
1496
1497         // get_text(self)
1498         static int l_get_text(lua_State *L)
1499         {
1500                 NodeMetaRef *ref = checkobject(L, 1);
1501                 NodeMetadata *meta = getmeta(ref);
1502                 if(meta == NULL) return 0;
1503                 // Do it
1504                 std::string text = meta->getText();
1505                 lua_pushstring(L, text.c_str());
1506                 return 1;
1507         }
1508
1509         // get_owner(self)
1510         static int l_get_owner(lua_State *L)
1511         {
1512                 NodeMetaRef *ref = checkobject(L, 1);
1513                 NodeMetadata *meta = getmeta(ref);
1514                 if(meta == NULL) return 0;
1515                 // Do it
1516                 std::string owner = meta->getOwner();
1517                 lua_pushstring(L, owner.c_str());
1518                 return 1;
1519         }
1520
1521         /* IGenericNodeMetadata interface */
1522         
1523         // set_infotext(self, text)
1524         static int l_set_infotext(lua_State *L)
1525         {
1526                 infostream<<__FUNCTION_NAME<<std::endl;
1527                 NodeMetaRef *ref = checkobject(L, 1);
1528                 NodeMetadata *meta = getmeta(ref);
1529                 if(meta == NULL) return 0;
1530                 // Do it
1531                 std::string text = lua_tostring(L, 2);
1532                 meta->setInfoText(text);
1533                 reportMetadataChange(ref);
1534                 return 0;
1535         }
1536
1537         // inventory_set_list(self, name, {item1, item2, ...})
1538         static int l_inventory_set_list(lua_State *L)
1539         {
1540                 NodeMetaRef *ref = checkobject(L, 1);
1541                 NodeMetadata *meta = getmeta(ref);
1542                 if(meta == NULL) return 0;
1543                 // Do it
1544                 Inventory *inv = meta->getInventory();
1545                 const char *name = lua_tostring(L, 2);
1546                 inventory_set_list_from_lua(inv, name, L, 3,
1547                                 ref->m_env->getGameDef());
1548                 reportMetadataChange(ref);
1549                 return 0;
1550         }
1551
1552         // inventory_get_list(self, name)
1553         static int l_inventory_get_list(lua_State *L)
1554         {
1555                 NodeMetaRef *ref = checkobject(L, 1);
1556                 NodeMetadata *meta = getmeta(ref);
1557                 if(meta == NULL) return 0;
1558                 // Do it
1559                 Inventory *inv = meta->getInventory();
1560                 const char *name = lua_tostring(L, 2);
1561                 inventory_get_list_to_lua(inv, name, L);
1562                 return 1;
1563         }
1564
1565         // set_inventory_draw_spec(self, text)
1566         static int l_set_inventory_draw_spec(lua_State *L)
1567         {
1568                 NodeMetaRef *ref = checkobject(L, 1);
1569                 NodeMetadata *meta = getmeta(ref);
1570                 if(meta == NULL) return 0;
1571                 // Do it
1572                 std::string text = lua_tostring(L, 2);
1573                 meta->setInventoryDrawSpec(text);
1574                 reportMetadataChange(ref);
1575                 return 0;
1576         }
1577
1578         // set_allow_text_input(self, text)
1579         static int l_set_allow_text_input(lua_State *L)
1580         {
1581                 NodeMetaRef *ref = checkobject(L, 1);
1582                 NodeMetadata *meta = getmeta(ref);
1583                 if(meta == NULL) return 0;
1584                 // Do it
1585                 bool b = lua_toboolean(L, 2);
1586                 meta->setAllowTextInput(b);
1587                 reportMetadataChange(ref);
1588                 return 0;
1589         }
1590
1591         // set_allow_removal(self, text)
1592         static int l_set_allow_removal(lua_State *L)
1593         {
1594                 NodeMetaRef *ref = checkobject(L, 1);
1595                 NodeMetadata *meta = getmeta(ref);
1596                 if(meta == NULL) return 0;
1597                 // Do it
1598                 bool b = lua_toboolean(L, 2);
1599                 meta->setRemovalDisabled(!b);
1600                 reportMetadataChange(ref);
1601                 return 0;
1602         }
1603
1604         // set_enforce_owner(self, text)
1605         static int l_set_enforce_owner(lua_State *L)
1606         {
1607                 NodeMetaRef *ref = checkobject(L, 1);
1608                 NodeMetadata *meta = getmeta(ref);
1609                 if(meta == NULL) return 0;
1610                 // Do it
1611                 bool b = lua_toboolean(L, 2);
1612                 meta->setEnforceOwner(b);
1613                 reportMetadataChange(ref);
1614                 return 0;
1615         }
1616
1617         // is_inventory_modified(self)
1618         static int l_is_inventory_modified(lua_State *L)
1619         {
1620                 NodeMetaRef *ref = checkobject(L, 1);
1621                 NodeMetadata *meta = getmeta(ref);
1622                 if(meta == NULL) return 0;
1623                 // Do it
1624                 lua_pushboolean(L, meta->isInventoryModified());
1625                 return 1;
1626         }
1627
1628         // reset_inventory_modified(self)
1629         static int l_reset_inventory_modified(lua_State *L)
1630         {
1631                 NodeMetaRef *ref = checkobject(L, 1);
1632                 NodeMetadata *meta = getmeta(ref);
1633                 if(meta == NULL) return 0;
1634                 // Do it
1635                 meta->resetInventoryModified();
1636                 reportMetadataChange(ref);
1637                 return 0;
1638         }
1639
1640         // is_text_modified(self)
1641         static int l_is_text_modified(lua_State *L)
1642         {
1643                 NodeMetaRef *ref = checkobject(L, 1);
1644                 NodeMetadata *meta = getmeta(ref);
1645                 if(meta == NULL) return 0;
1646                 // Do it
1647                 lua_pushboolean(L, meta->isTextModified());
1648                 return 1;
1649         }
1650
1651         // reset_text_modified(self)
1652         static int l_reset_text_modified(lua_State *L)
1653         {
1654                 NodeMetaRef *ref = checkobject(L, 1);
1655                 NodeMetadata *meta = getmeta(ref);
1656                 if(meta == NULL) return 0;
1657                 // Do it
1658                 meta->resetTextModified();
1659                 reportMetadataChange(ref);
1660                 return 0;
1661         }
1662
1663         // set_string(self, name, var)
1664         static int l_set_string(lua_State *L)
1665         {
1666                 NodeMetaRef *ref = checkobject(L, 1);
1667                 NodeMetadata *meta = getmeta(ref);
1668                 if(meta == NULL) return 0;
1669                 // Do it
1670                 std::string name = lua_tostring(L, 2);
1671                 size_t len = 0;
1672                 const char *s = lua_tolstring(L, 3, &len);
1673                 std::string str(s, len);
1674                 meta->setString(name, str);
1675                 reportMetadataChange(ref);
1676                 return 0;
1677         }
1678
1679         // get_string(self, name)
1680         static int l_get_string(lua_State *L)
1681         {
1682                 NodeMetaRef *ref = checkobject(L, 1);
1683                 NodeMetadata *meta = getmeta(ref);
1684                 if(meta == NULL) return 0;
1685                 // Do it
1686                 std::string name = lua_tostring(L, 2);
1687                 std::string str = meta->getString(name);
1688                 lua_pushlstring(L, str.c_str(), str.size());
1689                 return 1;
1690         }
1691
1692 public:
1693         NodeMetaRef(v3s16 p, ServerEnvironment *env):
1694                 m_p(p),
1695                 m_env(env)
1696         {
1697         }
1698
1699         ~NodeMetaRef()
1700         {
1701         }
1702
1703         // Creates an NodeMetaRef and leaves it on top of stack
1704         // Not callable from Lua; all references are created on the C side.
1705         static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
1706         {
1707                 NodeMetaRef *o = new NodeMetaRef(p, env);
1708                 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
1709                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1710                 luaL_getmetatable(L, className);
1711                 lua_setmetatable(L, -2);
1712         }
1713
1714         static void Register(lua_State *L)
1715         {
1716                 lua_newtable(L);
1717                 int methodtable = lua_gettop(L);
1718                 luaL_newmetatable(L, className);
1719                 int metatable = lua_gettop(L);
1720
1721                 lua_pushliteral(L, "__metatable");
1722                 lua_pushvalue(L, methodtable);
1723                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1724
1725                 lua_pushliteral(L, "__index");
1726                 lua_pushvalue(L, methodtable);
1727                 lua_settable(L, metatable);
1728
1729                 lua_pushliteral(L, "__gc");
1730                 lua_pushcfunction(L, gc_object);
1731                 lua_settable(L, metatable);
1732
1733                 lua_pop(L, 1);  // drop metatable
1734
1735                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
1736                 lua_pop(L, 1);  // drop methodtable
1737
1738                 // Cannot be created from Lua
1739                 //lua_register(L, className, create_object);
1740         }
1741 };
1742 const char NodeMetaRef::className[] = "NodeMetaRef";
1743 const luaL_reg NodeMetaRef::methods[] = {
1744         method(NodeMetaRef, get_type),
1745         method(NodeMetaRef, allows_text_input),
1746         method(NodeMetaRef, set_text),
1747         method(NodeMetaRef, get_text),
1748         method(NodeMetaRef, get_owner),
1749         method(NodeMetaRef, set_infotext),
1750         method(NodeMetaRef, inventory_set_list),
1751         method(NodeMetaRef, inventory_get_list),
1752         method(NodeMetaRef, set_inventory_draw_spec),
1753         method(NodeMetaRef, set_allow_text_input),
1754         method(NodeMetaRef, set_allow_removal),
1755         method(NodeMetaRef, set_enforce_owner),
1756         method(NodeMetaRef, is_inventory_modified),
1757         method(NodeMetaRef, reset_inventory_modified),
1758         method(NodeMetaRef, is_text_modified),
1759         method(NodeMetaRef, reset_text_modified),
1760         method(NodeMetaRef, set_string),
1761         method(NodeMetaRef, get_string),
1762         {0,0}
1763 };
1764
1765 /*
1766         ObjectRef
1767 */
1768
1769 class ObjectRef
1770 {
1771 private:
1772         ServerActiveObject *m_object;
1773
1774         static const char className[];
1775         static const luaL_reg methods[];
1776
1777         static ObjectRef *checkobject(lua_State *L, int narg)
1778         {
1779                 luaL_checktype(L, narg, LUA_TUSERDATA);
1780                 void *ud = luaL_checkudata(L, narg, className);
1781                 if(!ud) luaL_typerror(L, narg, className);
1782                 return *(ObjectRef**)ud;  // unbox pointer
1783         }
1784         
1785         static ServerActiveObject* getobject(ObjectRef *ref)
1786         {
1787                 ServerActiveObject *co = ref->m_object;
1788                 return co;
1789         }
1790         
1791         static LuaEntitySAO* getluaobject(ObjectRef *ref)
1792         {
1793                 ServerActiveObject *obj = getobject(ref);
1794                 if(obj == NULL)
1795                         return NULL;
1796                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1797                         return NULL;
1798                 return (LuaEntitySAO*)obj;
1799         }
1800         
1801         static ServerRemotePlayer* getplayer(ObjectRef *ref)
1802         {
1803                 ServerActiveObject *obj = getobject(ref);
1804                 if(obj == NULL)
1805                         return NULL;
1806                 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
1807                         return NULL;
1808                 return static_cast<ServerRemotePlayer*>(obj);
1809         }
1810         
1811         // Exported functions
1812         
1813         // garbage collector
1814         static int gc_object(lua_State *L) {
1815                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1816                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1817                 delete o;
1818                 return 0;
1819         }
1820
1821         // remove(self)
1822         static int l_remove(lua_State *L)
1823         {
1824                 ObjectRef *ref = checkobject(L, 1);
1825                 ServerActiveObject *co = getobject(ref);
1826                 if(co == NULL) return 0;
1827                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1828                 co->m_removed = true;
1829                 return 0;
1830         }
1831         
1832         // getpos(self)
1833         // returns: {x=num, y=num, z=num}
1834         static int l_getpos(lua_State *L)
1835         {
1836                 ObjectRef *ref = checkobject(L, 1);
1837                 ServerActiveObject *co = getobject(ref);
1838                 if(co == NULL) return 0;
1839                 v3f pos = co->getBasePosition() / BS;
1840                 lua_newtable(L);
1841                 lua_pushnumber(L, pos.X);
1842                 lua_setfield(L, -2, "x");
1843                 lua_pushnumber(L, pos.Y);
1844                 lua_setfield(L, -2, "y");
1845                 lua_pushnumber(L, pos.Z);
1846                 lua_setfield(L, -2, "z");
1847                 return 1;
1848         }
1849         
1850         // setpos(self, pos)
1851         static int l_setpos(lua_State *L)
1852         {
1853                 ObjectRef *ref = checkobject(L, 1);
1854                 //LuaEntitySAO *co = getluaobject(ref);
1855                 ServerActiveObject *co = getobject(ref);
1856                 if(co == NULL) return 0;
1857                 // pos
1858                 v3f pos = readFloatPos(L, 2);
1859                 // Do it
1860                 co->setPos(pos);
1861                 return 0;
1862         }
1863         
1864         // moveto(self, pos, continuous=false)
1865         static int l_moveto(lua_State *L)
1866         {
1867                 ObjectRef *ref = checkobject(L, 1);
1868                 //LuaEntitySAO *co = getluaobject(ref);
1869                 ServerActiveObject *co = getobject(ref);
1870                 if(co == NULL) return 0;
1871                 // pos
1872                 v3f pos = readFloatPos(L, 2);
1873                 // continuous
1874                 bool continuous = lua_toboolean(L, 3);
1875                 // Do it
1876                 co->moveTo(pos, continuous);
1877                 return 0;
1878         }
1879
1880         // punch(self, puncher); puncher = an another ObjectRef
1881         static int l_punch(lua_State *L)
1882         {
1883                 ObjectRef *ref = checkobject(L, 1);
1884                 ObjectRef *ref2 = checkobject(L, 2);
1885                 ServerActiveObject *co = getobject(ref);
1886                 ServerActiveObject *co2 = getobject(ref2);
1887                 if(co == NULL) return 0;
1888                 if(co2 == NULL) return 0;
1889                 // Do it
1890                 co->punch(co2);
1891                 return 0;
1892         }
1893
1894         // right_click(self, clicker); clicker = an another ObjectRef
1895         static int l_right_click(lua_State *L)
1896         {
1897                 ObjectRef *ref = checkobject(L, 1);
1898                 ObjectRef *ref2 = checkobject(L, 2);
1899                 ServerActiveObject *co = getobject(ref);
1900                 ServerActiveObject *co2 = getobject(ref2);
1901                 if(co == NULL) return 0;
1902                 if(co2 == NULL) return 0;
1903                 // Do it
1904                 co->rightClick(co2);
1905                 return 0;
1906         }
1907
1908         // get_wield_digging_properties(self)
1909         static int l_get_wield_digging_properties(lua_State *L)
1910         {
1911                 ObjectRef *ref = checkobject(L, 1);
1912                 ServerActiveObject *co = getobject(ref);
1913                 if(co == NULL) return 0;
1914                 // Do it
1915                 ToolDiggingProperties prop;
1916                 co->getWieldDiggingProperties(&prop);
1917                 push_tool_digging_properties(L, prop);
1918                 return 1;
1919         }
1920
1921         // damage_wielded_item(self, amount)
1922         static int l_damage_wielded_item(lua_State *L)
1923         {
1924                 ObjectRef *ref = checkobject(L, 1);
1925                 ServerActiveObject *co = getobject(ref);
1926                 if(co == NULL) return 0;
1927                 // Do it
1928                 int amount = lua_tonumber(L, 2);
1929                 co->damageWieldedItem(amount);
1930                 return 0;
1931         }
1932
1933         // add_to_inventory(self, itemstring)
1934         // returns: true if item was added, (false, "reason") otherwise
1935         static int l_add_to_inventory(lua_State *L)
1936         {
1937                 ObjectRef *ref = checkobject(L, 1);
1938                 luaL_checkstring(L, 2);
1939                 ServerActiveObject *co = getobject(ref);
1940                 if(co == NULL) return 0;
1941                 // itemstring
1942                 const char *itemstring = lua_tostring(L, 2);
1943                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1944                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1945                 // Do it
1946                 std::istringstream is(itemstring, std::ios::binary);
1947                 ServerEnvironment *env = co->getEnv();
1948                 assert(env);
1949                 IGameDef *gamedef = env->getGameDef();
1950                 try{
1951                         InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1952                         if(item->getCount() == 0)
1953                                 item->setCount(1);
1954                         bool added = co->addToInventory(item);
1955                         // Return
1956                         lua_pushboolean(L, added);
1957                         if(!added)
1958                                 lua_pushstring(L, "failed to add item");
1959                         return 2;
1960                 } catch(SerializationError &e){
1961                         // Return
1962                         lua_pushboolean(L, false);
1963                         lua_pushstring(L, (std::string("Invalid item: ")
1964                                         + e.what()).c_str());
1965                         return 2;
1966                 }
1967         }
1968
1969         // add_to_inventory_later(self, itemstring)
1970         // returns: nil
1971         static int l_add_to_inventory_later(lua_State *L)
1972         {
1973                 ObjectRef *ref = checkobject(L, 1);
1974                 luaL_checkstring(L, 2);
1975                 ServerActiveObject *co = getobject(ref);
1976                 if(co == NULL) return 0;
1977                 // itemstring
1978                 const char *itemstring = lua_tostring(L, 2);
1979                 infostream<<"ObjectRef::l_add_to_inventory_later(): id="<<co->getId()
1980                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1981                 // Do it
1982                 std::istringstream is(itemstring, std::ios::binary);
1983                 ServerEnvironment *env = co->getEnv();
1984                 assert(env);
1985                 IGameDef *gamedef = env->getGameDef();
1986                 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1987                 infostream<<"item="<<env<<std::endl;
1988                 co->addToInventoryLater(item);
1989                 // Return
1990                 return 0;
1991         }
1992
1993         // set_hp(self, hp)
1994         // hp = number of hitpoints (2 * number of hearts)
1995         // returns: nil
1996         static int l_set_hp(lua_State *L)
1997         {
1998                 ObjectRef *ref = checkobject(L, 1);
1999                 luaL_checknumber(L, 2);
2000                 ServerActiveObject *co = getobject(ref);
2001                 if(co == NULL) return 0;
2002                 int hp = lua_tonumber(L, 2);
2003                 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
2004                                 <<" hp="<<hp<<std::endl;
2005                 // Do it
2006                 co->setHP(hp);
2007                 // Return
2008                 return 0;
2009         }
2010
2011         // get_hp(self)
2012         // returns: number of hitpoints (2 * number of hearts)
2013         // 0 if not applicable to this type of object
2014         static int l_get_hp(lua_State *L)
2015         {
2016                 ObjectRef *ref = checkobject(L, 1);
2017                 ServerActiveObject *co = getobject(ref);
2018                 if(co == NULL) return 0;
2019                 int hp = co->getHP();
2020                 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
2021                                 <<" hp="<<hp<<std::endl;
2022                 // Return
2023                 lua_pushnumber(L, hp);
2024                 return 1;
2025         }
2026
2027         /* LuaEntitySAO-only */
2028
2029         // setvelocity(self, {x=num, y=num, z=num})
2030         static int l_setvelocity(lua_State *L)
2031         {
2032                 ObjectRef *ref = checkobject(L, 1);
2033                 LuaEntitySAO *co = getluaobject(ref);
2034                 if(co == NULL) return 0;
2035                 // pos
2036                 v3f pos = readFloatPos(L, 2);
2037                 // Do it
2038                 co->setVelocity(pos);
2039                 return 0;
2040         }
2041         
2042         // setacceleration(self, {x=num, y=num, z=num})
2043         static int l_setacceleration(lua_State *L)
2044         {
2045                 ObjectRef *ref = checkobject(L, 1);
2046                 LuaEntitySAO *co = getluaobject(ref);
2047                 if(co == NULL) return 0;
2048                 // pos
2049                 v3f pos = readFloatPos(L, 2);
2050                 // Do it
2051                 co->setAcceleration(pos);
2052                 return 0;
2053         }
2054         
2055         // getacceleration(self)
2056         static int l_getacceleration(lua_State *L)
2057         {
2058                 ObjectRef *ref = checkobject(L, 1);
2059                 LuaEntitySAO *co = getluaobject(ref);
2060                 if(co == NULL) return 0;
2061                 // Do it
2062                 v3f v = co->getAcceleration();
2063                 pushFloatPos(L, v);
2064                 return 1;
2065         }
2066         
2067         // settexturemod(self, mod)
2068         static int l_settexturemod(lua_State *L)
2069         {
2070                 ObjectRef *ref = checkobject(L, 1);
2071                 LuaEntitySAO *co = getluaobject(ref);
2072                 if(co == NULL) return 0;
2073                 // Do it
2074                 std::string mod = lua_tostring(L, 2);
2075                 co->setTextureMod(mod);
2076                 return 0;
2077         }
2078         
2079         // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
2080         //           select_horiz_by_yawpitch=false)
2081         static int l_setsprite(lua_State *L)
2082         {
2083                 ObjectRef *ref = checkobject(L, 1);
2084                 LuaEntitySAO *co = getluaobject(ref);
2085                 if(co == NULL) return 0;
2086                 // Do it
2087                 v2s16 p(0,0);
2088                 if(!lua_isnil(L, 2))
2089                         p = read_v2s16(L, 2);
2090                 int num_frames = 1;
2091                 if(!lua_isnil(L, 3))
2092                         num_frames = lua_tonumber(L, 3);
2093                 float framelength = 0.2;
2094                 if(!lua_isnil(L, 4))
2095                         framelength = lua_tonumber(L, 4);
2096                 bool select_horiz_by_yawpitch = false;
2097                 if(!lua_isnil(L, 5))
2098                         select_horiz_by_yawpitch = lua_toboolean(L, 5);
2099                 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
2100                 return 0;
2101         }
2102
2103         /* Player-only */
2104         
2105         // get_player_name(self)
2106         static int l_get_player_name(lua_State *L)
2107         {
2108                 ObjectRef *ref = checkobject(L, 1);
2109                 ServerRemotePlayer *player = getplayer(ref);
2110                 if(player == NULL){
2111                         lua_pushnil(L);
2112                         return 1;
2113                 }
2114                 // Do it
2115                 lua_pushstring(L, player->getName());
2116                 return 1;
2117         }
2118         
2119         // inventory_set_list(self, name, {item1, item2, ...})
2120         static int l_inventory_set_list(lua_State *L)
2121         {
2122                 ObjectRef *ref = checkobject(L, 1);
2123                 ServerRemotePlayer *player = getplayer(ref);
2124                 if(player == NULL) return 0;
2125                 const char *name = lua_tostring(L, 2);
2126                 // Do it
2127                 inventory_set_list_from_lua(&player->inventory, name, L, 3,
2128                                 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2129                 player->m_inventory_not_sent = true;
2130                 return 0;
2131         }
2132
2133         // inventory_get_list(self, name)
2134         static int l_inventory_get_list(lua_State *L)
2135         {
2136                 ObjectRef *ref = checkobject(L, 1);
2137                 ServerRemotePlayer *player = getplayer(ref);
2138                 if(player == NULL) return 0;
2139                 const char *name = lua_tostring(L, 2);
2140                 // Do it
2141                 inventory_get_list_to_lua(&player->inventory, name, L);
2142                 return 1;
2143         }
2144
2145         // get_wielded_itemstring(self)
2146         static int l_get_wielded_itemstring(lua_State *L)
2147         {
2148                 ObjectRef *ref = checkobject(L, 1);
2149                 ServerRemotePlayer *player = getplayer(ref);
2150                 if(player == NULL) return 0;
2151                 // Do it
2152                 InventoryItem *item = player->getWieldedItem();
2153                 if(item == NULL){
2154                         lua_pushnil(L);
2155                         return 1;
2156                 }
2157                 lua_pushstring(L, item->getItemString().c_str());
2158                 return 1;
2159         }
2160
2161         // get_wielded_item(self)
2162         static int l_get_wielded_item(lua_State *L)
2163         {
2164                 ObjectRef *ref = checkobject(L, 1);
2165                 ServerRemotePlayer *player = getplayer(ref);
2166                 if(player == NULL) return 0;
2167                 // Do it
2168                 InventoryItem *item0 = player->getWieldedItem();
2169                 if(item0 == NULL){
2170                         lua_pushnil(L);
2171                         return 1;
2172                 }
2173                 if(std::string("MaterialItem") == item0->getName()){
2174                         MaterialItem *item = (MaterialItem*)item0;
2175                         lua_newtable(L);
2176                         lua_pushstring(L, "NodeItem");
2177                         lua_setfield(L, -2, "type");
2178                         lua_pushstring(L, item->getNodeName().c_str());
2179                         lua_setfield(L, -2, "name");
2180                 }
2181                 else if(std::string("CraftItem") == item0->getName()){
2182                         CraftItem *item = (CraftItem*)item0;
2183                         lua_newtable(L);
2184                         lua_pushstring(L, "CraftItem");
2185                         lua_setfield(L, -2, "type");
2186                         lua_pushstring(L, item->getSubName().c_str());
2187                         lua_setfield(L, -2, "name");
2188                 }
2189                 else if(std::string("ToolItem") == item0->getName()){
2190                         ToolItem *item = (ToolItem*)item0;
2191                         lua_newtable(L);
2192                         lua_pushstring(L, "ToolItem");
2193                         lua_setfield(L, -2, "type");
2194                         lua_pushstring(L, item->getToolName().c_str());
2195                         lua_setfield(L, -2, "name");
2196                         lua_pushstring(L, itos(item->getWear()).c_str());
2197                         lua_setfield(L, -2, "wear");
2198                 }
2199                 else{
2200                         errorstream<<"l_get_wielded_item: Unknown item name: \""
2201                                         <<item0->getName()<<"\""<<std::endl;
2202                         lua_pushnil(L);
2203                 }
2204                 return 1;
2205         }
2206
2207 public:
2208         ObjectRef(ServerActiveObject *object):
2209                 m_object(object)
2210         {
2211                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2212         }
2213
2214         ~ObjectRef()
2215         {
2216                 /*if(m_object)
2217                         infostream<<"ObjectRef destructing for id="
2218                                         <<m_object->getId()<<std::endl;
2219                 else
2220                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
2221         }
2222
2223         // Creates an ObjectRef and leaves it on top of stack
2224         // Not callable from Lua; all references are created on the C side.
2225         static void create(lua_State *L, ServerActiveObject *object)
2226         {
2227                 ObjectRef *o = new ObjectRef(object);
2228                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2229                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2230                 luaL_getmetatable(L, className);
2231                 lua_setmetatable(L, -2);
2232         }
2233
2234         static void set_null(lua_State *L)
2235         {
2236                 ObjectRef *o = checkobject(L, -1);
2237                 o->m_object = NULL;
2238         }
2239         
2240         static void Register(lua_State *L)
2241         {
2242                 lua_newtable(L);
2243                 int methodtable = lua_gettop(L);
2244                 luaL_newmetatable(L, className);
2245                 int metatable = lua_gettop(L);
2246
2247                 lua_pushliteral(L, "__metatable");
2248                 lua_pushvalue(L, methodtable);
2249                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
2250
2251                 lua_pushliteral(L, "__index");
2252                 lua_pushvalue(L, methodtable);
2253                 lua_settable(L, metatable);
2254
2255                 lua_pushliteral(L, "__gc");
2256                 lua_pushcfunction(L, gc_object);
2257                 lua_settable(L, metatable);
2258
2259                 lua_pop(L, 1);  // drop metatable
2260
2261                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
2262                 lua_pop(L, 1);  // drop methodtable
2263
2264                 // Cannot be created from Lua
2265                 //lua_register(L, className, create_object);
2266         }
2267 };
2268 const char ObjectRef::className[] = "ObjectRef";
2269 const luaL_reg ObjectRef::methods[] = {
2270         // ServerActiveObject
2271         method(ObjectRef, remove),
2272         method(ObjectRef, getpos),
2273         method(ObjectRef, setpos),
2274         method(ObjectRef, moveto),
2275         method(ObjectRef, punch),
2276         method(ObjectRef, right_click),
2277         method(ObjectRef, get_wield_digging_properties),
2278         method(ObjectRef, damage_wielded_item),
2279         method(ObjectRef, add_to_inventory),
2280         method(ObjectRef, add_to_inventory_later),
2281         method(ObjectRef, set_hp),
2282         method(ObjectRef, get_hp),
2283         // LuaEntitySAO-only
2284         method(ObjectRef, setvelocity),
2285         method(ObjectRef, setacceleration),
2286         method(ObjectRef, getacceleration),
2287         method(ObjectRef, settexturemod),
2288         method(ObjectRef, setsprite),
2289         // Player-only
2290         method(ObjectRef, get_player_name),
2291         method(ObjectRef, inventory_set_list),
2292         method(ObjectRef, inventory_get_list),
2293         method(ObjectRef, get_wielded_itemstring),
2294         method(ObjectRef, get_wielded_item),
2295         {0,0}
2296 };
2297
2298 // Creates a new anonymous reference if id=0
2299 static void objectref_get_or_create(lua_State *L,
2300                 ServerActiveObject *cobj)
2301 {
2302         if(cobj->getId() == 0){
2303                 ObjectRef::create(L, cobj);
2304         } else {
2305                 objectref_get(L, cobj->getId());
2306         }
2307 }
2308
2309 /*
2310         EnvRef
2311 */
2312
2313 class EnvRef
2314 {
2315 private:
2316         ServerEnvironment *m_env;
2317
2318         static const char className[];
2319         static const luaL_reg methods[];
2320
2321         static EnvRef *checkobject(lua_State *L, int narg)
2322         {
2323                 luaL_checktype(L, narg, LUA_TUSERDATA);
2324                 void *ud = luaL_checkudata(L, narg, className);
2325                 if(!ud) luaL_typerror(L, narg, className);
2326                 return *(EnvRef**)ud;  // unbox pointer
2327         }
2328         
2329         // Exported functions
2330
2331         // EnvRef:add_node(pos, node)
2332         // pos = {x=num, y=num, z=num}
2333         static int l_add_node(lua_State *L)
2334         {
2335                 //infostream<<"EnvRef::l_add_node()"<<std::endl;
2336                 EnvRef *o = checkobject(L, 1);
2337                 ServerEnvironment *env = o->m_env;
2338                 if(env == NULL) return 0;
2339                 // pos
2340                 v3s16 pos = readpos(L, 2);
2341                 // content
2342                 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
2343                 // Do it
2344                 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
2345                 lua_pushboolean(L, succeeded);
2346                 return 1;
2347         }
2348
2349         // EnvRef:remove_node(pos)
2350         // pos = {x=num, y=num, z=num}
2351         static int l_remove_node(lua_State *L)
2352         {
2353                 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
2354                 EnvRef *o = checkobject(L, 1);
2355                 ServerEnvironment *env = o->m_env;
2356                 if(env == NULL) return 0;
2357                 // pos
2358                 v3s16 pos = readpos(L, 2);
2359                 // Do it
2360                 bool succeeded = env->getMap().removeNodeWithEvent(pos);
2361                 lua_pushboolean(L, succeeded);
2362                 return 1;
2363         }
2364
2365         // EnvRef:get_node(pos)
2366         // pos = {x=num, y=num, z=num}
2367         static int l_get_node(lua_State *L)
2368         {
2369                 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2370                 EnvRef *o = checkobject(L, 1);
2371                 ServerEnvironment *env = o->m_env;
2372                 if(env == NULL) return 0;
2373                 // pos
2374                 v3s16 pos = readpos(L, 2);
2375                 // Do it
2376                 MapNode n = env->getMap().getNodeNoEx(pos);
2377                 // Return node
2378                 pushnode(L, n, env->getGameDef()->ndef());
2379                 return 1;
2380         }
2381
2382         // EnvRef:get_node_or_nil(pos)
2383         // pos = {x=num, y=num, z=num}
2384         static int l_get_node_or_nil(lua_State *L)
2385         {
2386                 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2387                 EnvRef *o = checkobject(L, 1);
2388                 ServerEnvironment *env = o->m_env;
2389                 if(env == NULL) return 0;
2390                 // pos
2391                 v3s16 pos = readpos(L, 2);
2392                 // Do it
2393                 try{
2394                         MapNode n = env->getMap().getNode(pos);
2395                         // Return node
2396                         pushnode(L, n, env->getGameDef()->ndef());
2397                         return 1;
2398                 } catch(InvalidPositionException &e)
2399                 {
2400                         lua_pushnil(L);
2401                         return 1;
2402                 }
2403         }
2404
2405         // EnvRef:add_luaentity(pos, entityname)
2406         // pos = {x=num, y=num, z=num}
2407         static int l_add_luaentity(lua_State *L)
2408         {
2409                 //infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
2410                 EnvRef *o = checkobject(L, 1);
2411                 ServerEnvironment *env = o->m_env;
2412                 if(env == NULL) return 0;
2413                 // pos
2414                 v3f pos = readFloatPos(L, 2);
2415                 // content
2416                 const char *name = lua_tostring(L, 3);
2417                 // Do it
2418                 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
2419                 env->addActiveObject(obj);
2420                 return 0;
2421         }
2422
2423         // EnvRef:add_item(pos, inventorystring)
2424         // pos = {x=num, y=num, z=num}
2425         static int l_add_item(lua_State *L)
2426         {
2427                 infostream<<"EnvRef::l_add_item()"<<std::endl;
2428                 EnvRef *o = checkobject(L, 1);
2429                 ServerEnvironment *env = o->m_env;
2430                 if(env == NULL) return 0;
2431                 // pos
2432                 v3f pos = readFloatPos(L, 2);
2433                 // inventorystring
2434                 const char *inventorystring = lua_tostring(L, 3);
2435                 // Do it
2436                 ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring);
2437                 env->addActiveObject(obj);
2438                 return 0;
2439         }
2440
2441         // EnvRef:add_rat(pos)
2442         // pos = {x=num, y=num, z=num}
2443         static int l_add_rat(lua_State *L)
2444         {
2445                 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2446                 EnvRef *o = checkobject(L, 1);
2447                 ServerEnvironment *env = o->m_env;
2448                 if(env == NULL) return 0;
2449                 // pos
2450                 v3f pos = readFloatPos(L, 2);
2451                 // Do it
2452                 ServerActiveObject *obj = new RatSAO(env, pos);
2453                 env->addActiveObject(obj);
2454                 return 0;
2455         }
2456
2457         // EnvRef:add_firefly(pos)
2458         // pos = {x=num, y=num, z=num}
2459         static int l_add_firefly(lua_State *L)
2460         {
2461                 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2462                 EnvRef *o = checkobject(L, 1);
2463                 ServerEnvironment *env = o->m_env;
2464                 if(env == NULL) return 0;
2465                 // pos
2466                 v3f pos = readFloatPos(L, 2);
2467                 // Do it
2468                 ServerActiveObject *obj = new FireflySAO(env, pos);
2469                 env->addActiveObject(obj);
2470                 return 0;
2471         }
2472
2473         // EnvRef:get_meta(pos)
2474         static int l_get_meta(lua_State *L)
2475         {
2476                 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2477                 EnvRef *o = checkobject(L, 1);
2478                 ServerEnvironment *env = o->m_env;
2479                 if(env == NULL) return 0;
2480                 // Do it
2481                 v3s16 p = readpos(L, 2);
2482                 NodeMetaRef::create(L, p, env);
2483                 return 1;
2484         }
2485
2486         // EnvRef:get_player_by_name(name)
2487         static int l_get_player_by_name(lua_State *L)
2488         {
2489                 EnvRef *o = checkobject(L, 1);
2490                 ServerEnvironment *env = o->m_env;
2491                 if(env == NULL) return 0;
2492                 // Do it
2493                 const char *name = lua_tostring(L, 2);
2494                 ServerRemotePlayer *player =
2495                                 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2496                 if(player == NULL){
2497                         lua_pushnil(L);
2498                         return 1;
2499                 }
2500                 // Put player on stack
2501                 objectref_get_or_create(L, player);
2502                 return 1;
2503         }
2504
2505         static int gc_object(lua_State *L) {
2506                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
2507                 delete o;
2508                 return 0;
2509         }
2510
2511 public:
2512         EnvRef(ServerEnvironment *env):
2513                 m_env(env)
2514         {
2515                 infostream<<"EnvRef created"<<std::endl;
2516         }
2517
2518         ~EnvRef()
2519         {
2520                 infostream<<"EnvRef destructing"<<std::endl;
2521         }
2522
2523         // Creates an EnvRef and leaves it on top of stack
2524         // Not callable from Lua; all references are created on the C side.
2525         static void create(lua_State *L, ServerEnvironment *env)
2526         {
2527                 EnvRef *o = new EnvRef(env);
2528                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
2529                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2530                 luaL_getmetatable(L, className);
2531                 lua_setmetatable(L, -2);
2532         }
2533
2534         static void set_null(lua_State *L)
2535         {
2536                 EnvRef *o = checkobject(L, -1);
2537                 o->m_env = NULL;
2538         }
2539         
2540         static void Register(lua_State *L)
2541         {
2542                 lua_newtable(L);
2543                 int methodtable = lua_gettop(L);
2544                 luaL_newmetatable(L, className);
2545                 int metatable = lua_gettop(L);
2546
2547                 lua_pushliteral(L, "__metatable");
2548                 lua_pushvalue(L, methodtable);
2549                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
2550
2551                 lua_pushliteral(L, "__index");
2552                 lua_pushvalue(L, methodtable);
2553                 lua_settable(L, metatable);
2554
2555                 lua_pushliteral(L, "__gc");
2556                 lua_pushcfunction(L, gc_object);
2557                 lua_settable(L, metatable);
2558
2559                 lua_pop(L, 1);  // drop metatable
2560
2561                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
2562                 lua_pop(L, 1);  // drop methodtable
2563
2564                 // Cannot be created from Lua
2565                 //lua_register(L, className, create_object);
2566         }
2567 };
2568 const char EnvRef::className[] = "EnvRef";
2569 const luaL_reg EnvRef::methods[] = {
2570         method(EnvRef, add_node),
2571         method(EnvRef, remove_node),
2572         method(EnvRef, get_node),
2573         method(EnvRef, get_node_or_nil),
2574         method(EnvRef, add_luaentity),
2575         method(EnvRef, add_item),
2576         method(EnvRef, add_rat),
2577         method(EnvRef, add_firefly),
2578         method(EnvRef, get_meta),
2579         method(EnvRef, get_player_by_name),
2580         {0,0}
2581 };
2582
2583 /*
2584         Main export function
2585 */
2586
2587 void scriptapi_export(lua_State *L, Server *server)
2588 {
2589         realitycheck(L);
2590         assert(lua_checkstack(L, 20));
2591         infostream<<"scriptapi_export"<<std::endl;
2592         StackUnroller stack_unroller(L);
2593
2594         // Store server as light userdata in registry
2595         lua_pushlightuserdata(L, server);
2596         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
2597
2598         // Store nil as minetest_nodedef_defaults in registry
2599         lua_pushnil(L);
2600         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
2601         
2602         // Register global functions in table minetest
2603         lua_newtable(L);
2604         luaL_register(L, NULL, minetest_f);
2605         lua_setglobal(L, "minetest");
2606         
2607         // Get the main minetest table
2608         lua_getglobal(L, "minetest");
2609
2610         // Add tables to minetest
2611         
2612         lua_newtable(L);
2613         lua_setfield(L, -2, "registered_nodes");
2614         lua_newtable(L);
2615         lua_setfield(L, -2, "registered_entities");
2616         lua_newtable(L);
2617         lua_setfield(L, -2, "registered_craftitems");
2618         lua_newtable(L);
2619         lua_setfield(L, -2, "registered_abms");
2620         
2621         lua_newtable(L);
2622         lua_setfield(L, -2, "object_refs");
2623         lua_newtable(L);
2624         lua_setfield(L, -2, "luaentities");
2625
2626         // Create entity prototype
2627         luaL_newmetatable(L, "minetest.entity");
2628         // metatable.__index = metatable
2629         lua_pushvalue(L, -1); // Duplicate metatable
2630         lua_setfield(L, -2, "__index");
2631         // Put functions in metatable
2632         luaL_register(L, NULL, minetest_entity_m);
2633         // Put other stuff in metatable
2634         
2635         // Register reference wrappers
2636         NodeMetaRef::Register(L);
2637         EnvRef::Register(L);
2638         ObjectRef::Register(L);
2639 }
2640
2641 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
2642                 const std::string &modname)
2643 {
2644         ModNameStorer modnamestorer(L, modname);
2645
2646         bool success = false;
2647
2648         try{
2649                 success = script_load(L, scriptpath.c_str());
2650         }
2651         catch(LuaError &e){
2652                 errorstream<<"Error loading mod \""<<modname
2653                                 <<"\": "<<e.what()<<std::endl;
2654         }
2655
2656         return success;
2657 }
2658
2659 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
2660 {
2661         realitycheck(L);
2662         assert(lua_checkstack(L, 20));
2663         infostream<<"scriptapi_add_environment"<<std::endl;
2664         StackUnroller stack_unroller(L);
2665
2666         // Create EnvRef on stack
2667         EnvRef::create(L, env);
2668         int envref = lua_gettop(L);
2669
2670         // minetest.env = envref
2671         lua_getglobal(L, "minetest");
2672         luaL_checktype(L, -1, LUA_TTABLE);
2673         lua_pushvalue(L, envref);
2674         lua_setfield(L, -2, "env");
2675
2676         // Store environment as light userdata in registry
2677         lua_pushlightuserdata(L, env);
2678         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
2679
2680         /*
2681                 Add ActiveBlockModifiers to environment
2682         */
2683
2684         // Get minetest.registered_abms
2685         lua_getglobal(L, "minetest");
2686         lua_getfield(L, -1, "registered_abms");
2687         luaL_checktype(L, -1, LUA_TTABLE);
2688         int registered_abms = lua_gettop(L);
2689         
2690         if(lua_istable(L, registered_abms)){
2691                 int table = lua_gettop(L);
2692                 lua_pushnil(L);
2693                 while(lua_next(L, table) != 0){
2694                         // key at index -2 and value at index -1
2695                         int id = lua_tonumber(L, -2);
2696                         int current_abm = lua_gettop(L);
2697
2698                         std::set<std::string> trigger_contents;
2699                         lua_getfield(L, current_abm, "nodenames");
2700                         if(lua_istable(L, -1)){
2701                                 int table = lua_gettop(L);
2702                                 lua_pushnil(L);
2703                                 while(lua_next(L, table) != 0){
2704                                         // key at index -2 and value at index -1
2705                                         luaL_checktype(L, -1, LUA_TSTRING);
2706                                         trigger_contents.insert(lua_tostring(L, -1));
2707                                         // removes value, keeps key for next iteration
2708                                         lua_pop(L, 1);
2709                                 }
2710                         } else if(lua_isstring(L, -1)){
2711                                 trigger_contents.insert(lua_tostring(L, -1));
2712                         }
2713                         lua_pop(L, 1);
2714
2715                         std::set<std::string> required_neighbors;
2716                         lua_getfield(L, current_abm, "neighbors");
2717                         if(lua_istable(L, -1)){
2718                                 int table = lua_gettop(L);
2719                                 lua_pushnil(L);
2720                                 while(lua_next(L, table) != 0){
2721                                         // key at index -2 and value at index -1
2722                                         luaL_checktype(L, -1, LUA_TSTRING);
2723                                         required_neighbors.insert(lua_tostring(L, -1));
2724                                         // removes value, keeps key for next iteration
2725                                         lua_pop(L, 1);
2726                                 }
2727                         } else if(lua_isstring(L, -1)){
2728                                 required_neighbors.insert(lua_tostring(L, -1));
2729                         }
2730                         lua_pop(L, 1);
2731
2732                         float trigger_interval = 10.0;
2733                         getfloatfield(L, current_abm, "interval", trigger_interval);
2734
2735                         int trigger_chance = 50;
2736                         getintfield(L, current_abm, "chance", trigger_chance);
2737
2738                         LuaABM *abm = new LuaABM(L, id, trigger_contents,
2739                                         required_neighbors, trigger_interval, trigger_chance);
2740                         
2741                         env->addActiveBlockModifier(abm);
2742
2743                         // removes value, keeps key for next iteration
2744                         lua_pop(L, 1);
2745                 }
2746         }
2747         lua_pop(L, 1);
2748 }
2749
2750 #if 0
2751 // Dump stack top with the dump2 function
2752 static void dump2(lua_State *L, const char *name)
2753 {
2754         // Dump object (debug)
2755         lua_getglobal(L, "dump2");
2756         luaL_checktype(L, -1, LUA_TFUNCTION);
2757         lua_pushvalue(L, -2); // Get previous stack top as first parameter
2758         lua_pushstring(L, name);
2759         if(lua_pcall(L, 2, 0, 0))
2760                 script_error(L, "error: %s", lua_tostring(L, -1));
2761 }
2762 #endif
2763
2764 /*
2765         object_reference
2766 */
2767
2768 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
2769 {
2770         realitycheck(L);
2771         assert(lua_checkstack(L, 20));
2772         //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
2773         StackUnroller stack_unroller(L);
2774
2775         // Create object on stack
2776         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
2777         int object = lua_gettop(L);
2778
2779         // Get minetest.object_refs table
2780         lua_getglobal(L, "minetest");
2781         lua_getfield(L, -1, "object_refs");
2782         luaL_checktype(L, -1, LUA_TTABLE);
2783         int objectstable = lua_gettop(L);
2784         
2785         // object_refs[id] = object
2786         lua_pushnumber(L, cobj->getId()); // Push id
2787         lua_pushvalue(L, object); // Copy object to top of stack
2788         lua_settable(L, objectstable);
2789 }
2790
2791 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
2792 {
2793         realitycheck(L);
2794         assert(lua_checkstack(L, 20));
2795         //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
2796         StackUnroller stack_unroller(L);
2797
2798         // Get minetest.object_refs table
2799         lua_getglobal(L, "minetest");
2800         lua_getfield(L, -1, "object_refs");
2801         luaL_checktype(L, -1, LUA_TTABLE);
2802         int objectstable = lua_gettop(L);
2803         
2804         // Get object_refs[id]
2805         lua_pushnumber(L, cobj->getId()); // Push id
2806         lua_gettable(L, objectstable);
2807         // Set object reference to NULL
2808         ObjectRef::set_null(L);
2809         lua_pop(L, 1); // pop object
2810
2811         // Set object_refs[id] = nil
2812         lua_pushnumber(L, cobj->getId()); // Push id
2813         lua_pushnil(L);
2814         lua_settable(L, objectstable);
2815 }
2816
2817 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
2818                 const std::string &message)
2819 {
2820         realitycheck(L);
2821         assert(lua_checkstack(L, 20));
2822         StackUnroller stack_unroller(L);
2823
2824         // Get minetest.registered_on_chat_messages
2825         lua_getglobal(L, "minetest");
2826         lua_getfield(L, -1, "registered_on_chat_messages");
2827         luaL_checktype(L, -1, LUA_TTABLE);
2828         int table = lua_gettop(L);
2829         // Foreach
2830         lua_pushnil(L);
2831         while(lua_next(L, table) != 0){
2832                 // key at index -2 and value at index -1
2833                 luaL_checktype(L, -1, LUA_TFUNCTION);
2834                 // Call function
2835                 lua_pushstring(L, name.c_str());
2836                 lua_pushstring(L, message.c_str());
2837                 if(lua_pcall(L, 2, 1, 0))
2838                         script_error(L, "error: %s", lua_tostring(L, -1));
2839                 bool ate = lua_toboolean(L, -1);
2840                 lua_pop(L, 1);
2841                 if(ate)
2842                         return true;
2843                 // value removed, keep key for next iteration
2844         }
2845         return false;
2846 }
2847
2848 /*
2849         misc
2850 */
2851
2852 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
2853 {
2854         realitycheck(L);
2855         assert(lua_checkstack(L, 20));
2856         StackUnroller stack_unroller(L);
2857
2858         // Get minetest.registered_on_newplayers
2859         lua_getglobal(L, "minetest");
2860         lua_getfield(L, -1, "registered_on_newplayers");
2861         luaL_checktype(L, -1, LUA_TTABLE);
2862         int table = lua_gettop(L);
2863         // Foreach
2864         lua_pushnil(L);
2865         while(lua_next(L, table) != 0){
2866                 // key at index -2 and value at index -1
2867                 luaL_checktype(L, -1, LUA_TFUNCTION);
2868                 // Call function
2869                 objectref_get_or_create(L, player);
2870                 if(lua_pcall(L, 1, 0, 0))
2871                         script_error(L, "error: %s", lua_tostring(L, -1));
2872                 // value removed, keep key for next iteration
2873         }
2874 }
2875 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
2876 {
2877         realitycheck(L);
2878         assert(lua_checkstack(L, 20));
2879         StackUnroller stack_unroller(L);
2880
2881         bool positioning_handled_by_some = false;
2882
2883         // Get minetest.registered_on_respawnplayers
2884         lua_getglobal(L, "minetest");
2885         lua_getfield(L, -1, "registered_on_respawnplayers");
2886         luaL_checktype(L, -1, LUA_TTABLE);
2887         int table = lua_gettop(L);
2888         // Foreach
2889         lua_pushnil(L);
2890         while(lua_next(L, table) != 0){
2891                 // key at index -2 and value at index -1
2892                 luaL_checktype(L, -1, LUA_TFUNCTION);
2893                 // Call function
2894                 objectref_get_or_create(L, player);
2895                 if(lua_pcall(L, 1, 1, 0))
2896                         script_error(L, "error: %s", lua_tostring(L, -1));
2897                 bool positioning_handled = lua_toboolean(L, -1);
2898                 lua_pop(L, 1);
2899                 if(positioning_handled)
2900                         positioning_handled_by_some = true;
2901                 // value removed, keep key for next iteration
2902         }
2903         return positioning_handled_by_some;
2904 }
2905
2906 void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
2907 {
2908         lua_getglobal(L, "minetest");
2909         lua_getfield(L, -1, "creative_inventory");
2910         luaL_checktype(L, -1, LUA_TTABLE);
2911         inventory_set_list_from_lua(&player->inventory, "main", L, -1,
2912                         player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2913 }
2914
2915 /*
2916         craftitem
2917 */
2918
2919 static void pushPointedThing(lua_State *L, const PointedThing& pointed)
2920 {
2921         lua_newtable(L);
2922         if(pointed.type == POINTEDTHING_NODE)
2923         {
2924                 lua_pushstring(L, "node");
2925                 lua_setfield(L, -2, "type");
2926                 pushpos(L, pointed.node_undersurface);
2927                 lua_setfield(L, -2, "under");
2928                 pushpos(L, pointed.node_abovesurface);
2929                 lua_setfield(L, -2, "above");
2930         }
2931         else if(pointed.type == POINTEDTHING_OBJECT)
2932         {
2933                 lua_pushstring(L, "object");
2934                 lua_setfield(L, -2, "type");
2935                 objectref_get(L, pointed.object_id);
2936                 lua_setfield(L, -2, "ref");
2937         }
2938         else
2939         {
2940                 lua_pushstring(L, "nothing");
2941                 lua_setfield(L, -2, "type");
2942         }
2943 }
2944
2945 void scriptapi_add_craftitem(lua_State *L, const char *name)
2946 {
2947         StackUnroller stack_unroller(L);
2948         assert(lua_gettop(L) > 0);
2949
2950         // Set minetest.registered_craftitems[name] = table on top of stack
2951         lua_getglobal(L, "minetest");
2952         lua_getfield(L, -1, "registered_craftitems");
2953         luaL_checktype(L, -1, LUA_TTABLE);
2954         lua_pushvalue(L, -3); // push another reference to the table to be registered
2955         lua_setfield(L, -2, name); // set minetest.registered_craftitems[name]
2956 }
2957
2958 static bool get_craftitem_callback(lua_State *L, const char *name,
2959                 const char *callbackname)
2960 {
2961         // Get minetest.registered_craftitems[name][callbackname]
2962         // If that is nil or on error, return false and stack is unchanged
2963         // If that is a function, returns true and pushes the
2964         // function onto the stack
2965
2966         lua_getglobal(L, "minetest");
2967         lua_getfield(L, -1, "registered_craftitems");
2968         lua_remove(L, -2);
2969         luaL_checktype(L, -1, LUA_TTABLE);
2970         lua_getfield(L, -1, name);
2971         lua_remove(L, -2);
2972         // Should be a table
2973         if(lua_type(L, -1) != LUA_TTABLE)
2974         {
2975                 errorstream<<"CraftItem name \""<<name<<"\" not defined"<<std::endl;
2976                 lua_pop(L, 1);
2977                 return false;
2978         }
2979         lua_getfield(L, -1, callbackname);
2980         lua_remove(L, -2);
2981         // Should be a function or nil
2982         if(lua_type(L, -1) == LUA_TFUNCTION)
2983         {
2984                 return true;
2985         }
2986         else if(lua_isnil(L, -1))
2987         {
2988                 lua_pop(L, 1);
2989                 return false;
2990         }
2991         else
2992         {
2993                 errorstream<<"CraftItem name \""<<name<<"\" callback \""
2994                         <<callbackname<<" is not a function"<<std::endl;
2995                 lua_pop(L, 1);
2996                 return false;
2997         }
2998 }
2999
3000 bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
3001                 ServerActiveObject *dropper, v3f pos,
3002                 bool &callback_exists)
3003 {
3004         realitycheck(L);
3005         assert(lua_checkstack(L, 20));
3006         //infostream<<"scriptapi_craftitem_on_drop"<<std::endl;
3007         StackUnroller stack_unroller(L);
3008
3009         bool result = false;
3010         callback_exists = get_craftitem_callback(L, name, "on_drop");
3011         if(callback_exists)
3012         {
3013                 // Call function
3014                 lua_pushstring(L, name);
3015                 objectref_get_or_create(L, dropper);
3016                 pushFloatPos(L, pos);
3017                 if(lua_pcall(L, 3, 1, 0))
3018                         script_error(L, "error: %s", lua_tostring(L, -1));
3019                 result = lua_toboolean(L, -1);
3020         }
3021         return result;
3022 }
3023
3024 bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
3025                 ServerActiveObject *placer, v3f pos,
3026                 bool &callback_exists)
3027 {
3028         realitycheck(L);
3029         assert(lua_checkstack(L, 20));
3030         //infostream<<"scriptapi_craftitem_on_place_on_ground"<<std::endl;
3031         StackUnroller stack_unroller(L);
3032
3033         bool result = false;
3034         callback_exists = get_craftitem_callback(L, name, "on_place_on_ground");
3035         if(callback_exists)
3036         {
3037                 // Call function
3038                 lua_pushstring(L, name);
3039                 objectref_get_or_create(L, placer);
3040                 pushFloatPos(L, pos);
3041                 if(lua_pcall(L, 3, 1, 0))
3042                         script_error(L, "error: %s", lua_tostring(L, -1));
3043                 result = lua_toboolean(L, -1);
3044         }
3045         return result;
3046 }
3047
3048 bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
3049                 ServerActiveObject *user, const PointedThing& pointed,
3050                 bool &callback_exists)
3051 {
3052         realitycheck(L);
3053         assert(lua_checkstack(L, 20));
3054         //infostream<<"scriptapi_craftitem_on_use"<<std::endl;
3055         StackUnroller stack_unroller(L);
3056
3057         bool result = false;
3058         callback_exists = get_craftitem_callback(L, name, "on_use");
3059         if(callback_exists)
3060         {
3061                 // Call function
3062                 lua_pushstring(L, name);
3063                 objectref_get_or_create(L, user);
3064                 pushPointedThing(L, pointed);
3065                 if(lua_pcall(L, 3, 1, 0))
3066                         script_error(L, "error: %s", lua_tostring(L, -1));
3067                 result = lua_toboolean(L, -1);
3068         }
3069         return result;
3070 }
3071
3072 /*
3073         environment
3074 */
3075
3076 void scriptapi_environment_step(lua_State *L, float dtime)
3077 {
3078         realitycheck(L);
3079         assert(lua_checkstack(L, 20));
3080         //infostream<<"scriptapi_environment_step"<<std::endl;
3081         StackUnroller stack_unroller(L);
3082
3083         // Get minetest.registered_globalsteps
3084         lua_getglobal(L, "minetest");
3085         lua_getfield(L, -1, "registered_globalsteps");
3086         luaL_checktype(L, -1, LUA_TTABLE);
3087         int table = lua_gettop(L);
3088         // Foreach
3089         lua_pushnil(L);
3090         while(lua_next(L, table) != 0){
3091                 // key at index -2 and value at index -1
3092                 luaL_checktype(L, -1, LUA_TFUNCTION);
3093                 // Call function
3094                 lua_pushnumber(L, dtime);
3095                 if(lua_pcall(L, 1, 0, 0))
3096                         script_error(L, "error: %s", lua_tostring(L, -1));
3097                 // value removed, keep key for next iteration
3098         }
3099 }
3100
3101 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
3102                 ServerActiveObject *placer)
3103 {
3104         realitycheck(L);
3105         assert(lua_checkstack(L, 20));
3106         //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
3107         StackUnroller stack_unroller(L);
3108
3109         // Get server from registry
3110         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3111         Server *server = (Server*)lua_touserdata(L, -1);
3112         // And get the writable node definition manager from the server
3113         IWritableNodeDefManager *ndef =
3114                         server->getWritableNodeDefManager();
3115         
3116         // Get minetest.registered_on_placenodes
3117         lua_getglobal(L, "minetest");
3118         lua_getfield(L, -1, "registered_on_placenodes");
3119         luaL_checktype(L, -1, LUA_TTABLE);
3120         int table = lua_gettop(L);
3121         // Foreach
3122         lua_pushnil(L);
3123         while(lua_next(L, table) != 0){
3124                 // key at index -2 and value at index -1
3125                 luaL_checktype(L, -1, LUA_TFUNCTION);
3126                 // Call function
3127                 pushpos(L, p);
3128                 pushnode(L, newnode, ndef);
3129                 objectref_get_or_create(L, placer);
3130                 if(lua_pcall(L, 3, 0, 0))
3131                         script_error(L, "error: %s", lua_tostring(L, -1));
3132                 // value removed, keep key for next iteration
3133         }
3134 }
3135
3136 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
3137                 ServerActiveObject *digger)
3138 {
3139         realitycheck(L);
3140         assert(lua_checkstack(L, 20));
3141         //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
3142         StackUnroller stack_unroller(L);
3143
3144         // Get server from registry
3145         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3146         Server *server = (Server*)lua_touserdata(L, -1);
3147         // And get the writable node definition manager from the server
3148         IWritableNodeDefManager *ndef =
3149                         server->getWritableNodeDefManager();
3150         
3151         // Get minetest.registered_on_dignodes
3152         lua_getglobal(L, "minetest");
3153         lua_getfield(L, -1, "registered_on_dignodes");
3154         luaL_checktype(L, -1, LUA_TTABLE);
3155         int table = lua_gettop(L);
3156         // Foreach
3157         lua_pushnil(L);
3158         while(lua_next(L, table) != 0){
3159                 // key at index -2 and value at index -1
3160                 luaL_checktype(L, -1, LUA_TFUNCTION);
3161                 // Call function
3162                 pushpos(L, p);
3163                 pushnode(L, oldnode, ndef);
3164                 objectref_get_or_create(L, digger);
3165                 if(lua_pcall(L, 3, 0, 0))
3166                         script_error(L, "error: %s", lua_tostring(L, -1));
3167                 // value removed, keep key for next iteration
3168         }
3169 }
3170
3171 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
3172                 ServerActiveObject *puncher)
3173 {
3174         realitycheck(L);
3175         assert(lua_checkstack(L, 20));
3176         //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
3177         StackUnroller stack_unroller(L);
3178
3179         // Get server from registry
3180         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3181         Server *server = (Server*)lua_touserdata(L, -1);
3182         // And get the writable node definition manager from the server
3183         IWritableNodeDefManager *ndef =
3184                         server->getWritableNodeDefManager();
3185         
3186         // Get minetest.registered_on_punchnodes
3187         lua_getglobal(L, "minetest");
3188         lua_getfield(L, -1, "registered_on_punchnodes");
3189         luaL_checktype(L, -1, LUA_TTABLE);
3190         int table = lua_gettop(L);
3191         // Foreach
3192         lua_pushnil(L);
3193         while(lua_next(L, table) != 0){
3194                 // key at index -2 and value at index -1
3195                 luaL_checktype(L, -1, LUA_TFUNCTION);
3196                 // Call function
3197                 pushpos(L, p);
3198                 pushnode(L, node, ndef);
3199                 objectref_get_or_create(L, puncher);
3200                 if(lua_pcall(L, 3, 0, 0))
3201                         script_error(L, "error: %s", lua_tostring(L, -1));
3202                 // value removed, keep key for next iteration
3203         }
3204 }
3205
3206 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
3207 {
3208         realitycheck(L);
3209         assert(lua_checkstack(L, 20));
3210         //infostream<<"scriptapi_environment_on_generated"<<std::endl;
3211         StackUnroller stack_unroller(L);
3212
3213         // Get minetest.registered_on_generateds
3214         lua_getglobal(L, "minetest");
3215         lua_getfield(L, -1, "registered_on_generateds");
3216         luaL_checktype(L, -1, LUA_TTABLE);
3217         int table = lua_gettop(L);
3218         // Foreach
3219         lua_pushnil(L);
3220         while(lua_next(L, table) != 0){
3221                 // key at index -2 and value at index -1
3222                 luaL_checktype(L, -1, LUA_TFUNCTION);
3223                 // Call function
3224                 pushpos(L, minp);
3225                 pushpos(L, maxp);
3226                 if(lua_pcall(L, 2, 0, 0))
3227                         script_error(L, "error: %s", lua_tostring(L, -1));
3228                 // value removed, keep key for next iteration
3229         }
3230 }
3231
3232 /*
3233         luaentity
3234 */
3235
3236 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
3237                 const std::string &staticdata)
3238 {
3239         realitycheck(L);
3240         assert(lua_checkstack(L, 20));
3241         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
3242                         <<name<<"\""<<std::endl;
3243         StackUnroller stack_unroller(L);
3244         
3245         // Get minetest.registered_entities[name]
3246         lua_getglobal(L, "minetest");
3247         lua_getfield(L, -1, "registered_entities");
3248         luaL_checktype(L, -1, LUA_TTABLE);
3249         lua_pushstring(L, name);
3250         lua_gettable(L, -2);
3251         // Should be a table, which we will use as a prototype
3252         //luaL_checktype(L, -1, LUA_TTABLE);
3253         if(lua_type(L, -1) != LUA_TTABLE){
3254                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
3255                 return false;
3256         }
3257         int prototype_table = lua_gettop(L);
3258         //dump2(L, "prototype_table");
3259         
3260         // Create entity object
3261         lua_newtable(L);
3262         int object = lua_gettop(L);
3263
3264         // Set object metatable
3265         lua_pushvalue(L, prototype_table);
3266         lua_setmetatable(L, -2);
3267         
3268         // Add object reference
3269         // This should be userdata with metatable ObjectRef
3270         objectref_get(L, id);
3271         luaL_checktype(L, -1, LUA_TUSERDATA);
3272         if(!luaL_checkudata(L, -1, "ObjectRef"))
3273                 luaL_typerror(L, -1, "ObjectRef");
3274         lua_setfield(L, -2, "object");
3275
3276         // minetest.luaentities[id] = object
3277         lua_getglobal(L, "minetest");
3278         lua_getfield(L, -1, "luaentities");
3279         luaL_checktype(L, -1, LUA_TTABLE);
3280         lua_pushnumber(L, id); // Push id
3281         lua_pushvalue(L, object); // Copy object to top of stack
3282         lua_settable(L, -3);
3283         
3284         // Get on_activate function
3285         lua_pushvalue(L, object);
3286         lua_getfield(L, -1, "on_activate");
3287         if(!lua_isnil(L, -1)){
3288                 luaL_checktype(L, -1, LUA_TFUNCTION);
3289                 lua_pushvalue(L, object); // self
3290                 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
3291                 // Call with 2 arguments, 0 results
3292                 if(lua_pcall(L, 2, 0, 0))
3293                         script_error(L, "error running function %s:on_activate: %s\n",
3294                                         name, lua_tostring(L, -1));
3295         }
3296         
3297         return true;
3298 }
3299
3300 void scriptapi_luaentity_rm(lua_State *L, u16 id)
3301 {
3302         realitycheck(L);
3303         assert(lua_checkstack(L, 20));
3304         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
3305
3306         // Get minetest.luaentities table
3307         lua_getglobal(L, "minetest");
3308         lua_getfield(L, -1, "luaentities");
3309         luaL_checktype(L, -1, LUA_TTABLE);
3310         int objectstable = lua_gettop(L);
3311         
3312         // Set luaentities[id] = nil
3313         lua_pushnumber(L, id); // Push id
3314         lua_pushnil(L);
3315         lua_settable(L, objectstable);
3316         
3317         lua_pop(L, 2); // pop luaentities, minetest
3318 }
3319
3320 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
3321 {
3322         realitycheck(L);
3323         assert(lua_checkstack(L, 20));
3324         infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
3325         StackUnroller stack_unroller(L);
3326
3327         // Get minetest.luaentities[id]
3328         luaentity_get(L, id);
3329         int object = lua_gettop(L);
3330         
3331         // Get get_staticdata function
3332         lua_pushvalue(L, object);
3333         lua_getfield(L, -1, "get_staticdata");
3334         if(lua_isnil(L, -1))
3335                 return "";
3336         
3337         luaL_checktype(L, -1, LUA_TFUNCTION);
3338         lua_pushvalue(L, object); // self
3339         // Call with 1 arguments, 1 results
3340         if(lua_pcall(L, 1, 1, 0))
3341                 script_error(L, "error running function get_staticdata: %s\n",
3342                                 lua_tostring(L, -1));
3343         
3344         size_t len=0;
3345         const char *s = lua_tolstring(L, -1, &len);
3346         return std::string(s, len);
3347 }
3348
3349 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
3350                 LuaEntityProperties *prop)
3351 {
3352         realitycheck(L);
3353         assert(lua_checkstack(L, 20));
3354         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
3355         StackUnroller stack_unroller(L);
3356
3357         // Get minetest.luaentities[id]
3358         luaentity_get(L, id);
3359         //int object = lua_gettop(L);
3360
3361         /* Read stuff */
3362         
3363         getboolfield(L, -1, "physical", prop->physical);
3364
3365         getfloatfield(L, -1, "weight", prop->weight);
3366
3367         lua_getfield(L, -1, "collisionbox");
3368         if(lua_istable(L, -1))
3369                 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
3370         lua_pop(L, 1);
3371
3372         getstringfield(L, -1, "visual", prop->visual);
3373         
3374         lua_getfield(L, -1, "visual_size");
3375         if(lua_istable(L, -1))
3376                 prop->visual_size = read_v2f(L, -1);
3377         lua_pop(L, 1);
3378
3379         lua_getfield(L, -1, "textures");
3380         if(lua_istable(L, -1)){
3381                 prop->textures.clear();
3382                 int table = lua_gettop(L);
3383                 lua_pushnil(L);
3384                 while(lua_next(L, table) != 0){
3385                         // key at index -2 and value at index -1
3386                         if(lua_isstring(L, -1))
3387                                 prop->textures.push_back(lua_tostring(L, -1));
3388                         else
3389                                 prop->textures.push_back("");
3390                         // removes value, keeps key for next iteration
3391                         lua_pop(L, 1);
3392                 }
3393         }
3394         lua_pop(L, 1);
3395         
3396         lua_getfield(L, -1, "spritediv");
3397         if(lua_istable(L, -1))
3398                 prop->spritediv = read_v2s16(L, -1);
3399         lua_pop(L, 1);
3400
3401         lua_getfield(L, -1, "initial_sprite_basepos");
3402         if(lua_istable(L, -1))
3403                 prop->initial_sprite_basepos = read_v2s16(L, -1);
3404         lua_pop(L, 1);
3405 }
3406
3407 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
3408 {
3409         realitycheck(L);
3410         assert(lua_checkstack(L, 20));
3411         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3412         StackUnroller stack_unroller(L);
3413
3414         // Get minetest.luaentities[id]
3415         luaentity_get(L, id);
3416         int object = lua_gettop(L);
3417         // State: object is at top of stack
3418         // Get step function
3419         lua_getfield(L, -1, "on_step");
3420         if(lua_isnil(L, -1))
3421                 return;
3422         luaL_checktype(L, -1, LUA_TFUNCTION);
3423         lua_pushvalue(L, object); // self
3424         lua_pushnumber(L, dtime); // dtime
3425         // Call with 2 arguments, 0 results
3426         if(lua_pcall(L, 2, 0, 0))
3427                 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
3428 }
3429
3430 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
3431 void scriptapi_luaentity_punch(lua_State *L, u16 id,
3432                 ServerActiveObject *puncher, float time_from_last_punch)
3433 {
3434         realitycheck(L);
3435         assert(lua_checkstack(L, 20));
3436         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3437         StackUnroller stack_unroller(L);
3438
3439         // Get minetest.luaentities[id]
3440         luaentity_get(L, id);
3441         int object = lua_gettop(L);
3442         // State: object is at top of stack
3443         // Get function
3444         lua_getfield(L, -1, "on_punch");
3445         if(lua_isnil(L, -1))
3446                 return;
3447         luaL_checktype(L, -1, LUA_TFUNCTION);
3448         lua_pushvalue(L, object); // self
3449         objectref_get_or_create(L, puncher); // Clicker reference
3450         lua_pushnumber(L, time_from_last_punch);
3451         // Call with 2 arguments, 0 results
3452         if(lua_pcall(L, 3, 0, 0))
3453                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
3454 }
3455
3456 // Calls entity:on_rightclick(ObjectRef clicker)
3457 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
3458                 ServerActiveObject *clicker)
3459 {
3460         realitycheck(L);
3461         assert(lua_checkstack(L, 20));
3462         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3463         StackUnroller stack_unroller(L);
3464
3465         // Get minetest.luaentities[id]
3466         luaentity_get(L, id);
3467         int object = lua_gettop(L);
3468         // State: object is at top of stack
3469         // Get function
3470         lua_getfield(L, -1, "on_rightclick");
3471         if(lua_isnil(L, -1))
3472                 return;
3473         luaL_checktype(L, -1, LUA_TFUNCTION);
3474         lua_pushvalue(L, object); // self
3475         objectref_get_or_create(L, clicker); // Clicker reference
3476         // Call with 2 arguments, 0 results
3477         if(lua_pcall(L, 2, 0, 0))
3478                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
3479 }
3480