]> git.lizzy.rs Git - dragonfireclient.git/blob - src/scriptapi.cpp
a18c144d3b8837e6cfc802ab2c9db4898725cc73
[dragonfireclient.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         f.dug_item = std::string("NodeItem \"")+name+"\" 1";
356
357         nodedef->set(name, f);
358         return 0; /* number of results */
359 }
360
361 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
362 static int l_register_craft(lua_State *L)
363 {
364         infostream<<"register_craft"<<std::endl;
365         luaL_checktype(L, 1, LUA_TTABLE);
366         int table0 = 1;
367
368         // Get server from registry
369         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
370         Server *server = (Server*)lua_touserdata(L, -1);
371         // And get the writable craft definition manager from the server
372         IWritableCraftDefManager *craftdef =
373                         server->getWritableCraftDefManager();
374         
375         std::string output;
376         int width = 0;
377         std::vector<std::string> input;
378
379         lua_getfield(L, table0, "output");
380         luaL_checktype(L, -1, LUA_TSTRING);
381         if(lua_isstring(L, -1))
382                 output = lua_tostring(L, -1);
383         lua_pop(L, 1);
384
385         lua_getfield(L, table0, "recipe");
386         luaL_checktype(L, -1, LUA_TTABLE);
387         if(lua_istable(L, -1)){
388                 int table1 = lua_gettop(L);
389                 lua_pushnil(L);
390                 int rowcount = 0;
391                 while(lua_next(L, table1) != 0){
392                         int colcount = 0;
393                         // key at index -2 and value at index -1
394                         luaL_checktype(L, -1, LUA_TTABLE);
395                         if(lua_istable(L, -1)){
396                                 int table2 = lua_gettop(L);
397                                 lua_pushnil(L);
398                                 while(lua_next(L, table2) != 0){
399                                         // key at index -2 and value at index -1
400                                         luaL_checktype(L, -1, LUA_TSTRING);
401                                         input.push_back(lua_tostring(L, -1));
402                                         // removes value, keeps key for next iteration
403                                         lua_pop(L, 1);
404                                         colcount++;
405                                 }
406                         }
407                         if(rowcount == 0){
408                                 width = colcount;
409                         } else {
410                                 if(colcount != width){
411                                         script_error(L, "error: %s\n", "Invalid crafting recipe");
412                                 }
413                         }
414                         // removes value, keeps key for next iteration
415                         lua_pop(L, 1);
416                         rowcount++;
417                 }
418         }
419         lua_pop(L, 1);
420
421         CraftDefinition def(output, width, input);
422         craftdef->registerCraft(def);
423
424         return 0; /* number of results */
425 }
426
427 // Register a global step function
428 // register_globalstep(function)
429 static int l_register_globalstep(lua_State *L)
430 {
431         luaL_checktype(L, 1, LUA_TFUNCTION);
432         infostream<<"register_globalstep"<<std::endl;
433
434         lua_getglobal(L, "table");
435         lua_getfield(L, -1, "insert");
436         int table_insert = lua_gettop(L);
437         // Get minetest.registered_globalsteps
438         lua_getglobal(L, "minetest");
439         lua_getfield(L, -1, "registered_globalsteps");
440         luaL_checktype(L, -1, LUA_TTABLE);
441         int registered_globalsteps = lua_gettop(L);
442         // table.insert(registered_globalsteps, func)
443         lua_pushvalue(L, table_insert);
444         lua_pushvalue(L, registered_globalsteps);
445         lua_pushvalue(L, 1); // push function from argument 1
446         // Call insert
447         if(lua_pcall(L, 2, 0, 0))
448                 script_error(L, "error: %s\n", lua_tostring(L, -1));
449
450         return 0; /* number of results */
451 }
452
453 // register_on_placenode(function)
454 static int l_register_on_placenode(lua_State *L)
455 {
456         luaL_checktype(L, 1, LUA_TFUNCTION);
457         infostream<<"register_on_placenode"<<std::endl;
458
459         lua_getglobal(L, "table");
460         lua_getfield(L, -1, "insert");
461         int table_insert = lua_gettop(L);
462         // Get minetest.registered_on_placenodes
463         lua_getglobal(L, "minetest");
464         lua_getfield(L, -1, "registered_on_placenodes");
465         luaL_checktype(L, -1, LUA_TTABLE);
466         int registered_on_placenodes = lua_gettop(L);
467         // table.insert(registered_on_placenodes, func)
468         lua_pushvalue(L, table_insert);
469         lua_pushvalue(L, registered_on_placenodes);
470         lua_pushvalue(L, 1); // push function from argument 1
471         // Call insert
472         if(lua_pcall(L, 2, 0, 0))
473                 script_error(L, "error: %s\n", lua_tostring(L, -1));
474
475         return 0; /* number of results */
476 }
477
478 // register_on_dignode(function)
479 static int l_register_on_dignode(lua_State *L)
480 {
481         luaL_checktype(L, 1, LUA_TFUNCTION);
482         infostream<<"register_on_dignode"<<std::endl;
483
484         lua_getglobal(L, "table");
485         lua_getfield(L, -1, "insert");
486         int table_insert = lua_gettop(L);
487         // Get minetest.registered_on_dignodes
488         lua_getglobal(L, "minetest");
489         lua_getfield(L, -1, "registered_on_dignodes");
490         luaL_checktype(L, -1, LUA_TTABLE);
491         int registered_on_dignodes = lua_gettop(L);
492         // table.insert(registered_on_dignodes, func)
493         lua_pushvalue(L, table_insert);
494         lua_pushvalue(L, registered_on_dignodes);
495         lua_pushvalue(L, 1); // push function from argument 1
496         // Call insert
497         if(lua_pcall(L, 2, 0, 0))
498                 script_error(L, "error: %s\n", lua_tostring(L, -1));
499
500         return 0; /* number of results */
501 }
502
503 static const struct luaL_Reg minetest_f [] = {
504         {"register_entity", l_register_entity},
505         {"register_tool", l_register_tool},
506         {"register_node", l_register_node},
507         {"register_craft", l_register_craft},
508         {"register_globalstep", l_register_globalstep},
509         {"register_on_placenode", l_register_on_placenode},
510         {"register_on_dignode", l_register_on_dignode},
511         {NULL, NULL}
512 };
513
514 /*
515         LuaEntity functions
516 */
517
518 static const struct luaL_Reg minetest_entity_m [] = {
519         {NULL, NULL}
520 };
521
522 /*
523         Getters for stuff in main tables
524 */
525
526 static void objectref_get(lua_State *L, u16 id)
527 {
528         // Get minetest.object_refs[i]
529         lua_getglobal(L, "minetest");
530         lua_getfield(L, -1, "object_refs");
531         luaL_checktype(L, -1, LUA_TTABLE);
532         lua_pushnumber(L, id);
533         lua_gettable(L, -2);
534         lua_remove(L, -2); // object_refs
535         lua_remove(L, -2); // minetest
536 }
537
538 static void luaentity_get(lua_State *L, u16 id)
539 {
540         // Get minetest.luaentities[i]
541         lua_getglobal(L, "minetest");
542         lua_getfield(L, -1, "luaentities");
543         luaL_checktype(L, -1, LUA_TTABLE);
544         lua_pushnumber(L, id);
545         lua_gettable(L, -2);
546         lua_remove(L, -2); // luaentities
547         lua_remove(L, -2); // minetest
548 }
549
550 /*
551         Reference objects
552 */
553 #define method(class, name) {#name, class::l_##name}
554
555 class EnvRef
556 {
557 private:
558         ServerEnvironment *m_env;
559
560         static const char className[];
561         static const luaL_reg methods[];
562
563         static EnvRef *checkobject(lua_State *L, int narg)
564         {
565                 luaL_checktype(L, narg, LUA_TUSERDATA);
566                 void *ud = luaL_checkudata(L, narg, className);
567                 if(!ud) luaL_typerror(L, narg, className);
568                 return *(EnvRef**)ud;  // unbox pointer
569         }
570         
571         // Exported functions
572
573         // EnvRef:add_node(pos, node)
574         // pos = {x=num, y=num, z=num}
575         static int l_add_node(lua_State *L)
576         {
577                 infostream<<"EnvRef::l_add_node()"<<std::endl;
578                 EnvRef *o = checkobject(L, 1);
579                 ServerEnvironment *env = o->m_env;
580                 if(env == NULL) return 0;
581                 // pos
582                 v3s16 pos = readpos(L, 2);
583                 // content
584                 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
585                 // Do it
586                 env->getMap().addNodeWithEvent(pos, n);
587                 return 0;
588         }
589
590         // EnvRef:remove_node(pos)
591         // pos = {x=num, y=num, z=num}
592         static int l_remove_node(lua_State *L)
593         {
594                 infostream<<"EnvRef::l_remove_node()"<<std::endl;
595                 EnvRef *o = checkobject(L, 1);
596                 ServerEnvironment *env = o->m_env;
597                 if(env == NULL) return 0;
598                 // pos
599                 v3s16 pos = readpos(L, 2);
600                 // Do it
601                 env->getMap().removeNodeWithEvent(pos);
602                 return 0;
603         }
604
605         // EnvRef:get_node(pos)
606         // pos = {x=num, y=num, z=num}
607         static int l_get_node(lua_State *L)
608         {
609                 infostream<<"EnvRef::l_get_node()"<<std::endl;
610                 EnvRef *o = checkobject(L, 1);
611                 ServerEnvironment *env = o->m_env;
612                 if(env == NULL) return 0;
613                 // pos
614                 v3s16 pos = readpos(L, 2);
615                 // Do it
616                 MapNode n = env->getMap().getNodeNoEx(pos);
617                 // Return node
618                 pushnode(L, n, env->getGameDef()->ndef());
619                 return 1;
620         }
621
622         // EnvRef:add_luaentity(pos, entityname)
623         // pos = {x=num, y=num, z=num}
624         static int l_add_luaentity(lua_State *L)
625         {
626                 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
627                 EnvRef *o = checkobject(L, 1);
628                 ServerEnvironment *env = o->m_env;
629                 if(env == NULL) return 0;
630                 // pos
631                 v3f pos = readFloatPos(L, 2);
632                 // content
633                 const char *name = lua_tostring(L, 3);
634                 // Do it
635                 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
636                 env->addActiveObject(obj);
637                 return 0;
638         }
639
640         static int gc_object(lua_State *L) {
641                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
642                 delete o;
643                 return 0;
644         }
645
646 public:
647         EnvRef(ServerEnvironment *env):
648                 m_env(env)
649         {
650                 infostream<<"EnvRef created"<<std::endl;
651         }
652
653         ~EnvRef()
654         {
655                 infostream<<"EnvRef destructing"<<std::endl;
656         }
657
658         // Creates an EnvRef and leaves it on top of stack
659         // Not callable from Lua; all references are created on the C side.
660         static void create(lua_State *L, ServerEnvironment *env)
661         {
662                 EnvRef *o = new EnvRef(env);
663                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
664                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
665                 luaL_getmetatable(L, className);
666                 lua_setmetatable(L, -2);
667         }
668
669         static void set_null(lua_State *L)
670         {
671                 EnvRef *o = checkobject(L, -1);
672                 o->m_env = NULL;
673         }
674         
675         static void Register(lua_State *L)
676         {
677                 lua_newtable(L);
678                 int methodtable = lua_gettop(L);
679                 luaL_newmetatable(L, className);
680                 int metatable = lua_gettop(L);
681
682                 lua_pushliteral(L, "__metatable");
683                 lua_pushvalue(L, methodtable);
684                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
685
686                 lua_pushliteral(L, "__index");
687                 lua_pushvalue(L, methodtable);
688                 lua_settable(L, metatable);
689
690                 lua_pushliteral(L, "__gc");
691                 lua_pushcfunction(L, gc_object);
692                 lua_settable(L, metatable);
693
694                 lua_pop(L, 1);  // drop metatable
695
696                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
697                 lua_pop(L, 1);  // drop methodtable
698
699                 // Cannot be created from Lua
700                 //lua_register(L, className, create_object);
701         }
702 };
703 const char EnvRef::className[] = "EnvRef";
704 const luaL_reg EnvRef::methods[] = {
705         method(EnvRef, add_node),
706         method(EnvRef, remove_node),
707         method(EnvRef, get_node),
708         method(EnvRef, add_luaentity),
709         {0,0}
710 };
711
712 class ObjectRef
713 {
714 private:
715         ServerActiveObject *m_object;
716
717         static const char className[];
718         static const luaL_reg methods[];
719
720         static ObjectRef *checkobject(lua_State *L, int narg)
721         {
722                 luaL_checktype(L, narg, LUA_TUSERDATA);
723                 void *ud = luaL_checkudata(L, narg, className);
724                 if(!ud) luaL_typerror(L, narg, className);
725                 return *(ObjectRef**)ud;  // unbox pointer
726         }
727         
728         static ServerActiveObject* getobject(ObjectRef *ref)
729         {
730                 ServerActiveObject *co = ref->m_object;
731                 return co;
732         }
733         
734         static LuaEntitySAO* getluaobject(ObjectRef *ref)
735         {
736                 ServerActiveObject *obj = getobject(ref);
737                 if(obj == NULL)
738                         return NULL;
739                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
740                         return NULL;
741                 return (LuaEntitySAO*)obj;
742         }
743         
744         // Exported functions
745         
746         // garbage collector
747         static int gc_object(lua_State *L) {
748                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
749                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
750                 delete o;
751                 return 0;
752         }
753
754         // remove(self)
755         static int l_remove(lua_State *L)
756         {
757                 ObjectRef *ref = checkobject(L, 1);
758                 ServerActiveObject *co = getobject(ref);
759                 if(co == NULL) return 0;
760                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
761                 co->m_removed = true;
762                 return 0;
763         }
764         
765         // getpos(self)
766         // returns: {x=num, y=num, z=num}
767         static int l_getpos(lua_State *L)
768         {
769                 ObjectRef *ref = checkobject(L, 1);
770                 ServerActiveObject *co = getobject(ref);
771                 if(co == NULL) return 0;
772                 v3f pos = co->getBasePosition() / BS;
773                 lua_newtable(L);
774                 lua_pushnumber(L, pos.X);
775                 lua_setfield(L, -2, "x");
776                 lua_pushnumber(L, pos.Y);
777                 lua_setfield(L, -2, "y");
778                 lua_pushnumber(L, pos.Z);
779                 lua_setfield(L, -2, "z");
780                 return 1;
781         }
782         
783         // setpos(self, pos)
784         static int l_setpos(lua_State *L)
785         {
786                 ObjectRef *ref = checkobject(L, 1);
787                 //LuaEntitySAO *co = getluaobject(ref);
788                 ServerActiveObject *co = getobject(ref);
789                 if(co == NULL) return 0;
790                 // pos
791                 v3f pos = readFloatPos(L, 2);
792                 // Do it
793                 co->setPos(pos);
794                 return 0;
795         }
796         
797         // moveto(self, pos, continuous=false)
798         static int l_moveto(lua_State *L)
799         {
800                 ObjectRef *ref = checkobject(L, 1);
801                 //LuaEntitySAO *co = getluaobject(ref);
802                 ServerActiveObject *co = getobject(ref);
803                 if(co == NULL) return 0;
804                 // pos
805                 v3f pos = readFloatPos(L, 2);
806                 // continuous
807                 bool continuous = lua_toboolean(L, 3);
808                 // Do it
809                 co->moveTo(pos, continuous);
810                 return 0;
811         }
812
813         // add_to_inventory(self, itemstring)
814         // returns: true if item was added, false otherwise
815         static int l_add_to_inventory(lua_State *L)
816         {
817                 ObjectRef *ref = checkobject(L, 1);
818                 luaL_checkstring(L, 2);
819                 ServerActiveObject *co = getobject(ref);
820                 if(co == NULL) return 0;
821                 // itemstring
822                 const char *itemstring = lua_tostring(L, 2);
823                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
824                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
825                 // Do it
826                 std::istringstream is(itemstring, std::ios::binary);
827                 ServerEnvironment *env = co->getEnv();
828                 assert(env);
829                 IGameDef *gamedef = env->getGameDef();
830                 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
831                 infostream<<"item="<<env<<std::endl;
832                 bool fits = co->addToInventory(item);
833                 // Return
834                 lua_pushboolean(L, fits);
835                 return 1;
836         }
837
838 public:
839         ObjectRef(ServerActiveObject *object):
840                 m_object(object)
841         {
842                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
843         }
844
845         ~ObjectRef()
846         {
847                 /*if(m_object)
848                         infostream<<"ObjectRef destructing for id="
849                                         <<m_object->getId()<<std::endl;
850                 else
851                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
852         }
853
854         // Creates an ObjectRef and leaves it on top of stack
855         // Not callable from Lua; all references are created on the C side.
856         static void create(lua_State *L, ServerActiveObject *object)
857         {
858                 ObjectRef *o = new ObjectRef(object);
859                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
860                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
861                 luaL_getmetatable(L, className);
862                 lua_setmetatable(L, -2);
863         }
864
865         static void set_null(lua_State *L)
866         {
867                 ObjectRef *o = checkobject(L, -1);
868                 o->m_object = NULL;
869         }
870         
871         static void Register(lua_State *L)
872         {
873                 lua_newtable(L);
874                 int methodtable = lua_gettop(L);
875                 luaL_newmetatable(L, className);
876                 int metatable = lua_gettop(L);
877
878                 lua_pushliteral(L, "__metatable");
879                 lua_pushvalue(L, methodtable);
880                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
881
882                 lua_pushliteral(L, "__index");
883                 lua_pushvalue(L, methodtable);
884                 lua_settable(L, metatable);
885
886                 lua_pushliteral(L, "__gc");
887                 lua_pushcfunction(L, gc_object);
888                 lua_settable(L, metatable);
889
890                 lua_pop(L, 1);  // drop metatable
891
892                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
893                 lua_pop(L, 1);  // drop methodtable
894
895                 // Cannot be created from Lua
896                 //lua_register(L, className, create_object);
897         }
898 };
899 const char ObjectRef::className[] = "ObjectRef";
900 const luaL_reg ObjectRef::methods[] = {
901         method(ObjectRef, remove),
902         method(ObjectRef, getpos),
903         method(ObjectRef, setpos),
904         method(ObjectRef, moveto),
905         method(ObjectRef, add_to_inventory),
906         {0,0}
907 };
908
909 // Creates a new anonymous reference if id=0
910 static void objectref_get_or_create(lua_State *L,
911                 ServerActiveObject *cobj)
912 {
913         if(cobj->getId() == 0){
914                 ObjectRef::create(L, cobj);
915         } else {
916                 objectref_get(L, cobj->getId());
917         }
918 }
919
920 /*
921         Main export function
922 */
923
924 void scriptapi_export(lua_State *L, Server *server)
925 {
926         realitycheck(L);
927         assert(lua_checkstack(L, 20));
928         infostream<<"scriptapi_export"<<std::endl;
929         StackUnroller stack_unroller(L);
930
931         // Store server as light userdata in registry
932         lua_pushlightuserdata(L, server);
933         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
934         
935         // Register global functions in table minetest
936         lua_newtable(L);
937         luaL_register(L, NULL, minetest_f);
938         lua_setglobal(L, "minetest");
939         
940         // Get the main minetest table
941         lua_getglobal(L, "minetest");
942
943         // Add tables to minetest
944         
945         /*lua_newtable(L);
946         lua_setfield(L, -2, "registered_blocks");*/
947
948         lua_newtable(L);
949         lua_setfield(L, -2, "registered_entities");
950
951         lua_newtable(L);
952         lua_setfield(L, -2, "registered_globalsteps");
953
954         lua_newtable(L);
955         lua_setfield(L, -2, "registered_on_placenodes");
956
957         lua_newtable(L);
958         lua_setfield(L, -2, "registered_on_dignodes");
959
960         lua_newtable(L);
961         lua_setfield(L, -2, "object_refs");
962
963         lua_newtable(L);
964         lua_setfield(L, -2, "luaentities");
965
966         // Create entity prototype
967         luaL_newmetatable(L, "minetest.entity");
968         // metatable.__index = metatable
969         lua_pushvalue(L, -1); // Duplicate metatable
970         lua_setfield(L, -2, "__index");
971         // Put functions in metatable
972         luaL_register(L, NULL, minetest_entity_m);
973         // Put other stuff in metatable
974
975         // Environment C reference
976         EnvRef::Register(L);
977
978         // Object C reference
979         ObjectRef::Register(L);
980 }
981
982 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
983 {
984         realitycheck(L);
985         assert(lua_checkstack(L, 20));
986         infostream<<"scriptapi_add_environment"<<std::endl;
987         StackUnroller stack_unroller(L);
988
989         // Create EnvRef on stack
990         EnvRef::create(L, env);
991         int envref = lua_gettop(L);
992
993         // minetest.env = envref
994         lua_getglobal(L, "minetest");
995         luaL_checktype(L, -1, LUA_TTABLE);
996         lua_pushvalue(L, envref);
997         lua_setfield(L, -2, "env");
998 }
999
1000 #if 0
1001 // Dump stack top with the dump2 function
1002 static void dump2(lua_State *L, const char *name)
1003 {
1004         // Dump object (debug)
1005         lua_getglobal(L, "dump2");
1006         luaL_checktype(L, -1, LUA_TFUNCTION);
1007         lua_pushvalue(L, -2); // Get previous stack top as first parameter
1008         lua_pushstring(L, name);
1009         if(lua_pcall(L, 2, 0, 0))
1010                 script_error(L, "error: %s\n", lua_tostring(L, -1));
1011 }
1012 #endif
1013
1014 /*
1015         object_reference
1016 */
1017
1018 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1019 {
1020         realitycheck(L);
1021         assert(lua_checkstack(L, 20));
1022         infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1023         StackUnroller stack_unroller(L);
1024
1025         // Create object on stack
1026         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1027         int object = lua_gettop(L);
1028
1029         // Get minetest.object_refs table
1030         lua_getglobal(L, "minetest");
1031         lua_getfield(L, -1, "object_refs");
1032         luaL_checktype(L, -1, LUA_TTABLE);
1033         int objectstable = lua_gettop(L);
1034         
1035         // object_refs[id] = object
1036         lua_pushnumber(L, cobj->getId()); // Push id
1037         lua_pushvalue(L, object); // Copy object to top of stack
1038         lua_settable(L, objectstable);
1039 }
1040
1041 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1042 {
1043         realitycheck(L);
1044         assert(lua_checkstack(L, 20));
1045         infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1046         StackUnroller stack_unroller(L);
1047
1048         // Get minetest.object_refs table
1049         lua_getglobal(L, "minetest");
1050         lua_getfield(L, -1, "object_refs");
1051         luaL_checktype(L, -1, LUA_TTABLE);
1052         int objectstable = lua_gettop(L);
1053         
1054         // Get object_refs[id]
1055         lua_pushnumber(L, cobj->getId()); // Push id
1056         lua_gettable(L, objectstable);
1057         // Set object reference to NULL
1058         ObjectRef::set_null(L);
1059         lua_pop(L, 1); // pop object
1060
1061         // Set object_refs[id] = nil
1062         lua_pushnumber(L, cobj->getId()); // Push id
1063         lua_pushnil(L);
1064         lua_settable(L, objectstable);
1065 }
1066
1067 /*
1068         environment
1069 */
1070
1071 void scriptapi_environment_step(lua_State *L, float dtime)
1072 {
1073         realitycheck(L);
1074         assert(lua_checkstack(L, 20));
1075         //infostream<<"scriptapi_environment_step"<<std::endl;
1076         StackUnroller stack_unroller(L);
1077
1078         // Get minetest.registered_globalsteps
1079         lua_getglobal(L, "minetest");
1080         lua_getfield(L, -1, "registered_globalsteps");
1081         luaL_checktype(L, -1, LUA_TTABLE);
1082         int table = lua_gettop(L);
1083         // Foreach
1084         lua_pushnil(L);
1085         while(lua_next(L, table) != 0){
1086                 // key at index -2 and value at index -1
1087                 luaL_checktype(L, -1, LUA_TFUNCTION);
1088                 // Call function
1089                 lua_pushnumber(L, dtime);
1090                 if(lua_pcall(L, 1, 0, 0))
1091                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1092                 // value removed, keep key for next iteration
1093         }
1094 }
1095
1096 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode)
1097 {
1098         realitycheck(L);
1099         assert(lua_checkstack(L, 20));
1100         //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1101         StackUnroller stack_unroller(L);
1102
1103         // Get server from registry
1104         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1105         Server *server = (Server*)lua_touserdata(L, -1);
1106         // And get the writable node definition manager from the server
1107         IWritableNodeDefManager *ndef =
1108                         server->getWritableNodeDefManager();
1109         
1110         // Get minetest.registered_on_placenodes
1111         lua_getglobal(L, "minetest");
1112         lua_getfield(L, -1, "registered_on_placenodes");
1113         luaL_checktype(L, -1, LUA_TTABLE);
1114         int table = lua_gettop(L);
1115         // Foreach
1116         lua_pushnil(L);
1117         while(lua_next(L, table) != 0){
1118                 // key at index -2 and value at index -1
1119                 luaL_checktype(L, -1, LUA_TFUNCTION);
1120                 // Call function
1121                 pushpos(L, p);
1122                 pushnode(L, newnode, ndef);
1123                 if(lua_pcall(L, 2, 0, 0))
1124                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1125                 // value removed, keep key for next iteration
1126         }
1127 }
1128
1129 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode)
1130 {
1131         realitycheck(L);
1132         assert(lua_checkstack(L, 20));
1133         //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1134         StackUnroller stack_unroller(L);
1135
1136         // Get server from registry
1137         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1138         Server *server = (Server*)lua_touserdata(L, -1);
1139         // And get the writable node definition manager from the server
1140         IWritableNodeDefManager *ndef =
1141                         server->getWritableNodeDefManager();
1142         
1143         // Get minetest.registered_on_dignodes
1144         lua_getglobal(L, "minetest");
1145         lua_getfield(L, -1, "registered_on_dignodes");
1146         luaL_checktype(L, -1, LUA_TTABLE);
1147         int table = lua_gettop(L);
1148         // Foreach
1149         lua_pushnil(L);
1150         while(lua_next(L, table) != 0){
1151                 // key at index -2 and value at index -1
1152                 luaL_checktype(L, -1, LUA_TFUNCTION);
1153                 // Call function
1154                 pushpos(L, p);
1155                 pushnode(L, oldnode, ndef);
1156                 if(lua_pcall(L, 2, 0, 0))
1157                         script_error(L, "error: %s\n", lua_tostring(L, -1));
1158                 // value removed, keep key for next iteration
1159         }
1160 }
1161
1162 /*
1163         luaentity
1164 */
1165
1166 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1167                 const char *init_state)
1168 {
1169         realitycheck(L);
1170         assert(lua_checkstack(L, 20));
1171         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1172                         <<name<<"\""<<std::endl;
1173         StackUnroller stack_unroller(L);
1174         
1175         // Create object as a dummy string (TODO: Create properly)
1176
1177         // Get minetest.registered_entities[name]
1178         lua_getglobal(L, "minetest");
1179         lua_getfield(L, -1, "registered_entities");
1180         luaL_checktype(L, -1, LUA_TTABLE);
1181         lua_pushstring(L, name);
1182         lua_gettable(L, -2);
1183         // Should be a table, which we will use as a prototype
1184         //luaL_checktype(L, -1, LUA_TTABLE);
1185         if(lua_type(L, -1) != LUA_TTABLE){
1186                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1187                 return false;
1188         }
1189         int prototype_table = lua_gettop(L);
1190         //dump2(L, "prototype_table");
1191         
1192         // Create entity object
1193         lua_newtable(L);
1194         int object = lua_gettop(L);
1195
1196         // Set object metatable
1197         lua_pushvalue(L, prototype_table);
1198         lua_setmetatable(L, -2);
1199         
1200         // Add object reference
1201         // This should be userdata with metatable ObjectRef
1202         objectref_get(L, id);
1203         luaL_checktype(L, -1, LUA_TUSERDATA);
1204         if(!luaL_checkudata(L, -1, "ObjectRef"))
1205                 luaL_typerror(L, -1, "ObjectRef");
1206         lua_setfield(L, -2, "object");
1207
1208         // minetest.luaentities[id] = object
1209         lua_getglobal(L, "minetest");
1210         lua_getfield(L, -1, "luaentities");
1211         luaL_checktype(L, -1, LUA_TTABLE);
1212         lua_pushnumber(L, id); // Push id
1213         lua_pushvalue(L, object); // Copy object to top of stack
1214         lua_settable(L, -3);
1215         
1216         // This callback doesn't really make sense
1217         /*// Get on_activate function
1218         lua_pushvalue(L, object);
1219         lua_getfield(L, -1, "on_activate");
1220         luaL_checktype(L, -1, LUA_TFUNCTION);
1221         lua_pushvalue(L, object); // self
1222         // Call with 1 arguments, 0 results
1223         if(lua_pcall(L, 1, 0, 0))
1224                 script_error(L, "error running function %s:on_activate: %s\n",
1225                                 name, lua_tostring(L, -1));*/
1226
1227         return true;
1228 }
1229
1230 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1231 {
1232         realitycheck(L);
1233         assert(lua_checkstack(L, 20));
1234         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1235
1236         // Get minetest.luaentities table
1237         lua_getglobal(L, "minetest");
1238         lua_getfield(L, -1, "luaentities");
1239         luaL_checktype(L, -1, LUA_TTABLE);
1240         int objectstable = lua_gettop(L);
1241         
1242         // Set luaentities[id] = nil
1243         lua_pushnumber(L, id); // Push id
1244         lua_pushnil(L);
1245         lua_settable(L, objectstable);
1246         
1247         lua_pop(L, 2); // pop luaentities, minetest
1248 }
1249
1250 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
1251 {
1252         realitycheck(L);
1253         assert(lua_checkstack(L, 20));
1254         infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
1255         
1256         return "";
1257 }
1258
1259 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1260                 LuaEntityProperties *prop)
1261 {
1262         realitycheck(L);
1263         assert(lua_checkstack(L, 20));
1264         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1265         StackUnroller stack_unroller(L);
1266
1267         // Get minetest.luaentities[id]
1268         luaentity_get(L, id);
1269         //int object = lua_gettop(L);
1270
1271         lua_getfield(L, -1, "physical");
1272         if(lua_isboolean(L, -1))
1273                 prop->physical = lua_toboolean(L, -1);
1274         lua_pop(L, 1);
1275         
1276         lua_getfield(L, -1, "weight");
1277         prop->weight = lua_tonumber(L, -1);
1278         lua_pop(L, 1);
1279
1280         lua_getfield(L, -1, "collisionbox");
1281         if(lua_istable(L, -1)){
1282                 lua_rawgeti(L, -1, 1);
1283                 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
1284                 lua_pop(L, 1);
1285                 lua_rawgeti(L, -1, 2);
1286                 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1287                 lua_pop(L, 1);
1288                 lua_rawgeti(L, -1, 3);
1289                 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1290                 lua_pop(L, 1);
1291                 lua_rawgeti(L, -1, 4);
1292                 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1293                 lua_pop(L, 1);
1294                 lua_rawgeti(L, -1, 5);
1295                 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1296                 lua_pop(L, 1);
1297                 lua_rawgeti(L, -1, 6);
1298                 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1299                 lua_pop(L, 1);
1300         }
1301         lua_pop(L, 1);
1302
1303         lua_getfield(L, -1, "visual");
1304         if(lua_isstring(L, -1))
1305                 prop->visual = lua_tostring(L, -1);
1306         lua_pop(L, 1);
1307         
1308         lua_getfield(L, -1, "textures");
1309         if(lua_istable(L, -1)){
1310                 prop->textures.clear();
1311                 int table = lua_gettop(L);
1312                 lua_pushnil(L);
1313                 while(lua_next(L, table) != 0){
1314                         // key at index -2 and value at index -1
1315                         if(lua_isstring(L, -1))
1316                                 prop->textures.push_back(lua_tostring(L, -1));
1317                         else
1318                                 prop->textures.push_back("");
1319                         // removes value, keeps key for next iteration
1320                         lua_pop(L, 1);
1321                 }
1322         }
1323         lua_pop(L, 1);
1324
1325 }
1326
1327 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1328 {
1329         realitycheck(L);
1330         assert(lua_checkstack(L, 20));
1331         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1332         StackUnroller stack_unroller(L);
1333
1334         // Get minetest.luaentities[id]
1335         luaentity_get(L, id);
1336         int object = lua_gettop(L);
1337         // State: object is at top of stack
1338         // Get step function
1339         lua_getfield(L, -1, "on_step");
1340         if(lua_isnil(L, -1))
1341                 return;
1342         luaL_checktype(L, -1, LUA_TFUNCTION);
1343         lua_pushvalue(L, object); // self
1344         lua_pushnumber(L, dtime); // dtime
1345         // Call with 2 arguments, 0 results
1346         if(lua_pcall(L, 2, 0, 0))
1347                 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
1348 }
1349
1350 // Calls entity:on_punch(ObjectRef puncher)
1351 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1352                 ServerActiveObject *puncher)
1353 {
1354         realitycheck(L);
1355         assert(lua_checkstack(L, 20));
1356         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1357         StackUnroller stack_unroller(L);
1358
1359         // Get minetest.luaentities[id]
1360         luaentity_get(L, id);
1361         int object = lua_gettop(L);
1362         // State: object is at top of stack
1363         // Get function
1364         lua_getfield(L, -1, "on_punch");
1365         if(lua_isnil(L, -1))
1366                 return;
1367         luaL_checktype(L, -1, LUA_TFUNCTION);
1368         lua_pushvalue(L, object); // self
1369         objectref_get_or_create(L, puncher); // Clicker reference
1370         // Call with 2 arguments, 0 results
1371         if(lua_pcall(L, 2, 0, 0))
1372                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1373 }
1374
1375 // Calls entity:on_rightclick(ObjectRef clicker)
1376 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1377                 ServerActiveObject *clicker)
1378 {
1379         realitycheck(L);
1380         assert(lua_checkstack(L, 20));
1381         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1382         StackUnroller stack_unroller(L);
1383
1384         // Get minetest.luaentities[id]
1385         luaentity_get(L, id);
1386         int object = lua_gettop(L);
1387         // State: object is at top of stack
1388         // Get function
1389         lua_getfield(L, -1, "on_rightclick");
1390         if(lua_isnil(L, -1))
1391                 return;
1392         luaL_checktype(L, -1, LUA_TFUNCTION);
1393         lua_pushvalue(L, object); // self
1394         objectref_get_or_create(L, clicker); // Clicker reference
1395         // Call with 2 arguments, 0 results
1396         if(lua_pcall(L, 2, 0, 0))
1397                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
1398 }
1399