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 v3f readFloatPos(lua_State *L, int index)
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);
134 lua_getfield(L, -1, "y");
135 pos.Y = lua_tonumber(L, -1);
137 lua_getfield(L, -1, "z");
138 pos.Z = lua_tonumber(L, -1);
140 lua_pop(L, 1); // Pop pos
141 pos *= BS; // Scale to internal format
149 // Register new object prototype
150 // register_entity(name, prototype)
151 static int l_register_entity(lua_State *L)
153 const char *name = luaL_checkstring(L, 1);
154 infostream<<"register_entity: "<<name<<std::endl;
155 luaL_checktype(L, 2, LUA_TTABLE);
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);
166 // Get registered object to top of stack
169 // Set __index to point to itself
170 lua_pushvalue(L, -1);
171 lua_setfield(L, -2, "__index");
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);
180 return 0; /* number of results */
183 // Register a global step function
184 // register_globalstep(function)
185 static int l_register_globalstep(lua_State *L)
187 luaL_checktype(L, 1, LUA_TFUNCTION);
188 infostream<<"register_globalstep"<<std::endl;
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
203 if(lua_pcall(L, 2, 0, 0))
204 script_error(L, "error: %s\n", lua_tostring(L, -1));
206 return 0; /* number of results */
209 // register_tool(name, {lots of stuff})
210 static int l_register_tool(lua_State *L)
212 const char *name = luaL_checkstring(L, 1);
213 infostream<<"register_tool: "<<name<<std::endl;
214 luaL_checktype(L, 2, LUA_TTABLE);
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();
226 lua_getfield(L, table, "image");
227 if(lua_isstring(L, -1))
228 def.imagename = lua_tostring(L, -1);
231 lua_getfield(L, table, "basetime");
232 def.properties.basetime = lua_tonumber(L, -1);
235 lua_getfield(L, table, "dt_weight");
236 def.properties.dt_weight = lua_tonumber(L, -1);
239 lua_getfield(L, table, "dt_crackiness");
240 def.properties.dt_crackiness = lua_tonumber(L, -1);
243 lua_getfield(L, table, "dt_crumbliness");
244 def.properties.dt_crumbliness = lua_tonumber(L, -1);
247 lua_getfield(L, table, "dt_cuttability");
248 def.properties.dt_cuttability = lua_tonumber(L, -1);
251 lua_getfield(L, table, "basedurability");
252 def.properties.basedurability = lua_tonumber(L, -1);
255 lua_getfield(L, table, "dd_weight");
256 def.properties.dd_weight = lua_tonumber(L, -1);
259 lua_getfield(L, table, "dd_crackiness");
260 def.properties.dd_crackiness = lua_tonumber(L, -1);
263 lua_getfield(L, table, "dd_crumbliness");
264 def.properties.dd_crumbliness = lua_tonumber(L, -1);
267 lua_getfield(L, table, "dd_cuttability");
268 def.properties.dd_cuttability = lua_tonumber(L, -1);
271 tooldef->registerTool(name, def);
272 return 0; /* number of results */
275 // register_node(name, {lots of stuff})
276 static int l_register_node(lua_State *L)
278 const char *name = luaL_checkstring(L, 1);
279 infostream<<"register_node: "<<name<<std::endl;
280 luaL_checktype(L, 2, LUA_TTABLE);
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();
293 lua_getfield(L, table0, "tile_images");
294 if(lua_istable(L, -1)){
295 int table = lua_gettop(L);
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);
303 f.tname_tiles[i] = "";
304 // removes value, keeps key for next iteration
315 lua_getfield(L, table0, "inventory_image");
316 if(lua_isstring(L, -1))
317 f.tname_inventory = lua_tostring(L, -1);
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;
328 nodedef->set(name, f);
329 return 0; /* number of results */
332 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
333 static int l_register_craft(lua_State *L)
335 infostream<<"register_craft"<<std::endl;
336 luaL_checktype(L, 1, LUA_TTABLE);
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();
348 std::vector<std::string> input;
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);
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);
362 while(lua_next(L, table1) != 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);
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
381 if(colcount != width){
382 script_error(L, "error: %s\n", "Invalid crafting recipe");
385 // removes value, keeps key for next iteration
392 CraftDefinition def(output, width, input);
393 craftdef->registerCraft(def);
395 return 0; /* number of results */
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},
411 static const struct luaL_Reg minetest_entity_m [] = {
416 Getters for stuff in main tables
419 static void objectref_get(lua_State *L, u16 id)
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);
427 lua_remove(L, -2); // object_refs
428 lua_remove(L, -2); // minetest
431 static void luaentity_get(lua_State *L, u16 id)
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);
439 lua_remove(L, -2); // luaentities
440 lua_remove(L, -2); // minetest
446 #define method(class, name) {#name, class::l_##name}
451 ServerEnvironment *m_env;
453 static const char className[];
454 static const luaL_reg methods[];
456 static EnvRef *checkobject(lua_State *L, int narg)
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
464 // Exported functions
466 // EnvRef:add_node(pos, content)
467 // pos = {x=num, y=num, z=num}
469 static int l_add_node(lua_State *L)
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;
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);
482 lua_getfield(L, -1, "y");
483 pos.Y = lua_tonumber(L, -1);
485 lua_getfield(L, -1, "z");
486 pos.Z = lua_tonumber(L, -1);
488 lua_pop(L, 1); // Pop pos
491 lua_pushvalue(L, 3); // Push content
492 content = lua_tonumber(L, -1);
493 lua_pop(L, 1); // Pop content
495 env->getMap().addNodeWithEvent(pos, MapNode(content));
499 static int gc_object(lua_State *L) {
500 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
506 EnvRef(ServerEnvironment *env):
509 infostream<<"EnvRef created"<<std::endl;
514 infostream<<"EnvRef destructing"<<std::endl;
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)
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);
528 static void set_null(lua_State *L)
530 EnvRef *o = checkobject(L, -1);
534 static void Register(lua_State *L)
537 int methodtable = lua_gettop(L);
538 luaL_newmetatable(L, className);
539 int metatable = lua_gettop(L);
541 lua_pushliteral(L, "__metatable");
542 lua_pushvalue(L, methodtable);
543 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
545 lua_pushliteral(L, "__index");
546 lua_pushvalue(L, methodtable);
547 lua_settable(L, metatable);
549 lua_pushliteral(L, "__gc");
550 lua_pushcfunction(L, gc_object);
551 lua_settable(L, metatable);
553 lua_pop(L, 1); // drop metatable
555 luaL_openlib(L, 0, methods, 0); // fill methodtable
556 lua_pop(L, 1); // drop methodtable
558 // Cannot be created from Lua
559 //lua_register(L, className, create_object);
562 const char EnvRef::className[] = "EnvRef";
563 const luaL_reg EnvRef::methods[] = {
564 method(EnvRef, add_node),
571 ServerActiveObject *m_object;
573 static const char className[];
574 static const luaL_reg methods[];
576 static ObjectRef *checkobject(lua_State *L, int narg)
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
584 static ServerActiveObject* getobject(ObjectRef *ref)
586 ServerActiveObject *co = ref->m_object;
590 static LuaEntitySAO* getluaobject(ObjectRef *ref)
592 ServerActiveObject *obj = getobject(ref);
595 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
597 return (LuaEntitySAO*)obj;
600 // Exported functions
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;
611 static int l_remove(lua_State *L)
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;
622 // returns: {x=num, y=num, z=num}
623 static int l_getpos(lua_State *L)
625 ObjectRef *ref = checkobject(L, 1);
626 ServerActiveObject *co = getobject(ref);
627 if(co == NULL) return 0;
628 v3f pos = co->getBasePosition() / BS;
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");
640 static int l_setpos(lua_State *L)
642 ObjectRef *ref = checkobject(L, 1);
643 //LuaEntitySAO *co = getluaobject(ref);
644 ServerActiveObject *co = getobject(ref);
645 if(co == NULL) return 0;
647 v3f pos = readFloatPos(L, 2);
653 // moveto(self, pos, continuous=false)
654 static int l_moveto(lua_State *L)
656 ObjectRef *ref = checkobject(L, 1);
657 //LuaEntitySAO *co = getluaobject(ref);
658 ServerActiveObject *co = getobject(ref);
659 if(co == NULL) return 0;
661 v3f pos = readFloatPos(L, 2);
663 bool continuous = lua_toboolean(L, 3);
665 co->moveTo(pos, continuous);
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)
673 ObjectRef *ref = checkobject(L, 1);
674 luaL_checkstring(L, 2);
675 ServerActiveObject *co = getobject(ref);
676 if(co == NULL) return 0;
678 const char *itemstring = lua_tostring(L, 2);
679 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
680 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
682 std::istringstream is(itemstring, std::ios::binary);
683 ServerEnvironment *env = co->getEnv();
685 IGameDef *gamedef = env->getGameDef();
686 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
687 infostream<<"item="<<env<<std::endl;
688 bool fits = co->addToInventory(item);
690 lua_pushboolean(L, fits);
695 ObjectRef(ServerActiveObject *object):
698 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
704 infostream<<"ObjectRef destructing for id="
705 <<m_object->getId()<<std::endl;
707 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
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)
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);
721 static void set_null(lua_State *L)
723 ObjectRef *o = checkobject(L, -1);
727 static void Register(lua_State *L)
730 int methodtable = lua_gettop(L);
731 luaL_newmetatable(L, className);
732 int metatable = lua_gettop(L);
734 lua_pushliteral(L, "__metatable");
735 lua_pushvalue(L, methodtable);
736 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
738 lua_pushliteral(L, "__index");
739 lua_pushvalue(L, methodtable);
740 lua_settable(L, metatable);
742 lua_pushliteral(L, "__gc");
743 lua_pushcfunction(L, gc_object);
744 lua_settable(L, metatable);
746 lua_pop(L, 1); // drop metatable
748 luaL_openlib(L, 0, methods, 0); // fill methodtable
749 lua_pop(L, 1); // drop methodtable
751 // Cannot be created from Lua
752 //lua_register(L, className, create_object);
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),
765 // Creates a new anonymous reference if id=0
766 static void objectref_get_or_create(lua_State *L,
767 ServerActiveObject *cobj)
769 if(cobj->getId() == 0){
770 ObjectRef::create(L, cobj);
772 objectref_get(L, cobj->getId());
780 void scriptapi_export(lua_State *L, Server *server)
783 assert(lua_checkstack(L, 20));
784 infostream<<"scriptapi_export"<<std::endl;
785 StackUnroller stack_unroller(L);
787 // Store server as light userdata in registry
788 lua_pushlightuserdata(L, server);
789 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
791 // Register global functions in table minetest
793 luaL_register(L, NULL, minetest_f);
794 lua_setglobal(L, "minetest");
796 // Get the main minetest table
797 lua_getglobal(L, "minetest");
799 // Add tables to minetest
802 lua_setfield(L, -2, "registered_blocks");*/
805 lua_setfield(L, -2, "registered_entities");
808 lua_setfield(L, -2, "registered_globalsteps");
811 lua_setfield(L, -2, "object_refs");
814 lua_setfield(L, -2, "luaentities");
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
825 // Environment C reference
828 // Object C reference
829 ObjectRef::Register(L);
832 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
835 assert(lua_checkstack(L, 20));
836 infostream<<"scriptapi_add_environment"<<std::endl;
837 StackUnroller stack_unroller(L);
839 // Create EnvRef on stack
840 EnvRef::create(L, env);
841 int envref = lua_gettop(L);
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");
851 // Dump stack top with the dump2 function
852 static void dump2(lua_State *L, const char *name)
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));
868 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
871 assert(lua_checkstack(L, 20));
872 infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
873 StackUnroller stack_unroller(L);
875 // Create object on stack
876 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
877 int object = lua_gettop(L);
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);
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);
891 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
894 assert(lua_checkstack(L, 20));
895 infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
896 StackUnroller stack_unroller(L);
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);
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
911 // Set object_refs[id] = nil
912 lua_pushnumber(L, cobj->getId()); // Push id
914 lua_settable(L, objectstable);
921 void scriptapi_environment_step(lua_State *L, float dtime)
924 assert(lua_checkstack(L, 20));
925 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
926 StackUnroller stack_unroller(L);
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);
935 while(lua_next(L, table) != 0){
936 // key at index -2 and value at index -1
937 luaL_checktype(L, -1, LUA_TFUNCTION);
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
950 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
951 const char *init_state)
954 assert(lua_checkstack(L, 20));
955 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
956 <<name<<"\""<<std::endl;
957 StackUnroller stack_unroller(L);
959 // Create object as a dummy string (TODO: Create properly)
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);
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;
973 int prototype_table = lua_gettop(L);
974 //dump2(L, "prototype_table");
976 // Create entity object
978 int object = lua_gettop(L);
980 // Set object metatable
981 lua_pushvalue(L, prototype_table);
982 lua_setmetatable(L, -2);
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");
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
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));*/
1014 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1017 assert(lua_checkstack(L, 20));
1018 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
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);
1026 // Set luaentities[id] = nil
1027 lua_pushnumber(L, id); // Push id
1029 lua_settable(L, objectstable);
1031 lua_pop(L, 2); // pop luaentities, minetest
1034 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
1037 assert(lua_checkstack(L, 20));
1038 infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
1043 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1044 LuaEntityProperties *prop)
1047 assert(lua_checkstack(L, 20));
1048 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1049 StackUnroller stack_unroller(L);
1051 // Get minetest.luaentities[id]
1052 luaentity_get(L, id);
1053 //int object = lua_gettop(L);
1055 lua_getfield(L, -1, "physical");
1056 if(lua_isboolean(L, -1))
1057 prop->physical = lua_toboolean(L, -1);
1060 lua_getfield(L, -1, "weight");
1061 prop->weight = lua_tonumber(L, -1);
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);
1069 lua_rawgeti(L, -1, 2);
1070 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1072 lua_rawgeti(L, -1, 3);
1073 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1075 lua_rawgeti(L, -1, 4);
1076 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1078 lua_rawgeti(L, -1, 5);
1079 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1081 lua_rawgeti(L, -1, 6);
1082 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1087 lua_getfield(L, -1, "visual");
1088 if(lua_isstring(L, -1))
1089 prop->visual = lua_tostring(L, -1);
1092 lua_getfield(L, -1, "textures");
1093 if(lua_istable(L, -1)){
1094 prop->textures.clear();
1095 int table = lua_gettop(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));
1102 prop->textures.push_back("");
1103 // removes value, keeps key for next iteration
1111 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1114 assert(lua_checkstack(L, 20));
1115 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1116 StackUnroller stack_unroller(L);
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));
1132 // Calls entity:on_punch(ObjectRef puncher)
1133 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1134 ServerActiveObject *puncher)
1137 assert(lua_checkstack(L, 20));
1138 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1139 StackUnroller stack_unroller(L);
1141 // Get minetest.luaentities[id]
1142 luaentity_get(L, id);
1143 int object = lua_gettop(L);
1144 // State: object is at top of stack
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));
1155 // Calls entity:on_rightclick(ObjectRef clicker)
1156 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1157 ServerActiveObject *clicker)
1160 assert(lua_checkstack(L, 20));
1161 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1162 StackUnroller stack_unroller(L);
1164 // Get minetest.luaentities[id]
1165 luaentity_get(L, id);
1166 int object = lua_gettop(L);
1167 // State: object is at top of stack
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));