Generic NodeMetadata text input
[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 - Node type definition
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 per MapBlock
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 // Register a global step function
174 // register_globalstep(function)
175 static int l_register_globalstep(lua_State *L)
176 {
177         luaL_checktype(L, 1, LUA_TFUNCTION);
178         infostream<<"register_globalstep"<<std::endl;
179
180         lua_getglobal(L, "table");
181         lua_getfield(L, -1, "insert");
182         int table_insert = lua_gettop(L);
183         // Get minetest.registered_globalsteps
184         lua_getglobal(L, "minetest");
185         lua_getfield(L, -1, "registered_globalsteps");
186         luaL_checktype(L, -1, LUA_TTABLE);
187         int registered_globalsteps = lua_gettop(L);
188         // table.insert(registered_globalsteps, func)
189         lua_pushvalue(L, table_insert);
190         lua_pushvalue(L, registered_globalsteps);
191         lua_pushvalue(L, 1); // push function from argument 1
192         // Call insert
193         if(lua_pcall(L, 2, 0, 0))
194                 script_error(L, "error: %s\n", lua_tostring(L, -1));
195
196         return 0; /* number of results */
197 }
198
199 static const struct luaL_Reg minetest_f [] = {
200         {"register_entity", l_register_entity},
201         {"register_globalstep", l_register_globalstep},
202         {NULL, NULL}
203 };
204
205 /*
206         LuaEntity functions
207 */
208
209 static const struct luaL_Reg minetest_entity_m [] = {
210         {NULL, NULL}
211 };
212
213 /*
214         Getters for stuff in main tables
215 */
216
217 static void objectref_get(lua_State *L, u16 id)
218 {
219         // Get minetest.object_refs[i]
220         lua_getglobal(L, "minetest");
221         lua_getfield(L, -1, "object_refs");
222         luaL_checktype(L, -1, LUA_TTABLE);
223         lua_pushnumber(L, id);
224         lua_gettable(L, -2);
225         lua_remove(L, -2); // object_refs
226         lua_remove(L, -2); // minetest
227 }
228
229 static void luaentity_get(lua_State *L, u16 id)
230 {
231         // Get minetest.luaentities[i]
232         lua_getglobal(L, "minetest");
233         lua_getfield(L, -1, "luaentities");
234         luaL_checktype(L, -1, LUA_TTABLE);
235         lua_pushnumber(L, id);
236         lua_gettable(L, -2);
237         lua_remove(L, -2); // luaentities
238         lua_remove(L, -2); // minetest
239 }
240
241 /*
242         Reference objects
243 */
244 #define method(class, name) {#name, class::l_##name}
245
246 class EnvRef
247 {
248 private:
249         ServerEnvironment *m_env;
250
251         static const char className[];
252         static const luaL_reg methods[];
253
254         static EnvRef *checkobject(lua_State *L, int narg)
255         {
256                 luaL_checktype(L, narg, LUA_TUSERDATA);
257                 void *ud = luaL_checkudata(L, narg, className);
258                 if(!ud) luaL_typerror(L, narg, className);
259                 return *(EnvRef**)ud;  // unbox pointer
260         }
261         
262         // Exported functions
263
264         // EnvRef:add_node(pos, content)
265         // pos = {x=num, y=num, z=num}
266         // content = number
267         static int l_add_node(lua_State *L)
268         {
269                 infostream<<"EnvRef::l_add_node()"<<std::endl;
270                 EnvRef *o = checkobject(L, 1);
271                 ServerEnvironment *env = o->m_env;
272                 if(env == NULL) return 0;
273                 // pos
274                 v3s16 pos;
275                 lua_pushvalue(L, 2); // Push pos
276                 luaL_checktype(L, -1, LUA_TTABLE);
277                 lua_getfield(L, -1, "x");
278                 pos.X = lua_tonumber(L, -1);
279                 lua_pop(L, 1);
280                 lua_getfield(L, -1, "y");
281                 pos.Y = lua_tonumber(L, -1);
282                 lua_pop(L, 1);
283                 lua_getfield(L, -1, "z");
284                 pos.Z = lua_tonumber(L, -1);
285                 lua_pop(L, 1);
286                 lua_pop(L, 1); // Pop pos
287                 // content
288                 u16 content = 0;
289                 lua_pushvalue(L, 3); // Push content
290                 content = lua_tonumber(L, -1);
291                 lua_pop(L, 1); // Pop content
292                 // Do it
293                 env->getMap().addNodeWithEvent(pos, MapNode(content));
294                 return 0;
295         }
296
297         static int gc_object(lua_State *L) {
298                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
299                 delete o;
300                 return 0;
301         }
302
303 public:
304         EnvRef(ServerEnvironment *env):
305                 m_env(env)
306         {
307                 infostream<<"EnvRef created"<<std::endl;
308         }
309
310         ~EnvRef()
311         {
312                 infostream<<"EnvRef destructing"<<std::endl;
313         }
314
315         // Creates an EnvRef and leaves it on top of stack
316         // Not callable from Lua; all references are created on the C side.
317         static void create(lua_State *L, ServerEnvironment *env)
318         {
319                 EnvRef *o = new EnvRef(env);
320                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
321                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
322                 luaL_getmetatable(L, className);
323                 lua_setmetatable(L, -2);
324         }
325
326         static void set_null(lua_State *L)
327         {
328                 EnvRef *o = checkobject(L, -1);
329                 o->m_env = NULL;
330         }
331         
332         static void Register(lua_State *L)
333         {
334                 lua_newtable(L);
335                 int methodtable = lua_gettop(L);
336                 luaL_newmetatable(L, className);
337                 int metatable = lua_gettop(L);
338
339                 lua_pushliteral(L, "__metatable");
340                 lua_pushvalue(L, methodtable);
341                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
342
343                 lua_pushliteral(L, "__index");
344                 lua_pushvalue(L, methodtable);
345                 lua_settable(L, metatable);
346
347                 lua_pushliteral(L, "__gc");
348                 lua_pushcfunction(L, gc_object);
349                 lua_settable(L, metatable);
350
351                 lua_pop(L, 1);  // drop metatable
352
353                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
354                 lua_pop(L, 1);  // drop methodtable
355
356                 // Cannot be created from Lua
357                 //lua_register(L, className, create_object);
358         }
359 };
360 const char EnvRef::className[] = "EnvRef";
361 const luaL_reg EnvRef::methods[] = {
362         method(EnvRef, add_node),
363         {0,0}
364 };
365
366 class ObjectRef
367 {
368 private:
369         ServerActiveObject *m_object;
370
371         static const char className[];
372         static const luaL_reg methods[];
373
374         static ObjectRef *checkobject(lua_State *L, int narg)
375         {
376                 luaL_checktype(L, narg, LUA_TUSERDATA);
377                 void *ud = luaL_checkudata(L, narg, className);
378                 if(!ud) luaL_typerror(L, narg, className);
379                 return *(ObjectRef**)ud;  // unbox pointer
380         }
381         
382         static ServerActiveObject* getobject(ObjectRef *ref)
383         {
384                 ServerActiveObject *co = ref->m_object;
385                 return co;
386         }
387         
388         static LuaEntitySAO* getluaobject(ObjectRef *ref)
389         {
390                 ServerActiveObject *obj = getobject(ref);
391                 if(obj == NULL)
392                         return NULL;
393                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
394                         return NULL;
395                 return (LuaEntitySAO*)obj;
396         }
397         
398         // Exported functions
399         
400         // garbage collector
401         static int gc_object(lua_State *L) {
402                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
403                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
404                 delete o;
405                 return 0;
406         }
407
408         // remove(self)
409         static int l_remove(lua_State *L)
410         {
411                 ObjectRef *ref = checkobject(L, 1);
412                 ServerActiveObject *co = getobject(ref);
413                 if(co == NULL) return 0;
414                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
415                 co->m_removed = true;
416                 return 0;
417         }
418         
419         // getpos(self)
420         // returns: {x=num, y=num, z=num}
421         static int l_getpos(lua_State *L)
422         {
423                 ObjectRef *ref = checkobject(L, 1);
424                 ServerActiveObject *co = getobject(ref);
425                 if(co == NULL) return 0;
426                 v3f pos = co->getBasePosition() / BS;
427                 lua_newtable(L);
428                 lua_pushnumber(L, pos.X);
429                 lua_setfield(L, -2, "x");
430                 lua_pushnumber(L, pos.Y);
431                 lua_setfield(L, -2, "y");
432                 lua_pushnumber(L, pos.Z);
433                 lua_setfield(L, -2, "z");
434                 return 1;
435         }
436         
437         // setpos(self, pos)
438         static int l_setpos(lua_State *L)
439         {
440                 ObjectRef *ref = checkobject(L, 1);
441                 //LuaEntitySAO *co = getluaobject(ref);
442                 ServerActiveObject *co = getobject(ref);
443                 if(co == NULL) return 0;
444                 // pos
445                 v3f pos = readFloatPos(L, 2);
446                 // Do it
447                 co->setPos(pos);
448                 return 0;
449         }
450         
451         // moveto(self, pos, continuous=false)
452         static int l_moveto(lua_State *L)
453         {
454                 ObjectRef *ref = checkobject(L, 1);
455                 //LuaEntitySAO *co = getluaobject(ref);
456                 ServerActiveObject *co = getobject(ref);
457                 if(co == NULL) return 0;
458                 // pos
459                 v3f pos = readFloatPos(L, 2);
460                 // continuous
461                 bool continuous = lua_toboolean(L, 3);
462                 // Do it
463                 co->moveTo(pos, continuous);
464                 return 0;
465         }
466
467         // add_to_inventory(self, itemstring)
468         // returns: true if item was added, false otherwise
469         static int l_add_to_inventory(lua_State *L)
470         {
471                 ObjectRef *ref = checkobject(L, 1);
472                 luaL_checkstring(L, 2);
473                 ServerActiveObject *co = getobject(ref);
474                 if(co == NULL) return 0;
475                 // itemstring
476                 const char *itemstring = lua_tostring(L, 2);
477                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
478                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
479                 // Do it
480                 std::istringstream is(itemstring, std::ios::binary);
481                 InventoryItem *item = InventoryItem::deSerialize(is);
482                 bool fits = co->addToInventory(item);
483                 // Return
484                 lua_pushboolean(L, fits);
485                 return 1;
486         }
487
488 public:
489         ObjectRef(ServerActiveObject *object):
490                 m_object(object)
491         {
492                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
493         }
494
495         ~ObjectRef()
496         {
497                 /*if(m_object)
498                         infostream<<"ObjectRef destructing for id="
499                                         <<m_object->getId()<<std::endl;
500                 else
501                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
502         }
503
504         // Creates an ObjectRef and leaves it on top of stack
505         // Not callable from Lua; all references are created on the C side.
506         static void create(lua_State *L, ServerActiveObject *object)
507         {
508                 ObjectRef *o = new ObjectRef(object);
509                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
510                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
511                 luaL_getmetatable(L, className);
512                 lua_setmetatable(L, -2);
513         }
514
515         static void set_null(lua_State *L)
516         {
517                 ObjectRef *o = checkobject(L, -1);
518                 o->m_object = NULL;
519         }
520         
521         static void Register(lua_State *L)
522         {
523                 lua_newtable(L);
524                 int methodtable = lua_gettop(L);
525                 luaL_newmetatable(L, className);
526                 int metatable = lua_gettop(L);
527
528                 lua_pushliteral(L, "__metatable");
529                 lua_pushvalue(L, methodtable);
530                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
531
532                 lua_pushliteral(L, "__index");
533                 lua_pushvalue(L, methodtable);
534                 lua_settable(L, metatable);
535
536                 lua_pushliteral(L, "__gc");
537                 lua_pushcfunction(L, gc_object);
538                 lua_settable(L, metatable);
539
540                 lua_pop(L, 1);  // drop metatable
541
542                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
543                 lua_pop(L, 1);  // drop methodtable
544
545                 // Cannot be created from Lua
546                 //lua_register(L, className, create_object);
547         }
548 };
549 const char ObjectRef::className[] = "ObjectRef";
550 const luaL_reg ObjectRef::methods[] = {
551         method(ObjectRef, remove),
552         method(ObjectRef, getpos),
553         method(ObjectRef, setpos),
554         method(ObjectRef, moveto),
555         method(ObjectRef, add_to_inventory),
556         {0,0}
557 };
558
559 // Creates a new anonymous reference if id=0
560 static void objectref_get_or_create(lua_State *L, ServerActiveObject *cobj)
561 {
562         if(cobj->getId() == 0){
563                 ObjectRef::create(L, cobj);
564         } else {
565                 objectref_get(L, cobj->getId());
566         }
567 }
568
569 /*
570         Main export function
571 */
572
573 void scriptapi_export(lua_State *L, Server *server)
574 {
575         realitycheck(L);
576         assert(lua_checkstack(L, 20));
577         infostream<<"scriptapi_export"<<std::endl;
578         StackUnroller stack_unroller(L);
579         
580         // Register global functions in table minetest
581         lua_newtable(L);
582         luaL_register(L, NULL, minetest_f);
583         lua_setglobal(L, "minetest");
584         
585         // Get the main minetest table
586         lua_getglobal(L, "minetest");
587
588         // Add tables to minetest
589         
590         /*lua_newtable(L);
591         lua_setfield(L, -2, "registered_blocks");*/
592
593         lua_newtable(L);
594         lua_setfield(L, -2, "registered_entities");
595
596         lua_newtable(L);
597         lua_setfield(L, -2, "registered_globalsteps");
598
599         lua_newtable(L);
600         lua_setfield(L, -2, "object_refs");
601
602         lua_newtable(L);
603         lua_setfield(L, -2, "luaentities");
604
605         // Create entity prototype
606         luaL_newmetatable(L, "minetest.entity");
607         // metatable.__index = metatable
608         lua_pushvalue(L, -1); // Duplicate metatable
609         lua_setfield(L, -2, "__index");
610         // Put functions in metatable
611         luaL_register(L, NULL, minetest_entity_m);
612         // Put other stuff in metatable
613
614         // Environment C reference
615         EnvRef::Register(L);
616
617         // Object C reference
618         ObjectRef::Register(L);
619 }
620
621 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
622 {
623         realitycheck(L);
624         assert(lua_checkstack(L, 20));
625         infostream<<"scriptapi_add_environment"<<std::endl;
626         StackUnroller stack_unroller(L);
627
628         // Create EnvRef on stack
629         EnvRef::create(L, env);
630         int envref = lua_gettop(L);
631
632         // minetest.env = envref
633         lua_getglobal(L, "minetest");
634         luaL_checktype(L, -1, LUA_TTABLE);
635         lua_pushvalue(L, envref);
636         lua_setfield(L, -2, "env");
637 }
638
639 #if 0
640 // Dump stack top with the dump2 function
641 static void dump2(lua_State *L, const char *name)
642 {
643         // Dump object (debug)
644         lua_getglobal(L, "dump2");
645         luaL_checktype(L, -1, LUA_TFUNCTION);
646         lua_pushvalue(L, -2); // Get previous stack top as first parameter
647         lua_pushstring(L, name);
648         if(lua_pcall(L, 2, 0, 0))
649                 script_error(L, "error: %s\n", lua_tostring(L, -1));
650 }
651 #endif
652
653 /*
654         object_reference
655 */
656
657 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
658 {
659         realitycheck(L);
660         assert(lua_checkstack(L, 20));
661         infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
662         StackUnroller stack_unroller(L);
663
664         // Create object on stack
665         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
666         int object = lua_gettop(L);
667
668         // Get minetest.object_refs table
669         lua_getglobal(L, "minetest");
670         lua_getfield(L, -1, "object_refs");
671         luaL_checktype(L, -1, LUA_TTABLE);
672         int objectstable = lua_gettop(L);
673         
674         // object_refs[id] = object
675         lua_pushnumber(L, cobj->getId()); // Push id
676         lua_pushvalue(L, object); // Copy object to top of stack
677         lua_settable(L, objectstable);
678 }
679
680 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
681 {
682         realitycheck(L);
683         assert(lua_checkstack(L, 20));
684         infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
685         StackUnroller stack_unroller(L);
686
687         // Get minetest.object_refs table
688         lua_getglobal(L, "minetest");
689         lua_getfield(L, -1, "object_refs");
690         luaL_checktype(L, -1, LUA_TTABLE);
691         int objectstable = lua_gettop(L);
692         
693         // Get object_refs[id]
694         lua_pushnumber(L, cobj->getId()); // Push id
695         lua_gettable(L, objectstable);
696         // Set object reference to NULL
697         ObjectRef::set_null(L);
698         lua_pop(L, 1); // pop object
699
700         // Set object_refs[id] = nil
701         lua_pushnumber(L, cobj->getId()); // Push id
702         lua_pushnil(L);
703         lua_settable(L, objectstable);
704 }
705
706 /*
707         environment
708 */
709
710 void scriptapi_environment_step(lua_State *L, float dtime)
711 {
712         realitycheck(L);
713         assert(lua_checkstack(L, 20));
714         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
715         StackUnroller stack_unroller(L);
716
717         // Get minetest.registered_globalsteps
718         lua_getglobal(L, "minetest");
719         lua_getfield(L, -1, "registered_globalsteps");
720         luaL_checktype(L, -1, LUA_TTABLE);
721         int table = lua_gettop(L);
722         // Foreach
723         lua_pushnil(L);
724         while(lua_next(L, table) != 0){
725                 // key at index -2 and value at index -1
726                 luaL_checktype(L, -1, LUA_TFUNCTION);
727                 // Call function
728                 lua_pushnumber(L, dtime);
729                 if(lua_pcall(L, 1, 0, 0))
730                         script_error(L, "error: %s\n", lua_tostring(L, -1));
731                 // value removed, keep key for next iteration
732         }
733 }
734
735 /*
736         luaentity
737 */
738
739 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
740                 const char *init_state)
741 {
742         realitycheck(L);
743         assert(lua_checkstack(L, 20));
744         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
745                         <<name<<"\""<<std::endl;
746         StackUnroller stack_unroller(L);
747         
748         // Create object as a dummy string (TODO: Create properly)
749
750         // Get minetest.registered_entities[name]
751         lua_getglobal(L, "minetest");
752         lua_getfield(L, -1, "registered_entities");
753         luaL_checktype(L, -1, LUA_TTABLE);
754         lua_pushstring(L, name);
755         lua_gettable(L, -2);
756         // Should be a table, which we will use as a prototype
757         //luaL_checktype(L, -1, LUA_TTABLE);
758         if(lua_type(L, -1) != LUA_TTABLE){
759                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
760                 return false;
761         }
762         int prototype_table = lua_gettop(L);
763         //dump2(L, "prototype_table");
764         
765         // Create entity object
766         lua_newtable(L);
767         int object = lua_gettop(L);
768
769         // Set object metatable
770         lua_pushvalue(L, prototype_table);
771         lua_setmetatable(L, -2);
772         
773         // Add object reference
774         // This should be userdata with metatable ObjectRef
775         objectref_get(L, id);
776         luaL_checktype(L, -1, LUA_TUSERDATA);
777         if(!luaL_checkudata(L, -1, "ObjectRef"))
778                 luaL_typerror(L, -1, "ObjectRef");
779         lua_setfield(L, -2, "object");
780
781         // minetest.luaentities[id] = object
782         lua_getglobal(L, "minetest");
783         lua_getfield(L, -1, "luaentities");
784         luaL_checktype(L, -1, LUA_TTABLE);
785         lua_pushnumber(L, id); // Push id
786         lua_pushvalue(L, object); // Copy object to top of stack
787         lua_settable(L, -3);
788         
789         // This callback doesn't really make sense
790         /*// Get on_activate function
791         lua_pushvalue(L, object);
792         lua_getfield(L, -1, "on_activate");
793         luaL_checktype(L, -1, LUA_TFUNCTION);
794         lua_pushvalue(L, object); // self
795         // Call with 1 arguments, 0 results
796         if(lua_pcall(L, 1, 0, 0))
797                 script_error(L, "error running function %s:on_activate: %s\n",
798                                 name, lua_tostring(L, -1));*/
799
800         return true;
801 }
802
803 void scriptapi_luaentity_rm(lua_State *L, u16 id)
804 {
805         realitycheck(L);
806         assert(lua_checkstack(L, 20));
807         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
808
809         // Get minetest.luaentities table
810         lua_getglobal(L, "minetest");
811         lua_getfield(L, -1, "luaentities");
812         luaL_checktype(L, -1, LUA_TTABLE);
813         int objectstable = lua_gettop(L);
814         
815         // Set luaentities[id] = nil
816         lua_pushnumber(L, id); // Push id
817         lua_pushnil(L);
818         lua_settable(L, objectstable);
819         
820         lua_pop(L, 2); // pop luaentities, minetest
821 }
822
823 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
824 {
825         realitycheck(L);
826         assert(lua_checkstack(L, 20));
827         infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
828         
829         return "";
830 }
831
832 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
833                 LuaEntityProperties *prop)
834 {
835         realitycheck(L);
836         assert(lua_checkstack(L, 20));
837         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
838         StackUnroller stack_unroller(L);
839
840         // Get minetest.luaentities[id]
841         luaentity_get(L, id);
842         //int object = lua_gettop(L);
843
844         lua_getfield(L, -1, "physical");
845         if(lua_isboolean(L, -1))
846                 prop->physical = lua_toboolean(L, -1);
847         lua_pop(L, 1);
848         
849         lua_getfield(L, -1, "weight");
850         prop->weight = lua_tonumber(L, -1);
851         lua_pop(L, 1);
852
853         lua_getfield(L, -1, "collisionbox");
854         if(lua_istable(L, -1)){
855                 lua_rawgeti(L, -1, 1);
856                 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
857                 lua_pop(L, 1);
858                 lua_rawgeti(L, -1, 2);
859                 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
860                 lua_pop(L, 1);
861                 lua_rawgeti(L, -1, 3);
862                 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
863                 lua_pop(L, 1);
864                 lua_rawgeti(L, -1, 4);
865                 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
866                 lua_pop(L, 1);
867                 lua_rawgeti(L, -1, 5);
868                 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
869                 lua_pop(L, 1);
870                 lua_rawgeti(L, -1, 6);
871                 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
872                 lua_pop(L, 1);
873         }
874         lua_pop(L, 1);
875
876         lua_getfield(L, -1, "visual");
877         if(lua_isstring(L, -1))
878                 prop->visual = lua_tostring(L, -1);
879         lua_pop(L, 1);
880         
881         lua_getfield(L, -1, "textures");
882         if(lua_istable(L, -1)){
883                 prop->textures.clear();
884                 int table = lua_gettop(L);
885                 lua_pushnil(L);
886                 while(lua_next(L, table) != 0){
887                         // key at index -2 and value at index -1
888                         if(lua_isstring(L, -1))
889                                 prop->textures.push_back(lua_tostring(L, -1));
890                         else
891                                 prop->textures.push_back("");
892                         // removes value, keeps key for next iteration
893                         lua_pop(L, 1);
894                 }
895         }
896         lua_pop(L, 1);
897
898 }
899
900 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
901 {
902         realitycheck(L);
903         assert(lua_checkstack(L, 20));
904         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
905         StackUnroller stack_unroller(L);
906
907         // Get minetest.luaentities[id]
908         luaentity_get(L, id);
909         int object = lua_gettop(L);
910         // State: object is at top of stack
911         // Get step function
912         lua_getfield(L, -1, "on_step");
913         luaL_checktype(L, -1, LUA_TFUNCTION);
914         lua_pushvalue(L, object); // self
915         lua_pushnumber(L, dtime); // dtime
916         // Call with 2 arguments, 0 results
917         if(lua_pcall(L, 2, 0, 0))
918                 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
919 }
920
921 // Calls entity:on_punch(ObjectRef puncher)
922 void scriptapi_luaentity_punch(lua_State *L, u16 id,
923                 ServerActiveObject *puncher)
924 {
925         realitycheck(L);
926         assert(lua_checkstack(L, 20));
927         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
928         StackUnroller stack_unroller(L);
929
930         // Get minetest.luaentities[id]
931         luaentity_get(L, id);
932         int object = lua_gettop(L);
933         // State: object is at top of stack
934         // Get function
935         lua_getfield(L, -1, "on_punch");
936         luaL_checktype(L, -1, LUA_TFUNCTION);
937         lua_pushvalue(L, object); // self
938         objectref_get_or_create(L, puncher); // Clicker reference
939         // Call with 2 arguments, 0 results
940         if(lua_pcall(L, 2, 0, 0))
941                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
942 }
943
944 // Calls entity:on_rightclick(ObjectRef clicker)
945 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
946                 ServerActiveObject *clicker)
947 {
948         realitycheck(L);
949         assert(lua_checkstack(L, 20));
950         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
951         StackUnroller stack_unroller(L);
952
953         // Get minetest.luaentities[id]
954         luaentity_get(L, id);
955         int object = lua_gettop(L);
956         // State: object is at top of stack
957         // Get function
958         lua_getfield(L, -1, "on_rightclick");
959         luaL_checktype(L, -1, LUA_TFUNCTION);
960         lua_pushvalue(L, object); // self
961         objectref_get_or_create(L, clicker); // Clicker reference
962         // Call with 2 arguments, 0 results
963         if(lua_pcall(L, 2, 0, 0))
964                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
965 }
966