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"
34 #include "serverobject.h"
37 #include "luaentity_common.h"
38 #include "content_sao.h" // For LuaEntitySAO
42 #include "craftitemdef.h"
43 #include "main.h" // For g_settings
44 #include "settings.h" // For accessing g_settings
45 #include "nodemetadata.h"
46 #include "mapblock.h" // For getNodeBlockPos
47 #include "content_nodemeta.h"
50 static void stackDump(lua_State *L, std::ostream &o)
53 int top = lua_gettop(L);
54 for (i = 1; i <= top; i++) { /* repeat for each level */
55 int t = lua_type(L, i);
58 case LUA_TSTRING: /* strings */
59 o<<"\""<<lua_tostring(L, i)<<"\"";
62 case LUA_TBOOLEAN: /* booleans */
63 o<<(lua_toboolean(L, i) ? "true" : "false");
66 case LUA_TNUMBER: /* numbers */ {
68 snprintf(buf, 10, "%g", lua_tonumber(L, i));
72 default: /* other values */
73 o<<lua_typename(L, t);
82 static void realitycheck(lua_State *L)
84 int top = lua_gettop(L);
86 dstream<<"Stack is over 30:"<<std::endl;
87 stackDump(L, dstream);
88 script_error(L, "Stack is over 30 (reality check)");
98 StackUnroller(lua_State *L):
102 m_original_top = lua_gettop(m_lua); // store stack height
106 lua_settop(m_lua, m_original_top); // restore stack height
115 ModNameStorer(lua_State *L_, const std::string modname):
118 // Store current modname in registry
119 lua_pushstring(L, modname.c_str());
120 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
124 // Clear current modname in registry
126 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
130 std::string get_current_modname(lua_State *L)
132 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
133 std::string modname = "";
134 if(lua_type(L, -1) == LUA_TSTRING)
135 modname = lua_tostring(L, -1);
140 void check_modname_prefix(lua_State *L, std::string &name)
143 throw LuaError(L, std::string("Name is empty"));
146 name = name.substr(1);
150 std::string modname = get_current_modname(L);
151 assert(modname != "");
153 // For __builtin, anything goes
154 if(modname == "__builtin")
157 if(name.substr(0, modname.size()+1) != modname + ":")
158 throw LuaError(L, std::string("Name \"")+name
159 +"\" does not follow naming conventions: "
160 +"\"modname:\" or \":\" prefix required)");
162 std::string subname = name.substr(modname.size()+1);
163 if(!string_allowed(subname, "abcdefghijklmnopqrstuvwxyz"
164 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
165 throw LuaError(L, std::string("Name \"")+name
166 +"\" does not follow naming conventions: "
167 +"\"contains unallowed characters)");
170 static v3f readFloatPos(lua_State *L, int index)
173 luaL_checktype(L, index, LUA_TTABLE);
174 lua_getfield(L, index, "x");
175 pos.X = lua_tonumber(L, -1);
177 lua_getfield(L, index, "y");
178 pos.Y = lua_tonumber(L, -1);
180 lua_getfield(L, index, "z");
181 pos.Z = lua_tonumber(L, -1);
183 pos *= BS; // Scale to internal format
187 static void pushFloatPos(lua_State *L, v3f p)
191 lua_pushnumber(L, p.X);
192 lua_setfield(L, -2, "x");
193 lua_pushnumber(L, p.Y);
194 lua_setfield(L, -2, "y");
195 lua_pushnumber(L, p.Z);
196 lua_setfield(L, -2, "z");
199 static void pushpos(lua_State *L, v3s16 p)
202 lua_pushnumber(L, p.X);
203 lua_setfield(L, -2, "x");
204 lua_pushnumber(L, p.Y);
205 lua_setfield(L, -2, "y");
206 lua_pushnumber(L, p.Z);
207 lua_setfield(L, -2, "z");
210 static v3s16 readpos(lua_State *L, int index)
212 // Correct rounding at <0
213 v3f pf = readFloatPos(L, index);
214 return floatToInt(pf, BS);
217 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
220 lua_pushstring(L, ndef->get(n).name.c_str());
221 lua_setfield(L, -2, "name");
222 lua_pushnumber(L, n.getParam1());
223 lua_setfield(L, -2, "param1");
224 lua_pushnumber(L, n.getParam2());
225 lua_setfield(L, -2, "param2");
228 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
230 lua_getfield(L, index, "name");
231 const char *name = lua_tostring(L, -1);
234 lua_getfield(L, index, "param1");
238 param1 = lua_tonumber(L, -1);
241 lua_getfield(L, index, "param2");
245 param2 = lua_tonumber(L, -1);
247 return MapNode(ndef, name, param1, param2);
250 static video::SColor readARGB8(lua_State *L, int index)
253 luaL_checktype(L, index, LUA_TTABLE);
254 lua_getfield(L, index, "a");
255 if(lua_isnumber(L, -1))
256 color.setAlpha(lua_tonumber(L, -1));
258 lua_getfield(L, index, "r");
259 color.setRed(lua_tonumber(L, -1));
261 lua_getfield(L, index, "g");
262 color.setGreen(lua_tonumber(L, -1));
264 lua_getfield(L, index, "b");
265 color.setBlue(lua_tonumber(L, -1));
270 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
272 core::aabbox3d<f32> box;
273 if(lua_istable(L, -1)){
274 lua_rawgeti(L, -1, 1);
275 box.MinEdge.X = lua_tonumber(L, -1) * scale;
277 lua_rawgeti(L, -1, 2);
278 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
280 lua_rawgeti(L, -1, 3);
281 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
283 lua_rawgeti(L, -1, 4);
284 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
286 lua_rawgeti(L, -1, 5);
287 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
289 lua_rawgeti(L, -1, 6);
290 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
296 static v2s16 read_v2s16(lua_State *L, int index)
299 luaL_checktype(L, index, LUA_TTABLE);
300 lua_getfield(L, index, "x");
301 p.X = lua_tonumber(L, -1);
303 lua_getfield(L, index, "y");
304 p.Y = lua_tonumber(L, -1);
309 static v2f read_v2f(lua_State *L, int index)
312 luaL_checktype(L, index, LUA_TTABLE);
313 lua_getfield(L, index, "x");
314 p.X = lua_tonumber(L, -1);
316 lua_getfield(L, index, "y");
317 p.Y = lua_tonumber(L, -1);
322 static bool getstringfield(lua_State *L, int table,
323 const char *fieldname, std::string &result)
325 lua_getfield(L, table, fieldname);
327 if(lua_isstring(L, -1)){
328 result = lua_tostring(L, -1);
335 static bool getintfield(lua_State *L, int table,
336 const char *fieldname, int &result)
338 lua_getfield(L, table, fieldname);
340 if(lua_isnumber(L, -1)){
341 result = lua_tonumber(L, -1);
348 static bool getfloatfield(lua_State *L, int table,
349 const char *fieldname, float &result)
351 lua_getfield(L, table, fieldname);
353 if(lua_isnumber(L, -1)){
354 result = lua_tonumber(L, -1);
361 static bool getboolfield(lua_State *L, int table,
362 const char *fieldname, bool &result)
364 lua_getfield(L, table, fieldname);
366 if(lua_isboolean(L, -1)){
367 result = lua_toboolean(L, -1);
374 static std::string getstringfield_default(lua_State *L, int table,
375 const char *fieldname, const std::string &default_)
377 std::string result = default_;
378 getstringfield(L, table, fieldname, result);
382 static int getintfield_default(lua_State *L, int table,
383 const char *fieldname, int default_)
385 int result = default_;
386 getintfield(L, table, fieldname, result);
390 /*static float getfloatfield_default(lua_State *L, int table,
391 const char *fieldname, float default_)
393 float result = default_;
394 getfloatfield(L, table, fieldname, result);
398 static bool getboolfield_default(lua_State *L, int table,
399 const char *fieldname, bool default_)
401 bool result = default_;
402 getboolfield(L, table, fieldname, result);
412 static bool string_to_enum(const EnumString *spec, int &result,
413 const std::string &str)
415 const EnumString *esp = spec;
417 if(str == std::string(esp->str)){
426 /*static bool enum_to_string(const EnumString *spec, std::string &result,
429 const EnumString *esp = spec;
440 static int getenumfield(lua_State *L, int table,
441 const char *fieldname, const EnumString *spec, int default_)
443 int result = default_;
444 string_to_enum(spec, result,
445 getstringfield_default(L, table, fieldname, ""));
449 static void setfloatfield(lua_State *L, int table,
450 const char *fieldname, float value)
452 lua_pushnumber(L, value);
455 lua_setfield(L, table, fieldname);
462 static void inventory_set_list_from_lua(Inventory *inv, const char *name,
463 lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
466 tableindex = lua_gettop(L) + 1 + tableindex;
467 // If nil, delete list
468 if(lua_isnil(L, tableindex)){
469 inv->deleteList(name);
472 // Otherwise set list
473 std::list<std::string> items;
474 luaL_checktype(L, tableindex, LUA_TTABLE);
475 int table = tableindex;
477 while(lua_next(L, table) != 0){
478 // key at index -2 and value at index -1
479 luaL_checktype(L, -1, LUA_TSTRING);
480 std::string itemstring = lua_tostring(L, -1);
481 items.push_back(itemstring);
482 // removes value, keeps key for next iteration
485 int listsize = (forcesize != -1) ? forcesize : items.size();
486 InventoryList *invlist = inv->addList(name, listsize);
488 for(std::list<std::string>::const_iterator
489 i = items.begin(); i != items.end(); i++){
490 if(forcesize != -1 && index == forcesize)
492 const std::string &itemstring = *i;
493 InventoryItem *newitem = NULL;
495 newitem = InventoryItem::deSerialize(itemstring,
497 InventoryItem *olditem = invlist->changeItem(index, newitem);
501 while(forcesize != -1 && index < forcesize){
502 InventoryItem *olditem = invlist->changeItem(index, NULL);
508 static void inventory_get_list_to_lua(Inventory *inv, const char *name,
511 InventoryList *invlist = inv->getList(name);
516 // Get the table insert function
517 lua_getglobal(L, "table");
518 lua_getfield(L, -1, "insert");
519 int table_insert = lua_gettop(L);
520 // Create and fill table
522 int table = lua_gettop(L);
523 for(u32 i=0; i<invlist->getSize(); i++){
524 InventoryItem *item = invlist->getItem(i);
525 lua_pushvalue(L, table_insert);
526 lua_pushvalue(L, table);
528 lua_pushstring(L, "");
530 lua_pushstring(L, item->getItemString().c_str());
532 if(lua_pcall(L, 2, 0, 0))
533 script_error(L, "error: %s", lua_tostring(L, -1));
538 ToolDiggingProperties
541 static ToolDiggingProperties read_tool_digging_properties(
542 lua_State *L, int table)
544 ToolDiggingProperties prop;
545 getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
546 getfloatfield(L, table, "basetime", prop.basetime);
547 getfloatfield(L, table, "dt_weight", prop.dt_weight);
548 getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
549 getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
550 getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
551 getfloatfield(L, table, "basedurability", prop.basedurability);
552 getfloatfield(L, table, "dd_weight", prop.dd_weight);
553 getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
554 getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
555 getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
559 static void set_tool_digging_properties(lua_State *L, int table,
560 const ToolDiggingProperties &prop)
562 setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
563 setfloatfield(L, table, "basetime", prop.basetime);
564 setfloatfield(L, table, "dt_weight", prop.dt_weight);
565 setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
566 setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
567 setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
568 setfloatfield(L, table, "basedurability", prop.basedurability);
569 setfloatfield(L, table, "dd_weight", prop.dd_weight);
570 setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
571 setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
572 setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
575 static void push_tool_digging_properties(lua_State *L,
576 const ToolDiggingProperties &prop)
579 set_tool_digging_properties(L, -1, prop);
586 static ToolDefinition read_tool_definition(lua_State *L, int table)
589 getstringfield(L, table, "image", def.imagename);
590 def.properties = read_tool_digging_properties(L, table);
594 static void push_tool_definition(lua_State *L, const ToolDefinition &def)
597 lua_pushstring(L, def.imagename.c_str());
598 lua_setfield(L, -2, "image");
599 set_tool_digging_properties(L, -1, def.properties);
603 EnumString definitions
606 struct EnumString es_DrawType[] =
608 {NDT_NORMAL, "normal"},
609 {NDT_AIRLIKE, "airlike"},
610 {NDT_LIQUID, "liquid"},
611 {NDT_FLOWINGLIQUID, "flowingliquid"},
612 {NDT_GLASSLIKE, "glasslike"},
613 {NDT_ALLFACES, "allfaces"},
614 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
615 {NDT_TORCHLIKE, "torchlike"},
616 {NDT_SIGNLIKE, "signlike"},
617 {NDT_PLANTLIKE, "plantlike"},
618 {NDT_FENCELIKE, "fencelike"},
619 {NDT_RAILLIKE, "raillike"},
623 struct EnumString es_ContentParamType[] =
626 {CPT_LIGHT, "light"},
627 {CPT_MINERAL, "mineral"},
628 {CPT_FACEDIR_SIMPLE, "facedir_simple"},
632 struct EnumString es_LiquidType[] =
634 {LIQUID_NONE, "none"},
635 {LIQUID_FLOWING, "flowing"},
636 {LIQUID_SOURCE, "source"},
640 struct EnumString es_NodeBoxType[] =
642 {NODEBOX_REGULAR, "regular"},
643 {NODEBOX_FIXED, "fixed"},
644 {NODEBOX_WALLMOUNTED, "wallmounted"},
648 struct EnumString es_Diggability[] =
650 {DIGGABLE_NOT, "not"},
651 {DIGGABLE_NORMAL, "normal"},
652 {DIGGABLE_CONSTANT, "constant"},
660 static int l_register_nodedef_defaults(lua_State *L)
662 luaL_checktype(L, 1, LUA_TTABLE);
664 lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
665 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
670 // Register new object prototype
671 // register_entity(name, prototype)
672 static int l_register_entity(lua_State *L)
674 std::string name = luaL_checkstring(L, 1);
675 check_modname_prefix(L, name);
676 //infostream<<"register_entity: "<<name<<std::endl;
677 luaL_checktype(L, 2, LUA_TTABLE);
679 // Get minetest.registered_entities
680 lua_getglobal(L, "minetest");
681 lua_getfield(L, -1, "registered_entities");
682 luaL_checktype(L, -1, LUA_TTABLE);
683 int registered_entities = lua_gettop(L);
684 lua_pushvalue(L, 2); // Object = param 2 -> stack top
685 // registered_entities[name] = object
686 lua_setfield(L, registered_entities, name.c_str());
688 // Get registered object to top of stack
691 // Set __index to point to itself
692 lua_pushvalue(L, -1);
693 lua_setfield(L, -2, "__index");
695 // Set metatable.__index = metatable
696 luaL_getmetatable(L, "minetest.entity");
697 lua_pushvalue(L, -1); // duplicate metatable
698 lua_setfield(L, -2, "__index");
699 // Set object metatable
700 lua_setmetatable(L, -2);
702 return 0; /* number of results */
705 class LuaABM : public ActiveBlockModifier
711 std::set<std::string> m_trigger_contents;
712 float m_trigger_interval;
713 u32 m_trigger_chance;
715 LuaABM(lua_State *L, int id,
716 const std::set<std::string> &trigger_contents,
717 float trigger_interval, u32 trigger_chance):
720 m_trigger_contents(trigger_contents),
721 m_trigger_interval(trigger_interval),
722 m_trigger_chance(trigger_chance)
725 virtual std::set<std::string> getTriggerContents()
727 return m_trigger_contents;
729 virtual float getTriggerInterval()
731 return m_trigger_interval;
733 virtual u32 getTriggerChance()
735 return m_trigger_chance;
737 virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
738 u32 active_object_count, u32 active_object_count_wider)
740 lua_State *L = m_lua;
743 assert(lua_checkstack(L, 20));
744 StackUnroller stack_unroller(L);
746 // Get minetest.registered_abms
747 lua_getglobal(L, "minetest");
748 lua_getfield(L, -1, "registered_abms");
749 luaL_checktype(L, -1, LUA_TTABLE);
750 int registered_abms = lua_gettop(L);
752 // Get minetest.registered_abms[m_id]
753 lua_pushnumber(L, m_id);
754 lua_gettable(L, registered_abms);
759 luaL_checktype(L, -1, LUA_TTABLE);
760 lua_getfield(L, -1, "action");
761 luaL_checktype(L, -1, LUA_TFUNCTION);
763 pushnode(L, n, env->getGameDef()->ndef());
764 lua_pushnumber(L, active_object_count);
765 lua_pushnumber(L, active_object_count_wider);
766 if(lua_pcall(L, 4, 0, 0))
767 script_error(L, "error: %s", lua_tostring(L, -1));
771 // register_abm({...})
772 static int l_register_abm(lua_State *L)
774 //infostream<<"register_abm"<<std::endl;
775 luaL_checktype(L, 1, LUA_TTABLE);
777 // Get minetest.registered_abms
778 lua_getglobal(L, "minetest");
779 lua_getfield(L, -1, "registered_abms");
780 luaL_checktype(L, -1, LUA_TTABLE);
781 int registered_abms = lua_gettop(L);
786 lua_pushnumber(L, id);
787 lua_gettable(L, registered_abms);
795 infostream<<"register_abm: id="<<id<<std::endl;
797 // registered_abms[id] = spec
798 lua_pushnumber(L, id);
800 lua_settable(L, registered_abms);
802 return 0; /* number of results */
805 // register_tool(name, {lots of stuff})
806 static int l_register_tool(lua_State *L)
808 std::string name = luaL_checkstring(L, 1);
809 check_modname_prefix(L, name);
810 //infostream<<"register_tool: "<<name<<std::endl;
811 luaL_checktype(L, 2, LUA_TTABLE);
814 // Get server from registry
815 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
816 Server *server = (Server*)lua_touserdata(L, -1);
817 // And get the writable tool definition manager from the server
818 IWritableToolDefManager *tooldef =
819 server->getWritableToolDefManager();
821 ToolDefinition def = read_tool_definition(L, table);
823 tooldef->registerTool(name, def);
824 return 0; /* number of results */
827 // register_craftitem(name, {lots of stuff})
828 static int l_register_craftitem(lua_State *L)
830 std::string name = luaL_checkstring(L, 1);
831 check_modname_prefix(L, name);
832 //infostream<<"register_craftitem: "<<name<<std::endl;
833 luaL_checktype(L, 2, LUA_TTABLE);
836 // Get server from registry
837 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
838 Server *server = (Server*)lua_touserdata(L, -1);
839 // And get the writable CraftItem definition manager from the server
840 IWritableCraftItemDefManager *craftitemdef =
841 server->getWritableCraftItemDefManager();
843 // Check if on_drop is defined
844 lua_getfield(L, table, "on_drop");
845 bool got_on_drop = !lua_isnil(L, -1);
848 // Check if on_use is defined
849 lua_getfield(L, table, "on_use");
850 bool got_on_use = !lua_isnil(L, -1);
853 CraftItemDefinition def;
855 getstringfield(L, table, "image", def.imagename);
856 getstringfield(L, table, "cookresult_item", def.cookresult_item);
857 getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
858 getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
859 def.usable = getboolfield_default(L, table, "usable", got_on_use);
860 getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
861 def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
862 def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
864 // If an on_drop callback is defined, force dropcount to 1
869 craftitemdef->registerCraftItem(name, def);
871 lua_pushvalue(L, table);
872 scriptapi_add_craftitem(L, name.c_str());
874 return 0; /* number of results */
877 // register_node(name, {lots of stuff})
878 static int l_register_node(lua_State *L)
880 std::string name = luaL_checkstring(L, 1);
881 check_modname_prefix(L, name);
882 //infostream<<"register_node: "<<name<<std::endl;
883 luaL_checktype(L, 2, LUA_TTABLE);
884 int nodedef_table = 2;
886 // Get server from registry
887 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
888 Server *server = (Server*)lua_touserdata(L, -1);
889 // And get the writable node definition manager from the server
890 IWritableNodeDefManager *nodedef =
891 server->getWritableNodeDefManager();
893 // Get default node definition from registry
894 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
895 int nodedef_default = lua_gettop(L);
898 Add to minetest.registered_nodes with default as metatable
901 // Get the node definition table given as parameter
902 lua_pushvalue(L, nodedef_table);
904 // Set __index to point to itself
905 lua_pushvalue(L, -1);
906 lua_setfield(L, -2, "__index");
908 // Set nodedef_default as metatable for the definition
909 lua_pushvalue(L, nodedef_default);
910 lua_setmetatable(L, nodedef_table);
912 // minetest.registered_nodes[name] = nodedef
913 lua_getglobal(L, "minetest");
914 lua_getfield(L, -1, "registered_nodes");
915 luaL_checktype(L, -1, LUA_TTABLE);
916 lua_pushstring(L, name.c_str());
917 lua_pushvalue(L, nodedef_table);
926 // Default to getting the corresponding NodeItem when dug
927 f.dug_item = std::string("NodeItem \"")+name+"\" 1";
929 // Default to unknown_block.png as all textures
930 f.setAllTextures("unknown_block.png");
933 Read definiton from Lua
938 /* Visual definition */
940 f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
942 getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
944 lua_getfield(L, nodedef_table, "tile_images");
945 if(lua_istable(L, -1)){
946 int table = lua_gettop(L);
949 while(lua_next(L, table) != 0){
950 // key at index -2 and value at index -1
951 if(lua_isstring(L, -1))
952 f.tname_tiles[i] = lua_tostring(L, -1);
954 f.tname_tiles[i] = "";
955 // removes value, keeps key for next iteration
963 // Copy last value to all remaining textures
965 std::string lastname = f.tname_tiles[i-1];
967 f.tname_tiles[i] = lastname;
974 getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
976 lua_getfield(L, nodedef_table, "special_materials");
977 if(lua_istable(L, -1)){
978 int table = lua_gettop(L);
981 while(lua_next(L, table) != 0){
982 // key at index -2 and value at index -1
983 int smtable = lua_gettop(L);
984 std::string tname = getstringfield_default(
985 L, smtable, "image", "");
986 bool backface_culling = getboolfield_default(
987 L, smtable, "backface_culling", true);
988 MaterialSpec mspec(tname, backface_culling);
989 f.setSpecialMaterial(i, mspec);
990 // removes value, keeps key for next iteration
1001 f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
1005 lua_getfield(L, nodedef_table, "post_effect_color");
1006 if(!lua_isnil(L, -1))
1007 f.post_effect_color = readARGB8(L, -1);
1010 f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
1011 es_ContentParamType, CPT_NONE);
1013 // True for all ground-like things like stone and mud, false for eg. trees
1014 getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
1015 getboolfield(L, nodedef_table, "light_propagates", f.light_propagates);
1016 getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
1017 // This is used for collision detection.
1018 // Also for general solidness queries.
1019 getboolfield(L, nodedef_table, "walkable", f.walkable);
1020 // Player can point to these
1021 getboolfield(L, nodedef_table, "pointable", f.pointable);
1022 // Player can dig these
1023 getboolfield(L, nodedef_table, "diggable", f.diggable);
1024 // Player can climb these
1025 getboolfield(L, nodedef_table, "climbable", f.climbable);
1026 // Player can build on these
1027 getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
1028 // If true, param2 is set to direction when placed. Used for torches.
1029 // NOTE: the direction format is quite inefficient and should be changed
1030 getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
1031 // Whether this content type often contains mineral.
1032 // Used for texture atlas creation.
1033 // Currently only enabled for CONTENT_STONE.
1034 getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
1035 // Inventory item string as which the node appears in inventory when dug.
1036 // Mineral overrides this.
1037 getstringfield(L, nodedef_table, "dug_item", f.dug_item);
1038 // Extra dug item and its rarity
1039 getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
1040 // Usual get interval for extra dug item
1041 getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
1042 // Metadata name of node (eg. "furnace")
1043 getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
1044 // Whether the node is non-liquid, source liquid or flowing liquid
1045 f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
1046 es_LiquidType, LIQUID_NONE);
1047 // If the content is liquid, this is the flowing version of the liquid.
1048 getstringfield(L, nodedef_table, "liquid_alternative_flowing",
1049 f.liquid_alternative_flowing);
1050 // If the content is liquid, this is the source version of the liquid.
1051 getstringfield(L, nodedef_table, "liquid_alternative_source",
1052 f.liquid_alternative_source);
1053 // Viscosity for fluid flow, ranging from 1 to 7, with
1054 // 1 giving almost instantaneous propagation and 7 being
1055 // the slowest possible
1056 f.liquid_viscosity = getintfield_default(L, nodedef_table,
1057 "liquid_viscosity", f.liquid_viscosity);
1058 // Amount of light the node emits
1059 f.light_source = getintfield_default(L, nodedef_table,
1060 "light_source", f.light_source);
1061 f.damage_per_second = getintfield_default(L, nodedef_table,
1062 "damage_per_second", f.damage_per_second);
1064 lua_getfield(L, nodedef_table, "selection_box");
1065 if(lua_istable(L, -1)){
1066 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
1067 es_NodeBoxType, NODEBOX_REGULAR);
1069 lua_getfield(L, -1, "fixed");
1070 if(lua_istable(L, -1))
1071 f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
1074 lua_getfield(L, -1, "wall_top");
1075 if(lua_istable(L, -1))
1076 f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
1079 lua_getfield(L, -1, "wall_bottom");
1080 if(lua_istable(L, -1))
1081 f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
1084 lua_getfield(L, -1, "wall_side");
1085 if(lua_istable(L, -1))
1086 f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
1091 lua_getfield(L, nodedef_table, "material");
1092 if(lua_istable(L, -1)){
1093 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
1094 es_Diggability, DIGGABLE_NORMAL);
1096 getfloatfield(L, -1, "constant_time", f.material.constant_time);
1097 getfloatfield(L, -1, "weight", f.material.weight);
1098 getfloatfield(L, -1, "crackiness", f.material.crackiness);
1099 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
1100 getfloatfield(L, -1, "cuttability", f.material.cuttability);
1101 getfloatfield(L, -1, "flammability", f.material.flammability);
1105 getstringfield(L, nodedef_table, "cookresult_item", f.cookresult_item);
1106 getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
1107 getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
1113 nodedef->set(name, f);
1115 return 0; /* number of results */
1118 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
1119 static int l_register_craft(lua_State *L)
1121 //infostream<<"register_craft"<<std::endl;
1122 luaL_checktype(L, 1, LUA_TTABLE);
1125 // Get server from registry
1126 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1127 Server *server = (Server*)lua_touserdata(L, -1);
1128 // And get the writable craft definition manager from the server
1129 IWritableCraftDefManager *craftdef =
1130 server->getWritableCraftDefManager();
1134 std::vector<std::string> input;
1136 lua_getfield(L, table0, "output");
1137 luaL_checktype(L, -1, LUA_TSTRING);
1138 if(lua_isstring(L, -1))
1139 output = lua_tostring(L, -1);
1142 lua_getfield(L, table0, "recipe");
1143 luaL_checktype(L, -1, LUA_TTABLE);
1144 if(lua_istable(L, -1)){
1145 int table1 = lua_gettop(L);
1148 while(lua_next(L, table1) != 0){
1150 // key at index -2 and value at index -1
1151 luaL_checktype(L, -1, LUA_TTABLE);
1152 if(lua_istable(L, -1)){
1153 int table2 = lua_gettop(L);
1155 while(lua_next(L, table2) != 0){
1156 // key at index -2 and value at index -1
1157 luaL_checktype(L, -1, LUA_TSTRING);
1158 input.push_back(lua_tostring(L, -1));
1159 // removes value, keeps key for next iteration
1167 if(colcount != width){
1169 error += "Invalid crafting recipe (output=\""
1171 throw LuaError(L, error);
1174 // removes value, keeps key for next iteration
1181 CraftDefinition def(output, width, input);
1182 craftdef->registerCraft(def);
1184 return 0; /* number of results */
1187 // setting_get(name)
1188 static int l_setting_get(lua_State *L)
1190 const char *name = luaL_checkstring(L, 1);
1192 std::string value = g_settings->get(name);
1193 lua_pushstring(L, value.c_str());
1194 } catch(SettingNotFoundException &e){
1200 // setting_getbool(name)
1201 static int l_setting_getbool(lua_State *L)
1203 const char *name = luaL_checkstring(L, 1);
1205 bool value = g_settings->getBool(name);
1206 lua_pushboolean(L, value);
1207 } catch(SettingNotFoundException &e){
1213 // chat_send_all(text)
1214 static int l_chat_send_all(lua_State *L)
1216 const char *text = luaL_checkstring(L, 1);
1217 // Get server from registry
1218 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1219 Server *server = (Server*)lua_touserdata(L, -1);
1221 server->notifyPlayers(narrow_to_wide(text));
1225 // chat_send_player(name, text)
1226 static int l_chat_send_player(lua_State *L)
1228 const char *name = luaL_checkstring(L, 1);
1229 const char *text = luaL_checkstring(L, 2);
1230 // Get server from registry
1231 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1232 Server *server = (Server*)lua_touserdata(L, -1);
1234 server->notifyPlayer(name, narrow_to_wide(text));
1238 // get_player_privs(name, text)
1239 static int l_get_player_privs(lua_State *L)
1241 const char *name = luaL_checkstring(L, 1);
1242 // Get server from registry
1243 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1244 Server *server = (Server*)lua_touserdata(L, -1);
1247 int table = lua_gettop(L);
1248 u64 privs_i = server->getPlayerAuthPrivs(name);
1249 // Special case for the "name" setting (local player / server owner)
1250 if(name == g_settings->get("name"))
1252 std::set<std::string> privs_s = privsToSet(privs_i);
1253 for(std::set<std::string>::const_iterator
1254 i = privs_s.begin(); i != privs_s.end(); i++){
1255 lua_pushboolean(L, true);
1256 lua_setfield(L, table, i->c_str());
1258 lua_pushvalue(L, table);
1262 static const struct luaL_Reg minetest_f [] = {
1263 {"register_nodedef_defaults", l_register_nodedef_defaults},
1264 {"register_entity", l_register_entity},
1265 {"register_tool", l_register_tool},
1266 {"register_craftitem", l_register_craftitem},
1267 {"register_node", l_register_node},
1268 {"register_craft", l_register_craft},
1269 {"register_abm", l_register_abm},
1270 {"setting_get", l_setting_get},
1271 {"setting_getbool", l_setting_getbool},
1272 {"chat_send_all", l_chat_send_all},
1273 {"chat_send_player", l_chat_send_player},
1274 {"get_player_privs", l_get_player_privs},
1282 static const struct luaL_Reg minetest_entity_m [] = {
1287 Getters for stuff in main tables
1290 static void objectref_get(lua_State *L, u16 id)
1292 // Get minetest.object_refs[i]
1293 lua_getglobal(L, "minetest");
1294 lua_getfield(L, -1, "object_refs");
1295 luaL_checktype(L, -1, LUA_TTABLE);
1296 lua_pushnumber(L, id);
1297 lua_gettable(L, -2);
1298 lua_remove(L, -2); // object_refs
1299 lua_remove(L, -2); // minetest
1302 static void luaentity_get(lua_State *L, u16 id)
1304 // Get minetest.luaentities[i]
1305 lua_getglobal(L, "minetest");
1306 lua_getfield(L, -1, "luaentities");
1307 luaL_checktype(L, -1, LUA_TTABLE);
1308 lua_pushnumber(L, id);
1309 lua_gettable(L, -2);
1310 lua_remove(L, -2); // luaentities
1311 lua_remove(L, -2); // minetest
1318 #define method(class, name) {#name, class::l_##name}
1328 ServerEnvironment *m_env;
1330 static const char className[];
1331 static const luaL_reg methods[];
1333 static NodeMetaRef *checkobject(lua_State *L, int narg)
1335 luaL_checktype(L, narg, LUA_TUSERDATA);
1336 void *ud = luaL_checkudata(L, narg, className);
1337 if(!ud) luaL_typerror(L, narg, className);
1338 return *(NodeMetaRef**)ud; // unbox pointer
1341 static NodeMetadata* getmeta(NodeMetaRef *ref)
1343 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1347 /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1349 NodeMetadata *meta = getmeta(ref);
1352 if(meta->typeId() != NODEMETA_GENERIC)
1354 return (IGenericNodeMetadata*)meta;
1357 static void reportMetadataChange(NodeMetaRef *ref)
1359 // Inform other things that the metadata has changed
1360 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1362 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1364 ref->m_env->getMap().dispatchEvent(&event);
1365 // Set the block to be saved
1366 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1368 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1369 "NodeMetaRef::reportMetadataChange");
1372 // Exported functions
1374 // garbage collector
1375 static int gc_object(lua_State *L) {
1376 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1382 static int l_get_type(lua_State *L)
1384 NodeMetaRef *ref = checkobject(L, 1);
1385 NodeMetadata *meta = getmeta(ref);
1391 lua_pushstring(L, meta->typeName());
1395 // allows_text_input(self)
1396 static int l_allows_text_input(lua_State *L)
1398 NodeMetaRef *ref = checkobject(L, 1);
1399 NodeMetadata *meta = getmeta(ref);
1400 if(meta == NULL) return 0;
1402 lua_pushboolean(L, meta->allowsTextInput());
1406 // set_text(self, text)
1407 static int l_set_text(lua_State *L)
1409 NodeMetaRef *ref = checkobject(L, 1);
1410 NodeMetadata *meta = getmeta(ref);
1411 if(meta == NULL) return 0;
1413 std::string text = lua_tostring(L, 2);
1414 meta->setText(text);
1415 reportMetadataChange(ref);
1420 static int l_get_text(lua_State *L)
1422 NodeMetaRef *ref = checkobject(L, 1);
1423 NodeMetadata *meta = getmeta(ref);
1424 if(meta == NULL) return 0;
1426 std::string text = meta->getText();
1427 lua_pushstring(L, text.c_str());
1432 static int l_get_owner(lua_State *L)
1434 NodeMetaRef *ref = checkobject(L, 1);
1435 NodeMetadata *meta = getmeta(ref);
1436 if(meta == NULL) return 0;
1438 std::string owner = meta->getOwner();
1439 lua_pushstring(L, owner.c_str());
1443 /* IGenericNodeMetadata interface */
1445 // set_infotext(self, text)
1446 static int l_set_infotext(lua_State *L)
1448 infostream<<__FUNCTION_NAME<<std::endl;
1449 NodeMetaRef *ref = checkobject(L, 1);
1450 NodeMetadata *meta = getmeta(ref);
1451 if(meta == NULL) return 0;
1453 std::string text = lua_tostring(L, 2);
1454 meta->setInfoText(text);
1455 reportMetadataChange(ref);
1459 // inventory_set_list(self, name, {item1, item2, ...})
1460 static int l_inventory_set_list(lua_State *L)
1462 NodeMetaRef *ref = checkobject(L, 1);
1463 NodeMetadata *meta = getmeta(ref);
1464 if(meta == NULL) return 0;
1466 Inventory *inv = meta->getInventory();
1467 const char *name = lua_tostring(L, 2);
1468 inventory_set_list_from_lua(inv, name, L, 3,
1469 ref->m_env->getGameDef());
1470 reportMetadataChange(ref);
1474 // inventory_get_list(self, name)
1475 static int l_inventory_get_list(lua_State *L)
1477 NodeMetaRef *ref = checkobject(L, 1);
1478 NodeMetadata *meta = getmeta(ref);
1479 if(meta == NULL) return 0;
1481 Inventory *inv = meta->getInventory();
1482 const char *name = lua_tostring(L, 2);
1483 inventory_get_list_to_lua(inv, name, L);
1487 // set_inventory_draw_spec(self, text)
1488 static int l_set_inventory_draw_spec(lua_State *L)
1490 NodeMetaRef *ref = checkobject(L, 1);
1491 NodeMetadata *meta = getmeta(ref);
1492 if(meta == NULL) return 0;
1494 std::string text = lua_tostring(L, 2);
1495 meta->setInventoryDrawSpec(text);
1496 reportMetadataChange(ref);
1500 // set_allow_text_input(self, text)
1501 static int l_set_allow_text_input(lua_State *L)
1503 NodeMetaRef *ref = checkobject(L, 1);
1504 NodeMetadata *meta = getmeta(ref);
1505 if(meta == NULL) return 0;
1507 bool b = lua_toboolean(L, 2);
1508 meta->setAllowTextInput(b);
1509 reportMetadataChange(ref);
1513 // set_allow_removal(self, text)
1514 static int l_set_allow_removal(lua_State *L)
1516 NodeMetaRef *ref = checkobject(L, 1);
1517 NodeMetadata *meta = getmeta(ref);
1518 if(meta == NULL) return 0;
1520 bool b = lua_toboolean(L, 2);
1521 meta->setRemovalDisabled(!b);
1522 reportMetadataChange(ref);
1526 // set_enforce_owner(self, text)
1527 static int l_set_enforce_owner(lua_State *L)
1529 NodeMetaRef *ref = checkobject(L, 1);
1530 NodeMetadata *meta = getmeta(ref);
1531 if(meta == NULL) return 0;
1533 bool b = lua_toboolean(L, 2);
1534 meta->setEnforceOwner(b);
1535 reportMetadataChange(ref);
1539 // is_inventory_modified(self)
1540 static int l_is_inventory_modified(lua_State *L)
1542 NodeMetaRef *ref = checkobject(L, 1);
1543 NodeMetadata *meta = getmeta(ref);
1544 if(meta == NULL) return 0;
1546 lua_pushboolean(L, meta->isInventoryModified());
1550 // reset_inventory_modified(self)
1551 static int l_reset_inventory_modified(lua_State *L)
1553 NodeMetaRef *ref = checkobject(L, 1);
1554 NodeMetadata *meta = getmeta(ref);
1555 if(meta == NULL) return 0;
1557 meta->resetInventoryModified();
1558 reportMetadataChange(ref);
1562 // is_text_modified(self)
1563 static int l_is_text_modified(lua_State *L)
1565 NodeMetaRef *ref = checkobject(L, 1);
1566 NodeMetadata *meta = getmeta(ref);
1567 if(meta == NULL) return 0;
1569 lua_pushboolean(L, meta->isTextModified());
1573 // reset_text_modified(self)
1574 static int l_reset_text_modified(lua_State *L)
1576 NodeMetaRef *ref = checkobject(L, 1);
1577 NodeMetadata *meta = getmeta(ref);
1578 if(meta == NULL) return 0;
1580 meta->resetTextModified();
1581 reportMetadataChange(ref);
1585 // set_string(self, name, var)
1586 static int l_set_string(lua_State *L)
1588 NodeMetaRef *ref = checkobject(L, 1);
1589 NodeMetadata *meta = getmeta(ref);
1590 if(meta == NULL) return 0;
1592 std::string name = lua_tostring(L, 2);
1594 const char *s = lua_tolstring(L, 3, &len);
1595 std::string str(s, len);
1596 meta->setString(name, str);
1597 reportMetadataChange(ref);
1601 // get_string(self, name)
1602 static int l_get_string(lua_State *L)
1604 NodeMetaRef *ref = checkobject(L, 1);
1605 NodeMetadata *meta = getmeta(ref);
1606 if(meta == NULL) return 0;
1608 std::string name = lua_tostring(L, 2);
1609 std::string str = meta->getString(name);
1610 lua_pushlstring(L, str.c_str(), str.size());
1615 NodeMetaRef(v3s16 p, ServerEnvironment *env):
1625 // Creates an NodeMetaRef and leaves it on top of stack
1626 // Not callable from Lua; all references are created on the C side.
1627 static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
1629 NodeMetaRef *o = new NodeMetaRef(p, env);
1630 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
1631 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1632 luaL_getmetatable(L, className);
1633 lua_setmetatable(L, -2);
1636 static void Register(lua_State *L)
1639 int methodtable = lua_gettop(L);
1640 luaL_newmetatable(L, className);
1641 int metatable = lua_gettop(L);
1643 lua_pushliteral(L, "__metatable");
1644 lua_pushvalue(L, methodtable);
1645 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1647 lua_pushliteral(L, "__index");
1648 lua_pushvalue(L, methodtable);
1649 lua_settable(L, metatable);
1651 lua_pushliteral(L, "__gc");
1652 lua_pushcfunction(L, gc_object);
1653 lua_settable(L, metatable);
1655 lua_pop(L, 1); // drop metatable
1657 luaL_openlib(L, 0, methods, 0); // fill methodtable
1658 lua_pop(L, 1); // drop methodtable
1660 // Cannot be created from Lua
1661 //lua_register(L, className, create_object);
1664 const char NodeMetaRef::className[] = "NodeMetaRef";
1665 const luaL_reg NodeMetaRef::methods[] = {
1666 method(NodeMetaRef, get_type),
1667 method(NodeMetaRef, allows_text_input),
1668 method(NodeMetaRef, set_text),
1669 method(NodeMetaRef, get_text),
1670 method(NodeMetaRef, get_owner),
1671 method(NodeMetaRef, set_infotext),
1672 method(NodeMetaRef, inventory_set_list),
1673 method(NodeMetaRef, inventory_get_list),
1674 method(NodeMetaRef, set_inventory_draw_spec),
1675 method(NodeMetaRef, set_allow_text_input),
1676 method(NodeMetaRef, set_allow_removal),
1677 method(NodeMetaRef, set_enforce_owner),
1678 method(NodeMetaRef, is_inventory_modified),
1679 method(NodeMetaRef, reset_inventory_modified),
1680 method(NodeMetaRef, is_text_modified),
1681 method(NodeMetaRef, reset_text_modified),
1682 method(NodeMetaRef, set_string),
1683 method(NodeMetaRef, get_string),
1694 ServerActiveObject *m_object;
1696 static const char className[];
1697 static const luaL_reg methods[];
1699 static ObjectRef *checkobject(lua_State *L, int narg)
1701 luaL_checktype(L, narg, LUA_TUSERDATA);
1702 void *ud = luaL_checkudata(L, narg, className);
1703 if(!ud) luaL_typerror(L, narg, className);
1704 return *(ObjectRef**)ud; // unbox pointer
1707 static ServerActiveObject* getobject(ObjectRef *ref)
1709 ServerActiveObject *co = ref->m_object;
1713 static LuaEntitySAO* getluaobject(ObjectRef *ref)
1715 ServerActiveObject *obj = getobject(ref);
1718 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1720 return (LuaEntitySAO*)obj;
1723 static ServerRemotePlayer* getplayer(ObjectRef *ref)
1725 ServerActiveObject *obj = getobject(ref);
1728 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
1730 return static_cast<ServerRemotePlayer*>(obj);
1733 // Exported functions
1735 // garbage collector
1736 static int gc_object(lua_State *L) {
1737 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1738 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1744 static int l_remove(lua_State *L)
1746 ObjectRef *ref = checkobject(L, 1);
1747 ServerActiveObject *co = getobject(ref);
1748 if(co == NULL) return 0;
1749 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1750 co->m_removed = true;
1755 // returns: {x=num, y=num, z=num}
1756 static int l_getpos(lua_State *L)
1758 ObjectRef *ref = checkobject(L, 1);
1759 ServerActiveObject *co = getobject(ref);
1760 if(co == NULL) return 0;
1761 v3f pos = co->getBasePosition() / BS;
1763 lua_pushnumber(L, pos.X);
1764 lua_setfield(L, -2, "x");
1765 lua_pushnumber(L, pos.Y);
1766 lua_setfield(L, -2, "y");
1767 lua_pushnumber(L, pos.Z);
1768 lua_setfield(L, -2, "z");
1772 // setpos(self, pos)
1773 static int l_setpos(lua_State *L)
1775 ObjectRef *ref = checkobject(L, 1);
1776 //LuaEntitySAO *co = getluaobject(ref);
1777 ServerActiveObject *co = getobject(ref);
1778 if(co == NULL) return 0;
1780 v3f pos = readFloatPos(L, 2);
1786 // moveto(self, pos, continuous=false)
1787 static int l_moveto(lua_State *L)
1789 ObjectRef *ref = checkobject(L, 1);
1790 //LuaEntitySAO *co = getluaobject(ref);
1791 ServerActiveObject *co = getobject(ref);
1792 if(co == NULL) return 0;
1794 v3f pos = readFloatPos(L, 2);
1796 bool continuous = lua_toboolean(L, 3);
1798 co->moveTo(pos, continuous);
1802 // punch(self, puncher); puncher = an another ObjectRef
1803 static int l_punch(lua_State *L)
1805 ObjectRef *ref = checkobject(L, 1);
1806 ObjectRef *ref2 = checkobject(L, 2);
1807 ServerActiveObject *co = getobject(ref);
1808 ServerActiveObject *co2 = getobject(ref2);
1809 if(co == NULL) return 0;
1810 if(co2 == NULL) return 0;
1816 // right_click(self, clicker); clicker = an another ObjectRef
1817 static int l_right_click(lua_State *L)
1819 ObjectRef *ref = checkobject(L, 1);
1820 ObjectRef *ref2 = checkobject(L, 2);
1821 ServerActiveObject *co = getobject(ref);
1822 ServerActiveObject *co2 = getobject(ref2);
1823 if(co == NULL) return 0;
1824 if(co2 == NULL) return 0;
1826 co->rightClick(co2);
1830 // get_wield_digging_properties(self)
1831 static int l_get_wield_digging_properties(lua_State *L)
1833 ObjectRef *ref = checkobject(L, 1);
1834 ServerActiveObject *co = getobject(ref);
1835 if(co == NULL) return 0;
1837 ToolDiggingProperties prop;
1838 co->getWieldDiggingProperties(&prop);
1839 push_tool_digging_properties(L, prop);
1843 // damage_wielded_item(self, amount)
1844 static int l_damage_wielded_item(lua_State *L)
1846 ObjectRef *ref = checkobject(L, 1);
1847 ServerActiveObject *co = getobject(ref);
1848 if(co == NULL) return 0;
1850 int amount = lua_tonumber(L, 2);
1851 co->damageWieldedItem(amount);
1855 // add_to_inventory(self, itemstring)
1856 // returns: true if item was added, (false, "reason") otherwise
1857 static int l_add_to_inventory(lua_State *L)
1859 ObjectRef *ref = checkobject(L, 1);
1860 luaL_checkstring(L, 2);
1861 ServerActiveObject *co = getobject(ref);
1862 if(co == NULL) return 0;
1864 const char *itemstring = lua_tostring(L, 2);
1865 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1866 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1868 std::istringstream is(itemstring, std::ios::binary);
1869 ServerEnvironment *env = co->getEnv();
1871 IGameDef *gamedef = env->getGameDef();
1873 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1874 if(item->getCount() == 0)
1876 bool added = co->addToInventory(item);
1878 lua_pushboolean(L, added);
1880 lua_pushstring(L, "failed to add item");
1882 } catch(SerializationError &e){
1884 lua_pushboolean(L, false);
1885 lua_pushstring(L, (std::string("Invalid item: ")
1886 + e.what()).c_str());
1891 // add_to_inventory_later(self, itemstring)
1893 static int l_add_to_inventory_later(lua_State *L)
1895 ObjectRef *ref = checkobject(L, 1);
1896 luaL_checkstring(L, 2);
1897 ServerActiveObject *co = getobject(ref);
1898 if(co == NULL) return 0;
1900 const char *itemstring = lua_tostring(L, 2);
1901 infostream<<"ObjectRef::l_add_to_inventory_later(): id="<<co->getId()
1902 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1904 std::istringstream is(itemstring, std::ios::binary);
1905 ServerEnvironment *env = co->getEnv();
1907 IGameDef *gamedef = env->getGameDef();
1908 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1909 infostream<<"item="<<env<<std::endl;
1910 co->addToInventoryLater(item);
1916 // hp = number of hitpoints (2 * number of hearts)
1918 static int l_set_hp(lua_State *L)
1920 ObjectRef *ref = checkobject(L, 1);
1921 luaL_checknumber(L, 2);
1922 ServerActiveObject *co = getobject(ref);
1923 if(co == NULL) return 0;
1924 int hp = lua_tonumber(L, 2);
1925 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
1926 <<" hp="<<hp<<std::endl;
1934 // returns: number of hitpoints (2 * number of hearts)
1935 // 0 if not applicable to this type of object
1936 static int l_get_hp(lua_State *L)
1938 ObjectRef *ref = checkobject(L, 1);
1939 ServerActiveObject *co = getobject(ref);
1940 if(co == NULL) return 0;
1941 int hp = co->getHP();
1942 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
1943 <<" hp="<<hp<<std::endl;
1945 lua_pushnumber(L, hp);
1949 /* LuaEntitySAO-only */
1951 // setvelocity(self, {x=num, y=num, z=num})
1952 static int l_setvelocity(lua_State *L)
1954 ObjectRef *ref = checkobject(L, 1);
1955 LuaEntitySAO *co = getluaobject(ref);
1956 if(co == NULL) return 0;
1958 v3f pos = readFloatPos(L, 2);
1960 co->setVelocity(pos);
1964 // setacceleration(self, {x=num, y=num, z=num})
1965 static int l_setacceleration(lua_State *L)
1967 ObjectRef *ref = checkobject(L, 1);
1968 LuaEntitySAO *co = getluaobject(ref);
1969 if(co == NULL) return 0;
1971 v3f pos = readFloatPos(L, 2);
1973 co->setAcceleration(pos);
1977 // getacceleration(self)
1978 static int l_getacceleration(lua_State *L)
1980 ObjectRef *ref = checkobject(L, 1);
1981 LuaEntitySAO *co = getluaobject(ref);
1982 if(co == NULL) return 0;
1984 v3f v = co->getAcceleration();
1989 // settexturemod(self, mod)
1990 static int l_settexturemod(lua_State *L)
1992 ObjectRef *ref = checkobject(L, 1);
1993 LuaEntitySAO *co = getluaobject(ref);
1994 if(co == NULL) return 0;
1996 std::string mod = lua_tostring(L, 2);
1997 co->setTextureMod(mod);
2001 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
2002 // select_horiz_by_yawpitch=false)
2003 static int l_setsprite(lua_State *L)
2005 ObjectRef *ref = checkobject(L, 1);
2006 LuaEntitySAO *co = getluaobject(ref);
2007 if(co == NULL) return 0;
2010 if(!lua_isnil(L, 2))
2011 p = read_v2s16(L, 2);
2013 if(!lua_isnil(L, 3))
2014 num_frames = lua_tonumber(L, 3);
2015 float framelength = 0.2;
2016 if(!lua_isnil(L, 4))
2017 framelength = lua_tonumber(L, 4);
2018 bool select_horiz_by_yawpitch = false;
2019 if(!lua_isnil(L, 5))
2020 select_horiz_by_yawpitch = lua_toboolean(L, 5);
2021 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
2027 // get_player_name(self)
2028 static int l_get_player_name(lua_State *L)
2030 ObjectRef *ref = checkobject(L, 1);
2031 ServerRemotePlayer *player = getplayer(ref);
2037 lua_pushstring(L, player->getName());
2041 // inventory_set_list(self, name, {item1, item2, ...})
2042 static int l_inventory_set_list(lua_State *L)
2044 ObjectRef *ref = checkobject(L, 1);
2045 ServerRemotePlayer *player = getplayer(ref);
2046 if(player == NULL) return 0;
2047 const char *name = lua_tostring(L, 2);
2049 inventory_set_list_from_lua(&player->inventory, name, L, 3,
2050 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2051 player->m_inventory_not_sent = true;
2055 // inventory_get_list(self, name)
2056 static int l_inventory_get_list(lua_State *L)
2058 ObjectRef *ref = checkobject(L, 1);
2059 ServerRemotePlayer *player = getplayer(ref);
2060 if(player == NULL) return 0;
2061 const char *name = lua_tostring(L, 2);
2063 inventory_get_list_to_lua(&player->inventory, name, L);
2067 // get_wielded_itemstring(self)
2068 static int l_get_wielded_itemstring(lua_State *L)
2070 ObjectRef *ref = checkobject(L, 1);
2071 ServerRemotePlayer *player = getplayer(ref);
2072 if(player == NULL) return 0;
2074 InventoryItem *item = player->getWieldedItem();
2079 lua_pushstring(L, item->getItemString().c_str());
2083 // get_wielded_item(self)
2084 static int l_get_wielded_item(lua_State *L)
2086 ObjectRef *ref = checkobject(L, 1);
2087 ServerRemotePlayer *player = getplayer(ref);
2088 if(player == NULL) return 0;
2090 InventoryItem *item0 = player->getWieldedItem();
2095 if(std::string("MaterialItem") == item0->getName()){
2096 MaterialItem *item = (MaterialItem*)item0;
2098 lua_pushstring(L, "NodeItem");
2099 lua_setfield(L, -2, "type");
2100 lua_pushstring(L, item->getNodeName().c_str());
2101 lua_setfield(L, -2, "name");
2103 else if(std::string("CraftItem") == item0->getName()){
2104 CraftItem *item = (CraftItem*)item0;
2106 lua_pushstring(L, "CraftItem");
2107 lua_setfield(L, -2, "type");
2108 lua_pushstring(L, item->getSubName().c_str());
2109 lua_setfield(L, -2, "name");
2111 else if(std::string("ToolItem") == item0->getName()){
2112 ToolItem *item = (ToolItem*)item0;
2114 lua_pushstring(L, "ToolItem");
2115 lua_setfield(L, -2, "type");
2116 lua_pushstring(L, item->getToolName().c_str());
2117 lua_setfield(L, -2, "name");
2118 lua_pushstring(L, itos(item->getWear()).c_str());
2119 lua_setfield(L, -2, "wear");
2122 errorstream<<"l_get_wielded_item: Unknown item name: \""
2123 <<item0->getName()<<"\""<<std::endl;
2130 ObjectRef(ServerActiveObject *object):
2133 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2139 infostream<<"ObjectRef destructing for id="
2140 <<m_object->getId()<<std::endl;
2142 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
2145 // Creates an ObjectRef and leaves it on top of stack
2146 // Not callable from Lua; all references are created on the C side.
2147 static void create(lua_State *L, ServerActiveObject *object)
2149 ObjectRef *o = new ObjectRef(object);
2150 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2151 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2152 luaL_getmetatable(L, className);
2153 lua_setmetatable(L, -2);
2156 static void set_null(lua_State *L)
2158 ObjectRef *o = checkobject(L, -1);
2162 static void Register(lua_State *L)
2165 int methodtable = lua_gettop(L);
2166 luaL_newmetatable(L, className);
2167 int metatable = lua_gettop(L);
2169 lua_pushliteral(L, "__metatable");
2170 lua_pushvalue(L, methodtable);
2171 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2173 lua_pushliteral(L, "__index");
2174 lua_pushvalue(L, methodtable);
2175 lua_settable(L, metatable);
2177 lua_pushliteral(L, "__gc");
2178 lua_pushcfunction(L, gc_object);
2179 lua_settable(L, metatable);
2181 lua_pop(L, 1); // drop metatable
2183 luaL_openlib(L, 0, methods, 0); // fill methodtable
2184 lua_pop(L, 1); // drop methodtable
2186 // Cannot be created from Lua
2187 //lua_register(L, className, create_object);
2190 const char ObjectRef::className[] = "ObjectRef";
2191 const luaL_reg ObjectRef::methods[] = {
2192 // ServerActiveObject
2193 method(ObjectRef, remove),
2194 method(ObjectRef, getpos),
2195 method(ObjectRef, setpos),
2196 method(ObjectRef, moveto),
2197 method(ObjectRef, punch),
2198 method(ObjectRef, right_click),
2199 method(ObjectRef, get_wield_digging_properties),
2200 method(ObjectRef, damage_wielded_item),
2201 method(ObjectRef, add_to_inventory),
2202 method(ObjectRef, add_to_inventory_later),
2203 method(ObjectRef, set_hp),
2204 method(ObjectRef, get_hp),
2205 // LuaEntitySAO-only
2206 method(ObjectRef, setvelocity),
2207 method(ObjectRef, setacceleration),
2208 method(ObjectRef, getacceleration),
2209 method(ObjectRef, settexturemod),
2210 method(ObjectRef, setsprite),
2212 method(ObjectRef, get_player_name),
2213 method(ObjectRef, inventory_set_list),
2214 method(ObjectRef, inventory_get_list),
2215 method(ObjectRef, get_wielded_itemstring),
2216 method(ObjectRef, get_wielded_item),
2220 // Creates a new anonymous reference if id=0
2221 static void objectref_get_or_create(lua_State *L,
2222 ServerActiveObject *cobj)
2224 if(cobj->getId() == 0){
2225 ObjectRef::create(L, cobj);
2227 objectref_get(L, cobj->getId());
2238 ServerEnvironment *m_env;
2240 static const char className[];
2241 static const luaL_reg methods[];
2243 static EnvRef *checkobject(lua_State *L, int narg)
2245 luaL_checktype(L, narg, LUA_TUSERDATA);
2246 void *ud = luaL_checkudata(L, narg, className);
2247 if(!ud) luaL_typerror(L, narg, className);
2248 return *(EnvRef**)ud; // unbox pointer
2251 // Exported functions
2253 // EnvRef:add_node(pos, node)
2254 // pos = {x=num, y=num, z=num}
2255 static int l_add_node(lua_State *L)
2257 //infostream<<"EnvRef::l_add_node()"<<std::endl;
2258 EnvRef *o = checkobject(L, 1);
2259 ServerEnvironment *env = o->m_env;
2260 if(env == NULL) return 0;
2262 v3s16 pos = readpos(L, 2);
2264 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
2266 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
2267 lua_pushboolean(L, succeeded);
2271 // EnvRef:remove_node(pos)
2272 // pos = {x=num, y=num, z=num}
2273 static int l_remove_node(lua_State *L)
2275 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
2276 EnvRef *o = checkobject(L, 1);
2277 ServerEnvironment *env = o->m_env;
2278 if(env == NULL) return 0;
2280 v3s16 pos = readpos(L, 2);
2282 bool succeeded = env->getMap().removeNodeWithEvent(pos);
2283 lua_pushboolean(L, succeeded);
2287 // EnvRef:get_node(pos)
2288 // pos = {x=num, y=num, z=num}
2289 static int l_get_node(lua_State *L)
2291 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2292 EnvRef *o = checkobject(L, 1);
2293 ServerEnvironment *env = o->m_env;
2294 if(env == NULL) return 0;
2296 v3s16 pos = readpos(L, 2);
2298 MapNode n = env->getMap().getNodeNoEx(pos);
2300 pushnode(L, n, env->getGameDef()->ndef());
2304 // EnvRef:add_luaentity(pos, entityname)
2305 // pos = {x=num, y=num, z=num}
2306 static int l_add_luaentity(lua_State *L)
2308 //infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
2309 EnvRef *o = checkobject(L, 1);
2310 ServerEnvironment *env = o->m_env;
2311 if(env == NULL) return 0;
2313 v3f pos = readFloatPos(L, 2);
2315 const char *name = lua_tostring(L, 3);
2317 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
2318 env->addActiveObject(obj);
2322 // EnvRef:add_item(pos, inventorystring)
2323 // pos = {x=num, y=num, z=num}
2324 static int l_add_item(lua_State *L)
2326 infostream<<"EnvRef::l_add_item()"<<std::endl;
2327 EnvRef *o = checkobject(L, 1);
2328 ServerEnvironment *env = o->m_env;
2329 if(env == NULL) return 0;
2331 v3f pos = readFloatPos(L, 2);
2333 const char *inventorystring = lua_tostring(L, 3);
2335 ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring);
2336 env->addActiveObject(obj);
2340 // EnvRef:add_rat(pos)
2341 // pos = {x=num, y=num, z=num}
2342 static int l_add_rat(lua_State *L)
2344 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2345 EnvRef *o = checkobject(L, 1);
2346 ServerEnvironment *env = o->m_env;
2347 if(env == NULL) return 0;
2349 v3f pos = readFloatPos(L, 2);
2351 ServerActiveObject *obj = new RatSAO(env, pos);
2352 env->addActiveObject(obj);
2356 // EnvRef:add_firefly(pos)
2357 // pos = {x=num, y=num, z=num}
2358 static int l_add_firefly(lua_State *L)
2360 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2361 EnvRef *o = checkobject(L, 1);
2362 ServerEnvironment *env = o->m_env;
2363 if(env == NULL) return 0;
2365 v3f pos = readFloatPos(L, 2);
2367 ServerActiveObject *obj = new FireflySAO(env, pos);
2368 env->addActiveObject(obj);
2372 // EnvRef:get_meta(pos)
2373 static int l_get_meta(lua_State *L)
2375 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2376 EnvRef *o = checkobject(L, 1);
2377 ServerEnvironment *env = o->m_env;
2378 if(env == NULL) return 0;
2380 v3s16 p = readpos(L, 2);
2381 NodeMetaRef::create(L, p, env);
2385 // EnvRef:get_player_by_name(name)
2386 static int l_get_player_by_name(lua_State *L)
2388 EnvRef *o = checkobject(L, 1);
2389 ServerEnvironment *env = o->m_env;
2390 if(env == NULL) return 0;
2392 const char *name = lua_tostring(L, 2);
2393 ServerRemotePlayer *player =
2394 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2399 // Put player on stack
2400 objectref_get_or_create(L, player);
2404 static int gc_object(lua_State *L) {
2405 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
2411 EnvRef(ServerEnvironment *env):
2414 infostream<<"EnvRef created"<<std::endl;
2419 infostream<<"EnvRef destructing"<<std::endl;
2422 // Creates an EnvRef and leaves it on top of stack
2423 // Not callable from Lua; all references are created on the C side.
2424 static void create(lua_State *L, ServerEnvironment *env)
2426 EnvRef *o = new EnvRef(env);
2427 //infostream<<"EnvRef::create: o="<<o<<std::endl;
2428 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2429 luaL_getmetatable(L, className);
2430 lua_setmetatable(L, -2);
2433 static void set_null(lua_State *L)
2435 EnvRef *o = checkobject(L, -1);
2439 static void Register(lua_State *L)
2442 int methodtable = lua_gettop(L);
2443 luaL_newmetatable(L, className);
2444 int metatable = lua_gettop(L);
2446 lua_pushliteral(L, "__metatable");
2447 lua_pushvalue(L, methodtable);
2448 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2450 lua_pushliteral(L, "__index");
2451 lua_pushvalue(L, methodtable);
2452 lua_settable(L, metatable);
2454 lua_pushliteral(L, "__gc");
2455 lua_pushcfunction(L, gc_object);
2456 lua_settable(L, metatable);
2458 lua_pop(L, 1); // drop metatable
2460 luaL_openlib(L, 0, methods, 0); // fill methodtable
2461 lua_pop(L, 1); // drop methodtable
2463 // Cannot be created from Lua
2464 //lua_register(L, className, create_object);
2467 const char EnvRef::className[] = "EnvRef";
2468 const luaL_reg EnvRef::methods[] = {
2469 method(EnvRef, add_node),
2470 method(EnvRef, remove_node),
2471 method(EnvRef, get_node),
2472 method(EnvRef, add_luaentity),
2473 method(EnvRef, add_item),
2474 method(EnvRef, add_rat),
2475 method(EnvRef, add_firefly),
2476 method(EnvRef, get_meta),
2477 method(EnvRef, get_player_by_name),
2482 Main export function
2485 void scriptapi_export(lua_State *L, Server *server)
2488 assert(lua_checkstack(L, 20));
2489 infostream<<"scriptapi_export"<<std::endl;
2490 StackUnroller stack_unroller(L);
2492 // Store server as light userdata in registry
2493 lua_pushlightuserdata(L, server);
2494 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
2496 // Store nil as minetest_nodedef_defaults in registry
2498 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
2500 // Register global functions in table minetest
2502 luaL_register(L, NULL, minetest_f);
2503 lua_setglobal(L, "minetest");
2505 // Get the main minetest table
2506 lua_getglobal(L, "minetest");
2508 // Add tables to minetest
2511 lua_setfield(L, -2, "registered_nodes");
2513 lua_setfield(L, -2, "registered_entities");
2515 lua_setfield(L, -2, "registered_craftitems");
2517 lua_setfield(L, -2, "registered_abms");
2520 lua_setfield(L, -2, "object_refs");
2522 lua_setfield(L, -2, "luaentities");
2524 // Create entity prototype
2525 luaL_newmetatable(L, "minetest.entity");
2526 // metatable.__index = metatable
2527 lua_pushvalue(L, -1); // Duplicate metatable
2528 lua_setfield(L, -2, "__index");
2529 // Put functions in metatable
2530 luaL_register(L, NULL, minetest_entity_m);
2531 // Put other stuff in metatable
2533 // Register reference wrappers
2534 NodeMetaRef::Register(L);
2535 EnvRef::Register(L);
2536 ObjectRef::Register(L);
2539 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
2540 const std::string &modname)
2542 ModNameStorer modnamestorer(L, modname);
2544 bool success = false;
2547 success = script_load(L, scriptpath.c_str());
2550 errorstream<<"Error loading mod \""<<modname
2551 <<"\": "<<e.what()<<std::endl;
2557 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
2560 assert(lua_checkstack(L, 20));
2561 infostream<<"scriptapi_add_environment"<<std::endl;
2562 StackUnroller stack_unroller(L);
2564 // Create EnvRef on stack
2565 EnvRef::create(L, env);
2566 int envref = lua_gettop(L);
2568 // minetest.env = envref
2569 lua_getglobal(L, "minetest");
2570 luaL_checktype(L, -1, LUA_TTABLE);
2571 lua_pushvalue(L, envref);
2572 lua_setfield(L, -2, "env");
2574 // Store environment as light userdata in registry
2575 lua_pushlightuserdata(L, env);
2576 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
2578 /* Add ActiveBlockModifiers to environment */
2580 // Get minetest.registered_abms
2581 lua_getglobal(L, "minetest");
2582 lua_getfield(L, -1, "registered_abms");
2583 luaL_checktype(L, -1, LUA_TTABLE);
2584 int registered_abms = lua_gettop(L);
2586 if(lua_istable(L, registered_abms)){
2587 int table = lua_gettop(L);
2589 while(lua_next(L, table) != 0){
2590 // key at index -2 and value at index -1
2591 int id = lua_tonumber(L, -2);
2592 int current_abm = lua_gettop(L);
2594 std::set<std::string> trigger_contents;
2595 lua_getfield(L, current_abm, "nodenames");
2596 if(lua_istable(L, -1)){
2597 int table = lua_gettop(L);
2599 while(lua_next(L, table) != 0){
2600 // key at index -2 and value at index -1
2601 luaL_checktype(L, -1, LUA_TSTRING);
2602 trigger_contents.insert(lua_tostring(L, -1));
2603 // removes value, keeps key for next iteration
2609 float trigger_interval = 10.0;
2610 getfloatfield(L, current_abm, "interval", trigger_interval);
2612 int trigger_chance = 50;
2613 getintfield(L, current_abm, "chance", trigger_chance);
2615 LuaABM *abm = new LuaABM(L, id, trigger_contents,
2616 trigger_interval, trigger_chance);
2618 env->addActiveBlockModifier(abm);
2620 // removes value, keeps key for next iteration
2628 // Dump stack top with the dump2 function
2629 static void dump2(lua_State *L, const char *name)
2631 // Dump object (debug)
2632 lua_getglobal(L, "dump2");
2633 luaL_checktype(L, -1, LUA_TFUNCTION);
2634 lua_pushvalue(L, -2); // Get previous stack top as first parameter
2635 lua_pushstring(L, name);
2636 if(lua_pcall(L, 2, 0, 0))
2637 script_error(L, "error: %s", lua_tostring(L, -1));
2645 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
2648 assert(lua_checkstack(L, 20));
2649 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
2650 StackUnroller stack_unroller(L);
2652 // Create object on stack
2653 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
2654 int object = lua_gettop(L);
2656 // Get minetest.object_refs table
2657 lua_getglobal(L, "minetest");
2658 lua_getfield(L, -1, "object_refs");
2659 luaL_checktype(L, -1, LUA_TTABLE);
2660 int objectstable = lua_gettop(L);
2662 // object_refs[id] = object
2663 lua_pushnumber(L, cobj->getId()); // Push id
2664 lua_pushvalue(L, object); // Copy object to top of stack
2665 lua_settable(L, objectstable);
2668 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
2671 assert(lua_checkstack(L, 20));
2672 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
2673 StackUnroller stack_unroller(L);
2675 // Get minetest.object_refs table
2676 lua_getglobal(L, "minetest");
2677 lua_getfield(L, -1, "object_refs");
2678 luaL_checktype(L, -1, LUA_TTABLE);
2679 int objectstable = lua_gettop(L);
2681 // Get object_refs[id]
2682 lua_pushnumber(L, cobj->getId()); // Push id
2683 lua_gettable(L, objectstable);
2684 // Set object reference to NULL
2685 ObjectRef::set_null(L);
2686 lua_pop(L, 1); // pop object
2688 // Set object_refs[id] = nil
2689 lua_pushnumber(L, cobj->getId()); // Push id
2691 lua_settable(L, objectstable);
2694 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
2695 const std::string &message)
2698 assert(lua_checkstack(L, 20));
2699 StackUnroller stack_unroller(L);
2701 // Get minetest.registered_on_chat_messages
2702 lua_getglobal(L, "minetest");
2703 lua_getfield(L, -1, "registered_on_chat_messages");
2704 luaL_checktype(L, -1, LUA_TTABLE);
2705 int table = lua_gettop(L);
2708 while(lua_next(L, table) != 0){
2709 // key at index -2 and value at index -1
2710 luaL_checktype(L, -1, LUA_TFUNCTION);
2712 lua_pushstring(L, name.c_str());
2713 lua_pushstring(L, message.c_str());
2714 if(lua_pcall(L, 2, 1, 0))
2715 script_error(L, "error: %s", lua_tostring(L, -1));
2716 bool ate = lua_toboolean(L, -1);
2720 // value removed, keep key for next iteration
2729 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
2732 assert(lua_checkstack(L, 20));
2733 StackUnroller stack_unroller(L);
2735 // Get minetest.registered_on_newplayers
2736 lua_getglobal(L, "minetest");
2737 lua_getfield(L, -1, "registered_on_newplayers");
2738 luaL_checktype(L, -1, LUA_TTABLE);
2739 int table = lua_gettop(L);
2742 while(lua_next(L, table) != 0){
2743 // key at index -2 and value at index -1
2744 luaL_checktype(L, -1, LUA_TFUNCTION);
2746 objectref_get_or_create(L, player);
2747 if(lua_pcall(L, 1, 0, 0))
2748 script_error(L, "error: %s", lua_tostring(L, -1));
2749 // value removed, keep key for next iteration
2752 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
2755 assert(lua_checkstack(L, 20));
2756 StackUnroller stack_unroller(L);
2758 bool positioning_handled_by_some = false;
2760 // Get minetest.registered_on_respawnplayers
2761 lua_getglobal(L, "minetest");
2762 lua_getfield(L, -1, "registered_on_respawnplayers");
2763 luaL_checktype(L, -1, LUA_TTABLE);
2764 int table = lua_gettop(L);
2767 while(lua_next(L, table) != 0){
2768 // key at index -2 and value at index -1
2769 luaL_checktype(L, -1, LUA_TFUNCTION);
2771 objectref_get_or_create(L, player);
2772 if(lua_pcall(L, 1, 1, 0))
2773 script_error(L, "error: %s", lua_tostring(L, -1));
2774 bool positioning_handled = lua_toboolean(L, -1);
2776 if(positioning_handled)
2777 positioning_handled_by_some = true;
2778 // value removed, keep key for next iteration
2780 return positioning_handled_by_some;
2783 void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
2785 lua_getglobal(L, "minetest");
2786 lua_getfield(L, -1, "creative_inventory");
2787 luaL_checktype(L, -1, LUA_TTABLE);
2788 inventory_set_list_from_lua(&player->inventory, "main", L, -1,
2789 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2796 static void pushPointedThing(lua_State *L, const PointedThing& pointed)
2799 if(pointed.type == POINTEDTHING_NODE)
2801 lua_pushstring(L, "node");
2802 lua_setfield(L, -2, "type");
2803 pushpos(L, pointed.node_undersurface);
2804 lua_setfield(L, -2, "under");
2805 pushpos(L, pointed.node_abovesurface);
2806 lua_setfield(L, -2, "above");
2808 else if(pointed.type == POINTEDTHING_OBJECT)
2810 lua_pushstring(L, "object");
2811 lua_setfield(L, -2, "type");
2812 objectref_get(L, pointed.object_id);
2813 lua_setfield(L, -2, "ref");
2817 lua_pushstring(L, "nothing");
2818 lua_setfield(L, -2, "type");
2822 void scriptapi_add_craftitem(lua_State *L, const char *name)
2824 StackUnroller stack_unroller(L);
2825 assert(lua_gettop(L) > 0);
2827 // Set minetest.registered_craftitems[name] = table on top of stack
2828 lua_getglobal(L, "minetest");
2829 lua_getfield(L, -1, "registered_craftitems");
2830 luaL_checktype(L, -1, LUA_TTABLE);
2831 lua_pushvalue(L, -3); // push another reference to the table to be registered
2832 lua_setfield(L, -2, name); // set minetest.registered_craftitems[name]
2835 static bool get_craftitem_callback(lua_State *L, const char *name,
2836 const char *callbackname)
2838 // Get minetest.registered_craftitems[name][callbackname]
2839 // If that is nil or on error, return false and stack is unchanged
2840 // If that is a function, returns true and pushes the
2841 // function onto the stack
2843 lua_getglobal(L, "minetest");
2844 lua_getfield(L, -1, "registered_craftitems");
2846 luaL_checktype(L, -1, LUA_TTABLE);
2847 lua_getfield(L, -1, name);
2849 // Should be a table
2850 if(lua_type(L, -1) != LUA_TTABLE)
2852 errorstream<<"CraftItem name \""<<name<<"\" not defined"<<std::endl;
2856 lua_getfield(L, -1, callbackname);
2858 // Should be a function or nil
2859 if(lua_type(L, -1) == LUA_TFUNCTION)
2863 else if(lua_isnil(L, -1))
2870 errorstream<<"CraftItem name \""<<name<<"\" callback \""
2871 <<callbackname<<" is not a function"<<std::endl;
2877 bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
2878 ServerActiveObject *dropper, v3f pos,
2879 bool &callback_exists)
2882 assert(lua_checkstack(L, 20));
2883 //infostream<<"scriptapi_craftitem_on_drop"<<std::endl;
2884 StackUnroller stack_unroller(L);
2886 bool result = false;
2887 callback_exists = get_craftitem_callback(L, name, "on_drop");
2891 lua_pushstring(L, name);
2892 objectref_get_or_create(L, dropper);
2893 pushFloatPos(L, pos);
2894 if(lua_pcall(L, 3, 1, 0))
2895 script_error(L, "error: %s", lua_tostring(L, -1));
2896 result = lua_toboolean(L, -1);
2901 bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
2902 ServerActiveObject *placer, v3f pos,
2903 bool &callback_exists)
2906 assert(lua_checkstack(L, 20));
2907 //infostream<<"scriptapi_craftitem_on_place_on_ground"<<std::endl;
2908 StackUnroller stack_unroller(L);
2910 bool result = false;
2911 callback_exists = get_craftitem_callback(L, name, "on_place_on_ground");
2915 lua_pushstring(L, name);
2916 objectref_get_or_create(L, placer);
2917 pushFloatPos(L, pos);
2918 if(lua_pcall(L, 3, 1, 0))
2919 script_error(L, "error: %s", lua_tostring(L, -1));
2920 result = lua_toboolean(L, -1);
2925 bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
2926 ServerActiveObject *user, const PointedThing& pointed,
2927 bool &callback_exists)
2930 assert(lua_checkstack(L, 20));
2931 //infostream<<"scriptapi_craftitem_on_use"<<std::endl;
2932 StackUnroller stack_unroller(L);
2934 bool result = false;
2935 callback_exists = get_craftitem_callback(L, name, "on_use");
2939 lua_pushstring(L, name);
2940 objectref_get_or_create(L, user);
2941 pushPointedThing(L, pointed);
2942 if(lua_pcall(L, 3, 1, 0))
2943 script_error(L, "error: %s", lua_tostring(L, -1));
2944 result = lua_toboolean(L, -1);
2953 void scriptapi_environment_step(lua_State *L, float dtime)
2956 assert(lua_checkstack(L, 20));
2957 //infostream<<"scriptapi_environment_step"<<std::endl;
2958 StackUnroller stack_unroller(L);
2960 // Get minetest.registered_globalsteps
2961 lua_getglobal(L, "minetest");
2962 lua_getfield(L, -1, "registered_globalsteps");
2963 luaL_checktype(L, -1, LUA_TTABLE);
2964 int table = lua_gettop(L);
2967 while(lua_next(L, table) != 0){
2968 // key at index -2 and value at index -1
2969 luaL_checktype(L, -1, LUA_TFUNCTION);
2971 lua_pushnumber(L, dtime);
2972 if(lua_pcall(L, 1, 0, 0))
2973 script_error(L, "error: %s", lua_tostring(L, -1));
2974 // value removed, keep key for next iteration
2978 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
2979 ServerActiveObject *placer)
2982 assert(lua_checkstack(L, 20));
2983 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
2984 StackUnroller stack_unroller(L);
2986 // Get server from registry
2987 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
2988 Server *server = (Server*)lua_touserdata(L, -1);
2989 // And get the writable node definition manager from the server
2990 IWritableNodeDefManager *ndef =
2991 server->getWritableNodeDefManager();
2993 // Get minetest.registered_on_placenodes
2994 lua_getglobal(L, "minetest");
2995 lua_getfield(L, -1, "registered_on_placenodes");
2996 luaL_checktype(L, -1, LUA_TTABLE);
2997 int table = lua_gettop(L);
3000 while(lua_next(L, table) != 0){
3001 // key at index -2 and value at index -1
3002 luaL_checktype(L, -1, LUA_TFUNCTION);
3005 pushnode(L, newnode, ndef);
3006 objectref_get_or_create(L, placer);
3007 if(lua_pcall(L, 3, 0, 0))
3008 script_error(L, "error: %s", lua_tostring(L, -1));
3009 // value removed, keep key for next iteration
3013 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
3014 ServerActiveObject *digger)
3017 assert(lua_checkstack(L, 20));
3018 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
3019 StackUnroller stack_unroller(L);
3021 // Get server from registry
3022 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3023 Server *server = (Server*)lua_touserdata(L, -1);
3024 // And get the writable node definition manager from the server
3025 IWritableNodeDefManager *ndef =
3026 server->getWritableNodeDefManager();
3028 // Get minetest.registered_on_dignodes
3029 lua_getglobal(L, "minetest");
3030 lua_getfield(L, -1, "registered_on_dignodes");
3031 luaL_checktype(L, -1, LUA_TTABLE);
3032 int table = lua_gettop(L);
3035 while(lua_next(L, table) != 0){
3036 // key at index -2 and value at index -1
3037 luaL_checktype(L, -1, LUA_TFUNCTION);
3040 pushnode(L, oldnode, ndef);
3041 objectref_get_or_create(L, digger);
3042 if(lua_pcall(L, 3, 0, 0))
3043 script_error(L, "error: %s", lua_tostring(L, -1));
3044 // value removed, keep key for next iteration
3048 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
3049 ServerActiveObject *puncher)
3052 assert(lua_checkstack(L, 20));
3053 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
3054 StackUnroller stack_unroller(L);
3056 // Get server from registry
3057 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3058 Server *server = (Server*)lua_touserdata(L, -1);
3059 // And get the writable node definition manager from the server
3060 IWritableNodeDefManager *ndef =
3061 server->getWritableNodeDefManager();
3063 // Get minetest.registered_on_punchnodes
3064 lua_getglobal(L, "minetest");
3065 lua_getfield(L, -1, "registered_on_punchnodes");
3066 luaL_checktype(L, -1, LUA_TTABLE);
3067 int table = lua_gettop(L);
3070 while(lua_next(L, table) != 0){
3071 // key at index -2 and value at index -1
3072 luaL_checktype(L, -1, LUA_TFUNCTION);
3075 pushnode(L, node, ndef);
3076 objectref_get_or_create(L, puncher);
3077 if(lua_pcall(L, 3, 0, 0))
3078 script_error(L, "error: %s", lua_tostring(L, -1));
3079 // value removed, keep key for next iteration
3083 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
3086 assert(lua_checkstack(L, 20));
3087 //infostream<<"scriptapi_environment_on_generated"<<std::endl;
3088 StackUnroller stack_unroller(L);
3090 // Get minetest.registered_on_generateds
3091 lua_getglobal(L, "minetest");
3092 lua_getfield(L, -1, "registered_on_generateds");
3093 luaL_checktype(L, -1, LUA_TTABLE);
3094 int table = lua_gettop(L);
3097 while(lua_next(L, table) != 0){
3098 // key at index -2 and value at index -1
3099 luaL_checktype(L, -1, LUA_TFUNCTION);
3103 if(lua_pcall(L, 2, 0, 0))
3104 script_error(L, "error: %s", lua_tostring(L, -1));
3105 // value removed, keep key for next iteration
3113 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
3114 const std::string &staticdata)
3117 assert(lua_checkstack(L, 20));
3118 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
3119 <<name<<"\""<<std::endl;
3120 StackUnroller stack_unroller(L);
3122 // Get minetest.registered_entities[name]
3123 lua_getglobal(L, "minetest");
3124 lua_getfield(L, -1, "registered_entities");
3125 luaL_checktype(L, -1, LUA_TTABLE);
3126 lua_pushstring(L, name);
3127 lua_gettable(L, -2);
3128 // Should be a table, which we will use as a prototype
3129 //luaL_checktype(L, -1, LUA_TTABLE);
3130 if(lua_type(L, -1) != LUA_TTABLE){
3131 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
3134 int prototype_table = lua_gettop(L);
3135 //dump2(L, "prototype_table");
3137 // Create entity object
3139 int object = lua_gettop(L);
3141 // Set object metatable
3142 lua_pushvalue(L, prototype_table);
3143 lua_setmetatable(L, -2);
3145 // Add object reference
3146 // This should be userdata with metatable ObjectRef
3147 objectref_get(L, id);
3148 luaL_checktype(L, -1, LUA_TUSERDATA);
3149 if(!luaL_checkudata(L, -1, "ObjectRef"))
3150 luaL_typerror(L, -1, "ObjectRef");
3151 lua_setfield(L, -2, "object");
3153 // minetest.luaentities[id] = object
3154 lua_getglobal(L, "minetest");
3155 lua_getfield(L, -1, "luaentities");
3156 luaL_checktype(L, -1, LUA_TTABLE);
3157 lua_pushnumber(L, id); // Push id
3158 lua_pushvalue(L, object); // Copy object to top of stack
3159 lua_settable(L, -3);
3161 // Get on_activate function
3162 lua_pushvalue(L, object);
3163 lua_getfield(L, -1, "on_activate");
3164 if(!lua_isnil(L, -1)){
3165 luaL_checktype(L, -1, LUA_TFUNCTION);
3166 lua_pushvalue(L, object); // self
3167 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
3168 // Call with 2 arguments, 0 results
3169 if(lua_pcall(L, 2, 0, 0))
3170 script_error(L, "error running function %s:on_activate: %s\n",
3171 name, lua_tostring(L, -1));
3177 void scriptapi_luaentity_rm(lua_State *L, u16 id)
3180 assert(lua_checkstack(L, 20));
3181 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
3183 // Get minetest.luaentities table
3184 lua_getglobal(L, "minetest");
3185 lua_getfield(L, -1, "luaentities");
3186 luaL_checktype(L, -1, LUA_TTABLE);
3187 int objectstable = lua_gettop(L);
3189 // Set luaentities[id] = nil
3190 lua_pushnumber(L, id); // Push id
3192 lua_settable(L, objectstable);
3194 lua_pop(L, 2); // pop luaentities, minetest
3197 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
3200 assert(lua_checkstack(L, 20));
3201 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
3202 StackUnroller stack_unroller(L);
3204 // Get minetest.luaentities[id]
3205 luaentity_get(L, id);
3206 int object = lua_gettop(L);
3208 // Get get_staticdata function
3209 lua_pushvalue(L, object);
3210 lua_getfield(L, -1, "get_staticdata");
3211 if(lua_isnil(L, -1))
3214 luaL_checktype(L, -1, LUA_TFUNCTION);
3215 lua_pushvalue(L, object); // self
3216 // Call with 1 arguments, 1 results
3217 if(lua_pcall(L, 1, 1, 0))
3218 script_error(L, "error running function get_staticdata: %s\n",
3219 lua_tostring(L, -1));
3222 const char *s = lua_tolstring(L, -1, &len);
3223 return std::string(s, len);
3226 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
3227 LuaEntityProperties *prop)
3230 assert(lua_checkstack(L, 20));
3231 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
3232 StackUnroller stack_unroller(L);
3234 // Get minetest.luaentities[id]
3235 luaentity_get(L, id);
3236 //int object = lua_gettop(L);
3240 getboolfield(L, -1, "physical", prop->physical);
3242 getfloatfield(L, -1, "weight", prop->weight);
3244 lua_getfield(L, -1, "collisionbox");
3245 if(lua_istable(L, -1))
3246 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
3249 getstringfield(L, -1, "visual", prop->visual);
3251 lua_getfield(L, -1, "visual_size");
3252 if(lua_istable(L, -1))
3253 prop->visual_size = read_v2f(L, -1);
3256 lua_getfield(L, -1, "textures");
3257 if(lua_istable(L, -1)){
3258 prop->textures.clear();
3259 int table = lua_gettop(L);
3261 while(lua_next(L, table) != 0){
3262 // key at index -2 and value at index -1
3263 if(lua_isstring(L, -1))
3264 prop->textures.push_back(lua_tostring(L, -1));
3266 prop->textures.push_back("");
3267 // removes value, keeps key for next iteration
3273 lua_getfield(L, -1, "spritediv");
3274 if(lua_istable(L, -1))
3275 prop->spritediv = read_v2s16(L, -1);
3278 lua_getfield(L, -1, "initial_sprite_basepos");
3279 if(lua_istable(L, -1))
3280 prop->initial_sprite_basepos = read_v2s16(L, -1);
3284 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
3287 assert(lua_checkstack(L, 20));
3288 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3289 StackUnroller stack_unroller(L);
3291 // Get minetest.luaentities[id]
3292 luaentity_get(L, id);
3293 int object = lua_gettop(L);
3294 // State: object is at top of stack
3295 // Get step function
3296 lua_getfield(L, -1, "on_step");
3297 if(lua_isnil(L, -1))
3299 luaL_checktype(L, -1, LUA_TFUNCTION);
3300 lua_pushvalue(L, object); // self
3301 lua_pushnumber(L, dtime); // dtime
3302 // Call with 2 arguments, 0 results
3303 if(lua_pcall(L, 2, 0, 0))
3304 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
3307 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
3308 void scriptapi_luaentity_punch(lua_State *L, u16 id,
3309 ServerActiveObject *puncher, float time_from_last_punch)
3312 assert(lua_checkstack(L, 20));
3313 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3314 StackUnroller stack_unroller(L);
3316 // Get minetest.luaentities[id]
3317 luaentity_get(L, id);
3318 int object = lua_gettop(L);
3319 // State: object is at top of stack
3321 lua_getfield(L, -1, "on_punch");
3322 if(lua_isnil(L, -1))
3324 luaL_checktype(L, -1, LUA_TFUNCTION);
3325 lua_pushvalue(L, object); // self
3326 objectref_get_or_create(L, puncher); // Clicker reference
3327 lua_pushnumber(L, time_from_last_punch);
3328 // Call with 2 arguments, 0 results
3329 if(lua_pcall(L, 3, 0, 0))
3330 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
3333 // Calls entity:on_rightclick(ObjectRef clicker)
3334 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
3335 ServerActiveObject *clicker)
3338 assert(lua_checkstack(L, 20));
3339 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3340 StackUnroller stack_unroller(L);
3342 // Get minetest.luaentities[id]
3343 luaentity_get(L, id);
3344 int object = lua_gettop(L);
3345 // State: object is at top of stack
3347 lua_getfield(L, -1, "on_rightclick");
3348 if(lua_isnil(L, -1))
3350 luaL_checktype(L, -1, LUA_TFUNCTION);
3351 lua_pushvalue(L, object); // self
3352 objectref_get_or_create(L, clicker); // Clicker reference
3353 // Call with 2 arguments, 0 results
3354 if(lua_pcall(L, 2, 0, 0))
3355 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));