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