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