Scripting WIP
[oweals/minetest.git] / src / scriptapi.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "scriptapi.h"
21
22 #include <iostream>
23 extern "C" {
24 #include <lua.h>
25 #include <lualib.h>
26 #include <lauxlib.h>
27 }
28
29 #include "log.h"
30 #include "server.h"
31 #include "porting.h"
32 #include "filesys.h"
33 #include "serverobject.h"
34 #include "script.h"
35 //#include "luna.h"
36
37 static void stackDump(lua_State *L, std::ostream &o)
38 {
39   int i;
40   int top = lua_gettop(L);
41   for (i = 1; i <= top; i++) {  /* repeat for each level */
42         int t = lua_type(L, i);
43         switch (t) {
44
45           case LUA_TSTRING:  /* strings */
46                 o<<"\""<<lua_tostring(L, i)<<"\"";
47                 break;
48
49           case LUA_TBOOLEAN:  /* booleans */
50                 o<<(lua_toboolean(L, i) ? "true" : "false");
51                 break;
52
53           case LUA_TNUMBER:  /* numbers */ {
54                 char buf[10];
55                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
56                 o<<buf;
57                 break; }
58
59           default:  /* other values */
60                 o<<lua_typename(L, t);
61                 break;
62
63         }
64         o<<" ";
65   }
66   o<<std::endl;
67 }
68
69 static void realitycheck(lua_State *L)
70 {
71         int top = lua_gettop(L);
72         if(top >= 30){
73                 dstream<<"Stack is over 30:"<<std::endl;
74                 stackDump(L, dstream);
75                 script_error(L, "Stack is over 30 (reality check)");
76         }
77 }
78
79 class StackUnroller
80 {
81 private:
82         lua_State *m_lua;
83         int m_original_top;
84 public:
85         StackUnroller(lua_State *L):
86                 m_lua(L),
87                 m_original_top(-1)
88         {
89                 m_original_top = lua_gettop(m_lua); // store stack height
90         }
91         ~StackUnroller()
92         {
93                 lua_settop(m_lua, m_original_top); // restore stack height
94         }
95 };
96
97 // Register new object prototype
98 // register_entity(name, prototype)
99 static int l_register_entity(lua_State *L)
100 {
101         const char *name = luaL_checkstring(L, 1);
102         luaL_checktype(L, 2, LUA_TTABLE);
103         infostream<<"register_entity: "<<name<<std::endl;
104
105         // Get minetest.registered_entities
106         lua_getglobal(L, "minetest");
107         lua_getfield(L, -1, "registered_entities");
108         luaL_checktype(L, -1, LUA_TTABLE);
109         int registered_entities = lua_gettop(L);
110         lua_pushvalue(L, 2); // Object = param 2 -> stack top
111         // registered_entities[name] = object
112         lua_setfield(L, registered_entities, name);
113         
114         // Get registered object to top of stack
115         lua_pushvalue(L, 2);
116         
117         // Set __index to point to itself
118         lua_pushvalue(L, -1);
119         lua_setfield(L, -2, "__index");
120
121         // Set metatable.__index = metatable
122         luaL_getmetatable(L, "minetest.entity");
123         lua_pushvalue(L, -1); // duplicate metatable
124         lua_setfield(L, -2, "__index");
125         // Set object metatable
126         lua_setmetatable(L, -2);
127
128         return 0; /* number of results */
129 }
130
131 #if 0
132 static int l_new_entity(lua_State *L)
133 {
134         /* o = o or {}
135            setmetatable(o, self)
136            self.__index = self
137            return o */
138         if(lua_isnil(L, -1))
139                 lua_newtable(L);
140         luaL_checktype(L, -1, LUA_TTABLE);
141         luaL_getmetatable(L, "minetest.entity");
142         lua_pushvalue(L, -1); // duplicate metatable
143         lua_setfield(L, -2, "__index");
144         lua_setmetatable(L, -2);
145         // return table
146         return 1;
147 }
148 #endif
149
150 static const struct luaL_Reg minetest_f [] = {
151         {"register_entity", l_register_entity},
152         //{"new_entity", l_new_entity},
153         {NULL, NULL}
154 };
155
156 static int l_entity_set_deleted(lua_State *L)
157 {
158         return 0;
159 }
160
161 static const struct luaL_Reg minetest_entity_m [] = {
162         {"set_deleted", l_entity_set_deleted},
163         {NULL, NULL}
164 };
165
166 /*
167         Reference objects
168 */
169 #define method(class, name) {#name, class::l_##name}
170
171 class EnvRef
172 {
173 private:
174         ServerEnvironment *m_env;
175
176         static const char className[];
177         static const luaL_reg methods[];
178
179         static EnvRef *checkobject(lua_State *L, int narg)
180         {
181                 luaL_checktype(L, narg, LUA_TUSERDATA);
182                 void *ud = luaL_checkudata(L, narg, className);
183                 if(!ud) luaL_typerror(L, narg, className);
184                 return *(EnvRef**)ud;  // unbox pointer
185         }
186         
187         // Exported functions
188
189         // EnvRef:add_node(pos, content)
190         // pos = {x=num, y=num, z=num}
191         // content = number
192         static int l_add_node(lua_State *L)
193         {
194                 infostream<<"EnvRef::l_add_node()"<<std::endl;
195                 EnvRef *o = checkobject(L, 1);
196                 ServerEnvironment *env = o->m_env;
197                 if(env == NULL) return 0;
198                 // pos
199                 v3s16 pos;
200                 lua_pushvalue(L, 2); // Push pos
201                 luaL_checktype(L, -1, LUA_TTABLE);
202                 lua_getfield(L, -1, "x");
203                 pos.X = lua_tonumber(L, -1);
204                 lua_pop(L, 1);
205                 lua_getfield(L, -1, "y");
206                 pos.Y = lua_tonumber(L, -1);
207                 lua_pop(L, 1);
208                 lua_getfield(L, -1, "z");
209                 pos.Z = lua_tonumber(L, -1);
210                 lua_pop(L, 1);
211                 lua_pop(L, 1); // Pop pos
212                 // content
213                 u16 content = 0;
214                 lua_pushvalue(L, 3); // Push content
215                 content = lua_tonumber(L, -1);
216                 lua_pop(L, 1); // Pop content
217                 // Do it
218                 env->getMap().addNodeWithEvent(pos, MapNode(content));
219                 return 0;
220         }
221
222         static int gc_object(lua_State *L) {
223                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
224                 delete o;
225                 return 0;
226         }
227
228 public:
229         EnvRef(ServerEnvironment *env):
230                 m_env(env)
231         {
232                 infostream<<"EnvRef created"<<std::endl;
233         }
234
235         ~EnvRef()
236         {
237                 infostream<<"EnvRef destructing"<<std::endl;
238         }
239
240         // Creates an EnvRef and leaves it on top of stack
241         // Not callable from Lua; all references are created on the C side.
242         static void create(lua_State *L, ServerEnvironment *env)
243         {
244                 EnvRef *o = new EnvRef(env);
245                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
246                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
247                 luaL_getmetatable(L, className);
248                 lua_setmetatable(L, -2);
249         }
250
251         static void set_null(lua_State *L)
252         {
253                 EnvRef *o = checkobject(L, -1);
254                 o->m_env = NULL;
255         }
256         
257         static void Register(lua_State *L)
258         {
259                 lua_newtable(L);
260                 int methodtable = lua_gettop(L);
261                 luaL_newmetatable(L, className);
262                 int metatable = lua_gettop(L);
263
264                 lua_pushliteral(L, "__metatable");
265                 lua_pushvalue(L, methodtable);
266                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
267
268                 lua_pushliteral(L, "__index");
269                 lua_pushvalue(L, methodtable);
270                 lua_settable(L, metatable);
271
272                 lua_pushliteral(L, "__gc");
273                 lua_pushcfunction(L, gc_object);
274                 lua_settable(L, metatable);
275
276                 lua_pop(L, 1);  // drop metatable
277
278                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
279                 lua_pop(L, 1);  // drop methodtable
280
281                 // Cannot be created from Lua
282                 //lua_register(L, className, create_object);
283         }
284 };
285 const char EnvRef::className[] = "EnvRef";
286 const luaL_reg EnvRef::methods[] = {
287         method(EnvRef, add_node),
288         {0,0}
289 };
290
291 class ObjectRef
292 {
293 private:
294         ServerActiveObject *m_object;
295
296         static const char className[];
297         static const luaL_reg methods[];
298
299         static ObjectRef *checkobject(lua_State *L, int narg)
300         {
301                 luaL_checktype(L, narg, LUA_TUSERDATA);
302                 void *ud = luaL_checkudata(L, narg, className);
303                 if(!ud) luaL_typerror(L, narg, className);
304                 return *(ObjectRef**)ud;  // unbox pointer
305         }
306         
307         // Exported functions
308
309         static int l_remove(lua_State *L)
310         {
311                 ObjectRef *o = checkobject(L, 1);
312                 ServerActiveObject *co = o->m_object;
313                 if(co == NULL) return 0;
314                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
315                 co->m_removed = true;
316                 return 0;
317         }
318
319         static int l_getpos(lua_State *L)
320         {
321                 ObjectRef *o = checkobject(L, 1);
322                 ServerActiveObject *co = o->m_object;
323                 if(co == NULL) return 0;
324                 infostream<<"ObjectRef::l_getpos(): id="<<co->getId()<<std::endl;
325                 v3f pos = co->getBasePosition() / BS;
326                 lua_newtable(L);
327                 lua_pushnumber(L, pos.X);
328                 lua_setfield(L, -2, "x");
329                 lua_pushnumber(L, pos.Y);
330                 lua_setfield(L, -2, "y");
331                 lua_pushnumber(L, pos.Z);
332                 lua_setfield(L, -2, "z");
333                 return 1;
334         }
335
336         static int gc_object(lua_State *L) {
337                 //ObjectRef *o = checkobject(L, 1);
338                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
339                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
340                 delete o;
341                 return 0;
342         }
343
344 public:
345         ObjectRef(ServerActiveObject *object):
346                 m_object(object)
347         {
348                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
349         }
350
351         ~ObjectRef()
352         {
353                 /*if(m_object)
354                         infostream<<"ObjectRef destructing for id="
355                                         <<m_object->getId()<<std::endl;
356                 else
357                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
358         }
359
360         // Creates an ObjectRef and leaves it on top of stack
361         // Not callable from Lua; all references are created on the C side.
362         static void create(lua_State *L, ServerActiveObject *object)
363         {
364                 ObjectRef *o = new ObjectRef(object);
365                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
366                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
367                 luaL_getmetatable(L, className);
368                 lua_setmetatable(L, -2);
369         }
370
371         static void set_null(lua_State *L)
372         {
373                 ObjectRef *o = checkobject(L, -1);
374                 o->m_object = NULL;
375         }
376         
377         static void Register(lua_State *L)
378         {
379                 lua_newtable(L);
380                 int methodtable = lua_gettop(L);
381                 luaL_newmetatable(L, className);
382                 int metatable = lua_gettop(L);
383
384                 lua_pushliteral(L, "__metatable");
385                 lua_pushvalue(L, methodtable);
386                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
387
388                 lua_pushliteral(L, "__index");
389                 lua_pushvalue(L, methodtable);
390                 lua_settable(L, metatable);
391
392                 lua_pushliteral(L, "__gc");
393                 lua_pushcfunction(L, gc_object);
394                 lua_settable(L, metatable);
395
396                 lua_pop(L, 1);  // drop metatable
397
398                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
399                 lua_pop(L, 1);  // drop methodtable
400
401                 // Cannot be created from Lua
402                 //lua_register(L, className, create_object);
403         }
404 };
405 const char ObjectRef::className[] = "ObjectRef";
406 const luaL_reg ObjectRef::methods[] = {
407         method(ObjectRef, remove),
408         method(ObjectRef, getpos),
409         {0,0}
410 };
411
412 /*
413         Main export function
414 */
415
416 void scriptapi_export(lua_State *L, Server *server)
417 {
418         realitycheck(L);
419         assert(lua_checkstack(L, 20));
420         infostream<<"scriptapi_export"<<std::endl;
421         
422         // Register global functions in table minetest
423         lua_newtable(L);
424         luaL_register(L, NULL, minetest_f);
425         lua_setglobal(L, "minetest");
426         
427         // Get the main minetest table
428         lua_getglobal(L, "minetest");
429
430         // Add registered_entities table in minetest
431         lua_newtable(L);
432         lua_setfield(L, -2, "registered_entities");
433
434         // Add object_refs table in minetest
435         lua_newtable(L);
436         lua_setfield(L, -2, "object_refs");
437
438         // Add luaentities table in minetest
439         lua_newtable(L);
440         lua_setfield(L, -2, "luaentities");
441
442         // Load and run some base Lua stuff
443         /*script_load(L, (porting::path_data + DIR_DELIM + "scripts"
444                         + DIR_DELIM + "base.lua").c_str());*/
445         
446         // Create entity reference metatable
447         //luaL_newmetatable(L, "minetest.entity_reference");
448         //lua_pop(L, 1);
449         
450         // Create entity prototype
451         luaL_newmetatable(L, "minetest.entity");
452         // metatable.__index = metatable
453         lua_pushvalue(L, -1); // Duplicate metatable
454         lua_setfield(L, -2, "__index");
455         // Put functions in metatable
456         luaL_register(L, NULL, minetest_entity_m);
457         // Put other stuff in metatable
458
459         // Environment C reference
460         EnvRef::Register(L);
461
462         // Object C reference
463         ObjectRef::Register(L);
464 }
465
466 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
467 {
468         realitycheck(L);
469         assert(lua_checkstack(L, 20));
470         infostream<<"scriptapi_add_environment"<<std::endl;
471
472         // Create EnvRef on stack
473         EnvRef::create(L, env);
474         int envref = lua_gettop(L);
475
476         // minetest.env = envref
477         lua_getglobal(L, "minetest");
478         luaL_checktype(L, -1, LUA_TTABLE);
479         lua_pushvalue(L, envref);
480         lua_setfield(L, -2, "env");
481         
482         // pop minetest and envref
483         lua_pop(L, 2);
484 }
485
486 // Dump stack top with the dump2 function
487 static void dump2(lua_State *L, const char *name)
488 {
489         // Dump object (debug)
490         lua_getglobal(L, "dump2");
491         luaL_checktype(L, -1, LUA_TFUNCTION);
492         lua_pushvalue(L, -2); // Get previous stack top as first parameter
493         lua_pushstring(L, name);
494         if(lua_pcall(L, 2, 0, 0))
495                 script_error(L, "error: %s\n", lua_tostring(L, -1));
496 }
497
498 /*
499         object_reference
500 */
501
502 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
503 {
504         realitycheck(L);
505         assert(lua_checkstack(L, 20));
506         infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
507
508         // Create object on stack
509         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
510         int object = lua_gettop(L);
511
512         // Get minetest.object_refs table
513         lua_getglobal(L, "minetest");
514         lua_getfield(L, -1, "object_refs");
515         luaL_checktype(L, -1, LUA_TTABLE);
516         int objectstable = lua_gettop(L);
517         
518         // object_refs[id] = object
519         lua_pushnumber(L, cobj->getId()); // Push id
520         lua_pushvalue(L, object); // Copy object to top of stack
521         lua_settable(L, objectstable);
522         
523         // pop object_refs, minetest and the object
524         lua_pop(L, 3);
525 }
526
527 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
528 {
529         realitycheck(L);
530         assert(lua_checkstack(L, 20));
531         infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
532
533         // Get minetest.object_refs table
534         lua_getglobal(L, "minetest");
535         lua_getfield(L, -1, "object_refs");
536         luaL_checktype(L, -1, LUA_TTABLE);
537         int objectstable = lua_gettop(L);
538         
539         // Get object_refs[id]
540         lua_pushnumber(L, cobj->getId()); // Push id
541         lua_gettable(L, objectstable);
542         // Set object reference to NULL
543         ObjectRef::set_null(L);
544         lua_pop(L, 1); // pop object
545
546         // Set object_refs[id] = nil
547         lua_pushnumber(L, cobj->getId()); // Push id
548         lua_pushnil(L);
549         lua_settable(L, objectstable);
550         
551         // pop object_refs, minetest
552         lua_pop(L, 2);
553 }
554
555 static void objectref_get(lua_State *L, u16 id)
556 {
557         // Get minetest.object_refs[i]
558         lua_getglobal(L, "minetest");
559         lua_getfield(L, -1, "object_refs");
560         luaL_checktype(L, -1, LUA_TTABLE);
561         lua_pushnumber(L, id);
562         lua_gettable(L, -2);
563         lua_remove(L, -2); // object_refs
564         lua_remove(L, -2); // minetest
565 }
566
567 /*
568         luaentity
569 */
570
571 void scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
572                 const char *init_state)
573 {
574         realitycheck(L);
575         assert(lua_checkstack(L, 20));
576         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
577                         <<name<<"\""<<std::endl;
578         StackUnroller stack_unroller(L);
579         
580         // Create object as a dummy string (TODO: Create properly)
581
582         // Get minetest.registered_entities[name]
583         lua_getglobal(L, "minetest");
584         lua_getfield(L, -1, "registered_entities");
585         luaL_checktype(L, -1, LUA_TTABLE);
586         lua_pushstring(L, name);
587         lua_gettable(L, -2);
588         // Should be a table, which we will use as a prototype
589         luaL_checktype(L, -1, LUA_TTABLE);
590         int prototype_table = lua_gettop(L);
591         //dump2(L, "prototype_table");
592         
593         // Create entity object
594         lua_newtable(L);
595         int object = lua_gettop(L);
596
597         // Set object metatable
598         lua_pushvalue(L, prototype_table);
599         lua_setmetatable(L, -2);
600         
601         // Add object reference
602         // This should be userdata with metatable ObjectRef
603         objectref_get(L, id);
604         luaL_checktype(L, -1, LUA_TUSERDATA);
605         if(!luaL_checkudata(L, -1, "ObjectRef"))
606                 luaL_typerror(L, -1, "ObjectRef");
607         lua_setfield(L, -2, "object");
608
609         // minetest.luaentities[id] = object
610         lua_getglobal(L, "minetest");
611         lua_getfield(L, -1, "luaentities");
612         luaL_checktype(L, -1, LUA_TTABLE);
613         lua_pushnumber(L, id); // Push id
614         lua_pushvalue(L, object); // Copy object to top of stack
615         lua_settable(L, -3);
616         
617         // This callback doesn't really make sense
618         /*// Get on_activate function
619         lua_pushvalue(L, object);
620         lua_getfield(L, -1, "on_activate");
621         luaL_checktype(L, -1, LUA_TFUNCTION);
622         lua_pushvalue(L, object); // self
623         // Call with 1 arguments, 0 results
624         if(lua_pcall(L, 1, 0, 0))
625                 script_error(L, "error running function %s:on_activate: %s\n",
626                                 name, lua_tostring(L, -1));*/
627 }
628
629 void scriptapi_luaentity_rm(lua_State *L, u16 id)
630 {
631         realitycheck(L);
632         assert(lua_checkstack(L, 20));
633         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
634
635         // Get minetest.luaentities table
636         lua_getglobal(L, "minetest");
637         lua_getfield(L, -1, "luaentities");
638         luaL_checktype(L, -1, LUA_TTABLE);
639         int objectstable = lua_gettop(L);
640         
641         // Set luaentities[id] = nil
642         lua_pushnumber(L, id); // Push id
643         lua_pushnil(L);
644         lua_settable(L, objectstable);
645         
646         lua_pop(L, 2); // pop luaentities, minetest
647 }
648
649 static void luaentity_get(lua_State *L, u16 id)
650 {
651         // Get minetest.luaentities[i]
652         lua_getglobal(L, "minetest");
653         lua_getfield(L, -1, "luaentities");
654         luaL_checktype(L, -1, LUA_TTABLE);
655         lua_pushnumber(L, id);
656         lua_gettable(L, -2);
657         lua_remove(L, -2); // luaentities
658         lua_remove(L, -2); // minetest
659 }
660
661 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
662 {
663         realitycheck(L);
664         assert(lua_checkstack(L, 20));
665         infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
666         
667         return "";
668 }
669
670 LuaEntityProperties scriptapi_luaentity_get_properties(lua_State *L, u16 id)
671 {
672         realitycheck(L);
673         assert(lua_checkstack(L, 20));
674         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
675         StackUnroller stack_unroller(L);
676
677         LuaEntityProperties prop;
678
679         // Get minetest.luaentities[id]
680         luaentity_get(L, id);
681         //int object = lua_gettop(L);
682
683         lua_getfield(L, -1, "physical");
684         if(lua_isboolean(L, -1))
685                 prop.physical = lua_toboolean(L, -1);
686         lua_pop(L, 1);
687         
688         lua_getfield(L, -1, "weight");
689         prop.weight = lua_tonumber(L, -1);
690         lua_pop(L, 1);
691
692         lua_getfield(L, -1, "boundingbox");
693         if(lua_istable(L, -1)){
694                 lua_rawgeti(L, -1, 1);
695                 prop.boundingbox.MinEdge.X = lua_tonumber(L, -1);
696                 lua_pop(L, 1);
697                 lua_rawgeti(L, -1, 2);
698                 prop.boundingbox.MinEdge.Y = lua_tonumber(L, -1);
699                 lua_pop(L, 1);
700                 lua_rawgeti(L, -1, 3);
701                 prop.boundingbox.MinEdge.Z = lua_tonumber(L, -1);
702                 lua_pop(L, 1);
703                 lua_rawgeti(L, -1, 4);
704                 prop.boundingbox.MaxEdge.X = lua_tonumber(L, -1);
705                 lua_pop(L, 1);
706                 lua_rawgeti(L, -1, 5);
707                 prop.boundingbox.MaxEdge.Y = lua_tonumber(L, -1);
708                 lua_pop(L, 1);
709                 lua_rawgeti(L, -1, 6);
710                 prop.boundingbox.MaxEdge.Z = lua_tonumber(L, -1);
711                 lua_pop(L, 1);
712         }
713         lua_pop(L, 1);
714
715         lua_getfield(L, -1, "visual");
716         if(lua_isstring(L, -1))
717                 prop.visual = lua_tostring(L, -1);
718         lua_pop(L, 1);
719         
720         lua_getfield(L, -1, "textures");
721         if(lua_istable(L, -1)){
722                 prop.textures.clear();
723                 int table = lua_gettop(L);
724                 lua_pushnil(L);
725                 while(lua_next(L, table) != 0){
726                         // key at index -2 and value at index -1
727                         if(lua_isstring(L, -1))
728                                 prop.textures.push_back(lua_tostring(L, -1));
729                         else
730                                 prop.textures.push_back("");
731                         // removes value, keeps key for next iteration
732                         lua_pop(L, 1);
733                 }
734         }
735         lua_pop(L, 1);
736
737         return prop;
738 }
739
740 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
741 {
742         realitycheck(L);
743         assert(lua_checkstack(L, 20));
744         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
745         StackUnroller stack_unroller(L);
746
747         // Get minetest.luaentities[id]
748         luaentity_get(L, id);
749         int object = lua_gettop(L);
750         // State: object is at top of stack
751         // Get step function
752         lua_getfield(L, -1, "on_step");
753         luaL_checktype(L, -1, LUA_TFUNCTION);
754         lua_pushvalue(L, object); // self
755         lua_pushnumber(L, dtime); // dtime
756         // Call with 2 arguments, 0 results
757         if(lua_pcall(L, 2, 0, 0))
758                 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
759 }
760
761 void scriptapi_luaentity_rightclick_player(lua_State *L, u16 id,
762                 const char *playername)
763 {
764         realitycheck(L);
765         assert(lua_checkstack(L, 20));
766         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
767         StackUnroller stack_unroller(L);
768
769         // Get minetest.luaentities[id]
770         luaentity_get(L, id);
771         int object = lua_gettop(L);
772         // State: object is at top of stack
773         // Get step function
774         lua_getfield(L, -1, "on_rightclick");
775         luaL_checktype(L, -1, LUA_TFUNCTION);
776         lua_pushvalue(L, object); // self
777         // Call with 1 arguments, 0 results
778         if(lua_pcall(L, 1, 0, 0))
779                 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
780 }
781