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
43 - Random node triggers
44 - Object visual client-side stuff
46 - Spritesheets and animation
47 - Named node types and dynamic id allocation per MapBlock
49 blockdef.has_metadata = true/false
50 - Stores an inventory and stuff in a Settings object
51 meta.inventory_add_list("main")
52 blockdef.on_inventory_modified
53 meta.set("owner", playername)
58 static void stackDump(lua_State *L, std::ostream &o)
61 int top = lua_gettop(L);
62 for (i = 1; i <= top; i++) { /* repeat for each level */
63 int t = lua_type(L, i);
66 case LUA_TSTRING: /* strings */
67 o<<"\""<<lua_tostring(L, i)<<"\"";
70 case LUA_TBOOLEAN: /* booleans */
71 o<<(lua_toboolean(L, i) ? "true" : "false");
74 case LUA_TNUMBER: /* numbers */ {
76 snprintf(buf, 10, "%g", lua_tonumber(L, i));
80 default: /* other values */
81 o<<lua_typename(L, t);
90 static void realitycheck(lua_State *L)
92 int top = lua_gettop(L);
94 dstream<<"Stack is over 30:"<<std::endl;
95 stackDump(L, dstream);
96 script_error(L, "Stack is over 30 (reality check)");
106 StackUnroller(lua_State *L):
110 m_original_top = lua_gettop(m_lua); // store stack height
114 lua_settop(m_lua, m_original_top); // restore stack height
118 v3f readFloatPos(lua_State *L, int index)
121 lua_pushvalue(L, index); // Push pos
122 luaL_checktype(L, -1, LUA_TTABLE);
123 lua_getfield(L, -1, "x");
124 pos.X = lua_tonumber(L, -1);
126 lua_getfield(L, -1, "y");
127 pos.Y = lua_tonumber(L, -1);
129 lua_getfield(L, -1, "z");
130 pos.Z = lua_tonumber(L, -1);
132 lua_pop(L, 1); // Pop pos
133 pos *= BS; // Scale to internal format
141 // Register new object prototype
142 // register_entity(name, prototype)
143 static int l_register_entity(lua_State *L)
145 const char *name = luaL_checkstring(L, 1);
146 infostream<<"register_entity: "<<name<<std::endl;
147 luaL_checktype(L, 2, LUA_TTABLE);
149 // Get minetest.registered_entities
150 lua_getglobal(L, "minetest");
151 lua_getfield(L, -1, "registered_entities");
152 luaL_checktype(L, -1, LUA_TTABLE);
153 int registered_entities = lua_gettop(L);
154 lua_pushvalue(L, 2); // Object = param 2 -> stack top
155 // registered_entities[name] = object
156 lua_setfield(L, registered_entities, name);
158 // Get registered object to top of stack
161 // Set __index to point to itself
162 lua_pushvalue(L, -1);
163 lua_setfield(L, -2, "__index");
165 // Set metatable.__index = metatable
166 luaL_getmetatable(L, "minetest.entity");
167 lua_pushvalue(L, -1); // duplicate metatable
168 lua_setfield(L, -2, "__index");
169 // Set object metatable
170 lua_setmetatable(L, -2);
172 return 0; /* number of results */
175 // Register a global step function
176 // register_globalstep(function)
177 static int l_register_globalstep(lua_State *L)
179 luaL_checktype(L, 1, LUA_TFUNCTION);
180 infostream<<"register_globalstep"<<std::endl;
182 lua_getglobal(L, "table");
183 lua_getfield(L, -1, "insert");
184 int table_insert = lua_gettop(L);
185 // Get minetest.registered_globalsteps
186 lua_getglobal(L, "minetest");
187 lua_getfield(L, -1, "registered_globalsteps");
188 luaL_checktype(L, -1, LUA_TTABLE);
189 int registered_globalsteps = lua_gettop(L);
190 // table.insert(registered_globalsteps, func)
191 lua_pushvalue(L, table_insert);
192 lua_pushvalue(L, registered_globalsteps);
193 lua_pushvalue(L, 1); // push function from argument 1
195 if(lua_pcall(L, 2, 0, 0))
196 script_error(L, "error: %s\n", lua_tostring(L, -1));
198 return 0; /* number of results */
202 // Clear all registered tools
203 // deregister_tools()
204 static int l_deregister_tools(lua_State *L)
206 infostream<<"deregister_tools"<<std::endl;
208 // Get server from registry
209 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
210 Server *server = (Server*)lua_touserdata(L, -1);
211 // And get the writable tool definition manager from the server
212 IWritableToolDefManager *tooldef =
213 server->getWritableToolDefManager();
217 return 0; /* number of results */
221 // register_tool(name, {lots of stuff})
222 static int l_register_tool(lua_State *L)
224 const char *name = luaL_checkstring(L, 1);
225 infostream<<"register_tool: "<<name<<std::endl;
226 luaL_checktype(L, 2, LUA_TTABLE);
228 // Get server from registry
229 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
230 Server *server = (Server*)lua_touserdata(L, -1);
231 // And get the writable tool definition manager from the server
232 IWritableToolDefManager *tooldef =
233 server->getWritableToolDefManager();
239 lua_getfield(L, table, "image");
240 if(lua_isstring(L, -1))
241 def.imagename = lua_tostring(L, -1);
244 lua_getfield(L, table, "basetime");
245 def.properties.basetime = lua_tonumber(L, -1);
248 lua_getfield(L, table, "dt_weight");
249 def.properties.dt_weight = lua_tonumber(L, -1);
252 lua_getfield(L, table, "dt_crackiness");
253 def.properties.dt_crackiness = lua_tonumber(L, -1);
256 lua_getfield(L, table, "dt_crumbliness");
257 def.properties.dt_crumbliness = lua_tonumber(L, -1);
260 lua_getfield(L, table, "dt_cuttability");
261 def.properties.dt_cuttability = lua_tonumber(L, -1);
264 lua_getfield(L, table, "basedurability");
265 def.properties.basedurability = lua_tonumber(L, -1);
268 lua_getfield(L, table, "dd_weight");
269 def.properties.dd_weight = lua_tonumber(L, -1);
272 lua_getfield(L, table, "dd_crackiness");
273 def.properties.dd_crackiness = lua_tonumber(L, -1);
276 lua_getfield(L, table, "dd_crumbliness");
277 def.properties.dd_crumbliness = lua_tonumber(L, -1);
280 lua_getfield(L, table, "dd_cuttability");
281 def.properties.dd_cuttability = lua_tonumber(L, -1);
284 tooldef->registerTool(name, def);
286 return 0; /* number of results */
289 static const struct luaL_Reg minetest_f [] = {
290 {"register_entity", l_register_entity},
291 {"register_globalstep", l_register_globalstep},
292 //{"deregister_tools", l_deregister_tools},
293 {"register_tool", l_register_tool},
301 static const struct luaL_Reg minetest_entity_m [] = {
306 Getters for stuff in main tables
309 static void objectref_get(lua_State *L, u16 id)
311 // Get minetest.object_refs[i]
312 lua_getglobal(L, "minetest");
313 lua_getfield(L, -1, "object_refs");
314 luaL_checktype(L, -1, LUA_TTABLE);
315 lua_pushnumber(L, id);
317 lua_remove(L, -2); // object_refs
318 lua_remove(L, -2); // minetest
321 static void luaentity_get(lua_State *L, u16 id)
323 // Get minetest.luaentities[i]
324 lua_getglobal(L, "minetest");
325 lua_getfield(L, -1, "luaentities");
326 luaL_checktype(L, -1, LUA_TTABLE);
327 lua_pushnumber(L, id);
329 lua_remove(L, -2); // luaentities
330 lua_remove(L, -2); // minetest
336 #define method(class, name) {#name, class::l_##name}
341 ServerEnvironment *m_env;
343 static const char className[];
344 static const luaL_reg methods[];
346 static EnvRef *checkobject(lua_State *L, int narg)
348 luaL_checktype(L, narg, LUA_TUSERDATA);
349 void *ud = luaL_checkudata(L, narg, className);
350 if(!ud) luaL_typerror(L, narg, className);
351 return *(EnvRef**)ud; // unbox pointer
354 // Exported functions
356 // EnvRef:add_node(pos, content)
357 // pos = {x=num, y=num, z=num}
359 static int l_add_node(lua_State *L)
361 infostream<<"EnvRef::l_add_node()"<<std::endl;
362 EnvRef *o = checkobject(L, 1);
363 ServerEnvironment *env = o->m_env;
364 if(env == NULL) return 0;
367 lua_pushvalue(L, 2); // Push pos
368 luaL_checktype(L, -1, LUA_TTABLE);
369 lua_getfield(L, -1, "x");
370 pos.X = lua_tonumber(L, -1);
372 lua_getfield(L, -1, "y");
373 pos.Y = lua_tonumber(L, -1);
375 lua_getfield(L, -1, "z");
376 pos.Z = lua_tonumber(L, -1);
378 lua_pop(L, 1); // Pop pos
381 lua_pushvalue(L, 3); // Push content
382 content = lua_tonumber(L, -1);
383 lua_pop(L, 1); // Pop content
385 env->getMap().addNodeWithEvent(pos, MapNode(content));
389 static int gc_object(lua_State *L) {
390 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
396 EnvRef(ServerEnvironment *env):
399 infostream<<"EnvRef created"<<std::endl;
404 infostream<<"EnvRef destructing"<<std::endl;
407 // Creates an EnvRef and leaves it on top of stack
408 // Not callable from Lua; all references are created on the C side.
409 static void create(lua_State *L, ServerEnvironment *env)
411 EnvRef *o = new EnvRef(env);
412 //infostream<<"EnvRef::create: o="<<o<<std::endl;
413 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
414 luaL_getmetatable(L, className);
415 lua_setmetatable(L, -2);
418 static void set_null(lua_State *L)
420 EnvRef *o = checkobject(L, -1);
424 static void Register(lua_State *L)
427 int methodtable = lua_gettop(L);
428 luaL_newmetatable(L, className);
429 int metatable = lua_gettop(L);
431 lua_pushliteral(L, "__metatable");
432 lua_pushvalue(L, methodtable);
433 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
435 lua_pushliteral(L, "__index");
436 lua_pushvalue(L, methodtable);
437 lua_settable(L, metatable);
439 lua_pushliteral(L, "__gc");
440 lua_pushcfunction(L, gc_object);
441 lua_settable(L, metatable);
443 lua_pop(L, 1); // drop metatable
445 luaL_openlib(L, 0, methods, 0); // fill methodtable
446 lua_pop(L, 1); // drop methodtable
448 // Cannot be created from Lua
449 //lua_register(L, className, create_object);
452 const char EnvRef::className[] = "EnvRef";
453 const luaL_reg EnvRef::methods[] = {
454 method(EnvRef, add_node),
461 ServerActiveObject *m_object;
463 static const char className[];
464 static const luaL_reg methods[];
466 static ObjectRef *checkobject(lua_State *L, int narg)
468 luaL_checktype(L, narg, LUA_TUSERDATA);
469 void *ud = luaL_checkudata(L, narg, className);
470 if(!ud) luaL_typerror(L, narg, className);
471 return *(ObjectRef**)ud; // unbox pointer
474 static ServerActiveObject* getobject(ObjectRef *ref)
476 ServerActiveObject *co = ref->m_object;
480 static LuaEntitySAO* getluaobject(ObjectRef *ref)
482 ServerActiveObject *obj = getobject(ref);
485 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
487 return (LuaEntitySAO*)obj;
490 // Exported functions
493 static int gc_object(lua_State *L) {
494 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
495 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
501 static int l_remove(lua_State *L)
503 ObjectRef *ref = checkobject(L, 1);
504 ServerActiveObject *co = getobject(ref);
505 if(co == NULL) return 0;
506 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
507 co->m_removed = true;
512 // returns: {x=num, y=num, z=num}
513 static int l_getpos(lua_State *L)
515 ObjectRef *ref = checkobject(L, 1);
516 ServerActiveObject *co = getobject(ref);
517 if(co == NULL) return 0;
518 v3f pos = co->getBasePosition() / BS;
520 lua_pushnumber(L, pos.X);
521 lua_setfield(L, -2, "x");
522 lua_pushnumber(L, pos.Y);
523 lua_setfield(L, -2, "y");
524 lua_pushnumber(L, pos.Z);
525 lua_setfield(L, -2, "z");
530 static int l_setpos(lua_State *L)
532 ObjectRef *ref = checkobject(L, 1);
533 //LuaEntitySAO *co = getluaobject(ref);
534 ServerActiveObject *co = getobject(ref);
535 if(co == NULL) return 0;
537 v3f pos = readFloatPos(L, 2);
543 // moveto(self, pos, continuous=false)
544 static int l_moveto(lua_State *L)
546 ObjectRef *ref = checkobject(L, 1);
547 //LuaEntitySAO *co = getluaobject(ref);
548 ServerActiveObject *co = getobject(ref);
549 if(co == NULL) return 0;
551 v3f pos = readFloatPos(L, 2);
553 bool continuous = lua_toboolean(L, 3);
555 co->moveTo(pos, continuous);
559 // add_to_inventory(self, itemstring)
560 // returns: true if item was added, false otherwise
561 static int l_add_to_inventory(lua_State *L)
563 ObjectRef *ref = checkobject(L, 1);
564 luaL_checkstring(L, 2);
565 ServerActiveObject *co = getobject(ref);
566 if(co == NULL) return 0;
568 const char *itemstring = lua_tostring(L, 2);
569 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
570 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
572 std::istringstream is(itemstring, std::ios::binary);
573 ServerEnvironment *env = co->getEnv();
575 IGameDef *gamedef = env->getGameDef();
576 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
577 infostream<<"item="<<env<<std::endl;
578 bool fits = co->addToInventory(item);
580 lua_pushboolean(L, fits);
585 ObjectRef(ServerActiveObject *object):
588 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
594 infostream<<"ObjectRef destructing for id="
595 <<m_object->getId()<<std::endl;
597 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
600 // Creates an ObjectRef and leaves it on top of stack
601 // Not callable from Lua; all references are created on the C side.
602 static void create(lua_State *L, ServerActiveObject *object)
604 ObjectRef *o = new ObjectRef(object);
605 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
606 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
607 luaL_getmetatable(L, className);
608 lua_setmetatable(L, -2);
611 static void set_null(lua_State *L)
613 ObjectRef *o = checkobject(L, -1);
617 static void Register(lua_State *L)
620 int methodtable = lua_gettop(L);
621 luaL_newmetatable(L, className);
622 int metatable = lua_gettop(L);
624 lua_pushliteral(L, "__metatable");
625 lua_pushvalue(L, methodtable);
626 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
628 lua_pushliteral(L, "__index");
629 lua_pushvalue(L, methodtable);
630 lua_settable(L, metatable);
632 lua_pushliteral(L, "__gc");
633 lua_pushcfunction(L, gc_object);
634 lua_settable(L, metatable);
636 lua_pop(L, 1); // drop metatable
638 luaL_openlib(L, 0, methods, 0); // fill methodtable
639 lua_pop(L, 1); // drop methodtable
641 // Cannot be created from Lua
642 //lua_register(L, className, create_object);
645 const char ObjectRef::className[] = "ObjectRef";
646 const luaL_reg ObjectRef::methods[] = {
647 method(ObjectRef, remove),
648 method(ObjectRef, getpos),
649 method(ObjectRef, setpos),
650 method(ObjectRef, moveto),
651 method(ObjectRef, add_to_inventory),
655 // Creates a new anonymous reference if id=0
656 static void objectref_get_or_create(lua_State *L,
657 ServerActiveObject *cobj)
659 if(cobj->getId() == 0){
660 ObjectRef::create(L, cobj);
662 objectref_get(L, cobj->getId());
670 void scriptapi_export(lua_State *L, Server *server)
673 assert(lua_checkstack(L, 20));
674 infostream<<"scriptapi_export"<<std::endl;
675 StackUnroller stack_unroller(L);
677 // Store server as light userdata in registry
678 lua_pushlightuserdata(L, server);
679 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
681 // Register global functions in table minetest
683 luaL_register(L, NULL, minetest_f);
684 lua_setglobal(L, "minetest");
686 // Get the main minetest table
687 lua_getglobal(L, "minetest");
689 // Add tables to minetest
692 lua_setfield(L, -2, "registered_blocks");*/
695 lua_setfield(L, -2, "registered_entities");
698 lua_setfield(L, -2, "registered_globalsteps");
701 lua_setfield(L, -2, "object_refs");
704 lua_setfield(L, -2, "luaentities");
706 // Create entity prototype
707 luaL_newmetatable(L, "minetest.entity");
708 // metatable.__index = metatable
709 lua_pushvalue(L, -1); // Duplicate metatable
710 lua_setfield(L, -2, "__index");
711 // Put functions in metatable
712 luaL_register(L, NULL, minetest_entity_m);
713 // Put other stuff in metatable
715 // Environment C reference
718 // Object C reference
719 ObjectRef::Register(L);
722 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
725 assert(lua_checkstack(L, 20));
726 infostream<<"scriptapi_add_environment"<<std::endl;
727 StackUnroller stack_unroller(L);
729 // Create EnvRef on stack
730 EnvRef::create(L, env);
731 int envref = lua_gettop(L);
733 // minetest.env = envref
734 lua_getglobal(L, "minetest");
735 luaL_checktype(L, -1, LUA_TTABLE);
736 lua_pushvalue(L, envref);
737 lua_setfield(L, -2, "env");
741 // Dump stack top with the dump2 function
742 static void dump2(lua_State *L, const char *name)
744 // Dump object (debug)
745 lua_getglobal(L, "dump2");
746 luaL_checktype(L, -1, LUA_TFUNCTION);
747 lua_pushvalue(L, -2); // Get previous stack top as first parameter
748 lua_pushstring(L, name);
749 if(lua_pcall(L, 2, 0, 0))
750 script_error(L, "error: %s\n", lua_tostring(L, -1));
758 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
761 assert(lua_checkstack(L, 20));
762 infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
763 StackUnroller stack_unroller(L);
765 // Create object on stack
766 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
767 int object = lua_gettop(L);
769 // Get minetest.object_refs table
770 lua_getglobal(L, "minetest");
771 lua_getfield(L, -1, "object_refs");
772 luaL_checktype(L, -1, LUA_TTABLE);
773 int objectstable = lua_gettop(L);
775 // object_refs[id] = object
776 lua_pushnumber(L, cobj->getId()); // Push id
777 lua_pushvalue(L, object); // Copy object to top of stack
778 lua_settable(L, objectstable);
781 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
784 assert(lua_checkstack(L, 20));
785 infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
786 StackUnroller stack_unroller(L);
788 // Get minetest.object_refs table
789 lua_getglobal(L, "minetest");
790 lua_getfield(L, -1, "object_refs");
791 luaL_checktype(L, -1, LUA_TTABLE);
792 int objectstable = lua_gettop(L);
794 // Get object_refs[id]
795 lua_pushnumber(L, cobj->getId()); // Push id
796 lua_gettable(L, objectstable);
797 // Set object reference to NULL
798 ObjectRef::set_null(L);
799 lua_pop(L, 1); // pop object
801 // Set object_refs[id] = nil
802 lua_pushnumber(L, cobj->getId()); // Push id
804 lua_settable(L, objectstable);
811 void scriptapi_environment_step(lua_State *L, float dtime)
814 assert(lua_checkstack(L, 20));
815 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
816 StackUnroller stack_unroller(L);
818 // Get minetest.registered_globalsteps
819 lua_getglobal(L, "minetest");
820 lua_getfield(L, -1, "registered_globalsteps");
821 luaL_checktype(L, -1, LUA_TTABLE);
822 int table = lua_gettop(L);
825 while(lua_next(L, table) != 0){
826 // key at index -2 and value at index -1
827 luaL_checktype(L, -1, LUA_TFUNCTION);
829 lua_pushnumber(L, dtime);
830 if(lua_pcall(L, 1, 0, 0))
831 script_error(L, "error: %s\n", lua_tostring(L, -1));
832 // value removed, keep key for next iteration
840 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
841 const char *init_state)
844 assert(lua_checkstack(L, 20));
845 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
846 <<name<<"\""<<std::endl;
847 StackUnroller stack_unroller(L);
849 // Create object as a dummy string (TODO: Create properly)
851 // Get minetest.registered_entities[name]
852 lua_getglobal(L, "minetest");
853 lua_getfield(L, -1, "registered_entities");
854 luaL_checktype(L, -1, LUA_TTABLE);
855 lua_pushstring(L, name);
857 // Should be a table, which we will use as a prototype
858 //luaL_checktype(L, -1, LUA_TTABLE);
859 if(lua_type(L, -1) != LUA_TTABLE){
860 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
863 int prototype_table = lua_gettop(L);
864 //dump2(L, "prototype_table");
866 // Create entity object
868 int object = lua_gettop(L);
870 // Set object metatable
871 lua_pushvalue(L, prototype_table);
872 lua_setmetatable(L, -2);
874 // Add object reference
875 // This should be userdata with metatable ObjectRef
876 objectref_get(L, id);
877 luaL_checktype(L, -1, LUA_TUSERDATA);
878 if(!luaL_checkudata(L, -1, "ObjectRef"))
879 luaL_typerror(L, -1, "ObjectRef");
880 lua_setfield(L, -2, "object");
882 // minetest.luaentities[id] = object
883 lua_getglobal(L, "minetest");
884 lua_getfield(L, -1, "luaentities");
885 luaL_checktype(L, -1, LUA_TTABLE);
886 lua_pushnumber(L, id); // Push id
887 lua_pushvalue(L, object); // Copy object to top of stack
890 // This callback doesn't really make sense
891 /*// Get on_activate function
892 lua_pushvalue(L, object);
893 lua_getfield(L, -1, "on_activate");
894 luaL_checktype(L, -1, LUA_TFUNCTION);
895 lua_pushvalue(L, object); // self
896 // Call with 1 arguments, 0 results
897 if(lua_pcall(L, 1, 0, 0))
898 script_error(L, "error running function %s:on_activate: %s\n",
899 name, lua_tostring(L, -1));*/
904 void scriptapi_luaentity_rm(lua_State *L, u16 id)
907 assert(lua_checkstack(L, 20));
908 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
910 // Get minetest.luaentities table
911 lua_getglobal(L, "minetest");
912 lua_getfield(L, -1, "luaentities");
913 luaL_checktype(L, -1, LUA_TTABLE);
914 int objectstable = lua_gettop(L);
916 // Set luaentities[id] = nil
917 lua_pushnumber(L, id); // Push id
919 lua_settable(L, objectstable);
921 lua_pop(L, 2); // pop luaentities, minetest
924 std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
927 assert(lua_checkstack(L, 20));
928 infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
933 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
934 LuaEntityProperties *prop)
937 assert(lua_checkstack(L, 20));
938 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
939 StackUnroller stack_unroller(L);
941 // Get minetest.luaentities[id]
942 luaentity_get(L, id);
943 //int object = lua_gettop(L);
945 lua_getfield(L, -1, "physical");
946 if(lua_isboolean(L, -1))
947 prop->physical = lua_toboolean(L, -1);
950 lua_getfield(L, -1, "weight");
951 prop->weight = lua_tonumber(L, -1);
954 lua_getfield(L, -1, "collisionbox");
955 if(lua_istable(L, -1)){
956 lua_rawgeti(L, -1, 1);
957 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
959 lua_rawgeti(L, -1, 2);
960 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
962 lua_rawgeti(L, -1, 3);
963 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
965 lua_rawgeti(L, -1, 4);
966 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
968 lua_rawgeti(L, -1, 5);
969 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
971 lua_rawgeti(L, -1, 6);
972 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
977 lua_getfield(L, -1, "visual");
978 if(lua_isstring(L, -1))
979 prop->visual = lua_tostring(L, -1);
982 lua_getfield(L, -1, "textures");
983 if(lua_istable(L, -1)){
984 prop->textures.clear();
985 int table = lua_gettop(L);
987 while(lua_next(L, table) != 0){
988 // key at index -2 and value at index -1
989 if(lua_isstring(L, -1))
990 prop->textures.push_back(lua_tostring(L, -1));
992 prop->textures.push_back("");
993 // removes value, keeps key for next iteration
1001 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1004 assert(lua_checkstack(L, 20));
1005 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1006 StackUnroller stack_unroller(L);
1008 // Get minetest.luaentities[id]
1009 luaentity_get(L, id);
1010 int object = lua_gettop(L);
1011 // State: object is at top of stack
1012 // Get step function
1013 lua_getfield(L, -1, "on_step");
1014 luaL_checktype(L, -1, LUA_TFUNCTION);
1015 lua_pushvalue(L, object); // self
1016 lua_pushnumber(L, dtime); // dtime
1017 // Call with 2 arguments, 0 results
1018 if(lua_pcall(L, 2, 0, 0))
1019 script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
1022 // Calls entity:on_punch(ObjectRef puncher)
1023 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1024 ServerActiveObject *puncher)
1027 assert(lua_checkstack(L, 20));
1028 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1029 StackUnroller stack_unroller(L);
1031 // Get minetest.luaentities[id]
1032 luaentity_get(L, id);
1033 int object = lua_gettop(L);
1034 // State: object is at top of stack
1036 lua_getfield(L, -1, "on_punch");
1037 luaL_checktype(L, -1, LUA_TFUNCTION);
1038 lua_pushvalue(L, object); // self
1039 objectref_get_or_create(L, puncher); // Clicker reference
1040 // Call with 2 arguments, 0 results
1041 if(lua_pcall(L, 2, 0, 0))
1042 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1045 // Calls entity:on_rightclick(ObjectRef clicker)
1046 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1047 ServerActiveObject *clicker)
1050 assert(lua_checkstack(L, 20));
1051 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1052 StackUnroller stack_unroller(L);
1054 // Get minetest.luaentities[id]
1055 luaentity_get(L, id);
1056 int object = lua_gettop(L);
1057 // State: object is at top of stack
1059 lua_getfield(L, -1, "on_rightclick");
1060 luaL_checktype(L, -1, LUA_TFUNCTION);
1061 lua_pushvalue(L, object); // self
1062 objectref_get_or_create(L, clicker); // Clicker reference
1063 // Call with 2 arguments, 0 results
1064 if(lua_pcall(L, 2, 0, 0))
1065 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));