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