3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #include "scriptapi.h"
33 #include "serverobject.h"
36 #include "luaentity_common.h"
37 #include "content_sao.h" // For LuaEntitySAO
45 - Random node triggers (like grass growth)
46 - Deterministic node triggers (like falling sand)
47 - Object visual client-side stuff
49 - Spritesheets and animation
51 blockdef.metadata_type =
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)
63 - Item definition (actually, only CraftItem)
66 static void stackDump(lua_State *L, std::ostream &o)
69 int top = lua_gettop(L);
70 for (i = 1; i <= top; i++) { /* repeat for each level */
71 int t = lua_type(L, i);
74 case LUA_TSTRING: /* strings */
75 o<<"\""<<lua_tostring(L, i)<<"\"";
78 case LUA_TBOOLEAN: /* booleans */
79 o<<(lua_toboolean(L, i) ? "true" : "false");
82 case LUA_TNUMBER: /* numbers */ {
84 snprintf(buf, 10, "%g", lua_tonumber(L, i));
88 default: /* other values */
89 o<<lua_typename(L, t);
98 static void realitycheck(lua_State *L)
100 int top = lua_gettop(L);
102 dstream<<"Stack is over 30:"<<std::endl;
103 stackDump(L, dstream);
104 script_error(L, "Stack is over 30 (reality check)");
114 StackUnroller(lua_State *L):
118 m_original_top = lua_gettop(m_lua); // store stack height
122 lua_settop(m_lua, m_original_top); // restore stack height
126 static v3f readFloatPos(lua_State *L, int index)
129 luaL_checktype(L, index, LUA_TTABLE);
130 lua_getfield(L, index, "x");
131 pos.X = lua_tonumber(L, -1);
133 lua_getfield(L, index, "y");
134 pos.Y = lua_tonumber(L, -1);
136 lua_getfield(L, index, "z");
137 pos.Z = lua_tonumber(L, -1);
139 pos *= BS; // Scale to internal format
143 static void pushpos(lua_State *L, v3s16 p)
146 lua_pushnumber(L, p.X);
147 lua_setfield(L, -2, "x");
148 lua_pushnumber(L, p.Y);
149 lua_setfield(L, -2, "y");
150 lua_pushnumber(L, p.Z);
151 lua_setfield(L, -2, "z");
154 static v3s16 readpos(lua_State *L, int index)
157 lua_getfield(L, index, "x");
158 p.X = lua_tonumber(L, -1);
159 lua_getfield(L, index, "y");
160 p.Y = lua_tonumber(L, -1);
161 lua_getfield(L, index, "z");
162 p.Z = lua_tonumber(L, -1);
166 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
169 lua_pushstring(L, ndef->get(n).name.c_str());
170 lua_setfield(L, -2, "name");
171 lua_pushnumber(L, n.getParam1());
172 lua_setfield(L, -2, "param1");
173 lua_pushnumber(L, n.getParam2());
174 lua_setfield(L, -2, "param2");
177 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
179 lua_getfield(L, index, "name");
180 const char *name = lua_tostring(L, -1);
183 lua_getfield(L, index, "param1");
187 param1 = lua_tonumber(L, -1);
190 lua_getfield(L, index, "param2");
194 param2 = lua_tonumber(L, -1);
196 return MapNode(ndef, name, param1, param2);
203 // Register new object prototype
204 // register_entity(name, prototype)
205 static int l_register_entity(lua_State *L)
207 const char *name = luaL_checkstring(L, 1);
208 infostream<<"register_entity: "<<name<<std::endl;
209 luaL_checktype(L, 2, LUA_TTABLE);
211 // Get minetest.registered_entities
212 lua_getglobal(L, "minetest");
213 lua_getfield(L, -1, "registered_entities");
214 luaL_checktype(L, -1, LUA_TTABLE);
215 int registered_entities = lua_gettop(L);
216 lua_pushvalue(L, 2); // Object = param 2 -> stack top
217 // registered_entities[name] = object
218 lua_setfield(L, registered_entities, name);
220 // Get registered object to top of stack
223 // Set __index to point to itself
224 lua_pushvalue(L, -1);
225 lua_setfield(L, -2, "__index");
227 // Set metatable.__index = metatable
228 luaL_getmetatable(L, "minetest.entity");
229 lua_pushvalue(L, -1); // duplicate metatable
230 lua_setfield(L, -2, "__index");
231 // Set object metatable
232 lua_setmetatable(L, -2);
234 return 0; /* number of results */
237 // register_tool(name, {lots of stuff})
238 static int l_register_tool(lua_State *L)
240 const char *name = luaL_checkstring(L, 1);
241 infostream<<"register_tool: "<<name<<std::endl;
242 luaL_checktype(L, 2, LUA_TTABLE);
245 // Get server from registry
246 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
247 Server *server = (Server*)lua_touserdata(L, -1);
248 // And get the writable tool definition manager from the server
249 IWritableToolDefManager *tooldef =
250 server->getWritableToolDefManager();
254 lua_getfield(L, table, "image");
255 if(lua_isstring(L, -1))
256 def.imagename = lua_tostring(L, -1);
259 lua_getfield(L, table, "basetime");
260 def.properties.basetime = lua_tonumber(L, -1);
263 lua_getfield(L, table, "dt_weight");
264 def.properties.dt_weight = lua_tonumber(L, -1);
267 lua_getfield(L, table, "dt_crackiness");
268 def.properties.dt_crackiness = lua_tonumber(L, -1);
271 lua_getfield(L, table, "dt_crumbliness");
272 def.properties.dt_crumbliness = lua_tonumber(L, -1);
275 lua_getfield(L, table, "dt_cuttability");
276 def.properties.dt_cuttability = lua_tonumber(L, -1);
279 lua_getfield(L, table, "basedurability");
280 def.properties.basedurability = lua_tonumber(L, -1);
283 lua_getfield(L, table, "dd_weight");
284 def.properties.dd_weight = lua_tonumber(L, -1);
287 lua_getfield(L, table, "dd_crackiness");
288 def.properties.dd_crackiness = lua_tonumber(L, -1);
291 lua_getfield(L, table, "dd_crumbliness");
292 def.properties.dd_crumbliness = lua_tonumber(L, -1);
295 lua_getfield(L, table, "dd_cuttability");
296 def.properties.dd_cuttability = lua_tonumber(L, -1);
299 tooldef->registerTool(name, def);
300 return 0; /* number of results */
303 // register_node(name, {lots of stuff})
304 static int l_register_node(lua_State *L)
306 const char *name = luaL_checkstring(L, 1);
307 infostream<<"register_node: "<<name<<std::endl;
308 luaL_checktype(L, 2, LUA_TTABLE);
311 // Get server from registry
312 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
313 Server *server = (Server*)lua_touserdata(L, -1);
314 // And get the writable node definition manager from the server
315 IWritableNodeDefManager *nodedef =
316 server->getWritableNodeDefManager();
321 lua_getfield(L, table0, "tile_images");
322 if(lua_istable(L, -1)){
323 int table = lua_gettop(L);
326 while(lua_next(L, table) != 0){
327 // key at index -2 and value at index -1
328 if(lua_isstring(L, -1))
329 f.tname_tiles[i] = lua_tostring(L, -1);
331 f.tname_tiles[i] = "";
332 // removes value, keeps key for next iteration
343 lua_getfield(L, table0, "inventory_image");
344 if(lua_isstring(L, -1))
345 f.tname_inventory = lua_tostring(L, -1);
348 // TODO: Replace with actual parameter reading
349 // Temporarily set some sane parameters to allow digging
350 f.material.diggability = DIGGABLE_NORMAL;
351 f.material.weight = 0;
352 f.material.crackiness = 0;
353 f.material.crumbliness = 0;
354 f.material.cuttability = 0;
356 nodedef->set(name, f);
357 return 0; /* number of results */
360 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
361 static int l_register_craft(lua_State *L)
363 infostream<<"register_craft"<<std::endl;
364 luaL_checktype(L, 1, LUA_TTABLE);
367 // Get server from registry
368 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
369 Server *server = (Server*)lua_touserdata(L, -1);
370 // And get the writable craft definition manager from the server
371 IWritableCraftDefManager *craftdef =
372 server->getWritableCraftDefManager();
376 std::vector<std::string> input;
378 lua_getfield(L, table0, "output");
379 luaL_checktype(L, -1, LUA_TSTRING);
380 if(lua_isstring(L, -1))
381 output = lua_tostring(L, -1);
384 lua_getfield(L, table0, "recipe");
385 luaL_checktype(L, -1, LUA_TTABLE);
386 if(lua_istable(L, -1)){
387 int table1 = lua_gettop(L);
390 while(lua_next(L, table1) != 0){
392 // key at index -2 and value at index -1
393 luaL_checktype(L, -1, LUA_TTABLE);
394 if(lua_istable(L, -1)){
395 int table2 = lua_gettop(L);
397 while(lua_next(L, table2) != 0){
398 // key at index -2 and value at index -1
399 luaL_checktype(L, -1, LUA_TSTRING);
400 input.push_back(lua_tostring(L, -1));
401 // removes value, keeps key for next iteration
409 if(colcount != width){
410 script_error(L, "error: %s\n", "Invalid crafting recipe");
413 // removes value, keeps key for next iteration
420 CraftDefinition def(output, width, input);
421 craftdef->registerCraft(def);
423 return 0; /* number of results */
426 // Register a global step function
427 // register_globalstep(function)
428 static int l_register_globalstep(lua_State *L)
430 luaL_checktype(L, 1, LUA_TFUNCTION);
431 infostream<<"register_globalstep"<<std::endl;
433 lua_getglobal(L, "table");
434 lua_getfield(L, -1, "insert");
435 int table_insert = lua_gettop(L);
436 // Get minetest.registered_globalsteps
437 lua_getglobal(L, "minetest");
438 lua_getfield(L, -1, "registered_globalsteps");
439 luaL_checktype(L, -1, LUA_TTABLE);
440 int registered_globalsteps = lua_gettop(L);
441 // table.insert(registered_globalsteps, func)
442 lua_pushvalue(L, table_insert);
443 lua_pushvalue(L, registered_globalsteps);
444 lua_pushvalue(L, 1); // push function from argument 1
446 if(lua_pcall(L, 2, 0, 0))
447 script_error(L, "error: %s\n", lua_tostring(L, -1));
449 return 0; /* number of results */
452 // register_on_placenode(function)
453 static int l_register_on_placenode(lua_State *L)
455 luaL_checktype(L, 1, LUA_TFUNCTION);
456 infostream<<"register_on_placenode"<<std::endl;
458 lua_getglobal(L, "table");
459 lua_getfield(L, -1, "insert");
460 int table_insert = lua_gettop(L);
461 // Get minetest.registered_on_placenodes
462 lua_getglobal(L, "minetest");
463 lua_getfield(L, -1, "registered_on_placenodes");
464 luaL_checktype(L, -1, LUA_TTABLE);
465 int registered_on_placenodes = lua_gettop(L);
466 // table.insert(registered_on_placenodes, func)
467 lua_pushvalue(L, table_insert);
468 lua_pushvalue(L, registered_on_placenodes);
469 lua_pushvalue(L, 1); // push function from argument 1
471 if(lua_pcall(L, 2, 0, 0))
472 script_error(L, "error: %s\n", lua_tostring(L, -1));
474 return 0; /* number of results */
477 // register_on_dignode(function)
478 static int l_register_on_dignode(lua_State *L)
480 luaL_checktype(L, 1, LUA_TFUNCTION);
481 infostream<<"register_on_dignode"<<std::endl;
483 lua_getglobal(L, "table");
484 lua_getfield(L, -1, "insert");
485 int table_insert = lua_gettop(L);
486 // Get minetest.registered_on_dignodes
487 lua_getglobal(L, "minetest");
488 lua_getfield(L, -1, "registered_on_dignodes");
489 luaL_checktype(L, -1, LUA_TTABLE);
490 int registered_on_dignodes = lua_gettop(L);
491 // table.insert(registered_on_dignodes, func)
492 lua_pushvalue(L, table_insert);
493 lua_pushvalue(L, registered_on_dignodes);
494 lua_pushvalue(L, 1); // push function from argument 1
496 if(lua_pcall(L, 2, 0, 0))
497 script_error(L, "error: %s\n", lua_tostring(L, -1));
499 return 0; /* number of results */
502 static const struct luaL_Reg minetest_f [] = {
503 {"register_entity", l_register_entity},
504 {"register_tool", l_register_tool},
505 {"register_node", l_register_node},
506 {"register_craft", l_register_craft},
507 {"register_globalstep", l_register_globalstep},
508 {"register_on_placenode", l_register_on_placenode},
509 {"register_on_dignode", l_register_on_dignode},
517 static const struct luaL_Reg minetest_entity_m [] = {
522 Getters for stuff in main tables
525 static void objectref_get(lua_State *L, u16 id)
527 // Get minetest.object_refs[i]
528 lua_getglobal(L, "minetest");
529 lua_getfield(L, -1, "object_refs");
530 luaL_checktype(L, -1, LUA_TTABLE);
531 lua_pushnumber(L, id);
533 lua_remove(L, -2); // object_refs
534 lua_remove(L, -2); // minetest
537 static void luaentity_get(lua_State *L, u16 id)
539 // Get minetest.luaentities[i]
540 lua_getglobal(L, "minetest");
541 lua_getfield(L, -1, "luaentities");
542 luaL_checktype(L, -1, LUA_TTABLE);
543 lua_pushnumber(L, id);
545 lua_remove(L, -2); // luaentities
546 lua_remove(L, -2); // minetest
552 #define method(class, name) {#name, class::l_##name}
557 ServerEnvironment *m_env;
559 static const char className[];
560 static const luaL_reg methods[];
562 static EnvRef *checkobject(lua_State *L, int narg)
564 luaL_checktype(L, narg, LUA_TUSERDATA);
565 void *ud = luaL_checkudata(L, narg, className);
566 if(!ud) luaL_typerror(L, narg, className);
567 return *(EnvRef**)ud; // unbox pointer
570 // Exported functions
572 // EnvRef:add_node(pos, node)
573 // pos = {x=num, y=num, z=num}
574 static int l_add_node(lua_State *L)
576 infostream<<"EnvRef::l_add_node()"<<std::endl;
577 EnvRef *o = checkobject(L, 1);
578 ServerEnvironment *env = o->m_env;
579 if(env == NULL) return 0;
581 v3s16 pos = readpos(L, 2);
583 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
585 env->getMap().addNodeWithEvent(pos, n);
589 // EnvRef:remove_node(pos)
590 // pos = {x=num, y=num, z=num}
591 static int l_remove_node(lua_State *L)
593 infostream<<"EnvRef::l_remove_node()"<<std::endl;
594 EnvRef *o = checkobject(L, 1);
595 ServerEnvironment *env = o->m_env;
596 if(env == NULL) return 0;
598 v3s16 pos = readpos(L, 2);
600 env->getMap().removeNodeWithEvent(pos);
604 // EnvRef:get_node(pos)
605 // pos = {x=num, y=num, z=num}
606 static int l_get_node(lua_State *L)
608 infostream<<"EnvRef::l_get_node()"<<std::endl;
609 EnvRef *o = checkobject(L, 1);
610 ServerEnvironment *env = o->m_env;
611 if(env == NULL) return 0;
613 v3s16 pos = readpos(L, 2);
615 MapNode n = env->getMap().getNodeNoEx(pos);
617 pushnode(L, n, env->getGameDef()->ndef());
621 // EnvRef:add_luaentity(pos, entityname)
622 // pos = {x=num, y=num, z=num}
623 static int l_add_luaentity(lua_State *L)
625 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
626 EnvRef *o = checkobject(L, 1);
627 ServerEnvironment *env = o->m_env;
628 if(env == NULL) return 0;
630 v3f pos = readFloatPos(L, 2);
632 const char *name = lua_tostring(L, 3);
634 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
635 env->addActiveObject(obj);
639 static int gc_object(lua_State *L) {
640 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
646 EnvRef(ServerEnvironment *env):
649 infostream<<"EnvRef created"<<std::endl;
654 infostream<<"EnvRef destructing"<<std::endl;
657 // Creates an EnvRef and leaves it on top of stack
658 // Not callable from Lua; all references are created on the C side.
659 static void create(lua_State *L, ServerEnvironment *env)
661 EnvRef *o = new EnvRef(env);
662 //infostream<<"EnvRef::create: o="<<o<<std::endl;
663 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
664 luaL_getmetatable(L, className);
665 lua_setmetatable(L, -2);
668 static void set_null(lua_State *L)
670 EnvRef *o = checkobject(L, -1);
674 static void Register(lua_State *L)
677 int methodtable = lua_gettop(L);
678 luaL_newmetatable(L, className);
679 int metatable = lua_gettop(L);
681 lua_pushliteral(L, "__metatable");
682 lua_pushvalue(L, methodtable);
683 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
685 lua_pushliteral(L, "__index");
686 lua_pushvalue(L, methodtable);
687 lua_settable(L, metatable);
689 lua_pushliteral(L, "__gc");
690 lua_pushcfunction(L, gc_object);
691 lua_settable(L, metatable);
693 lua_pop(L, 1); // drop metatable
695 luaL_openlib(L, 0, methods, 0); // fill methodtable
696 lua_pop(L, 1); // drop methodtable
698 // Cannot be created from Lua
699 //lua_register(L, className, create_object);
702 const char EnvRef::className[] = "EnvRef";
703 const luaL_reg EnvRef::methods[] = {
704 method(EnvRef, add_node),
705 method(EnvRef, remove_node),
706 method(EnvRef, get_node),
707 method(EnvRef, add_luaentity),
714 ServerActiveObject *m_object;
716 static const char className[];
717 static const luaL_reg methods[];
719 static ObjectRef *checkobject(lua_State *L, int narg)
721 luaL_checktype(L, narg, LUA_TUSERDATA);
722 void *ud = luaL_checkudata(L, narg, className);
723 if(!ud) luaL_typerror(L, narg, className);
724 return *(ObjectRef**)ud; // unbox pointer
727 static ServerActiveObject* getobject(ObjectRef *ref)
729 ServerActiveObject *co = ref->m_object;
733 static LuaEntitySAO* getluaobject(ObjectRef *ref)
735 ServerActiveObject *obj = getobject(ref);
738 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
740 return (LuaEntitySAO*)obj;
743 // Exported functions
746 static int gc_object(lua_State *L) {
747 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
748 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
754 static int l_remove(lua_State *L)
756 ObjectRef *ref = checkobject(L, 1);
757 ServerActiveObject *co = getobject(ref);
758 if(co == NULL) return 0;
759 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
760 co->m_removed = true;
765 // returns: {x=num, y=num, z=num}
766 static int l_getpos(lua_State *L)
768 ObjectRef *ref = checkobject(L, 1);
769 ServerActiveObject *co = getobject(ref);
770 if(co == NULL) return 0;
771 v3f pos = co->getBasePosition() / BS;
773 lua_pushnumber(L, pos.X);
774 lua_setfield(L, -2, "x");
775 lua_pushnumber(L, pos.Y);
776 lua_setfield(L, -2, "y");
777 lua_pushnumber(L, pos.Z);
778 lua_setfield(L, -2, "z");
783 static int l_setpos(lua_State *L)
785 ObjectRef *ref = checkobject(L, 1);
786 //LuaEntitySAO *co = getluaobject(ref);
787 ServerActiveObject *co = getobject(ref);
788 if(co == NULL) return 0;
790 v3f pos = readFloatPos(L, 2);
796 // moveto(self, pos, continuous=false)
797 static int l_moveto(lua_State *L)
799 ObjectRef *ref = checkobject(L, 1);
800 //LuaEntitySAO *co = getluaobject(ref);
801 ServerActiveObject *co = getobject(ref);
802 if(co == NULL) return 0;
804 v3f pos = readFloatPos(L, 2);
806 bool continuous = lua_toboolean(L, 3);
808 co->moveTo(pos, continuous);
812 // add_to_inventory(self, itemstring)
813 // returns: true if item was added, false otherwise
814 static int l_add_to_inventory(lua_State *L)
816 ObjectRef *ref = checkobject(L, 1);
817 luaL_checkstring(L, 2);
818 ServerActiveObject *co = getobject(ref);
819 if(co == NULL) return 0;
821 const char *itemstring = lua_tostring(L, 2);
822 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
823 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
825 std::istringstream is(itemstring, std::ios::binary);
826 ServerEnvironment *env = co->getEnv();
828 IGameDef *gamedef = env->getGameDef();
829 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
830 infostream<<"item="<<env<<std::endl;
831 bool fits = co->addToInventory(item);
833 lua_pushboolean(L, fits);
838 ObjectRef(ServerActiveObject *object):
841 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
847 infostream<<"ObjectRef destructing for id="
848 <<m_object->getId()<<std::endl;
850 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
853 // Creates an ObjectRef and leaves it on top of stack
854 // Not callable from Lua; all references are created on the C side.
855 static void create(lua_State *L, ServerActiveObject *object)
857 ObjectRef *o = new ObjectRef(object);
858 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
859 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
860 luaL_getmetatable(L, className);
861 lua_setmetatable(L, -2);
864 static void set_null(lua_State *L)
866 ObjectRef *o = checkobject(L, -1);
870 static void Register(lua_State *L)
873 int methodtable = lua_gettop(L);
874 luaL_newmetatable(L, className);
875 int metatable = lua_gettop(L);
877 lua_pushliteral(L, "__metatable");
878 lua_pushvalue(L, methodtable);
879 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
881 lua_pushliteral(L, "__index");
882 lua_pushvalue(L, methodtable);
883 lua_settable(L, metatable);
885 lua_pushliteral(L, "__gc");
886 lua_pushcfunction(L, gc_object);
887 lua_settable(L, metatable);
889 lua_pop(L, 1); // drop metatable
891 luaL_openlib(L, 0, methods, 0); // fill methodtable
892 lua_pop(L, 1); // drop methodtable
894 // Cannot be created from Lua
895 //lua_register(L, className, create_object);
898 const char ObjectRef::className[] = "ObjectRef";
899 const luaL_reg ObjectRef::methods[] = {
900 method(ObjectRef, remove),
901 method(ObjectRef, getpos),
902 method(ObjectRef, setpos),
903 method(ObjectRef, moveto),
904 method(ObjectRef, add_to_inventory),
908 // Creates a new anonymous reference if id=0
909 static void objectref_get_or_create(lua_State *L,
910 ServerActiveObject *cobj)
912 if(cobj->getId() == 0){
913 ObjectRef::create(L, cobj);
915 objectref_get(L, cobj->getId());
923 void scriptapi_export(lua_State *L, Server *server)
926 assert(lua_checkstack(L, 20));
927 infostream<<"scriptapi_export"<<std::endl;
928 StackUnroller stack_unroller(L);
930 // Store server as light userdata in registry
931 lua_pushlightuserdata(L, server);
932 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
934 // Register global functions in table minetest
936 luaL_register(L, NULL, minetest_f);
937 lua_setglobal(L, "minetest");
939 // Get the main minetest table
940 lua_getglobal(L, "minetest");
942 // Add tables to minetest
945 lua_setfield(L, -2, "registered_blocks");*/
948 lua_setfield(L, -2, "registered_entities");
951 lua_setfield(L, -2, "registered_globalsteps");
954 lua_setfield(L, -2, "registered_on_placenodes");
957 lua_setfield(L, -2, "registered_on_dignodes");
960 lua_setfield(L, -2, "object_refs");
963 lua_setfield(L, -2, "luaentities");
965 // Create entity prototype
966 luaL_newmetatable(L, "minetest.entity");
967 // metatable.__index = metatable
968 lua_pushvalue(L, -1); // Duplicate metatable
969 lua_setfield(L, -2, "__index");
970 // Put functions in metatable
971 luaL_register(L, NULL, minetest_entity_m);
972 // Put other stuff in metatable
974 // Environment C reference
977 // Object C reference
978 ObjectRef::Register(L);
981 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
984 assert(lua_checkstack(L, 20));
985 infostream<<"scriptapi_add_environment"<<std::endl;
986 StackUnroller stack_unroller(L);
988 // Create EnvRef on stack
989 EnvRef::create(L, env);
990 int envref = lua_gettop(L);
992 // minetest.env = envref
993 lua_getglobal(L, "minetest");
994 luaL_checktype(L, -1, LUA_TTABLE);
995 lua_pushvalue(L, envref);
996 lua_setfield(L, -2, "env");
1000 // Dump stack top with the dump2 function
1001 static void dump2(lua_State *L, const char *name)
1003 // Dump object (debug)
1004 lua_getglobal(L, "dump2");
1005 luaL_checktype(L, -1, LUA_TFUNCTION);
1006 lua_pushvalue(L, -2); // Get previous stack top as first parameter
1007 lua_pushstring(L, name);
1008 if(lua_pcall(L, 2, 0, 0))
1009 script_error(L, "error: %s\n", lua_tostring(L, -1));
1017 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1020 assert(lua_checkstack(L, 20));
1021 infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1022 StackUnroller stack_unroller(L);
1024 // Create object on stack
1025 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1026 int object = lua_gettop(L);
1028 // Get minetest.object_refs table
1029 lua_getglobal(L, "minetest");
1030 lua_getfield(L, -1, "object_refs");
1031 luaL_checktype(L, -1, LUA_TTABLE);
1032 int objectstable = lua_gettop(L);
1034 // object_refs[id] = object
1035 lua_pushnumber(L, cobj->getId()); // Push id
1036 lua_pushvalue(L, object); // Copy object to top of stack
1037 lua_settable(L, objectstable);
1040 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1043 assert(lua_checkstack(L, 20));
1044 infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1045 StackUnroller stack_unroller(L);
1047 // Get minetest.object_refs table
1048 lua_getglobal(L, "minetest");
1049 lua_getfield(L, -1, "object_refs");
1050 luaL_checktype(L, -1, LUA_TTABLE);
1051 int objectstable = lua_gettop(L);
1053 // Get object_refs[id]
1054 lua_pushnumber(L, cobj->getId()); // Push id
1055 lua_gettable(L, objectstable);
1056 // Set object reference to NULL
1057 ObjectRef::set_null(L);
1058 lua_pop(L, 1); // pop object
1060 // Set object_refs[id] = nil
1061 lua_pushnumber(L, cobj->getId()); // Push id
1063 lua_settable(L, objectstable);
1070 void scriptapi_environment_step(lua_State *L, float dtime)
1073 assert(lua_checkstack(L, 20));
1074 //infostream<<"scriptapi_environment_step"<<std::endl;
1075 StackUnroller stack_unroller(L);
1077 // Get minetest.registered_globalsteps
1078 lua_getglobal(L, "minetest");
1079 lua_getfield(L, -1, "registered_globalsteps");
1080 luaL_checktype(L, -1, LUA_TTABLE);
1081 int table = lua_gettop(L);
1084 while(lua_next(L, table) != 0){
1085 // key at index -2 and value at index -1
1086 luaL_checktype(L, -1, LUA_TFUNCTION);
1088 lua_pushnumber(L, dtime);
1089 if(lua_pcall(L, 1, 0, 0))
1090 script_error(L, "error: %s\n", lua_tostring(L, -1));
1091 // value removed, keep key for next iteration
1095 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode)
1098 assert(lua_checkstack(L, 20));
1099 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1100 StackUnroller stack_unroller(L);
1102 // Get server from registry
1103 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1104 Server *server = (Server*)lua_touserdata(L, -1);
1105 // And get the writable node definition manager from the server
1106 IWritableNodeDefManager *ndef =
1107 server->getWritableNodeDefManager();
1109 // Get minetest.registered_on_placenodes
1110 lua_getglobal(L, "minetest");
1111 lua_getfield(L, -1, "registered_on_placenodes");
1112 luaL_checktype(L, -1, LUA_TTABLE);
1113 int table = lua_gettop(L);
1116 while(lua_next(L, table) != 0){
1117 // key at index -2 and value at index -1
1118 luaL_checktype(L, -1, LUA_TFUNCTION);
1121 pushnode(L, newnode, ndef);
1122 if(lua_pcall(L, 2, 0, 0))
1123 script_error(L, "error: %s\n", lua_tostring(L, -1));
1124 // value removed, keep key for next iteration
1128 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode)
1131 assert(lua_checkstack(L, 20));
1132 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1133 StackUnroller stack_unroller(L);
1135 // Get server from registry
1136 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1137 Server *server = (Server*)lua_touserdata(L, -1);
1138 // And get the writable node definition manager from the server
1139 IWritableNodeDefManager *ndef =
1140 server->getWritableNodeDefManager();
1142 // Get minetest.registered_on_dignodes
1143 lua_getglobal(L, "minetest");
1144 lua_getfield(L, -1, "registered_on_dignodes");
1145 luaL_checktype(L, -1, LUA_TTABLE);
1146 int table = lua_gettop(L);
1149 while(lua_next(L, table) != 0){
1150 // key at index -2 and value at index -1
1151 luaL_checktype(L, -1, LUA_TFUNCTION);
1154 pushnode(L, oldnode, ndef);
1155 if(lua_pcall(L, 2, 0, 0))
1156 script_error(L, "error: %s\n", lua_tostring(L, -1));
1157 // value removed, keep key for next iteration
1165 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1166 const char *init_state)
1169 assert(lua_checkstack(L, 20));
1170 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1171 <<name<<"\""<<std::endl;
1172 StackUnroller stack_unroller(L);
1174 // Create object as a dummy string (TODO: Create properly)
1176 // Get minetest.registered_entities[name]
1177 lua_getglobal(L, "minetest");
1178 lua_getfield(L, -1, "registered_entities");
1179 luaL_checktype(L, -1, LUA_TTABLE);
1180 lua_pushstring(L, name);
1181 lua_gettable(L, -2);
1182 // Should be a table, which we will use as a prototype
1183 //luaL_checktype(L, -1, LUA_TTABLE);
1184 if(lua_type(L, -1) != LUA_TTABLE){
1185 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1188 int prototype_table = lua_gettop(L);
1189 //dump2(L, "prototype_table");
1191 // Create entity object
1193 int object = lua_gettop(L);
1195 // Set object metatable
1196 lua_pushvalue(L, prototype_table);
1197 lua_setmetatable(L, -2);
1199 // Add object reference
1200 // This should be userdata with metatable ObjectRef
1201 objectref_get(L, id);
1202 luaL_checktype(L, -1, LUA_TUSERDATA);
1203 if(!luaL_checkudata(L, -1, "ObjectRef"))
1204 luaL_typerror(L, -1, "ObjectRef");
1205 lua_setfield(L, -2, "object");
1207 // minetest.luaentities[id] = object
1208 lua_getglobal(L, "minetest");
1209 lua_getfield(L, -1, "luaentities");
1210 luaL_checktype(L, -1, LUA_TTABLE);
1211 lua_pushnumber(L, id); // Push id
1212 lua_pushvalue(L, object); // Copy object to top of stack
1213 lua_settable(L, -3);
1215 // This callback doesn't really make sense
1216 /*// Get on_activate function
1217 lua_pushvalue(L, object);
1218 lua_getfield(L, -1, "on_activate");
1219 luaL_checktype(L, -1, LUA_TFUNCTION);
1220 lua_pushvalue(L, object); // self
1221 // Call with 1 arguments, 0 results
1222 if(lua_pcall(L, 1, 0, 0))
1223 script_error(L, "error running function %s:on_activate: %s\n",
1224 name, lua_tostring(L, -1));*/
1229 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1232 assert(lua_checkstack(L, 20));
1233 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1235 // Get minetest.luaentities table
1236 lua_getglobal(L, "minetest");
1237 lua_getfield(L, -1, "luaentities");
1238 luaL_checktype(L, -1, LUA_TTABLE);
1239 int objectstable = lua_gettop(L);
1241 // Set luaentities[id] = nil
1242 lua_pushnumber(L, id); // Push id
1244 lua_settable(L, objectstable);
1246 lua_pop(L, 2); // pop luaentities, minetest
1249 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
1252 assert(lua_checkstack(L, 20));
1253 infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
1258 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1259 LuaEntityProperties *prop)
1262 assert(lua_checkstack(L, 20));
1263 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1264 StackUnroller stack_unroller(L);
1266 // Get minetest.luaentities[id]
1267 luaentity_get(L, id);
1268 //int object = lua_gettop(L);
1270 lua_getfield(L, -1, "physical");
1271 if(lua_isboolean(L, -1))
1272 prop->physical = lua_toboolean(L, -1);
1275 lua_getfield(L, -1, "weight");
1276 prop->weight = lua_tonumber(L, -1);
1279 lua_getfield(L, -1, "collisionbox");
1280 if(lua_istable(L, -1)){
1281 lua_rawgeti(L, -1, 1);
1282 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
1284 lua_rawgeti(L, -1, 2);
1285 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1287 lua_rawgeti(L, -1, 3);
1288 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1290 lua_rawgeti(L, -1, 4);
1291 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1293 lua_rawgeti(L, -1, 5);
1294 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1296 lua_rawgeti(L, -1, 6);
1297 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1302 lua_getfield(L, -1, "visual");
1303 if(lua_isstring(L, -1))
1304 prop->visual = lua_tostring(L, -1);
1307 lua_getfield(L, -1, "textures");
1308 if(lua_istable(L, -1)){
1309 prop->textures.clear();
1310 int table = lua_gettop(L);
1312 while(lua_next(L, table) != 0){
1313 // key at index -2 and value at index -1
1314 if(lua_isstring(L, -1))
1315 prop->textures.push_back(lua_tostring(L, -1));
1317 prop->textures.push_back("");
1318 // removes value, keeps key for next iteration
1326 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1329 assert(lua_checkstack(L, 20));
1330 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1331 StackUnroller stack_unroller(L);
1333 // Get minetest.luaentities[id]
1334 luaentity_get(L, id);
1335 int object = lua_gettop(L);
1336 // State: object is at top of stack
1337 // Get step function
1338 lua_getfield(L, -1, "on_step");
1339 if(lua_isnil(L, -1))
1341 luaL_checktype(L, -1, LUA_TFUNCTION);
1342 lua_pushvalue(L, object); // self
1343 lua_pushnumber(L, dtime); // dtime
1344 // Call with 2 arguments, 0 results
1345 if(lua_pcall(L, 2, 0, 0))
1346 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
1349 // Calls entity:on_punch(ObjectRef puncher)
1350 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1351 ServerActiveObject *puncher)
1354 assert(lua_checkstack(L, 20));
1355 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1356 StackUnroller stack_unroller(L);
1358 // Get minetest.luaentities[id]
1359 luaentity_get(L, id);
1360 int object = lua_gettop(L);
1361 // State: object is at top of stack
1363 lua_getfield(L, -1, "on_punch");
1364 if(lua_isnil(L, -1))
1366 luaL_checktype(L, -1, LUA_TFUNCTION);
1367 lua_pushvalue(L, object); // self
1368 objectref_get_or_create(L, puncher); // Clicker reference
1369 // Call with 2 arguments, 0 results
1370 if(lua_pcall(L, 2, 0, 0))
1371 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1374 // Calls entity:on_rightclick(ObjectRef clicker)
1375 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1376 ServerActiveObject *clicker)
1379 assert(lua_checkstack(L, 20));
1380 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1381 StackUnroller stack_unroller(L);
1383 // Get minetest.luaentities[id]
1384 luaentity_get(L, id);
1385 int object = lua_gettop(L);
1386 // State: object is at top of stack
1388 lua_getfield(L, -1, "on_rightclick");
1389 if(lua_isnil(L, -1))
1391 luaL_checktype(L, -1, LUA_TFUNCTION);
1392 lua_pushvalue(L, object); // self
1393 objectref_get_or_create(L, clicker); // Clicker reference
1394 // Call with 2 arguments, 0 results
1395 if(lua_pcall(L, 2, 0, 0))
1396 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));