Falling sand and gravel
[oweals/minetest.git] / src / scriptapi.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "scriptapi.h"
21
22 #include <iostream>
23 extern "C" {
24 #include <lua.h>
25 #include <lualib.h>
26 #include <lauxlib.h>
27 }
28
29 #include "log.h"
30 #include "server.h"
31 #include "porting.h"
32 #include "filesys.h"
33 #include "serverobject.h"
34 #include "script.h"
35 //#include "luna.h"
36 #include "luaentity_common.h"
37 #include "content_sao.h" // For LuaEntitySAO
38 #include "tooldef.h"
39 #include "nodedef.h"
40 #include "craftdef.h"
41
42 /*
43 TODO:
44 - Node definition
45 - Random node triggers (like grass growth)
46 - Deterministic node triggers (like falling sand)
47 - Object visual client-side stuff
48         - Blink effect
49         - Spritesheets and animation
50 - LuaNodeMetadata
51         blockdef.metadata_type =
52                 ""
53                 "sign"
54                 "furnace"
55                 "chest"
56                 "locked_chest"
57                 "lua"
58         - Stores an inventory and stuff in a Settings object
59         meta.inventory_add_list("main")
60         blockdef.on_inventory_modified
61         meta.set("owner", playername)
62         meta.get("owner")
63 - Item definition (actually, only CraftItem)
64 */
65
66 static void stackDump(lua_State *L, std::ostream &o)
67 {
68   int i;
69   int top = lua_gettop(L);
70   for (i = 1; i <= top; i++) {  /* repeat for each level */
71         int t = lua_type(L, i);
72         switch (t) {
73
74           case LUA_TSTRING:  /* strings */
75                 o<<"\""<<lua_tostring(L, i)<<"\"";
76                 break;
77
78           case LUA_TBOOLEAN:  /* booleans */
79                 o<<(lua_toboolean(L, i) ? "true" : "false");
80                 break;
81
82           case LUA_TNUMBER:  /* numbers */ {
83                 char buf[10];
84                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
85                 o<<buf;
86                 break; }
87
88           default:  /* other values */
89                 o<<lua_typename(L, t);
90                 break;
91
92         }
93         o<<" ";
94   }
95   o<<std::endl;
96 }
97
98 static void realitycheck(lua_State *L)
99 {
100         int top = lua_gettop(L);
101         if(top >= 30){
102                 dstream<<"Stack is over 30:"<<std::endl;
103                 stackDump(L, dstream);
104                 script_error(L, "Stack is over 30 (reality check)");
105         }
106 }
107
108 class StackUnroller
109 {
110 private:
111         lua_State *m_lua;
112         int m_original_top;
113 public:
114         StackUnroller(lua_State *L):
115                 m_lua(L),
116                 m_original_top(-1)
117         {
118                 m_original_top = lua_gettop(m_lua); // store stack height
119         }
120         ~StackUnroller()
121         {
122                 lua_settop(m_lua, m_original_top); // restore stack height
123         }
124 };
125
126 static v3f readFloatPos(lua_State *L, int index)
127 {
128         v3f pos;
129         luaL_checktype(L, index, LUA_TTABLE);
130         lua_getfield(L, index, "x");
131         pos.X = lua_tonumber(L, -1);
132         lua_pop(L, 1);
133         lua_getfield(L, index, "y");
134         pos.Y = lua_tonumber(L, -1);
135         lua_pop(L, 1);
136         lua_getfield(L, index, "z");
137         pos.Z = lua_tonumber(L, -1);
138         lua_pop(L, 1);
139         pos *= BS; // Scale to internal format
140         return pos;
141 }
142
143 static void pushpos(lua_State *L, v3s16 p)
144 {
145         lua_newtable(L);
146         lua_pushnumber(L, p.X);
147         lua_setfield(L, -2, "x");
148         lua_pushnumber(L, p.Y);
149         lua_setfield(L, -2, "y");
150         lua_pushnumber(L, p.Z);
151         lua_setfield(L, -2, "z");
152 }
153
154 static v3s16 readpos(lua_State *L, int index)
155 {
156         v3s16 p;
157         lua_getfield(L, index, "x");
158         p.X = lua_tonumber(L, -1);
159         lua_getfield(L, index, "y");
160         p.Y = lua_tonumber(L, -1);
161         lua_getfield(L, index, "z");
162         p.Z = lua_tonumber(L, -1);
163         return p;
164 }
165
166 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
167 {
168         lua_newtable(L);
169         lua_pushstring(L, ndef->get(n).name.c_str());
170         lua_setfield(L, -2, "name");
171         lua_pushnumber(L, n.getParam1());
172         lua_setfield(L, -2, "param1");
173         lua_pushnumber(L, n.getParam2());
174         lua_setfield(L, -2, "param2");
175 }
176
177 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
178 {
179         lua_getfield(L, index, "name");
180         const char *name = lua_tostring(L, -1);
181         lua_pop(L, 1);
182         u8 param1;
183         lua_getfield(L, index, "param1");
184         if(lua_isnil(L, -1))
185                 param1 = 0;
186         else
187                 param1 = lua_tonumber(L, -1);
188         lua_pop(L, 1);
189         u8 param2;
190         lua_getfield(L, index, "param2");
191         if(lua_isnil(L, -1))
192                 param2 = 0;
193         else
194                 param2 = lua_tonumber(L, -1);
195         lua_pop(L, 1);
196         return MapNode(ndef, name, param1, param2);
197 }
198
199 /*
200         Global functions
201 */
202
203 // Register new object prototype
204 // register_entity(name, prototype)
205 static int l_register_entity(lua_State *L)
206 {
207         const char *name = luaL_checkstring(L, 1);
208         infostream<<"register_entity: "<<name<<std::endl;
209         luaL_checktype(L, 2, LUA_TTABLE);
210
211         // Get minetest.registered_entities
212         lua_getglobal(L, "minetest");
213         lua_getfield(L, -1, "registered_entities");
214         luaL_checktype(L, -1, LUA_TTABLE);
215         int registered_entities = lua_gettop(L);
216         lua_pushvalue(L, 2); // Object = param 2 -> stack top
217         // registered_entities[name] = object
218         lua_setfield(L, registered_entities, name);
219         
220         // Get registered object to top of stack
221         lua_pushvalue(L, 2);
222         
223         // Set __index to point to itself
224         lua_pushvalue(L, -1);
225         lua_setfield(L, -2, "__index");
226
227         // Set metatable.__index = metatable
228         luaL_getmetatable(L, "minetest.entity");
229         lua_pushvalue(L, -1); // duplicate metatable
230         lua_setfield(L, -2, "__index");
231         // Set object metatable
232         lua_setmetatable(L, -2);
233
234         return 0; /* number of results */
235 }
236
237 // register_tool(name, {lots of stuff})
238 static int l_register_tool(lua_State *L)
239 {
240         const char *name = luaL_checkstring(L, 1);
241         infostream<<"register_tool: "<<name<<std::endl;
242         luaL_checktype(L, 2, LUA_TTABLE);
243         int table = 2;
244
245         // Get server from registry
246         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
247         Server *server = (Server*)lua_touserdata(L, -1);
248         // And get the writable tool definition manager from the server
249         IWritableToolDefManager *tooldef =
250                         server->getWritableToolDefManager();
251         
252         ToolDefinition def;
253
254         lua_getfield(L, table, "image");
255         if(lua_isstring(L, -1))
256                 def.imagename = lua_tostring(L, -1);
257         lua_pop(L, 1);
258         
259         lua_getfield(L, table, "basetime");
260         def.properties.basetime = lua_tonumber(L, -1);
261         lua_pop(L, 1);
262
263         lua_getfield(L, table, "dt_weight");
264         def.properties.dt_weight = lua_tonumber(L, -1);
265         lua_pop(L, 1);
266
267         lua_getfield(L, table, "dt_crackiness");
268         def.properties.dt_crackiness = lua_tonumber(L, -1);
269         lua_pop(L, 1);
270
271         lua_getfield(L, table, "dt_crumbliness");
272         def.properties.dt_crumbliness = lua_tonumber(L, -1);
273         lua_pop(L, 1);
274
275         lua_getfield(L, table, "dt_cuttability");
276         def.properties.dt_cuttability = lua_tonumber(L, -1);
277         lua_pop(L, 1);
278
279         lua_getfield(L, table, "basedurability");
280         def.properties.basedurability = lua_tonumber(L, -1);
281         lua_pop(L, 1);
282
283         lua_getfield(L, table, "dd_weight");
284         def.properties.dd_weight = lua_tonumber(L, -1);
285         lua_pop(L, 1);
286
287         lua_getfield(L, table, "dd_crackiness");
288         def.properties.dd_crackiness = lua_tonumber(L, -1);
289         lua_pop(L, 1);
290
291         lua_getfield(L, table, "dd_crumbliness");
292         def.properties.dd_crumbliness = lua_tonumber(L, -1);
293         lua_pop(L, 1);
294
295         lua_getfield(L, table, "dd_cuttability");
296         def.properties.dd_cuttability = lua_tonumber(L, -1);
297         lua_pop(L, 1);
298
299         tooldef->registerTool(name, def);
300         return 0; /* number of results */
301 }
302
303 // register_node(name, {lots of stuff})
304 static int l_register_node(lua_State *L)
305 {
306         const char *name = luaL_checkstring(L, 1);
307         infostream<<"register_node: "<<name<<std::endl;
308         luaL_checktype(L, 2, LUA_TTABLE);
309         int table0 = 2;
310
311         // Get server from registry
312         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
313         Server *server = (Server*)lua_touserdata(L, -1);
314         // And get the writable node definition manager from the server
315         IWritableNodeDefManager *nodedef =
316                         server->getWritableNodeDefManager();
317         
318         ContentFeatures f;
319         f.name = name;
320
321         lua_getfield(L, table0, "tile_images");
322         if(lua_istable(L, -1)){
323                 int table = lua_gettop(L);
324                 lua_pushnil(L);
325                 int i = 0;
326                 while(lua_next(L, table) != 0){
327                         // key at index -2 and value at index -1
328                         if(lua_isstring(L, -1))
329                                 f.tname_tiles[i] = lua_tostring(L, -1);
330                         else
331                                 f.tname_tiles[i] = "";
332                         // removes value, keeps key for next iteration
333                         lua_pop(L, 1);
334                         i++;
335                         if(i==6){
336                                 lua_pop(L, 1);
337                                 break;
338                         }
339                 }
340         }
341         lua_pop(L, 1);
342
343         lua_getfield(L, table0, "inventory_image");
344         if(lua_isstring(L, -1))
345                 f.tname_inventory = lua_tostring(L, -1);
346         lua_pop(L, 1);
347
348         // TODO: Replace with actual parameter reading
349         // Temporarily set some sane parameters to allow digging
350         f.material.diggability = DIGGABLE_NORMAL;
351         f.material.weight = 0;
352         f.material.crackiness = 0;
353         f.material.crumbliness = 0;
354         f.material.cuttability = 0;
355
356         nodedef->set(name, f);
357         return 0; /* number of results */
358 }
359
360 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
361 static int l_register_craft(lua_State *L)
362 {
363         infostream<<"register_craft"<<std::endl;
364         luaL_checktype(L, 1, LUA_TTABLE);
365         int table0 = 1;
366
367         // Get server from registry
368         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
369         Server *server = (Server*)lua_touserdata(L, -1);
370         // And get the writable craft definition manager from the server
371         IWritableCraftDefManager *craftdef =
372                         server->getWritableCraftDefManager();
373         
374         std::string output;
375         int width = 0;
376         std::vector<std::string> input;
377
378         lua_getfield(L, table0, "output");
379         luaL_checktype(L, -1, LUA_TSTRING);
380         if(lua_isstring(L, -1))
381                 output = lua_tostring(L, -1);
382         lua_pop(L, 1);
383
384         lua_getfield(L, table0, "recipe");
385         luaL_checktype(L, -1, LUA_TTABLE);
386         if(lua_istable(L, -1)){
387                 int table1 = lua_gettop(L);
388                 lua_pushnil(L);
389                 int rowcount = 0;
390                 while(lua_next(L, table1) != 0){
391                         int colcount = 0;
392                         // key at index -2 and value at index -1
393                         luaL_checktype(L, -1, LUA_TTABLE);
394                         if(lua_istable(L, -1)){
395                                 int table2 = lua_gettop(L);
396                                 lua_pushnil(L);
397                                 while(lua_next(L, table2) != 0){
398                                         // key at index -2 and value at index -1
399                                         luaL_checktype(L, -1, LUA_TSTRING);
400                                         input.push_back(lua_tostring(L, -1));
401                                         // removes value, keeps key for next iteration
402                                         lua_pop(L, 1);
403                                         colcount++;
404                                 }
405                         }
406                         if(rowcount == 0){
407                                 width = colcount;
408                         } else {
409                                 if(colcount != width){
410                                         script_error(L, "error: %s\n", "Invalid crafting recipe");
411                                 }
412                         }
413                         // removes value, keeps key for next iteration
414                         lua_pop(L, 1);
415                         rowcount++;
416                 }
417         }
418         lua_pop(L, 1);
419
420         CraftDefinition def(output, width, input);
421         craftdef->registerCraft(def);
422
423         return 0; /* number of results */
424 }
425
426 // Register a global step function
427 // register_globalstep(function)
428 static int l_register_globalstep(lua_State *L)
429 {
430         luaL_checktype(L, 1, LUA_TFUNCTION);
431         infostream<<"register_globalstep"<<std::endl;
432
433         lua_getglobal(L, "table");
434         lua_getfield(L, -1, "insert");
435         int table_insert = lua_gettop(L);
436         // Get minetest.registered_globalsteps
437         lua_getglobal(L, "minetest");
438         lua_getfield(L, -1, "registered_globalsteps");
439         luaL_checktype(L, -1, LUA_TTABLE);
440         int registered_globalsteps = lua_gettop(L);
441         // table.insert(registered_globalsteps, func)
442         lua_pushvalue(L, table_insert);
443         lua_pushvalue(L, registered_globalsteps);
444         lua_pushvalue(L, 1); // push function from argument 1
445         // Call insert
446         if(lua_pcall(L, 2, 0, 0))
447                 script_error(L, "error: %s\n", lua_tostring(L, -1));
448
449         return 0; /* number of results */
450 }
451
452 // register_on_placenode(function)
453 static int l_register_on_placenode(lua_State *L)
454 {
455         luaL_checktype(L, 1, LUA_TFUNCTION);
456         infostream<<"register_on_placenode"<<std::endl;
457
458         lua_getglobal(L, "table");
459         lua_getfield(L, -1, "insert");
460         int table_insert = lua_gettop(L);
461         // Get minetest.registered_on_placenodes
462         lua_getglobal(L, "minetest");
463         lua_getfield(L, -1, "registered_on_placenodes");
464         luaL_checktype(L, -1, LUA_TTABLE);
465         int registered_on_placenodes = lua_gettop(L);
466         // table.insert(registered_on_placenodes, func)
467         lua_pushvalue(L, table_insert);
468         lua_pushvalue(L, registered_on_placenodes);
469         lua_pushvalue(L, 1); // push function from argument 1
470         // Call insert
471         if(lua_pcall(L, 2, 0, 0))
472                 script_error(L, "error: %s\n", lua_tostring(L, -1));
473
474         return 0; /* number of results */
475 }
476
477 // register_on_dignode(function)
478 static int l_register_on_dignode(lua_State *L)
479 {
480         luaL_checktype(L, 1, LUA_TFUNCTION);
481         infostream<<"register_on_dignode"<<std::endl;
482
483         lua_getglobal(L, "table");
484         lua_getfield(L, -1, "insert");
485         int table_insert = lua_gettop(L);
486         // Get minetest.registered_on_dignodes
487         lua_getglobal(L, "minetest");
488         lua_getfield(L, -1, "registered_on_dignodes");
489         luaL_checktype(L, -1, LUA_TTABLE);
490         int registered_on_dignodes = lua_gettop(L);
491         // table.insert(registered_on_dignodes, func)
492         lua_pushvalue(L, table_insert);
493         lua_pushvalue(L, registered_on_dignodes);
494         lua_pushvalue(L, 1); // push function from argument 1
495         // Call insert
496         if(lua_pcall(L, 2, 0, 0))
497                 script_error(L, "error: %s\n", lua_tostring(L, -1));
498
499         return 0; /* number of results */
500 }
501
502 static const struct luaL_Reg minetest_f [] = {
503         {"register_entity", l_register_entity},
504         {"register_tool", l_register_tool},
505         {"register_node", l_register_node},
506         {"register_craft", l_register_craft},
507         {"register_globalstep", l_register_globalstep},
508         {"register_on_placenode", l_register_on_placenode},
509         {"register_on_dignode", l_register_on_dignode},
510         {NULL, NULL}
511 };
512
513 /*
514         LuaEntity functions
515 */
516
517 static const struct luaL_Reg minetest_entity_m [] = {
518         {NULL, NULL}
519 };
520
521 /*
522         Getters for stuff in main tables
523 */
524
525 static void objectref_get(lua_State *L, u16 id)
526 {
527         // Get minetest.object_refs[i]
528         lua_getglobal(L, "minetest");
529         lua_getfield(L, -1, "object_refs");
530         luaL_checktype(L, -1, LUA_TTABLE);
531         lua_pushnumber(L, id);
532         lua_gettable(L, -2);
533         lua_remove(L, -2); // object_refs
534         lua_remove(L, -2); // minetest
535 }
536
537 static void luaentity_get(lua_State *L, u16 id)
538 {
539         // Get minetest.luaentities[i]
540         lua_getglobal(L, "minetest");
541         lua_getfield(L, -1, "luaentities");
542         luaL_checktype(L, -1, LUA_TTABLE);
543         lua_pushnumber(L, id);
544         lua_gettable(L, -2);
545         lua_remove(L, -2); // luaentities
546         lua_remove(L, -2); // minetest
547 }
548
549 /*
550         Reference objects
551 */
552 #define method(class, name) {#name, class::l_##name}
553
554 class EnvRef
555 {
556 private:
557         ServerEnvironment *m_env;
558
559         static const char className[];
560         static const luaL_reg methods[];
561
562         static EnvRef *checkobject(lua_State *L, int narg)
563         {
564                 luaL_checktype(L, narg, LUA_TUSERDATA);
565                 void *ud = luaL_checkudata(L, narg, className);
566                 if(!ud) luaL_typerror(L, narg, className);
567                 return *(EnvRef**)ud;  // unbox pointer
568         }
569         
570         // Exported functions
571
572         // EnvRef:add_node(pos, node)
573         // pos = {x=num, y=num, z=num}
574         static int l_add_node(lua_State *L)
575         {
576                 infostream<<"EnvRef::l_add_node()"<<std::endl;
577                 EnvRef *o = checkobject(L, 1);
578                 ServerEnvironment *env = o->m_env;
579                 if(env == NULL) return 0;
580                 // pos
581                 v3s16 pos = readpos(L, 2);
582                 // content
583                 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
584                 // Do it
585                 env->getMap().addNodeWithEvent(pos, n);
586                 return 0;
587         }
588
589         // EnvRef:remove_node(pos)
590         // pos = {x=num, y=num, z=num}
591         static int l_remove_node(lua_State *L)
592         {
593                 infostream<<"EnvRef::l_remove_node()"<<std::endl;
594                 EnvRef *o = checkobject(L, 1);
595                 ServerEnvironment *env = o->m_env;
596                 if(env == NULL) return 0;
597                 // pos
598                 v3s16 pos = readpos(L, 2);
599                 // Do it
600                 env->getMap().removeNodeWithEvent(pos);
601                 return 0;
602         }
603
604         // EnvRef:get_node(pos)
605         // pos = {x=num, y=num, z=num}
606         static int l_get_node(lua_State *L)
607         {
608                 infostream<<"EnvRef::l_get_node()"<<std::endl;
609                 EnvRef *o = checkobject(L, 1);
610                 ServerEnvironment *env = o->m_env;
611                 if(env == NULL) return 0;
612                 // pos
613                 v3s16 pos = readpos(L, 2);
614                 // Do it
615                 MapNode n = env->getMap().getNodeNoEx(pos);
616                 // Return node
617                 pushnode(L, n, env->getGameDef()->ndef());
618                 return 1;
619         }
620
621         // EnvRef:add_luaentity(pos, entityname)
622         // pos = {x=num, y=num, z=num}
623         static int l_add_luaentity(lua_State *L)
624         {
625                 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
626                 EnvRef *o = checkobject(L, 1);
627                 ServerEnvironment *env = o->m_env;
628                 if(env == NULL) return 0;
629                 // pos
630                 v3f pos = readFloatPos(L, 2);
631                 // content
632                 const char *name = lua_tostring(L, 3);
633                 // Do it
634                 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
635                 env->addActiveObject(obj);
636                 return 0;
637         }
638
639         static int gc_object(lua_State *L) {
640                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
641                 delete o;
642                 return 0;
643         }
644
645 public:
646         EnvRef(ServerEnvironment *env):
647                 m_env(env)
648         {
649                 infostream<<"EnvRef created"<<std::endl;
650         }
651
652         ~EnvRef()
653         {
654                 infostream<<"EnvRef destructing"<<std::endl;
655         }
656
657         // Creates an EnvRef and leaves it on top of stack
658         // Not callable from Lua; all references are created on the C side.
659         static void create(lua_State *L, ServerEnvironment *env)
660         {
661                 EnvRef *o = new EnvRef(env);
662                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
663                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
664                 luaL_getmetatable(L, className);
665                 lua_setmetatable(L, -2);
666         }
667
668         static void set_null(lua_State *L)
669         {
670                 EnvRef *o = checkobject(L, -1);
671                 o->m_env = NULL;
672         }
673         
674         static void Register(lua_State *L)
675         {
676                 lua_newtable(L);
677                 int methodtable = lua_gettop(L);
678                 luaL_newmetatable(L, className);
679                 int metatable = lua_gettop(L);
680
681                 lua_pushliteral(L, "__metatable");
682                 lua_pushvalue(L, methodtable);
683                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
684
685                 lua_pushliteral(L, "__index");
686                 lua_pushvalue(L, methodtable);
687                 lua_settable(L, metatable);
688
689                 lua_pushliteral(L, "__gc");
690                 lua_pushcfunction(L, gc_object);
691                 lua_settable(L, metatable);
692
693                 lua_pop(L, 1);  // drop metatable
694
695                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
696                 lua_pop(L, 1);  // drop methodtable
697
698                 // Cannot be created from Lua
699                 //lua_register(L, className, create_object);
700         }
701 };
702 const char EnvRef::className[] = "EnvRef";
703 const luaL_reg EnvRef::methods[] = {
704         method(EnvRef, add_node),
705         method(EnvRef, remove_node),
706         method(EnvRef, get_node),
707         method(EnvRef, add_luaentity),
708         {0,0}
709 };
710
711 class ObjectRef
712 {
713 private:
714         ServerActiveObject *m_object;
715
716         static const char className[];
717         static const luaL_reg methods[];
718
719         static ObjectRef *checkobject(lua_State *L, int narg)
720         {
721                 luaL_checktype(L, narg, LUA_TUSERDATA);
722                 void *ud = luaL_checkudata(L, narg, className);
723                 if(!ud) luaL_typerror(L, narg, className);
724                 return *(ObjectRef**)ud;  // unbox pointer
725         }
726         
727         static ServerActiveObject* getobject(ObjectRef *ref)
728         {
729                 ServerActiveObject *co = ref->m_object;
730                 return co;
731         }
732         
733         static LuaEntitySAO* getluaobject(ObjectRef *ref)
734         {
735                 ServerActiveObject *obj = getobject(ref);
736                 if(obj == NULL)
737                         return NULL;
738                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
739                         return NULL;
740                 return (LuaEntitySAO*)obj;
741         }
742         
743         // Exported functions
744         
745         // garbage collector
746         static int gc_object(lua_State *L) {
747                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
748                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
749                 delete o;
750                 return 0;
751         }
752
753         // remove(self)
754         static int l_remove(lua_State *L)
755         {
756                 ObjectRef *ref = checkobject(L, 1);
757                 ServerActiveObject *co = getobject(ref);
758                 if(co == NULL) return 0;
759                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
760                 co->m_removed = true;
761                 return 0;
762         }
763         
764         // getpos(self)
765         // returns: {x=num, y=num, z=num}
766         static int l_getpos(lua_State *L)
767         {
768                 ObjectRef *ref = checkobject(L, 1);
769                 ServerActiveObject *co = getobject(ref);
770                 if(co == NULL) return 0;
771                 v3f pos = co->getBasePosition() / BS;
772                 lua_newtable(L);
773                 lua_pushnumber(L, pos.X);
774                 lua_setfield(L, -2, "x");
775                 lua_pushnumber(L, pos.Y);
776                 lua_setfield(L, -2, "y");
777                 lua_pushnumber(L, pos.Z);
778                 lua_setfield(L, -2, "z");
779                 return 1;
780         }
781         
782         // setpos(self, pos)
783         static int l_setpos(lua_State *L)
784         {
785                 ObjectRef *ref = checkobject(L, 1);
786                 //LuaEntitySAO *co = getluaobject(ref);
787                 ServerActiveObject *co = getobject(ref);
788                 if(co == NULL) return 0;
789                 // pos
790                 v3f pos = readFloatPos(L, 2);
791                 // Do it
792                 co->setPos(pos);
793                 return 0;
794         }
795         
796         // moveto(self, pos, continuous=false)
797         static int l_moveto(lua_State *L)
798         {
799                 ObjectRef *ref = checkobject(L, 1);
800                 //LuaEntitySAO *co = getluaobject(ref);
801                 ServerActiveObject *co = getobject(ref);
802                 if(co == NULL) return 0;
803                 // pos
804                 v3f pos = readFloatPos(L, 2);
805                 // continuous
806                 bool continuous = lua_toboolean(L, 3);
807                 // Do it
808                 co->moveTo(pos, continuous);
809                 return 0;
810         }
811
812         // add_to_inventory(self, itemstring)
813         // returns: true if item was added, false otherwise
814         static int l_add_to_inventory(lua_State *L)
815         {
816                 ObjectRef *ref = checkobject(L, 1);
817                 luaL_checkstring(L, 2);
818                 ServerActiveObject *co = getobject(ref);
819                 if(co == NULL) return 0;
820                 // itemstring
821                 const char *itemstring = lua_tostring(L, 2);
822                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
823                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
824                 // Do it
825                 std::istringstream is(itemstring, std::ios::binary);
826                 ServerEnvironment *env = co->getEnv();
827                 assert(env);
828                 IGameDef *gamedef = env->getGameDef();
829                 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
830                 infostream<<"item="<<env<<std::endl;
831                 bool fits = co->addToInventory(item);
832                 // Return
833                 lua_pushboolean(L, fits);
834                 return 1;
835         }
836
837 public:
838         ObjectRef(ServerActiveObject *object):
839                 m_object(object)
840         {
841                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
842         }
843
844         ~ObjectRef()
845         {
846                 /*if(m_object)
847                         infostream<<"ObjectRef destructing for id="
848                                         <<m_object->getId()<<std::endl;
849                 else
850                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
851         }
852
853         // Creates an ObjectRef and leaves it on top of stack
854         // Not callable from Lua; all references are created on the C side.
855         static void create(lua_State *L, ServerActiveObject *object)
856         {
857                 ObjectRef *o = new ObjectRef(object);
858                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
859                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
860                 luaL_getmetatable(L, className);
861                 lua_setmetatable(L, -2);
862         }
863
864         static void set_null(lua_State *L)
865         {
866                 ObjectRef *o = checkobject(L, -1);
867                 o->m_object = NULL;
868         }
869         
870         static void Register(lua_State *L)
871         {
872                 lua_newtable(L);
873                 int methodtable = lua_gettop(L);
874                 luaL_newmetatable(L, className);
875                 int metatable = lua_gettop(L);
876
877                 lua_pushliteral(L, "__metatable");
878                 lua_pushvalue(L, methodtable);
879                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
880
881                 lua_pushliteral(L, "__index");
882                 lua_pushvalue(L, methodtable);
883                 lua_settable(L, metatable);
884
885                 lua_pushliteral(L, "__gc");
886                 lua_pushcfunction(L, gc_object);
887                 lua_settable(L, metatable);
888
889                 lua_pop(L, 1);  // drop metatable
890
891                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
892                 lua_pop(L, 1);  // drop methodtable
893
894                 // Cannot be created from Lua
895                 //lua_register(L, className, create_object);
896         }
897 };
898 const char ObjectRef::className[] = "ObjectRef";
899 const luaL_reg ObjectRef::methods[] = {
900         method(ObjectRef, remove),
901         method(ObjectRef, getpos),
902         method(ObjectRef, setpos),
903         method(ObjectRef, moveto),
904         method(ObjectRef, add_to_inventory),
905         {0,0}
906 };
907
908 // Creates a new anonymous reference if id=0
909 static void objectref_get_or_create(lua_State *L,
910                 ServerActiveObject *cobj)
911 {
912         if(cobj->getId() == 0){
913                 ObjectRef::create(L, cobj);
914         } else {
915                 objectref_get(L, cobj->getId());
916         }
917 }
918
919 /*
920         Main export function
921 */
922
923 void scriptapi_export(lua_State *L, Server *server)
924 {
925         realitycheck(L);
926         assert(lua_checkstack(L, 20));
927         infostream<<"scriptapi_export"<<std::endl;
928         StackUnroller stack_unroller(L);
929
930         // Store server as light userdata in registry
931         lua_pushlightuserdata(L, server);
932         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
933         
934         // Register global functions in table minetest
935         lua_newtable(L);
936         luaL_register(L, NULL, minetest_f);
937         lua_setglobal(L, "minetest");
938         
939         // Get the main minetest table
940         lua_getglobal(L, "minetest");
941
942         // Add tables to minetest
943         
944         /*lua_newtable(L);
945         lua_setfield(L, -2, "registered_blocks");*/
946
947         lua_newtable(L);
948         lua_setfield(L, -2, "registered_entities");
949
950         lua_newtable(L);
951         lua_setfield(L, -2, "registered_globalsteps");
952
953         lua_newtable(L);
954         lua_setfield(L, -2, "registered_on_placenodes");
955
956         lua_newtable(L);
957         lua_setfield(L, -2, "registered_on_dignodes");
958
959         lua_newtable(L);
960         lua_setfield(L, -2, "object_refs");
961
962         lua_newtable(L);
963         lua_setfield(L, -2, "luaentities");
964
965         // Create entity prototype
966         luaL_newmetatable(L, "minetest.entity");
967         // metatable.__index = metatable
968         lua_pushvalue(L, -1); // Duplicate metatable
969         lua_setfield(L, -2, "__index");
970         // Put functions in metatable
971         luaL_register(L, NULL, minetest_entity_m);
972         // Put other stuff in metatable
973
974         // Environment C reference
975         EnvRef::Register(L);
976
977         // Object C reference
978         ObjectRef::Register(L);
979 }
980
981 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
982 {
983         realitycheck(L);
984         assert(lua_checkstack(L, 20));
985         infostream<<"scriptapi_add_environment"<<std::endl;
986         StackUnroller stack_unroller(L);
987
988         // Create EnvRef on stack
989         EnvRef::create(L, env);
990         int envref = lua_gettop(L);
991
992         // minetest.env = envref
993         lua_getglobal(L, "minetest");
994         luaL_checktype(L, -1, LUA_TTABLE);
995         lua_pushvalue(L, envref);
996         lua_setfield(L, -2, "env");
997 }
998
999 #if 0
1000 // Dump stack top with the dump2 function
1001 static void dump2(lua_State *L, const char *name)
1002 {
1003         // Dump object (debug)
1004         lua_getglobal(L, "dump2");
1005         luaL_checktype(L, -1, LUA_TFUNCTION);
1006         lua_pushvalue(L, -2); // Get previous stack top as first parameter
1007         lua_pushstring(L, name);
1008         if(lua_pcall(L, 2, 0, 0))
1009                 script_error(L, "error: %s\n", lua_tostring(L, -1));
1010 }
1011 #endif
1012
1013 /*
1014         object_reference
1015 */
1016
1017 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1018 {
1019         realitycheck(L);
1020         assert(lua_checkstack(L, 20));
1021         infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1022         StackUnroller stack_unroller(L);
1023
1024         // Create object on stack
1025         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1026         int object = lua_gettop(L);
1027
1028         // Get minetest.object_refs table
1029         lua_getglobal(L, "minetest");
1030         lua_getfield(L, -1, "object_refs");
1031         luaL_checktype(L, -1, LUA_TTABLE);
1032         int objectstable = lua_gettop(L);
1033         
1034         // object_refs[id] = object
1035         lua_pushnumber(L, cobj->getId()); // Push id
1036         lua_pushvalue(L, object); // Copy object to top of stack
1037         lua_settable(L, objectstable);
1038 }
1039
1040 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1041 {
1042         realitycheck(L);
1043         assert(lua_checkstack(L, 20));
1044         infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1045         StackUnroller stack_unroller(L);
1046
1047         // Get minetest.object_refs table
1048         lua_getglobal(L, "minetest");
1049         lua_getfield(L, -1, "object_refs");
1050         luaL_checktype(L, -1, LUA_TTABLE);
1051         int objectstable = lua_gettop(L);
1052         
1053         // Get object_refs[id]
1054         lua_pushnumber(L, cobj->getId()); // Push id
1055         lua_gettable(L, objectstable);
1056         // Set object reference to NULL
1057         ObjectRef::set_null(L);
1058         lua_pop(L, 1); // pop object
1059
1060         // Set object_refs[id] = nil
1061         lua_pushnumber(L, cobj->getId()); // Push id
1062         lua_pushnil(L);
1063         lua_settable(L, objectstable);
1064 }
1065
1066 /*
1067         environment
1068 */
1069
1070 void scriptapi_environment_step(lua_State *L, float dtime)
1071 {
1072         realitycheck(L);
1073         assert(lua_checkstack(L, 20));
1074         //infostream<<"scriptapi_environment_step"<<std::endl;
1075         StackUnroller stack_unroller(L);
1076
1077         // Get minetest.registered_globalsteps
1078         lua_getglobal(L, "minetest");
1079         lua_getfield(L, -1, "registered_globalsteps");
1080         luaL_checktype(L, -1, LUA_TTABLE);
1081         int table = lua_gettop(L);
1082         // Foreach
1083         lua_pushnil(L);
1084         while(lua_next(L, table) != 0){
1085                 // key at index -2 and value at index -1
1086                 luaL_checktype(L, -1, LUA_TFUNCTION);
1087                 // Call function
1088                 lua_pushnumber(L, dtime);
1089                 if(lua_pcall(L, 1, 0, 0))
1090                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1091                 // value removed, keep key for next iteration
1092         }
1093 }
1094
1095 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode)
1096 {
1097         realitycheck(L);
1098         assert(lua_checkstack(L, 20));
1099         //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1100         StackUnroller stack_unroller(L);
1101
1102         // Get server from registry
1103         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1104         Server *server = (Server*)lua_touserdata(L, -1);
1105         // And get the writable node definition manager from the server
1106         IWritableNodeDefManager *ndef =
1107                         server->getWritableNodeDefManager();
1108         
1109         // Get minetest.registered_on_placenodes
1110         lua_getglobal(L, "minetest");
1111         lua_getfield(L, -1, "registered_on_placenodes");
1112         luaL_checktype(L, -1, LUA_TTABLE);
1113         int table = lua_gettop(L);
1114         // Foreach
1115         lua_pushnil(L);
1116         while(lua_next(L, table) != 0){
1117                 // key at index -2 and value at index -1
1118                 luaL_checktype(L, -1, LUA_TFUNCTION);
1119                 // Call function
1120                 pushpos(L, p);
1121                 pushnode(L, newnode, ndef);
1122                 if(lua_pcall(L, 2, 0, 0))
1123                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1124                 // value removed, keep key for next iteration
1125         }
1126 }
1127
1128 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode)
1129 {
1130         realitycheck(L);
1131         assert(lua_checkstack(L, 20));
1132         //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1133         StackUnroller stack_unroller(L);
1134
1135         // Get server from registry
1136         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1137         Server *server = (Server*)lua_touserdata(L, -1);
1138         // And get the writable node definition manager from the server
1139         IWritableNodeDefManager *ndef =
1140                         server->getWritableNodeDefManager();
1141         
1142         // Get minetest.registered_on_dignodes
1143         lua_getglobal(L, "minetest");
1144         lua_getfield(L, -1, "registered_on_dignodes");
1145         luaL_checktype(L, -1, LUA_TTABLE);
1146         int table = lua_gettop(L);
1147         // Foreach
1148         lua_pushnil(L);
1149         while(lua_next(L, table) != 0){
1150                 // key at index -2 and value at index -1
1151                 luaL_checktype(L, -1, LUA_TFUNCTION);
1152                 // Call function
1153                 pushpos(L, p);
1154                 pushnode(L, oldnode, ndef);
1155                 if(lua_pcall(L, 2, 0, 0))
1156                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1157                 // value removed, keep key for next iteration
1158         }
1159 }
1160
1161 /*
1162         luaentity
1163 */
1164
1165 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1166                 const char *init_state)
1167 {
1168         realitycheck(L);
1169         assert(lua_checkstack(L, 20));
1170         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1171                         <<name<<"\""<<std::endl;
1172         StackUnroller stack_unroller(L);
1173         
1174         // Create object as a dummy string (TODO: Create properly)
1175
1176         // Get minetest.registered_entities[name]
1177         lua_getglobal(L, "minetest");
1178         lua_getfield(L, -1, "registered_entities");
1179         luaL_checktype(L, -1, LUA_TTABLE);
1180         lua_pushstring(L, name);
1181         lua_gettable(L, -2);
1182         // Should be a table, which we will use as a prototype
1183         //luaL_checktype(L, -1, LUA_TTABLE);
1184         if(lua_type(L, -1) != LUA_TTABLE){
1185                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1186                 return false;
1187         }
1188         int prototype_table = lua_gettop(L);
1189         //dump2(L, "prototype_table");
1190         
1191         // Create entity object
1192         lua_newtable(L);
1193         int object = lua_gettop(L);
1194
1195         // Set object metatable
1196         lua_pushvalue(L, prototype_table);
1197         lua_setmetatable(L, -2);
1198         
1199         // Add object reference
1200         // This should be userdata with metatable ObjectRef
1201         objectref_get(L, id);
1202         luaL_checktype(L, -1, LUA_TUSERDATA);
1203         if(!luaL_checkudata(L, -1, "ObjectRef"))
1204                 luaL_typerror(L, -1, "ObjectRef");
1205         lua_setfield(L, -2, "object");
1206
1207         // minetest.luaentities[id] = object
1208         lua_getglobal(L, "minetest");
1209         lua_getfield(L, -1, "luaentities");
1210         luaL_checktype(L, -1, LUA_TTABLE);
1211         lua_pushnumber(L, id); // Push id
1212         lua_pushvalue(L, object); // Copy object to top of stack
1213         lua_settable(L, -3);
1214         
1215         // This callback doesn't really make sense
1216         /*// Get on_activate function
1217         lua_pushvalue(L, object);
1218         lua_getfield(L, -1, "on_activate");
1219         luaL_checktype(L, -1, LUA_TFUNCTION);
1220         lua_pushvalue(L, object); // self
1221         // Call with 1 arguments, 0 results
1222         if(lua_pcall(L, 1, 0, 0))
1223                 script_error(L, "error running function %s:on_activate: %s\n",
1224                                 name, lua_tostring(L, -1));*/
1225
1226         return true;
1227 }
1228
1229 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1230 {
1231         realitycheck(L);
1232         assert(lua_checkstack(L, 20));
1233         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1234
1235         // Get minetest.luaentities table
1236         lua_getglobal(L, "minetest");
1237         lua_getfield(L, -1, "luaentities");
1238         luaL_checktype(L, -1, LUA_TTABLE);
1239         int objectstable = lua_gettop(L);
1240         
1241         // Set luaentities[id] = nil
1242         lua_pushnumber(L, id); // Push id
1243         lua_pushnil(L);
1244         lua_settable(L, objectstable);
1245         
1246         lua_pop(L, 2); // pop luaentities, minetest
1247 }
1248
1249 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
1250 {
1251         realitycheck(L);
1252         assert(lua_checkstack(L, 20));
1253         infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
1254         
1255         return "";
1256 }
1257
1258 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1259                 LuaEntityProperties *prop)
1260 {
1261         realitycheck(L);
1262         assert(lua_checkstack(L, 20));
1263         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1264         StackUnroller stack_unroller(L);
1265
1266         // Get minetest.luaentities[id]
1267         luaentity_get(L, id);
1268         //int object = lua_gettop(L);
1269
1270         lua_getfield(L, -1, "physical");
1271         if(lua_isboolean(L, -1))
1272                 prop->physical = lua_toboolean(L, -1);
1273         lua_pop(L, 1);
1274         
1275         lua_getfield(L, -1, "weight");
1276         prop->weight = lua_tonumber(L, -1);
1277         lua_pop(L, 1);
1278
1279         lua_getfield(L, -1, "collisionbox");
1280         if(lua_istable(L, -1)){
1281                 lua_rawgeti(L, -1, 1);
1282                 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
1283                 lua_pop(L, 1);
1284                 lua_rawgeti(L, -1, 2);
1285                 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1286                 lua_pop(L, 1);
1287                 lua_rawgeti(L, -1, 3);
1288                 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1289                 lua_pop(L, 1);
1290                 lua_rawgeti(L, -1, 4);
1291                 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1292                 lua_pop(L, 1);
1293                 lua_rawgeti(L, -1, 5);
1294                 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1295                 lua_pop(L, 1);
1296                 lua_rawgeti(L, -1, 6);
1297                 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1298                 lua_pop(L, 1);
1299         }
1300         lua_pop(L, 1);
1301
1302         lua_getfield(L, -1, "visual");
1303         if(lua_isstring(L, -1))
1304                 prop->visual = lua_tostring(L, -1);
1305         lua_pop(L, 1);
1306         
1307         lua_getfield(L, -1, "textures");
1308         if(lua_istable(L, -1)){
1309                 prop->textures.clear();
1310                 int table = lua_gettop(L);
1311                 lua_pushnil(L);
1312                 while(lua_next(L, table) != 0){
1313                         // key at index -2 and value at index -1
1314                         if(lua_isstring(L, -1))
1315                                 prop->textures.push_back(lua_tostring(L, -1));
1316                         else
1317                                 prop->textures.push_back("");
1318                         // removes value, keeps key for next iteration
1319                         lua_pop(L, 1);
1320                 }
1321         }
1322         lua_pop(L, 1);
1323
1324 }
1325
1326 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1327 {
1328         realitycheck(L);
1329         assert(lua_checkstack(L, 20));
1330         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1331         StackUnroller stack_unroller(L);
1332
1333         // Get minetest.luaentities[id]
1334         luaentity_get(L, id);
1335         int object = lua_gettop(L);
1336         // State: object is at top of stack
1337         // Get step function
1338         lua_getfield(L, -1, "on_step");
1339         if(lua_isnil(L, -1))
1340                 return;
1341         luaL_checktype(L, -1, LUA_TFUNCTION);
1342         lua_pushvalue(L, object); // self
1343         lua_pushnumber(L, dtime); // dtime
1344         // Call with 2 arguments, 0 results
1345         if(lua_pcall(L, 2, 0, 0))
1346                 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
1347 }
1348
1349 // Calls entity:on_punch(ObjectRef puncher)
1350 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1351                 ServerActiveObject *puncher)
1352 {
1353         realitycheck(L);
1354         assert(lua_checkstack(L, 20));
1355         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1356         StackUnroller stack_unroller(L);
1357
1358         // Get minetest.luaentities[id]
1359         luaentity_get(L, id);
1360         int object = lua_gettop(L);
1361         // State: object is at top of stack
1362         // Get function
1363         lua_getfield(L, -1, "on_punch");
1364         if(lua_isnil(L, -1))
1365                 return;
1366         luaL_checktype(L, -1, LUA_TFUNCTION);
1367         lua_pushvalue(L, object); // self
1368         objectref_get_or_create(L, puncher); // Clicker reference
1369         // Call with 2 arguments, 0 results
1370         if(lua_pcall(L, 2, 0, 0))
1371                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1372 }
1373
1374 // Calls entity:on_rightclick(ObjectRef clicker)
1375 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1376                 ServerActiveObject *clicker)
1377 {
1378         realitycheck(L);
1379         assert(lua_checkstack(L, 20));
1380         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1381         StackUnroller stack_unroller(L);
1382
1383         // Get minetest.luaentities[id]
1384         luaentity_get(L, id);
1385         int object = lua_gettop(L);
1386         // State: object is at top of stack
1387         // Get function
1388         lua_getfield(L, -1, "on_rightclick");
1389         if(lua_isnil(L, -1))
1390                 return;
1391         luaL_checktype(L, -1, LUA_TFUNCTION);
1392         lua_pushvalue(L, object); // self
1393         objectref_get_or_create(L, clicker); // Clicker reference
1394         // Call with 2 arguments, 0 results
1395         if(lua_pcall(L, 2, 0, 0))
1396                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
1397 }
1398