Node definition names
[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 #include "tooldef.h"
39
40 /*
41 TODO:
42 - Node definition
43 - Random node triggers (like grass growth)
44 - Deterministic node triggers (like falling sand)
45 - Object visual client-side stuff
46         - Blink effect
47         - Spritesheets and animation
48 - Named node types and dynamic id allocation per MapBlock
49 - LuaNodeMetadata
50         blockdef.has_metadata = true/false
51         - Stores an inventory and stuff in a Settings object
52         meta.inventory_add_list("main")
53         blockdef.on_inventory_modified
54         meta.set("owner", playername)
55         meta.get("owner")
56 - Item definition (actually, only CraftItem)
57 */
58
59 static void stackDump(lua_State *L, std::ostream &o)
60 {
61   int i;
62   int top = lua_gettop(L);
63   for (i = 1; i <= top; i++) {  /* repeat for each level */
64         int t = lua_type(L, i);
65         switch (t) {
66
67           case LUA_TSTRING:  /* strings */
68                 o<<"\""<<lua_tostring(L, i)<<"\"";
69                 break;
70
71           case LUA_TBOOLEAN:  /* booleans */
72                 o<<(lua_toboolean(L, i) ? "true" : "false");
73                 break;
74
75           case LUA_TNUMBER:  /* numbers */ {
76                 char buf[10];
77                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
78                 o<<buf;
79                 break; }
80
81           default:  /* other values */
82                 o<<lua_typename(L, t);
83                 break;
84
85         }
86         o<<" ";
87   }
88   o<<std::endl;
89 }
90
91 static void realitycheck(lua_State *L)
92 {
93         int top = lua_gettop(L);
94         if(top >= 30){
95                 dstream<<"Stack is over 30:"<<std::endl;
96                 stackDump(L, dstream);
97                 script_error(L, "Stack is over 30 (reality check)");
98         }
99 }
100
101 class StackUnroller
102 {
103 private:
104         lua_State *m_lua;
105         int m_original_top;
106 public:
107         StackUnroller(lua_State *L):
108                 m_lua(L),
109                 m_original_top(-1)
110         {
111                 m_original_top = lua_gettop(m_lua); // store stack height
112         }
113         ~StackUnroller()
114         {
115                 lua_settop(m_lua, m_original_top); // restore stack height
116         }
117 };
118
119 v3f readFloatPos(lua_State *L, int index)
120 {
121         v3f pos;
122         lua_pushvalue(L, index); // Push pos
123         luaL_checktype(L, -1, LUA_TTABLE);
124         lua_getfield(L, -1, "x");
125         pos.X = lua_tonumber(L, -1);
126         lua_pop(L, 1);
127         lua_getfield(L, -1, "y");
128         pos.Y = lua_tonumber(L, -1);
129         lua_pop(L, 1);
130         lua_getfield(L, -1, "z");
131         pos.Z = lua_tonumber(L, -1);
132         lua_pop(L, 1);
133         lua_pop(L, 1); // Pop pos
134         pos *= BS; // Scale to internal format
135         return pos;
136 }
137
138 /*
139         Global functions
140 */
141
142 // Register new object prototype
143 // register_entity(name, prototype)
144 static int l_register_entity(lua_State *L)
145 {
146         const char *name = luaL_checkstring(L, 1);
147         infostream<<"register_entity: "<<name<<std::endl;
148         luaL_checktype(L, 2, LUA_TTABLE);
149
150         // Get minetest.registered_entities
151         lua_getglobal(L, "minetest");
152         lua_getfield(L, -1, "registered_entities");
153         luaL_checktype(L, -1, LUA_TTABLE);
154         int registered_entities = lua_gettop(L);
155         lua_pushvalue(L, 2); // Object = param 2 -> stack top
156         // registered_entities[name] = object
157         lua_setfield(L, registered_entities, name);
158         
159         // Get registered object to top of stack
160         lua_pushvalue(L, 2);
161         
162         // Set __index to point to itself
163         lua_pushvalue(L, -1);
164         lua_setfield(L, -2, "__index");
165
166         // Set metatable.__index = metatable
167         luaL_getmetatable(L, "minetest.entity");
168         lua_pushvalue(L, -1); // duplicate metatable
169         lua_setfield(L, -2, "__index");
170         // Set object metatable
171         lua_setmetatable(L, -2);
172
173         return 0; /* number of results */
174 }
175
176 // Register a global step function
177 // register_globalstep(function)
178 static int l_register_globalstep(lua_State *L)
179 {
180         luaL_checktype(L, 1, LUA_TFUNCTION);
181         infostream<<"register_globalstep"<<std::endl;
182
183         lua_getglobal(L, "table");
184         lua_getfield(L, -1, "insert");
185         int table_insert = lua_gettop(L);
186         // Get minetest.registered_globalsteps
187         lua_getglobal(L, "minetest");
188         lua_getfield(L, -1, "registered_globalsteps");
189         luaL_checktype(L, -1, LUA_TTABLE);
190         int registered_globalsteps = lua_gettop(L);
191         // table.insert(registered_globalsteps, func)
192         lua_pushvalue(L, table_insert);
193         lua_pushvalue(L, registered_globalsteps);
194         lua_pushvalue(L, 1); // push function from argument 1
195         // Call insert
196         if(lua_pcall(L, 2, 0, 0))
197                 script_error(L, "error: %s\n", lua_tostring(L, -1));
198
199         return 0; /* number of results */
200 }
201
202 #if 0
203 // Clear all registered tools
204 // deregister_tools()
205 static int l_deregister_tools(lua_State *L)
206 {
207         infostream<<"deregister_tools"<<std::endl;
208
209         // Get server from registry
210         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
211         Server *server = (Server*)lua_touserdata(L, -1);
212         // And get the writable tool definition manager from the server
213         IWritableToolDefManager *tooldef =
214                         server->getWritableToolDefManager();
215         
216         tooldef->clear();
217
218         return 0; /* number of results */
219 }
220 #endif
221
222 // register_tool(name, {lots of stuff})
223 static int l_register_tool(lua_State *L)
224 {
225         const char *name = luaL_checkstring(L, 1);
226         infostream<<"register_tool: "<<name<<std::endl;
227         luaL_checktype(L, 2, LUA_TTABLE);
228
229         // Get server from registry
230         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
231         Server *server = (Server*)lua_touserdata(L, -1);
232         // And get the writable tool definition manager from the server
233         IWritableToolDefManager *tooldef =
234                         server->getWritableToolDefManager();
235         
236         int table = 2;
237         
238         ToolDefinition def;
239
240         lua_getfield(L, table, "image");
241         if(lua_isstring(L, -1))
242                 def.imagename = lua_tostring(L, -1);
243         lua_pop(L, 1);
244         
245         lua_getfield(L, table, "basetime");
246         def.properties.basetime = lua_tonumber(L, -1);
247         lua_pop(L, 1);
248
249         lua_getfield(L, table, "dt_weight");
250         def.properties.dt_weight = lua_tonumber(L, -1);
251         lua_pop(L, 1);
252
253         lua_getfield(L, table, "dt_crackiness");
254         def.properties.dt_crackiness = lua_tonumber(L, -1);
255         lua_pop(L, 1);
256
257         lua_getfield(L, table, "dt_crumbliness");
258         def.properties.dt_crumbliness = lua_tonumber(L, -1);
259         lua_pop(L, 1);
260
261         lua_getfield(L, table, "dt_cuttability");
262         def.properties.dt_cuttability = lua_tonumber(L, -1);
263         lua_pop(L, 1);
264
265         lua_getfield(L, table, "basedurability");
266         def.properties.basedurability = lua_tonumber(L, -1);
267         lua_pop(L, 1);
268
269         lua_getfield(L, table, "dd_weight");
270         def.properties.dd_weight = lua_tonumber(L, -1);
271         lua_pop(L, 1);
272
273         lua_getfield(L, table, "dd_crackiness");
274         def.properties.dd_crackiness = lua_tonumber(L, -1);
275         lua_pop(L, 1);
276
277         lua_getfield(L, table, "dd_crumbliness");
278         def.properties.dd_crumbliness = lua_tonumber(L, -1);
279         lua_pop(L, 1);
280
281         lua_getfield(L, table, "dd_cuttability");
282         def.properties.dd_cuttability = lua_tonumber(L, -1);
283         lua_pop(L, 1);
284
285         tooldef->registerTool(name, def);
286
287         return 0; /* number of results */
288 }
289
290 static const struct luaL_Reg minetest_f [] = {
291         {"register_entity", l_register_entity},
292         {"register_globalstep", l_register_globalstep},
293         //{"deregister_tools", l_deregister_tools},
294         {"register_tool", l_register_tool},
295         {NULL, NULL}
296 };
297
298 /*
299         LuaEntity functions
300 */
301
302 static const struct luaL_Reg minetest_entity_m [] = {
303         {NULL, NULL}
304 };
305
306 /*
307         Getters for stuff in main tables
308 */
309
310 static void objectref_get(lua_State *L, u16 id)
311 {
312         // Get minetest.object_refs[i]
313         lua_getglobal(L, "minetest");
314         lua_getfield(L, -1, "object_refs");
315         luaL_checktype(L, -1, LUA_TTABLE);
316         lua_pushnumber(L, id);
317         lua_gettable(L, -2);
318         lua_remove(L, -2); // object_refs
319         lua_remove(L, -2); // minetest
320 }
321
322 static void luaentity_get(lua_State *L, u16 id)
323 {
324         // Get minetest.luaentities[i]
325         lua_getglobal(L, "minetest");
326         lua_getfield(L, -1, "luaentities");
327         luaL_checktype(L, -1, LUA_TTABLE);
328         lua_pushnumber(L, id);
329         lua_gettable(L, -2);
330         lua_remove(L, -2); // luaentities
331         lua_remove(L, -2); // minetest
332 }
333
334 /*
335         Reference objects
336 */
337 #define method(class, name) {#name, class::l_##name}
338
339 class EnvRef
340 {
341 private:
342         ServerEnvironment *m_env;
343
344         static const char className[];
345         static const luaL_reg methods[];
346
347         static EnvRef *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 *(EnvRef**)ud;  // unbox pointer
353         }
354         
355         // Exported functions
356
357         // EnvRef:add_node(pos, content)
358         // pos = {x=num, y=num, z=num}
359         // content = number
360         static int l_add_node(lua_State *L)
361         {
362                 infostream<<"EnvRef::l_add_node()"<<std::endl;
363                 EnvRef *o = checkobject(L, 1);
364                 ServerEnvironment *env = o->m_env;
365                 if(env == NULL) return 0;
366                 // pos
367                 v3s16 pos;
368                 lua_pushvalue(L, 2); // Push pos
369                 luaL_checktype(L, -1, LUA_TTABLE);
370                 lua_getfield(L, -1, "x");
371                 pos.X = lua_tonumber(L, -1);
372                 lua_pop(L, 1);
373                 lua_getfield(L, -1, "y");
374                 pos.Y = lua_tonumber(L, -1);
375                 lua_pop(L, 1);
376                 lua_getfield(L, -1, "z");
377                 pos.Z = lua_tonumber(L, -1);
378                 lua_pop(L, 1);
379                 lua_pop(L, 1); // Pop pos
380                 // content
381                 u16 content = 0;
382                 lua_pushvalue(L, 3); // Push content
383                 content = lua_tonumber(L, -1);
384                 lua_pop(L, 1); // Pop content
385                 // Do it
386                 env->getMap().addNodeWithEvent(pos, MapNode(content));
387                 return 0;
388         }
389
390         static int gc_object(lua_State *L) {
391                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
392                 delete o;
393                 return 0;
394         }
395
396 public:
397         EnvRef(ServerEnvironment *env):
398                 m_env(env)
399         {
400                 infostream<<"EnvRef created"<<std::endl;
401         }
402
403         ~EnvRef()
404         {
405                 infostream<<"EnvRef destructing"<<std::endl;
406         }
407
408         // Creates an EnvRef and leaves it on top of stack
409         // Not callable from Lua; all references are created on the C side.
410         static void create(lua_State *L, ServerEnvironment *env)
411         {
412                 EnvRef *o = new EnvRef(env);
413                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
414                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
415                 luaL_getmetatable(L, className);
416                 lua_setmetatable(L, -2);
417         }
418
419         static void set_null(lua_State *L)
420         {
421                 EnvRef *o = checkobject(L, -1);
422                 o->m_env = NULL;
423         }
424         
425         static void Register(lua_State *L)
426         {
427                 lua_newtable(L);
428                 int methodtable = lua_gettop(L);
429                 luaL_newmetatable(L, className);
430                 int metatable = lua_gettop(L);
431
432                 lua_pushliteral(L, "__metatable");
433                 lua_pushvalue(L, methodtable);
434                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
435
436                 lua_pushliteral(L, "__index");
437                 lua_pushvalue(L, methodtable);
438                 lua_settable(L, metatable);
439
440                 lua_pushliteral(L, "__gc");
441                 lua_pushcfunction(L, gc_object);
442                 lua_settable(L, metatable);
443
444                 lua_pop(L, 1);  // drop metatable
445
446                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
447                 lua_pop(L, 1);  // drop methodtable
448
449                 // Cannot be created from Lua
450                 //lua_register(L, className, create_object);
451         }
452 };
453 const char EnvRef::className[] = "EnvRef";
454 const luaL_reg EnvRef::methods[] = {
455         method(EnvRef, add_node),
456         {0,0}
457 };
458
459 class ObjectRef
460 {
461 private:
462         ServerActiveObject *m_object;
463
464         static const char className[];
465         static const luaL_reg methods[];
466
467         static ObjectRef *checkobject(lua_State *L, int narg)
468         {
469                 luaL_checktype(L, narg, LUA_TUSERDATA);
470                 void *ud = luaL_checkudata(L, narg, className);
471                 if(!ud) luaL_typerror(L, narg, className);
472                 return *(ObjectRef**)ud;  // unbox pointer
473         }
474         
475         static ServerActiveObject* getobject(ObjectRef *ref)
476         {
477                 ServerActiveObject *co = ref->m_object;
478                 return co;
479         }
480         
481         static LuaEntitySAO* getluaobject(ObjectRef *ref)
482         {
483                 ServerActiveObject *obj = getobject(ref);
484                 if(obj == NULL)
485                         return NULL;
486                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
487                         return NULL;
488                 return (LuaEntitySAO*)obj;
489         }
490         
491         // Exported functions
492         
493         // garbage collector
494         static int gc_object(lua_State *L) {
495                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
496                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
497                 delete o;
498                 return 0;
499         }
500
501         // remove(self)
502         static int l_remove(lua_State *L)
503         {
504                 ObjectRef *ref = checkobject(L, 1);
505                 ServerActiveObject *co = getobject(ref);
506                 if(co == NULL) return 0;
507                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
508                 co->m_removed = true;
509                 return 0;
510         }
511         
512         // getpos(self)
513         // returns: {x=num, y=num, z=num}
514         static int l_getpos(lua_State *L)
515         {
516                 ObjectRef *ref = checkobject(L, 1);
517                 ServerActiveObject *co = getobject(ref);
518                 if(co == NULL) return 0;
519                 v3f pos = co->getBasePosition() / BS;
520                 lua_newtable(L);
521                 lua_pushnumber(L, pos.X);
522                 lua_setfield(L, -2, "x");
523                 lua_pushnumber(L, pos.Y);
524                 lua_setfield(L, -2, "y");
525                 lua_pushnumber(L, pos.Z);
526                 lua_setfield(L, -2, "z");
527                 return 1;
528         }
529         
530         // setpos(self, pos)
531         static int l_setpos(lua_State *L)
532         {
533                 ObjectRef *ref = checkobject(L, 1);
534                 //LuaEntitySAO *co = getluaobject(ref);
535                 ServerActiveObject *co = getobject(ref);
536                 if(co == NULL) return 0;
537                 // pos
538                 v3f pos = readFloatPos(L, 2);
539                 // Do it
540                 co->setPos(pos);
541                 return 0;
542         }
543         
544         // moveto(self, pos, continuous=false)
545         static int l_moveto(lua_State *L)
546         {
547                 ObjectRef *ref = checkobject(L, 1);
548                 //LuaEntitySAO *co = getluaobject(ref);
549                 ServerActiveObject *co = getobject(ref);
550                 if(co == NULL) return 0;
551                 // pos
552                 v3f pos = readFloatPos(L, 2);
553                 // continuous
554                 bool continuous = lua_toboolean(L, 3);
555                 // Do it
556                 co->moveTo(pos, continuous);
557                 return 0;
558         }
559
560         // add_to_inventory(self, itemstring)
561         // returns: true if item was added, false otherwise
562         static int l_add_to_inventory(lua_State *L)
563         {
564                 ObjectRef *ref = checkobject(L, 1);
565                 luaL_checkstring(L, 2);
566                 ServerActiveObject *co = getobject(ref);
567                 if(co == NULL) return 0;
568                 // itemstring
569                 const char *itemstring = lua_tostring(L, 2);
570                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
571                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
572                 // Do it
573                 std::istringstream is(itemstring, std::ios::binary);
574                 ServerEnvironment *env = co->getEnv();
575                 assert(env);
576                 IGameDef *gamedef = env->getGameDef();
577                 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
578                 infostream<<"item="<<env<<std::endl;
579                 bool fits = co->addToInventory(item);
580                 // Return
581                 lua_pushboolean(L, fits);
582                 return 1;
583         }
584
585 public:
586         ObjectRef(ServerActiveObject *object):
587                 m_object(object)
588         {
589                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
590         }
591
592         ~ObjectRef()
593         {
594                 /*if(m_object)
595                         infostream<<"ObjectRef destructing for id="
596                                         <<m_object->getId()<<std::endl;
597                 else
598                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
599         }
600
601         // Creates an ObjectRef and leaves it on top of stack
602         // Not callable from Lua; all references are created on the C side.
603         static void create(lua_State *L, ServerActiveObject *object)
604         {
605                 ObjectRef *o = new ObjectRef(object);
606                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
607                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
608                 luaL_getmetatable(L, className);
609                 lua_setmetatable(L, -2);
610         }
611
612         static void set_null(lua_State *L)
613         {
614                 ObjectRef *o = checkobject(L, -1);
615                 o->m_object = NULL;
616         }
617         
618         static void Register(lua_State *L)
619         {
620                 lua_newtable(L);
621                 int methodtable = lua_gettop(L);
622                 luaL_newmetatable(L, className);
623                 int metatable = lua_gettop(L);
624
625                 lua_pushliteral(L, "__metatable");
626                 lua_pushvalue(L, methodtable);
627                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
628
629                 lua_pushliteral(L, "__index");
630                 lua_pushvalue(L, methodtable);
631                 lua_settable(L, metatable);
632
633                 lua_pushliteral(L, "__gc");
634                 lua_pushcfunction(L, gc_object);
635                 lua_settable(L, metatable);
636
637                 lua_pop(L, 1);  // drop metatable
638
639                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
640                 lua_pop(L, 1);  // drop methodtable
641
642                 // Cannot be created from Lua
643                 //lua_register(L, className, create_object);
644         }
645 };
646 const char ObjectRef::className[] = "ObjectRef";
647 const luaL_reg ObjectRef::methods[] = {
648         method(ObjectRef, remove),
649         method(ObjectRef, getpos),
650         method(ObjectRef, setpos),
651         method(ObjectRef, moveto),
652         method(ObjectRef, add_to_inventory),
653         {0,0}
654 };
655
656 // Creates a new anonymous reference if id=0
657 static void objectref_get_or_create(lua_State *L,
658                 ServerActiveObject *cobj)
659 {
660         if(cobj->getId() == 0){
661                 ObjectRef::create(L, cobj);
662         } else {
663                 objectref_get(L, cobj->getId());
664         }
665 }
666
667 /*
668         Main export function
669 */
670
671 void scriptapi_export(lua_State *L, Server *server)
672 {
673         realitycheck(L);
674         assert(lua_checkstack(L, 20));
675         infostream<<"scriptapi_export"<<std::endl;
676         StackUnroller stack_unroller(L);
677
678         // Store server as light userdata in registry
679         lua_pushlightuserdata(L, server);
680         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
681         
682         // Register global functions in table minetest
683         lua_newtable(L);
684         luaL_register(L, NULL, minetest_f);
685         lua_setglobal(L, "minetest");
686         
687         // Get the main minetest table
688         lua_getglobal(L, "minetest");
689
690         // Add tables to minetest
691         
692         /*lua_newtable(L);
693         lua_setfield(L, -2, "registered_blocks");*/
694
695         lua_newtable(L);
696         lua_setfield(L, -2, "registered_entities");
697
698         lua_newtable(L);
699         lua_setfield(L, -2, "registered_globalsteps");
700
701         lua_newtable(L);
702         lua_setfield(L, -2, "object_refs");
703
704         lua_newtable(L);
705         lua_setfield(L, -2, "luaentities");
706
707         // Create entity prototype
708         luaL_newmetatable(L, "minetest.entity");
709         // metatable.__index = metatable
710         lua_pushvalue(L, -1); // Duplicate metatable
711         lua_setfield(L, -2, "__index");
712         // Put functions in metatable
713         luaL_register(L, NULL, minetest_entity_m);
714         // Put other stuff in metatable
715
716         // Environment C reference
717         EnvRef::Register(L);
718
719         // Object C reference
720         ObjectRef::Register(L);
721 }
722
723 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
724 {
725         realitycheck(L);
726         assert(lua_checkstack(L, 20));
727         infostream<<"scriptapi_add_environment"<<std::endl;
728         StackUnroller stack_unroller(L);
729
730         // Create EnvRef on stack
731         EnvRef::create(L, env);
732         int envref = lua_gettop(L);
733
734         // minetest.env = envref
735         lua_getglobal(L, "minetest");
736         luaL_checktype(L, -1, LUA_TTABLE);
737         lua_pushvalue(L, envref);
738         lua_setfield(L, -2, "env");
739 }
740
741 #if 0
742 // Dump stack top with the dump2 function
743 static void dump2(lua_State *L, const char *name)
744 {
745         // Dump object (debug)
746         lua_getglobal(L, "dump2");
747         luaL_checktype(L, -1, LUA_TFUNCTION);
748         lua_pushvalue(L, -2); // Get previous stack top as first parameter
749         lua_pushstring(L, name);
750         if(lua_pcall(L, 2, 0, 0))
751                 script_error(L, "error: %s\n", lua_tostring(L, -1));
752 }
753 #endif
754
755 /*
756         object_reference
757 */
758
759 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
760 {
761         realitycheck(L);
762         assert(lua_checkstack(L, 20));
763         infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
764         StackUnroller stack_unroller(L);
765
766         // Create object on stack
767         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
768         int object = lua_gettop(L);
769
770         // Get minetest.object_refs table
771         lua_getglobal(L, "minetest");
772         lua_getfield(L, -1, "object_refs");
773         luaL_checktype(L, -1, LUA_TTABLE);
774         int objectstable = lua_gettop(L);
775         
776         // object_refs[id] = object
777         lua_pushnumber(L, cobj->getId()); // Push id
778         lua_pushvalue(L, object); // Copy object to top of stack
779         lua_settable(L, objectstable);
780 }
781
782 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
783 {
784         realitycheck(L);
785         assert(lua_checkstack(L, 20));
786         infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
787         StackUnroller stack_unroller(L);
788
789         // Get minetest.object_refs table
790         lua_getglobal(L, "minetest");
791         lua_getfield(L, -1, "object_refs");
792         luaL_checktype(L, -1, LUA_TTABLE);
793         int objectstable = lua_gettop(L);
794         
795         // Get object_refs[id]
796         lua_pushnumber(L, cobj->getId()); // Push id
797         lua_gettable(L, objectstable);
798         // Set object reference to NULL
799         ObjectRef::set_null(L);
800         lua_pop(L, 1); // pop object
801
802         // Set object_refs[id] = nil
803         lua_pushnumber(L, cobj->getId()); // Push id
804         lua_pushnil(L);
805         lua_settable(L, objectstable);
806 }
807
808 /*
809         environment
810 */
811
812 void scriptapi_environment_step(lua_State *L, float dtime)
813 {
814         realitycheck(L);
815         assert(lua_checkstack(L, 20));
816         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
817         StackUnroller stack_unroller(L);
818
819         // Get minetest.registered_globalsteps
820         lua_getglobal(L, "minetest");
821         lua_getfield(L, -1, "registered_globalsteps");
822         luaL_checktype(L, -1, LUA_TTABLE);
823         int table = lua_gettop(L);
824         // Foreach
825         lua_pushnil(L);
826         while(lua_next(L, table) != 0){
827                 // key at index -2 and value at index -1
828                 luaL_checktype(L, -1, LUA_TFUNCTION);
829                 // Call function
830                 lua_pushnumber(L, dtime);
831                 if(lua_pcall(L, 1, 0, 0))
832                         script_error(L, "error: %s\n", lua_tostring(L, -1));
833                 // value removed, keep key for next iteration
834         }
835 }
836
837 /*
838         luaentity
839 */
840
841 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
842                 const char *init_state)
843 {
844         realitycheck(L);
845         assert(lua_checkstack(L, 20));
846         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
847                         <<name<<"\""<<std::endl;
848         StackUnroller stack_unroller(L);
849         
850         // Create object as a dummy string (TODO: Create properly)
851
852         // Get minetest.registered_entities[name]
853         lua_getglobal(L, "minetest");
854         lua_getfield(L, -1, "registered_entities");
855         luaL_checktype(L, -1, LUA_TTABLE);
856         lua_pushstring(L, name);
857         lua_gettable(L, -2);
858         // Should be a table, which we will use as a prototype
859         //luaL_checktype(L, -1, LUA_TTABLE);
860         if(lua_type(L, -1) != LUA_TTABLE){
861                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
862                 return false;
863         }
864         int prototype_table = lua_gettop(L);
865         //dump2(L, "prototype_table");
866         
867         // Create entity object
868         lua_newtable(L);
869         int object = lua_gettop(L);
870
871         // Set object metatable
872         lua_pushvalue(L, prototype_table);
873         lua_setmetatable(L, -2);
874         
875         // Add object reference
876         // This should be userdata with metatable ObjectRef
877         objectref_get(L, id);
878         luaL_checktype(L, -1, LUA_TUSERDATA);
879         if(!luaL_checkudata(L, -1, "ObjectRef"))
880                 luaL_typerror(L, -1, "ObjectRef");
881         lua_setfield(L, -2, "object");
882
883         // minetest.luaentities[id] = object
884         lua_getglobal(L, "minetest");
885         lua_getfield(L, -1, "luaentities");
886         luaL_checktype(L, -1, LUA_TTABLE);
887         lua_pushnumber(L, id); // Push id
888         lua_pushvalue(L, object); // Copy object to top of stack
889         lua_settable(L, -3);
890         
891         // This callback doesn't really make sense
892         /*// Get on_activate function
893         lua_pushvalue(L, object);
894         lua_getfield(L, -1, "on_activate");
895         luaL_checktype(L, -1, LUA_TFUNCTION);
896         lua_pushvalue(L, object); // self
897         // Call with 1 arguments, 0 results
898         if(lua_pcall(L, 1, 0, 0))
899                 script_error(L, "error running function %s:on_activate: %s\n",
900                                 name, lua_tostring(L, -1));*/
901
902         return true;
903 }
904
905 void scriptapi_luaentity_rm(lua_State *L, u16 id)
906 {
907         realitycheck(L);
908         assert(lua_checkstack(L, 20));
909         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
910
911         // Get minetest.luaentities table
912         lua_getglobal(L, "minetest");
913         lua_getfield(L, -1, "luaentities");
914         luaL_checktype(L, -1, LUA_TTABLE);
915         int objectstable = lua_gettop(L);
916         
917         // Set luaentities[id] = nil
918         lua_pushnumber(L, id); // Push id
919         lua_pushnil(L);
920         lua_settable(L, objectstable);
921         
922         lua_pop(L, 2); // pop luaentities, minetest
923 }
924
925 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
926 {
927         realitycheck(L);
928         assert(lua_checkstack(L, 20));
929         infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
930         
931         return "";
932 }
933
934 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
935                 LuaEntityProperties *prop)
936 {
937         realitycheck(L);
938         assert(lua_checkstack(L, 20));
939         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
940         StackUnroller stack_unroller(L);
941
942         // Get minetest.luaentities[id]
943         luaentity_get(L, id);
944         //int object = lua_gettop(L);
945
946         lua_getfield(L, -1, "physical");
947         if(lua_isboolean(L, -1))
948                 prop->physical = lua_toboolean(L, -1);
949         lua_pop(L, 1);
950         
951         lua_getfield(L, -1, "weight");
952         prop->weight = lua_tonumber(L, -1);
953         lua_pop(L, 1);
954
955         lua_getfield(L, -1, "collisionbox");
956         if(lua_istable(L, -1)){
957                 lua_rawgeti(L, -1, 1);
958                 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
959                 lua_pop(L, 1);
960                 lua_rawgeti(L, -1, 2);
961                 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
962                 lua_pop(L, 1);
963                 lua_rawgeti(L, -1, 3);
964                 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
965                 lua_pop(L, 1);
966                 lua_rawgeti(L, -1, 4);
967                 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
968                 lua_pop(L, 1);
969                 lua_rawgeti(L, -1, 5);
970                 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
971                 lua_pop(L, 1);
972                 lua_rawgeti(L, -1, 6);
973                 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
974                 lua_pop(L, 1);
975         }
976         lua_pop(L, 1);
977
978         lua_getfield(L, -1, "visual");
979         if(lua_isstring(L, -1))
980                 prop->visual = lua_tostring(L, -1);
981         lua_pop(L, 1);
982         
983         lua_getfield(L, -1, "textures");
984         if(lua_istable(L, -1)){
985                 prop->textures.clear();
986                 int table = lua_gettop(L);
987                 lua_pushnil(L);
988                 while(lua_next(L, table) != 0){
989                         // key at index -2 and value at index -1
990                         if(lua_isstring(L, -1))
991                                 prop->textures.push_back(lua_tostring(L, -1));
992                         else
993                                 prop->textures.push_back("");
994                         // removes value, keeps key for next iteration
995                         lua_pop(L, 1);
996                 }
997         }
998         lua_pop(L, 1);
999
1000 }
1001
1002 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1003 {
1004         realitycheck(L);
1005         assert(lua_checkstack(L, 20));
1006         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1007         StackUnroller stack_unroller(L);
1008
1009         // Get minetest.luaentities[id]
1010         luaentity_get(L, id);
1011         int object = lua_gettop(L);
1012         // State: object is at top of stack
1013         // Get step function
1014         lua_getfield(L, -1, "on_step");
1015         luaL_checktype(L, -1, LUA_TFUNCTION);
1016         lua_pushvalue(L, object); // self
1017         lua_pushnumber(L, dtime); // dtime
1018         // Call with 2 arguments, 0 results
1019         if(lua_pcall(L, 2, 0, 0))
1020                 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
1021 }
1022
1023 // Calls entity:on_punch(ObjectRef puncher)
1024 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1025                 ServerActiveObject *puncher)
1026 {
1027         realitycheck(L);
1028         assert(lua_checkstack(L, 20));
1029         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1030         StackUnroller stack_unroller(L);
1031
1032         // Get minetest.luaentities[id]
1033         luaentity_get(L, id);
1034         int object = lua_gettop(L);
1035         // State: object is at top of stack
1036         // Get function
1037         lua_getfield(L, -1, "on_punch");
1038         luaL_checktype(L, -1, LUA_TFUNCTION);
1039         lua_pushvalue(L, object); // self
1040         objectref_get_or_create(L, puncher); // Clicker reference
1041         // Call with 2 arguments, 0 results
1042         if(lua_pcall(L, 2, 0, 0))
1043                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1044 }
1045
1046 // Calls entity:on_rightclick(ObjectRef clicker)
1047 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1048                 ServerActiveObject *clicker)
1049 {
1050         realitycheck(L);
1051         assert(lua_checkstack(L, 20));
1052         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1053         StackUnroller stack_unroller(L);
1054
1055         // Get minetest.luaentities[id]
1056         luaentity_get(L, id);
1057         int object = lua_gettop(L);
1058         // State: object is at top of stack
1059         // Get function
1060         lua_getfield(L, -1, "on_rightclick");
1061         luaL_checktype(L, -1, LUA_TFUNCTION);
1062         lua_pushvalue(L, object); // self
1063         objectref_get_or_create(L, clicker); // Clicker reference
1064         // Call with 2 arguments, 0 results
1065         if(lua_pcall(L, 2, 0, 0))
1066                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
1067 }
1068